How to programmatically use GPIO Expander driver in Linux?

5.3k views Asked by At

I am trying to configure my Yocto Linux distro to setup two on-board I2C GPIO Expanders and document how to access them programmatically (i.e. from a C user application). The GPIO Expanders are both NXP PCA9557, which is supported by the gpio-pca953x.c kernel driver.

I understand how to compile this driver into the kernel (using CONFIG_GPIO_PCA953X configuration option) and load it (using modprobe). I also understand I can instantiate these two I2C devices in the device tree (this is an embedded device, so the GPIO expanders are static and unchanging):

gpio@20 {
    compatible = "nxp,pca9557";
    reg = <0x1a>;
    gpio-controller;
    #gpio-cells = <2>;
};

The information I'm lacking is how to use the gpio-pca953x driver with these instantiated devices? Do I need to associate these devices with that particular driver? What APIs do I use to access them in a user application written in C? Do these just act like normal GPIOs once I've configured them correctly?

I'm more than happy to read through any relevant documentation, lengthy or otherwise, on how to do this. I'm just a beginner in Linux device drivers and have no idea where to go from here, despite a great deal of googling.

2

There are 2 answers

1
John b On

There are several way to control GPIO from user space, but What are you trying to control? Linux is able to use GPIO as LED, key, interrupt and more.

sysfs is the "old" way of controlling GPIOs. It works and it is still being maintained. Essentially you write nodes in the /sys directory. Writing files is straight forward process in C. You can test writing to file from in Shell first, if you want.

$ echo 7 > /sys/class/gpio/export 
$ echo "out" > /sys/class/gpio/gpio7/direction 
$ echo 1 > /sys/class/gpio/gpio7/value #turn on 
$ echo 0 > /sys/class/gpio/gpio7/value #turn off

There is a newer way to access the GPIO. You can open the /dev/chip and make some IOCTL calls. Include #include <linux/gpio.h> then

  • GPIO_GET_LINEHANDLE_IOCTL, to see current status
  • GPIOHANDLE_GET_LINE_VALUES_IOCTL then to read
  • GPIOHANDLE_SET_LINE_VALUES_IOCTL to write

You could test it by using a Shell program that uses this same interface.

$ gpiodetect
$ gpioinfo
$ gpioset

I have never done this, but here is an example tool that does this. Also on kernel newer then 5.9 you could used #include "gpio-utils.h".

0
Levente Révész On

When working correctly, the driver should provide a gpiochipX device in /dev. This can be used with ioctl calls.

The libgpiod library provides a friendly API for interacting with these devices.

Install the libgpiod package in Yocto. It comes with some handy command line tools for debugging.

  • gpiodetect - list all gpiochips present on the system, their names, labels and number of GPIO lines

  • gpioinfo - list all lines of specified gpiochips, their names, consumers, direction, active state and additional flags

  • gpioget - read values of specified GPIO lines

  • gpioset - set values of specified GPIO lines, potentially keep the lines exported and wait until timeout, user input or signal

  • gpiofind - find the gpiochip name and line offset given the line name

  • gpiomon - wait for events on GPIO lines, specify which events to watch, how many events to process before exiting or if the events should be reported to the console


If you don't have the file, then the driver did not start. Check dmesg for clues.

# dmesg | grep pca953x
[    0.208762] pca953x 1-0020: using AI

You can also check if the pca chip is accessible on i2c. List i2c buses and find out which one the pca9557 is on.

# i2cdetect -l
i2c-0   21a0000.i2c
i2c-1   21a4000.i2c
i2c-2   21a8000.i2c

Let's say the pca chip is on the i2c-1 bus. Detect devices on the bus.

# i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:       -- -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- UU -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --

The table should contain

  • UU at the 1a address if the pca953x driver is running,
  • 1a at the 1a address if the driver is not running, but the chip is functioning and can be controlled over i2c,
  • -- at the 1a address if the chip is off or its i2c address is not actually 1a.