aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-at91/generic.h2
-rw-r--r--arch/arm/mach-at91/include/mach/at91_aic.h26
-rw-r--r--arch/arm/mach-at91/irq.c343
3 files changed, 314 insertions, 57 deletions
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index 0a60bf837037..f49650677653 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -29,6 +29,8 @@ extern void __init at91x40_init_interrupts(unsigned int priority[]);
29extern void __init at91_aic_init(unsigned int priority[]); 29extern void __init at91_aic_init(unsigned int priority[]);
30extern int __init at91_aic_of_init(struct device_node *node, 30extern int __init at91_aic_of_init(struct device_node *node,
31 struct device_node *parent); 31 struct device_node *parent);
32extern int __init at91_aic5_of_init(struct device_node *node,
33 struct device_node *parent);
32 34
33 35
34 /* Timer */ 36 /* Timer */
diff --git a/arch/arm/mach-at91/include/mach/at91_aic.h b/arch/arm/mach-at91/include/mach/at91_aic.h
index fd42a85b7eb1..eaea66197fa1 100644
--- a/arch/arm/mach-at91/include/mach/at91_aic.h
+++ b/arch/arm/mach-at91/include/mach/at91_aic.h
@@ -30,11 +30,16 @@ extern void __iomem *at91_aic_base;
30 30
31/* Number of irq lines managed by AIC */ 31/* Number of irq lines managed by AIC */
32#define NR_AIC_IRQS 32 32#define NR_AIC_IRQS 32
33#define NR_AIC5_IRQS 128
34
35#define AT91_AIC5_SSR 0x0 /* Source Select Register [AIC5] */
36#define AT91_AIC5_INTSEL_MSK (0x7f << 0) /* Interrupt Line Selection Mask */
33 37
34#define AT91_AIC_IRQ_MIN_PRIORITY 0 38#define AT91_AIC_IRQ_MIN_PRIORITY 0
35#define AT91_AIC_IRQ_MAX_PRIORITY 7 39#define AT91_AIC_IRQ_MAX_PRIORITY 7
36 40
37#define AT91_AIC_SMR(n) ((n) * 4) /* Source Mode Registers 0-31 */ 41#define AT91_AIC_SMR(n) ((n) * 4) /* Source Mode Registers 0-31 */
42#define AT91_AIC5_SMR 0x4 /* Source Mode Register [AIC5] */
38#define AT91_AIC_PRIOR (7 << 0) /* Priority Level */ 43#define AT91_AIC_PRIOR (7 << 0) /* Priority Level */
39#define AT91_AIC_SRCTYPE (3 << 5) /* Interrupt Source Type */ 44#define AT91_AIC_SRCTYPE (3 << 5) /* Interrupt Source Type */
40#define AT91_AIC_SRCTYPE_LOW (0 << 5) 45#define AT91_AIC_SRCTYPE_LOW (0 << 5)
@@ -43,31 +48,52 @@ extern void __iomem *at91_aic_base;
43#define AT91_AIC_SRCTYPE_RISING (3 << 5) 48#define AT91_AIC_SRCTYPE_RISING (3 << 5)
44 49
45#define AT91_AIC_SVR(n) (0x80 + ((n) * 4)) /* Source Vector Registers 0-31 */ 50#define AT91_AIC_SVR(n) (0x80 + ((n) * 4)) /* Source Vector Registers 0-31 */
51#define AT91_AIC5_SVR 0x8 /* Source Vector Register [AIC5] */
46#define AT91_AIC_IVR 0x100 /* Interrupt Vector Register */ 52#define AT91_AIC_IVR 0x100 /* Interrupt Vector Register */
53#define AT91_AIC5_IVR 0x10 /* Interrupt Vector Register [AIC5] */
47#define AT91_AIC_FVR 0x104 /* Fast Interrupt Vector Register */ 54#define AT91_AIC_FVR 0x104 /* Fast Interrupt Vector Register */
55#define AT91_AIC5_FVR 0x14 /* Fast Interrupt Vector Register [AIC5] */
48#define AT91_AIC_ISR 0x108 /* Interrupt Status Register */ 56#define AT91_AIC_ISR 0x108 /* Interrupt Status Register */
57#define AT91_AIC5_ISR 0x18 /* Interrupt Status Register [AIC5] */
49#define AT91_AIC_IRQID (0x1f << 0) /* Current Interrupt Identifier */ 58#define AT91_AIC_IRQID (0x1f << 0) /* Current Interrupt Identifier */
50 59
51#define AT91_AIC_IPR 0x10c /* Interrupt Pending Register */ 60#define AT91_AIC_IPR 0x10c /* Interrupt Pending Register */
61#define AT91_AIC5_IPR0 0x20 /* Interrupt Pending Register 0 [AIC5] */
62#define AT91_AIC5_IPR1 0x24 /* Interrupt Pending Register 1 [AIC5] */
63#define AT91_AIC5_IPR2 0x28 /* Interrupt Pending Register 2 [AIC5] */
64#define AT91_AIC5_IPR3 0x2c /* Interrupt Pending Register 3 [AIC5] */
52#define AT91_AIC_IMR 0x110 /* Interrupt Mask Register */ 65#define AT91_AIC_IMR 0x110 /* Interrupt Mask Register */
66#define AT91_AIC5_IMR 0x30 /* Interrupt Mask Register [AIC5] */
53#define AT91_AIC_CISR 0x114 /* Core Interrupt Status Register */ 67#define AT91_AIC_CISR 0x114 /* Core Interrupt Status Register */
68#define AT91_AIC5_CISR 0x34 /* Core Interrupt Status Register [AIC5] */
54#define AT91_AIC_NFIQ (1 << 0) /* nFIQ Status */ 69#define AT91_AIC_NFIQ (1 << 0) /* nFIQ Status */
55#define AT91_AIC_NIRQ (1 << 1) /* nIRQ Status */ 70#define AT91_AIC_NIRQ (1 << 1) /* nIRQ Status */
56 71
57#define AT91_AIC_IECR 0x120 /* Interrupt Enable Command Register */ 72#define AT91_AIC_IECR 0x120 /* Interrupt Enable Command Register */
73#define AT91_AIC5_IECR 0x40 /* Interrupt Enable Command Register [AIC5] */
58#define AT91_AIC_IDCR 0x124 /* Interrupt Disable Command Register */ 74#define AT91_AIC_IDCR 0x124 /* Interrupt Disable Command Register */
75#define AT91_AIC5_IDCR 0x44 /* Interrupt Disable Command Register [AIC5] */
59#define AT91_AIC_ICCR 0x128 /* Interrupt Clear Command Register */ 76#define AT91_AIC_ICCR 0x128 /* Interrupt Clear Command Register */
77#define AT91_AIC5_ICCR 0x48 /* Interrupt Clear Command Register [AIC5] */
60#define AT91_AIC_ISCR 0x12c /* Interrupt Set Command Register */ 78#define AT91_AIC_ISCR 0x12c /* Interrupt Set Command Register */
79#define AT91_AIC5_ISCR 0x4c /* Interrupt Set Command Register [AIC5] */
61#define AT91_AIC_EOICR 0x130 /* End of Interrupt Command Register */ 80#define AT91_AIC_EOICR 0x130 /* End of Interrupt Command Register */
81#define AT91_AIC5_EOICR 0x38 /* End of Interrupt Command Register [AIC5] */
62#define AT91_AIC_SPU 0x134 /* Spurious Interrupt Vector Register */ 82#define AT91_AIC_SPU 0x134 /* Spurious Interrupt Vector Register */
83#define AT91_AIC5_SPU 0x3c /* Spurious Interrupt Vector Register [AIC5] */
63#define AT91_AIC_DCR 0x138 /* Debug Control Register */ 84#define AT91_AIC_DCR 0x138 /* Debug Control Register */
85#define AT91_AIC5_DCR 0x6c /* Debug Control Register [AIC5] */
64#define AT91_AIC_DCR_PROT (1 << 0) /* Protection Mode */ 86#define AT91_AIC_DCR_PROT (1 << 0) /* Protection Mode */
65#define AT91_AIC_DCR_GMSK (1 << 1) /* General Mask */ 87#define AT91_AIC_DCR_GMSK (1 << 1) /* General Mask */
66 88
67#define AT91_AIC_FFER 0x140 /* Fast Forcing Enable Register [SAM9 only] */ 89#define AT91_AIC_FFER 0x140 /* Fast Forcing Enable Register [SAM9 only] */
90#define AT91_AIC5_FFER 0x50 /* Fast Forcing Enable Register [AIC5] */
68#define AT91_AIC_FFDR 0x144 /* Fast Forcing Disable Register [SAM9 only] */ 91#define AT91_AIC_FFDR 0x144 /* Fast Forcing Disable Register [SAM9 only] */
92#define AT91_AIC5_FFDR 0x54 /* Fast Forcing Disable Register [AIC5] */
69#define AT91_AIC_FFSR 0x148 /* Fast Forcing Status Register [SAM9 only] */ 93#define AT91_AIC_FFSR 0x148 /* Fast Forcing Status Register [SAM9 only] */
94#define AT91_AIC5_FFSR 0x58 /* Fast Forcing Status Register [AIC5] */
70 95
71void at91_aic_handle_irq(struct pt_regs *regs); 96void at91_aic_handle_irq(struct pt_regs *regs);
97void at91_aic5_handle_irq(struct pt_regs *regs);
72 98
73#endif 99#endif
diff --git a/arch/arm/mach-at91/irq.c b/arch/arm/mach-at91/irq.c
index 75ca2f44c78e..c5eaaa060bd8 100644
--- a/arch/arm/mach-at91/irq.c
+++ b/arch/arm/mach-at91/irq.c
@@ -23,6 +23,7 @@
23#include <linux/init.h> 23#include <linux/init.h>
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/mm.h> 25#include <linux/mm.h>
26#include <linux/bitmap.h>
26#include <linux/types.h> 27#include <linux/types.h>
27#include <linux/irq.h> 28#include <linux/irq.h>
28#include <linux/of.h> 29#include <linux/of.h>
@@ -46,9 +47,116 @@
46void __iomem *at91_aic_base; 47void __iomem *at91_aic_base;
47static struct irq_domain *at91_aic_domain; 48static struct irq_domain *at91_aic_domain;
48static struct device_node *at91_aic_np; 49static struct device_node *at91_aic_np;
50static unsigned int n_irqs = NR_AIC_IRQS;
51static unsigned long at91_aic_caps = 0;
49static unsigned int *at91_aic_irq_priorities; 52static unsigned int *at91_aic_irq_priorities;
50 53
51asmlinkage void __exception_irq_entry at91_aic_handle_irq(struct pt_regs *regs) 54/* AIC5 introduces a Source Select Register */
55#define AT91_AIC_CAP_AIC5 (1 << 0)
56#define has_aic5() (at91_aic_caps & AT91_AIC_CAP_AIC5)
57
58#ifdef CONFIG_PM
59
60static unsigned long *wakeups;
61static unsigned long *backups;
62
63#define set_backup(bit) set_bit(bit, backups)
64#define clear_backup(bit) clear_bit(bit, backups)
65
66static int at91_aic_pm_init(void)
67{
68 backups = kzalloc(BITS_TO_LONGS(n_irqs) * sizeof(*backups), GFP_KERNEL);
69 if (!backups)
70 return -ENOMEM;
71
72 wakeups = kzalloc(BITS_TO_LONGS(n_irqs) * sizeof(*backups), GFP_KERNEL);
73 if (!wakeups) {
74 kfree(backups);
75 return -ENOMEM;
76 }
77
78 return 0;
79}
80
81static int at91_aic_set_wake(struct irq_data *d, unsigned value)
82{
83 if (unlikely(d->hwirq >= n_irqs))
84 return -EINVAL;
85
86 if (value)
87 set_bit(d->hwirq, wakeups);
88 else
89 clear_bit(d->hwirq, wakeups);
90
91 return 0;
92}
93
94void at91_irq_suspend(void)
95{
96 int i = 0, bit;
97
98 if (has_aic5()) {
99 /* disable enabled irqs */
100 while ((bit = find_next_bit(backups, n_irqs, i)) < n_irqs) {
101 at91_aic_write(AT91_AIC5_SSR,
102 bit & AT91_AIC5_INTSEL_MSK);
103 at91_aic_write(AT91_AIC5_IDCR, 1);
104 i = bit;
105 }
106 /* enable wakeup irqs */
107 i = 0;
108 while ((bit = find_next_bit(wakeups, n_irqs, i)) < n_irqs) {
109 at91_aic_write(AT91_AIC5_SSR,
110 bit & AT91_AIC5_INTSEL_MSK);
111 at91_aic_write(AT91_AIC5_IECR, 1);
112 i = bit;
113 }
114 } else {
115 at91_aic_write(AT91_AIC_IDCR, *backups);
116 at91_aic_write(AT91_AIC_IECR, *wakeups);
117 }
118}
119
120void at91_irq_resume(void)
121{
122 int i = 0, bit;
123
124 if (has_aic5()) {
125 /* disable wakeup irqs */
126 while ((bit = find_next_bit(wakeups, n_irqs, i)) < n_irqs) {
127 at91_aic_write(AT91_AIC5_SSR,
128 bit & AT91_AIC5_INTSEL_MSK);
129 at91_aic_write(AT91_AIC5_IDCR, 1);
130 i = bit;
131 }
132 /* enable irqs disabled for suspend */
133 i = 0;
134 while ((bit = find_next_bit(backups, n_irqs, i)) < n_irqs) {
135 at91_aic_write(AT91_AIC5_SSR,
136 bit & AT91_AIC5_INTSEL_MSK);
137 at91_aic_write(AT91_AIC5_IECR, 1);
138 i = bit;
139 }
140 } else {
141 at91_aic_write(AT91_AIC_IDCR, *wakeups);
142 at91_aic_write(AT91_AIC_IECR, *backups);
143 }
144}
145
146#else
147static inline int at91_aic_pm_init(void)
148{
149 return 0;
150}
151
152#define set_backup(bit)
153#define clear_backup(bit)
154#define at91_aic_set_wake NULL
155
156#endif /* CONFIG_PM */
157
158asmlinkage void __exception_irq_entry
159at91_aic_handle_irq(struct pt_regs *regs)
52{ 160{
53 u32 irqnr; 161 u32 irqnr;
54 u32 irqstat; 162 u32 irqstat;
@@ -66,16 +174,53 @@ asmlinkage void __exception_irq_entry at91_aic_handle_irq(struct pt_regs *regs)
66 handle_IRQ(irqnr, regs); 174 handle_IRQ(irqnr, regs);
67} 175}
68 176
177asmlinkage void __exception_irq_entry
178at91_aic5_handle_irq(struct pt_regs *regs)
179{
180 u32 irqnr;
181 u32 irqstat;
182
183 irqnr = at91_aic_read(AT91_AIC5_IVR);
184 irqstat = at91_aic_read(AT91_AIC5_ISR);
185
186 if (!irqstat)
187 at91_aic_write(AT91_AIC5_EOICR, 0);
188 else
189 handle_IRQ(irqnr, regs);
190}
191
69static void at91_aic_mask_irq(struct irq_data *d) 192static void at91_aic_mask_irq(struct irq_data *d)
70{ 193{
71 /* Disable interrupt on AIC */ 194 /* Disable interrupt on AIC */
72 at91_aic_write(AT91_AIC_IDCR, 1 << d->hwirq); 195 at91_aic_write(AT91_AIC_IDCR, 1 << d->hwirq);
196 /* Update ISR cache */
197 clear_backup(d->hwirq);
198}
199
200static void __maybe_unused at91_aic5_mask_irq(struct irq_data *d)
201{
202 /* Disable interrupt on AIC5 */
203 at91_aic_write(AT91_AIC5_SSR, d->hwirq & AT91_AIC5_INTSEL_MSK);
204 at91_aic_write(AT91_AIC5_IDCR, 1);
205 /* Update ISR cache */
206 clear_backup(d->hwirq);
73} 207}
74 208
75static void at91_aic_unmask_irq(struct irq_data *d) 209static void at91_aic_unmask_irq(struct irq_data *d)
76{ 210{
77 /* Enable interrupt on AIC */ 211 /* Enable interrupt on AIC */
78 at91_aic_write(AT91_AIC_IECR, 1 << d->hwirq); 212 at91_aic_write(AT91_AIC_IECR, 1 << d->hwirq);
213 /* Update ISR cache */
214 set_backup(d->hwirq);
215}
216
217static void __maybe_unused at91_aic5_unmask_irq(struct irq_data *d)
218{
219 /* Enable interrupt on AIC5 */
220 at91_aic_write(AT91_AIC5_SSR, d->hwirq & AT91_AIC5_INTSEL_MSK);
221 at91_aic_write(AT91_AIC5_IECR, 1);
222 /* Update ISR cache */
223 set_backup(d->hwirq);
79} 224}
80 225
81static void at91_aic_eoi(struct irq_data *d) 226static void at91_aic_eoi(struct irq_data *d)
@@ -87,13 +232,18 @@ static void at91_aic_eoi(struct irq_data *d)
87 at91_aic_write(AT91_AIC_EOICR, 0); 232 at91_aic_write(AT91_AIC_EOICR, 0);
88} 233}
89 234
90unsigned int at91_extern_irq; 235static void __maybe_unused at91_aic5_eoi(struct irq_data *d)
236{
237 at91_aic_write(AT91_AIC5_EOICR, 0);
238}
91 239
92#define is_extern_irq(hwirq) ((1 << (hwirq)) & at91_extern_irq) 240unsigned long *at91_extern_irq;
93 241
94static int at91_aic_set_type(struct irq_data *d, unsigned type) 242#define is_extern_irq(hwirq) test_bit(hwirq, at91_extern_irq)
243
244static int at91_aic_compute_srctype(struct irq_data *d, unsigned type)
95{ 245{
96 unsigned int smr, srctype; 246 int srctype;
97 247
98 switch (type) { 248 switch (type) {
99 case IRQ_TYPE_LEVEL_HIGH: 249 case IRQ_TYPE_LEVEL_HIGH:
@@ -106,58 +256,44 @@ static int at91_aic_set_type(struct irq_data *d, unsigned type)
106 if ((d->hwirq == AT91_ID_FIQ) || is_extern_irq(d->hwirq)) /* only supported on external interrupts */ 256 if ((d->hwirq == AT91_ID_FIQ) || is_extern_irq(d->hwirq)) /* only supported on external interrupts */
107 srctype = AT91_AIC_SRCTYPE_LOW; 257 srctype = AT91_AIC_SRCTYPE_LOW;
108 else 258 else
109 return -EINVAL; 259 srctype = -EINVAL;
110 break; 260 break;
111 case IRQ_TYPE_EDGE_FALLING: 261 case IRQ_TYPE_EDGE_FALLING:
112 if ((d->hwirq == AT91_ID_FIQ) || is_extern_irq(d->hwirq)) /* only supported on external interrupts */ 262 if ((d->hwirq == AT91_ID_FIQ) || is_extern_irq(d->hwirq)) /* only supported on external interrupts */
113 srctype = AT91_AIC_SRCTYPE_FALLING; 263 srctype = AT91_AIC_SRCTYPE_FALLING;
114 else 264 else
115 return -EINVAL; 265 srctype = -EINVAL;
116 break; 266 break;
117 default: 267 default:
118 return -EINVAL; 268 srctype = -EINVAL;
119 } 269 }
120 270
121 smr = at91_aic_read(AT91_AIC_SMR(d->hwirq)) & ~AT91_AIC_SRCTYPE; 271 return srctype;
122 at91_aic_write(AT91_AIC_SMR(d->hwirq), smr | srctype);
123 return 0;
124} 272}
125 273
126#ifdef CONFIG_PM 274static int at91_aic_set_type(struct irq_data *d, unsigned type)
127
128static u32 wakeups;
129static u32 backups;
130
131static int at91_aic_set_wake(struct irq_data *d, unsigned value)
132{ 275{
133 if (unlikely(d->hwirq >= NR_AIC_IRQS)) 276 unsigned int smr;
134 return -EINVAL; 277 int srctype;
135 278
136 if (value) 279 srctype = at91_aic_compute_srctype(d, type);
137 wakeups |= (1 << d->hwirq); 280 if (srctype < 0)
138 else 281 return srctype;
139 wakeups &= ~(1 << d->hwirq); 282
283 if (has_aic5()) {
284 at91_aic_write(AT91_AIC5_SSR,
285 d->hwirq & AT91_AIC5_INTSEL_MSK);
286 smr = at91_aic_read(AT91_AIC5_SMR) & ~AT91_AIC_SRCTYPE;
287 at91_aic_write(AT91_AIC5_SMR, smr | srctype);
288 } else {
289 smr = at91_aic_read(AT91_AIC_SMR(d->hwirq))
290 & ~AT91_AIC_SRCTYPE;
291 at91_aic_write(AT91_AIC_SMR(d->hwirq), smr | srctype);
292 }
140 293
141 return 0; 294 return 0;
142} 295}
143 296
144void at91_irq_suspend(void)
145{
146 backups = at91_aic_read(AT91_AIC_IMR);
147 at91_aic_write(AT91_AIC_IDCR, backups);
148 at91_aic_write(AT91_AIC_IECR, wakeups);
149}
150
151void at91_irq_resume(void)
152{
153 at91_aic_write(AT91_AIC_IDCR, wakeups);
154 at91_aic_write(AT91_AIC_IECR, backups);
155}
156
157#else
158#define at91_aic_set_wake NULL
159#endif
160
161static struct irq_chip at91_aic_chip = { 297static struct irq_chip at91_aic_chip = {
162 .name = "AIC", 298 .name = "AIC",
163 .irq_mask = at91_aic_mask_irq, 299 .irq_mask = at91_aic_mask_irq,
@@ -193,6 +329,35 @@ static void __init at91_aic_hw_init(unsigned int spu_vector)
193 at91_aic_write(AT91_AIC_ICCR, 0xFFFFFFFF); 329 at91_aic_write(AT91_AIC_ICCR, 0xFFFFFFFF);
194} 330}
195 331
332static void __init __maybe_unused at91_aic5_hw_init(unsigned int spu_vector)
333{
334 int i;
335
336 /*
337 * Perform 8 End Of Interrupt Command to make sure AIC
338 * will not Lock out nIRQ
339 */
340 for (i = 0; i < 8; i++)
341 at91_aic_write(AT91_AIC5_EOICR, 0);
342
343 /*
344 * Spurious Interrupt ID in Spurious Vector Register.
345 * When there is no current interrupt, the IRQ Vector Register
346 * reads the value stored in AIC_SPU
347 */
348 at91_aic_write(AT91_AIC5_SPU, spu_vector);
349
350 /* No debugging in AIC: Debug (Protect) Control Register */
351 at91_aic_write(AT91_AIC5_DCR, 0);
352
353 /* Disable and clear all interrupts initially */
354 for (i = 0; i < n_irqs; i++) {
355 at91_aic_write(AT91_AIC5_SSR, i & AT91_AIC5_INTSEL_MSK);
356 at91_aic_write(AT91_AIC5_IDCR, 1);
357 at91_aic_write(AT91_AIC5_ICCR, 1);
358 }
359}
360
196#if defined(CONFIG_OF) 361#if defined(CONFIG_OF)
197static int at91_aic_irq_map(struct irq_domain *h, unsigned int virq, 362static int at91_aic_irq_map(struct irq_domain *h, unsigned int virq,
198 irq_hw_number_t hw) 363 irq_hw_number_t hw)
@@ -210,13 +375,31 @@ static int at91_aic_irq_map(struct irq_domain *h, unsigned int virq,
210 return 0; 375 return 0;
211} 376}
212 377
378static int at91_aic5_irq_map(struct irq_domain *h, unsigned int virq,
379 irq_hw_number_t hw)
380{
381 at91_aic_write(AT91_AIC5_SSR, hw & AT91_AIC5_INTSEL_MSK);
382
383 /* Put virq number in Source Vector Register */
384 at91_aic_write(AT91_AIC5_SVR, virq);
385
386 /* Active Low interrupt, with priority */
387 at91_aic_write(AT91_AIC5_SMR,
388 AT91_AIC_SRCTYPE_LOW | at91_aic_irq_priorities[hw]);
389
390 irq_set_chip_and_handler(virq, &at91_aic_chip, handle_fasteoi_irq);
391 set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
392
393 return 0;
394}
395
213static int at91_aic_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr, 396static int at91_aic_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
214 const u32 *intspec, unsigned int intsize, 397 const u32 *intspec, unsigned int intsize,
215 irq_hw_number_t *out_hwirq, unsigned int *out_type) 398 irq_hw_number_t *out_hwirq, unsigned int *out_type)
216{ 399{
217 if (WARN_ON(intsize < 3)) 400 if (WARN_ON(intsize < 3))
218 return -EINVAL; 401 return -EINVAL;
219 if (WARN_ON(intspec[0] >= NR_AIC_IRQS)) 402 if (WARN_ON(intspec[0] >= n_irqs))
220 return -EINVAL; 403 return -EINVAL;
221 if (WARN_ON((intspec[2] < AT91_AIC_IRQ_MIN_PRIORITY) 404 if (WARN_ON((intspec[2] < AT91_AIC_IRQ_MIN_PRIORITY)
222 || (intspec[2] > AT91_AIC_IRQ_MAX_PRIORITY))) 405 || (intspec[2] > AT91_AIC_IRQ_MAX_PRIORITY)))
@@ -234,14 +417,24 @@ static struct irq_domain_ops at91_aic_irq_ops = {
234 .xlate = at91_aic_irq_domain_xlate, 417 .xlate = at91_aic_irq_domain_xlate,
235}; 418};
236 419
237int __init at91_aic_of_init(struct device_node *node, 420int __init at91_aic_of_common_init(struct device_node *node,
238 struct device_node *parent) 421 struct device_node *parent)
239{ 422{
240 struct property *prop; 423 struct property *prop;
241 const __be32 *p; 424 const __be32 *p;
242 u32 val; 425 u32 val;
243 426
244 at91_aic_irq_priorities = kzalloc(NR_AIC_IRQS 427 at91_extern_irq = kzalloc(BITS_TO_LONGS(n_irqs)
428 * sizeof(*at91_extern_irq), GFP_KERNEL);
429 if (!at91_extern_irq)
430 return -ENOMEM;
431
432 if (at91_aic_pm_init()) {
433 kfree(at91_extern_irq);
434 return -ENOMEM;
435 }
436
437 at91_aic_irq_priorities = kzalloc(n_irqs
245 * sizeof(*at91_aic_irq_priorities), 438 * sizeof(*at91_aic_irq_priorities),
246 GFP_KERNEL); 439 GFP_KERNEL);
247 if (!at91_aic_irq_priorities) 440 if (!at91_aic_irq_priorities)
@@ -250,22 +443,56 @@ int __init at91_aic_of_init(struct device_node *node,
250 at91_aic_base = of_iomap(node, 0); 443 at91_aic_base = of_iomap(node, 0);
251 at91_aic_np = node; 444 at91_aic_np = node;
252 445
253 at91_aic_domain = irq_domain_add_linear(at91_aic_np, NR_AIC_IRQS, 446 at91_aic_domain = irq_domain_add_linear(at91_aic_np, n_irqs,
254 &at91_aic_irq_ops, NULL); 447 &at91_aic_irq_ops, NULL);
255 if (!at91_aic_domain) 448 if (!at91_aic_domain)
256 panic("Unable to add AIC irq domain (DT)\n"); 449 panic("Unable to add AIC irq domain (DT)\n");
257 450
258 at91_extern_irq = 0;
259 of_property_for_each_u32(node, "atmel,external-irqs", prop, p, val) { 451 of_property_for_each_u32(node, "atmel,external-irqs", prop, p, val) {
260 if (val > 31) 452 if (val >= n_irqs)
261 pr_warn("AIC: external irq %d > 31 skip it\n", val); 453 pr_warn("AIC: external irq %d >= %d skip it\n",
454 val, n_irqs);
262 else 455 else
263 at91_extern_irq |= (1 << val); 456 set_bit(val, at91_extern_irq);
264 } 457 }
265 458
266 irq_set_default_host(at91_aic_domain); 459 irq_set_default_host(at91_aic_domain);
267 460
268 at91_aic_hw_init(NR_AIC_IRQS); 461 return 0;
462}
463
464int __init at91_aic_of_init(struct device_node *node,
465 struct device_node *parent)
466{
467 int err;
468
469 err = at91_aic_of_common_init(node, parent);
470 if (err)
471 return err;
472
473 at91_aic_hw_init(n_irqs);
474
475 return 0;
476}
477
478int __init at91_aic5_of_init(struct device_node *node,
479 struct device_node *parent)
480{
481 int err;
482
483 at91_aic_caps |= AT91_AIC_CAP_AIC5;
484 n_irqs = NR_AIC5_IRQS;
485 at91_aic_chip.irq_ack = at91_aic5_mask_irq;
486 at91_aic_chip.irq_mask = at91_aic5_mask_irq;
487 at91_aic_chip.irq_unmask = at91_aic5_unmask_irq;
488 at91_aic_chip.irq_eoi = at91_aic5_eoi;
489 at91_aic_irq_ops.map = at91_aic5_irq_map;
490
491 err = at91_aic_of_common_init(node, parent);
492 if (err)
493 return err;
494
495 at91_aic5_hw_init(n_irqs);
269 496
270 return 0; 497 return 0;
271} 498}
@@ -274,22 +501,25 @@ int __init at91_aic_of_init(struct device_node *node,
274/* 501/*
275 * Initialize the AIC interrupt controller. 502 * Initialize the AIC interrupt controller.
276 */ 503 */
277void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS]) 504void __init at91_aic_init(unsigned int *priority)
278{ 505{
279 unsigned int i; 506 unsigned int i;
280 int irq_base; 507 int irq_base;
281 508
509 if (at91_aic_pm_init())
510 panic("Unable to allocate bit maps\n");
511
282 at91_aic_base = ioremap(AT91_AIC, 512); 512 at91_aic_base = ioremap(AT91_AIC, 512);
283 if (!at91_aic_base) 513 if (!at91_aic_base)
284 panic("Unable to ioremap AIC registers\n"); 514 panic("Unable to ioremap AIC registers\n");
285 515
286 /* Add irq domain for AIC */ 516 /* Add irq domain for AIC */
287 irq_base = irq_alloc_descs(-1, 0, NR_AIC_IRQS, 0); 517 irq_base = irq_alloc_descs(-1, 0, n_irqs, 0);
288 if (irq_base < 0) { 518 if (irq_base < 0) {
289 WARN(1, "Cannot allocate irq_descs, assuming pre-allocated\n"); 519 WARN(1, "Cannot allocate irq_descs, assuming pre-allocated\n");
290 irq_base = 0; 520 irq_base = 0;
291 } 521 }
292 at91_aic_domain = irq_domain_add_legacy(at91_aic_np, NR_AIC_IRQS, 522 at91_aic_domain = irq_domain_add_legacy(at91_aic_np, n_irqs,
293 irq_base, 0, 523 irq_base, 0,
294 &irq_domain_simple_ops, NULL); 524 &irq_domain_simple_ops, NULL);
295 525
@@ -302,15 +532,14 @@ void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS])
302 * The IVR is used by macro get_irqnr_and_base to read and verify. 532 * The IVR is used by macro get_irqnr_and_base to read and verify.
303 * The irq number is NR_AIC_IRQS when a spurious interrupt has occurred. 533 * The irq number is NR_AIC_IRQS when a spurious interrupt has occurred.
304 */ 534 */
305 for (i = 0; i < NR_AIC_IRQS; i++) { 535 for (i = 0; i < n_irqs; i++) {
306 /* Put hardware irq number in Source Vector Register: */ 536 /* Put hardware irq number in Source Vector Register: */
307 at91_aic_write(AT91_AIC_SVR(i), NR_IRQS_LEGACY + i); 537 at91_aic_write(AT91_AIC_SVR(i), NR_IRQS_LEGACY + i);
308 /* Active Low interrupt, with the specified priority */ 538 /* Active Low interrupt, with the specified priority */
309 at91_aic_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]); 539 at91_aic_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]);
310
311 irq_set_chip_and_handler(NR_IRQS_LEGACY + i, &at91_aic_chip, handle_fasteoi_irq); 540 irq_set_chip_and_handler(NR_IRQS_LEGACY + i, &at91_aic_chip, handle_fasteoi_irq);
312 set_irq_flags(i, IRQF_VALID | IRQF_PROBE); 541 set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
313 } 542 }
314 543
315 at91_aic_hw_init(NR_AIC_IRQS); 544 at91_aic_hw_init(n_irqs);
316} 545}