GPIO using kernel ioctrl interface

GlynJones
GlynJones New Member Posts: 3
edited May 2019 in UP Board Linux

My UP board has Ubilinux v 4 on it with some minor changes to udev that enables a group to access GPIO rather than just root.
I have some code to control GPIOs using the kernel interface (ioctl) that runs perfectly on a Raspberry Pi. It uses the BCM pin numbers to control outputs and respond to inputs. The hardware connected to the GPIOs are the LEDs and Buttons on a Pi Rainbow Hat.
The kernel sees this on the PI:

pi@raspberrypi:~ $ sudo cat /sys/kernel/debug/gpio
gpiochip0: GPIOs 0-53, parent: platform/3f200000.gpio, pinctrl-bcm2835:   
gpio-16  (                    |Button C            ) in  hi IRQ
gpio-19  (                    |digital_output      ) out lo    
gpio-20  (                    |Button B            ) in  hi IRQ
gpio-21  (                    |Button A            ) in  hi IRQ
gpio-26  (                    |digital_output      ) out lo    
gpio-29  (                    |led0                ) out lo    

gpiochip1: GPIOs 128-135, brcmexp-gpio, can sleep:
gpio-130 (                    |led1                ) out lo 

You can see the "digital_output" and "Button X" labels where my software has connected to the appropriate lines.

The same code on the UP board runs without error, but the pin outputs do not change, and touching the buttons causes no interrupt to my software.

The numbering of the gpio controlled by the gpiochip0 is very different on the UP board:
ubilinux@ubilinux4:~$ sudo cat /sys/kernel/debug/gpio
gpiochip4: GPIOs 0-27, parent: platform/up-pinctrl, up-pinctrl:

gpiochip3: GPIOs 318-372, parent: platform/INT33FF:03, INT33FF:03:

gpiochip2: GPIOs 373-396, parent: platform/INT33FF:02, INT33FF:02:
 gpio-386 (                    |up-pinctrl          ) out lo    
 gpio-388 (                    |up-pinctrl          ) out hi    
 gpio-396 (                    |up-pinctrl          ) in  lo    

gpiochip1: GPIOs 397-455, parent: platform/INT33FF:01, INT33FF:01:
 gpio-418 (                    |up-pinctrl          ) out hi    

gpiochip0: GPIOs 456-511, parent: platform/INT33FF:00, INT33FF:00:
 gpio-472 (                    |Button C            ) in  hi IRQ
 gpio-475 (                    |digital_output      ) out lo    
 gpio-476 (                    |Button B            ) in  hi IRQ
 gpio-477 (                    |Button A            ) in  hi IRQ
 gpio-482 (                    |digital_output      ) out lo    
 gpio-499 (                    |up-pinctrl          ) out hi 

Where are the numbers such as gpio-472 coming from? My code connects using BCM number 16 for Button C, and on the PI, this matches directly.
Do I need to use numbers other than the BCM values when using the ioctrl interface on the UP board? If so, where do I find the correct mapping?
Thanks in advance.

Tagged:

