diff options
Diffstat (limited to 'arch/arm/mach-at91/gpio.c')
-rw-r--r-- | arch/arm/mach-at91/gpio.c | 122 |
1 files changed, 94 insertions, 28 deletions
diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c index ecf6bbb9103a..567df654a2e1 100644 --- a/arch/arm/mach-at91/gpio.c +++ b/arch/arm/mach-at91/gpio.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/irqdomain.h> | 24 | #include <linux/irqdomain.h> |
25 | #include <linux/of_address.h> | 25 | #include <linux/of_address.h> |
26 | #include <linux/of_irq.h> | 26 | #include <linux/of_irq.h> |
27 | #include <linux/of_gpio.h> | ||
27 | 28 | ||
28 | #include <mach/hardware.h> | 29 | #include <mach/hardware.h> |
29 | #include <mach/at91_pio.h> | 30 | #include <mach/at91_pio.h> |
@@ -34,6 +35,7 @@ struct at91_gpio_chip { | |||
34 | struct gpio_chip chip; | 35 | struct gpio_chip chip; |
35 | struct at91_gpio_chip *next; /* Bank sharing same clock */ | 36 | struct at91_gpio_chip *next; /* Bank sharing same clock */ |
36 | int pioc_hwirq; /* PIO bank interrupt identifier on AIC */ | 37 | int pioc_hwirq; /* PIO bank interrupt identifier on AIC */ |
38 | int pioc_virq; /* PIO bank Linux virtual interrupt */ | ||
37 | int pioc_idx; /* PIO bank index */ | 39 | int pioc_idx; /* PIO bank index */ |
38 | void __iomem *regbase; /* PIO bank virtual address */ | 40 | void __iomem *regbase; /* PIO bank virtual address */ |
39 | struct clk *clock; /* associated clock */ | 41 | struct clk *clock; /* associated clock */ |
@@ -292,7 +294,7 @@ static int gpio_irq_set_wake(struct irq_data *d, unsigned state) | |||
292 | else | 294 | else |
293 | wakeups[bank] &= ~mask; | 295 | wakeups[bank] &= ~mask; |
294 | 296 | ||
295 | irq_set_irq_wake(gpio_chip[bank].pioc_hwirq, state); | 297 | irq_set_irq_wake(at91_gpio->pioc_virq, state); |
296 | 298 | ||
297 | return 0; | 299 | return 0; |
298 | } | 300 | } |
@@ -394,12 +396,12 @@ static struct irq_chip gpio_irqchip = { | |||
394 | 396 | ||
395 | static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) | 397 | static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) |
396 | { | 398 | { |
397 | unsigned virq; | ||
398 | struct irq_data *idata = irq_desc_get_irq_data(desc); | 399 | struct irq_data *idata = irq_desc_get_irq_data(desc); |
399 | struct irq_chip *chip = irq_data_get_irq_chip(idata); | 400 | struct irq_chip *chip = irq_data_get_irq_chip(idata); |
400 | struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(idata); | 401 | struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(idata); |
401 | void __iomem *pio = at91_gpio->regbase; | 402 | void __iomem *pio = at91_gpio->regbase; |
402 | u32 isr; | 403 | unsigned long isr; |
404 | int n; | ||
403 | 405 | ||
404 | /* temporarily mask (level sensitive) parent IRQ */ | 406 | /* temporarily mask (level sensitive) parent IRQ */ |
405 | chip->irq_ack(idata); | 407 | chip->irq_ack(idata); |
@@ -417,13 +419,10 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) | |||
417 | continue; | 419 | continue; |
418 | } | 420 | } |
419 | 421 | ||
420 | virq = gpio_to_irq(at91_gpio->chip.base); | 422 | n = find_first_bit(&isr, BITS_PER_LONG); |
421 | 423 | while (n < BITS_PER_LONG) { | |
422 | while (isr) { | 424 | generic_handle_irq(irq_find_mapping(at91_gpio->domain, n)); |
423 | if (isr & 1) | 425 | n = find_next_bit(&isr, BITS_PER_LONG, n + 1); |
424 | generic_handle_irq(virq); | ||
425 | virq++; | ||
426 | isr >>= 1; | ||
427 | } | 426 | } |
428 | } | 427 | } |
429 | chip->irq_unmask(idata); | 428 | chip->irq_unmask(idata); |
@@ -493,23 +492,91 @@ postcore_initcall(at91_gpio_debugfs_init); | |||
493 | /*--------------------------------------------------------------------------*/ | 492 | /*--------------------------------------------------------------------------*/ |
494 | 493 | ||
495 | /* | 494 | /* |
495 | * This lock class tells lockdep that GPIO irqs are in a different | ||
496 | * category than their parents, so it won't report false recursion. | ||
497 | */ | ||
498 | static struct lock_class_key gpio_lock_class; | ||
499 | |||
500 | #if defined(CONFIG_OF) | ||
501 | static int at91_gpio_irq_map(struct irq_domain *h, unsigned int virq, | ||
502 | irq_hw_number_t hw) | ||
503 | { | ||
504 | struct at91_gpio_chip *at91_gpio = h->host_data; | ||
505 | |||
506 | irq_set_lockdep_class(virq, &gpio_lock_class); | ||
507 | |||
508 | /* | ||
509 | * Can use the "simple" and not "edge" handler since it's | ||
510 | * shorter, and the AIC handles interrupts sanely. | ||
511 | */ | ||
512 | irq_set_chip_and_handler(virq, &gpio_irqchip, | ||
513 | handle_simple_irq); | ||
514 | set_irq_flags(virq, IRQF_VALID); | ||
515 | irq_set_chip_data(virq, at91_gpio); | ||
516 | |||
517 | return 0; | ||
518 | } | ||
519 | |||
520 | static struct irq_domain_ops at91_gpio_ops = { | ||
521 | .map = at91_gpio_irq_map, | ||
522 | .xlate = irq_domain_xlate_twocell, | ||
523 | }; | ||
524 | |||
525 | int __init at91_gpio_of_irq_setup(struct device_node *node, | ||
526 | struct device_node *parent) | ||
527 | { | ||
528 | struct at91_gpio_chip *prev = NULL; | ||
529 | int alias_idx = of_alias_get_id(node, "gpio"); | ||
530 | struct at91_gpio_chip *at91_gpio = &gpio_chip[alias_idx]; | ||
531 | |||
532 | /* Disable irqs of this PIO controller */ | ||
533 | __raw_writel(~0, at91_gpio->regbase + PIO_IDR); | ||
534 | |||
535 | /* Setup irq domain */ | ||
536 | at91_gpio->domain = irq_domain_add_linear(node, at91_gpio->chip.ngpio, | ||
537 | &at91_gpio_ops, at91_gpio); | ||
538 | if (!at91_gpio->domain) | ||
539 | panic("at91_gpio.%d: couldn't allocate irq domain (DT).\n", | ||
540 | at91_gpio->pioc_idx); | ||
541 | |||
542 | /* Setup chained handler */ | ||
543 | if (at91_gpio->pioc_idx) | ||
544 | prev = &gpio_chip[at91_gpio->pioc_idx - 1]; | ||
545 | |||
546 | /* The toplevel handler handles one bank of GPIOs, except | ||
547 | * on some SoC it can handles up to three... | ||
548 | * We only set up the handler for the first of the list. | ||
549 | */ | ||
550 | if (prev && prev->next == at91_gpio) | ||
551 | return 0; | ||
552 | |||
553 | at91_gpio->pioc_virq = irq_create_mapping(irq_find_host(parent), | ||
554 | at91_gpio->pioc_hwirq); | ||
555 | irq_set_chip_data(at91_gpio->pioc_virq, at91_gpio); | ||
556 | irq_set_chained_handler(at91_gpio->pioc_virq, gpio_irq_handler); | ||
557 | |||
558 | return 0; | ||
559 | } | ||
560 | #else | ||
561 | int __init at91_gpio_of_irq_setup(struct device_node *node, | ||
562 | struct device_node *parent) | ||
563 | { | ||
564 | return -EINVAL; | ||
565 | } | ||
566 | #endif | ||
567 | |||
568 | /* | ||
496 | * irqdomain initialization: pile up irqdomains on top of AIC range | 569 | * irqdomain initialization: pile up irqdomains on top of AIC range |
497 | */ | 570 | */ |
498 | static void __init at91_gpio_irqdomain(struct at91_gpio_chip *at91_gpio) | 571 | static void __init at91_gpio_irqdomain(struct at91_gpio_chip *at91_gpio) |
499 | { | 572 | { |
500 | int irq_base; | 573 | int irq_base; |
501 | #if defined(CONFIG_OF) | ||
502 | struct device_node *of_node = at91_gpio->chip.of_node; | ||
503 | #else | ||
504 | struct device_node *of_node = NULL; | ||
505 | #endif | ||
506 | 574 | ||
507 | irq_base = irq_alloc_descs(-1, 0, at91_gpio->chip.ngpio, 0); | 575 | irq_base = irq_alloc_descs(-1, 0, at91_gpio->chip.ngpio, 0); |
508 | if (irq_base < 0) | 576 | if (irq_base < 0) |
509 | panic("at91_gpio.%d: error %d: couldn't allocate IRQ numbers.\n", | 577 | panic("at91_gpio.%d: error %d: couldn't allocate IRQ numbers.\n", |
510 | at91_gpio->pioc_idx, irq_base); | 578 | at91_gpio->pioc_idx, irq_base); |
511 | at91_gpio->domain = irq_domain_add_legacy(of_node, | 579 | at91_gpio->domain = irq_domain_add_legacy(NULL, at91_gpio->chip.ngpio, |
512 | at91_gpio->chip.ngpio, | ||
513 | irq_base, 0, | 580 | irq_base, 0, |
514 | &irq_domain_simple_ops, NULL); | 581 | &irq_domain_simple_ops, NULL); |
515 | if (!at91_gpio->domain) | 582 | if (!at91_gpio->domain) |
@@ -518,12 +585,6 @@ static void __init at91_gpio_irqdomain(struct at91_gpio_chip *at91_gpio) | |||
518 | } | 585 | } |
519 | 586 | ||
520 | /* | 587 | /* |
521 | * This lock class tells lockdep that GPIO irqs are in a different | ||
522 | * category than their parents, so it won't report false recursion. | ||
523 | */ | ||
524 | static struct lock_class_key gpio_lock_class; | ||
525 | |||
526 | /* | ||
527 | * Called from the processor-specific init to enable GPIO interrupt support. | 588 | * Called from the processor-specific init to enable GPIO interrupt support. |
528 | */ | 589 | */ |
529 | void __init at91_gpio_irq_setup(void) | 590 | void __init at91_gpio_irq_setup(void) |
@@ -535,8 +596,7 @@ void __init at91_gpio_irq_setup(void) | |||
535 | for (pioc = 0, this = gpio_chip, prev = NULL; | 596 | for (pioc = 0, this = gpio_chip, prev = NULL; |
536 | pioc++ < gpio_banks; | 597 | pioc++ < gpio_banks; |
537 | prev = this, this++) { | 598 | prev = this, this++) { |
538 | unsigned pioc_hwirq = this->pioc_hwirq; | 599 | int offset; |
539 | int offset; | ||
540 | 600 | ||
541 | __raw_writel(~0, this->regbase + PIO_IDR); | 601 | __raw_writel(~0, this->regbase + PIO_IDR); |
542 | 602 | ||
@@ -566,8 +626,9 @@ void __init at91_gpio_irq_setup(void) | |||
566 | if (prev && prev->next == this) | 626 | if (prev && prev->next == this) |
567 | continue; | 627 | continue; |
568 | 628 | ||
569 | irq_set_chip_data(pioc_hwirq, this); | 629 | this->pioc_virq = irq_create_mapping(NULL, this->pioc_hwirq); |
570 | irq_set_chained_handler(pioc_hwirq, gpio_irq_handler); | 630 | irq_set_chip_data(this->pioc_virq, this); |
631 | irq_set_chained_handler(this->pioc_virq, gpio_irq_handler); | ||
571 | } | 632 | } |
572 | pr_info("AT91: %d gpio irqs in %d banks\n", gpio_irqnbr, gpio_banks); | 633 | pr_info("AT91: %d gpio irqs in %d banks\n", gpio_irqnbr, gpio_banks); |
573 | } | 634 | } |
@@ -645,7 +706,12 @@ static void at91_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip) | |||
645 | static int at91_gpiolib_to_irq(struct gpio_chip *chip, unsigned offset) | 706 | static int at91_gpiolib_to_irq(struct gpio_chip *chip, unsigned offset) |
646 | { | 707 | { |
647 | struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip); | 708 | struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip); |
648 | int virq = irq_find_mapping(at91_gpio->domain, offset); | 709 | int virq; |
710 | |||
711 | if (offset < chip->ngpio) | ||
712 | virq = irq_create_mapping(at91_gpio->domain, offset); | ||
713 | else | ||
714 | virq = -ENXIO; | ||
649 | 715 | ||
650 | dev_dbg(chip->dev, "%s: request IRQ for GPIO %d, return %d\n", | 716 | dev_dbg(chip->dev, "%s: request IRQ for GPIO %d, return %d\n", |
651 | chip->label, offset + chip->base, virq); | 717 | chip->label, offset + chip->base, virq); |