Documentation/driver-api/gpio/driver.rst GitHub 원문 ↗

Linux 6.18.37 · Driver API

GPIO Driver Interface

GPIO chip driver의 번호 체계, 전기 구성, irqchip topology, helper와 실시간 제약을 설명합니다.

Source pathDocumentation/driver-api/gpio/driver.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약과 해설

driver.rst:1-777

GPIO provider driver는 hardware offset을 중심으로 `gpio_chip`을 구현하고, 필요하면 pin control과 `irq_chip`을 결합합니다. Electrical mode와 IRQ topology는 hardware capability와 실행 context를 정확히 반영해야 합니다.

GPIO와 IRQ service는 독립적이므로 `gpiod_to_irq()` 호출에 초기화를 의존해서는 안 됩니다. -RT에서는 chained·generic·threaded handler의 context 차이를 고려하고 lock과 sleep 가능 API를 엄격히 배치해야 합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 =====================
2 GPIO Driver Interface
3 =====================
4
5 This document serves as a guide for writers of GPIO chip drivers.
6
7 Each GPIO controller driver needs to include the following header, which defines
8 the structures used to define a GPIO driver::
9
10 #include <linux/gpio/driver.h>
11
12
13 Internal Representation of GPIOs
14 ================================
15
16 A GPIO chip handles one or more GPIO lines. To be considered a GPIO chip, the
17 lines must conform to the definition: General Purpose Input/Output. If the
18 line is not general purpose, it is not GPIO and should not be handled by a
19 GPIO chip. The use case is the indicative: certain lines in a system may be
20 called GPIO but serve a very particular purpose thus not meeting the criteria
21 of a general purpose I/O. On the other hand a LED driver line may be used as a
22 GPIO and should therefore still be handled by a GPIO chip driver.
23
24 Inside a GPIO driver, individual GPIO lines are identified by their hardware
25 number, sometime also referred to as ``offset``, which is a unique number
26 between 0 and n-1, n being the number of GPIOs managed by the chip.
27
28 The hardware GPIO number should be something intuitive to the hardware, for
29 example if a system uses a memory-mapped set of I/O-registers where 32 GPIO
30 lines are handled by one bit per line in a 32-bit register, it makes sense to
31 use hardware offsets 0..31 for these, corresponding to bits 0..31 in the
32 register.
33
34 This number is purely internal: the hardware number of a particular GPIO
35 line is never made visible outside of the driver.
36
37 On top of this internal number, each GPIO line also needs to have a global
38 number in the integer GPIO namespace so that it can be used with the legacy GPIO
39 interface. Each chip must thus have a "base" number (which can be automatically
40 assigned), and for each GPIO line the global number will be (base + hardware
41 number). Although the integer representation is considered deprecated, it still
42 has many users and thus needs to be maintained.
43
44 So for example one platform could use global numbers 32-159 for GPIOs, with a
45 controller defining 128 GPIOs at a "base" of 32 ; while another platform uses
46 global numbers 0..63 with one set of GPIO controllers, 64-79 with another type
47 of GPIO controller, and on one particular board 80-95 with an FPGA. The legacy
48 numbers need not be contiguous; either of those platforms could also use numbers
49 2000-2063 to identify GPIO lines in a bank of I2C GPIO expanders.
50
51
52 Controller Drivers: gpio_chip
53 =============================
54
55 In the gpiolib framework each GPIO controller is packaged as a "struct
56 gpio_chip" (see <linux/gpio/driver.h> for its complete definition) with members
57 common to each controller of that type, these should be assigned by the
58 driver code:
59
60 - methods to establish GPIO line direction
61 - methods used to access GPIO line values
62 - method to set electrical configuration for a given GPIO line
63 - method to return the IRQ number associated to a given GPIO line
64 - flag saying whether calls to its methods may sleep
65 - optional line names array to identify lines
66 - optional debugfs dump method (showing extra state information)
67 - optional base number (will be automatically assigned if omitted)
68 - optional label for diagnostics and GPIO chip mapping using platform data
69
70 The code implementing a gpio_chip should support multiple instances of the
71 controller, preferably using the driver model. That code will configure each
72 gpio_chip and issue gpiochip_add_data() or devm_gpiochip_add_data(). Removing
73 a GPIO controller should be rare; use gpiochip_remove() when it is unavoidable.
74
75 Often a gpio_chip is part of an instance-specific structure with states not
76 exposed by the GPIO interfaces, such as addressing, power management, and more.
77 Chips such as audio codecs will have complex non-GPIO states.
78
79 Any debugfs dump method should normally ignore lines which haven't been
80 requested. They can use gpiochip_is_requested(), which returns either
81 NULL or the label associated with that GPIO line when it was requested.
82
83 Realtime considerations: the GPIO driver should not use spinlock_t or any
84 sleepable APIs (like PM runtime) in its gpio_chip implementation (.get/.set
85 and direction control callbacks) if it is expected to call GPIO APIs from
86 atomic context on realtime kernels (inside hard IRQ handlers and similar
87 contexts). Normally this should not be required.
88
89
90 GPIO electrical configuration
91 -----------------------------
92
93 GPIO lines can be configured for several electrical modes of operation by using
94 the .set_config() callback. Currently this API supports setting:
95
96 - Debouncing
97 - Single-ended modes (open drain/open source)
98 - Pull up and pull down resistor enablement
99
100 These settings are described below.
101
102 The .set_config() callback uses the same enumerators and configuration
103 semantics as the generic pin control drivers. This is not a coincidence: it is
104 possible to assign the .set_config() to the function gpiochip_generic_config()
105 which will result in pinctrl_gpio_set_config() being called and eventually
106 ending up in the pin control back-end "behind" the GPIO controller, usually
107 closer to the actual pins. This way the pin controller can manage the below
108 listed GPIO configurations.
109
110 If a pin controller back-end is used, the GPIO controller or hardware
111 description needs to provide "GPIO ranges" mapping the GPIO line offsets to pin
112 numbers on the pin controller so they can properly cross-reference each other.
113
114
115 GPIO lines with debounce support
116 --------------------------------
117
118 Debouncing is a configuration set to a pin indicating that it is connected to
119 a mechanical switch or button, or similar that may bounce. Bouncing means the
120 line is pulled high/low quickly at very short intervals for mechanical
121 reasons. This can result in the value being unstable or irqs firing repeatedly
122 unless the line is debounced.
123
124 Debouncing in practice involves setting up a timer when something happens on
125 the line, wait a little while and then sample the line again, so see if it
126 still has the same value (low or high). This could also be repeated by a clever
127 state machine, waiting for a line to become stable. In either case, it sets
128 a certain number of milliseconds for debouncing, or just "on/off" if that time
129 is not configurable.
130
131
132 GPIO lines with open drain/source support
133 -----------------------------------------
134
135 Open drain (CMOS) or open collector (TTL) means the line is not actively driven
136 high: instead you provide the drain/collector as output, so when the transistor
137 is not open, it will present a high-impedance (tristate) to the external rail::
138
139
140 CMOS CONFIGURATION TTL CONFIGURATION
141
142 ||--- out +--- out
143 in ----|| |/
144 ||--+ in ----|
145 | |\
146 GND GND
147
148 This configuration is normally used as a way to achieve one of two things:
149
150 - Level-shifting: to reach a logical level higher than that of the silicon
151 where the output resides.
152
153 - Inverse wire-OR on an I/O line, for example a GPIO line, making it possible
154 for any driving stage on the line to drive it low even if any other output
155 to the same line is simultaneously driving it high. A special case of this
156 is driving the SCL and SDA lines of an I2C bus, which is by definition a
157 wire-OR bus.
158
159 Both use cases require that the line be equipped with a pull-up resistor. This
160 resistor will make the line tend to high level unless one of the transistors on
161 the rail actively pulls it down.
162
163 The level on the line will go as high as the VDD on the pull-up resistor, which
164 may be higher than the level supported by the transistor, achieving a
165 level-shift to the higher VDD.
166
167 Integrated electronics often have an output driver stage in the form of a CMOS
168 "totem-pole" with one N-MOS and one P-MOS transistor where one of them drives
169 the line high and one of them drives the line low. This is called a push-pull
170 output. The "totem-pole" looks like so::
171
172 VDD
173 |
174 OD ||--+
175 +--/ ---o|| P-MOS-FET
176 | ||--+
177 IN --+ +----- out
178 | ||--+
179 +--/ ----|| N-MOS-FET
180 OS ||--+
181 |
182 GND
183
184 The desired output signal (e.g. coming directly from some GPIO output register)
185 arrives at IN. The switches named "OD" and "OS" are normally closed, creating
186 a push-pull circuit.
187
188 Consider the little "switches" named "OD" and "OS" that enable/disable the
189 P-MOS or N-MOS transistor right after the split of the input. As you can see,
190 either transistor will go totally numb if this switch is open. The totem-pole
191 is then halved and give high impedance instead of actively driving the line
192 high or low respectively. That is usually how software-controlled open
193 drain/source works.
194
195 Some GPIO hardware come in open drain / open source configuration. Some are
196 hard-wired lines that will only support open drain or open source no matter
197 what: there is only one transistor there. Some are software-configurable:
198 by flipping a bit in a register the output can be configured as open drain
199 or open source, in practice by flicking open the switches labeled "OD" and "OS"
200 in the drawing above.
201
202 By disabling the P-MOS transistor, the output can be driven between GND and
203 high impedance (open drain), and by disabling the N-MOS transistor, the output
204 can be driven between VDD and high impedance (open source). In the first case,
205 a pull-up resistor is needed on the outgoing rail to complete the circuit, and
206 in the second case, a pull-down resistor is needed on the rail.
207
208 Hardware that supports open drain or open source or both, can implement a
209 special callback in the gpio_chip: .set_config() that takes a generic
210 pinconf packed value telling whether to configure the line as open drain,
211 open source or push-pull. This will happen in response to the
212 GPIO_OPEN_DRAIN or GPIO_OPEN_SOURCE flag set in the machine file, or coming
213 from other hardware descriptions.
214
215 If this state can not be configured in hardware, i.e. if the GPIO hardware does
216 not support open drain/open source in hardware, the GPIO library will instead
217 use a trick: when a line is set as output, if the line is flagged as open
218 drain, and the IN output value is low, it will be driven low as usual. But
219 if the IN output value is set to high, it will instead *NOT* be driven high,
220 instead it will be switched to input, as input mode is an equivalent to
221 high impedance, thus achieving an "open drain emulation" of sorts: electrically
222 the behaviour will be identical, with the exception of possible hardware glitches
223 when switching the mode of the line.
224
225 For open source configuration the same principle is used, just that instead
226 of actively driving the line low, it is set to input.
227
228
229 GPIO lines with pull up/down resistor support
230 ---------------------------------------------
231
232 A GPIO line can support pull-up/down using the .set_config() callback. This
233 means that a pull up or pull-down resistor is available on the output of the
234 GPIO line, and this resistor is software controlled.
235
236 In discrete designs, a pull-up or pull-down resistor is simply soldered on
237 the circuit board. This is not something we deal with or model in software. The
238 most you will think about these lines is that they will very likely be
239 configured as open drain or open source (see the section above).
240
241 The .set_config() callback can only turn pull up or down on and off, and will
242 no have any semantic knowledge about the resistance used. It will only say
243 switch a bit in a register enabling or disabling pull-up or pull-down.
244
245 If the GPIO line supports shunting in different resistance values for the
246 pull-up or pull-down resistor, the GPIO chip callback .set_config() will not
247 suffice. For these complex use cases, a combined GPIO chip and pin controller
248 need to be implemented, as the pin config interface of a pin controller
249 supports more versatile control over electrical properties and can handle
250 different pull-up or pull-down resistance values.
251
252
253 GPIO drivers providing IRQs
254 ===========================
255
256 It is custom that GPIO drivers (GPIO chips) are also providing interrupts,
257 most often cascaded off a parent interrupt controller, and in some special
258 cases the GPIO logic is melded with a SoC's primary interrupt controller.
259
260 The IRQ portions of the GPIO block are implemented using an irq_chip, using
261 the header <linux/irq.h>. So this combined driver is utilizing two sub-
262 systems simultaneously: gpio and irq.
263
264 It is legal for any IRQ consumer to request an IRQ from any irqchip even if it
265 is a combined GPIO+IRQ driver. The basic premise is that gpio_chip and
266 irq_chip are orthogonal, and offering their services independent of each
267 other.
268
269 gpiod_to_irq() is just a convenience function to figure out the IRQ for a
270 certain GPIO line and should not be relied upon to have been called before
271 the IRQ is used.
272
273 Always prepare the hardware and make it ready for action in respective
274 callbacks from the GPIO and irq_chip APIs. Do not rely on gpiod_to_irq() having
275 been called first.
276
277 We can divide GPIO irqchips in two broad categories:
278
279 - CASCADED INTERRUPT CHIPS: this means that the GPIO chip has one common
280 interrupt output line, which is triggered by any enabled GPIO line on that
281 chip. The interrupt output line will then be routed to an parent interrupt
282 controller one level up, in the most simple case the systems primary
283 interrupt controller. This is modeled by an irqchip that will inspect bits
284 inside the GPIO controller to figure out which line fired it. The irqchip
285 part of the driver needs to inspect registers to figure this out and it
286 will likely also need to acknowledge that it is handling the interrupt
287 by clearing some bit (sometime implicitly, by just reading a status
288 register) and it will often need to set up the configuration such as
289 edge sensitivity (rising or falling edge, or high/low level interrupt for
290 example).
291
292 - HIERARCHICAL INTERRUPT CHIPS: this means that each GPIO line has a dedicated
293 irq line to a parent interrupt controller one level up. There is no need
294 to inquire the GPIO hardware to figure out which line has fired, but it
295 may still be necessary to acknowledge the interrupt and set up configuration
296 such as edge sensitivity.
297
298 Realtime considerations: a realtime compliant GPIO driver should not use
299 spinlock_t or any sleepable APIs (like PM runtime) as part of its irqchip
300 implementation.
301
302 - spinlock_t should be replaced with raw_spinlock_t.[1]
303 - If sleepable APIs have to be used, these can be done from the .irq_bus_lock()
304 and .irq_bus_unlock() callbacks, as these are the only slowpath callbacks
305 on an irqchip. Create the callbacks if needed.[2]
306
307
308 Cascaded GPIO irqchips
309 ----------------------
310
311 Cascaded GPIO irqchips usually fall in one of three categories:
312
313 - CHAINED CASCADED GPIO IRQCHIPS: these are usually the type that is embedded on
314 an SoC. This means that there is a fast IRQ flow handler for the GPIOs that
315 gets called in a chain from the parent IRQ handler, most typically the
316 system interrupt controller. This means that the GPIO irqchip handler will
317 be called immediately from the parent irqchip, while holding the IRQs
318 disabled. The GPIO irqchip will then end up calling something like this
319 sequence in its interrupt handler::
320
321 static irqreturn_t foo_gpio_irq(int irq, void *data)
322 chained_irq_enter(...);
323 generic_handle_irq(...);
324 chained_irq_exit(...);
325
326 Chained GPIO irqchips typically can NOT set the .can_sleep flag on
327 struct gpio_chip, as everything happens directly in the callbacks: no
328 slow bus traffic like I2C can be used.
329
330 Realtime considerations: Note that chained IRQ handlers will not be forced
331 threaded on -RT. As a result, spinlock_t or any sleepable APIs (like PM
332 runtime) can't be used in a chained IRQ handler.
333
334 If required (and if it can't be converted to the nested threaded GPIO irqchip,
335 see below) a chained IRQ handler can be converted to generic irq handler and
336 this way it will become a threaded IRQ handler on -RT and a hard IRQ handler
337 on non-RT (for example, see [3]).
338
339 The generic_handle_irq() is expected to be called with IRQ disabled,
340 so the IRQ core will complain if it is called from an IRQ handler which is
341 forced to a thread. The "fake?" raw lock can be used to work around this
342 problem::
343
344 raw_spinlock_t wa_lock;
345 static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
346 unsigned long wa_lock_flags;
347 raw_spin_lock_irqsave(&bank->wa_lock, wa_lock_flags);
348 generic_handle_irq(irq_find_mapping(bank->chip.irq.domain, bit));
349 raw_spin_unlock_irqrestore(&bank->wa_lock, wa_lock_flags);
350
351 - GENERIC CHAINED GPIO IRQCHIPS: these are the same as "CHAINED GPIO irqchips",
352 but chained IRQ handlers are not used. Instead GPIO IRQs dispatching is
353 performed by generic IRQ handler which is configured using request_irq().
354 The GPIO irqchip will then end up calling something like this sequence in
355 its interrupt handler::
356
357 static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id)
358 for each detected GPIO IRQ
359 generic_handle_irq(...);
360
361 Realtime considerations: this kind of handlers will be forced threaded on -RT,
362 and as result the IRQ core will complain that generic_handle_irq() is called
363 with IRQ enabled and the same work-around as for "CHAINED GPIO irqchips" can
364 be applied.
365
366 - NESTED THREADED GPIO IRQCHIPS: these are off-chip GPIO expanders and any
367 other GPIO irqchip residing on the other side of a sleeping bus such as I2C
368 or SPI.
369
370 Of course such drivers that need slow bus traffic to read out IRQ status and
371 similar, traffic which may in turn incur other IRQs to happen, cannot be
372 handled in a quick IRQ handler with IRQs disabled. Instead they need to spawn
373 a thread and then mask the parent IRQ line until the interrupt is handled
374 by the driver. The hallmark of this driver is to call something like
375 this in its interrupt handler::
376
377 static irqreturn_t foo_gpio_irq(int irq, void *data)
378 ...
379 handle_nested_irq(irq);
380
381 The hallmark of threaded GPIO irqchips is that they set the .can_sleep
382 flag on struct gpio_chip to true, indicating that this chip may sleep
383 when accessing the GPIOs.
384
385 These kinds of irqchips are inherently realtime tolerant as they are
386 already set up to handle sleeping contexts.
387
388
389 Infrastructure helpers for GPIO irqchips
390 ----------------------------------------
391
392 To help out in handling the set-up and management of GPIO irqchips and the
393 associated irqdomain and resource allocation callbacks. These are activated
394 by selecting the Kconfig symbol GPIOLIB_IRQCHIP. If the symbol
395 IRQ_DOMAIN_HIERARCHY is also selected, hierarchical helpers will also be
396 provided. A big portion of overhead code will be managed by gpiolib,
397 under the assumption that your interrupts are 1-to-1-mapped to the
398 GPIO line index:
399
400 .. csv-table::
401 :header: GPIO line offset, Hardware IRQ
402
403 0,0
404 1,1
405 2,2
406 ...,...
407 ngpio-1, ngpio-1
408
409
410 If some GPIO lines do not have corresponding IRQs, the bitmask valid_mask
411 and the flag need_valid_mask in gpio_irq_chip can be used to mask off some
412 lines as invalid for associating with IRQs.
413
414 The preferred way to set up the helpers is to fill in the
415 struct gpio_irq_chip inside struct gpio_chip before adding the gpio_chip.
416 If you do this, the additional irq_chip will be set up by gpiolib at the
417 same time as setting up the rest of the GPIO functionality. The following
418 is a typical example of a chained cascaded interrupt handler using
419 the gpio_irq_chip. Note how the mask/unmask (or disable/enable) functions
420 call into the core gpiolib code:
421
422 .. code-block:: c
423
424 /* Typical state container */
425 struct my_gpio {
426 struct gpio_chip gc;
427 };
428
429 static void my_gpio_mask_irq(struct irq_data *d)
430 {
431 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
432 irq_hw_number_t hwirq = irqd_to_hwirq(d);
433
434 /*
435 * Perform any necessary action to mask the interrupt,
436 * and then call into the core code to synchronise the
437 * state.
438 */
439
440 gpiochip_disable_irq(gc, hwirq);
441 }
442
443 static void my_gpio_unmask_irq(struct irq_data *d)
444 {
445 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
446 irq_hw_number_t hwirq = irqd_to_hwirq(d);
447
448 gpiochip_enable_irq(gc, hwirq);
449
450 /*
451 * Perform any necessary action to unmask the interrupt,
452 * after having called into the core code to synchronise
453 * the state.
454 */
455 }
456
457 /*
458 * Statically populate the irqchip. Note that it is made const
459 * (further indicated by the IRQCHIP_IMMUTABLE flag), and that
460 * the GPIOCHIP_IRQ_RESOURCE_HELPER macro adds some extra
461 * callbacks to the structure.
462 */
463 static const struct irq_chip my_gpio_irq_chip = {
464 .name = "my_gpio_irq",
465 .irq_ack = my_gpio_ack_irq,
466 .irq_mask = my_gpio_mask_irq,
467 .irq_unmask = my_gpio_unmask_irq,
468 .irq_set_type = my_gpio_set_irq_type,
469 .flags = IRQCHIP_IMMUTABLE,
470 /* Provide the gpio resource callbacks */
471 GPIOCHIP_IRQ_RESOURCE_HELPERS,
472 };
473
474 int irq; /* from platform etc */
475 struct my_gpio *g;
476 struct gpio_irq_chip *girq;
477
478 /* Get a pointer to the gpio_irq_chip */
479 girq = &g->gc.irq;
480 gpio_irq_chip_set_chip(girq, &my_gpio_irq_chip);
481 girq->parent_handler = ftgpio_gpio_irq_handler;
482 girq->num_parents = 1;
483 girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents),
484 GFP_KERNEL);
485 if (!girq->parents)
486 return -ENOMEM;
487 girq->default_type = IRQ_TYPE_NONE;
488 girq->handler = handle_bad_irq;
489 girq->parents[0] = irq;
490
491 return devm_gpiochip_add_data(dev, &g->gc, g);
492
493 The helper supports using threaded interrupts as well. Then you just request
494 the interrupt separately and go with it:
495
496 .. code-block:: c
497
498 /* Typical state container */
499 struct my_gpio {
500 struct gpio_chip gc;
501 };
502
503 static void my_gpio_mask_irq(struct irq_data *d)
504 {
505 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
506 irq_hw_number_t hwirq = irqd_to_hwirq(d);
507
508 /*
509 * Perform any necessary action to mask the interrupt,
510 * and then call into the core code to synchronise the
511 * state.
512 */
513
514 gpiochip_disable_irq(gc, hwirq);
515 }
516
517 static void my_gpio_unmask_irq(struct irq_data *d)
518 {
519 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
520 irq_hw_number_t hwirq = irqd_to_hwirq(d);
521
522 gpiochip_enable_irq(gc, hwirq);
523
524 /*
525 * Perform any necessary action to unmask the interrupt,
526 * after having called into the core code to synchronise
527 * the state.
528 */
529 }
530
531 /*
532 * Statically populate the irqchip. Note that it is made const
533 * (further indicated by the IRQCHIP_IMMUTABLE flag), and that
534 * the GPIOCHIP_IRQ_RESOURCE_HELPER macro adds some extra
535 * callbacks to the structure.
536 */
537 static const struct irq_chip my_gpio_irq_chip = {
538 .name = "my_gpio_irq",
539 .irq_ack = my_gpio_ack_irq,
540 .irq_mask = my_gpio_mask_irq,
541 .irq_unmask = my_gpio_unmask_irq,
542 .irq_set_type = my_gpio_set_irq_type,
543 .flags = IRQCHIP_IMMUTABLE,
544 /* Provide the gpio resource callbacks */
545 GPIOCHIP_IRQ_RESOURCE_HELPERS,
546 };
547
548 int irq; /* from platform etc */
549 struct my_gpio *g;
550 struct gpio_irq_chip *girq;
551
552 ret = devm_request_threaded_irq(dev, irq, NULL, irq_thread_fn,
553 IRQF_ONESHOT, "my-chip", g);
554 if (ret < 0)
555 return ret;
556
557 /* Get a pointer to the gpio_irq_chip */
558 girq = &g->gc.irq;
559 gpio_irq_chip_set_chip(girq, &my_gpio_irq_chip);
560 /* This will let us handle the parent IRQ in the driver */
561 girq->parent_handler = NULL;
562 girq->num_parents = 0;
563 girq->parents = NULL;
564 girq->default_type = IRQ_TYPE_NONE;
565 girq->handler = handle_bad_irq;
566
567 return devm_gpiochip_add_data(dev, &g->gc, g);
568
569 The helper supports using hierarchical interrupt controllers as well.
570 In this case the typical set-up will look like this:
571
572 .. code-block:: c
573
574 /* Typical state container with dynamic irqchip */
575 struct my_gpio {
576 struct gpio_chip gc;
577 struct fwnode_handle *fwnode;
578 };
579
580 static void my_gpio_mask_irq(struct irq_data *d)
581 {
582 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
583 irq_hw_number_t hwirq = irqd_to_hwirq(d);
584
585 /*
586 * Perform any necessary action to mask the interrupt,
587 * and then call into the core code to synchronise the
588 * state.
589 */
590
591 gpiochip_disable_irq(gc, hwirq);
592 irq_mask_mask_parent(d);
593 }
594
595 static void my_gpio_unmask_irq(struct irq_data *d)
596 {
597 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
598 irq_hw_number_t hwirq = irqd_to_hwirq(d);
599
600 gpiochip_enable_irq(gc, hwirq);
601
602 /*
603 * Perform any necessary action to unmask the interrupt,
604 * after having called into the core code to synchronise
605 * the state.
606 */
607
608 irq_mask_unmask_parent(d);
609 }
610
611 /*
612 * Statically populate the irqchip. Note that it is made const
613 * (further indicated by the IRQCHIP_IMMUTABLE flag), and that
614 * the GPIOCHIP_IRQ_RESOURCE_HELPER macro adds some extra
615 * callbacks to the structure.
616 */
617 static const struct irq_chip my_gpio_irq_chip = {
618 .name = "my_gpio_irq",
619 .irq_ack = my_gpio_ack_irq,
620 .irq_mask = my_gpio_mask_irq,
621 .irq_unmask = my_gpio_unmask_irq,
622 .irq_set_type = my_gpio_set_irq_type,
623 .flags = IRQCHIP_IMMUTABLE,
624 /* Provide the gpio resource callbacks */
625 GPIOCHIP_IRQ_RESOURCE_HELPERS,
626 };
627
628 struct my_gpio *g;
629 struct gpio_irq_chip *girq;
630
631 /* Get a pointer to the gpio_irq_chip */
632 girq = &g->gc.irq;
633 gpio_irq_chip_set_chip(girq, &my_gpio_irq_chip);
634 girq->default_type = IRQ_TYPE_NONE;
635 girq->handler = handle_bad_irq;
636 girq->fwnode = g->fwnode;
637 girq->parent_domain = parent;
638 girq->child_to_parent_hwirq = my_gpio_child_to_parent_hwirq;
639
640 return devm_gpiochip_add_data(dev, &g->gc, g);
641
642 As you can see pretty similar, but you do not supply a parent handler for
643 the IRQ, instead a parent irqdomain, an fwnode for the hardware and
644 a function .child_to_parent_hwirq() that has the purpose of looking up
645 the parent hardware irq from a child (i.e. this gpio chip) hardware irq.
646 As always it is good to look at examples in the kernel tree for advice
647 on how to find the required pieces.
648
649 If there is a need to exclude certain GPIO lines from the IRQ domain handled by
650 these helpers, we can set .irq.need_valid_mask of the gpiochip before
651 devm_gpiochip_add_data() or gpiochip_add_data() is called. This allocates an
652 .irq.valid_mask with as many bits set as there are GPIO lines in the chip, each
653 bit representing line 0..n-1. Drivers can exclude GPIO lines by clearing bits
654 from this mask. The mask can be filled in the init_valid_mask() callback
655 that is part of the struct gpio_irq_chip.
656
657 To use the helpers please keep the following in mind:
658
659 - Make sure to assign all relevant members of the struct gpio_chip so that
660 the irqchip can initialize. E.g. .dev and .can_sleep shall be set up
661 properly.
662
663 - Nominally set gpio_irq_chip.handler to handle_bad_irq. Then, if your irqchip
664 is cascaded, set the handler to handle_level_irq() and/or handle_edge_irq()
665 in the irqchip .set_type() callback depending on what your controller
666 supports and what is requested by the consumer.
667
668
669 Locking IRQ usage
670 -----------------
671
672 Since GPIO and irq_chip are orthogonal, we can get conflicts between different
673 use cases. For example a GPIO line used for IRQs should be an input line,
674 it does not make sense to fire interrupts on an output GPIO.
675
676 If there is competition inside the subsystem which side is using the
677 resource (a certain GPIO line and register for example) it needs to deny
678 certain operations and keep track of usage inside of the gpiolib subsystem.
679
680 Input GPIOs can be used as IRQ signals. When this happens, a driver is requested
681 to mark the GPIO as being used as an IRQ::
682
683 int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
684
685 This will prevent the use of non-irq related GPIO APIs until the GPIO IRQ lock
686 is released::
687
688 void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)
689
690 When implementing an irqchip inside a GPIO driver, these two functions should
691 typically be called in the .startup() and .shutdown() callbacks from the
692 irqchip.
693
694 When using the gpiolib irqchip helpers, these callbacks are automatically
695 assigned.
696
697
698 Disabling and enabling IRQs
699 ---------------------------
700
701 In some (fringe) use cases, a driver may be using a GPIO line as input for IRQs,
702 but occasionally switch that line over to drive output and then back to being
703 an input with interrupts again. This happens on things like CEC (Consumer
704 Electronics Control).
705
706 When a GPIO is used as an IRQ signal, then gpiolib also needs to know if
707 the IRQ is enabled or disabled. In order to inform gpiolib about this,
708 the irqchip driver should call::
709
710 void gpiochip_disable_irq(struct gpio_chip *chip, unsigned int offset)
711
712 This allows drivers to drive the GPIO as an output while the IRQ is
713 disabled. When the IRQ is enabled again, a driver should call::
714
715 void gpiochip_enable_irq(struct gpio_chip *chip, unsigned int offset)
716
717 When implementing an irqchip inside a GPIO driver, these two functions should
718 typically be called in the .irq_disable() and .irq_enable() callbacks from the
719 irqchip.
720
721 When IRQCHIP_IMMUTABLE is not advertised by the irqchip, these callbacks
722 are automatically assigned. This behaviour is deprecated and on its way
723 to be removed from the kernel.
724
725
726 Real-Time compliance for GPIO IRQ chips
727 ---------------------------------------
728
729 Any provider of irqchips needs to be carefully tailored to support Real-Time
730 preemption. It is desirable that all irqchips in the GPIO subsystem keep this
731 in mind and do the proper testing to assure they are real time-enabled.
732
733 So, pay attention on above realtime considerations in the documentation.
734
735 The following is a checklist to follow when preparing a driver for real-time
736 compliance:
737
738 - ensure spinlock_t is not used as part irq_chip implementation
739 - ensure that sleepable APIs are not used as part irq_chip implementation
740 If sleepable APIs have to be used, these can be done from the .irq_bus_lock()
741 and .irq_bus_unlock() callbacks
742 - Chained GPIO irqchips: ensure spinlock_t or any sleepable APIs are not used
743 from the chained IRQ handler
744 - Generic chained GPIO irqchips: take care about generic_handle_irq() calls and
745 apply corresponding work-around
746 - Chained GPIO irqchips: get rid of the chained IRQ handler and use generic irq
747 handler if possible
748 - regmap_mmio: it is possible to disable internal locking in regmap by setting
749 .disable_locking and handling the locking in the GPIO driver
750 - Test your driver with the appropriate in-kernel real-time test cases for both
751 level and edge IRQs
752
753 * [1] https://lore.kernel.org/r/1437496011-11486-1-git-send-email-bigeasy@linutronix.de/
754 * [2] https://lore.kernel.org/r/1443209283-20781-2-git-send-email-grygorii.strashko@ti.com
755 * [3] https://lore.kernel.org/r/1443209283-20781-3-git-send-email-grygorii.strashko@ti.com
756
757
758 Requesting self-owned GPIO pins
759 ===============================
760
761 Sometimes it is useful to allow a GPIO chip driver to request its own GPIO
762 descriptors through the gpiolib API. A GPIO driver can use the following
763 functions to request and free descriptors::
764
765 struct gpio_desc *gpiochip_request_own_desc(struct gpio_desc *desc,
766 u16 hwnum,
767 const char *label,
768 enum gpiod_flags flags)
769
770 void gpiochip_free_own_desc(struct gpio_desc *desc)
771
772 Descriptors requested with gpiochip_request_own_desc() must be released with
773 gpiochip_free_own_desc().
774
775 These functions must be used with care since they do not affect module use
776 count. Do not use the functions to request gpio descriptors not owned by the
777 calling driver.
778

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

