GPIO Driver Interface

This document serves as a guide for writers of GPIO chip drivers.

Each GPIO controller driver needs to include the following header, which definesthe structures used to define a GPIO driver:

#include <linux/gpio/driver.h>

Internal Representation of GPIOs

A GPIO chip handles one or more GPIO lines. To be considered a GPIO chip, thelines must conform to the definition: General Purpose Input/Output. If theline is not general purpose, it is not GPIO and should not be handled by aGPIO chip. The use case is the indicative: certain lines in a system may becalled GPIO but serve a very particular purpose thus not meeting the criteriaof a general purpose I/O. On the other hand a LED driver line may be used as aGPIO and should therefore still be handled by a GPIO chip driver.

Inside a GPIO driver, individual GPIO lines are identified by their hardwarenumber, sometime also referred to asoffset, which is a unique numberbetween 0 and n-1, n being the number of GPIOs managed by the chip.

The hardware GPIO number should be something intuitive to the hardware, forexample if a system uses a memory-mapped set of I/O-registers where 32 GPIOlines are handled by one bit per line in a 32-bit register, it makes sense touse hardware offsets 0..31 for these, corresponding to bits 0..31 in theregister.

This number is purely internal: the hardware number of a particular GPIOline is never made visible outside of the driver.

On top of this internal number, each GPIO line also needs to have a globalnumber in the integer GPIO namespace so that it can be used with the legacy GPIOinterface. Each chip must thus have a “base” number (which can be automaticallyassigned), and for each GPIO line the global number will be (base + hardwarenumber). Although the integer representation is considered deprecated, it stillhas many users and thus needs to be maintained.

So for example one platform could use global numbers 32-159 for GPIOs, with acontroller defining 128 GPIOs at a “base” of 32 ; while another platform usesglobal numbers 0..63 with one set of GPIO controllers, 64-79 with another typeof GPIO controller, and on one particular board 80-95 with an FPGA. The legacynumbers need not be contiguous; either of those platforms could also use numbers2000-2063 to identify GPIO lines in a bank of I2C GPIO expanders.

Controller Drivers: gpio_chip

In the gpiolib framework each GPIO controller is packaged as a “structgpio_chip” (see <linux/gpio/driver.h> for its complete definition) with memberscommon to each controller of that type, these should be assigned by thedriver code:

  • methods to establish GPIO line direction

  • methods used to access GPIO line values

  • method to set electrical configuration for a given GPIO line

  • method to return the IRQ number associated to a given GPIO line

  • flag saying whether calls to its methods may sleep

  • optional line names array to identify lines

  • optional debugfs dump method (showing extra state information)

  • optional base number (will be automatically assigned if omitted)

  • optional label for diagnostics and GPIO chip mapping using platform data

The code implementing a gpio_chip should support multiple instances of thecontroller, preferably using the driver model. That code will configure eachgpio_chip and issuegpiochip_add_data() ordevm_gpiochip_add_data(). Removinga GPIO controller should be rare; usegpiochip_remove() when it is unavoidable.

Often a gpio_chip is part of an instance-specific structure with states notexposed by the GPIO interfaces, such as addressing, power management, and more.Chips such as audio codecs will have complex non-GPIO states.

Any debugfs dump method should normally ignore lines which haven’t beenrequested. They can usegpiochip_is_requested(), which returns eitherNULL or the label associated with that GPIO line when it was requested.

Realtime considerations: the GPIO driver should not use spinlock_t or anysleepable APIs (like PM runtime) in its gpio_chip implementation (.get/.setand direction control callbacks) if it is expected to call GPIO APIs fromatomic context on realtime kernels (inside hard IRQ handlers and similarcontexts). Normally this should not be required.

GPIO electrical configuration

GPIO lines can be configured for several electrical modes of operation by usingthe .set_config() callback. Currently this API supports setting:

  • Debouncing

  • Single-ended modes (open drain/open source)

  • Pull up and pull down resistor enablement

These settings are described below.

