Skip to content

Commit 86bfb91

Browse files
committed
Merge branch 'irq/gpio-immutable' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into gpio/for-next
This pulls in changes improving the handling of immutable irqchips in core gpiolib and several drivers.
2 parents 7f42aa7 + 5644b66 commit 86bfb91

File tree

11 files changed

+293
-90
lines changed

11 files changed

+293
-90
lines changed

Documentation/driver-api/gpio/driver.rst

Lines changed: 142 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -417,30 +417,66 @@ struct gpio_irq_chip inside struct gpio_chip before adding the gpio_chip.
417417
If you do this, the additional irq_chip will be set up by gpiolib at the
418418
same time as setting up the rest of the GPIO functionality. The following
419419
is a typical example of a chained cascaded interrupt handler using
420-
the gpio_irq_chip:
420+
the gpio_irq_chip. Note how the mask/unmask (or disable/enable) functions
421+
call into the core gpiolib code:
421422

422423
.. code-block:: c
423424
424-
/* Typical state container with dynamic irqchip */
425+
/* Typical state container */
425426
struct my_gpio {
426427
struct gpio_chip gc;
427-
struct irq_chip irq;
428+
};
429+
430+
static void my_gpio_mask_irq(struct irq_data *d)
431+
{
432+
struct gpio_chip *gc = irq_desc_get_handler_data(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, d->hwirq);
441+
}
442+
443+
static void my_gpio_unmask_irq(struct irq_data *d)
444+
{
445+
struct gpio_chip *gc = irq_desc_get_handler_data(d);
446+
447+
gpiochip_enable_irq(gc, d->hwirq);
448+
449+
/*
450+
* Perform any necessary action to unmask the interrupt,
451+
* after having called into the core code to synchronise
452+
* the state.
453+
*/
454+
}
455+
456+
/*
457+
* Statically populate the irqchip. Note that it is made const
458+
* (further indicated by the IRQCHIP_IMMUTABLE flag), and that
459+
* the GPIOCHIP_IRQ_RESOURCE_HELPER macro adds some extra
460+
* callbacks to the structure.
461+
*/
462+
static const struct irq_chip my_gpio_irq_chip = {
463+
.name = "my_gpio_irq",
464+
.irq_ack = my_gpio_ack_irq,
465+
.irq_mask = my_gpio_mask_irq,
466+
.irq_unmask = my_gpio_unmask_irq,
467+
.irq_set_type = my_gpio_set_irq_type,
468+
.flags = IRQCHIP_IMMUTABLE,
469+
/* Provide the gpio resource callbacks */
470+
GPIOCHIP_IRQ_RESOURCE_HELPERS,
428471
};
429472
430473
int irq; /* from platform etc */
431474
struct my_gpio *g;
432475
struct gpio_irq_chip *girq;
433476
434-
/* Set up the irqchip dynamically */
435-
g->irq.name = "my_gpio_irq";
436-
g->irq.irq_ack = my_gpio_ack_irq;
437-
g->irq.irq_mask = my_gpio_mask_irq;
438-
g->irq.irq_unmask = my_gpio_unmask_irq;
439-
g->irq.irq_set_type = my_gpio_set_irq_type;
440-
441477
/* Get a pointer to the gpio_irq_chip */
442478
girq = &g->gc.irq;
443-
girq->chip = &g->irq;
479+
gpio_irq_chip_set_chip(girq, &my_gpio_irq_chip);
444480
girq->parent_handler = ftgpio_gpio_irq_handler;
445481
girq->num_parents = 1;
446482
girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents),
@@ -458,31 +494,66 @@ the interrupt separately and go with it:
458494