GPIO driver와 내부 번호 표현

1-51

문서 제목은 `GPIO Driver Interface`이며 GPIO chip driver 작성자를 위한 지침입니다. 모든 GPIO controller driver는 GPIO driver structure가 선언된 header를 include해야 합니다.

#include <linux/gpio/driver.h>

GPIO chip은 하나 이상의 GPIO line을 다룹니다. Line이 General Purpose Input/Output 정의에 맞아야 GPIO입니다. 특정 용도로만 쓰이는 line은 이름에 GPIO가 들어가더라도 GPIO chip이 관리하면 안 됩니다. 반대로 LED driver line이라도 범용 GPIO로 사용할 수 있다면 GPIO chip driver가 관리해야 합니다.

GPIO driver 내부에서 각 line은 hardware number, 즉 `offset`으로 식별합니다. 이 값은 chip이 관리하는 GPIO 수를 n이라고 할 때 0부터 n-1 사이의 고유 번호입니다.

Hardware GPIO number는 hardware와 직관적으로 대응해야 합니다. 예를 들어 32-bit memory-mapped I/O register의 각 bit가 32개 GPIO line 하나씩을 담당한다면 register bit 0..31에 맞춰 hardware offset 0..31을 쓰는 것이 자연스럽습니다.

이 번호는 완전히 내부용이며 특정 GPIO line의 hardware number는 driver 밖에 노출되지 않습니다.