The .set_config() callback uses the same enumerators and configurationsemantics as the generic pin control drivers. This is not a coincidence: it ispossible to assign the .set_config() to the functiongpiochip_generic_config()which will result inpinctrl_gpio_set_config() being called and eventuallyending up in the pin control back-end “behind” the GPIO controller, usuallycloser to the actual pins. This way the pin controller can manage the belowlisted GPIO configurations.

If a pin controller back-end is used, the GPIO controller or hardwaredescription needs to provide “GPIO ranges” mapping the GPIO line offsets to pinnumbers on the pin controller so they can properly cross-reference each other.

GPIO lines with debounce support

Debouncing is a configuration set to a pin indicating that it is connected toa mechanical switch or button, or similar that may bounce. Bouncing means theline is pulled high/low quickly at very short intervals for mechanicalreasons. This can result in the value being unstable or irqs firing repeatedlyunless the line is debounced.

Debouncing in practice involves setting up a timer when something happens onthe line, wait a little while and then sample the line again, so see if itstill has the same value (low or high). This could also be repeated by a cleverstate machine, waiting for a line to become stable. In either case, it setsa certain number of milliseconds for debouncing, or just “on/off” if that timeis not configurable.

GPIO lines with open drain/source support

Open drain (CMOS) or open collector (TTL) means the line is not actively drivenhigh: instead you provide the drain/collector as output, so when the transistoris not open, it will present a high-impedance (tristate) to the external rail:

CMOS CONFIGURATION      TTL CONFIGURATION         ||--- out              +--- out  in ----||                   |/         ||--+         in ----|             |                |\            GND                 GND

This configuration is normally used as a way to achieve one of two things:

  • Level-shifting: to reach a logical level higher than that of the siliconwhere the output resides.

  • Inverse wire-OR on an I/O line, for example a GPIO line, making it possiblefor any driving stage on the line to drive it low even if any other outputto the same line is simultaneously driving it high. A special case of thisis driving the SCL and SDA lines of an I2C bus, which is by definition awire-OR bus.

Both use cases require that the line be equipped with a pull-up resistor. Thisresistor will make the line tend to high level unless one of the transistors onthe rail actively pulls it down.

The level on the line will go as high as the VDD on the pull-up resistor, whichmay be higher than the level supported by the transistor, achieving alevel-shift to the higher VDD.

Integrated electronics often have an output driver stage in the form of a CMOS“totem-pole” with one N-MOS and one P-MOS transistor where one of them drivesthe line high and one of them drives the line low. This is called a push-pulloutput. The “totem-pole” looks like so:

                 VDD                  |        OD    ||--+     +--/ ---o||     P-MOS-FET     |        ||--+IN --+            +----- out     |        ||--+     +--/ ----||     N-MOS-FET        OS    ||--+                  |                 GND

The desired output signal (e.g. coming directly from some GPIO output register)arrives at IN. The switches named “OD” and “OS” are normally closed, creatinga push-pull circuit.

Consider the little “switches” named “OD” and “OS” that enable/disable theP-MOS or N-MOS transistor right after the split of the input. As you can see,either transistor will go totally numb if this switch is open. The totem-poleis then halved and give high impedance instead of actively driving the linehigh or low respectively. That is usually how software-controlled opendrain/source works.

Some GPIO hardware come in open drain / open source configuration. Some arehard-wired lines that will only support open drain or open source no matterwhat: there is only one transistor there. Some are software-configurable:by flipping a bit in a register the output can be configured as open drainor open source, in practice by flicking open the switches labeled “OD” and “OS”in the drawing above.

By disabling the P-MOS transistor, the output can be driven between GND andhigh impedance (open drain), and by disabling the N-MOS transistor, the outputcan be driven between VDD and high impedance (open source). In the first case,a pull-up resistor is needed on the outgoing rail to complete the circuit, andin the second case, a pull-down resistor is needed on the rail.

Hardware that supports open drain or open source or both, can implement aspecial callback in the gpio_chip: .set_config() that takes a genericpinconf packed value telling whether to configure the line as open drain,open source or push-pull. This will happen in response to theGPIO_OPEN_DRAIN or GPIO_OPEN_SOURCE flag set in the machine file, or comingfrom other hardware descriptions.