Comments

  • Dan O'Donovan
    Dan O'Donovan Administrator, Moderator, Emutex Posts: 241 admin

    Hi @GlynJones

    The underlying hardware implementation of the GPIO controller on UP is very different to the Raspberry Pi. On the UP board, the Intel Cherry Trail SoC has 4 GPIO controllers (with ACPI device IDs INT33FF:00-03 as seen above). 28 of those SoC GPIO signals are connected out to the 40-pin HAT connector on the UP board, via a CPLD device that performs voltage level shifting.

    We provide a driver (up-pinctrl above) which creates a "virtual" GPIO controller device to mimick the 28 RPi GPIO pins on the HAT connector. But that driver is actually doing 2 things under the hood:

    • It will reconfigure the CPLD device to tell it whether the selected GPIO pin is in input or output mode, for the purpose of voltage level shifting
    • It will redirect the GPIO operations (get, set) to the corresponding SoC GPIO that will actually control the signal on the header

    The effect of all of this is that if you use the GPIO numbers in the "Linux GPIO" column of this table (https://wiki.up-community.org/Pinout) you should be accessing the same pins on the HAT connector that you would when using the BCM GPIO numbers on RPi.

    I'm not sure why the ioctl operations aren't working for you with the gpios provided by the up-pinctrl driver. I haven't tried them myself, but am not aware of any reason why they wouldn't work. Which ioctl commands are you using?

    Best regards,
    -Dan

  • GlynJones
    GlynJones New Member Posts: 3

    Hi Dan, thanks for the quick response.
    I am using the numbers in the Linux GPIO columns as described in your post.

    I have attached a zip file of some test code that initially listens to some GPIO inputs connected to the buttons (16, 20 and 21), then attempts to flash the LEDs using GPIO outputs (6, 19 and 26). This contains the ioctl calls I use.

    The gpio config during the listen is:

    ubilinux@ubilinux4:~$ sudo cat /sys/kernel/debug/gpio
    gpiochip4: GPIOs 0-27, parent: platform/up-pinctrl, up-pinctrl:
     gpio-26  (                    |sysfs               ) out lo    
    
    gpiochip3: GPIOs 318-372, parent: platform/INT33FF:03, INT33FF:03:
     gpio-332 (                    |up-pinctrl          ) out lo    
    
    gpiochip2: GPIOs 373-396, parent: platform/INT33FF:02, INT33FF:02:
     gpio-386 (                    |up-pinctrl          ) out lo    
     gpio-388 (                    |up-pinctrl          ) out hi    
     gpio-396 (                    |up-pinctrl          ) in  lo    
    
    gpiochip1: GPIOs 397-455, parent: platform/INT33FF:01, INT33FF:01:
     gpio-418 (                    |up-pinctrl          ) out hi    
    
    gpiochip0: GPIOs 456-511, parent: platform/INT33FF:00, INT33FF:00:
     gpio-472 (                    |ButtonC             ) in  hi IRQ
     gpio-476 (                    |ButtonB             ) in  hi IRQ
     gpio-477 (                    |ButtonA             ) in  hi IRQ
     gpio-499 (                    |up-pinctrl          ) out hi    
    

    And the output during the attempted flashing is:

    ubilinux@ubilinux4:~$ sudo cat /sys/kernel/debug/gpio
    gpiochip4: GPIOs 0-27, parent: platform/up-pinctrl, up-pinctrl:
     gpio-26  (                    |sysfs               ) out lo    
    
    gpiochip3: GPIOs 318-372, parent: platform/INT33FF:03, INT33FF:03:
     gpio-332 (                    |up-pinctrl          ) out lo    
    
    gpiochip2: GPIOs 373-396, parent: platform/INT33FF:02, INT33FF:02:
     gpio-386 (                    |up-pinctrl          ) out lo    
     gpio-388 (                    |up-pinctrl          ) out hi    
     gpio-396 (                    |up-pinctrl          ) in  lo    
    
    gpiochip1: GPIOs 397-455, parent: platform/INT33FF:01, INT33FF:01:
     gpio-418 (                    |up-pinctrl          ) out hi    
    
    gpiochip0: GPIOs 456-511, parent: platform/INT33FF:00, INT33FF:00:
     gpio-472 (                    |ButtonC             ) in  hi IRQ
     gpio-475 (                    |blinkerB            ) out hi    
     gpio-476 (                    |ButtonB             ) in  hi IRQ
     gpio-477 (                    |ButtonA             ) in  hi IRQ
     gpio-482 (                    |blinkerC            ) out lo    
     gpio-499 (                    |up-pinctrl          ) out hi
    

    (Note that blinkerA is not in the list - this is Linux GPIO 6).

    The output from the attached code is:

    ubilinux@ubilinux4:~$ ./gpiotest 
    GPIO chip: gpiochip0, "INT33FF:00", 56 GPIO lines
    fd=3
    req1.fd = 4
    req2.fd = 5
    req3.fd = 6
    Select timeout 0
    Select timeout 1
    Select timeout 2
    Select timeout 3
    Select timeout 4
    Select timeout 5
    Select timeout 6
    Select timeout 7
    Select timeout 8
    Select timeout 9
    Select timeout 10
    Select timeout 11
    Select timeout 12
    Select timeout 13
    Select timeout 14
    Select timeout 15
    Select timeout 16
    Select timeout 17
    Select timeout 18
    Select timeout 19
    Start button flashing
    loop 0
    loop 1
    loop 2
    loop 3
    loop 4
    loop 5
    loop 6
    loop 7
    loop 8
    loop 9
    

    If I can provide any further debug, please let me know.

  • GlynJones
    GlynJones New Member Posts: 3

    We have found a partial resolution to this problem.

    My code has been opening /dev/gpiochip0.
    If I open /dev/gpiochip4 instead, then the GPIO outputs work as expected.
    One of the inputs (Button C, BCM number 16) works, but the other two don't - these are connected to BCMs 20 and 21.
    Are they on a different /dev/gpiochip?

  • GarfieldMonday
    GarfieldMonday New Member Posts: 1

    libgpiod has gpio tools that may help making a quick check if the setup is working correctly. For example, use "gpiomon gpiochip4 21" to monitor Rising Edge or Fall Edge on pin 40 on UP HAT.