Legacy GPIO interface를 위해 각 line에는 integer GPIO namespace의 global number도 필요합니다. 각 chip은 자동 할당할 수 있는 `base` number를 가지며 line의 global number는 `base + hardware number`입니다. Integer 표현은 deprecated이지만 사용자가 많아 유지해야 합니다.

예를 들어 한 platform은 base 32에서 시작하는 128-line controller로 global GPIO 32-159를 쓸 수 있습니다. 다른 platform은 controller별로 0..63, 64-79를 쓰고 특정 board의 FPGA에 80-95를 줄 수 있습니다. Legacy number는 연속일 필요가 없으며 I2C GPIO expander bank에 2000-2063을 배정할 수도 있습니다.

GPIO line 번호 계층
번호범위·계산노출 범위용도
Hardware offset0..ngpio-1Driver 내부Register bit·pin과 대응
Chip base자동 또는 명시 할당Legacy namespaceGlobal 시작점
Global GPIObase + offsetLegacy consumerDeprecated integer API

Driver 내부 offset과 deprecated global integer 번호의 관계입니다.

Controller driver와 struct gpio_chip

52-89

gpiolib framework는 각 GPIO controller를 `<linux/gpio/driver.h>`에 완전한 정의가 있는 `struct gpio_chip`으로 포장합니다. Driver는 controller type에 공통인 member를 지정해야 합니다.

  • GPIO line direction을 설정하는 method
  • GPIO line value를 읽고 쓰는 method
  • 특정 line의 electrical configuration을 설정하는 method
  • 특정 line과 연결된 IRQ number를 반환하는 method
  • Method 호출이 sleep할 수 있는지를 나타내는 flag
  • Line 식별용 optional line-name array
  • 추가 state를 표시하는 optional debugfs dump method
  • 생략 시 자동 할당되는 optional base number
  • 진단과 platform-data GPIO chip mapping용 optional label