If this state can not be configured in hardware, i.e. if the GPIO hardware doesnot support open drain/open source in hardware, the GPIO library will insteaduse a trick: when a line is set as output, if the line is flagged as opendrain, and the IN output value is low, it will be driven low as usual. Butif the IN output value is set to high, it will insteadNOT be driven high,instead it will be switched to input, as input mode is an equivalent tohigh impedance, thus achieving an “open drain emulation” of sorts: electricallythe behaviour will be identical, with the exception of possible hardware glitcheswhen switching the mode of the line.

For open source configuration the same principle is used, just that insteadof actively driving the line low, it is set to input.

GPIO lines with pull up/down resistor support

A GPIO line can support pull-up/down using the .set_config() callback. Thismeans that a pull up or pull-down resistor is available on the output of theGPIO line, and this resistor is software controlled.

In discrete designs, a pull-up or pull-down resistor is simply soldered onthe circuit board. This is not something we deal with or model in software. Themost you will think about these lines is that they will very likely beconfigured as open drain or open source (see the section above).

The .set_config() callback can only turn pull up or down on and off, and willno have any semantic knowledge about the resistance used. It will only sayswitch a bit in a register enabling or disabling pull-up or pull-down.

If the GPIO line supports shunting in different resistance values for thepull-up or pull-down resistor, the GPIO chip callback .set_config() will notsuffice. For these complex use cases, a combined GPIO chip and pin controllerneed to be implemented, as the pin config interface of a pin controllersupports more versatile control over electrical properties and can handledifferent pull-up or pull-down resistance values.

GPIO drivers providing IRQs

It is custom that GPIO drivers (GPIO chips) are also providing interrupts,most often cascaded off a parent interrupt controller, and in some specialcases the GPIO logic is melded with a SoC’s primary interrupt controller.

The IRQ portions of the GPIO block are implemented using an irq_chip, usingthe header <linux/irq.h>. So this combined driver is utilizing two sub-systems simultaneously: gpio and irq.

It is legal for any IRQ consumer to request an IRQ from any irqchip even if itis a combined GPIO+IRQ driver. The basic premise is that gpio_chip andirq_chip are orthogonal, and offering their services independent of eachother.

gpiod_to_irq() is just a convenience function to figure out the IRQ for acertain GPIO line and should not be relied upon to have been called beforethe IRQ is used.

Always prepare the hardware and make it ready for action in respectivecallbacks from the GPIO and irq_chip APIs. Do not rely ongpiod_to_irq() havingbeen called first.

We can divide GPIO irqchips in two broad categories:

  • CASCADED INTERRUPT CHIPS: this means that the GPIO chip has one commoninterrupt output line, which is triggered by any enabled GPIO line on thatchip. The interrupt output line will then be routed to an parent interruptcontroller one level up, in the most simple case the systems primaryinterrupt controller. This is modeled by an irqchip that will inspect bitsinside the GPIO controller to figure out which line fired it. The irqchippart of the driver needs to inspect registers to figure this out and itwill likely also need to acknowledge that it is handling the interruptby clearing some bit (sometime implicitly, by just reading a statusregister) and it will often need to set up the configuration such asedge sensitivity (rising or falling edge, or high/low level interrupt forexample).

  • HIERARCHICAL INTERRUPT CHIPS: this means that each GPIO line has a dedicatedirq line to a parent interrupt controller one level up. There is no needto inquire the GPIO hardware to figure out which line has fired, but itmay still be necessary to acknowledge the interrupt and set up configurationsuch as edge sensitivity.

Realtime considerations: a realtime compliant GPIO driver should not usespinlock_t or any sleepable APIs (like PM runtime) as part of its irqchipimplementation.

  • spinlock_t should be replaced with raw_spinlock_t.[1]

  • If sleepable APIs have to be used, these can be done from the .irq_bus_lock()and .irq_bus_unlock() callbacks, as these are the only slowpath callbackson an irqchip. Create the callbacks if needed.[2]

Cascaded GPIO irqchips

