€•®Œsphinx.addnodes”Œdocument”“”)�”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)�”}”(hhh]”(hŒ pending_xref”“”)�”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…”�”}”Œparent”hsbaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ*/translations/zh_CN/driver-api/gpio/driver”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)�”}”(hhh]”hŒChinese (Traditional)”…”�”}”hh2sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ*/translations/zh_TW/driver-api/gpio/driver”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒItalian”…”�”}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ*/translations/it_IT/driver-api/gpio/driver”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒJapanese”…”�”}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ*/translations/ja_JP/driver-api/gpio/driver”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒKorean”…”�”}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ*/translations/ko_KR/driver-api/gpio/driver”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒPortuguese (Brazilian)”…”�”}”hh‚sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ*/translations/pt_BR/driver-api/gpio/driver”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒSpanish”…”�”}”hh–sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ*/translations/sp_SP/driver-api/gpio/driver”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒsection”“”)�”}”(hhh]”(hŒtitle”“”)�”}”(hŒGPIO Driver Interface”h]”hŒGPIO Driver Interface”…”�”}”(hh¼h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhh·h²hh³ŒD/var/lib/git/docbuild/linux/Documentation/driver-api/gpio/driver.rst”h´KubhŒ paragraph”“”)�”}”(hŒAThis document serves as a guide for writers of GPIO chip drivers.”h]”hŒAThis document serves as a guide for writers of GPIO chip drivers.”…”�”}”(hhÍh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khh·h²hubhÌ)�”}”(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:”…”�”}”(hhÛh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khh·h²hubhŒ literal_block”“”)�”}”(hŒ#include ”h]”hŒ#include ”…”�”}”hhësbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1héh³hÊh´K hh·h²hubh¶)�”}”(hhh]”(h»)�”}”(hŒ Internal Representation of GPIOs”h]”hŒ Internal Representation of GPIOs”…”�”}”(hhþh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhhûh²hh³hÊh´KubhÌ)�”}”(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.”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khhûh²hubhÌ)�”}”(hŒÚInside 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]”(hŒrInside a GPIO driver, individual GPIO lines are identified by their hardware number, sometime also referred to as ”…”�”}”(hjh²hh³Nh´NubhŒliteral”“”)�”}”(hŒ ``offset``”h]”hŒoffset”…”�”}”(hj$h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j"hjubhŒ^, which is a unique number between 0 and n-1, n being the number of GPIOs managed by the chip.”…”�”}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khhûh²hubhÌ)�”}”(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<h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khhûh²hubhÌ)�”}”(hŒzThis number is purely internal: the hardware number of a particular GPIO line is never made visible outside of the driver.”h]”hŒzThis number is purely internal: the hardware number of a particular GPIO line is never made visible outside of the driver.”…”�”}”(hjJh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K"hhûh²hubhÌ)�”}”(hX¸On 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]”hX¼On 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.”…”�”}”(hjXh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K%hhûh²hubhÌ)�”}”(hXÌSo 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]”hXÐSo 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.”…”�”}”(hjfh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K,hhûh²hubeh}”(h]”Œ internal-representation-of-gpios”ah ]”h"]”Œ internal representation of gpios”ah$]”h&]”uh1hµhh·h²hh³hÊh´Kubh¶)�”}”(hhh]”(h»)�”}”(hŒController Drivers: gpio_chip”h]”hŒController Drivers: gpio_chip”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhj|h²hh³hÊh´K5ubhÌ)�”}”(hŒëIn 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]”hŒïIn 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:”…”�”}”(hj�h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K7hj|h²hubhŒ 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 direction”h]”hÌ)�”}”(hjªh]”hŒ(methods to establish GPIO line direction”…”�”}”(hj¬h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KhjÖubah}”(h]”h ]”h"]”h$]”h&]”uh1j¦hj£ubj§)�”}”(hŒ?method to return the IRQ number associated to a given GPIO line”h]”hÌ)�”}”(hjïh]”hŒ?method to return the IRQ number associated to a given GPIO line”…”�”}”(hjñh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K?hjíubah}”(h]”h ]”h"]”h$]”h&]”uh1j¦hj£ubj§)�”}”(hŒ2flag saying whether calls to its methods may sleep”h]”hÌ)�”}”(hjh]”hŒ2flag saying whether calls to its methods may sleep”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K@hjubah}”(h]”h ]”h"]”h$]”h&]”uh1j¦hj£ubj§)�”}”(hŒ+optional line names array to identify lines”h]”hÌ)�”}”(hjh]”hŒ+optional line names array to identify lines”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KAhjubah}”(h]”h ]”h"]”h$]”h&]”uh1j¦hj£ubj§)�”}”(hŒ>optional debugfs dump method (showing extra state information)”h]”hÌ)�”}”(hj4h]”hŒ>optional debugfs dump method (showing extra state information)”…”�”}”(hj6h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KBhj2ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¦hj£ubj§)�”}”(hŒ@optional base number (will be automatically assigned if omitted)”h]”hÌ)�”}”(hjKh]”hŒ@optional base number (will be automatically assigned if omitted)”…”�”}”(hjMh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KChjIubah}”(h]”h ]”h"]”h$]”h&]”uh1j¦hj£ubj§)�”}”(hŒIoptional label for diagnostics and GPIO chip mapping using platform data ”h]”hÌ)�”}”(hŒHoptional label for diagnostics and GPIO chip mapping using platform data”h]”hŒHoptional label for diagnostics and GPIO chip mapping using platform data”…”�”}”(hjdh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KDhj`ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¦hj£ubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ-”uh1j¡h³hÊh´K. So this combined driver is utilizing two sub- systems simultaneously: gpio and irq.”h]”hŒ¹The 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Üh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mhj½h²hubhÌ)�”}”(hŒåIt 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]”hŒåIt 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êh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M#hj½h²hubhÌ)�”}”(hŒ¥gpiod_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]”hŒ¥gpiod_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øh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M(hj½h²hubhÌ)�”}”(hŒ©Always 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]”hŒ©Always 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.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M,hj½h²hubhÌ)�”}”(hŒ4We can divide GPIO irqchips in two broad categories:”h]”hŒ4We can divide GPIO irqchips in two broad categories:”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M0hj½h²hubj¢)�”}”(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).”…”�”}”(hj)h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M2hj%ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¦hj"h²hh³hÊh´Nubj§)�”}”(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.”…”�”}”(hjAh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M?hj=ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¦hj"h²hh³hÊh´Nubeh}”(h]”h ]”h"]”h$]”h&]”j~juh1j¡h³hÊh´M2hj½h²hubhÌ)�”}”(hŒ¢Realtime 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]”hŒ¢Realtime considerations: a realtime compliant GPIO driver should not use spinlock_t or any sleepable APIs (like PM runtime) as part of its irqchip implementation.”…”�”}”(hj[h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MEhj½h²hubj¢)�”}”(hhh]”(j§)�”}”(hŒ5spinlock_t should be replaced with raw_spinlock_t.[1]”h]”hÌ)�”}”(hjnh]”hŒ5spinlock_t should be replaced with raw_spinlock_t.[1]”…”�”}”(hjph²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MIhjlubah}”(h]”h ]”h"]”h$]”h&]”uh1j¦hjih²hh³hÊh´Nubj§)�”}”(hŒË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 callbacks on an irqchip. Create the callbacks if needed.[2] ”h]”hÌ)�”}”(hŒÉ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 callbacks on an irqchip. Create the callbacks if needed.[2]”h]”hŒÉ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 callbacks on an irqchip. Create the callbacks if needed.[2]”…”�”}”(hj‡h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MJhjƒubah}”(h]”h ]”h"]”h$]”h&]”uh1j¦hjih²hh³hÊh´Nubeh}”(h]”h ]”h"]”h$]”h&]”j~juh1j¡h³hÊh´MIhj½h²hubh¶)�”}”(hhh]”(h»)�”}”(hŒCascaded GPIO irqchips”h]”hŒCascaded GPIO irqchips”…”�”}”(hj¤h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhj¡h²hh³hÊh´MPubhÌ)�”}”(hŒ?Cascaded GPIO irqchips usually fall in one of three categories:”h]”hŒ?Cascaded GPIO irqchips usually fall in one of three categories:”…”�”}”(hj²h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MRhj¡h²hubj¢)�”}”(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Ì)�”}”(hXÞCHAINED 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]”hXÝCHAINED 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Çh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MThjÃubhê)�”}”(hŒˆstatic irqreturn_t foo_gpio_irq(int irq, void *data) chained_irq_enter(...); generic_handle_irq(...); chained_irq_exit(...);”h]”hŒˆstatic irqreturn_t foo_gpio_irq(int irq, void *data) chained_irq_enter(...); generic_handle_irq(...); chained_irq_exit(...);”…”�”}”hjÕsbah}”(h]”h ]”h"]”h$]”h&]”hùhúuh1héh³hÊh´M\hjÃubhÌ)�”}”(hŒ¯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.”h]”hŒ¯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.”…”�”}”(hjãh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MahjÃubhÌ)�”}”(hŒÃ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.”h]”hŒÅ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.”…”�”}”(hjñh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MehjÃubhÌ)�”}”(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]).”…”�”}”(hjÿh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MihjÃubhÌ)�”}”(hŒâ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::”h]”hŒå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:”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MnhjÃubhê)�”}”(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);”…”�”}”hjsbah}”(h]”h ]”h"]”h$]”h&]”hùhúuh1héh³hÊh´MshjÃubeh}”(h]”h ]”h"]”h$]”h&]”uh1j¦hjÀh²hh³hÊh´Nubj§)�”}”(hX¿GENERIC 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:”…”�”}”(hj3h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mzhj/ubhê)�”}”(hŒstatic irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id) for each detected GPIO IRQ generic_handle_irq(...);”h]”hŒstatic irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id) for each detected GPIO IRQ generic_handle_irq(...);”…”�”}”hjAsbah}”(h]”h ]”h"]”h$]”h&]”hùhúuh1héh³hÊh´M€hj/ubhÌ)�”}”(hŒô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Œø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.”…”�”}”(hjOh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M„hj/ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j¦hjÀh²hh³hÊh´Nubj§)�”}”(hX¬NESTED 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Ì)�”}”(hŒœNESTED 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]”hŒœNESTED 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.”…”�”}”(hjgh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M‰hjcubhÌ)�”}”(hX’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::”h]”hX‘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:”…”�”}”(hjuh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M�hjcubhê)�”}”(hŒXstatic irqreturn_t foo_gpio_irq(int irq, void *data) ... handle_nested_irq(irq);”h]”hŒXstatic irqreturn_t foo_gpio_irq(int irq, void *data) ... handle_nested_irq(irq);”…”�”}”hjƒsbah}”(h]”h ]”h"]”h$]”h&]”hùhúuh1héh³hÊh´M”hjcubhÌ)�”}”(hŒ¦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.”h]”hŒ¦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.”…”�”}”(hj‘h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M˜hjcubhÌ)�”}”(hŒpThese kinds of irqchips are inherently realtime tolerant as they are already set up to handle sleeping contexts.”h]”hŒpThese kinds of irqchips are inherently realtime tolerant as they are already set up to handle sleeping contexts.”…”�”}”(hjŸh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mœhjcubeh}”(h]”h ]”h"]”h$]”h&]”uh1j¦hjÀh²hh³hÊh´Nubeh}”(h]”h ]”h"]”h$]”h&]”j~juh1j¡h³hÊh´MThj¡h²hubeh}”(h]”Œcascaded-gpio-irqchips”ah ]”h"]”Œcascaded gpio irqchips”ah$]”h&]”uh1hµhj½h²hh³hÊh´MPubh¶)�”}”(hhh]”(h»)�”}”(hŒ(Infrastructure helpers for GPIO irqchips”h]”hŒ(Infrastructure helpers for GPIO irqchips”…”�”}”(hjÄh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjÁh²hh³hÊh´M¡ubhÌ)�”}”(hX·To 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]”hX·To 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:”…”�”}”(hjÒh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M£hjÁh²hubhŒtable”“”)�”}”(hhh]”hŒtgroup”“”)�”}”(hhh]”(hŒcolspec”“”)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”K2uh1jêhjçubjë)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”K2uh1jêhjçubhŒthead”“”)�”}”(hhh]”hŒrow”“”)�”}”(hhh]”(hŒentry”“”)�”}”(hhh]”hÌ)�”}”(hŒGPIO line offset”h]”hŒGPIO line offset”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khj ubah}”(h]”h ]”h"]”h$]”h&]”uh1j hjubj )�”}”(hhh]”hÌ)�”}”(hŒ Hardware IRQ”h]”hŒ Hardware IRQ”…”�”}”(hj&h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khj#ubah}”(h]”h ]”h"]”h$]”h&]”uh1j hjubeh}”(h]”h ]”h"]”h$]”h&]”uh1jhjubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjçubhŒtbody”“”)�”}”(hhh]”(j)�”}”(hhh]”(j )�”}”(hhh]”hÌ)�”}”(hŒ0”h]”hŒ0”…”�”}”(hjQh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KhjNubah}”(h]”h ]”h"]”h$]”h&]”uh1j hjKubj )�”}”(hhh]”hÌ)�”}”(hjSh]”hŒ0”…”�”}”(hjhh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khjeubah}”(h]”h ]”h"]”h$]”h&]”uh1j hjKubeh}”(h]”h ]”h"]”h$]”h&]”uh1jhjHubj)�”}”(hhh]”(j )�”}”(hhh]”hÌ)�”}”(hŒ1”h]”hŒ1”…”�”}”(hj‡h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khj„ubah}”(h]”h ]”h"]”h$]”h&]”uh1j hj�ubj )�”}”(hhh]”hÌ)�”}”(hj‰h]”hŒ1”…”�”}”(hjžh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khj›ubah}”(h]”h ]”h"]”h$]”h&]”uh1j hj�ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jhjHubj)�”}”(hhh]”(j )�”}”(hhh]”hÌ)�”}”(hŒ2”h]”hŒ2”…”�”}”(hj½h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khjºubah}”(h]”h ]”h"]”h$]”h&]”uh1j hj·ubj )�”}”(hhh]”hÌ)�”}”(hj¿h]”hŒ2”…”�”}”(hjÔh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KhjÑubah}”(h]”h ]”h"]”h$]”h&]”uh1j hj·ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jhjHubj)�”}”(hhh]”(j )�”}”(hhh]”hÌ)�”}”(hŒ...”h]”hŒ...”…”�”}”(hjóh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khjðubah}”(h]”h ]”h"]”h$]”h&]”uh1j hjíubj )�”}”(hhh]”hÌ)�”}”(hŒ...”h]”hŒ...”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khj ubah}”(h]”h ]”h"]”h$]”h&]”uh1j hjíubeh}”(h]”h ]”h"]”h$]”h&]”uh1jhjHubj)�”}”(hhh]”(j )�”}”(hhh]”hÌ)�”}”(hŒngpio-1”h]”hŒngpio-1”…”�”}”(hj* h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khj' ubah}”(h]”h ]”h"]”h$]”h&]”uh1j hj$ ubj )�”}”(hhh]”hÌ)�”}”(hŒngpio-1”h]”hŒngpio-1”…”�”}”(hjA h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khj> ubah}”(h]”h ]”h"]”h$]”h&]”uh1j hj$ ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jhjHubeh}”(h]”h ]”h"]”h$]”h&]”uh1jFhjçubeh}”(h]”h ]”h"]”h$]”h&]”Œcols”Kuh1jåhjâubah}”(h]”h ]”h"]”h$]”h&]”uh1jàhjÁh²hh³hÊh´NubhÌ)�”}”(hŒÀIf 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]”hŒÀIf 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.”…”�”}”(hjn h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MµhjÁh²hubhÌ)�”}”(hXÄThe 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]”hXÄThe 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:”…”�”}”(hj| h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M¹hjÁh²hubhê)�”}”(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);”…”�”}”hjŠ sbah}”(h]”h ]”h"]”h$]”h&]”hùhúŒforce”‰Œlanguage”Œc”Œhighlight_args”}”uh1héh³hÊh´MÁhjÁh²hubhÌ)�”}”(hŒuThe helper supports using threaded interrupts as well. Then you just request the interrupt separately and go with it:”h]”hŒuThe helper supports using threaded interrupts as well. Then you just request the interrupt separately and go with it:”…”�”}”(hj� h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MhjÁh²hubhê)�”}”(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);”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; 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);”…”�”}”hj« sbah}”(h]”h ]”h"]”h$]”h&]”hùhúj˜ ‰j™ jš j› }”uh1héh³hÊh´M hjÁh²hubhÌ)�”}”(hŒzThe helper supports using hierarchical interrupt controllers as well. In this case the typical set-up will look like this:”h]”hŒzThe helper supports using hierarchical interrupt controllers as well. In this case the typical set-up will look like this:”…”�”}”(hjº h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MThjÁh²hubhê)�”}”(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&]”hùhúj˜ ‰j™ jš j› }”uh1héh³hÊh´MWhjÁh²hubhÌ)�”}”(hXˆAs 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]”hXˆAs 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× h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M�hjÁh²hubhÌ)�”}”(hXóIf 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]”hXóIf 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å h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M¤hjÁh²hubhÌ)�”}”(hŒ5To use the helpers please keep the following in mind:”h]”hŒ5To use the helpers please keep the following in mind:”…”�”}”(hjó h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M¬hjÁh²hubj¢)�”}”(hhh]”(j§)�”}”(hŒ˜Make 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Ì)�”}”(hŒ—Make 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Œ—Make 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.”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M®hj ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¦hj h²hh³hÊh´Nubj§)�”}”(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.”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M²hj ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¦hj h²hh³hÊh´Nubeh}”(h]”h ]”h"]”h$]”h&]”j~juh1j¡h³hÊh´M®hjÁh²hubeh}”(h]”Œ(infrastructure-helpers-for-gpio-irqchips”ah ]”h"]”Œ(infrastructure helpers for gpio irqchips”ah$]”h&]”uh1hµhj½h²hh³hÊh´M¡ubh¶)�”}”(hhh]”(h»)�”}”(hŒLocking IRQ usage”h]”hŒLocking IRQ usage”…”�”}”(hjE h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjB h²hh³hÊh´M¹ubhÌ)�”}”(hŒÕSince 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]”hŒÕSince 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.”…”�”}”(hjS h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M»hjB h²hubhÌ)�”}”(hŒÙIf 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]”hŒÙIf 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.”…”�”}”(hja h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M¿hjB h²hubhÌ)�”}”(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]”hŒzInput GPIOs can be used as IRQ signals. When this happens, a driver is requested to mark the GPIO as being used as an IRQ:”…”�”}”(hjo h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MÃhjB h²hubhê)�”}”(hŒEint gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset)”h]”hŒEint gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset)”…”�”}”hj} sbah}”(h]”h ]”h"]”h$]”h&]”hùhúuh1héh³hÊh´MÆhjB h²hubhÌ)�”}”(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‹ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MÈhjB h²hubhê)�”}”(hŒHvoid gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)”h]”hŒHvoid gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)”…”�”}”hj™ sbah}”(h]”h ]”h"]”h$]”h&]”hùhúuh1héh³hÊh´MËhjB h²hubhÌ)�”}”(hŒŸWhen implementing an irqchip inside a GPIO driver, these two functions should typically be called in the .startup() and .shutdown() callbacks from the irqchip.”h]”hŒŸWhen implementing an irqchip inside a GPIO driver, these two functions should typically be called in the .startup() and .shutdown() callbacks from the irqchip.”…”�”}”(hj§ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MÍhjB h²hubhÌ)�”}”(hŒSWhen using the gpiolib irqchip helpers, these callbacks are automatically assigned.”h]”hŒSWhen using the gpiolib irqchip helpers, these callbacks are automatically assigned.”…”�”}”(hjµ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MÑhjB h²hubeh}”(h]”Œlocking-irq-usage”ah ]”h"]”Œlocking irq usage”ah$]”h&]”uh1hµhj½h²hh³hÊh´M¹ubh¶)�”}”(hhh]”(h»)�”}”(hŒDisabling and enabling IRQs”h]”hŒDisabling and enabling IRQs”…”�”}”(hjÎ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjË h²hh³hÊh´MÖubhÌ)�”}”(hŒþ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 being an input with interrupts again. This happens on things like CEC (Consumer Electronics Control).”h]”hŒþ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 being an input with interrupts again. This happens on things like CEC (Consumer Electronics Control).”…”�”}”(hjÜ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MØhjË h²hubhÌ)�”}”(hŒ°When 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]”hŒ¯When 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ê h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MÝhjË h²hubhê)�”}”(hŒFvoid gpiochip_disable_irq(struct gpio_chip *chip, unsigned int offset)”h]”hŒFvoid gpiochip_disable_irq(struct gpio_chip *chip, unsigned int offset)”…”�”}”hjø sbah}”(h]”h ]”h"]”h$]”h&]”hùhúuh1héh³hÊh´MáhjË h²hubhÌ)�”}”(hŒƒThis 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]”hŒ‚This allows drivers to drive the GPIO as an output while the IRQ is disabled. When the IRQ is enabled again, a driver should call:”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MãhjË h²hubhê)�”}”(hŒEvoid gpiochip_enable_irq(struct gpio_chip *chip, unsigned int offset)”h]”hŒEvoid gpiochip_enable_irq(struct gpio_chip *chip, unsigned int offset)”…”�”}”hj sbah}”(h]”h ]”h"]”h$]”h&]”hùhúuh1héh³hÊh´MæhjË h²hubhÌ)�”}”(hŒ¥When 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]”hŒ¥When 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.”…”�”}”(hj" h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MèhjË h²hubhÌ)�”}”(hŒ¯When 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]”hŒ¯When 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.”…”�”}”(hj0 h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MìhjË h²hubeh}”(h]”Œdisabling-and-enabling-irqs”ah ]”h"]”Œdisabling and enabling irqs”ah$]”h&]”uh1hµhj½h²hh³hÊh´MÖubh¶)�”}”(hhh]”(h»)�”}”(hŒ'Real-Time compliance for GPIO IRQ chips”h]”hŒ'Real-Time compliance for GPIO IRQ chips”…”�”}”(hjI h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjF h²hh³hÊh´MòubhÌ)�”}”(hŒâAny 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]”hŒâAny 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.”…”�”}”(hjW h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MôhjF h²hubhÌ)�”}”(hŒHSo, pay attention on above realtime considerations in the documentation.”h]”hŒHSo, pay attention on above realtime considerations in the documentation.”…”�”}”(hje h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MøhjF h²hubhÌ)�”}”(hŒXThe following is a checklist to follow when preparing a driver for real-time compliance:”h]”hŒXThe following is a checklist to follow when preparing a driver for real-time compliance:”…”�”}”(hjs h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MúhjF h²hubj¢)�”}”(hhh]”(j§)�”}”(hŒ=ensure spinlock_t is not used as part irq_chip implementation”h]”hÌ)�”}”(hj† h]”hŒ=ensure spinlock_t is not used as part irq_chip implementation”…”�”}”(hjˆ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mýhj„ ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¦hj� h²hh³hÊh´Nubj§)�”}”(hŒµensure 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”h]”hÌ)�”}”(hŒµensure 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”h]”hŒµensure 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Ÿ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mþhj› ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¦hj� h²hh³hÊh´Nubj§)�”}”(hŒhChained GPIO irqchips: ensure spinlock_t or any sleepable APIs are not used from the chained IRQ handler”h]”hÌ)�”}”(hŒhChained GPIO irqchips: ensure spinlock_t or any sleepable APIs are not used from the chained IRQ handler”h]”hŒhChained GPIO irqchips: ensure spinlock_t or any sleepable APIs are not used from the chained IRQ handler”…”�”}”(hj· h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mhj³ ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¦hj� h²hh³hÊh´Nubj§)�”}”(hŒmGeneric chained GPIO irqchips: take care about generic_handle_irq() calls and apply corresponding work-around”h]”hÌ)�”}”(hŒmGeneric chained GPIO irqchips: take care about generic_handle_irq() calls and apply corresponding work-around”h]”hŒmGeneric chained GPIO irqchips: take care about generic_handle_irq() calls and apply corresponding work-around”…”�”}”(hjÏ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MhjË ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¦hj� h²hh³hÊh´Nubj§)�”}”(hŒaChained GPIO irqchips: get rid of the chained IRQ handler and use generic irq handler if possible”h]”hÌ)�”}”(hŒaChained GPIO irqchips: get rid of the chained IRQ handler and use generic irq handler if possible”h]”hŒaChained GPIO irqchips: get rid of the chained IRQ handler and use generic irq handler if possible”…”�”}”(hjç h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mhjã ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¦hj� h²hh³hÊh´Nubj§)�”}”(hŒ‰regmap_mmio: it is possible to disable internal locking in regmap by setting .disable_locking and handling the locking in the GPIO driver”h]”hÌ)�”}”(hŒ‰regmap_mmio: it is possible to disable internal locking in regmap by setting .disable_locking and handling the locking in the GPIO driver”h]”hŒ‰regmap_mmio: it is possible to disable internal locking in regmap by setting .disable_locking and handling the locking in the GPIO driver”…”�”}”(hjÿ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mhjû ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¦hj� h²hh³hÊh´Nubj§)�”}”(hŒbTest your driver with the appropriate in-kernel real-time test cases for both level and edge IRQs ”h]”hÌ)�”}”(hŒaTest your driver with the appropriate in-kernel real-time test cases for both level and edge IRQs”h]”hŒaTest your driver with the appropriate in-kernel real-time test cases for both level and edge IRQs”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M hj ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¦hj� h²hh³hÊh´Nubeh}”(h]”h ]”h"]”h$]”h&]”j~juh1j¡h³hÊh´MýhjF h²hubj¢)�”}”(hhh]”(j§)�”}”(hŒV[1] https://lore.kernel.org/r/1437496011-11486-1-git-send-email-bigeasy@linutronix.de/”h]”hÌ)�”}”(hj6 h]”(hŒ[1] ”…”�”}”(hj8 h²hh³Nh´NubhŒ reference”“”)�”}”(hŒRhttps://lore.kernel.org/r/1437496011-11486-1-git-send-email-bigeasy@linutronix.de/”h]”hŒRhttps://lore.kernel.org/r/1437496011-11486-1-git-send-email-bigeasy@linutronix.de/”…”�”}”(hjA h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”Œrefuri”jC uh1j? hj8 ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M hj4 ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¦hj1 h²hh³hÊh´Nubj§)�”}”(hŒX[2] https://lore.kernel.org/r/1443209283-20781-2-git-send-email-grygorii.strashko@ti.com”h]”hÌ)�”}”(hj^ h]”(hŒ[2] ”…”�”}”(hj` h²hh³Nh´Nubj@ )�”}”(hŒThttps://lore.kernel.org/r/1443209283-20781-2-git-send-email-grygorii.strashko@ti.com”h]”hŒThttps://lore.kernel.org/r/1443209283-20781-2-git-send-email-grygorii.strashko@ti.com”…”�”}”(hjg h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”Œrefuri”ji uh1j? hj` ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M hj\ ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¦hj1 h²hh³hÊh´Nubj§)�”}”(hŒZ[3] https://lore.kernel.org/r/1443209283-20781-3-git-send-email-grygorii.strashko@ti.com ”h]”hÌ)�”}”(hŒX[3] https://lore.kernel.org/r/1443209283-20781-3-git-send-email-grygorii.strashko@ti.com”h]”(hŒ[3] ”…”�”}”(hj† h²hh³Nh´Nubj@ )�”}”(hŒThttps://lore.kernel.org/r/1443209283-20781-3-git-send-email-grygorii.strashko@ti.com”h]”hŒThttps://lore.kernel.org/r/1443209283-20781-3-git-send-email-grygorii.strashko@ti.com”…”�”}”(hjŽ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”Œrefuri”j� uh1j? hj† ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mhj‚ ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¦hj1 h²hh³hÊh´Nubeh}”(h]”h ]”h"]”h$]”h&]”j~Œ*”uh1j¡h³hÊh´M hjF h²hubeh}”(h]”Œ'real-time-compliance-for-gpio-irq-chips”ah ]”h"]”Œ'real-time compliance for gpio irq chips”ah$]”h&]”uh1hµhj½h²hh³hÊh´Mòubeh}”(h]”Œgpio-drivers-providing-irqs”ah ]”h"]”Œgpio drivers providing irqs”ah$]”h&]”uh1hµhh·h²hh³hÊh´Mubh¶)�”}”(hhh]”(h»)�”}”(hŒRequesting self-owned GPIO pins”h]”hŒRequesting self-owned GPIO pins”…”�”}”(hjà h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjÀ h²hh³hÊh´MubhÌ)�”}”(hŒ¿Sometimes 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]”hŒ¾Sometimes 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Ñ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MhjÀ h²hubhê)�”}”(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&]”hùhúuh1héh³hÊh´MhjÀ h²hubhÌ)�”}”(hŒfDescriptors requested with gpiochip_request_own_desc() must be released with gpiochip_free_own_desc().”h]”hŒfDescriptors requested with gpiochip_request_own_desc() must be released with gpiochip_free_own_desc().”…”�”}”(hjí h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MhjÀ h²hubhÌ)�”}”(hŒ§These 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]”hŒ§These 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û h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M"hjÀ h²hubeh}”(h]”Œrequesting-self-owned-gpio-pins”ah ]”h"]”Œrequesting self-owned gpio pins”ah$]”h&]”uh1hµhh·h²hh³hÊh´Mubeh}”(h]”Œgpio-driver-interface”ah ]”h"]”Œgpio driver interface”ah$]”h&]”uh1hµhhh²hh³hÊh´Kubeh}”(h]”h ]”h"]”h$]”h&]”Œsource”hÊuh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)�”}”(hºNŒ generator”NŒ datestamp”NŒ source_link”NŒ source_url”NŒ toc_backlinks”j Œfootnote_backlinks”KŒ sectnum_xform”KŒstrip_comments”NŒstrip_elements_with_classes”NŒ strip_classes”NŒ report_level”KŒ halt_level”KŒexit_status_level”KŒdebug”NŒwarning_stream”NŒ traceback”ˆŒinput_encoding”Œ utf-8-sig”Œinput_encoding_error_handler”Œstrict”Œoutput_encoding”Œutf-8”Œoutput_encoding_error_handler”j; Œerror_encoding”Œutf-8”Œerror_encoding_error_handler”Œbackslashreplace”Œ language_code”Œen”Œrecord_dependencies”NŒconfig”NŒ id_prefix”hŒauto_id_prefix”Œid”Œ dump_settings”NŒdump_internals”NŒdump_transforms”NŒdump_pseudo_xml”NŒexpose_internals”NŒstrict_visitor”NŒ_disable_config”NŒ_source”hÊŒ _destination”NŒ _config_files”]”Œ7/var/lib/git/docbuild/linux/Documentation/docutils.conf”aŒfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œpep_references”NŒ pep_base_url”Œhttps://peps.python.org/”Œpep_file_url_template”Œpep-%04d”Œrfc_references”NŒ rfc_base_url”Œ&https://datatracker.ietf.org/doc/html/”Œ tab_width”KŒtrim_footnote_reference_space”‰Œsyntax_highlight”Œlong”Œ smart_quotes”ˆŒsmartquotes_locales”]”Œcharacter_level_inline_markup”‰Œdoctitle_xform”‰Œ docinfo_xform”KŒsectsubtitle_xform”‰Œ image_loading”Œlink”Œembed_stylesheet”‰Œcloak_email_addresses”ˆŒsection_self_link”‰Œenv”NubŒreporter”NŒindirect_targets”]”Œsubstitution_defs”}”Œsubstitution_names”}”Œrefnames”}”Œrefids”}”Œnameids”}”(j j jyjvjºj·jdjajjj9j6jaj^j²j¯j½ jº j¾j»j? j< jÈ jÅ jC j@ jµ j² j j uŒ nametypes”}”(j ‰jy‰jº‰jd‰j‰j9‰ja‰j²‰j½ ‰j¾‰j? ‰jÈ ‰jC ‰jµ ‰j ‰uh}”(j h·jvhûj·j|jaj¾jjgj6jj^j<j¯jdjº j½j»j¡j< jÁjÅ jB j@ jË j² jF j jÀ uŒ footnote_refs”}”Œ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”Œ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”…”R”Œparse_messages”]”(hŒsystem_message”“”)�”}”(hhh]”hÌ)�”}”(hŒeUnexpected possible title overline or transition. Treating it as ordinary text because it's so short.”h]”hŒgUnexpected possible title overline or transition. Treating it as ordinary text because it’s so short.”…”�”}”(hj¢ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËhjŸ ubah}”(h]”h ]”h"]”h$]”h&]”Œlevel”KŒtype”ŒINFO”Œline”M®Œsource”hÊuh1j� hjðubjž )�”}”(hhh]”hÌ)�”}”(hŒeUnexpected possible title overline or transition. Treating it as ordinary text because it's so short.”h]”hŒgUnexpected possible title overline or transition. Treating it as ordinary text because it’s so short.”…”�”}”(hj¾ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËhj» ubah}”(h]”h ]”h"]”h$]”h&]”Œlevel”KŒtype”j¸ Œline”M®Œsource”hÊuh1j� hj ubeŒtransform_messages”]”Œ transformer”NŒ include_log”]”Œ decoration”Nh²hub.