459495
.. code-block:: c
460496
461-
/* Typical state container with dynamic irqchip */
497+
/* Typical state container */
462498
struct my_gpio {
463499
struct gpio_chip gc;
464-
struct irq_chip irq;
500+
};
501+
502+
static void my_gpio_mask_irq(struct irq_data *d)
503+
{
504+
struct gpio_chip *gc = irq_desc_get_handler_data(d);
505+
506+
/*
507+
* Perform any necessary action to mask the interrupt,
508+
* and then call into the core code to synchronise the
509+
* state.
510+
*/
511+
512+
gpiochip_disable_irq(gc, d->hwirq);
513+
}
514+
515+
static void my_gpio_unmask_irq(struct irq_data *d)
516+
{
517+
struct gpio_chip *gc = irq_desc_get_handler_data(d);
518+
519+
gpiochip_enable_irq(gc, d->hwirq);
520+
521+
/*
522+
* Perform any necessary action to unmask the interrupt,
523+
* after having called into the core code to synchronise
524+
* the state.
525+
*/
526+
}
527+
528+
/*
529+
* Statically populate the irqchip. Note that it is made const
530+
* (further indicated by the IRQCHIP_IMMUTABLE flag), and that
531+
* the GPIOCHIP_IRQ_RESOURCE_HELPER macro adds some extra
532+
* callbacks to the structure.
533+
*/
534+
static const struct irq_chip my_gpio_irq_chip = {
535+
.name = "my_gpio_irq",
536+
.irq_ack = my_gpio_ack_irq,
537+
.irq_mask = my_gpio_mask_irq,
538+
.irq_unmask = my_gpio_unmask_irq,
539+
.irq_set_type = my_gpio_set_irq_type,
540+
.flags = IRQCHIP_IMMUTABLE,
541+
/* Provide the gpio resource callbacks */
542+
GPIOCHIP_IRQ_RESOURCE_HELPERS,
465543
};
466544
467545
int irq; /* from platform etc */
468546
struct my_gpio *g;
469547
struct gpio_irq_chip *girq;
470548
471-
/* Set up the irqchip dynamically */
472-
g->irq.name = "my_gpio_irq";
473-
g->irq.irq_ack = my_gpio_ack_irq;
474-
g->irq.irq_mask = my_gpio_mask_irq;
475-
g->irq.irq_unmask = my_gpio_unmask_irq;
476-
g->irq.irq_set_type = my_gpio_set_irq_type;
477-
478549
ret = devm_request_threaded_irq(dev, irq, NULL,
479550
irq_thread_fn, IRQF_ONESHOT, "my-chip", g);
480551
if (ret < 0)
481552
return ret;
482553
483554
/* Get a pointer to the gpio_irq_chip */
484555
girq = &g->gc.irq;
485-
girq->chip = &g->irq;
556+
gpio_irq_chip_set_chip(girq, &my_gpio_irq_chip);
486557
/* This will let us handle the parent IRQ in the driver */
487558
girq->parent_handler = NULL;
488559
girq->num_parents = 0;
@@ -500,24 +571,61 @@ In this case the typical set-up will look like this:
500571
/* Typical state container with dynamic irqchip */
501572
struct my_gpio {
502573
struct gpio_chip gc;
503-
struct irq_chip irq;
504574
struct fwnode_handle *fwnode;
505575
};
506576
507-
int irq; /* from platform etc */
577+
static void my_gpio_mask_irq(struct irq_data *d)
578+
{
579+
struct gpio_chip *gc = irq_desc_get_handler_data(d);
580+
581+
/*
582+
* Perform any necessary action to mask the interrupt,
583+
* and then call into the core code to synchronise the
584+
* state.
585+
*/
586+
587+
gpiochip_disable_irq(gc, d->hwirq);
588+
irq_mask_mask_parent(d);
589+
}
590+
591+
static void my_gpio_unmask_irq(struct irq_data *d)
592+
{
593+
struct gpio_chip *gc = irq_desc_get_handler_data(d);
594+
595+
gpiochip_enable_irq(gc, d->hwirq);
596+
597+
/*
598+
* Perform any necessary action to unmask the interrupt,
599+
* after having called into the core code to synchronise
600+
* the state.
601+
*/
602+
603+
irq_mask_unmask_parent(d);
604+
}
605+
606+
/*
607+
* Statically populate the irqchip. Note that it is made const
608+
* (further indicated by the IRQCHIP_IMMUTABLE flag), and that
609+
* the GPIOCHIP_IRQ_RESOURCE_HELPER macro adds some extra
610+
* callbacks to the structure.
611+
*/
612+
static const struct irq_chip my_gpio_irq_chip = {
613+
.name = "my_gpio_irq",
614+
.irq_ack = my_gpio_ack_irq,
615+
.irq_mask = my_gpio_mask_irq,
616+
.irq_unmask = my_gpio_unmask_irq,
617+
.irq_set_type = my_gpio_set_irq_type,
618+
.flags = IRQCHIP_IMMUTABLE,
619+
/* Provide the gpio resource callbacks */
620+
GPIOCHIP_IRQ_RESOURCE_HELPERS,
621+
};
622+
508623
struct my_gpio *g;
509624
struct gpio_irq_chip *girq;
510625
511-
/* Set up the irqchip dynamically */
512-
g->irq.name = "my_gpio_irq";
513-
g->irq.irq_ack = my_gpio_ack_irq;
514-
g->irq.irq_mask = my_gpio_mask_irq;
515-
g->irq.irq_unmask = my_gpio_unmask_irq;
516-
g->irq.irq_set_type = my_gpio_set_irq_type;
517-
518626
/* Get a pointer to the gpio_irq_chip */
519627
girq = &g->gc.irq;
520-
girq->chip = &g->irq;
628+
gpio_irq_chip_set_chip(girq, &my_gpio_irq_chip);
521629
girq->default_type = IRQ_TYPE_NONE;
522630
girq->handler = handle_bad_irq;
523631
girq->fwnode = g->fwnode;
@@ -605,8 +713,9 @@ When implementing an irqchip inside a GPIO driver, these two functions should
605713
typically be called in the .irq_disable() and .irq_enable() callbacks from the
606714
irqchip.
607715