`gpio_chip` 구현은 driver model을 사용해 controller의 여러 instance를 지원하는 것이 좋습니다. 각 `gpio_chip`을 구성한 뒤 `gpiochip_add_data()` 또는 `devm_gpiochip_add_data()`를 호출합니다. GPIO controller 제거는 드물어야 하며 피할 수 없을 때만 `gpiochip_remove()`를 사용합니다.

`gpio_chip`은 흔히 address, power management처럼 GPIO interface에 노출되지 않는 instance별 state를 가진 structure의 일부입니다. Audio codec 같은 chip에는 복잡한 non-GPIO state도 함께 존재합니다.

Debugfs dump method는 보통 요청되지 않은 line을 무시해야 합니다. `gpiochip_is_requested()`는 `NULL` 또는 요청 당시 line과 연결된 label을 반환하므로 이를 사용할 수 있습니다.

실시간 kernel에서 hard IRQ handler 같은 atomic context가 GPIO API를 호출할 수 있어야 한다면 `gpio_chip`의 `.get`, `.set`, direction callback에서 `spinlock_t`나 PM runtime 같은 sleep 가능 API를 사용하면 안 됩니다. 보통은 이런 요구가 없어야 합니다.

gpio_chip 구현 책임
영역대표 member·API주의점
Direction·value.get/.set, direction callbacksAtomic 호출 가능성 검토
Electrical.set_config()Pin control backend 연계 가능
IRQto_irq 또는 gpio_irq_chipgpio_chip과 irq_chip은 직교
Lifecycledevm_gpiochip_add_data()제거는 드물게
Diagnosticsline names, label, debugfs미요청 line은 보통 생략

