NXP i.MXRT10XX: Controlling GPIO from Linux User Space

This application note shows how to control the i.MX RT1050/RT1060 GPIOs from the user level using the standard Linux GPIOLIB interface.

1. Changes to the Kernel Configuration

The generic GPIO interface is controlled by the CONFIG_GPIOLIB kernel option enabled by default in the rootfs project. Most of the i.MX RT1050/RT1060 GPIO pins can be used in different multiplexed I/O roles (for instance, some GPIO pins can be also configured as an SPI interface, etc.) Depending on the requirements of your application, you need to configure the pins that you want to use as GPIO for the GPIO role and other pins for an alternative I/O function.

In this application note, we configure the following two pins as GPIO:

  • GPIO_AD_B0_09 (GPIO1_IO09) - this pin is connected to the USER LED of the IMXRT10XX-EVKB board (refer to D18 on i.MX RT1050-EVKB or to the D8 LED on IMXRT1060-EVKB) and can be used as a GPIO Output to control LED

  • WAKEUP (GPIO5_IO00) - this pin is connected to the USER BUTTON of the IMXRT10XX-EVKB board (refer to SW8 on IMXRT1050-EVKB or SW5 on IMXRT1060-EVKB) and can be used as a GPIO Input to get status of the button.

Note that there is the pin conflict in design of the NXP's IMXRT10XX-EVK(B) boards: the GPIO_AD_B0_09 pin is connected to both USER LED and to the Ethernet PHY reset line. To avoid conflict in software and allow using GPIO_AD_B0_09 as a regular GPIO, the fec node should be disabled in DTS.

The pin multiplexing, as well as the PAD control specific configuration, is performed by the Linux kernel drivers using the information from the project's DTS file, this is rootfs.dts.IMXRT105X_NXPEVK or rootfs.dts.IMXRT106X_NXPEVK. Let's edit this file and add the information about the above two GPIOs:

  • Update the pinctrl_leds and pinctrl_gpio_key nodes with the information about specific (e.g. pull-up, alt mux, ...) settings of the used GPIOs.

  • Update the leds and gpio-keys nodes, and specify GPIOs which will be used with them.

  • Disable the fec node to free GPIO_AD_B0_09 from the Ethernet driver.

The result should look like this:

pinctrl_leds: ledsgrp { fsl,pins = < MXRT1050_IOMUXC_GPIO_AD_B0_09_GPIO1_IO09 MXRT10XX_PAD_CFG_GPIO >; }; pinctrl_keys: keysgrp { fsl,pins = < MXRT1050_IOMUXC_SNVS_WAKEUP_GPIO5_IO00 MXRT10XX_PAD_CFG_GPIO >; }; leds { compatible = "gpio-leds"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_leds>; #if 0 /* disbale user-led by deafult due to pinctrl conflict with the FEC device */ status = "disbaled"; user-led { label = "user-led"; gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>; default-state = "off"; }; #endif gpio-keys { compatible = "gpio-keys"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_keys>; #if 0 user-button { label = "user-button"; gpios = <&gpio5 0 GPIO_ACTIVE_LOW>; linux,code = <KEY_A>; }; #endif }; &fec { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_fec>; status = "disabled"; ... };

After applying the above changes to the DTS file, rebuild the rootfs project ( Building Linux ) and install it on the target (Building and Installing Linux uImage on the NXP i.MX RT10XX EVK Board ).

2. Testing GPIO

Each GPIO is assigned a unique integer GPIO number within the GPIO chip range of 0 to 142 by Linux. The i.MX RT1050/1060 supports 5 GPIO blocks (gpio_chips) of 32 pieces GPIO1, GPIO2, GPIO3, GPIO4 and GPIO5. Note that for the GPIO5 chip only 3 first signals are actually available: GPIO5_IO00, GPIO5_IO01 and GPIO5_IO02 - the rest are not output anywhere.

To calculate that number for a specific GPIO, use the following formula:

gpio = chip_base + pin

Kernel allocates the base numbers for GPIO chips dynamically, in 6.6.x the 512 offset is applied to all numbers, refer to include/linux/gpio.h in the Linux kernel sources:

/* * At the end we want all GPIOs to be dynamically allocated from 0. * However, some legacy drivers still perform fixed allocation. * Until they are all fixed, leave 0-512 space for them. */ #define GPIO_DYNAMIC_BASE 512

Since each chip contains the same amount of GPIOs equal to 32, the chip_base can be calculated as:

So the resultant formula for the GPIO number is:

For example:

  • gpio number for GPIO01.IO09 will be (1 – 1) * 32 + 512 + 9 = 521.

  • gpio number for GPIO05.IO00 will be (5 – 1) * 32 + 512 + 0 = 640.

2.1. Testing USER LED

  1. Export GPIO1_IO09:

  2. Use the following command to turn on the USER LED:

  3. Use the following command to turn off the USER LED:

2.2. Testing USER BUTTON

  1. Export GPIO5_IO00:

  2. Make sure the value of GPIO5_IO00 is 1 when the USER BUTTON is untouched (due to the internal PULL-UP being enabled):

  3. Press and hold the USER BUTTON and make sure the GPIO5_IO00 value has changed to 0:

3. Alternative Ways to Access GPIO

In Linux, you may access GPIOs using different approaches, not only the ones described in this application note above. Here are some external links that might be useful if you decide to try an alternative approach.

The following article describes accessing GPIOs from the kernel context: https://lwn.net/Articles/532714/

To work with GPIOs from the user space, there are the following possibilities:

or simply force input subsystem to generate a some-button-pressed event on changing GPIO input.