aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-at91/gpio.c
diff options
context:
space:
mode:
authorNicolas Ferre <nicolas.ferre@atmel.com>2012-02-14 12:08:14 -0500
committerNicolas Ferre <nicolas.ferre@atmel.com>2012-03-01 07:29:03 -0500
commit8014d6f4dd074d4d248d3de7f63348fa2568476b (patch)
tree7803070e93c4955e7b37eb4f4e81e4d1411aeb98 /arch/arm/mach-at91/gpio.c
parent34bc485ca143c4773fc2afbbeb41e50f86445d0d (diff)
ARM: at91: AIC and GPIO IRQ device tree initialization
Both AIC and GPIO controllers are now using the standard of_irq_init() function to initialize IRQs in case of DT use. The DT specific initialization functions are now separated from the non-DT case and are now using "linear" irq domains. The .map() irqdomain operation is responsible for positioning the IRQ handlers. In AIC case, the Linux IRQ number is directly programmed in the hardware to avoid an additional reverse mapping operation. The AIC position its irq domain as the "default" irq domain. For DT case, the priority is not yet filled in the SMR. It will be the subject of another patch. Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Diffstat (limited to 'arch/arm/mach-at91/gpio.c')
-rw-r--r--arch/arm/mach-at91/gpio.c122
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
395static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) 397static 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 */
498static struct lock_class_key gpio_lock_class;
499
500#if defined(CONFIG_OF)
501static 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
520static struct irq_domain_ops at91_gpio_ops = {
521 .map = at91_gpio_irq_map,
522 .xlate = irq_domain_xlate_twocell,
523};
524
525int __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
561int __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 */
498static void __init at91_gpio_irqdomain(struct at91_gpio_chip *at91_gpio) 571static 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 */
524static 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 */
529void __init at91_gpio_irq_setup(void) 590void __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)
645static int at91_gpiolib_to_irq(struct gpio_chip *chip, unsigned offset) 706static 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);