필수 동작과 optional metadata를 구분합니다.

전기 구성과 debounce

90-131

GPIO line은 `.set_config()` callback으로 여러 electrical operation mode를 구성할 수 있습니다. 현재 API는 debounce, open drain/open source 같은 single-ended mode, pull-up·pull-down resistor enable을 지원합니다.

`.set_config()`는 generic pin control driver와 같은 enumerator와 configuration semantics를 사용합니다. `.set_config()`에 `gpiochip_generic_config()`를 지정하면 `pinctrl_gpio_set_config()`가 호출되고 결국 실제 pin에 가까운 GPIO controller 뒤쪽의 pin-control backend로 전달됩니다. 이 방식으로 pin controller가 GPIO electrical configuration을 관리합니다.

Pin-controller backend를 사용하면 GPIO controller 또는 hardware description에 GPIO line offset과 pin-controller pin number를 연결하는 `GPIO ranges`가 있어야 서로를 정확히 참조할 수 있습니다.

Debounce는 mechanical switch나 button처럼 접점 튐이 발생할 수 있는 pin에 설정합니다. Bouncing은 기계적 이유로 line이 매우 짧은 간격에 high와 low를 오가며, debounce하지 않으면 값이 불안정하거나 IRQ가 반복해서 발생할 수 있습니다.

실제 debounce는 line에 event가 생기면 timer를 시작하고 잠시 기다린 뒤 같은 low 또는 high인지 다시 sampling합니다. 더 정교한 state machine이 안정될 때까지 반복할 수도 있습니다. Configuration은 debounce millisecond 수를 지정하거나, 시간을 조정할 수 없는 hardware에서는 단순 on/off를 지정합니다.

GPIO electrical configuration 전달
Consumer의 electrical mode 요청gpio_chip.set_config()gpiochip_generic_config()pinctrl_gpio_set_config()GPIO range로 offset을 pin에 mappingPin-control backend가 실제 pin 구성

gpio_chip callback에서 실제 pin-control backend까지의 경로입니다.

Debounce 동작
Line 변화 감지Debounce timer 시작설정 시간 대기Line 재-sampling같으면 안정 상태로 승인불안정하면 반복

기계 접점의 일시적 진동을 안정된 값으로 판별합니다.

Open drain·open source와 push-pull

132-228

Open drain(CMOS) 또는 open collector(TTL)는 line을 high로 적극 구동하지 않습니다. Drain 또는 collector를 output으로 제공하되 transistor가 열려 있지 않을 때 external rail에는 high-impedance, 즉 tristate가 나타납니다.

CMOS CONFIGURATION      TTL CONFIGURATION

         ||--- out              +--- out
  in ----||                   |/
         ||--+         in ----|
             |                |\
            GND                 GND

