Linux GPIO Driver

The purpose of this page is to introduce two methods for interacting with GPIO from user space on Zynq-7000 and Zynq Ultrascale+ MPSoC: the SysFs interface and the Linux kernel drivers (gpio-keys, leds-gpio).

The GPIO subsystem is documented in the kernel documentation in Documentation/gpio/.

Note: The SysFs driver has been tested and is working. It has been accepted into the mainline kernel and the old char mode GPIO driver that didn't work with arch/powerpc has been removed from the tree.


Table of Contents


HW IP Features

ZynqMP

  • 78 GPIO signals for device pins

    • Routed through the MIO multiplexer.

    • Outputs are 3-state capable.

  • 288 GPIO signals between the PS and PL through the EMIO interface

    • 96 inputs.

    • 192 outputs (96 true outputs and 96 output enables).

  • The function of each GPIO can be dynamically programmed on an individual or group basis.

  • Enable, bit or bank data write, output enable and direction controls.

  • Programmable interrupts on individual GPIO basis

    • Status read of raw and masked interrupt.

    • Selectable sensitivity: Level-sensitive (High or Low) or edge-sensitive (positive,negative, or both).

Zynq

  • 54 GPIO signals for device pins

    • Routed through the MIO multiplexer.

    • Outputs are 3-state capable.

  • 192 GPIO signals between the PS and PL via the EMIO interface

    • 64 Inputs

    • 128 Outputs(64 true outputs and 64 output enables).

  • The function of each GPIO can be dynamically programmed on an individual or group basis.

  • Enable, bit or bank data write, output enable and direction controls.

  • Programmable interrupts on individual GPIO basis

    • Status read of raw and masked interrupt.

    • Selectable sensitivity: Level-sensitive (High or Low) or edge-sensitive (positive,negative, or both).


Features supported in driver

ZynqMP

  • 78 GPIO signals for device pins
    • Routed through the MIO multiplexer.
    • Outputs are 3-state capable.
  • 288 GPIO signals between the PS and PL through the EMIO interface
    • 96 inputs.
    • 192 outputs (96 true outputs and 96 output enables).
  • The function of each GPIO can be dynamically programmed on an individual or group basis.
  • Enable, bit or bank data write, output enable and direction controls.
  • Programmable interrupts on individual GPIO basis
    • Status read of raw and masked interrupt.
    • Selectable sensitivity: Level-sensitive (High or Low) or edge-sensitive (positive,negative, or both).

Zynq

  • 54 GPIO signals for device pins
    • Routed through the MIO multiplexer.
    • Outputs are 3-state capable.
  • 192 GPIO signals between the PS and PL via the EMIO interface
    • 64 Inputs
    • 128 Outputs(64 true outputs and 64 output enables).
  • The function of each GPIO can be dynamically programmed on an individual or group basis.
  • Enable, bit or bank data write, output enable and direction controls.
  • Programmable interrupts on individual GPIO basis
    • Status read of raw and masked interrupt.
    • Selectable sensitivity: Level-sensitive (High or Low) or edge-sensitive (positive,negative, or both).


Missing Features, Known Issues and Limitations

Gpio driver have a dependency on pin-controller driver. Because of this dependency the GPIO driver probe was deferred from the 2017.1 release.
If any drivers have a dependency on GPIO driver that driver should have defer the probe.

Kernel Configuration

To enable GPIO in the kernel, the following configuration options need to be enabled:


Devicetree



Test procedure


SysFs Interface

The SysFs interface is a very simple way to access the GPIO from user space and has the advantage of requiring very little setup. This option is a good choice for manually checking the status of an input or writing values to outputs; this method should not be used where interrupts are required.
The SysFs interface is documented in the kernel documentation in Documentation/gpio/sysfs.txt

Using GPIO with SysFs

The GPIO driver fits in the Linux GPIO framework. It does provide access to the GPIO by user space through the sysfs filesystem. For details please refer to - the above-mentioned - documentation. The following text is aimed to augment, not replace the existing documentation.

For the examples below, there are some important points with sysfs.

  1. The GPIO controllers are visible in /sys/class/gpio. Each controller controls a number of GPIO signals.
  2. The GPIO signals must be exported into the sysfs before they can be manipulated. The number of the GPIO signal must be written to the GPIO export file to cause this to happen.
  3. After exporting the GPIO signal a new directory based on the GPIO signal number will appear in /sys/class/gpio. Under that directory are direction and value files that can be read and written.

Mounting Sysfs