Cascaded GPIO irqchips usually fall in one of three categories:

  • CHAINED CASCADED GPIO IRQCHIPS: these are usually the type that is embedded onan SoC. This means that there is a fast IRQ flow handler for the GPIOs thatgets called in a chain from the parent IRQ handler, most typically thesystem interrupt controller. This means that the GPIO irqchip handler willbe called immediately from the parent irqchip, while holding the IRQsdisabled. The GPIO irqchip will then end up calling something like thissequence in its interrupt handler:

    static irqreturn_t foo_gpio_irq(int irq, void *data)    chained_irq_enter(...);    generic_handle_irq(...);    chained_irq_exit(...);

    Chained GPIO irqchips typically can NOT set the .can_sleep flag onstructgpio_chip, as everything happens directly in the callbacks: noslow bus traffic like I2C can be used.

    Realtime considerations: Note that chained IRQ handlers will not be forcedthreaded on -RT. As a result, spinlock_t or any sleepable APIs (like PMruntime) can’t be used in a chained IRQ handler.

    If required (and if it can’t be converted to the nested threaded GPIO irqchip,see below) a chained IRQ handler can be converted to generic irq handler andthis way it will become a threaded IRQ handler on -RT and a hard IRQ handleron non-RT (for example, see [3]).

    Thegeneric_handle_irq() is expected to be called with IRQ disabled,so the IRQ core will complain if it is called from an IRQ handler which isforced to a thread. The “fake?” raw lock can be used to work around thisproblem:

    raw_spinlock_t wa_lock;static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)    unsigned long wa_lock_flags;    raw_spin_lock_irqsave(&bank->wa_lock, wa_lock_flags);    generic_handle_irq(irq_find_mapping(bank->chip.irq.domain, bit));    raw_spin_unlock_irqrestore(&bank->wa_lock, wa_lock_flags);
  • GENERIC CHAINED GPIO IRQCHIPS: these are the same as “CHAINED GPIO irqchips”,but chained IRQ handlers are not used. Instead GPIO IRQs dispatching isperformed by generic IRQ handler which is configured usingrequest_irq().The GPIO irqchip will then end up calling something like this sequence inits interrupt handler:

    static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id)    for each detected GPIO IRQ        generic_handle_irq(...);

    Realtime considerations: this kind of handlers will be forced threaded on -RT,and as result the IRQ core will complain thatgeneric_handle_irq() is calledwith IRQ enabled and the same work-around as for “CHAINED GPIO irqchips” canbe applied.

  • NESTED THREADED GPIO IRQCHIPS: these are off-chip GPIO expanders and anyother GPIO irqchip residing on the other side of a sleeping bus such as I2Cor SPI.

    Of course such drivers that need slow bus traffic to read out IRQ status andsimilar, traffic which may in turn incur other IRQs to happen, cannot behandled in a quick IRQ handler with IRQs disabled. Instead they need to spawna thread and then mask the parent IRQ line until the interrupt is handledby the driver. The hallmark of this driver is to call something likethis in its interrupt handler:

    static irqreturn_t foo_gpio_irq(int irq, void *data)    ...    handle_nested_irq(irq);

    The hallmark of threaded GPIO irqchips is that they set the .can_sleepflag onstructgpio_chip to true, indicating that this chip may sleepwhen accessing the GPIOs.

    These kinds of irqchips are inherently realtime tolerant as they arealready set up to handle sleeping contexts.

Infrastructure helpers for GPIO irqchips

To help out in handling the set-up and management of GPIO irqchips and theassociated irqdomain and resource allocation callbacks. These are activatedby selecting the Kconfig symbol GPIOLIB_IRQCHIP. If the symbolIRQ_DOMAIN_HIERARCHY is also selected, hierarchical helpers will also beprovided. A big portion of overhead code will be managed by gpiolib,under the assumption that your interrupts are 1-to-1-mapped to theGPIO line index:

GPIO line offset

Hardware IRQ

0

0

1

1

2

2

...

...

ngpio-1

ngpio-1

If some GPIO lines do not have corresponding IRQs, the bitmask valid_maskand the flag need_valid_mask in gpio_irq_chip can be used to mask off somelines as invalid for associating with IRQs.