이 구성은 두 가지 목적으로 사용합니다. 첫째는 output silicon보다 높은 logical level에 도달하는 level shifting입니다. 둘째는 I/O line의 inverse wire-OR입니다. 같은 line의 다른 output이 high를 구동 중이어도 어느 한 driving stage가 low로 끌어내릴 수 있습니다. I2C의 SCL과 SDA가 대표적인 wire-OR bus입니다.

두 경우 모두 pull-up resistor가 필요합니다. Rail의 transistor가 적극적으로 low로 끌어내리지 않는 한 resistor가 line을 high 쪽으로 끌어올립니다. Line level은 pull-up resistor의 VDD까지 올라가며 transistor가 지원하는 level보다 높을 수 있어 더 높은 VDD로 level shift됩니다.

Integrated electronics의 output driver stage는 흔히 N-MOS와 P-MOS transistor 하나씩으로 만든 CMOS `totem-pole`입니다. 하나는 line을 high로, 다른 하나는 low로 구동하며 이를 push-pull output이라고 합니다.

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

GPIO output register 등에서 온 원하는 output signal은 `IN`으로 들어옵니다. 입력 분기 직후 P-MOS와 N-MOS를 enable·disable하는 `OD`, `OS` switch는 보통 닫혀 있어 push-pull circuit을 만듭니다.

이 switch를 열면 해당 transistor가 완전히 비활성화됩니다. Totem-pole의 한쪽이 사라져 line을 high 또는 low로 적극 구동하는 대신 high impedance가 됩니다. Software-controlled open drain/source는 보통 이런 방식으로 구현됩니다.

일부 GPIO hardware는 open drain 또는 open source로 고정되어 transistor가 하나뿐입니다. 다른 hardware는 register bit를 바꿔 그림의 `OD` 또는 `OS` switch를 여는 방식으로 mode를 software에서 선택할 수 있습니다.

P-MOS를 disable하면 output은 GND와 high impedance 사이를 오가므로 open drain이 되고 outgoing rail에는 pull-up resistor가 필요합니다. N-MOS를 disable하면 VDD와 high impedance 사이를 오가므로 open source가 되고 pull-down resistor가 필요합니다.

Open drain·open source를 hardware에서 지원하면 `gpio_chip`의 `.set_config()` callback이 generic pinconf packed value를 받아 open drain, open source 또는 push-pull로 설정할 수 있습니다. Machine file이나 다른 hardware description의 `GPIO_OPEN_DRAIN`, `GPIO_OPEN_SOURCE` flag에 응답해 호출됩니다.

Hardware가 이 mode를 지원하지 않으면 GPIO library가 흉내 냅니다. Open-drain line에 low를 출력하면 그대로 low로 구동하지만 high를 출력하면 high를 적극 구동하지 않고 input으로 바꿉니다. Input mode는 high impedance와 같으므로 electrical behavior는 같지만 direction 전환 중 hardware glitch가 생길 수 있습니다.

Open-source emulation도 같은 원리이며, 차이는 low를 적극 구동해야 할 때 output 대신 input으로 전환한다는 점입니다.

GPIO output electrical mode
Mode활성 transistor구동 범위외부 resistor
Push-pullP-MOS + N-MOSGND 또는 VDD 적극 구동보통 불필요
Open drainN-MOS만GND 또는 high impedancePull-up
Open sourceP-MOS만VDD 또는 high impedancePull-down

원문의 transistor 회로를 동작 상태로 구조화했습니다.

Software open-drain emulation
GPIO_OPEN_DRAIN 지정Logical low면 output-lowN-MOS가 low 구동Logical high면 input 전환High impedancePull-up이 high 형성

Hardware mode가 없을 때 direction 전환으로 high impedance를 만듭니다.

Pull-up·pull-down resistor 지원

229-252

GPIO line은 `.set_config()` callback을 통해 software-controlled pull-up 또는 pull-down resistor를 지원할 수 있습니다.

Discrete design에서는 pull-up이나 pull-down resistor를 circuit board에 직접 납땜합니다. Software는 이를 다루거나 model하지 않으며, 이런 line이 open drain 또는 open source로 구성될 가능성만 고려합니다.

`.set_config()` callback은 pull-up·pull-down을 켜거나 끌 뿐 resistance 값의 의미를 알지 못합니다. Register의 enable bit를 바꾸라고 지시하는 수준입니다.

여러 resistance 값을 선택할 수 있는 GPIO line에는 GPIO chip의 `.set_config()`만으로 부족합니다. GPIO chip과 pin controller를 결합해 구현해야 하며, pin controller의 pin-config interface는 더 다양한 electrical property와 여러 pull resistance 값을 처리할 수 있습니다.

Pull resistor 제어 범위
형태Software model적합한 interface
Board 고정 resistor직접 model하지 않음Hardware description 고려
On-chip enable/disable켜기·끄기gpio_chip.set_config()
여러 resistance 값Electrical value 선택GPIO + pin controller

Board 부품, GPIO callback, pin controller가 담당하는 범위입니다.

GPIO driver가 제공하는 IRQ

253-307

GPIO chip이 interrupt도 제공하는 경우가 흔합니다. 대부분 parent interrupt controller에 cascaded되며, 특별한 경우에는 GPIO logic이 SoC primary interrupt controller와 합쳐져 있습니다.

GPIO block의 IRQ 부분은 `<linux/irq.h>`의 `irq_chip`으로 구현하므로 결합 driver는 GPIO와 IRQ 두 subsystem을 동시에 사용합니다.

GPIO+IRQ 결합 driver라도 모든 IRQ consumer는 어느 irqchip에서든 IRQ를 요청할 수 있습니다. 기본 전제는 `gpio_chip`과 `irq_chip`이 직교하며 서로 독립적으로 service를 제공한다는 것입니다.

`gpiod_to_irq()`는 특정 GPIO line의 IRQ를 찾는 편의 function일 뿐입니다. IRQ를 사용하기 전에 이 function이 호출됐다고 의존하면 안 됩니다. GPIO와 `irq_chip` API 각각의 callback에서 hardware를 항상 준비해 즉시 동작 가능한 상태로 만들어야 합니다.

GPIO irqchip은 크게 두 범주입니다. Cascaded interrupt chip은 chip의 enabled GPIO line 중 하나가 발생시키는 공통 interrupt output 하나를 parent controller로 전달합니다. Driver의 irqchip은 GPIO controller register bit를 조사해 발생 line을 찾고, status bit clear 또는 status register read로 acknowledge하며 edge·level sensitivity를 설정합니다.

Hierarchical interrupt chip은 각 GPIO line이 한 단계 위 parent interrupt controller에 전용 IRQ line을 가집니다. 어느 GPIO가 발생했는지 GPIO hardware에 물을 필요는 없지만 acknowledge와 edge sensitivity 같은 구성은 여전히 필요할 수 있습니다.

Real-time compliant GPIO driver는 irqchip 구현에서 `spinlock_t`나 PM runtime 같은 sleep 가능 API를 사용하면 안 됩니다. `spinlock_t`는 `raw_spinlock_t`로 바꿉니다. Sleep 가능 API가 꼭 필요하면 irqchip의 유일한 slowpath인 `.irq_bus_lock()`과 `.irq_bus_unlock()` callback에서 사용하고 필요하면 callback을 추가합니다.

Cascaded와 hierarchical GPIO irqchip
TopologyParent 연결발생 line 판별Driver 작업
CascadedChip당 공통 IRQ 1개GPIO status register 조사Dispatch·ack·type 구성
HierarchicalGPIO line마다 parent IRQParent mapping으로 식별Ack·type 구성

Parent interrupt controller에 연결되는 두 topology입니다.

GPIO와 IRQ service의 독립성
gpio_chip callback이 GPIO 준비irq_chip callback이 IRQ 준비두 subsystem은 독립적으로 service 제공gpiod_to_irq()는 mapping 조회만Consumer는 mapping 후 바로 IRQ 사용

gpiod_to_irq() 호출에 hardware 준비를 의존하지 않는 원칙입니다.

Cascaded GPIO irqchip 세 유형

308-388