The root file system being used may not have sysfs mounted and it cannot be used if it's not mounted. The directory /sys is also needed to mount the sysfs on. The root file system must be writable to do the following steps.


Using the GPIO driver from User Space

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.


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



Using the GPIO Driver from a User Space Application

The performance of this is pretty good. Using nfs root, running open source linux on the ML507 reference system, the GPIO can be toggled about every 4 usec.
This page, GPIO User Space Application, shows the application and provides it for download.


Linux Kernel Drivers

The gpio-keys, gpio-keys-polled and leds-gpio drivers are a powerful alternative to the SysFs interface for accessing GPIO from user space.

  • gpio-keys is used when GPIO line can generate interrupts in response to a key press.
  • gpio-keys-polled is used when GPIO line cannot generate interrupts, so it needs to be periodically polled by a timer.
  • leds-gpio will handle LEDs connected to GPIO lines, giving the LED sysfs interface.

This section covers process of modifying the device tree (DTS) and kernel configuration and includes an example application to demonstrate the function of these drivers.
These drivers are suitable for more complex applications involving generating patterns or handling interrupts.

Additional Setup Required

Required Information from the Device Tree

Use your preferred editor to open the device tree DTS file and locate the GPIO controller under the AXI interconnect; it should look something like this:

Note the name of your GPIO controller, since you will need it to create the new nodes; in this example it is ps7_gpio_0.

LEDS-GPIO Driver

Add LEDs to the Device Tree

The leds-gpio driver enables many LED control schemes (via the "default-trigger" option) and allows them to be modified from user space; these drivers are suitable for any output-only GPIO application.
Under the AXI interconnect, create a node named “leds-gpio”, like in the example below:

Multiple LEDs can be nested at the same level as led-ds23 within gpio-leds. In this example, the LED is named led-ds23 to match the label ("DS23") on the ZC702 board, but this does not have any technical impact.
The string <&ps7_gpio_0 10 0> references the GPIO controller and states that this device is on the GPIO pin/bit of 10; the 0 states that the device is active high.
The default-trigger property dictates that the control scheme for the LED is “heartbeat” mode; in this mode the LED will double-pulse with a frequency relative to the CPU load.

Kernel Configuration

In order to use these drivers the kernel must be configured correctly. Configure the kernel as described in Build Kernel, and then make sure the following options are enabled in menuconfig:

  • Device Drivers
    • GPIO Support
      • Xilinx GPIO support
      • Xilinx Zynq GPIO support
    • LED Support
      • LED Class Support
      • LED Support for GPIO connected LEDs
      • LED Trigger support
        • all desired triggers

The following configs should be present in .config afterwards:

  • CONFIG_NEW_LEDS
  • CONFIG_LEDS_CLASS
  • CONFIG_LEDS_TRIGGERS (all)
  • CONFIG_LEDS_GPIO

Using the LEDs

The LED can then be accessed from /sys/class/leds/led-ds23. Depending on the trigger type selected, different files will be visible; the trigger type can be changed by writing to /sys/class/leds/led-ds23/trigger.
A full list of triggers can be found at Documentation/devicetree/bindings/leds/common.txt.

GPIO-Keys Driver

GPIO Keys are more complex than LEDs. These drivers offer proper interrupt handling and work well with multi-key setups by mapping each key to a linux code; the entire gpio-keys node will be read as a single device with multiple key codes (like a keyboard).

Add GPIO-Keys to the Device Tree

Under the AXI interconnect, create a node named “gpio-keys”, like in the example below:


  • The string <&ps7_gpio_0 12 0> references the GPIO controller and states that sw14 device is on pin 12, while sw13 is on pin 14; the 0 states that the device is active high.
  • The linux,code property determines which key will show up in the event.
  • The autorepeat property allows holding the key to continuously generate events.
  • Using gpio-key,wakeup will enable the GPIO to wake the system from suspend.

Full documentation can be found here Documentation/devicetree/bindings/input/gpio-keys.txt.

Kernel Configuration

In order to use these drivers the kernel must be configured correctly. Configure the kernel as described in Build Kernel, and then make sure the following options are enabled in menuconfig:

  • Device Drivers
    • GPIO Support
      • Xilinx GPIO support
      • Xilinx Zynq GPIO support
    • Input device support
      • Keyboards
        • GPIO Buttons
        • Polled GPIO buttons


The following configs should be present in .config afterwards:

  • CONFIG_KEYBOARD_GPIO and CONFIG_KEYBOARD_GPIO_POLLED respectively


