Linux-2.6.12-rc2
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / arch / mips / vr4181 / common / irq.c
blob2cdf77c5cb3ea04b8926fdc705ff490369c05a42
1 /*
2 * Copyright (C) 2001 MontaVista Software Inc.
3 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
4 * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
6 * linux/arch/mips/vr4181/common/irq.c
7 * Completely re-written to use the new irq.c
9 * Credits to Bradley D. LaRonde and Michael Klar for writing the original
10 * irq.c file which was derived from the common irq.c file.
12 * This file is subject to the terms and conditions of the GNU General Public
13 * License. See the file "COPYING" in the main directory of this archive
14 * for more details.
16 #include <linux/types.h>
17 #include <linux/init.h>
18 #include <linux/kernel_stat.h>
19 #include <linux/signal.h>
20 #include <linux/sched.h>
21 #include <linux/interrupt.h>
22 #include <linux/slab.h>
23 #include <linux/random.h>
25 #include <asm/irq.h>
26 #include <asm/mipsregs.h>
27 #include <asm/gdb-stub.h>
29 #include <asm/vr4181/vr4181.h>
32 * Strategy:
34 * We essentially have three irq controllers, CPU, system, and gpio.
36 * CPU irq controller is taken care by arch/mips/kernel/irq_cpu.c and
37 * CONFIG_IRQ_CPU config option.
39 * We here provide sys_irq and gpio_irq controller code.
42 static int sys_irq_base;
43 static int gpio_irq_base;
45 /* ---------------------- sys irq ------------------------ */
46 static void
47 sys_irq_enable(unsigned int irq)
49 irq -= sys_irq_base;
50 if (irq < 16) {
51 *VR4181_MSYSINT1REG |= (u16)(1 << irq);
52 } else {
53 irq -= 16;
54 *VR4181_MSYSINT2REG |= (u16)(1 << irq);
58 static void
59 sys_irq_disable(unsigned int irq)
61 irq -= sys_irq_base;
62 if (irq < 16) {
63 *VR4181_MSYSINT1REG &= ~((u16)(1 << irq));
64 } else {
65 irq -= 16;
66 *VR4181_MSYSINT2REG &= ~((u16)(1 << irq));
71 static unsigned int
72 sys_irq_startup(unsigned int irq)
74 sys_irq_enable(irq);
75 return 0;
78 #define sys_irq_shutdown sys_irq_disable
79 #define sys_irq_ack sys_irq_disable
81 static void
82 sys_irq_end(unsigned int irq)
84 if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
85 sys_irq_enable(irq);
88 static hw_irq_controller sys_irq_controller = {
89 "vr4181_sys_irq",
90 sys_irq_startup,
91 sys_irq_shutdown,
92 sys_irq_enable,
93 sys_irq_disable,
94 sys_irq_ack,
95 sys_irq_end,
96 NULL /* no affinity stuff for UP */
99 /* ---------------------- gpio irq ------------------------ */
100 /* gpio irq lines use reverse logic */
101 static void
102 gpio_irq_enable(unsigned int irq)
104 irq -= gpio_irq_base;
105 *VR4181_GPINTMSK &= ~((u16)(1 << irq));
108 static void
109 gpio_irq_disable(unsigned int irq)
111 irq -= gpio_irq_base;
112 *VR4181_GPINTMSK |= (u16)(1 << irq);
115 static unsigned int
116 gpio_irq_startup(unsigned int irq)
118 gpio_irq_enable(irq);
120 irq -= gpio_irq_base;
121 *VR4181_GPINTEN |= (u16)(1 << irq );
123 return 0;
126 static void
127 gpio_irq_shutdown(unsigned int irq)
129 gpio_irq_disable(irq);
131 irq -= gpio_irq_base;
132 *VR4181_GPINTEN &= ~((u16)(1 << irq ));
135 static void
136 gpio_irq_ack(unsigned int irq)
138 u16 irqtype;
139 u16 irqshift;
141 gpio_irq_disable(irq);
143 /* we clear interrupt if it is edge triggered */
144 irq -= gpio_irq_base;
145 if (irq < 8) {
146 irqtype = *VR4181_GPINTTYPL;
147 irqshift = 2 << (irq*2);
148 } else {
149 irqtype = *VR4181_GPINTTYPH;
150 irqshift = 2 << ((irq-8)*2);
152 if ( ! (irqtype & irqshift) ) {
153 *VR4181_GPINTSTAT = (u16) (1 << irq);
157 static void
158 gpio_irq_end(unsigned int irq)
160 if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
161 gpio_irq_enable(irq);
164 static hw_irq_controller gpio_irq_controller = {
165 "vr4181_gpio_irq",
166 gpio_irq_startup,
167 gpio_irq_shutdown,
168 gpio_irq_enable,
169 gpio_irq_disable,
170 gpio_irq_ack,
171 gpio_irq_end,
172 NULL /* no affinity stuff for UP */
175 /* --------------------- IRQ init stuff ---------------------- */
177 extern asmlinkage void vr4181_handle_irq(void);
178 extern void breakpoint(void);
179 extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
180 extern void mips_cpu_irq_init(u32 irq_base);
182 static struct irqaction cascade =
183 { no_action, SA_INTERRUPT, CPU_MASK_NONE, "cascade", NULL, NULL };
184 static struct irqaction reserved =
185 { no_action, SA_INTERRUPT, CPU_MASK_NONE, "cascade", NULL, NULL };
187 void __init arch_init_irq(void)
189 int i;
191 set_except_vector(0, vr4181_handle_irq);
193 /* init CPU irqs */
194 mips_cpu_irq_init(VR4181_CPU_IRQ_BASE);
196 /* init sys irqs */
197 sys_irq_base = VR4181_SYS_IRQ_BASE;
198 for (i=sys_irq_base; i < sys_irq_base + VR4181_NUM_SYS_IRQ; i++) {
199 irq_desc[i].status = IRQ_DISABLED;
200 irq_desc[i].action = NULL;
201 irq_desc[i].depth = 1;
202 irq_desc[i].handler = &sys_irq_controller;
205 /* init gpio irqs */
206 gpio_irq_base = VR4181_GPIO_IRQ_BASE;
207 for (i=gpio_irq_base; i < gpio_irq_base + VR4181_NUM_GPIO_IRQ; i++) {
208 irq_desc[i].status = IRQ_DISABLED;
209 irq_desc[i].action = NULL;
210 irq_desc[i].depth = 1;
211 irq_desc[i].handler = &gpio_irq_controller;
214 /* Default all ICU IRQs to off ... */
215 *VR4181_MSYSINT1REG = 0;
216 *VR4181_MSYSINT2REG = 0;
218 /* We initialize the level 2 ICU registers to all bits disabled. */
219 *VR4181_MPIUINTREG = 0;
220 *VR4181_MAIUINTREG = 0;
221 *VR4181_MKIUINTREG = 0;
223 /* disable all GPIO intrs */
224 *VR4181_GPINTMSK = 0xffff;
226 /* vector handler. What these do is register the IRQ as non-sharable */
227 setup_irq(VR4181_IRQ_INT0, &cascade);
228 setup_irq(VR4181_IRQ_GIU, &cascade);
231 * RTC interrupts are interesting. They have two destinations.
232 * One is at sys irq controller, and the other is at CPU IP3 and IP4.
233 * RTC timer is used as system timer.
234 * We enable them here, but timer routine will register later
235 * with CPU IP3/IP4.
237 setup_irq(VR4181_IRQ_RTCL1, &reserved);
238 setup_irq(VR4181_IRQ_RTCL2, &reserved);