linux gpio driver can't export GPIO on mpc8308

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

linux gpio driver can't export GPIO on mpc8308

3,212 Views
alitahamia
Contributor I

I want to use linux GPIO driver to handle one of the GPIO pins of mpc8308 processor as output. so I enabled the GPIO driver and it's debugging in:

Device Drivers ---> GPIO Support ---> /sys/class/gpio/... (sysfs interface)

but when using `echo` command to export GPIO21, it gives Invalid argument errno:

gpio_request: gpio-21 (sysfs) status -22
export_store: status -22

I used `cat /sys/kernel/debug/gpio` to see which GPIO pins are reserved by other drivers, but it shows nothing. so this pin is free.

I hacked the kernel for the place of error and found that in beginning of `gpio_request` function in gpiolib.c it crashes at last line in bellow:

int gpio_request(unsigned gpio, const char *label)
{
struct gpio_desc *desc;
struct gpio_chip *chip;
int status = -EINVAL;
unsigned long flags;

spin_lock_irqsave(&gpio_lock, flags);

if (!gpio_is_valid(gpio))
goto done;
desc = &gpio_desc[gpio];
chip = desc->chip;
if (chip == NULL)
goto done

`gpio_desc[gpio]` is an entry of an array in driver (`static struct gpio_desc gpio_desc[ARCH_NR_GPIOS];`) that must be initialized by `gpiochip_add` function in driver. and this function must be called early as driver says:

/**
* gpiochip_add() - register a gpio_chip
* @chip: the chip to register, with chip->base initialized
* Context: potentially before irqs or kmalloc will work
*
* Returns a negative errno if the chip can't be registered, such as
* because the chip->base is invalid or already associated with a
* different chip. Otherwise it returns zero as a success code.
*
* When gpiochip_add() is called very early during boot, so that GPIOs
* can be freely used, the chip->dev device must be registered before
* the gpio framework's arch_initcall(). Otherwise sysfs initialization
* for GPIOs will fail rudely.
*
* If chip->base is negative, this requests dynamic assignment of
* a range of valid GPIOs.
*/

but `gpiochip_add` function never is called during boot.

Here is the .dts file:

gpio@c00 {

      device_type = "gpio";
      compatible = "fsl,mpc8315-gpio";
      reg = <0xc00 0x100>; //reg = <0xc00 0x18>;
      interrupt-parent = < &ipic >;
};

can you help me with this problem?

Edit:

I changed dts file to this:

gpio1: gpio-controller@c00 {
   #gpio-cells = <2>;
   compatible = "fsl,mpc8308-gpio", "fsl,mpc8349-gpio";
   reg = <0xc00 0x100>;
   interrupt-parent = <&ipic>;
   interrupts = <74 0x8>;
   gpio-controller;
   interrupt-controller;
   #interrupt-cells = <2>;
};


and now it shows `gpiochip224` in `/sys/class/gpio` and this gpiochip has 32 GPIOs. but I don't know what is the mapping between 21 and 224-255?
can anyone tell me what is the relation between PIN numbers in datasheet and GPIO numbers in kernel for MPC8308 PowerPC series processor? I try all numbers 224-255 and none of them works.

Tags (2)
2 Replies

1,843 Views
Pavel
NXP Employee
NXP Employee

The following setting is needed for sysfs GPIO using:

Check please that the following kernel configuration options are set. These options are necessary

for sysfs GPIO support:

CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB

CONFIG_MPC8XXX_GPIO (Platform Support / MPC8xxx GPIO support)

CONFIG_OF_GPIO

CONFIG_GPIOLIB (-*- GPIO Support  --->  )

CONFIG_GPIO_SYSFS (/sys/class/gpio/... (sysfs interface))

CONFIG_GENERIC_GPIO

 

This option can be checked using the .config file in the kernel source folder.

 

GPIO controllers should be declared in the Device Tree file.

More information on the device tree GPIO declaration can be found in the kernel source.

See please the following files:

/Documentation/powerpc/dts-bindings/gpio.txt and /Documentation/powerpc/dts-bindings/fsl/8xxx_gpio.txt

 

The MPC8308erd LTIB Linux BSP does not support all of these settings.

 

Use mmap possibility for gpio using on the MPC8308erdb board.


Have a great day,
Pavel Chubakov

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

1,843 Views
alitahamia
Contributor I

Thanks for your reply.

I have checked options you mentioned in kernel config file.

also I use the following dts file that is compatible with documentations in devicetree  bindings of ltib,

gpio1: gpio-controller@c00 {
#gpio-cells = <2>;
compatible = "fsl,mpc8308-gpio", "fsl,mpc8349-gpio";
reg = <0xc00 0x100>;
interrupts = <74 0x8>;
interrupt-parent = <&ipic>;
gpio-controller;
// interrupt-controller;
// #interrupt-cells = <2>;
};

but instead of using mmap I set GPIO and SICRH registers of mpc8308 and read them (for correct write) in kernel (I don't know that this should work):

void __iomem *immap;

unsigned long sicrh;

immap = ioremap(get_immrbase(), 0x1000);
if (immap) {
sicrh = in_be32(immap + MPC83XX_SICRH_OFFS);
printk(KERN_INFO " immap=0x%x SICRH=0x%x \n",immap,sicrh);
sicrh |= 0x0ff;
printk(KERN_INFO "SICRH=0x%x \n",sicrh);
out_be32(immap + MPC83XX_SICRH_OFFS, sicrh);
out_be32(immap + 0x0c00, 0x0ffff);//0x0c00 is offset of GPDIR register
out_be32(immap + 0x0c08, 0x0ffff);//0x0c08 is offset of GPDAT register
udelay(3000000);//after a delay set open drain register to 1 and try again
out_be32(immap + 0x0c04, 0x0ffff);//0x0c04 is offset of GPODR register
out_be32(immap + 0x0c08, 0x0ffff);
iounmap(immap);
}

however gpio pin still doesn't turn on!

0 Kudos
Reply