aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/boot/dts/at91sam9g20.dtsi18
-rw-r--r--arch/arm/boot/dts/at91sam9g45.dtsi16
-rw-r--r--arch/arm/mach-at91/irq.c74
4 files changed, 79 insertions, 30 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 92c9c79c140c..cabd8f556a1f 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -322,6 +322,7 @@ config ARCH_AT91
322 select ARCH_REQUIRE_GPIOLIB 322 select ARCH_REQUIRE_GPIOLIB
323 select HAVE_CLK 323 select HAVE_CLK
324 select CLKDEV_LOOKUP 324 select CLKDEV_LOOKUP
325 select IRQ_DOMAIN
325 help 326 help
326 This enables support for systems based on the Atmel AT91RM9200, 327 This enables support for systems based on the Atmel AT91RM9200,
327 AT91SAM9 processors. 328 AT91SAM9 processors.
diff --git a/arch/arm/boot/dts/at91sam9g20.dtsi b/arch/arm/boot/dts/at91sam9g20.dtsi
index 07603b8c9503..9a0aee791a40 100644
--- a/arch/arm/boot/dts/at91sam9g20.dtsi
+++ b/arch/arm/boot/dts/at91sam9g20.dtsi
@@ -47,7 +47,7 @@
47 ranges; 47 ranges;
48 48
49 aic: interrupt-controller@fffff000 { 49 aic: interrupt-controller@fffff000 {
50 #interrupt-cells = <1>; 50 #interrupt-cells = <2>;
51 compatible = "atmel,at91rm9200-aic"; 51 compatible = "atmel,at91rm9200-aic";
52 interrupt-controller; 52 interrupt-controller;
53 interrupt-parent; 53 interrupt-parent;
@@ -57,14 +57,14 @@
57 dbgu: serial@fffff200 { 57 dbgu: serial@fffff200 {
58 compatible = "atmel,at91sam9260-usart"; 58 compatible = "atmel,at91sam9260-usart";
59 reg = <0xfffff200 0x200>; 59 reg = <0xfffff200 0x200>;
60 interrupts = <1>; 60 interrupts = <1 4>;
61 status = "disabled"; 61 status = "disabled";
62 }; 62 };
63 63
64 usart0: serial@fffb0000 { 64 usart0: serial@fffb0000 {
65 compatible = "atmel,at91sam9260-usart"; 65 compatible = "atmel,at91sam9260-usart";
66 reg = <0xfffb0000 0x200>; 66 reg = <0xfffb0000 0x200>;
67 interrupts = <6>; 67 interrupts = <6 4>;
68 atmel,use-dma-rx; 68 atmel,use-dma-rx;
69 atmel,use-dma-tx; 69 atmel,use-dma-tx;
70 status = "disabled"; 70 status = "disabled";
@@ -73,7 +73,7 @@
73 usart1: serial@fffb4000 { 73 usart1: serial@fffb4000 {
74 compatible = "atmel,at91sam9260-usart"; 74 compatible = "atmel,at91sam9260-usart";
75 reg = <0xfffb4000 0x200>; 75 reg = <0xfffb4000 0x200>;
76 interrupts = <7>; 76 interrupts = <7 4>;
77 atmel,use-dma-rx; 77 atmel,use-dma-rx;
78 atmel,use-dma-tx; 78 atmel,use-dma-tx;
79 status = "disabled"; 79 status = "disabled";
@@ -82,7 +82,7 @@
82 usart2: serial@fffb8000 { 82 usart2: serial@fffb8000 {
83 compatible = "atmel,at91sam9260-usart"; 83 compatible = "atmel,at91sam9260-usart";
84 reg = <0xfffb8000 0x200>; 84 reg = <0xfffb8000 0x200>;
85 interrupts = <8>; 85 interrupts = <8 4>;
86 atmel,use-dma-rx; 86 atmel,use-dma-rx;
87 atmel,use-dma-tx; 87 atmel,use-dma-tx;
88 status = "disabled"; 88 status = "disabled";
@@ -91,7 +91,7 @@
91 usart3: serial@fffd0000 { 91 usart3: serial@fffd0000 {
92 compatible = "atmel,at91sam9260-usart"; 92 compatible = "atmel,at91sam9260-usart";
93 reg = <0xfffd0000 0x200>; 93 reg = <0xfffd0000 0x200>;
94 interrupts = <23>; 94 interrupts = <23 4>;
95 atmel,use-dma-rx; 95 atmel,use-dma-rx;
96 atmel,use-dma-tx; 96 atmel,use-dma-tx;
97 status = "disabled"; 97 status = "disabled";
@@ -100,7 +100,7 @@
100 usart4: serial@fffd4000 { 100 usart4: serial@fffd4000 {
101 compatible = "atmel,at91sam9260-usart"; 101 compatible = "atmel,at91sam9260-usart";
102 reg = <0xfffd4000 0x200>; 102 reg = <0xfffd4000 0x200>;
103 interrupts = <24>; 103 interrupts = <24 4>;
104 atmel,use-dma-rx; 104 atmel,use-dma-rx;
105 atmel,use-dma-tx; 105 atmel,use-dma-tx;
106 status = "disabled"; 106 status = "disabled";
@@ -109,7 +109,7 @@
109 usart5: serial@fffd8000 { 109 usart5: serial@fffd8000 {
110 compatible = "atmel,at91sam9260-usart"; 110 compatible = "atmel,at91sam9260-usart";
111 reg = <0xfffd8000 0x200>; 111 reg = <0xfffd8000 0x200>;
112 interrupts = <25>; 112 interrupts = <25 4>;
113 atmel,use-dma-rx; 113 atmel,use-dma-rx;
114 atmel,use-dma-tx; 114 atmel,use-dma-tx;
115 status = "disabled"; 115 status = "disabled";
@@ -118,7 +118,7 @@
118 macb0: ethernet@fffc4000 { 118 macb0: ethernet@fffc4000 {
119 compatible = "cdns,at32ap7000-macb", "cdns,macb"; 119 compatible = "cdns,at32ap7000-macb", "cdns,macb";
120 reg = <0xfffc4000 0x100>; 120 reg = <0xfffc4000 0x100>;
121 interrupts = <21>; 121 interrupts = <21 4>;
122 status = "disabled"; 122 status = "disabled";
123 }; 123 };
124 }; 124 };
diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
index fffa005300a4..67f94d3698a2 100644
--- a/arch/arm/boot/dts/at91sam9g45.dtsi
+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
@@ -46,7 +46,7 @@
46 ranges; 46 ranges;
47 47
48 aic: interrupt-controller@fffff000 { 48 aic: interrupt-controller@fffff000 {
49 #interrupt-cells = <1>; 49 #interrupt-cells = <2>;
50 compatible = "atmel,at91rm9200-aic"; 50 compatible = "atmel,at91rm9200-aic";
51 interrupt-controller; 51 interrupt-controller;
52 interrupt-parent; 52 interrupt-parent;
@@ -56,20 +56,20 @@
56 dma: dma-controller@ffffec00 { 56 dma: dma-controller@ffffec00 {
57 compatible = "atmel,at91sam9g45-dma"; 57 compatible = "atmel,at91sam9g45-dma";
58 reg = <0xffffec00 0x200>; 58 reg = <0xffffec00 0x200>;
59 interrupts = <21>; 59 interrupts = <21 4>;
60 }; 60 };
61 61
62 dbgu: serial@ffffee00 { 62 dbgu: serial@ffffee00 {
63 compatible = "atmel,at91sam9260-usart"; 63 compatible = "atmel,at91sam9260-usart";
64 reg = <0xffffee00 0x200>; 64 reg = <0xffffee00 0x200>;
65 interrupts = <1>; 65 interrupts = <1 4>;
66 status = "disabled"; 66 status = "disabled";
67 }; 67 };
68 68
69 usart0: serial@fff8c000 { 69 usart0: serial@fff8c000 {
70 compatible = "atmel,at91sam9260-usart"; 70 compatible = "atmel,at91sam9260-usart";
71 reg = <0xfff8c000 0x200>; 71 reg = <0xfff8c000 0x200>;
72 interrupts = <7>; 72 interrupts = <7 4>;
73 atmel,use-dma-rx; 73 atmel,use-dma-rx;
74 atmel,use-dma-tx; 74 atmel,use-dma-tx;
75 status = "disabled"; 75 status = "disabled";
@@ -78,7 +78,7 @@
78 usart1: serial@fff90000 { 78 usart1: serial@fff90000 {
79 compatible = "atmel,at91sam9260-usart"; 79 compatible = "atmel,at91sam9260-usart";
80 reg = <0xfff90000 0x200>; 80 reg = <0xfff90000 0x200>;
81 interrupts = <8>; 81 interrupts = <8 4>;
82 atmel,use-dma-rx; 82 atmel,use-dma-rx;
83 atmel,use-dma-tx; 83 atmel,use-dma-tx;
84 status = "disabled"; 84 status = "disabled";
@@ -87,7 +87,7 @@
87 usart2: serial@fff94000 { 87 usart2: serial@fff94000 {
88 compatible = "atmel,at91sam9260-usart"; 88 compatible = "atmel,at91sam9260-usart";
89 reg = <0xfff94000 0x200>; 89 reg = <0xfff94000 0x200>;
90 interrupts = <9>; 90 interrupts = <9 4>;
91 atmel,use-dma-rx; 91 atmel,use-dma-rx;
92 atmel,use-dma-tx; 92 atmel,use-dma-tx;
93 status = "disabled"; 93 status = "disabled";
@@ -96,7 +96,7 @@
96 usart3: serial@fff98000 { 96 usart3: serial@fff98000 {
97 compatible = "atmel,at91sam9260-usart"; 97 compatible = "atmel,at91sam9260-usart";
98 reg = <0xfff98000 0x200>; 98 reg = <0xfff98000 0x200>;
99 interrupts = <10>; 99 interrupts = <10 4>;
100 atmel,use-dma-rx; 100 atmel,use-dma-rx;
101 atmel,use-dma-tx; 101 atmel,use-dma-tx;
102 status = "disabled"; 102 status = "disabled";
@@ -105,7 +105,7 @@
105 macb0: ethernet@fffbc000 { 105 macb0: ethernet@fffbc000 {
106 compatible = "cdns,at32ap7000-macb", "cdns,macb"; 106 compatible = "cdns,at32ap7000-macb", "cdns,macb";
107 reg = <0xfffbc000 0x100>; 107 reg = <0xfffbc000 0x100>;
108 interrupts = <25>; 108 interrupts = <25 4>;
109 status = "disabled"; 109 status = "disabled";
110 }; 110 };
111 }; 111 };
diff --git a/arch/arm/mach-at91/irq.c b/arch/arm/mach-at91/irq.c
index be6b639ecd7b..46682fafa96f 100644
--- a/arch/arm/mach-at91/irq.c
+++ b/arch/arm/mach-at91/irq.c
@@ -24,6 +24,12 @@
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/mm.h> 25#include <linux/mm.h>
26#include <linux/types.h> 26#include <linux/types.h>
27#include <linux/irq.h>
28#include <linux/of.h>
29#include <linux/of_address.h>
30#include <linux/of_irq.h>
31#include <linux/irqdomain.h>
32#include <linux/err.h>
27 33
28#include <mach/hardware.h> 34#include <mach/hardware.h>
29#include <asm/irq.h> 35#include <asm/irq.h>
@@ -34,22 +40,24 @@
34#include <asm/mach/map.h> 40#include <asm/mach/map.h>
35 41
36void __iomem *at91_aic_base; 42void __iomem *at91_aic_base;
43static struct irq_domain *at91_aic_domain;
44static struct device_node *at91_aic_np;
37 45
38static void at91_aic_mask_irq(struct irq_data *d) 46static void at91_aic_mask_irq(struct irq_data *d)
39{ 47{
40 /* Disable interrupt on AIC */ 48 /* Disable interrupt on AIC */
41 at91_aic_write(AT91_AIC_IDCR, 1 << d->irq); 49 at91_aic_write(AT91_AIC_IDCR, 1 << d->hwirq);
42} 50}
43 51
44static void at91_aic_unmask_irq(struct irq_data *d) 52static void at91_aic_unmask_irq(struct irq_data *d)
45{ 53{
46 /* Enable interrupt on AIC */ 54 /* Enable interrupt on AIC */
47 at91_aic_write(AT91_AIC_IECR, 1 << d->irq); 55 at91_aic_write(AT91_AIC_IECR, 1 << d->hwirq);
48} 56}
49 57
50unsigned int at91_extern_irq; 58unsigned int at91_extern_irq;
51 59
52#define is_extern_irq(irq) ((1 << (irq)) & at91_extern_irq) 60#define is_extern_irq(hwirq) ((1 << (hwirq)) & at91_extern_irq)
53 61
54static int at91_aic_set_type(struct irq_data *d, unsigned type) 62static int at91_aic_set_type(struct irq_data *d, unsigned type)
55{ 63{
@@ -63,13 +71,13 @@ static int at91_aic_set_type(struct irq_data *d, unsigned type)
63 srctype = AT91_AIC_SRCTYPE_RISING; 71 srctype = AT91_AIC_SRCTYPE_RISING;
64 break; 72 break;
65 case IRQ_TYPE_LEVEL_LOW: 73 case IRQ_TYPE_LEVEL_LOW:
66 if ((d->irq == AT91_ID_FIQ) || is_extern_irq(d->irq)) /* only supported on external interrupts */ 74 if ((d->hwirq == AT91_ID_FIQ) || is_extern_irq(d->hwirq)) /* only supported on external interrupts */
67 srctype = AT91_AIC_SRCTYPE_LOW; 75 srctype = AT91_AIC_SRCTYPE_LOW;
68 else 76 else
69 return -EINVAL; 77 return -EINVAL;
70 break; 78 break;
71 case IRQ_TYPE_EDGE_FALLING: 79 case IRQ_TYPE_EDGE_FALLING:
72 if ((d->irq == AT91_ID_FIQ) || is_extern_irq(d->irq)) /* only supported on external interrupts */ 80 if ((d->hwirq == AT91_ID_FIQ) || is_extern_irq(d->hwirq)) /* only supported on external interrupts */
73 srctype = AT91_AIC_SRCTYPE_FALLING; 81 srctype = AT91_AIC_SRCTYPE_FALLING;
74 else 82 else
75 return -EINVAL; 83 return -EINVAL;
@@ -78,8 +86,8 @@ static int at91_aic_set_type(struct irq_data *d, unsigned type)
78 return -EINVAL; 86 return -EINVAL;
79 } 87 }
80 88
81 smr = at91_aic_read(AT91_AIC_SMR(d->irq)) & ~AT91_AIC_SRCTYPE; 89 smr = at91_aic_read(AT91_AIC_SMR(d->hwirq)) & ~AT91_AIC_SRCTYPE;
82 at91_aic_write(AT91_AIC_SMR(d->irq), smr | srctype); 90 at91_aic_write(AT91_AIC_SMR(d->hwirq), smr | srctype);
83 return 0; 91 return 0;
84} 92}
85 93
@@ -90,13 +98,13 @@ static u32 backups;
90 98
91static int at91_aic_set_wake(struct irq_data *d, unsigned value) 99static int at91_aic_set_wake(struct irq_data *d, unsigned value)
92{ 100{
93 if (unlikely(d->irq >= 32)) 101 if (unlikely(d->hwirq >= NR_AIC_IRQS))
94 return -EINVAL; 102 return -EINVAL;
95 103
96 if (value) 104 if (value)
97 wakeups |= (1 << d->irq); 105 wakeups |= (1 << d->hwirq);
98 else 106 else
99 wakeups &= ~(1 << d->irq); 107 wakeups &= ~(1 << d->hwirq);
100 108
101 return 0; 109 return 0;
102} 110}
@@ -127,24 +135,64 @@ static struct irq_chip at91_aic_chip = {
127 .irq_set_wake = at91_aic_set_wake, 135 .irq_set_wake = at91_aic_set_wake,
128}; 136};
129 137
138#if defined(CONFIG_OF)
139static int __init __at91_aic_of_init(struct device_node *node,
140 struct device_node *parent)
141{
142 at91_aic_base = of_iomap(node, 0);
143 at91_aic_np = node;
144
145 return 0;
146}
147
148static const struct of_device_id aic_ids[] __initconst = {
149 { .compatible = "atmel,at91rm9200-aic", .data = __at91_aic_of_init },
150 { /*sentinel*/ }
151};
152
153static void __init at91_aic_of_init(void)
154{
155 of_irq_init(aic_ids);
156}
157#else
158static void __init at91_aic_of_init(void) {}
159#endif
160
130/* 161/*
131 * Initialize the AIC interrupt controller. 162 * Initialize the AIC interrupt controller.
132 */ 163 */
133void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS]) 164void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS])
134{ 165{
135 unsigned int i; 166 unsigned int i;
167 int irq_base;
136 168
137 at91_aic_base = ioremap(AT91_AIC, 512); 169 if (of_have_populated_dt())
170 at91_aic_of_init();
171 else
172 at91_aic_base = ioremap(AT91_AIC, 512);
138 173
139 if (!at91_aic_base) 174 if (!at91_aic_base)
140 panic("Impossible to ioremap AT91_AIC\n"); 175 panic("Unable to ioremap AIC registers\n");
176
177 /* Add irq domain for AIC */
178 irq_base = irq_alloc_descs(-1, 0, NR_AIC_IRQS, 0);
179 if (irq_base < 0) {
180 WARN(1, "Cannot allocate irq_descs, assuming pre-allocated\n");
181 irq_base = 0;
182 }
183 at91_aic_domain = irq_domain_add_legacy(at91_aic_np, NR_AIC_IRQS,
184 irq_base, 0,
185 &irq_domain_simple_ops, NULL);
186
187 if (!at91_aic_domain)
188 panic("Unable to add AIC irq domain\n");
141 189
142 /* 190 /*
143 * The IVR is used by macro get_irqnr_and_base to read and verify. 191 * The IVR is used by macro get_irqnr_and_base to read and verify.
144 * The irq number is NR_AIC_IRQS when a spurious interrupt has occurred. 192 * The irq number is NR_AIC_IRQS when a spurious interrupt has occurred.
145 */ 193 */
146 for (i = 0; i < NR_AIC_IRQS; i++) { 194 for (i = 0; i < NR_AIC_IRQS; i++) {
147 /* Put irq number in Source Vector Register: */ 195 /* Put hardware irq number in Source Vector Register: */
148 at91_aic_write(AT91_AIC_SVR(i), i); 196 at91_aic_write(AT91_AIC_SVR(i), i);
149 /* Active Low interrupt, with the specified priority */ 197 /* Active Low interrupt, with the specified priority */
150 at91_aic_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]); 198 at91_aic_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]);