The preferred way to set up the helpers is to fill in thestructgpio_irq_chip insidestructgpio_chip before adding the gpio_chip.If you do this, the additional irq_chip will be set up by gpiolib at thesame time as setting up the rest of the GPIO functionality. The followingis a typical example of a chained cascaded interrupt handler usingthe gpio_irq_chip. Note how the mask/unmask (or disable/enable) functionscall into the core gpiolib code:

/* Typical state container */structmy_gpio{structgpio_chipgc;};staticvoidmy_gpio_mask_irq(structirq_data*d){structgpio_chip*gc=irq_data_get_irq_chip_data(d);irq_hw_number_thwirq=irqd_to_hwirq(d);/*     * Perform any necessary action to mask the interrupt,     * and then call into the core code to synchronise the     * state.     */gpiochip_disable_irq(gc,hwirq);}staticvoidmy_gpio_unmask_irq(structirq_data*d){structgpio_chip*gc=irq_data_get_irq_chip_data(d);irq_hw_number_thwirq=irqd_to_hwirq(d);gpiochip_enable_irq(gc,hwirq);/*     * Perform any necessary action to unmask the interrupt,     * after having called into the core code to synchronise     * the state.     */}/* * Statically populate the irqchip. Note that it is made const * (further indicated by the IRQCHIP_IMMUTABLE flag), and that * the GPIOCHIP_IRQ_RESOURCE_HELPER macro adds some extra * callbacks to the structure. */staticconststructirq_chipmy_gpio_irq_chip={.name="my_gpio_irq",.irq_ack=my_gpio_ack_irq,.irq_mask=my_gpio_mask_irq,.irq_unmask=my_gpio_unmask_irq,.irq_set_type=my_gpio_set_irq_type,.flags=IRQCHIP_IMMUTABLE,/* Provide the gpio resource callbacks */GPIOCHIP_IRQ_RESOURCE_HELPERS,};intirq;/* from platform etc */structmy_gpio*g;structgpio_irq_chip*girq;/* Get a pointer to the gpio_irq_chip */girq=&g->gc.irq;gpio_irq_chip_set_chip(girq,&my_gpio_irq_chip);girq->parent_handler=ftgpio_gpio_irq_handler;girq->num_parents=1;girq->parents=devm_kcalloc(dev,1,sizeof(*girq->parents),GFP_KERNEL);if(!girq->parents)return-ENOMEM;girq->default_type=IRQ_TYPE_NONE;girq->handler=handle_bad_irq;girq->parents[0]=irq;returndevm_gpiochip_add_data(dev,&g->gc,g);

The helper supports using threaded interrupts as well. Then you just requestthe interrupt separately and go with it:

/* Typical state container */structmy_gpio{structgpio_chipgc;};staticvoidmy_gpio_mask_irq(structirq_data*d){structgpio_chip*gc=irq_data_get_irq_chip_data(d);irq_hw_number_thwirq=irqd_to_hwirq(d);/*     * Perform any necessary action to mask the interrupt,     * and then call into the core code to synchronise the     * state.     */gpiochip_disable_irq(gc,hwirq);}staticvoidmy_gpio_unmask_irq(structirq_data*d){structgpio_chip*gc=irq_data_get_irq_chip_data(d);irq_hw_number_thwirq=irqd_to_hwirq(d);gpiochip_enable_irq(gc,hwirq);/*     * Perform any necessary action to unmask the interrupt,     * after having called into the core code to synchronise     * the state.     */}/* * Statically populate the irqchip. Note that it is made const * (further indicated by the IRQCHIP_IMMUTABLE flag), and that * the GPIOCHIP_IRQ_RESOURCE_HELPER macro adds some extra * callbacks to the structure. */staticconststructirq_chipmy_gpio_irq_chip={.name="my_gpio_irq",.irq_ack=my_gpio_ack_irq,.irq_mask=my_gpio_mask_irq,.irq_unmask=my_gpio_unmask_irq,.irq_set_type=my_gpio_set_irq_type,.flags=IRQCHIP_IMMUTABLE,/* Provide the gpio resource callbacks */GPIOCHIP_IRQ_RESOURCE_HELPERS,};intirq;/* from platform etc */structmy_gpio*g;structgpio_irq_chip*girq;ret=devm_request_threaded_irq(dev,irq,NULL,irq_thread_fn,IRQF_ONESHOT,"my-chip",g);if(ret<0)returnret;/* Get a pointer to the gpio_irq_chip */girq=&g->gc.irq;gpio_irq_chip_set_chip(girq,&my_gpio_irq_chip);/* This will let us handle the parent IRQ in the driver */girq->parent_handler=NULL;girq->num_parents=0;girq->parents=NULL;girq->default_type=IRQ_TYPE_NONE;girq->handler=handle_bad_irq;returndevm_gpiochip_add_data(dev,&g->gc,g);

