Skip to content

Convert GPIO drivers to new GPIO API #18530

@galak

Description

@galak

This is a tracking issue on process and status for converting GPIO drivers to support new GPIO API.

Driver Status

PR Ready On Topic On Master Driver Point of Contact Details
altera_nios2 @jenmwms Remove #20214
cc13xx_cc26xx @vanti #19626
cc2650 @galak @vanti Deprecated platform, remove, #22012
cc32xx @vanti #19626
cmsdk_ahb @galak #19382
dw @tbursztyka @dcpleung #19631
esp32 @ExtremeGTX #19753
gecko @mnkp #16648
ht16k33 @henrikbrixandersen #19641
imx @stanislav-poboril #19571
intel_apl @dcpleung #20400
litex #18038, added in topic-gpio
lmp90xxx @henrikbrixandersen #22212
mchp_xec @franciscomunoz @albertofloyd @scottwcpg #19555
mcux @MaureenHelm / @mnkp #16648
mcux_igpio @MaureenHelm #19247
mcux_lpc @agansari #19714
mmio32 @galak #20028
nrfx @mnkp #16648
pcal95xx @dcpleung #20268
rv32m1 @MaureenHelm #19664
sam @mnkp #16648
sam0 @pabigot #19785
sifive @nategraff-sifive #19668
stellaris @galak #19384
stm32 @erwango / @mnkp #19579
sx1509b @pabigot #19379

Steps required to convert a GPIO driver to the new API

Convert board .dts files

Before updating the driver source code it's best to start with updating all in-tree board .dts files (located in boards/ folder) the driver depends on. All the GPIO_* flags currently present in the .dts files, such as GPIO_INT_ACTIVE_LOW, GPIO_PUD_PULL_DOWN, GPIO_DIR_OUT are deprecated and should be removed. The newly introduced flags are compatible with Linux DT. They are located (and documented) in include/dt-bindings/gpio/gpio.h. Their naming and purpose is similar, though not identical to the old flags. Rather than mechanically changing old flags to the matching new ones it's better to consult board's schematic. Pin with no flags defaults to active high and, in case it is configured as an output, to a push-pull mode. The dts files that have been converted so far avoid explicit usage of GPIO_ACTIVE_HIGH or GPIO_PUSH_PULL flags.

At present it's not possible to define pin as input/output in DTS. This is done in the application code. Similarly, no interrupt configuration is possible in DTS.

Update the driver

Several drivers have been updated already. Please use any of the commits as an example, e.g.

  • "drivers: gpio_gecko: update to use new GPIO API"
  • "drivers: gpio_sam: update to use new GPIO API"
  • "drivers: gpio_nrfx: update to use new GPIO API"

Adding the implementation of the new port_get_raw, port_set_masked_raw, port_set_bits_raw, port_clear_bits_raw, port_toggle_bits, functions is usually quite straightforward:

  • get_raw(ptr) => *ptr = INPUT;
  • set_masked_raw(mask, value) => OUTPUT = (OUTPUT & ~mask) | (value & mask);
  • set_bits_raw(pins) => OUTPUT |= pins;
  • clear_bits_raw(pins) => OUTPUT &= ~pins;
  • toggle_bits(pins) => OUTPUT ^= pins;

The more complicated part is the implementation of pin_interrupt_configure function as well as updating config to support new flags.

The old GPIO API configures interrupts via the config function. This is not supported by the new API, however to keep backward compatibility the config function will call pin_interrupt_configure. This call will be removed in the future.

Support for all the flags defined in include/dt-bindings/gpio/gpio.h has to be implemented or the driver should return -ENOTSUP. Also GPIO_OUTPUT_INIT_LOW, GPIO_OUTPUT_INIT_HIGH flags have to be implemented since misbehaving driver has a potential of destroying the board.

The button sample located in samples/basic/button/ is a very simple application that is able to test most of the new features. It's quite handy when starting to work on the new code. The app generates an interrupt the moment board's button is pressed (and displays a message on the console). Also, whenever the button is pressed the board's LED should be ON.

The new GPIO API is not specifically designed to be fast, there is another API in the works which aims to achieve that goal. Nevertheless, once the driver is complete it's worth checking the generated assembly code of the new port_* functions. Following table shows typical length of the port_* functions implemented on ARM Cortex-M4, -M7 architecture.

Function name Assembly instructions no.
port_get_raw 7
port_set_masked_raw 10
port_set_bits_raw 6
port_clear_bits_raw 6
port_toggle_bits 6
port_toggle_bits (no toggle reg) 8

Update *.c files in the board directory

A few boards require initial configuration of GPIO pins. This is done by a *.c file placed in the board directory. If the file contains any calls to the deprecated GPIO functions, e.g. gpio_pin_write or use any of the deprecated flags e.g. GPIO_DIR_OUT they have to be replaced by the corresponding feature of the new API.

Test the driver code

The initial driver development can be guided by samples/basic/button/ sample project. Once the driver is working it should be tested with tests/drivers/gpio/gpio_api_1pin/ testcase. The testcase is using the pin where the board's LED0 is connected to run battery of tests. No hardware modifications to the board are required. However, it relies on the ability of the driver to configure the pin in input/output mode. If this is not supported by the driver the driver should return -ENOTSUP. The testcase should still pass but is pretty useless in assessing quality of the code.

The testcase which is using two (or more) different pins is not ready yet.

Steps required to convert samples / application code to the new API

@mnkp please fill in

List of users to convert: #20017

Metadata

Metadata

Labels

EnhancementChanges/Updates/Additions to existing featuresarea: GPIO

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions