aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
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
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')
-rw-r--r--arch/arm/mach-at91/board-dt.c11
-rw-r--r--arch/arm/mach-at91/generic.h6
-rw-r--r--arch/arm/mach-at91/gpio.c122
-rw-r--r--arch/arm/mach-at91/irq.c90
4 files changed, 168 insertions, 61 deletions
diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c
index 96d9a21dab68..acbe23c5b260 100644
--- a/arch/arm/mach-at91/board-dt.c
+++ b/arch/arm/mach-at91/board-dt.c
@@ -15,6 +15,8 @@
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/gpio.h> 17#include <linux/gpio.h>
18#include <linux/of.h>
19#include <linux/of_irq.h>
18#include <linux/of_platform.h> 20#include <linux/of_platform.h>
19 21
20#include <mach/hardware.h> 22#include <mach/hardware.h>
@@ -80,9 +82,16 @@ static void __init ek_add_device_nand(void)
80 at91_add_device_nand(&ek_nand_data); 82 at91_add_device_nand(&ek_nand_data);
81} 83}
82 84
85static const struct of_device_id irq_of_match[] __initconst = {
86
87 { .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init },
88 { .compatible = "atmel,at91rm9200-gpio", .data = at91_gpio_of_irq_setup },
89 { /*sentinel*/ }
90};
91
83static void __init at91_dt_init_irq(void) 92static void __init at91_dt_init_irq(void)
84{ 93{
85 at91_init_irq_default(); 94 of_irq_init(irq_of_match);
86} 95}
87 96
88static void __init at91_dt_device_init(void) 97static void __init at91_dt_device_init(void)
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index 4cad85e57470..459f01a4a546 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -9,6 +9,7 @@
9 */ 9 */
10 10
11#include <linux/clkdev.h> 11#include <linux/clkdev.h>
12#include <linux/of.h>
12 13
13 /* Map io */ 14 /* Map io */
14extern void __init at91_map_io(void); 15extern void __init at91_map_io(void);
@@ -25,6 +26,9 @@ extern void __init at91_init_irq_default(void);
25extern void __init at91_init_interrupts(unsigned int priority[]); 26extern void __init at91_init_interrupts(unsigned int priority[]);
26extern void __init at91x40_init_interrupts(unsigned int priority[]); 27extern void __init at91x40_init_interrupts(unsigned int priority[]);
27extern void __init at91_aic_init(unsigned int priority[]); 28extern void __init at91_aic_init(unsigned int priority[]);
29extern int __init at91_aic_of_init(struct device_node *node,
30 struct device_node *parent);
31
28 32
29 /* Timer */ 33 /* Timer */
30struct sys_timer; 34struct sys_timer;
@@ -84,5 +88,7 @@ struct at91_gpio_bank {
84}; 88};
85extern void __init at91_gpio_init(struct at91_gpio_bank *, int nr_banks); 89extern void __init at91_gpio_init(struct at91_gpio_bank *, int nr_banks);
86extern void __init at91_gpio_irq_setup(void); 90extern void __init at91_gpio_irq_setup(void);
91extern int __init at91_gpio_of_irq_setup(struct device_node *node,
92 struct device_node *parent);
87 93
88extern int at91_extern_irq; 94extern int at91_extern_irq;
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);
diff --git a/arch/arm/mach-at91/irq.c b/arch/arm/mach-at91/irq.c
index 46682fafa96f..cfcfcbe36269 100644
--- a/arch/arm/mach-at91/irq.c
+++ b/arch/arm/mach-at91/irq.c
@@ -135,27 +135,70 @@ static struct irq_chip at91_aic_chip = {
135 .irq_set_wake = at91_aic_set_wake, 135 .irq_set_wake = at91_aic_set_wake,
136}; 136};
137 137
138static void __init at91_aic_hw_init(unsigned int spu_vector)
139{
140 int i;
141
142 /*
143 * Perform 8 End Of Interrupt Command to make sure AIC
144 * will not Lock out nIRQ
145 */
146 for (i = 0; i < 8; i++)
147 at91_aic_write(AT91_AIC_EOICR, 0);
148
149 /*
150 * Spurious Interrupt ID in Spurious Vector Register.
151 * When there is no current interrupt, the IRQ Vector Register
152 * reads the value stored in AIC_SPU
153 */
154 at91_aic_write(AT91_AIC_SPU, spu_vector);
155
156 /* No debugging in AIC: Debug (Protect) Control Register */
157 at91_aic_write(AT91_AIC_DCR, 0);
158
159 /* Disable and clear all interrupts initially */
160 at91_aic_write(AT91_AIC_IDCR, 0xFFFFFFFF);
161 at91_aic_write(AT91_AIC_ICCR, 0xFFFFFFFF);
162}
163
138#if defined(CONFIG_OF) 164#if defined(CONFIG_OF)
139static int __init __at91_aic_of_init(struct device_node *node, 165static int at91_aic_irq_map(struct irq_domain *h, unsigned int virq,
140 struct device_node *parent) 166 irq_hw_number_t hw)
141{ 167{
142 at91_aic_base = of_iomap(node, 0); 168 /* Put virq number in Source Vector Register */
143 at91_aic_np = node; 169 at91_aic_write(AT91_AIC_SVR(hw), virq);
170
171 /* Active Low interrupt, without priority */
172 at91_aic_write(AT91_AIC_SMR(hw), AT91_AIC_SRCTYPE_LOW);
173
174 irq_set_chip_and_handler(virq, &at91_aic_chip, handle_level_irq);
175 set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
144 176
145 return 0; 177 return 0;
146} 178}
147 179
148static const struct of_device_id aic_ids[] __initconst = { 180static struct irq_domain_ops at91_aic_irq_ops = {
149 { .compatible = "atmel,at91rm9200-aic", .data = __at91_aic_of_init }, 181 .map = at91_aic_irq_map,
150 { /*sentinel*/ } 182 .xlate = irq_domain_xlate_twocell,
151}; 183};
152 184
153static void __init at91_aic_of_init(void) 185int __init at91_aic_of_init(struct device_node *node,
186 struct device_node *parent)
154{ 187{
155 of_irq_init(aic_ids); 188 at91_aic_base = of_iomap(node, 0);
189 at91_aic_np = node;
190
191 at91_aic_domain = irq_domain_add_linear(at91_aic_np, NR_AIC_IRQS,
192 &at91_aic_irq_ops, NULL);
193 if (!at91_aic_domain)
194 panic("Unable to add AIC irq domain (DT)\n");
195
196 irq_set_default_host(at91_aic_domain);
197
198 at91_aic_hw_init(NR_AIC_IRQS);
199
200 return 0;
156} 201}
157#else
158static void __init at91_aic_of_init(void) {}
159#endif 202#endif
160 203
161/* 204/*
@@ -166,11 +209,7 @@ void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS])
166 unsigned int i; 209 unsigned int i;
167 int irq_base; 210 int irq_base;
168 211
169 if (of_have_populated_dt()) 212 at91_aic_base = ioremap(AT91_AIC, 512);
170 at91_aic_of_init();
171 else
172 at91_aic_base = ioremap(AT91_AIC, 512);
173
174 if (!at91_aic_base) 213 if (!at91_aic_base)
175 panic("Unable to ioremap AIC registers\n"); 214 panic("Unable to ioremap AIC registers\n");
176 215
@@ -187,6 +226,8 @@ void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS])
187 if (!at91_aic_domain) 226 if (!at91_aic_domain)
188 panic("Unable to add AIC irq domain\n"); 227 panic("Unable to add AIC irq domain\n");
189 228
229 irq_set_default_host(at91_aic_domain);
230
190 /* 231 /*
191 * The IVR is used by macro get_irqnr_and_base to read and verify. 232 * The IVR is used by macro get_irqnr_and_base to read and verify.
192 * The irq number is NR_AIC_IRQS when a spurious interrupt has occurred. 233 * The irq number is NR_AIC_IRQS when a spurious interrupt has occurred.
@@ -199,22 +240,7 @@ void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS])
199 240
200 irq_set_chip_and_handler(i, &at91_aic_chip, handle_level_irq); 241 irq_set_chip_and_handler(i, &at91_aic_chip, handle_level_irq);
201 set_irq_flags(i, IRQF_VALID | IRQF_PROBE); 242 set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
202
203 /* Perform 8 End Of Interrupt Command to make sure AIC will not Lock out nIRQ */
204 if (i < 8)
205 at91_aic_write(AT91_AIC_EOICR, 0);
206 } 243 }
207 244
208 /* 245 at91_aic_hw_init(NR_AIC_IRQS);
209 * Spurious Interrupt ID in Spurious Vector Register is NR_AIC_IRQS
210 * When there is no current interrupt, the IRQ Vector Register reads the value stored in AIC_SPU
211 */
212 at91_aic_write(AT91_AIC_SPU, NR_AIC_IRQS);
213
214 /* No debugging in AIC: Debug (Protect) Control Register */
215 at91_aic_write(AT91_AIC_DCR, 0);
216
217 /* Disable and clear all interrupts initially */
218 at91_aic_write(AT91_AIC_IDCR, 0xFFFFFFFF);
219 at91_aic_write(AT91_AIC_ICCR, 0xFFFFFFFF);
220} 246}