The helper supports using hierarchical interrupt controllers as well.In this case the typical set-up will look like this:

/* Typical state container with dynamic irqchip */structmy_gpio{structgpio_chipgc;structfwnode_handle*fwnode;};staticvoidmy_gpio_mask_irq(structirq_data*d){structgpio_chip*gc=irq_data_get_irq_chip_data(d);irq_hw_number_thwirq=irqd_to_hwirq(d);/*     * Perform any necessary action to mask the interrupt,     * and then call into the core code to synchronise the     * state.     */gpiochip_disable_irq(gc,hwirq);irq_mask_mask_parent(d);}staticvoidmy_gpio_unmask_irq(structirq_data*d){structgpio_chip*gc=irq_data_get_irq_chip_data(d);irq_hw_number_thwirq=irqd_to_hwirq(d);gpiochip_enable_irq(gc,hwirq);/*     * Perform any necessary action to unmask the interrupt,     * after having called into the core code to synchronise     * the state.     */irq_mask_unmask_parent(d);}/* * Statically populate the irqchip. Note that it is made const * (further indicated by the IRQCHIP_IMMUTABLE flag), and that * the GPIOCHIP_IRQ_RESOURCE_HELPER macro adds some extra * callbacks to the structure. */staticconststructirq_chipmy_gpio_irq_chip={.name="my_gpio_irq",.irq_ack=my_gpio_ack_irq,.irq_mask=my_gpio_mask_irq,.irq_unmask=my_gpio_unmask_irq,.irq_set_type=my_gpio_set_irq_type,.flags=IRQCHIP_IMMUTABLE,/* Provide the gpio resource callbacks */GPIOCHIP_IRQ_RESOURCE_HELPERS,};structmy_gpio*g;structgpio_irq_chip*girq;/* Get a pointer to the gpio_irq_chip */girq=&g->gc.irq;gpio_irq_chip_set_chip(girq,&my_gpio_irq_chip);girq->default_type=IRQ_TYPE_NONE;girq->handler=handle_bad_irq;girq->fwnode=g->fwnode;girq->parent_domain=parent;girq->child_to_parent_hwirq=my_gpio_child_to_parent_hwirq;returndevm_gpiochip_add_data(dev,&g->gc,g);

As you can see pretty similar, but you do not supply a parent handler forthe IRQ, instead a parent irqdomain, an fwnode for the hardware anda function .child_to_parent_hwirq() that has the purpose of looking upthe parent hardware irq from a child (i.e. this gpio chip) hardware irq.As always it is good to look at examples in the kernel tree for adviceon how to find the required pieces.

If there is a need to exclude certain GPIO lines from the IRQ domain handled bythese helpers, we can set .irq.need_valid_mask of the gpiochip beforedevm_gpiochip_add_data() orgpiochip_add_data() is called. This allocates an.irq.valid_mask with as many bits set as there are GPIO lines in the chip, eachbit representing line 0..n-1. Drivers can exclude GPIO lines by clearing bitsfrom this mask. The mask can be filled in theinit_valid_mask() callbackthat is part of thestructgpio_irq_chip.