At this point, the Linux kernel is ready to be rebuilt.

Using the GPIO-Keys

The key events generated by the GPIO-keys can be read by opening the file /dev/input/event0. For a quick test, use cat /dev/input/event0 | hexdump and then press a key and the input event will print to the console; this data is of the input_event structure and is documented here Documentation/input/input.txt.

GPIO-Keys-Polled

For GPIO that do not use interrupts, the gpio-keys-polled drivers can be used and will still benefit from having linux key codes associated with them. Like in the previous example, create a new node under the AXI interconnect, but this time name it “gpio-keys-polled”. The structure for gpio-keys-polled is almost identical to that of gpio-keys – the polled keys do not have any interrupt capabilities, so gpio-key,wakeup is not relevant; the gpio-keys-polled driver also includes a poll-interval property, in milli-seconds.
Full documentation of this driver can be found here Documentation/devicetree/bindings/input/gpio-keys-polled.txt.

Demo Application

This application showcases the use of the gpio-keys and leds-gpio drivers by passing events into user space and then modifying the LEDs from there:

Run this application with leds-gpio and either gpio-keys or gpio-keys-polled. The demo will allow you to use push buttons to dictate the frequency of LED blinking using the kernel drivers.

Expected Output



Mainline Status

This driver is currently in sync with mainline kernel.

Recently sent few patches, Those are applied on mainline, Xilinx 5.10 repo contains those changes.



Change Log

2016.3
Summary:

  • gpio:Added zynq specific check for special pins on bank zero.

Commits:

  • e3296f1 gpio:Added zynq specific check for special pins on bank zero.


2016.4

  • None


2017.1
Summary:

  • gpio: zynq: Add support for suspend resume
  • gpio: zynq: Wakeup gpio controller when it is used as IRQ controller

Commits:

  • 764c694 gpio: zynq: Add support for suspend resume
  • 6a8c796 gpio: zynq: Wakeup gpio controller when it is used as IRQ controller


2017.2

  • None


2017.3
Summary:

  • gpio: gpio-zynq.c: Fix kernel doc warnings
  • gpio: gpio-zynq: Fix warnings in the driver
  • gpio: gpio-zynq: shift zynq_gpio_init() to subsys_initcall level
  • gpio: zynq: Clarify quirk and provide helper function
  • gpio: zynq: Provided workaround for GPIO

Commits:

  • 9572161 gpio: gpio-zynq.c: Fix kernel doc warnings
  • a9e595b gpio: gpio-zynq: Fix warnings in the driver
  • 554ae6b gpio: gpio-zynq: shift zynq_gpio_init() to subsys_initcall level
  • 913cf8b gpio: zynq: Clarify quirk and provide helper function
  • 8bc5037 gpio: zynq: Provided workaround for GPIO


2017.4

  • None


2018.1
Summary:

  • gpio: zynq: Add support for suspend resume


Commits:

  • e11de4d gpio: zynq: Add support for suspend resume

2018.2
Summary:

  • gpio: zynq: protect direction in/out with a spinlock


Commits:

  • 355168 gpio: zynq: protect direction in/out with a spinlock
2018.3
Summary:
  • gpio: zynq: Remove call to platform_get_irq
  • gpio: zynq: simplifly getting drvdata
  • gpio: zynq: Setup chip->base based on alias ID
Commits:
  • 52b64a2 gpio: zynq: Remove call to platform_get_irq 
  • eb816d4 gpio: zynq: simplifly getting drvdata
  • 5dd4162 gpio: zynq: Setup chip->base based on alias ID

2019.1

  • summary:
    • gpio: zynq: Configured zynq gpio's in boot loader stage.
    • gpio: zynq: Added support runtime PM for GPIO
    • gpio: zynq: Disable the irq if it is not a wakeup source
  • commits:
    • 81e13dbReport gpio direction at boot
    • d2fe433:  properly support runtime PM for GPIO used as interrupts
    • 65b9290Disable the irq if it is not a wakeup source

2019.2

    • summary
      • gpio: zynq: Add pmc gpio support
    • commits

2020.1

  • Summary
    • gpio:zynq: Remove error prints in EPROBE_DEFER
    • gpio:zynq:use module_platform_driver to simplify the code
  • commits
    • 9b515a08 :Remove error prints in EPROBE_DEFER
    • 5230a062 :use module_platform_driver to simplify the code

2020.2

  • Summary
    • None

Related Links