i have windriver ported linux with ls1020a chip. But in our side, it seemed that the gpio is not working.
After kernel boot, we can only see:
root@localhost:~# ls /sys/class/gpio/
export unexport
root@localhost:~#
And it seemed that there is no any gpio exported. What it should be?
And i am also not sure what kernel log should be when kernel enable gpio?
I need to use gpio2_14 to control external device but so far not able to export to user space and control with set/get value.
Please also help point to me what gpio source file i should look at in linux kernel. If you can, please let me know the working kernel source code and device tree then i can compare with the kernel & device tree i had in my side.
thanks a lot and it really affects our project seriously.
And this is the io map from gpio address, please help confirm whether this iomap is correct or not:
mpc8xxx_probe np->full_name /soc/gpio@2300000 mm_gc->regs 0xc08c0000
mpc8xxx_probe np->full_name /soc/gpio@2310000 mm_gc->regs 0xc08e0000
mpc8xxx_probe np->full_name /soc/gpio@2320000 mm_gc->regs 0xc0900000
mpc8xxx_probe np->full_name /soc/gpio@2330000 mm_gc->regs 0xc0920000
Please confirm whether this iomap address is correct or not.
I'm sorry, we do not support Windriver Linux and customization of kernel drivers for this Linux.
I suggest contacting Windriver support for Windriver Linux -specific questions.
ok, i have found the solution after i browse the gpio question here in this community. It really help.
Hi NXP support team,
i am able to setup direction output correctly but if i change the value in data register, it seemed that it not take effect. I am not sure why and stuck now at the last step.
root@localhost:~# ls /sys/class/gpio/
export gpiochip384/ gpiochip416/ gpiochip448/ gpiochip480/ unexport
root@localhost:~# cat /sys/class/gpio/gpiochip448/label
/soc/gpio@2310000
root@localhost:~# echo 462 > /sys/class/gpio/export (gpio2_14, 448 + 14 = 462)
root@localhost:~# ls /sys/class/gpio/
export gpio462 gpiochip384 gpiochip416 gpiochip448 gpiochip480 unexport
root@localhost:~# echo out > /sys/class/gpio/gpio462/direction
root@localhost:~# cat /sys/class/gpio/gpio462/direction
out
root@localhost:~# echo in > /sys/class/gpio/gpio462/direction
root@localhost:~# cat /sys/class/gpio/gpio462/direction
in
root@localhost:~# echo out > /sys/class/gpio/gpio462/direction
root@localhost:~# cat /sys/class/gpio/gpio462/direction
out
root@localhost:~#
But now the problem is that i am not able to change value. Also the output level is not changed as well.
root@localhost:~# echo 1 > /sys/class/gpio/gpio462/value
root@localhost:~# cat /sys/class/gpio/gpio462/value
0 <- suppose to see '1' here
Please help if you can, thanks very much.
And this is my gpio-mpc8xxx.c:
/*
* GPIOs on MPC512x/8349/8572/8610 and compatible
*
* Copyright (C) 2008 Peter Korsgaard <jacmet@sunsite.dk>
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/irq.h>
#define NGG_77_WA 1
#define NGG_77_DEBUG 1
#define MPC8XXX_GPIO_PINS 32
#define GPIO_DIR 0x00
#define GPIO_ODR 0x04
#define GPIO_DAT 0x08
#define GPIO_IER 0x0c
#define GPIO_IMR 0x10
#define GPIO_ICR 0x14
#define GPIO_ICR2 0x18
struct mpc8xxx_gpio_chip {
struct of_mm_gpio_chip mm_gc;
spinlock_t lock;
/*
* shadowed data register to be able to clear/set output pins in
* open drain mode safely
*/
u32 data;
struct irq_domain *irq;
unsigned int irqn;
const void *of_dev_id_data;
};
static inline u32 mpc8xxx_gpio2mask(unsigned int gpio)
{
return 1u << (MPC8XXX_GPIO_PINS - 1 - gpio);
}
static inline struct mpc8xxx_gpio_chip *
to_mpc8xxx_gpio_chip(struct of_mm_gpio_chip *mm)
{
return container_of(mm, struct mpc8xxx_gpio_chip, mm_gc);
}
static void mpc8xxx_gpio_save_regs(struct of_mm_gpio_chip *mm)
{
struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
mpc8xxx_gc->data = ioread32be(mm->regs + GPIO_DAT);
}
/* Workaround GPIO 1 errata on MPC8572/MPC8536. The status of GPIOs
* defined as output cannot be determined by reading GPDAT register,
* so we use shadow data register instead. The status of input pins
* is determined by reading GPDAT register.
*/
static int mpc8572_gpio_get(struct gpio_chip *gc, unsigned int gpio)
{
u32 val;
struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
u32 out_mask, out_shadow;
out_mask = ioread32be(mm->regs + GPIO_DIR);
val = ioread32be(mm->regs + GPIO_DAT) & ~out_mask;
out_shadow = mpc8xxx_gc->data & out_mask;
return (val | out_shadow) & mpc8xxx_gpio2mask(gpio);
}
static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio)
{
struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
return ioread32be(mm->regs + GPIO_DAT) & mpc8xxx_gpio2mask(gpio);
}
static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
{
struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
unsigned long flags;
#ifdef NGG_77_DEBUG
pr_err("NGG_77_DEBUG mpc8xxx_gpio_set 0x%x called\n", gc);
if (gc->label != NULL) {
pr_err("NGG_77_DEBUG gc->label %s\n", gc->label);
}
pr_err("NGG_77_DEBUG gc->base %d\n", gc->base);
pr_err("NGG_77_DEBUG gc->exported %s\n", ((gc->exported) ? "true" : "false"));
pr_err("NGG_77_DEBUG gpio %d val %d\n", gpio, val);
if (mm == NULL) {
pr_err("NGG_77_DEBUG NULL mm!!!\n");
return 0;
} else {
pr_err("NGG_77_DEBUG mm 0x%x\n", mm);
}
if (mpc8xxx_gc == NULL) {
pr_err("NGG_77_DEBUG NULL mpc8xxx_gc!!!\n");
return 0;
} else {
pr_err("NGG_77_DEBUG mpc8xxx_gc 0x%x\n", mpc8xxx_gc);
}
#endif
spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
#ifdef NGG_77_DEBUG
pr_err("mpc8xxx_gpio_set val before 0x%x\n", mpc8xxx_gc->data);
#endif
if (val)
mpc8xxx_gc->data |= mpc8xxx_gpio2mask(gpio);
else
mpc8xxx_gc->data &= ~mpc8xxx_gpio2mask(gpio);
#ifdef NGG_77_DEBUG
pr_err("mpc8xxx_gpio_set val after 0x%x\n", mpc8xxx_gc->data);
pr_err("mm->regs 0x%x\n", (u32)(mm->regs));
#endif
iowrite32be(mm->regs + GPIO_DAT, mpc8xxx_gc->data);
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
}
static void mpc8xxx_gpio_set_multiple(struct gpio_chip *gc,
unsigned long *mask, unsigned long *bits)
{
struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
unsigned long flags;
int i;
spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
for (i = 0; i < gc->ngpio; i++) {
if (*mask == 0)
break;
if (__test_and_clear_bit(i, mask)) {
if (test_bit(i, bits))
mpc8xxx_gc->data |= mpc8xxx_gpio2mask(i);
else
mpc8xxx_gc->data &= ~mpc8xxx_gpio2mask(i);
}
}
iowrite32be(mm->regs + GPIO_DAT, mpc8xxx_gc->data);
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
}
static int mpc8xxx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
{
struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
unsigned long flags;
spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
clrbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio));
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
return 0;
}
static int mpc8xxx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
{
struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
unsigned long flags;
#ifdef NGG_77_DEBUG
pr_err("NGG_77_DEBUG mpc8xxx_gpio_dir_out 0x%x called\n", gc);
if (gc->label != NULL) {
pr_err("NGG_77_DEBUG gc->label %s\n", gc->label);
}
pr_err("NGG_77_DEBUG gc->base %d\n", gc->base);
pr_err("NGG_77_DEBUG gc->exported %s\n", ((gc->exported) ? "true" : "false"));
pr_err("NGG_77_DEBUG gpio %d val %d\n", gpio, val);
if (mm == NULL) {
pr_err("NGG_77_DEBUG NULL mm!!!\n");
return 0;
} else {
pr_err("NGG_77_DEBUG mm 0x%x\n", mm);
}
if (mpc8xxx_gc == NULL) {
pr_err("NGG_77_DEBUG NULL mpc8xxx_gc!!!\n");
return 0;
} else {
pr_err("NGG_77_DEBUG mpc8xxx_gc 0x%x\n", mpc8xxx_gc);
}
#endif
mpc8xxx_gpio_set(gc, gpio, val);
spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
setbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio));
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
return 0;
}
static int mpc5121_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
{
/* GPIO 28..31 are input only on MPC5121 */
if (gpio >= 28)
return -EINVAL;
return mpc8xxx_gpio_dir_out(gc, gpio, val);
}
static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
{
struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
if (mpc8xxx_gc->irq && offset < MPC8XXX_GPIO_PINS)
return irq_create_mapping(mpc8xxx_gc->irq, offset);
else
return -ENXIO;
}
static void mpc8xxx_gpio_irq_cascade(unsigned int irq, struct irq_desc *desc)
{
struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_desc_get_handler_data(desc);
struct irq_chip *chip = irq_desc_get_chip(desc);
struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
unsigned int mask;
mask = ioread32be(mm->regs + GPIO_IER) & ioread32be(mm->regs + GPIO_IMR);
if (mask)
generic_handle_irq(irq_linear_revmap(mpc8xxx_gc->irq,
32 - ffs(mask)));
if (chip->irq_eoi)
chip->irq_eoi(&desc->irq_data);
}
static void mpc8xxx_irq_unmask(struct irq_data *d)
{
struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
unsigned long flags;
spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
setbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
}
static void mpc8xxx_irq_mask(struct irq_data *d)
{
struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
unsigned long flags;
spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
clrbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
}
static void mpc8xxx_irq_ack(struct irq_data *d)
{
struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
iowrite32be(mm->regs + GPIO_IER, mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
}
static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
{
struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
unsigned long flags;
switch (flow_type) {
case IRQ_TYPE_EDGE_FALLING:
spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
setbits32(mm->regs + GPIO_ICR,
mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
break;
case IRQ_TYPE_EDGE_BOTH:
spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
clrbits32(mm->regs + GPIO_ICR,
mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
break;
default:
return -EINVAL;
}
return 0;
}
static int mpc512x_irq_set_type(struct irq_data *d, unsigned int flow_type)
{
struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
unsigned long gpio = irqd_to_hwirq(d);
void __iomem *reg;
unsigned int shift;
unsigned long flags;
if (gpio < 16) {
reg = mm->regs + GPIO_ICR;
shift = (15 - gpio) * 2;
} else {
reg = mm->regs + GPIO_ICR2;
shift = (15 - (gpio % 16)) * 2;
}
switch (flow_type) {
case IRQ_TYPE_EDGE_FALLING:
case IRQ_TYPE_LEVEL_LOW:
spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
clrsetbits_be32(reg, 3 << shift, 2 << shift);
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
break;
case IRQ_TYPE_EDGE_RISING:
case IRQ_TYPE_LEVEL_HIGH:
spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
clrsetbits_be32(reg, 3 << shift, 1 << shift);
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
break;
case IRQ_TYPE_EDGE_BOTH:
spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
clrbits32(reg, 3 << shift);
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
break;
default:
return -EINVAL;
}
return 0;
}
static struct irq_chip mpc8xxx_irq_chip = {
.name = "mpc8xxx-gpio",
.irq_unmask = mpc8xxx_irq_unmask,
.irq_mask = mpc8xxx_irq_mask,
.irq_ack = mpc8xxx_irq_ack,
.irq_set_type = mpc8xxx_irq_set_type,
};
static int mpc8xxx_gpio_irq_map(struct irq_domain *h, unsigned int irq,
irq_hw_number_t hwirq)
{
struct mpc8xxx_gpio_chip *mpc8xxx_gc = h->host_data;
if (mpc8xxx_gc->of_dev_id_data)
mpc8xxx_irq_chip.irq_set_type = mpc8xxx_gc->of_dev_id_data;
irq_set_chip_data(irq, h->host_data);
irq_set_chip_and_handler(irq, &mpc8xxx_irq_chip, handle_level_irq);
return 0;
}
static struct irq_domain_ops mpc8xxx_gpio_irq_ops = {
.map = mpc8xxx_gpio_irq_map,
.xlate = irq_domain_xlate_twocell,
};
static struct of_device_id mpc8xxx_gpio_ids[] = {
{ .compatible = "fsl,mpc8349-gpio", },
{ .compatible = "fsl,mpc8572-gpio", },
{ .compatible = "fsl,mpc8610-gpio", },
{ .compatible = "fsl,mpc5121-gpio", .data = mpc512x_irq_set_type, },
{ .compatible = "fsl,pq3-gpio", },
{ .compatible = "fsl,qoriq-gpio", },
{ .compatible = "fsl,ls1021a-gpio", },
{}
};
static int mpc8xxx_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct mpc8xxx_gpio_chip *mpc8xxx_gc;
struct of_mm_gpio_chip *mm_gc;
struct gpio_chip *gc;
const struct of_device_id *id;
int ret;
mpc8xxx_gc = devm_kzalloc(&pdev->dev, sizeof(*mpc8xxx_gc), GFP_KERNEL);
if (!mpc8xxx_gc)
return -ENOMEM;
platform_set_drvdata(pdev, mpc8xxx_gc);
spin_lock_init(&mpc8xxx_gc->lock);
mm_gc = &mpc8xxx_gc->mm_gc;
gc = &mm_gc->gc;
#ifdef NGG_77_DEBUG
pr_err("NGG_77_DEBUG mpc8xxx_probe %s\n", np->full_name);
pr_err("NGG_77_DEBUG mpc8xxx_gc 0x%x\n", mpc8xxx_gc);
pr_err("NGG_77_DEBUG mm_gc 0x%x\n", mm_gc);
pr_err("NGG_77_DEBUG gc 0x%x\n", gc);
#endif
mm_gc->save_regs = mpc8xxx_gpio_save_regs;
gc->ngpio = MPC8XXX_GPIO_PINS;
gc->direction_input = mpc8xxx_gpio_dir_in;
gc->direction_output = of_device_is_compatible(np, "fsl,mpc5121-gpio") ?
mpc5121_gpio_dir_out : mpc8xxx_gpio_dir_out;
gc->get = of_device_is_compatible(np, "fsl,mpc8572-gpio") ?
mpc8572_gpio_get : mpc8xxx_gpio_get;
gc->set = mpc8xxx_gpio_set;
gc->set_multiple = mpc8xxx_gpio_set_multiple;
gc->to_irq = mpc8xxx_gpio_to_irq;
ret = of_mm_gpiochip_add(np, mm_gc);
if (ret)
return ret;
#ifdef NGG_77_WA
#else
mpc8xxx_gc->irqn = irq_of_parse_and_map(np, 0);
if (mpc8xxx_gc->irqn == NO_IRQ)
return 0;
mpc8xxx_gc->irq = irq_domain_add_linear(np, MPC8XXX_GPIO_PINS,
&mpc8xxx_gpio_irq_ops, mpc8xxx_gc);
if (!mpc8xxx_gc->irq)
return 0;
#endif
id = of_match_node(mpc8xxx_gpio_ids, np);
if (id)
mpc8xxx_gc->of_dev_id_data = id->data;
#ifdef NGG_77_WA
#else
/* ack and mask all irqs */
iowrite32be(mm_gc->regs + GPIO_IER, 0xffffffff);
iowrite32be(mm_gc->regs + GPIO_IMR, 0);
irq_set_handler_data(mpc8xxx_gc->irqn, mpc8xxx_gc);
irq_set_chained_handler(mpc8xxx_gc->irqn, mpc8xxx_gpio_irq_cascade);
#endif
return 0;
}
static int mpc8xxx_remove(struct platform_device *pdev)
{
struct mpc8xxx_gpio_chip *mpc8xxx_gc = platform_get_drvdata(pdev);
#ifdef NGG_77_DEBUG
struct device_node *np = pdev->dev.of_node;
pr_err("NGG_77_DEBUG mpc8xxx_remove %s called\n", np->full_name);
#endif
if (mpc8xxx_gc->irq) {
irq_set_handler_data(mpc8xxx_gc->irqn, NULL);
irq_set_chained_handler(mpc8xxx_gc->irqn, NULL);
irq_domain_remove(mpc8xxx_gc->irq);
}
of_mm_gpiochip_remove(&mpc8xxx_gc->mm_gc);
return 0;
}
static struct platform_driver mpc8xxx_plat_driver = {
.probe = mpc8xxx_probe,
.remove = mpc8xxx_remove,
.driver = {
.name = "gpio-mpc8xxx",
.of_match_table = mpc8xxx_gpio_ids,
},
};
static int __init mpc8xxx_init(void)
{
return platform_driver_register(&mpc8xxx_plat_driver);
}
arch_initcall(mpc8xxx_init);
I use below device tree file:
https://elixir.bootlin.com/linux/v4.1.21/source/arch/arm/boot/dts/ls1021a.dtsi
Add add gpio inside:
gpio1: gpio@2300000 {
compatible = "fsl,ls1021a-gpio";
reg = <0x0 0x2300000 0x0 0x10000>;
interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
sleep = <&rcpm 0x00000040 0x0>;
};
gpio2: gpio@2310000 {
compatible = "fsl,ls1021a-gpio";
reg = <0x0 0x2310000 0x0 0x10000>;
interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
gpio3: gpio@2320000 {
compatible = "fsl,ls1021a-gpio";
reg = <0x0 0x2320000 0x0 0x10000>;
interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
gpio4: gpio@2330000 {
compatible = "fsl,ls1021a-gpio";
reg = <0x0 0x2330000 0x0 0x10000>;
interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
kernel crash log:
root@localhost:~# echo out > /sys/class/gpio/gpio462/direction
NGG_77_DEBUG mpc8xxx_gpio_dir_out 0xbf1b49d0 called
NGG_77_DEBUG gc->label /soc/gpio@2310000
NGG_77_DEBUG gc->base 448
NGG_77_DEBUG gc->exported true
NGG_77_DEBUG gpio 14 val 0
NGG_77_DEBUG mm 0xbf1b49d0
NGG_77_DEBUG mpc8xxx_gc 0xbf1b49d0
NGG_77_DEBUG mpc8xxx_gpio_set 0xbf1b49d0 called
NGG_77_DEBUG gc->label /soc/gpio@2310000
NGG_77_DEBUG gc->base 448
NGG_77_DEBUG gc->exported true
NGG_77_DEBUG gpio 14 val 0
NGG_77_DEBUG mm 0xbf1b49d0
NGG_77_DEBUG mpc8xxx_gc 0xbf1b49d0
Unable to handle kernel NULL pointer dereference at virtual address 00000000
2019 Apr 9 15:33:55 localhost Unable to handle kernel NULL poipgd = b953ef00
nter dereference at virtual address 00000000
[00000000] *pgd=000000002019 Apr 9 15:33:55 localhost pgd = b953ef00
2019 Apr 9 15:33:55 localhost [00000000] *pgd=00000000Internal error: Oops: a05 [#1] PREEMPT SMP ARM
Modules linked in:
CPU: 0 PID: 393 Comm: sh Not tainted 4.1.21-WR8.0.0.24_standard #7
Hardware name: Freescale LS1021A
task: b8e339c0 ti: b9a64000 task.ti: b9a64000
PC is at mpc8xxx_gpio_set+0xec/0x120
LR is at vprintk_emit+0x440/0x4bc
pc : [<803d6528>] lr : [<8006ce98>] psr: 60070013
sp : b9a65e38 ip : b9a65d90 fp : b9a65e54
r10: 00000000 r9 : 76f58000 r8 : 00000000
r7 : b91d118c r6 : 00000000 r5 : 00000011 r4 : bf1b49d0
r3 : 08008ec0 r2 : 00000000 r1 : 00000007 r0 : 00000022
Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
Control: 30c5387d Table: b953ef00 DAC: fffffffd
Process sh (pid: 393, stack limit = 0xb9a64210)
Stack: (0xb9a65e38 to 0xb9a66000)
5e20: bf1b49d0 0000000e
5e40: 00000000 b91d118c b9a65e74 b9a65e58 803d6614 803d6448 bf1b49d0 bf1d6aa8
5e60: 803d655c b91d118c b9a65ea4 b9a65e78 803d2d2c 803d6568 bf1b49d0 bf1d6aa8
5e80: b91d1bc0 00000004 b91d118c b9a65f80 76f58000 00000000 b9a65eb4 b9a65ea8
5ea0: 803d3e14 803d2c64 b9a65ed4 b9a65eb8 803d551c 803d3de0 803d54ac b91d1bc0
5ec0: b91d1180 b91d118c b9a65eec b9a65ed8 80448700 803d54b8 804486d8 b91d1bc0
5ee0: b9a65f04 b9a65ef0 801aa604 804486e4 00000004 b91d1bc0 b9a65f34 b9a65f08
5f00: 801a9afc 801aa5c8 00000000 00000000 801a99d4 b91ee780 76f58000 b9a65f80
5f20: 8000f5e8 b9a64000 b9a65f4c b9a65f38 80148c78 801a99e0 00000004 b91ee780
5f40: b9a65f7c b9a65f50 8014937c 80148c5c 801636d8 80163644 b91ee780 b91ee780
5f60: 76f58000 00000004 8000f5e8 b9a64000 b9a65fa4 b9a65f80 80149ae0 801492cc
5f80: 00000000 00000000 00000004 76f58000 76ee5d60 00000004 00000000 b9a65fa8
5fa0: 8000f420 80149a94 00000004 76f58000 00000001 76f58000 00000004 00000000
5fc0: 00000004 76f58000 76ee5d60 00000004 00000004 00000000 54ca1d4c 54c85b24
5fe0: 00000000 7e926934 76e15684 76e6d7c0 60000010 00000001 00000000 00000000
[<803d6528>] (mpc8xxx_gpio_set) from [<803d6614>] (mpc8xxx_gpio_dir_out+0xb8/0x12c)
[<803d6614>] (mpc8xxx_gpio_dir_out) from [<803d2d2c>] (_gpiod_direction_output_raw+0xd4/0x2a8)
[<803d2d2c>] (_gpiod_direction_output_raw) from [<803d3e14>] (gpiod_direction_output_raw+0x40/0x4c)
[<803d3e14>] (gpiod_direction_output_raw) from [<803d551c>] (gpio_direction_store+0x70/0xd8)
[<803d551c>] (gpio_direction_store) from [<80448700>] (dev_attr_store+0x28/0x34)
[<80448700>] (dev_attr_store) from [<801aa604>] (sysfs_kf_write+0x48/0x54)
[<801aa604>] (sysfs_kf_write) from [<801a9afc>] (kernfs_fop_write+0x128/0x188)
[<801a9afc>] (kernfs_fop_write) from [<80148c78>] (__vfs_write+0x28/0x48)
[<80148c78>] (__vfs_write) from [<8014937c>] (vfs_write+0xbc/0x144)
[<8014937c>] (vfs_write) from [<80149ae0>] (SyS_write+0x58/0x98)
[<80149ae0>] (SyS_write) from [<8000f420>] (ret_fast_syscall+0x0/0x3c)
Code: e5943070 e5942078 e2833008 e6bf3f33 (e5823000)
2019 Apr 9 15:33:55 localhost Internal error: Oops: a05 [#1] P---[ end trace 3d3ab809ea928bd7 ]---
REEMPT SMP ARM
2019 Apr 9 15:33:55 localhost Process sh (pid:2019 Apr 9 15:33:55 localhost 5e80: b91d1bc0 00000004 b91d118c
Hi Alexander,
i have modified the attached gpio-mpc8xxx.c to support gpio in ls2010a on my board. And my linux version is 4.1.21.
I am able to export the pio now.
root@localhost:~# echo 462 > /sys/class/gpio/export (the gpio2_14)
root@localhost:~# ls /sys/class/gpio/
export gpio462 gpiochip384 gpiochip416 gpiochip448 gpiochip480 unexport
root@localhost:~# cat /sys/class/gpio/gpiochip448/label
/soc/gpio@2310000
root@localhost:~#
But i have problem when set direction to output and it crashed when try to set value 0 before set output direction.
It crash in my side.
I am not able to find place so i paste my crash log in next comment.
And if you know any kernel version which can support ls1020a gpio, i would like to compare. Thanks very much.
After boot the folder /sys/class/gpio/ contains only two files export and unexport, this is correct. This means all GPIO lines are managed by kernel. To control any GPIO line in your software, you have to export this line. To do that, you need to write GPIO number to export file, for example echo 8 > /sys/class/gpio/export ti indicate the kernel that you want to use this line. Note some GPIO lines may be multiplexed with other functions or used already. In case of success, you will see gpio8 folder in /sys/class/gpio/ and in this folder you will see several files - direction, value and etc. To set direction, you have echo "in" or "out". Writing "1" or "0" to value will set high or low, respectively.
Note we do not support Windriver Linux, so the answer is given "in general". For Windriver Linux -specific questions please contact Windriver support.
Have a great day,
Alexander,
TIC
-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!
- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------