To use the helpers please keep the following in mind:

  • Make sure to assign all relevant members of thestructgpio_chip so thatthe irqchip can initialize. E.g. .dev and .can_sleep shall be set upproperly.

  • Nominally set gpio_irq_chip.handler to handle_bad_irq. Then, if your irqchipis cascaded, set the handler tohandle_level_irq() and/orhandle_edge_irq()in the irqchip .set_type() callback depending on what your controllersupports and what is requested by the consumer.

Locking IRQ usage

Since GPIO and irq_chip are orthogonal, we can get conflicts between differentuse cases. For example a GPIO line used for IRQs should be an input line,it does not make sense to fire interrupts on an output GPIO.

If there is competition inside the subsystem which side is using theresource (a certain GPIO line and register for example) it needs to denycertain operations and keep track of usage inside of the gpiolib subsystem.

Input GPIOs can be used as IRQ signals. When this happens, a driver is requestedto mark the GPIO as being used as an IRQ:

int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset)

This will prevent the use of non-irq related GPIO APIs until the GPIO IRQ lockis released:

void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)

When implementing an irqchip inside a GPIO driver, these two functions shouldtypically be called in the .startup() and .shutdown() callbacks from theirqchip.

When using the gpiolib irqchip helpers, these callbacks are automaticallyassigned.

Disabling and enabling IRQs

In some (fringe) use cases, a driver may be using a GPIO line as input for IRQs,but occasionally switch that line over to drive output and then back to beingan input with interrupts again. This happens on things like CEC (ConsumerElectronics Control).

When a GPIO is used as an IRQ signal, then gpiolib also needs to know ifthe IRQ is enabled or disabled. In order to inform gpiolib about this,the irqchip driver should call:

void gpiochip_disable_irq(struct gpio_chip *chip, unsigned int offset)

This allows drivers to drive the GPIO as an output while the IRQ isdisabled. When the IRQ is enabled again, a driver should call:

void gpiochip_enable_irq(struct gpio_chip *chip, unsigned int offset)

When implementing an irqchip inside a GPIO driver, these two functions shouldtypically be called in the .irq_disable() and .irq_enable() callbacks from theirqchip.

When IRQCHIP_IMMUTABLE is not advertised by the irqchip, these callbacksare automatically assigned. This behaviour is deprecated and on its wayto be removed from the kernel.

Real-Time compliance for GPIO IRQ chips

Any provider of irqchips needs to be carefully tailored to support Real-Timepreemption. It is desirable that all irqchips in the GPIO subsystem keep thisin mind and do the proper testing to assure they are real time-enabled.

So, pay attention on above realtime considerations in the documentation.

The following is a checklist to follow when preparing a driver for real-timecompliance:

  • ensure spinlock_t is not used as part irq_chip implementation

  • ensure that sleepable APIs are not used as part irq_chip implementationIf sleepable APIs have to be used, these can be done from the .irq_bus_lock()and .irq_bus_unlock() callbacks

  • Chained GPIO irqchips: ensure spinlock_t or any sleepable APIs are not usedfrom the chained IRQ handler

  • Generic chained GPIO irqchips: take care aboutgeneric_handle_irq() calls andapply corresponding work-around

  • Chained GPIO irqchips: get rid of the chained IRQ handler and use generic irqhandler if possible

  • regmap_mmio: it is possible to disable internal locking in regmap by setting.disable_locking and handling the locking in the GPIO driver

  • Test your driver with the appropriate in-kernel real-time test cases for bothlevel and edge IRQs

Requesting self-owned GPIO pins

Sometimes it is useful to allow a GPIO chip driver to request its own GPIOdescriptors through the gpiolib API. A GPIO driver can use the followingfunctions to request and free descriptors:

struct gpio_desc *gpiochip_request_own_desc(struct gpio_desc *desc,                                            u16 hwnum,                                            const char *label,                                            enum gpiod_flags flags)void gpiochip_free_own_desc(struct gpio_desc *desc)

Descriptors requested withgpiochip_request_own_desc() must be released withgpiochip_free_own_desc().

These functions must be used with care since they do not affect module usecount. Do not use the functions to request gpio descriptors not owned by thecalling driver.