GPIO using kernel ioctrl interface
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.
Comments
-
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 -
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.
-
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? -
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.