This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM625: Ensuring Consistent GPIO Numbering with Removable I2C Expansion Module

Part Number: AM625

Tool/software:

On our Customer board, there is an I2C expansion IO module. When this module is connected, the IO numbering is as follows, and five gpiochips are detected. Among them, gpiochip2 to gpiochip4 represent mcu_gpio0, main_gpio0, and main_gpio1, respectively.

When the I2C module is removed, only four gpiochips remain. In this case, gpiochip1 to gpiochip3 represent mcu_gpio0, main_gpio0, and main_gpio1.

It can be observed that the starting GPIO numbers of mcu_gpio0, main_gpio0, and main_gpio1 have changed, which directly impacts the usage of our application.

How can we configure the system to ensure that the starting GPIO numbers for mcu_gpio0, main_gpio0, and main_gpio1 remain unchanged when the I2C expansion module is removed?


When the module is connected:

root@User:~# cat /sys/kernel/debug/gpio
gpiochip4: GPIOs 334-385, parent: platform/601000.gpio, 601000.gpio:
gpiochip3: GPIOs 386-477, parent: platform/600000.gpio, 600000.gpio:
gpiochip2: GPIOs 478-501, parent: platform/4201000.gpio, 4201000.gpio:
gpiochip1: GPIOs 502-509, parent: i2c/0-0020, 0-0020, can sleep:
gpiochip0: GPIOs 510-511, parent: platform/3b000000.memory-controller, omap-gpmc:

When the module is removed:

root@User:~# cat /sys/kernel/debug/gpio
gpiochip3: GPIOs 342-393, parent: platform/601000.gpio, 601000.gpio:
gpiochip2: GPIOs 394-485, parent: platform/600000.gpio, 600000.gpio:
gpiochip1: GPIOs 486-509, parent: platform/4201000.gpio, 4201000.gpio:
gpiochip0: GPIOs 510-511, parent: platform/3b000000.memory-controller, omap-gpmc:
  • Hi Stephen,

    You application should not rely on the gpiochip name. The properly implementation is to give unique names (in the devicetree) to the GPIO pins, then your application query the gpiochip name using the GPIO pin name as the parameter.

  • Hi Bin,

    I think you may not fully understand my question. In our APP, we do not rely on the gpiochip name but rather on their GPIO numbers.

    Here is a simple example of how we use it: we control an LED using main_gpio0_57.

    In this case, if the I2C expansion IO module is plugged in, MAIN_GPIO0_BASE needs to be defined as 386. However, if the module is removed, MAIN_GPIO0_BASE needs to be defined as 394 to control the same GPIO pin.

    #define MAIN_GPIO0_BASE 386
    #define GPIO_TO_PIN(base, gpio) ((base) + (gpio))
    #define GPIO_LED_ALARM	  GPIO_TO_PIN(MAIN_GPIO0_BASE, 57)
    ....
    
    
    if (temp > 0) {
    	gpio_direction_output(GPIO_LED_ALARM, ON);
    } else {
    	gpio_direction_output(GPIO_LED_ALARM, OFF);
    }

  • Hi Stephen,

    My point is that the user space applications should not rely on the gpiochip IDs or gpio pin numbers which vary from kernel to kernel or even platform to platform. To completely decouple the applications from kernel, gpio pin names should be used instead of gpiochip IDs and gpio pin numbers.

    Here is example on AM64x EVM (sorry to use AM64x an example, I just have the EVM running on my desk at the moment).

    In kernel device tree k3-am642-evm.dts, the I/O expander pin names are defined as:

      &main_i2c1 {                                                                                                                                                                                                                                                                                                                                                                                                                            
              status = "okay";                                                                                                                                                                                                                                                                                                                                                                                                                
              pinctrl-names = "default";                                                                                                                                                                                                                                                                                                                                                                                                      
              pinctrl-0 = <&main_i2c1_pins_default>;                                                                                                                                                                                                                                                                                                                                                                                          
              clock-frequency = <400000>;                                                                                                                                                                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                                                                                                                                                                                              
              exp1: gpio@22 {                                                                                                                                                                                                                                                                                                                                                                                                                 
                      compatible = "ti,tca6424";                                                                                                                                                                                                                                                                                                                                                                                              
                      reg = <0x22>;                                                                                                                                                                                                                                                                                                                                                                                                           
                      gpio-controller;                                                                                                                                                                                                                                                                                                                                                                                                        
                      #gpio-cells = <2>;                                                                                                                                                                                                                                                                                                                                                                                                      
                      gpio-line-names = "GPIO_eMMC_RSTn", "CAN_MUX_SEL",                                                                                                                                                                                                                                                                                                                                                                      
                                        "GPIO_CPSW1_RST", "GPIO_RGMII1_RST",                                                                                                                                                                                                                                                                                                                                                                  
                                        "GPIO_RGMII2_RST", "GPIO_PCIe_RST_OUT",                                                                                                                                                                                                                                                                                                                                                               
                                        "MMC1_SD_EN", "FSI_FET_SEL",
                    ...

    Using pin "GPIO_OLED_RESETn" as an example in Linux:

    root@am64xx-evm:~# gpiofind GPIO_OLED_RESETn
    gpiochip0 14
    root@am64xx-evm:~# gpioget 0 14
    0
    

  • Hi Bin,

    Thanks for providing the new method. I will test this approach for controlling the GPIO later.
    Additionally, if I want to continue using the previous method, is there a way to avoid the issues mentioned above?

  • Hi Stephen,

    Unfortunately I am not aware of any way to prevent kernel dynamically assigning the gpiochip IDs and pin numbers.

  • Hi Bin,

    If I want to call these unique names in a .c file, which header file needs to be included? Which function should be used to operate it? Are there examples of usage in user applications and kernel drivers? Thanks.

  • Hi Stephen,

    gpiofind command is part of the libgpiod package. Please check the libgpiod project source code for examples.