2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved.
7 * Copyright (C) 2006 FON Technology, SL.
8 * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org>
9 * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
13 * Platform devices for Atheros SoCs
16 #include <linux/init.h>
17 #include <linux/module.h>
18 #include <linux/types.h>
19 #include <linux/string.h>
20 #include <linux/kernel.h>
21 #include <linux/reboot.h>
22 #include <linux/interrupt.h>
23 #include <asm/bootinfo.h>
24 #include <asm/irq_cpu.h>
26 #include "../ar531x.h"
28 static u32 gpiointmask
= 0, gpiointval
= 0;
30 static inline void ar5315_gpio_irq(void)
33 sysRegWrite(AR5315_ISR
, sysRegRead(AR5315_IMR
) | ~AR5315_ISR_GPIO
);
35 /* only do one gpio interrupt at a time */
36 pend
= (sysRegRead(AR5315_GPIO_DI
) ^ gpiointval
) & gpiointmask
;
40 do_IRQ(AR531X_GPIO_IRQ_BASE
+ 31 - clz(pend
));
45 * Called when an interrupt is received, this function
46 * determines exactly which interrupt it was, and it
47 * invokes the appropriate handler.
49 * Implicitly, we also define interrupt priority by
50 * choosing which to dispatch first.
52 asmlinkage
void ar5315_irq_dispatch(void)
54 int pending
= read_c0_status() & read_c0_cause();
56 if (pending
& CAUSEF_IP3
)
57 do_IRQ(AR5315_IRQ_WLAN0_INTRS
);
58 else if (pending
& CAUSEF_IP4
)
59 do_IRQ(AR5315_IRQ_ENET0_INTRS
);
60 else if (pending
& CAUSEF_IP2
) {
61 unsigned int ar531x_misc_intrs
= sysRegRead(AR5315_ISR
) & sysRegRead(AR5315_IMR
);
63 if (ar531x_misc_intrs
& AR5315_ISR_SPI
)
64 do_IRQ(AR531X_MISC_IRQ_SPI
);
65 else if (ar531x_misc_intrs
& AR5315_ISR_TIMER
)
66 do_IRQ(AR531X_MISC_IRQ_TIMER
);
67 else if (ar531x_misc_intrs
& AR5315_ISR_AHB
)
68 do_IRQ(AR531X_MISC_IRQ_AHB_PROC
);
69 else if (ar531x_misc_intrs
& AR5315_ISR_GPIO
)
71 else if (ar531x_misc_intrs
& AR5315_ISR_UART0
)
72 do_IRQ(AR531X_MISC_IRQ_UART0
);
73 else if (ar531x_misc_intrs
& AR5315_ISR_WD
)
74 do_IRQ(AR531X_MISC_IRQ_WATCHDOG
);
76 do_IRQ(AR531X_MISC_IRQ_NONE
);
77 } else if (pending
& CAUSEF_IP7
)
78 do_IRQ(AR531X_IRQ_CPU_CLOCK
);
80 do_IRQ(AR531X_IRQ_NONE
);
83 static void ar5315_gpio_intr_enable(unsigned int irq
)
86 gpio
= irq
- AR531X_GPIO_IRQ_BASE
;
90 /* reconfigure GPIO line as input */
91 sysRegMask(AR5315_GPIO_CR
, AR5315_GPIO_CR_M(gpio
), AR5315_GPIO_CR_I(gpio
));
93 /* Enable interrupt with edge detection */
94 sysRegMask(AR5315_GPIO_INT
, AR5315_GPIO_INT_M
| AR5315_GPIO_INT_LVL_M
, gpio
| AR5315_GPIO_INT_LVL(3));
97 static void ar5315_gpio_intr_disable(unsigned int irq
)
100 gpio
= irq
- AR531X_GPIO_IRQ_BASE
;
103 gpiointmask
&= ~mask
;
105 /* Disable interrupt with edge detection */
106 sysRegMask(AR5315_GPIO_INT
, AR5315_GPIO_INT_M
| AR5315_GPIO_INT_LVL_M
, gpio
| AR5315_GPIO_INT_LVL(0));
109 /* Turn on the specified AR531X_MISC_IRQ interrupt */
110 static unsigned int ar5315_gpio_intr_startup(unsigned int irq
)
112 ar5315_gpio_intr_enable(irq
);
116 /* Turn off the specified AR531X_MISC_IRQ interrupt */
118 ar5315_gpio_intr_shutdown(unsigned int irq
)
120 ar5315_gpio_intr_disable(irq
);
124 ar5315_gpio_intr_ack(unsigned int irq
)
126 ar5315_gpio_intr_disable(irq
);
130 ar5315_gpio_intr_end(unsigned int irq
)
132 if (!(irq_desc
[irq
].status
& (IRQ_DISABLED
| IRQ_INPROGRESS
)))
133 ar5315_gpio_intr_enable(irq
);
136 static struct irq_chip ar5315_gpio_intr_controller
= {
137 .typename
= "AR5315 GPIO",
138 .startup
= ar5315_gpio_intr_startup
,
139 .shutdown
= ar5315_gpio_intr_shutdown
,
140 .enable
= ar5315_gpio_intr_enable
,
141 .disable
= ar5315_gpio_intr_disable
,
142 .ack
= ar5315_gpio_intr_ack
,
143 .end
= ar5315_gpio_intr_end
,
147 /* Enable the specified AR531X_MISC_IRQ interrupt */
149 ar5315_misc_intr_enable(unsigned int irq
)
153 imr
= sysRegRead(AR5315_IMR
);
156 case AR531X_MISC_IRQ_SPI
:
157 imr
|= AR5315_ISR_SPI
;
160 case AR531X_MISC_IRQ_TIMER
:
161 imr
|= AR5315_ISR_TIMER
;
164 case AR531X_MISC_IRQ_AHB_PROC
:
165 imr
|= AR5315_ISR_AHB
;
168 case AR531X_MISC_IRQ_AHB_DMA
:
172 case AR531X_MISC_IRQ_GPIO
:
173 imr
|= AR5315_ISR_GPIO
;
176 case AR531X_MISC_IRQ_UART0
:
177 imr
|= AR5315_ISR_UART0
;
181 case AR531X_MISC_IRQ_WATCHDOG
:
182 imr
|= AR5315_ISR_WD
;
185 case AR531X_MISC_IRQ_LOCAL
:
190 sysRegWrite(AR5315_IMR
, imr
);
191 imr
=sysRegRead(AR5315_IMR
); /* flush write buffer */
194 /* Disable the specified AR531X_MISC_IRQ interrupt */
196 ar5315_misc_intr_disable(unsigned int irq
)
200 imr
= sysRegRead(AR5315_IMR
);
203 case AR531X_MISC_IRQ_SPI
:
204 imr
&= ~AR5315_ISR_SPI
;
207 case AR531X_MISC_IRQ_TIMER
:
208 imr
&= (~AR5315_ISR_TIMER
);
211 case AR531X_MISC_IRQ_AHB_PROC
:
212 imr
&= (~AR5315_ISR_AHB
);
215 case AR531X_MISC_IRQ_AHB_DMA
:
219 case AR531X_MISC_IRQ_GPIO
:
220 imr
&= ~AR5315_ISR_GPIO
;
223 case AR531X_MISC_IRQ_UART0
:
224 imr
&= (~AR5315_ISR_UART0
);
227 case AR531X_MISC_IRQ_WATCHDOG
:
228 imr
&= (~AR5315_ISR_WD
);
231 case AR531X_MISC_IRQ_LOCAL
:
236 sysRegWrite(AR5315_IMR
, imr
);
237 sysRegRead(AR5315_IMR
); /* flush write buffer */
240 /* Turn on the specified AR531X_MISC_IRQ interrupt */
242 ar5315_misc_intr_startup(unsigned int irq
)
244 ar5315_misc_intr_enable(irq
);
248 /* Turn off the specified AR531X_MISC_IRQ interrupt */
250 ar5315_misc_intr_shutdown(unsigned int irq
)
252 ar5315_misc_intr_disable(irq
);
256 ar5315_misc_intr_ack(unsigned int irq
)
258 ar5315_misc_intr_disable(irq
);
262 ar5315_misc_intr_end(unsigned int irq
)
264 if (!(irq_desc
[irq
].status
& (IRQ_DISABLED
| IRQ_INPROGRESS
)))
265 ar5315_misc_intr_enable(irq
);
268 static struct irq_chip ar5315_misc_intr_controller
= {
269 .typename
= "AR5315 misc",
270 .startup
= ar5315_misc_intr_startup
,
271 .shutdown
= ar5315_misc_intr_shutdown
,
272 .enable
= ar5315_misc_intr_enable
,
273 .disable
= ar5315_misc_intr_disable
,
274 .ack
= ar5315_misc_intr_ack
,
275 .end
= ar5315_misc_intr_end
,
278 static irqreturn_t
ar5315_ahb_proc_handler(int cpl
, void *dev_id
)
280 sysRegWrite(AR5315_AHB_ERR0
,AHB_ERROR_DET
);
281 sysRegRead(AR5315_AHB_ERR1
);
283 printk("AHB fatal error\n");
284 machine_restart("AHB error"); /* Catastrophic failure */
289 static struct irqaction ar5315_ahb_proc_interrupt
= {
290 .handler
= ar5315_ahb_proc_handler
,
291 .flags
= IRQF_DISABLED
,
292 .name
= "ar5315_ahb_proc_interrupt",
296 static struct irqaction cascade
= {
297 .handler
= no_action
,
298 .flags
= IRQF_DISABLED
,
302 static void ar5315_gpio_intr_init(int irq_base
)
306 for (i
= irq_base
; i
< irq_base
+ AR531X_GPIO_IRQ_COUNT
; i
++) {
307 irq_desc
[i
].status
= IRQ_DISABLED
;
308 irq_desc
[i
].action
= NULL
;
309 irq_desc
[i
].depth
= 1;
310 irq_desc
[i
].chip
= &ar5315_gpio_intr_controller
;
312 setup_irq(AR531X_MISC_IRQ_GPIO
, &cascade
);
313 gpiointval
= sysRegRead(AR5315_GPIO_DI
);
316 void ar5315_misc_intr_init(int irq_base
)
320 for (i
= irq_base
; i
< irq_base
+ AR531X_MISC_IRQ_COUNT
; i
++) {
321 irq_desc
[i
].status
= IRQ_DISABLED
;
322 irq_desc
[i
].action
= NULL
;
323 irq_desc
[i
].depth
= 1;
324 irq_desc
[i
].chip
= &ar5315_misc_intr_controller
;
326 setup_irq(AR531X_MISC_IRQ_AHB_PROC
, &ar5315_ahb_proc_interrupt
);
327 setup_irq(AR5315_IRQ_MISC_INTRS
, &cascade
);
328 ar5315_gpio_intr_init(AR531X_GPIO_IRQ_BASE
);