Cascaded GPIO irqchip은 보통 세 범주로 나뉩니다.

`CHAINED CASCADED GPIO IRQCHIPS`는 대개 SoC에 내장됩니다. Parent IRQ handler, 보통 system interrupt controller에서 GPIO용 fast IRQ flow handler가 chain으로 즉시 호출되며 IRQ가 disabled된 상태입니다. Handler는 대략 다음 순서를 실행합니다.

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

Chained GPIO irqchip은 callback에서 모든 작업이 바로 일어나므로 보통 `struct gpio_chip`의 `.can_sleep`을 설정할 수 없고 I2C 같은 느린 bus traffic도 사용할 수 없습니다.

-RT에서도 chained IRQ handler는 강제로 threaded되지 않습니다. 따라서 chained handler에서 `spinlock_t`, PM runtime 같은 sleep 가능 API를 사용할 수 없습니다.

Nested threaded GPIO irqchip으로 바꿀 수 없다면 chained IRQ handler를 generic IRQ handler로 변환할 수 있습니다. 그러면 -RT에서는 threaded handler가 되고 non-RT에서는 hard IRQ handler가 됩니다.

`generic_handle_irq()`는 IRQ disabled 상태에서 호출되어야 합니다. 강제로 thread가 된 IRQ handler가 IRQ enabled 상태로 이를 호출하면 IRQ core가 경고하므로 raw lock을 이용한 workaround를 적용할 수 있습니다.

raw_spinlock_t wa_lock;
static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
    unsigned long wa_lock_flags;
    raw_spin_lock_irqsave(&bank->wa_lock, wa_lock_flags);
    generic_handle_irq(irq_find_mapping(bank->chip.irq.domain, bit));
    raw_spin_unlock_irqrestore(&bank->wa_lock, wa_lock_flags);

`GENERIC CHAINED GPIO IRQCHIPS`는 chained handler를 쓰지 않는다는 점만 다릅니다. `request_irq()`로 구성한 generic IRQ handler가 GPIO IRQ를 dispatch합니다.

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

이 handler는 -RT에서 강제로 threaded되므로 IRQ enabled 상태에서 `generic_handle_irq()`를 호출한다는 IRQ core 경고가 생길 수 있습니다. Chained GPIO irqchip과 같은 raw-lock workaround를 적용합니다.

`NESTED THREADED GPIO IRQCHIPS`는 I2C나 SPI처럼 sleep하는 bus 반대편의 off-chip GPIO expander 등에 사용합니다. IRQ status를 읽는 느린 traffic 자체가 다른 IRQ를 일으킬 수 있어 IRQ disabled 상태의 빠른 handler에서 처리할 수 없습니다. 대신 thread를 만들고 driver가 interrupt를 처리할 때까지 parent IRQ line을 mask합니다.

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

Threaded GPIO irqchip은 `struct gpio_chip`의 `.can_sleep`을 true로 설정해 GPIO access가 sleep할 수 있음을 나타냅니다. 이미 sleeping context를 처리하도록 구성되므로 본질적으로 real-time tolerant합니다.

Cascaded GPIO irqchip 유형
유형Handler context대표 dispatchcan_sleep
Chained cascadedIRQ disabled, -RT에서도 hardchained_irq_enter + generic_handle_irq보통 false
Generic chainedrequest_irq, -RT에서 threadedgeneric_handle_irqHardware에 따라
Nested threadedThreaded, parent IRQ maskhandle_nested_irqtrue

실행 context, bus 제약, dispatch primitive를 비교합니다.

Nested threaded GPIO IRQ
Parent IRQ 발생Parent IRQ line maskThreaded handler 실행I2C·SPI로 IRQ status 읽기handle_nested_irq()로 child dispatchParent IRQ unmask

Sleep bus 뒤의 GPIO expander가 interrupt를 처리하는 흐름입니다.

GPIO irqchip infrastructure helper

389-421

GPIO irqchip과 연결된 irqdomain·resource allocation callback의 설정과 관리를 돕는 helper가 있습니다. Kconfig `GPIOLIB_IRQCHIP`을 선택하면 활성화되고 `IRQ_DOMAIN_HIERARCHY`도 선택하면 hierarchical helper까지 제공됩니다.

Interrupt가 GPIO line index와 1:1로 mapping된다는 가정 아래 gpiolib이 상당한 boilerplate를 관리합니다.

.. csv-table::
    :header: GPIO line offset, Hardware IRQ

    0,0
    1,1
    2,2
    ...,...
    ngpio-1, ngpio-1

일부 GPIO line에 대응 IRQ가 없다면 `gpio_irq_chip`의 `valid_mask` bitmask와 `need_valid_mask` flag로 IRQ 연결이 invalid한 line을 mask할 수 있습니다.

권장 설정 방식은 `gpio_chip`을 추가하기 전에 내부의 `struct gpio_irq_chip`을 채우는 것입니다. 그러면 gpiolib이 GPIO 기능을 설정할 때 추가 `irq_chip`도 함께 구성합니다. 이어지는 chained cascaded example에서는 mask/unmask 또는 disable/enable function이 core gpiolib code를 호출해 state를 동기화합니다.

기본 GPIO-IRQ 1:1 mapping
GPIO line offsetHardware IRQ
00
11
22
......
ngpio-1ngpio-1

원문의 CSV 표를 구조화했습니다.

gpio_irq_chip helper 초기화
GPIOLIB_IRQCHIP 선택필요하면 IRQ_DOMAIN_HIERARCHY 선택gpio_irq_chip 채우기valid_mask로 line 제외devm_gpiochip_add_data()gpiolib이 irqdomain 구성

GPIO chip 등록과 동시에 IRQ infrastructure를 만드는 순서입니다.

Chained cascaded helper 예제

422-495

다음 C 예제는 typical state container, immutable `irq_chip`, GPIO core와 mask state를 동기화하는 callback, parent IRQ 한 개를 가진 chained setup을 모두 보여 줍니다. 원문 코드는 식별자와 주석을 포함해 그대로 보존합니다.

