sphinx.addnodesdocument)}( rawsourcechildren]( translations LanguagesNode)}(hhh](h pending_xref)}(hhh]docutils.nodesTextChinese (Simplified)}parenthsba attributes}(ids]classes]names]dupnames]backrefs] refdomainstdreftypedoc reftarget*/translations/zh_CN/driver-api/gpio/drivermodnameN classnameN refexplicitutagnamehhh ubh)}(hhh]hChinese (Traditional)}hh2sbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget*/translations/zh_TW/driver-api/gpio/drivermodnameN classnameN refexplicituh1hhh ubh)}(hhh]hItalian}hhFsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget*/translations/it_IT/driver-api/gpio/drivermodnameN classnameN refexplicituh1hhh ubh)}(hhh]hJapanese}hhZsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget*/translations/ja_JP/driver-api/gpio/drivermodnameN classnameN refexplicituh1hhh ubh)}(hhh]hKorean}hhnsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget*/translations/ko_KR/driver-api/gpio/drivermodnameN classnameN refexplicituh1hhh ubh)}(hhh]hSpanish}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget*/translations/sp_SP/driver-api/gpio/drivermodnameN classnameN refexplicituh1hhh ubeh}(h]h ]h"]h$]h&]current_languageEnglishuh1h hh _documenthsourceNlineNubhsection)}(hhh](htitle)}(hGPIO Driver Interfaceh]hGPIO Driver Interface}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhD/var/lib/git/docbuild/linux/Documentation/driver-api/gpio/driver.rsthKubh paragraph)}(hAThis document serves as a guide for writers of GPIO chip drivers.h]hAThis document serves as a guide for writers of GPIO chip drivers.}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(h~Each GPIO controller driver needs to include the following header, which defines the structures used to define a GPIO driver::h]h}Each GPIO controller driver needs to include the following header, which defines the structures used to define a GPIO driver:}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh literal_block)}(h#include h]h#include }hhsbah}(h]h ]h"]h$]h&] xml:spacepreserveuh1hhhhK hhhhubh)}(hhh](h)}(h Internal Representation of GPIOsh]h Internal Representation of GPIOs}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhhhKubh)}(hXA GPIO chip handles one or more GPIO lines. To be considered a GPIO chip, the lines must conform to the definition: General Purpose Input/Output. If the line is not general purpose, it is not GPIO and should not be handled by a GPIO chip. The use case is the indicative: certain lines in a system may be called GPIO but serve a very particular purpose thus not meeting the criteria of a general purpose I/O. On the other hand a LED driver line may be used as a GPIO and should therefore still be handled by a GPIO chip driver.h]hXA GPIO chip handles one or more GPIO lines. To be considered a GPIO chip, the lines must conform to the definition: General Purpose Input/Output. If the line is not general purpose, it is not GPIO and should not be handled by a GPIO chip. The use case is the indicative: certain lines in a system may be called GPIO but serve a very particular purpose thus not meeting the criteria of a general purpose I/O. On the other hand a LED driver line may be used as a GPIO and should therefore still be handled by a GPIO chip driver.}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hInside a GPIO driver, individual GPIO lines are identified by their hardware number, sometime also referred to as ``offset``, which is a unique number between 0 and n-1, n being the number of GPIOs managed by the chip.h](hrInside a GPIO driver, individual GPIO lines are identified by their hardware number, sometime also referred to as }(hjhhhNhNubhliteral)}(h ``offset``h]hoffset}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh^, which is a unique number between 0 and n-1, n being the number of GPIOs managed by the chip.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hX8The hardware GPIO number should be something intuitive to the hardware, for example if a system uses a memory-mapped set of I/O-registers where 32 GPIO lines are handled by one bit per line in a 32-bit register, it makes sense to use hardware offsets 0..31 for these, corresponding to bits 0..31 in the register.h]hX8The hardware GPIO number should be something intuitive to the hardware, for example if a system uses a memory-mapped set of I/O-registers where 32 GPIO lines are handled by one bit per line in a 32-bit register, it makes sense to use hardware offsets 0..31 for these, corresponding to bits 0..31 in the register.}(hj(hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hzThis number is purely internal: the hardware number of a particular GPIO line is never made visible outside of the driver.h]hzThis number is purely internal: the hardware number of a particular GPIO line is never made visible outside of the driver.}(hj6hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK"hhhhubh)}(hXOn top of this internal number, each GPIO line also needs to have a global number in the integer GPIO namespace so that it can be used with the legacy GPIO interface. Each chip must thus have a "base" number (which can be automatically assigned), and for each GPIO line the global number will be (base + hardware number). Although the integer representation is considered deprecated, it still has many users and thus needs to be maintained.h]hXOn top of this internal number, each GPIO line also needs to have a global number in the integer GPIO namespace so that it can be used with the legacy GPIO interface. Each chip must thus have a “base” number (which can be automatically assigned), and for each GPIO line the global number will be (base + hardware number). Although the integer representation is considered deprecated, it still has many users and thus needs to be maintained.}(hjDhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK%hhhhubh)}(hXSo for example one platform could use global numbers 32-159 for GPIOs, with a controller defining 128 GPIOs at a "base" of 32 ; while another platform uses global numbers 0..63 with one set of GPIO controllers, 64-79 with another type of GPIO controller, and on one particular board 80-95 with an FPGA. The legacy numbers need not be contiguous; either of those platforms could also use numbers 2000-2063 to identify GPIO lines in a bank of I2C GPIO expanders.h]hXSo for example one platform could use global numbers 32-159 for GPIOs, with a controller defining 128 GPIOs at a “base” of 32 ; while another platform uses global numbers 0..63 with one set of GPIO controllers, 64-79 with another type of GPIO controller, and on one particular board 80-95 with an FPGA. The legacy numbers need not be contiguous; either of those platforms could also use numbers 2000-2063 to identify GPIO lines in a bank of I2C GPIO expanders.}(hjRhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK,hhhhubeh}(h] internal-representation-of-gpiosah ]h"] internal representation of gpiosah$]h&]uh1hhhhhhhhKubh)}(hhh](h)}(hController Drivers: gpio_chiph]hController Drivers: gpio_chip}(hjkhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhhK5ubh)}(hIn the gpiolib framework each GPIO controller is packaged as a "struct gpio_chip" (see for its complete definition) with members common to each controller of that type, these should be assigned by the driver code:h]hIn the gpiolib framework each GPIO controller is packaged as a “struct gpio_chip” (see for its complete definition) with members common to each controller of that type, these should be assigned by the driver code:}(hjyhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK7hjhhhubh block_quote)}(hX- 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 h]h bullet_list)}(hhh](h list_item)}(h(methods to establish GPIO line directionh]h)}(hjh]h(methods to establish GPIO line direction}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(h?method to return the IRQ number associated to a given GPIO lineh]h)}(hjh]h?method to return the IRQ number associated to a given GPIO line}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK?hjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(h2flag saying whether calls to its methods may sleeph]h)}(hjh]h2flag saying whether calls to its methods may sleep}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK@hjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(h+optional line names array to identify linesh]h)}(hj h]h+optional line names array to identify lines}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKAhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(h>optional debugfs dump method (showing extra state information)h]h)}(hj h]h>optional debugfs dump method (showing extra state information)}(hj"hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKBhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(h@optional base number (will be automatically assigned if omitted)h]h)}(hj7h]h@optional base number (will be automatically assigned if omitted)}(hj9hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKChj5ubah}(h]h ]h"]h$]h&]uh1jhjubj)}(hIoptional label for diagnostics and GPIO chip mapping using platform data h]h)}(hHoptional label for diagnostics and GPIO chip mapping using platform datah]hHoptional label for diagnostics and GPIO chip mapping using platform data}(hjPhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKDhjLubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]bullet-uh1jhhhK. So this combined driver is utilizing two sub- systems simultaneously: gpio and irq.h]hThe IRQ portions of the GPIO block are implemented using an irq_chip, using the header . So this combined driver is utilizing two sub- systems simultaneously: gpio and irq.}(hj!hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(hIt is legal for any IRQ consumer to request an IRQ from any irqchip even if it is a combined GPIO+IRQ driver. The basic premise is that gpio_chip and irq_chip are orthogonal, and offering their services independent of each other.h]hIt is legal for any IRQ consumer to request an IRQ from any irqchip even if it is a combined GPIO+IRQ driver. The basic premise is that gpio_chip and irq_chip are orthogonal, and offering their services independent of each other.}(hj/hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(hgpiod_to_irq() is just a convenience function to figure out the IRQ for a certain GPIO line and should not be relied upon to have been called before the IRQ is used.h]hgpiod_to_irq() is just a convenience function to figure out the IRQ for a certain GPIO line and should not be relied upon to have been called before the IRQ is used.}(hj=hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM hjhhubh)}(hAlways prepare the hardware and make it ready for action in respective callbacks from the GPIO and irq_chip APIs. Do not rely on gpiod_to_irq() having been called first.h]hAlways prepare the hardware and make it ready for action in respective callbacks from the GPIO and irq_chip APIs. Do not rely on gpiod_to_irq() having been called first.}(hjKhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(h4We can divide GPIO irqchips in two broad categories:h]h4We can divide GPIO irqchips in two broad categories:}(hjYhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubj)}(hhh](j)}(hX#CASCADED INTERRUPT CHIPS: this means that the GPIO chip has one common interrupt output line, which is triggered by any enabled GPIO line on that chip. The interrupt output line will then be routed to an parent interrupt controller one level up, in the most simple case the systems primary interrupt controller. This is modeled by an irqchip that will inspect bits inside the GPIO controller to figure out which line fired it. The irqchip part of the driver needs to inspect registers to figure this out and it will likely also need to acknowledge that it is handling the interrupt by clearing some bit (sometime implicitly, by just reading a status register) and it will often need to set up the configuration such as edge sensitivity (rising or falling edge, or high/low level interrupt for example). h]h)}(hX"CASCADED INTERRUPT CHIPS: this means that the GPIO chip has one common interrupt output line, which is triggered by any enabled GPIO line on that chip. The interrupt output line will then be routed to an parent interrupt controller one level up, in the most simple case the systems primary interrupt controller. This is modeled by an irqchip that will inspect bits inside the GPIO controller to figure out which line fired it. The irqchip part of the driver needs to inspect registers to figure this out and it will likely also need to acknowledge that it is handling the interrupt by clearing some bit (sometime implicitly, by just reading a status register) and it will often need to set up the configuration such as edge sensitivity (rising or falling edge, or high/low level interrupt for example).h]hX"CASCADED INTERRUPT CHIPS: this means that the GPIO chip has one common interrupt output line, which is triggered by any enabled GPIO line on that chip. The interrupt output line will then be routed to an parent interrupt controller one level up, in the most simple case the systems primary interrupt controller. This is modeled by an irqchip that will inspect bits inside the GPIO controller to figure out which line fired it. The irqchip part of the driver needs to inspect registers to figure this out and it will likely also need to acknowledge that it is handling the interrupt by clearing some bit (sometime implicitly, by just reading a status register) and it will often need to set up the configuration such as edge sensitivity (rising or falling edge, or high/low level interrupt for example).}(hjnhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjjubah}(h]h ]h"]h$]h&]uh1jhjghhhhhNubj)}(hXEHIERARCHICAL INTERRUPT CHIPS: this means that each GPIO line has a dedicated irq line to a parent interrupt controller one level up. There is no need to inquire the GPIO hardware to figure out which line has fired, but it may still be necessary to acknowledge the interrupt and set up configuration such as edge sensitivity. h]h)}(hXDHIERARCHICAL INTERRUPT CHIPS: this means that each GPIO line has a dedicated irq line to a parent interrupt controller one level up. There is no need to inquire the GPIO hardware to figure out which line has fired, but it may still be necessary to acknowledge the interrupt and set up configuration such as edge sensitivity.h]hXDHIERARCHICAL INTERRUPT CHIPS: this means that each GPIO line has a dedicated irq line to a parent interrupt controller one level up. There is no need to inquire the GPIO hardware to figure out which line has fired, but it may still be necessary to acknowledge the interrupt and set up configuration such as edge sensitivity.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM$hjubah}(h]h ]h"]h$]h&]uh1jhjghhhhhNubeh}(h]h ]h"]h$]h&]jjjkuh1jhhhMhjhhubh)}(hRealtime considerations: a realtime compliant GPIO driver should not use spinlock_t or any sleepable APIs (like PM runtime) as part of its irqchip implementation.h]hRealtime considerations: a realtime compliant GPIO driver should not use spinlock_t or any sleepable APIs (like PM runtime) as part of its irqchip implementation.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM*hjhhubj)}(hhh](j)}(h5spinlock_t should be replaced with raw_spinlock_t.[1]h]h)}(hjh]h5spinlock_t should be replaced with raw_spinlock_t.[1]}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM.hjubah}(h]h ]h"]h$]h&]uh1jhjhhhhhNubj)}(hIf 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 callbacks on an irqchip. Create the callbacks if needed.[2] h]h)}(hIf 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 callbacks on an irqchip. Create the callbacks if needed.[2]h]hIf 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 callbacks on an irqchip. Create the callbacks if needed.[2]}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM/hjubah}(h]h ]h"]h$]h&]uh1jhjhhhhhNubeh}(h]h ]h"]h$]h&]jjjkuh1jhhhM.hjhhubh)}(hhh](h)}(hCascaded GPIO irqchipsh]hCascaded GPIO irqchips}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhM5ubh)}(h?Cascaded GPIO irqchips usually fall in one of three categories:h]h?Cascaded GPIO irqchips usually fall in one of three categories:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM7hjhhubj)}(hhh](j)}(hXCHAINED CASCADED GPIO IRQCHIPS: these are usually the type that is embedded on an SoC. This means that there is a fast IRQ flow handler for the GPIOs that gets called in a chain from the parent IRQ handler, most typically the system interrupt controller. This means that the GPIO irqchip handler will be called immediately from the parent irqchip, while holding the IRQs disabled. The GPIO irqchip will then end up calling something like this sequence 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 on struct gpio_chip, as everything happens directly in the callbacks: no slow bus traffic like I2C can be used. Realtime considerations: Note that chained IRQ handlers will not be forced threaded on -RT. As a result, spinlock_t or any sleepable APIs (like PM runtime) 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 and this way it will become a threaded IRQ handler on -RT and a hard IRQ handler on non-RT (for example, see [3]). The generic_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 is forced to a thread. The "fake?" raw lock can be used to work around this problem:: 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); h](h)}(hXCHAINED CASCADED GPIO IRQCHIPS: these are usually the type that is embedded on an SoC. This means that there is a fast IRQ flow handler for the GPIOs that gets called in a chain from the parent IRQ handler, most typically the system interrupt controller. This means that the GPIO irqchip handler will be called immediately from the parent irqchip, while holding the IRQs disabled. The GPIO irqchip will then end up calling something like this sequence in its interrupt handler::h]hXCHAINED CASCADED GPIO IRQCHIPS: these are usually the type that is embedded on an SoC. This means that there is a fast IRQ flow handler for the GPIOs that gets called in a chain from the parent IRQ handler, most typically the system interrupt controller. This means that the GPIO irqchip handler will be called immediately from the parent irqchip, while holding the IRQs disabled. The GPIO irqchip will then end up calling something like this sequence in its interrupt handler:}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM9hjubh)}(hstatic irqreturn_t foo_gpio_irq(int irq, void *data) chained_irq_enter(...); generic_handle_irq(...); chained_irq_exit(...);h]hstatic irqreturn_t foo_gpio_irq(int irq, void *data) chained_irq_enter(...); generic_handle_irq(...); chained_irq_exit(...);}hjsbah}(h]h ]h"]h$]h&]hhuh1hhhhMAhjubh)}(hChained GPIO irqchips typically can NOT set the .can_sleep flag on struct gpio_chip, as everything happens directly in the callbacks: no slow bus traffic like I2C can be used.h]hChained GPIO irqchips typically can NOT set the .can_sleep flag on struct gpio_chip, as everything happens directly in the callbacks: no slow bus traffic like I2C can be used.}(hj(hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMFhjubh)}(hRealtime considerations: Note that chained IRQ handlers will not be forced threaded on -RT. As a result, spinlock_t or any sleepable APIs (like PM runtime) can't be used in a chained IRQ handler.h]hRealtime considerations: Note that chained IRQ handlers will not be forced threaded on -RT. As a result, spinlock_t or any sleepable APIs (like PM runtime) can’t be used in a chained IRQ handler.}(hj6hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMJhjubh)}(hX 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 and this way it will become a threaded IRQ handler on -RT and a hard IRQ handler on non-RT (for example, see [3]).h]hX 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 and this way it will become a threaded IRQ handler on -RT and a hard IRQ handler on non-RT (for example, see [3]).}(hjDhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMNhjubh)}(hThe generic_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 is forced to a thread. The "fake?" raw lock can be used to work around this problem::h]hThe generic_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 is forced to a thread. The “fake?” raw lock can be used to work around this problem:}(hjRhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMShjubh)}(hX9raw_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);h]hX9raw_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);}hj`sbah}(h]h ]h"]h$]h&]hhuh1hhhhMXhjubeh}(h]h ]h"]h$]h&]uh1jhjhhhhhNubj)}(hXGENERIC CHAINED GPIO IRQCHIPS: these are the same as "CHAINED GPIO irqchips", but chained IRQ handlers are not used. Instead GPIO IRQs dispatching is performed by generic IRQ handler which is configured using request_irq(). The GPIO irqchip will then end up calling something like this sequence in its 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 that generic_handle_irq() is called with IRQ enabled and the same work-around as for "CHAINED GPIO irqchips" can be applied. h](h)}(hXAGENERIC CHAINED GPIO IRQCHIPS: these are the same as "CHAINED GPIO irqchips", but chained IRQ handlers are not used. Instead GPIO IRQs dispatching is performed by generic IRQ handler which is configured using request_irq(). The GPIO irqchip will then end up calling something like this sequence in its interrupt handler::h]hXDGENERIC CHAINED GPIO IRQCHIPS: these are the same as “CHAINED GPIO irqchips”, but chained IRQ handlers are not used. Instead GPIO IRQs dispatching is performed by generic IRQ handler which is configured using request_irq(). The GPIO irqchip will then end up calling something like this sequence in its interrupt handler:}(hjxhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM_hjtubh)}(hstatic irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id) for each detected GPIO IRQ generic_handle_irq(...);h]hstatic irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id) for each detected GPIO IRQ generic_handle_irq(...);}hjsbah}(h]h ]h"]h$]h&]hhuh1hhhhMehjtubh)}(hRealtime considerations: this kind of handlers will be forced threaded on -RT, and as result the IRQ core will complain that generic_handle_irq() is called with IRQ enabled and the same work-around as for "CHAINED GPIO irqchips" can be applied.h]hRealtime considerations: this kind of handlers will be forced threaded on -RT, and as result the IRQ core will complain that generic_handle_irq() is called with IRQ enabled and the same work-around as for “CHAINED GPIO irqchips” can be applied.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMihjtubeh}(h]h ]h"]h$]h&]uh1jhjhhhhhNubj)}(hXNESTED THREADED GPIO IRQCHIPS: these are off-chip GPIO expanders and any other GPIO irqchip residing on the other side of a sleeping bus such as I2C or SPI. Of course such drivers that need slow bus traffic to read out IRQ status and similar, traffic which may in turn incur other IRQs to happen, cannot be handled in a quick IRQ handler with IRQs disabled. Instead they need to spawn a thread and then mask the parent IRQ line until the interrupt is handled by the driver. The hallmark of this driver is to call something like this 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_sleep flag on struct gpio_chip to true, indicating that this chip may sleep when accessing the GPIOs. These kinds of irqchips are inherently realtime tolerant as they are already set up to handle sleeping contexts. h](h)}(hNESTED THREADED GPIO IRQCHIPS: these are off-chip GPIO expanders and any other GPIO irqchip residing on the other side of a sleeping bus such as I2C or SPI.h]hNESTED THREADED GPIO IRQCHIPS: these are off-chip GPIO expanders and any other GPIO irqchip residing on the other side of a sleeping bus such as I2C or SPI.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMnhjubh)}(hXOf course such drivers that need slow bus traffic to read out IRQ status and similar, traffic which may in turn incur other IRQs to happen, cannot be handled in a quick IRQ handler with IRQs disabled. Instead they need to spawn a thread and then mask the parent IRQ line until the interrupt is handled by the driver. The hallmark of this driver is to call something like this in its interrupt handler::h]hXOf course such drivers that need slow bus traffic to read out IRQ status and similar, traffic which may in turn incur other IRQs to happen, cannot be handled in a quick IRQ handler with IRQs disabled. Instead they need to spawn a thread and then mask the parent IRQ line until the interrupt is handled by the driver. The hallmark of this driver is to call something like this in its interrupt handler:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMrhjubh)}(hXstatic irqreturn_t foo_gpio_irq(int irq, void *data) ... handle_nested_irq(irq);h]hXstatic irqreturn_t foo_gpio_irq(int irq, void *data) ... handle_nested_irq(irq);}hjsbah}(h]h ]h"]h$]h&]hhuh1hhhhMyhjubh)}(hThe hallmark of threaded GPIO irqchips is that they set the .can_sleep flag on struct gpio_chip to true, indicating that this chip may sleep when accessing the GPIOs.h]hThe hallmark of threaded GPIO irqchips is that they set the .can_sleep flag on struct gpio_chip to true, indicating that this chip may sleep when accessing the GPIOs.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM}hjubh)}(hpThese kinds of irqchips are inherently realtime tolerant as they are already set up to handle sleeping contexts.h]hpThese kinds of irqchips are inherently realtime tolerant as they are already set up to handle sleeping contexts.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubeh}(h]h ]h"]h$]h&]uh1jhjhhhhhNubeh}(h]h ]h"]h$]h&]jjjkuh1jhhhM9hjhhubeh}(h]cascaded-gpio-irqchipsah ]h"]cascaded gpio irqchipsah$]h&]uh1hhjhhhhhM5ubh)}(hhh](h)}(h(Infrastructure helpers for GPIO irqchipsh]h(Infrastructure helpers for GPIO irqchips}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhMubh)}(hXTo help out in handling the set-up and management of GPIO irqchips and the associated irqdomain and resource allocation callbacks. These are activated by selecting the Kconfig symbol GPIOLIB_IRQCHIP. If the symbol IRQ_DOMAIN_HIERARCHY is also selected, hierarchical helpers will also be provided. A big portion of overhead code will be managed by gpiolib, under the assumption that your interrupts are 1-to-1-mapped to the GPIO line index:h]hXTo help out in handling the set-up and management of GPIO irqchips and the associated irqdomain and resource allocation callbacks. These are activated by selecting the Kconfig symbol GPIOLIB_IRQCHIP. If the symbol IRQ_DOMAIN_HIERARCHY is also selected, hierarchical helpers will also be provided. A big portion of overhead code will be managed by gpiolib, under the assumption that your interrupts are 1-to-1-mapped to the GPIO line index:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubhtable)}(hhh]htgroup)}(hhh](hcolspec)}(hhh]h}(h]h ]h"]h$]h&]colwidthK2uh1j/hj,ubj0)}(hhh]h}(h]h ]h"]h$]h&]colwidthK2uh1j/hj,ubhthead)}(hhh]hrow)}(hhh](hentry)}(hhh]h)}(hGPIO line offseth]hGPIO line offset}(hjThhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjQubah}(h]h ]h"]h$]h&]uh1jOhjLubjP)}(hhh]h)}(h Hardware IRQh]h Hardware IRQ}(hjkhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhubah}(h]h ]h"]h$]h&]uh1jOhjLubeh}(h]h ]h"]h$]h&]uh1jJhjGubah}(h]h ]h"]h$]h&]uh1jEhj,ubhtbody)}(hhh](jK)}(hhh](jP)}(hhh]h)}(h0h]h0}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jOhjubjP)}(hhh]h)}(hjh]h0}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jOhjubeh}(h]h ]h"]h$]h&]uh1jJhjubjK)}(hhh](jP)}(hhh]h)}(h1h]h1}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jOhjubjP)}(hhh]h)}(hjh]h1}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jOhjubeh}(h]h ]h"]h$]h&]uh1jJhjubjK)}(hhh](jP)}(hhh]h)}(h2h]h2}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jOhjubjP)}(hhh]h)}(hjh]h2}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jOhjubeh}(h]h ]h"]h$]h&]uh1jJhjubjK)}(hhh](jP)}(hhh]h)}(h...h]h...}(hj8hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj5ubah}(h]h ]h"]h$]h&]uh1jOhj2ubjP)}(hhh]h)}(h...h]h...}(hjOhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjLubah}(h]h ]h"]h$]h&]uh1jOhj2ubeh}(h]h ]h"]h$]h&]uh1jJhjubjK)}(hhh](jP)}(hhh]h)}(hngpio-1h]hngpio-1}(hjohhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjlubah}(h]h ]h"]h$]h&]uh1jOhjiubjP)}(hhh]h)}(hngpio-1h]hngpio-1}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jOhjiubeh}(h]h ]h"]h$]h&]uh1jJhjubeh}(h]h ]h"]h$]h&]uh1jhj,ubeh}(h]h ]h"]h$]h&]colsKuh1j*hj'ubah}(h]h ]h"]h$]h&]uh1j%hjhhhhhNubh)}(hIf some GPIO lines do not have corresponding IRQs, the bitmask valid_mask and the flag need_valid_mask in gpio_irq_chip can be used to mask off some lines as invalid for associating with IRQs.h]hIf some GPIO lines do not have corresponding IRQs, the bitmask valid_mask and the flag need_valid_mask in gpio_irq_chip can be used to mask off some lines as invalid for associating with IRQs.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(hXThe preferred way to set up the helpers is to fill in the struct gpio_irq_chip inside struct gpio_chip before adding the gpio_chip. If you do this, the additional irq_chip will be set up by gpiolib at the same time as setting up the rest of the GPIO functionality. The following is a typical example of a chained cascaded interrupt handler using the gpio_irq_chip. Note how the mask/unmask (or disable/enable) functions call into the core gpiolib code:h]hXThe preferred way to set up the helpers is to fill in the struct gpio_irq_chip inside struct gpio_chip before adding the gpio_chip. If you do this, the additional irq_chip will be set up by gpiolib at the same time as setting up the rest of the GPIO functionality. The following is a typical example of a chained cascaded interrupt handler using the gpio_irq_chip. Note how the mask/unmask (or disable/enable) functions call into the core gpiolib code:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(hX/* Typical state container */ struct my_gpio { struct gpio_chip gc; }; static void my_gpio_mask_irq(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); irq_hw_number_t hwirq = 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); } static void my_gpio_unmask_irq(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); irq_hw_number_t hwirq = 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. */ static const struct irq_chip my_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, }; int irq; /* from platform etc */ struct my_gpio *g; struct gpio_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; return devm_gpiochip_add_data(dev, &g->gc, g);h]hX/* Typical state container */ struct my_gpio { struct gpio_chip gc; }; static void my_gpio_mask_irq(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); irq_hw_number_t hwirq = 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); } static void my_gpio_unmask_irq(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); irq_hw_number_t hwirq = 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. */ static const struct irq_chip my_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, }; int irq; /* from platform etc */ struct my_gpio *g; struct gpio_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; return devm_gpiochip_add_data(dev, &g->gc, g);}hjsbah}(h]h ]h"]h$]h&]hhforcelanguagechighlight_args}uh1hhhhMhjhhubh)}(huThe helper supports using threaded interrupts as well. Then you just request the interrupt separately and go with it:h]huThe helper supports using threaded interrupts as well. Then you just request the interrupt separately and go with it:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(hX/* Typical state container */ struct my_gpio { struct gpio_chip gc; }; static void my_gpio_mask_irq(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); irq_hw_number_t hwirq = 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); } static void my_gpio_unmask_irq(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); irq_hw_number_t hwirq = 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. */ static const struct irq_chip my_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, }; int irq; /* from platform etc */ struct my_gpio *g; struct gpio_irq_chip *girq; ret = devm_request_threaded_irq(dev, irq, NULL, irq_thread_fn, IRQF_ONESHOT, "my-chip", g); if (ret < 0) return ret; /* 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; return devm_gpiochip_add_data(dev, &g->gc, g);ph]hX/* Typical state container */ struct my_gpio { struct gpio_chip gc; }; static void my_gpio_mask_irq(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); irq_hw_number_t hwirq = 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); } static void my_gpio_unmask_irq(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); irq_hw_number_t hwirq = 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. */ static const struct irq_chip my_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, }; int irq; /* from platform etc */ struct my_gpio *g; struct gpio_irq_chip *girq; ret = devm_request_threaded_irq(dev, irq, NULL, irq_thread_fn, IRQF_ONESHOT, "my-chip", g); if (ret < 0) return ret; /* 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; return devm_gpiochip_add_data(dev, &g->gc, g);}hjsbah}(h]h ]h"]h$]h&]hhjjjj}uh1hhhhMhjhhubh)}(hzThe helper supports using hierarchical interrupt controllers as well. In this case the typical set-up will look like this:h]hzThe helper supports using hierarchical interrupt controllers as well. In this case the typical set-up will look like this:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM9hjhhubh)}(hXb/* Typical state container with dynamic irqchip */ struct my_gpio { struct gpio_chip gc; struct fwnode_handle *fwnode; }; static void my_gpio_mask_irq(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); irq_hw_number_t hwirq = 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); } static void my_gpio_unmask_irq(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); irq_hw_number_t hwirq = 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. */ static const struct irq_chip my_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, }; struct my_gpio *g; struct gpio_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; return devm_gpiochip_add_data(dev, &g->gc, g);h]hXb/* Typical state container with dynamic irqchip */ struct my_gpio { struct gpio_chip gc; struct fwnode_handle *fwnode; }; static void my_gpio_mask_irq(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); irq_hw_number_t hwirq = 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); } static void my_gpio_unmask_irq(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); irq_hw_number_t hwirq = 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. */ static const struct irq_chip my_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, }; struct my_gpio *g; struct gpio_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; return devm_gpiochip_add_data(dev, &g->gc, g);}hj sbah}(h]h ]h"]h$]h&]hhjjjj}uh1hhhhM<hjhhubh)}(hXAs you can see pretty similar, but you do not supply a parent handler for the IRQ, instead a parent irqdomain, an fwnode for the hardware and a function .child_to_parent_hwirq() that has the purpose of looking up the 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 advice on how to find the required pieces.h]hXAs you can see pretty similar, but you do not supply a parent handler for the IRQ, instead a parent irqdomain, an fwnode for the hardware and a function .child_to_parent_hwirq() that has the purpose of looking up the 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 advice on how to find the required pieces.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(hXIf there is a need to exclude certain GPIO lines from the IRQ domain handled by these helpers, we can set .irq.need_valid_mask of the gpiochip before devm_gpiochip_add_data() or gpiochip_add_data() is called. This allocates an .irq.valid_mask with as many bits set as there are GPIO lines in the chip, each bit representing line 0..n-1. Drivers can exclude GPIO lines by clearing bits from this mask. The mask can be filled in the init_valid_mask() callback that is part of the struct gpio_irq_chip.h]hXIf there is a need to exclude certain GPIO lines from the IRQ domain handled by these helpers, we can set .irq.need_valid_mask of the gpiochip before devm_gpiochip_add_data() or gpiochip_add_data() is called. This allocates an .irq.valid_mask with as many bits set as there are GPIO lines in the chip, each bit representing line 0..n-1. Drivers can exclude GPIO lines by clearing bits from this mask. The mask can be filled in the init_valid_mask() callback that is part of the struct gpio_irq_chip.}(hj* hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(h5To use the helpers please keep the following in mind:h]h5To use the helpers please keep the following in mind:}(hj8 hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubj)}(hhh](j)}(hMake sure to assign all relevant members of the struct gpio_chip so that the irqchip can initialize. E.g. .dev and .can_sleep shall be set up properly. h]h)}(hMake sure to assign all relevant members of the struct gpio_chip so that the irqchip can initialize. E.g. .dev and .can_sleep shall be set up properly.h]hMake sure to assign all relevant members of the struct gpio_chip so that the irqchip can initialize. E.g. .dev and .can_sleep shall be set up properly.}(hjM hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjI ubah}(h]h ]h"]h$]h&]uh1jhjF hhhhhNubj)}(hXNominally set gpio_irq_chip.handler to handle_bad_irq. Then, if your irqchip is cascaded, set the handler to handle_level_irq() and/or handle_edge_irq() in the irqchip .set_type() callback depending on what your controller supports and what is requested by the consumer. h]h)}(hXNominally set gpio_irq_chip.handler to handle_bad_irq. Then, if your irqchip is cascaded, set the handler to handle_level_irq() and/or handle_edge_irq() in the irqchip .set_type() callback depending on what your controller supports and what is requested by the consumer.h]hXNominally set gpio_irq_chip.handler to handle_bad_irq. Then, if your irqchip is cascaded, set the handler to handle_level_irq() and/or handle_edge_irq() in the irqchip .set_type() callback depending on what your controller supports and what is requested by the consumer.}(hje hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhja ubah}(h]h ]h"]h$]h&]uh1jhjF hhhhhNubeh}(h]h ]h"]h$]h&]jjjkuh1jhhhMhjhhubeh}(h](infrastructure-helpers-for-gpio-irqchipsah ]h"](infrastructure helpers for gpio irqchipsah$]h&]uh1hhjhhhhhMubh)}(hhh](h)}(hLocking IRQ usageh]hLocking IRQ usage}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj hhhhhMubh)}(hSince GPIO and irq_chip are orthogonal, we can get conflicts between different use 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.h]hSince GPIO and irq_chip are orthogonal, we can get conflicts between different use 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.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj hhubh)}(hIf there is competition inside the subsystem which side is using the resource (a certain GPIO line and register for example) it needs to deny certain operations and keep track of usage inside of the gpiolib subsystem.h]hIf there is competition inside the subsystem which side is using the resource (a certain GPIO line and register for example) it needs to deny certain operations and keep track of usage inside of the gpiolib subsystem.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj hhubh)}(h{Input GPIOs can be used as IRQ signals. When this happens, a driver is requested to mark the GPIO as being used as an IRQ::h]hzInput GPIOs can be used as IRQ signals. When this happens, a driver is requested to mark the GPIO as being used as an IRQ:}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj hhubh)}(hEint gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset)h]hEint gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset)}hj sbah}(h]h ]h"]h$]h&]hhuh1hhhhMhj hhubh)}(h\This will prevent the use of non-irq related GPIO APIs until the GPIO IRQ lock is released::h]h[This will prevent the use of non-irq related GPIO APIs until the GPIO IRQ lock is released:}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj hhubh)}(hHvoid gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)h]hHvoid gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)}hj sbah}(h]h ]h"]h$]h&]hhuh1hhhhMhj hhubh)}(hWhen implementing an irqchip inside a GPIO driver, these two functions should typically be called in the .startup() and .shutdown() callbacks from the irqchip.h]hWhen implementing an irqchip inside a GPIO driver, these two functions should typically be called in the .startup() and .shutdown() callbacks from the irqchip.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj hhubh)}(hSWhen using the gpiolib irqchip helpers, these callbacks are automatically assigned.h]hSWhen using the gpiolib irqchip helpers, these callbacks are automatically assigned.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj hhubeh}(h]locking-irq-usageah ]h"]locking irq usageah$]h&]uh1hhjhhhhhMubh)}(hhh](h)}(hDisabling and enabling IRQsh]hDisabling and enabling IRQs}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj hhhhhMubh)}(hIn 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 being an input with interrupts again. This happens on things like CEC (Consumer Electronics Control).h]hIn 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 being an input with interrupts again. This happens on things like CEC (Consumer Electronics Control).}(hj! hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj hhubh)}(hWhen a GPIO is used as an IRQ signal, then gpiolib also needs to know if the IRQ is enabled or disabled. In order to inform gpiolib about this, the irqchip driver should call::h]hWhen a GPIO is used as an IRQ signal, then gpiolib also needs to know if the IRQ is enabled or disabled. In order to inform gpiolib about this, the irqchip driver should call:}(hj/ hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj hhubh)}(hFvoid gpiochip_disable_irq(struct gpio_chip *chip, unsigned int offset)h]hFvoid gpiochip_disable_irq(struct gpio_chip *chip, unsigned int offset)}hj= sbah}(h]h ]h"]h$]h&]hhuh1hhhhMhj hhubh)}(hThis allows drivers to drive the GPIO as an output while the IRQ is disabled. When the IRQ is enabled again, a driver should call::h]hThis allows drivers to drive the GPIO as an output while the IRQ is disabled. When the IRQ is enabled again, a driver should call:}(hjK hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj hhubh)}(hEvoid gpiochip_enable_irq(struct gpio_chip *chip, unsigned int offset)h]hEvoid gpiochip_enable_irq(struct gpio_chip *chip, unsigned int offset)}hjY sbah}(h]h ]h"]h$]h&]hhuh1hhhhMhj hhubh)}(hWhen implementing an irqchip inside a GPIO driver, these two functions should typically be called in the .irq_disable() and .irq_enable() callbacks from the irqchip.h]hWhen implementing an irqchip inside a GPIO driver, these two functions should typically be called in the .irq_disable() and .irq_enable() callbacks from the irqchip.}(hjg hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj hhubh)}(hWhen IRQCHIP_IMMUTABLE is not advertised by the irqchip, these callbacks are automatically assigned. This behaviour is deprecated and on its way to be removed from the kernel.h]hWhen IRQCHIP_IMMUTABLE is not advertised by the irqchip, these callbacks are automatically assigned. This behaviour is deprecated and on its way to be removed from the kernel.}(hju hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj hhubeh}(h]disabling-and-enabling-irqsah ]h"]disabling and enabling irqsah$]h&]uh1hhjhhhhhMubh)}(hhh](h)}(h'Real-Time compliance for GPIO IRQ chipsh]h'Real-Time compliance for GPIO IRQ chips}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj hhhhhMubh)}(hAny provider of irqchips needs to be carefully tailored to support Real-Time preemption. It is desirable that all irqchips in the GPIO subsystem keep this in mind and do the proper testing to assure they are real time-enabled.h]hAny provider of irqchips needs to be carefully tailored to support Real-Time preemption. It is desirable that all irqchips in the GPIO subsystem keep this in mind and do the proper testing to assure they are real time-enabled.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj hhubh)}(hHSo, pay attention on above realtime considerations in the documentation.h]hHSo, pay attention on above realtime considerations in the documentation.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj hhubh)}(hXThe following is a checklist to follow when preparing a driver for real-time compliance:h]hXThe following is a checklist to follow when preparing a driver for real-time compliance:}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj hhubj)}(hhh](j)}(h=ensure spinlock_t is not used as part irq_chip implementationh]h)}(hj h]h=ensure spinlock_t is not used as part irq_chip implementation}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj ubah}(h]h ]h"]h$]h&]uh1jhj hhhhhNubj)}(hensure that sleepable APIs are not used as part irq_chip implementation If sleepable APIs have to be used, these can be done from the .irq_bus_lock() and .irq_bus_unlock() callbacksh]h)}(hensure that sleepable APIs are not used as part irq_chip implementation If sleepable APIs have to be used, these can be done from the .irq_bus_lock() and .irq_bus_unlock() callbacksh]hensure that sleepable APIs are not used as part irq_chip implementation If sleepable APIs have to be used, these can be done from the .irq_bus_lock() and .irq_bus_unlock() callbacks}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj ubah}(h]h ]h"]h$]h&]uh1jhj hhhhhNubj)}(hhChained GPIO irqchips: ensure spinlock_t or any sleepable APIs are not used from the chained IRQ handlerh]h)}(hhChained GPIO irqchips: ensure spinlock_t or any sleepable APIs are not used from the chained IRQ handlerh]hhChained GPIO irqchips: ensure spinlock_t or any sleepable APIs are not used from the chained IRQ handler}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj ubah}(h]h ]h"]h$]h&]uh1jhj hhhhhNubj)}(hmGeneric chained GPIO irqchips: take care about generic_handle_irq() calls and apply corresponding work-aroundh]h)}(hmGeneric chained GPIO irqchips: take care about generic_handle_irq() calls and apply corresponding work-aroundh]hmGeneric chained GPIO irqchips: take care about generic_handle_irq() calls and apply corresponding work-around}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj ubah}(h]h ]h"]h$]h&]uh1jhj hhhhhNubj)}(haChained GPIO irqchips: get rid of the chained IRQ handler and use generic irq handler if possibleh]h)}(haChained GPIO irqchips: get rid of the chained IRQ handler and use generic irq handler if possibleh]haChained GPIO irqchips: get rid of the chained IRQ handler and use generic irq handler if possible}(hj, hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj( ubah}(h]h ]h"]h$]h&]uh1jhj hhhhhNubj)}(hregmap_mmio: it is possible to disable internal locking in regmap by setting .disable_locking and handling the locking in the GPIO driverh]h)}(hregmap_mmio: it is possible to disable internal locking in regmap by setting .disable_locking and handling the locking in the GPIO driverh]hregmap_mmio: it is possible to disable internal locking in regmap by setting .disable_locking and handling the locking in the GPIO driver}(hjD hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj@ ubah}(h]h ]h"]h$]h&]uh1jhj hhhhhNubj)}(hbTest your driver with the appropriate in-kernel real-time test cases for both level and edge IRQs h]h)}(haTest your driver with the appropriate in-kernel real-time test cases for both level and edge IRQsh]haTest your driver with the appropriate in-kernel real-time test cases for both level and edge IRQs}(hj\ hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjX ubah}(h]h ]h"]h$]h&]uh1jhj hhhhhNubeh}(h]h ]h"]h$]h&]jjjkuh1jhhhMhj hhubj)}(hhh](j)}(h:[1] http://www.spinics.net/lists/linux-omap/msg120425.htmlh]h)}(hj{ h](h[1] }(hj} hhhNhNubh reference)}(h6http://www.spinics.net/lists/linux-omap/msg120425.htmlh]h6http://www.spinics.net/lists/linux-omap/msg120425.html}(hj hhhNhNubah}(h]h ]h"]h$]h&]refurij uh1j hj} ubeh}(h]h ]h"]h$]h&]uh1hhhhMhjy ubah}(h]h ]h"]h$]h&]uh1jhjv hhhhhNubj)}(hX[2] https://lore.kernel.org/r/1443209283-20781-2-git-send-email-grygorii.strashko@ti.comh]h)}(hj h](h[2] }(hj hhhNhNubj )}(hThttps://lore.kernel.org/r/1443209283-20781-2-git-send-email-grygorii.strashko@ti.comh]hThttps://lore.kernel.org/r/1443209283-20781-2-git-send-email-grygorii.strashko@ti.com}(hj hhhNhNubah}(h]h ]h"]h$]h&]refurij uh1j hj ubeh}(h]h ]h"]h$]h&]uh1hhhhMhj ubah}(h]h ]h"]h$]h&]uh1jhjv hhhhhNubj)}(hZ[3] https://lore.kernel.org/r/1443209283-20781-3-git-send-email-grygorii.strashko@ti.com h]h)}(hX[3] https://lore.kernel.org/r/1443209283-20781-3-git-send-email-grygorii.strashko@ti.comh](h[3] }(hj hhhNhNubj )}(hThttps://lore.kernel.org/r/1443209283-20781-3-git-send-email-grygorii.strashko@ti.comh]hThttps://lore.kernel.org/r/1443209283-20781-3-git-send-email-grygorii.strashko@ti.com}(hj hhhNhNubah}(h]h ]h"]h$]h&]refurij uh1j hj ubeh}(h]h ]h"]h$]h&]uh1hhhhMhj ubah}(h]h ]h"]h$]h&]uh1jhjv hhhhhNubeh}(h]h ]h"]h$]h&]jj*uh1jhhhMhj hhubeh}(h]'real-time-compliance-for-gpio-irq-chipsah ]h"]'real-time compliance for gpio irq chipsah$]h&]uh1hhjhhhhhMubeh}(h]gpio-drivers-providing-irqsah ]h"]gpio drivers providing irqsah$]h&]uh1hhhhhhhhKubh)}(hhh](h)}(hRequesting self-owned GPIO pinsh]hRequesting self-owned GPIO pins}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj hhhhhMubh)}(hSometimes it is useful to allow a GPIO chip driver to request its own GPIO descriptors through the gpiolib API. A GPIO driver can use the following functions to request and free descriptors::h]hSometimes it is useful to allow a GPIO chip driver to request its own GPIO descriptors through the gpiolib API. A GPIO driver can use the following functions to request and free descriptors:}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj hhubh)}(hX2struct 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)h]hX2struct 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)}hj$ sbah}(h]h ]h"]h$]h&]hhuh1hhhhMhj hhubh)}(hfDescriptors requested with gpiochip_request_own_desc() must be released with gpiochip_free_own_desc().h]hfDescriptors requested with gpiochip_request_own_desc() must be released with gpiochip_free_own_desc().}(hj2 hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj hhubh)}(hThese functions must be used with care since they do not affect module use count. Do not use the functions to request gpio descriptors not owned by the calling driver.h]hThese functions must be used with care since they do not affect module use count. Do not use the functions to request gpio descriptors not owned by the calling driver.}(hj@ hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj hhubeh}(h]requesting-self-owned-gpio-pinsah ]h"]requesting self-owned gpio pinsah$]h&]uh1hhhhhhhhMubeh}(h]gpio-driver-interfaceah ]h"]gpio driver interfaceah$]h&]uh1hhhhhhhhKubeh}(h]h ]h"]h$]h&]sourcehuh1hcurrent_sourceN current_lineNsettingsdocutils.frontendValues)}(hN generatorN datestampN source_linkN source_urlN toc_backlinksjOfootnote_backlinksK sectnum_xformKstrip_commentsNstrip_elements_with_classesN strip_classesN report_levelK halt_levelKexit_status_levelKdebugNwarning_streamN tracebackinput_encoding utf-8-siginput_encoding_error_handlerstrictoutput_encodingutf-8output_encoding_error_handlerj error_encodingutf-8error_encoding_error_handlerbackslashreplace language_codeenrecord_dependenciesNconfigN id_prefixhauto_id_prefixid dump_settingsNdump_internalsNdump_transformsNdump_pseudo_xmlNexpose_internalsNstrict_visitorN_disable_configN_sourceh _destinationN _config_files]7/var/lib/git/docbuild/linux/Documentation/docutils.confafile_insertion_enabled raw_enabledKline_length_limitM'pep_referencesN pep_base_urlhttps://peps.python.org/pep_file_url_templatepep-%04drfc_referencesN rfc_base_url&https://datatracker.ietf.org/doc/html/ tab_widthKtrim_footnote_reference_spacesyntax_highlightlong smart_quotessmartquotes_locales]character_level_inline_markupdoctitle_xform docinfo_xformKsectsubtitle_xform image_loadinglinkembed_stylesheetcloak_email_addressessection_self_linkenvNubreporterNindirect_targets]substitution_defs}substitution_names}refnames}refids}nameids}(j[ jX jejbjjjGjDj|jyjjjjj j jjj j j j j j j j jS jP u nametypes}(j[ jejjGj|jjj jj j j j jS uh}(jX hjbhjjhjDjjyjJjjjjj jjjj jj j j j j j jP j u footnote_refs} citation_refs} autofootnotes]autofootnote_refs]symbol_footnotes]symbol_footnote_refs] footnotes] citations]autofootnote_startKsymbol_footnote_startK id_counter collectionsCounter}Rparse_messages](hsystem_message)}(hhh]h)}(heUnexpected possible title overline or transition. Treating it as ordinary text because it's so short.h]hgUnexpected possible title overline or transition. Treating it as ordinary text because it’s so short.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj ubah}(h]h ]h"]h$]h&]levelKtypeINFOlineMsourcehuh1j hj5ubj )}(hhh]h)}(heUnexpected possible title overline or transition. Treating it as ordinary text because it's so short.h]hgUnexpected possible title overline or transition. Treating it as ordinary text because it’s so short.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj ubah}(h]h ]h"]h$]h&]levelKtypej lineMsourcehuh1j hjLubetransform_messages] transformerN include_log] decorationNhhub.