aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorPhil Edworthy <phil.edworthy@renesas.com>2018-04-26 12:19:47 -0400
committerLinus Walleij <linus.walleij@linaro.org>2018-05-16 08:35:24 -0400
commite6ca26abd37606ba4864f20c85d3fe4a2173b93f (patch)
tree18cab27e25f3380c1f300904034a6823dabd8ec9 /drivers/gpio
parent413f9e991896a98c03da6b3c43dc7791a4d28d9a (diff)
gpio: dwapb: Add support for 1 interrupt per port A GPIO
The DesignWare GPIO IP can be configured for either 1 interrupt or 1 per GPIO in port A, but the driver currently only supports 1 interrupt. See the DesignWare DW_apb_gpio Databook description of the 'GPIO_INTR_IO' parameter. This change allows the driver to work with up to 32 interrupts, it will get as many interrupts as specified in the DT 'interrupts' property. It doesn't do anything clever with the different interrupts, it just calls the same handler used for single interrupt hardware. ACPI companion code provided by Hoan Tran <hotran@apm.com>. This was tested on X-Gene by Hoan. Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com> Reviewed-by: Rob Herring <robh@kernel.org> Acked-by: Lee Jones <lee.jones@linaro.org> Acked-by: Hoan Tran <hotran@apm.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpio-dwapb.c46
1 files changed, 37 insertions, 9 deletions
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index 226977f78482..7dcd06b11570 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -441,14 +441,19 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
441 irq_gc->chip_types[1].handler = handle_edge_irq; 441 irq_gc->chip_types[1].handler = handle_edge_irq;
442 442
443 if (!pp->irq_shared) { 443 if (!pp->irq_shared) {
444 irq_set_chained_handler_and_data(pp->irq, dwapb_irq_handler, 444 int i;
445 gpio); 445
446 for (i = 0; i < pp->ngpio; i++) {
447 if (pp->irq[i])
448 irq_set_chained_handler_and_data(pp->irq[i],
449 dwapb_irq_handler, gpio);
450 }
446 } else { 451 } else {
447 /* 452 /*
448 * Request a shared IRQ since where MFD would have devices 453 * Request a shared IRQ since where MFD would have devices
449 * using the same irq pin 454 * using the same irq pin
450 */ 455 */
451 err = devm_request_irq(gpio->dev, pp->irq, 456 err = devm_request_irq(gpio->dev, pp->irq[0],
452 dwapb_irq_handler_mfd, 457 dwapb_irq_handler_mfd,
453 IRQF_SHARED, "gpio-dwapb-mfd", gpio); 458 IRQF_SHARED, "gpio-dwapb-mfd", gpio);
454 if (err) { 459 if (err) {
@@ -524,7 +529,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
524 if (pp->idx == 0) 529 if (pp->idx == 0)
525 port->gc.set_config = dwapb_gpio_set_config; 530 port->gc.set_config = dwapb_gpio_set_config;
526 531
527 if (pp->irq) 532 if (pp->has_irq)
528 dwapb_configure_irqs(gpio, port, pp); 533 dwapb_configure_irqs(gpio, port, pp);
529 534
530 err = gpiochip_add_data(&port->gc, port); 535 err = gpiochip_add_data(&port->gc, port);
@@ -535,7 +540,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
535 port->is_registered = true; 540 port->is_registered = true;
536 541
537 /* Add GPIO-signaled ACPI event support */ 542 /* Add GPIO-signaled ACPI event support */
538 if (pp->irq) 543 if (pp->has_irq)
539 acpi_gpiochip_request_interrupts(&port->gc); 544 acpi_gpiochip_request_interrupts(&port->gc);
540 545
541 return err; 546 return err;
@@ -601,13 +606,36 @@ dwapb_gpio_get_pdata(struct device *dev)
601 if (dev->of_node && pp->idx == 0 && 606 if (dev->of_node && pp->idx == 0 &&
602 fwnode_property_read_bool(fwnode, 607 fwnode_property_read_bool(fwnode,
603 "interrupt-controller")) { 608 "interrupt-controller")) {
604 pp->irq = irq_of_parse_and_map(to_of_node(fwnode), 0); 609 struct device_node *np = to_of_node(fwnode);
605 if (!pp->irq) 610 unsigned int j;
611
612 /*
613 * The IP has configuration options to allow a single
614 * combined interrupt or one per gpio. If one per gpio,
615 * some might not be used.
616 */
617 for (j = 0; j < pp->ngpio; j++) {
618 int irq = of_irq_get(np, j);
619 if (irq < 0)
620 continue;
621
622 pp->irq[j] = irq;
623 pp->has_irq = true;
624 }
625
626 if (!pp->has_irq)
606 dev_warn(dev, "no irq for port%d\n", pp->idx); 627 dev_warn(dev, "no irq for port%d\n", pp->idx);
607 } 628 }
608 629
609 if (has_acpi_companion(dev) && pp->idx == 0) 630 if (has_acpi_companion(dev) && pp->idx == 0) {
610 pp->irq = platform_get_irq(to_platform_device(dev), 0); 631 unsigned int j;
632
633 for (j = 0; j < pp->ngpio; j++) {
634 pp->irq[j] = platform_get_irq(to_platform_device(dev), j);
635 if (pp->irq[j])
636 pp->has_irq = true;
637 }
638 }
611 639
612 pp->irq_shared = false; 640 pp->irq_shared = false;
613 pp->gpio_base = -1; 641 pp->gpio_base = -1;