.. code-block:: c

  /* 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);

`my_gpio_mask_irq()`는 hardware interrupt를 mask하는 동작 뒤 `gpiochip_disable_irq()`로 core state를 동기화합니다. `my_gpio_unmask_irq()`는 먼저 `gpiochip_enable_irq()`를 호출한 뒤 hardware를 unmask합니다.

`IRQCHIP_IMMUTABLE`과 `GPIOCHIP_IRQ_RESOURCE_HELPERS`가 있는 static const `irq_chip`을 `gpio_irq_chip_set_chip()`으로 연결합니다. Parent handler와 parent IRQ array, default type, `handle_bad_irq`를 지정한 뒤 `devm_gpiochip_add_data()`로 등록합니다.

Helper는 threaded interrupt도 지원하므로 다음 절처럼 interrupt를 별도로 요청할 수 있습니다.

Chained helper 등록 순서
Immutable irq_chip 정의gpio_irq_chip_set_chip()parent_handler 지정parents[0]에 parent IRQ 저장default_type·handle_bad_irq 지정devm_gpiochip_add_data()

예제 코드의 parent IRQ 연결과 GPIO chip 등록 흐름입니다.

Threaded helper 예제

496-571

Threaded 예제도 mask/unmask callback과 immutable `irq_chip` 정의는 chained 예제와 같습니다. 차이는 parent interrupt를 `devm_request_threaded_irq()`로 driver가 직접 요청한다는 점입니다.

.. code-block:: c

  /* 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);

Threaded parent IRQ는 `IRQF_ONESHOT`으로 요청합니다. Driver가 parent IRQ를 직접 처리하도록 `girq->parent_handler = NULL`, `num_parents = 0`, `parents = NULL`로 설정하고 나머지 default type과 child handler를 지정한 뒤 GPIO chip을 등록합니다.

Helper는 hierarchical interrupt controller도 지원하며 다음 절의 전형적인 설정을 사용할 수 있습니다.

Threaded helper 등록 순서
devm_request_threaded_irq(..., IRQF_ONESHOT)Immutable irq_chip 연결parent_handler = NULLnum_parents = 0default_type·handle_bad_irq 지정devm_gpiochip_add_data()

Parent handler를 gpiolib에 넘기지 않고 driver thread가 처리합니다.

Hierarchical helper와 valid mask

572-668

Hierarchical interrupt controller 예제는 dynamic irqchip state container에 `fwnode`를 보관하고 child mask/unmask와 parent mask/unmask를 함께 수행합니다.

.. code-block:: c

  /* 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);

구조는 앞선 예제와 비슷하지만 parent IRQ handler를 제공하지 않습니다. 대신 parent `irqdomain`, hardware용 `fwnode`, child hardware IRQ에서 parent hardware IRQ를 찾는 `.child_to_parent_hwirq()` function을 제공합니다. 필요한 구성 요소를 찾을 때는 kernel tree의 실제 driver 예제를 참고하는 것이 좋습니다.

Helper가 관리하는 IRQ domain에서 특정 GPIO line을 제외하려면 `devm_gpiochip_add_data()` 또는 `gpiochip_add_data()` 전에 gpiochip의 `.irq.need_valid_mask`를 설정합니다. 그러면 chip의 line 수만큼 bit가 설정된 `.irq.valid_mask`가 할당되며 0..n-1 line마다 bit 하나가 대응합니다. Driver는 bit를 clear해 line을 제외하거나 `struct gpio_irq_chip`의 `init_valid_mask()` callback에서 mask를 채울 수 있습니다.

Helper 사용 시 `irqchip`이 초기화되도록 `struct gpio_chip`의 관련 member를 모두 지정해야 합니다. 예를 들어 `.dev`와 `.can_sleep`을 올바르게 설정합니다.

보통 `gpio_irq_chip.handler`는 `handle_bad_irq`로 시작합니다. Cascaded irqchip이라면 controller 지원과 consumer 요청에 따라 irqchip `.set_type()` callback에서 `handle_level_irq()` 또는 `handle_edge_irq()`로 바꿉니다.

Hierarchical GPIO IRQ mapping
gpio_irq_chip_set_chip()fwnode 지정parent_domain 지정child_to_parent_hwirq 지정Child에서 parent hwirq 조회Parent·child mask 동기화

Child GPIO hwirq를 parent irqdomain으로 연결합니다.

IRQ valid mask 적용
등록 전 need_valid_mask 설정ngpio 크기 valid_mask 할당초기 bit 모두 setIRQ 없는 line bit clear또는 init_valid_mask() 사용Clear된 line은 IRQ 연결 금지

IRQ를 지원하지 않는 GPIO line을 domain에서 제외합니다.

IRQ 사용으로 GPIO line 잠그기

669-697

GPIO와 `irq_chip`은 직교하므로 use case가 충돌할 수 있습니다. IRQ에 쓰는 GPIO line은 input이어야 하며 output GPIO에서 interrupt를 발생시키는 것은 의미가 없습니다.

Subsystem 내부에서 특정 GPIO line과 register 같은 resource 사용 주체가 경쟁하면 일부 operation을 거부하고 gpiolib subsystem 내부에서 사용 상태를 추적해야 합니다.

Input GPIO를 IRQ signal로 사용할 때 driver는 다음 function으로 IRQ 사용 상태를 표시합니다.

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

이 lock이 유지되는 동안 non-IRQ GPIO API 사용은 막힙니다. 다음 function으로 GPIO IRQ lock을 해제합니다.

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

GPIO driver 안에 irqchip을 구현할 때 두 function은 보통 irqchip의 `.startup()`과 `.shutdown()` callback에서 호출합니다. Gpiolib irqchip helper를 사용하면 callback이 자동 할당됩니다.

GPIO line의 IRQ 소유권
Line을 input으로 구성irqchip.startup()gpiochip_lock_as_irq()Non-IRQ operation 거부irqchip.shutdown()gpiochip_unlock_as_irq()

Input line을 IRQ resource로 잠그고 다시 해제합니다.

IRQ disable·enable 상태 동기화

698-725

드문 use case에서는 GPIO line을 IRQ input으로 사용하다가 일시적으로 output을 구동한 뒤 다시 interrupt input으로 되돌립니다. CEC(Consumer Electronics Control)가 예입니다.

GPIO가 IRQ signal이면 gpiolib도 IRQ의 enabled·disabled 상태를 알아야 합니다. Driver는 다음 function으로 disabled 상태를 알립니다.

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

IRQ가 disabled된 동안에는 GPIO를 output으로 구동할 수 있습니다. IRQ를 다시 enable할 때는 다음 function을 호출합니다.

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

GPIO driver 안에 irqchip을 구현할 때 이 두 function은 보통 `.irq_disable()`과 `.irq_enable()` callback에서 호출합니다.

irqchip이 `IRQCHIP_IMMUTABLE`을 광고하지 않으면 callback이 자동 할당됩니다. 이 동작은 deprecated이며 kernel에서 제거될 예정입니다.

IRQ line의 일시적 output 전환
IRQ input 사용irq_disable callbackgpiochip_disable_irq()잠시 output 구동다시 input 전환gpiochip_enable_irq()

CEC 같은 경우 gpiolib 상태와 direction을 맞춥니다.

GPIO IRQ chip의 Real-Time 준수

726-757

모든 irqchip provider는 Real-Time preemption을 지원하도록 세심하게 설계해야 합니다. GPIO subsystem의 irqchip도 이를 고려하고 적절히 test해 real-time enabled임을 확인하는 것이 바람직합니다.

앞 절의 real-time 고려 사항에 주의하며 다음 checklist를 따릅니다.

  • `irq_chip` 구현에서 `spinlock_t`를 사용하지 않음
  • Sleep 가능 API를 사용하지 않음. 꼭 필요하면 `.irq_bus_lock()`·`.irq_bus_unlock()`에서 사용
  • Chained handler에서 `spinlock_t`나 sleep 가능 API를 사용하지 않음
  • Generic chained의 `generic_handle_irq()` 호출에 맞는 workaround 적용
  • 가능하면 chained handler를 제거하고 generic IRQ handler 사용
  • `regmap_mmio`는 `.disable_locking`으로 internal lock을 끄고 GPIO driver가 관리 가능
  • Level·edge IRQ 모두 적절한 in-kernel real-time test로 검증

원문은 `raw_spinlock_t` 전환, irqchip slowpath callback, chained handler를 generic handler로 바꾸는 사례를 설명하는 lore.kernel.org reference 세 개를 제공합니다.

* [1] https://lore.kernel.org/r/1437496011-11486-1-git-send-email-bigeasy@linutronix.de/
* [2] https://lore.kernel.org/r/1443209283-20781-2-git-send-email-grygorii.strashko@ti.com
* [3] https://lore.kernel.org/r/1443209283-20781-3-git-send-email-grygorii.strashko@ti.com
Real-Time GPIO irqchip 점검표
영역요구사항
Lockspinlock_t 대신 raw_spinlock_t 또는 driver-managed lock
Sleep APIirq_bus_lock/unlock slowpath에서만
Chained handlerSleep 금지, 가능하면 generic으로 전환
generic_handle_irqIRQ state에 맞는 workaround 검토
검증Level·edge real-time test 모두 실행

Lock, sleep, handler context, test 항목을 정리했습니다.

Driver 자체 소유 GPIO descriptor 요청

758-777

GPIO chip driver가 gpiolib API를 통해 자신의 GPIO descriptor를 요청해야 할 때가 있습니다. 다음 function으로 자체 descriptor를 요청하고 해제할 수 있습니다.

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

void gpiochip_free_own_desc(struct gpio_desc *desc)

`gpiochip_request_own_desc()`로 요청한 descriptor는 반드시 `gpiochip_free_own_desc()`로 해제해야 합니다.

이 function은 module use count에 영향을 주지 않으므로 주의해서 사용해야 합니다. 호출 driver가 소유하지 않은 GPIO descriptor를 요청하는 데 사용하면 안 됩니다.

Self-owned GPIO descriptor lifecycle
호출 driver의 GPIO 소유권 확인gpiochip_request_own_desc()Descriptor 사용Module use count는 증가하지 않음gpiochip_free_own_desc()다른 driver 소유 GPIO에는 사용 금지

GPIO chip driver가 자신의 line을 요청하고 해제하는 규칙입니다.