diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/boot/dts/at91sam9g20.dtsi | 18 | ||||
-rw-r--r-- | arch/arm/boot/dts/at91sam9g45.dtsi | 16 | ||||
-rw-r--r-- | arch/arm/mach-at91/irq.c | 74 |
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 | ||
36 | void __iomem *at91_aic_base; | 42 | void __iomem *at91_aic_base; |
43 | static struct irq_domain *at91_aic_domain; | ||
44 | static struct device_node *at91_aic_np; | ||
37 | 45 | ||
38 | static void at91_aic_mask_irq(struct irq_data *d) | 46 | static 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 | ||
44 | static void at91_aic_unmask_irq(struct irq_data *d) | 52 | static 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 | ||
50 | unsigned int at91_extern_irq; | 58 | unsigned 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 | ||
54 | static int at91_aic_set_type(struct irq_data *d, unsigned type) | 62 | static 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 | ||
91 | static int at91_aic_set_wake(struct irq_data *d, unsigned value) | 99 | static 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) | ||
139 | static 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 | |||
148 | static const struct of_device_id aic_ids[] __initconst = { | ||
149 | { .compatible = "atmel,at91rm9200-aic", .data = __at91_aic_of_init }, | ||
150 | { /*sentinel*/ } | ||
151 | }; | ||
152 | |||
153 | static void __init at91_aic_of_init(void) | ||
154 | { | ||
155 | of_irq_init(aic_ids); | ||
156 | } | ||
157 | #else | ||
158 | static 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 | */ |
133 | void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS]) | 164 | void __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]); |