Using the GPIO driver from User Space

Linux Drivers

Release Date
2023-07-22

Figuring out the exact GPIO was not totally obvious when there were multiple GPIOs in the system. One way to do is to go into the gpiochips in /sys/class/gpio and view the label as it should reflect the address of the GPIO in the system. The name of the chip appears to be the 1st GPIO of the controller.

> root@xilinx-zcu102-2017_2:~# cd /sys/class/gpio/
  /* For ZynqMP */
> root@xilinx-zcu102-2017_2:/sys/class/gpio# ls
  export    gpiochip306    gpiochip322    gpiochip338    unexport
> root@xilinx-zcu102-2017_2:/sys/class/gpio# cat gpiochip338/label
  zynqmp_gpio
  The above line indicates that gpio 0th pin starts from 338 and ends at 511 (GPIO has total 174 pins for ZynqMP)
  /* For Zynq */
> root@xilinx-zc702-2017_2:~# cd /sys/class/gpio/
> root@xilinx-zc702-2017_2:~# ls
  export    gpiochip906    unexport
> root@xilinx-zc702-2017_2:/sys/class/gpio# cat gpiochip906/label
  zynq_gpio
  The above line indicates that gpio 0th pin starts from 906 and ends at 1023 (GPIO has total 118 pins for Zynq)

It may also be calculated ahead of time based on compile-time options for Linux. The basic formula (for Zynq) is base_gpio=ARCH_NR_GPIOS - ZYNQ_GPIO_NR_GPIOS. Then, allocated_gpios=ARCH_NR_GPIOS - base_gpio. Next, other_gpio=allocated_gpios - ZYNQ_GPIO_NR_GPIOS. Finally, gpio_offset=base_gpio + other_gpio. So, to calculate a specific GPIO number, it is base_gpio + other_gpios. This method may not be reliable permanently if ARCH_NR_GPIOS or ZYNQ_GPIO_NR_GPIOS changes without warning in the Linux kernel source code. See the Linux Kernel Mailing List for more details on the challenges with this method: https://lkml.org/lkml/2014/7/7/390 The following commands from the console setup:

  1. Export a GPIO pin
  2. Read the direction and value from the GPIO pin.
  3. Set the direction to an output and write a value 1 to GPIO pin

/* Export a GPIO pin */
> root@xilinx-zcu102-2017_3:~# echo 338 > /sys/class/gpio/export
 
/* Read the direction and value from the GPIO pin */
> root@xilinx-zcu102-2017_3:~# ls /sys/class/gpio/gpio338/
  Output:
  active_low  direction  power  uevent  device  edge  subsystem  value
> root@xilinx-zcu102-2017_3:~# cat /sys/class/gpio/gpio338/direction
  Output:
  in
> root@xilinx-zcu102-2017_3:~# cat /sys/class/gpio/gpio338/value
  Output:
  0
 
/* Set the direction to an output and write a value 1 to GPIO pin */
> root@xilinx-zcu102-217_3:~# ls /sys/class/gpio/gpio338
  Output:
  active_low  direction  power  uevent  device  edge  subsystem  value
> root@xilinx-zcu102-2017_3:~# echo out > /sys/class/gpio/gpio338/direction
> root@xilinx-zcu102-2017_3:~# echo 1 > /sys/class/gpio/gpio338/value