608-
When using the gpiolib irqchip helpers, these callbacks are automatically
609-
assigned.
716+
When IRQCHIP_IMMUTABLE is not advertised by the irqchip, these callbacks
717+
are automatically assigned. This behaviour is deprecated and on its way
718+
to be removed from the kernel.
610719

611720

612721
Real-Time compliance for GPIO IRQ chips

drivers/gpio/TODO

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,3 +178,22 @@ discussed but the idea is to provide a low-level access point
178178
for debugging and hacking and to expose all lines without the
179179
need of any exporting. Also provide ample ammunition to shoot
180180
oneself in the foot, because this is debugfs after all.
181+
182+
183+
Moving over to immutable irq_chip structures
184+
185+
Most of the gpio chips implementing interrupt support rely on gpiolib
186+
intercepting some of the irq_chip callbacks, preventing the structures
187+
from being made read-only and forcing duplication of structures that
188+
should otherwise be unique.
189+
190+
The solution is to call into the gpiolib code when needed (resource
191+
management, enable/disable or unmask/mask callbacks), and to let the
192+
core code know about that by exposing a flag (IRQCHIP_IMMUTABLE) in
193+
the irq_chip structure. The irq_chip structure can then be made unique
194+
and const.
195+
196+
A small number of drivers have been converted (pl061, tegra186, msm,
197+
amd, apple), and can be used as examples of how to proceed with this
198+
conversion. Note that drivers using the generic irqchip framework
199+
cannot be converted yet, but watch this space!

drivers/gpio/gpio-pl061.c

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ struct pl061 {
5252

5353
void __iomem *base;
5454
struct gpio_chip gc;
55-
struct irq_chip irq_chip;
5655
int parent_irq;
5756

5857
#ifdef CONFIG_PM
@@ -241,6 +240,8 @@ static void pl061_irq_mask(struct irq_data *d)
241240
gpioie = readb(pl061->base + GPIOIE) & ~mask;
242241
writeb(gpioie, pl061->base + GPIOIE);
243242
raw_spin_unlock(&pl061->lock);
243+
244+
gpiochip_disable_irq(gc, d->hwirq);
244245
}
245246

246247
static void pl061_irq_unmask(struct irq_data *d)
@@ -250,6 +251,8 @@ static void pl061_irq_unmask(struct irq_data *d)
250251
u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
251252
u8 gpioie;
252253

254+
gpiochip_enable_irq(gc, d->hwirq);
255+
253256
raw_spin_lock(&pl061->lock);
254257
gpioie = readb(pl061->base + GPIOIE) | mask;
255258
writeb(gpioie, pl061->base + GPIOIE);
@@ -283,6 +286,24 @@ static int pl061_irq_set_wake(struct irq_data *d, unsigned int state)
283286
return irq_set_irq_wake(pl061->parent_irq, state);
284287
}
285288

289+
static void pl061_irq_print_chip(struct irq_data *data, struct seq_file *p)
290+
{
291+
struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
292+
293+
seq_printf(p, dev_name(gc->parent));
294+
}
295+
296+
static const struct irq_chip pl061_irq_chip = {
297+
.irq_ack = pl061_irq_ack,
298+
.irq_mask = pl061_irq_mask,
299+
.irq_unmask = pl061_irq_unmask,
300+
.irq_set_type = pl061_irq_type,
301+
.irq_set_wake = pl061_irq_set_wake,
302+
.irq_print_chip = pl061_irq_print_chip,
303+
.flags = IRQCHIP_IMMUTABLE,
304+
GPIOCHIP_IRQ_RESOURCE_HELPERS,
305+
};
306+
286307
static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
287308
{
288309
struct device *dev = &adev->dev;
@@ -315,21 +336,14 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
315336
/*
316337
* irq_chip support
317338
*/
318-
pl061->irq_chip.name = dev_name(dev);
319-
pl061->irq_chip.irq_ack = pl061_irq_ack;
320-
pl061->irq_chip.irq_mask = pl061_irq_mask;
321-
pl061->irq_chip.irq_unmask = pl061_irq_unmask;
322-
pl061->irq_chip.irq_set_type = pl061_irq_type;
323-
pl061->irq_chip.irq_set_wake = pl061_irq_set_wake;
324-
325339
writeb(0, pl061->base + GPIOIE); /* disable irqs */
326340
irq = adev->irq[0];
327341
if (!irq)
328342
dev_warn(&adev->dev, "IRQ support disabled\n");
329343
pl061->parent_irq = irq;
330344

331345
girq = &pl061->gc.irq;
332-
girq->chip = &pl061->irq_chip;
346+
gpio_irq_chip_set_chip(girq, &pl061_irq_chip);
333347
girq->parent_handler = pl061_irq_handler;
334348
girq->num_parents = 1;
335349
girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents),

0 commit comments

Comments
 (0)