diff options
Diffstat (limited to 'arch/mips/vr41xx')
-rw-r--r-- | arch/mips/vr41xx/common/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/vr41xx/common/icu.c | 270 | ||||
-rw-r--r-- | arch/mips/vr41xx/common/int-handler.S | 10 | ||||
-rw-r--r-- | arch/mips/vr41xx/common/irq.c | 94 |
4 files changed, 226 insertions, 150 deletions
diff --git a/arch/mips/vr41xx/common/Makefile b/arch/mips/vr41xx/common/Makefile index fa98ef3855bc..e5039031b69d 100644 --- a/arch/mips/vr41xx/common/Makefile +++ b/arch/mips/vr41xx/common/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for common code of the NEC VR4100 series. | 2 | # Makefile for common code of the NEC VR4100 series. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y += bcu.o cmu.o icu.o init.o int-handler.o pmu.o | 5 | obj-y += bcu.o cmu.o icu.o init.o int-handler.o irq.o pmu.o |
6 | obj-$(CONFIG_VRC4173) += vrc4173.o | 6 | obj-$(CONFIG_VRC4173) += vrc4173.o |
7 | 7 | ||
8 | EXTRA_AFLAGS := $(CFLAGS) | 8 | EXTRA_AFLAGS := $(CFLAGS) |
diff --git a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c index c842661144cb..0b73c5ab3c0c 100644 --- a/arch/mips/vr41xx/common/icu.c +++ b/arch/mips/vr41xx/common/icu.c | |||
@@ -3,8 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2001-2002 MontaVista Software Inc. | 4 | * Copyright (C) 2001-2002 MontaVista Software Inc. |
5 | * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> | 5 | * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> |
6 | * Copyright (C) 2003-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> | 6 | * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> |
7 | * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org) | ||
8 | * | 7 | * |
9 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
@@ -31,7 +30,7 @@ | |||
31 | */ | 30 | */ |
32 | #include <linux/errno.h> | 31 | #include <linux/errno.h> |
33 | #include <linux/init.h> | 32 | #include <linux/init.h> |
34 | #include <linux/interrupt.h> | 33 | #include <linux/ioport.h> |
35 | #include <linux/irq.h> | 34 | #include <linux/irq.h> |
36 | #include <linux/module.h> | 35 | #include <linux/module.h> |
37 | #include <linux/smp.h> | 36 | #include <linux/smp.h> |
@@ -39,34 +38,24 @@ | |||
39 | 38 | ||
40 | #include <asm/cpu.h> | 39 | #include <asm/cpu.h> |
41 | #include <asm/io.h> | 40 | #include <asm/io.h> |
42 | #include <asm/irq.h> | ||
43 | #include <asm/irq_cpu.h> | ||
44 | #include <asm/vr41xx/vr41xx.h> | 41 | #include <asm/vr41xx/vr41xx.h> |
45 | 42 | ||
46 | extern asmlinkage void vr41xx_handle_interrupt(void); | 43 | static void __iomem *icu1_base; |
47 | 44 | static void __iomem *icu2_base; | |
48 | extern void init_vr41xx_giuint_irq(void); | ||
49 | extern void giuint_irq_dispatch(struct pt_regs *regs); | ||
50 | |||
51 | static uint32_t icu1_base; | ||
52 | static uint32_t icu2_base; | ||
53 | |||
54 | static struct irqaction icu_cascade = { | ||
55 | .handler = no_action, | ||
56 | .mask = CPU_MASK_NONE, | ||
57 | .name = "cascade", | ||
58 | }; | ||
59 | 45 | ||
60 | static unsigned char sysint1_assign[16] = { | 46 | static unsigned char sysint1_assign[16] = { |
61 | 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | 47 | 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
62 | static unsigned char sysint2_assign[16] = { | 48 | static unsigned char sysint2_assign[16] = { |
63 | 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | 49 | 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
64 | 50 | ||
65 | #define SYSINT1REG_TYPE1 KSEG1ADDR(0x0b000080) | 51 | #define ICU1_TYPE1_BASE 0x0b000080UL |
66 | #define SYSINT2REG_TYPE1 KSEG1ADDR(0x0b000200) | 52 | #define ICU2_TYPE1_BASE 0x0b000200UL |
67 | 53 | ||
68 | #define SYSINT1REG_TYPE2 KSEG1ADDR(0x0f000080) | 54 | #define ICU1_TYPE2_BASE 0x0f000080UL |
69 | #define SYSINT2REG_TYPE2 KSEG1ADDR(0x0f0000a0) | 55 | #define ICU2_TYPE2_BASE 0x0f0000a0UL |
56 | |||
57 | #define ICU1_SIZE 0x20 | ||
58 | #define ICU2_SIZE 0x1c | ||
70 | 59 | ||
71 | #define SYSINT1REG 0x00 | 60 | #define SYSINT1REG 0x00 |
72 | #define PIUINTREG 0x02 | 61 | #define PIUINTREG 0x02 |
@@ -106,61 +95,61 @@ static unsigned char sysint2_assign[16] = { | |||
106 | #define SYSINT1_IRQ_TO_PIN(x) ((x) - SYSINT1_IRQ_BASE) /* Pin 0-15 */ | 95 | #define SYSINT1_IRQ_TO_PIN(x) ((x) - SYSINT1_IRQ_BASE) /* Pin 0-15 */ |
107 | #define SYSINT2_IRQ_TO_PIN(x) ((x) - SYSINT2_IRQ_BASE) /* Pin 0-15 */ | 96 | #define SYSINT2_IRQ_TO_PIN(x) ((x) - SYSINT2_IRQ_BASE) /* Pin 0-15 */ |
108 | 97 | ||
109 | #define read_icu1(offset) readw(icu1_base + (offset)) | 98 | #define INT_TO_IRQ(x) ((x) + 2) /* Int0-4 -> IRQ2-6 */ |
110 | #define write_icu1(val, offset) writew((val), icu1_base + (offset)) | 99 | |
100 | #define icu1_read(offset) readw(icu1_base + (offset)) | ||
101 | #define icu1_write(offset, value) writew((value), icu1_base + (offset)) | ||
111 | 102 | ||
112 | #define read_icu2(offset) readw(icu2_base + (offset)) | 103 | #define icu2_read(offset) readw(icu2_base + (offset)) |
113 | #define write_icu2(val, offset) writew((val), icu2_base + (offset)) | 104 | #define icu2_write(offset, value) writew((value), icu2_base + (offset)) |
114 | 105 | ||
115 | #define INTASSIGN_MAX 4 | 106 | #define INTASSIGN_MAX 4 |
116 | #define INTASSIGN_MASK 0x0007 | 107 | #define INTASSIGN_MASK 0x0007 |
117 | 108 | ||
118 | static inline uint16_t set_icu1(uint8_t offset, uint16_t set) | 109 | static inline uint16_t icu1_set(uint8_t offset, uint16_t set) |
119 | { | 110 | { |
120 | uint16_t res; | 111 | uint16_t data; |
121 | 112 | ||
122 | res = read_icu1(offset); | 113 | data = icu1_read(offset); |
123 | res |= set; | 114 | data |= set; |
124 | write_icu1(res, offset); | 115 | icu1_write(offset, data); |
125 | 116 | ||
126 | return res; | 117 | return data; |
127 | } | 118 | } |
128 | 119 | ||
129 | static inline uint16_t clear_icu1(uint8_t offset, uint16_t clear) | 120 | static inline uint16_t icu1_clear(uint8_t offset, uint16_t clear) |
130 | { | 121 | { |
131 | uint16_t res; | 122 | uint16_t data; |
132 | 123 | ||
133 | res = read_icu1(offset); | 124 | data = icu1_read(offset); |
134 | res &= ~clear; | 125 | data &= ~clear; |
135 | write_icu1(res, offset); | 126 | icu1_write(offset, data); |
136 | 127 | ||
137 | return res; | 128 | return data; |
138 | } | 129 | } |
139 | 130 | ||
140 | static inline uint16_t set_icu2(uint8_t offset, uint16_t set) | 131 | static inline uint16_t icu2_set(uint8_t offset, uint16_t set) |
141 | { | 132 | { |
142 | uint16_t res; | 133 | uint16_t data; |
143 | 134 | ||
144 | res = read_icu2(offset); | 135 | data = icu2_read(offset); |
145 | res |= set; | 136 | data |= set; |
146 | write_icu2(res, offset); | 137 | icu2_write(offset, data); |
147 | 138 | ||
148 | return res; | 139 | return data; |
149 | } | 140 | } |
150 | 141 | ||
151 | static inline uint16_t clear_icu2(uint8_t offset, uint16_t clear) | 142 | static inline uint16_t icu2_clear(uint8_t offset, uint16_t clear) |
152 | { | 143 | { |
153 | uint16_t res; | 144 | uint16_t data; |
154 | 145 | ||
155 | res = read_icu2(offset); | 146 | data = icu2_read(offset); |
156 | res &= ~clear; | 147 | data &= ~clear; |
157 | write_icu2(res, offset); | 148 | icu2_write(offset, data); |
158 | 149 | ||
159 | return res; | 150 | return data; |
160 | } | 151 | } |
161 | 152 | ||
162 | /*=======================================================================*/ | ||
163 | |||
164 | void vr41xx_enable_piuint(uint16_t mask) | 153 | void vr41xx_enable_piuint(uint16_t mask) |
165 | { | 154 | { |
166 | irq_desc_t *desc = irq_desc + PIU_IRQ; | 155 | irq_desc_t *desc = irq_desc + PIU_IRQ; |
@@ -169,7 +158,7 @@ void vr41xx_enable_piuint(uint16_t mask) | |||
169 | if (current_cpu_data.cputype == CPU_VR4111 || | 158 | if (current_cpu_data.cputype == CPU_VR4111 || |
170 | current_cpu_data.cputype == CPU_VR4121) { | 159 | current_cpu_data.cputype == CPU_VR4121) { |
171 | spin_lock_irqsave(&desc->lock, flags); | 160 | spin_lock_irqsave(&desc->lock, flags); |
172 | set_icu1(MPIUINTREG, mask); | 161 | icu1_set(MPIUINTREG, mask); |
173 | spin_unlock_irqrestore(&desc->lock, flags); | 162 | spin_unlock_irqrestore(&desc->lock, flags); |
174 | } | 163 | } |
175 | } | 164 | } |
@@ -184,7 +173,7 @@ void vr41xx_disable_piuint(uint16_t mask) | |||
184 | if (current_cpu_data.cputype == CPU_VR4111 || | 173 | if (current_cpu_data.cputype == CPU_VR4111 || |
185 | current_cpu_data.cputype == CPU_VR4121) { | 174 | current_cpu_data.cputype == CPU_VR4121) { |
186 | spin_lock_irqsave(&desc->lock, flags); | 175 | spin_lock_irqsave(&desc->lock, flags); |
187 | clear_icu1(MPIUINTREG, mask); | 176 | icu1_clear(MPIUINTREG, mask); |
188 | spin_unlock_irqrestore(&desc->lock, flags); | 177 | spin_unlock_irqrestore(&desc->lock, flags); |
189 | } | 178 | } |
190 | } | 179 | } |
@@ -199,7 +188,7 @@ void vr41xx_enable_aiuint(uint16_t mask) | |||
199 | if (current_cpu_data.cputype == CPU_VR4111 || | 188 | if (current_cpu_data.cputype == CPU_VR4111 || |
200 | current_cpu_data.cputype == CPU_VR4121) { | 189 | current_cpu_data.cputype == CPU_VR4121) { |
201 | spin_lock_irqsave(&desc->lock, flags); | 190 | spin_lock_irqsave(&desc->lock, flags); |
202 | set_icu1(MAIUINTREG, mask); | 191 | icu1_set(MAIUINTREG, mask); |
203 | spin_unlock_irqrestore(&desc->lock, flags); | 192 | spin_unlock_irqrestore(&desc->lock, flags); |
204 | } | 193 | } |
205 | } | 194 | } |
@@ -214,7 +203,7 @@ void vr41xx_disable_aiuint(uint16_t mask) | |||
214 | if (current_cpu_data.cputype == CPU_VR4111 || | 203 | if (current_cpu_data.cputype == CPU_VR4111 || |
215 | current_cpu_data.cputype == CPU_VR4121) { | 204 | current_cpu_data.cputype == CPU_VR4121) { |
216 | spin_lock_irqsave(&desc->lock, flags); | 205 | spin_lock_irqsave(&desc->lock, flags); |
217 | clear_icu1(MAIUINTREG, mask); | 206 | icu1_clear(MAIUINTREG, mask); |
218 | spin_unlock_irqrestore(&desc->lock, flags); | 207 | spin_unlock_irqrestore(&desc->lock, flags); |
219 | } | 208 | } |
220 | } | 209 | } |
@@ -229,7 +218,7 @@ void vr41xx_enable_kiuint(uint16_t mask) | |||
229 | if (current_cpu_data.cputype == CPU_VR4111 || | 218 | if (current_cpu_data.cputype == CPU_VR4111 || |
230 | current_cpu_data.cputype == CPU_VR4121) { | 219 | current_cpu_data.cputype == CPU_VR4121) { |
231 | spin_lock_irqsave(&desc->lock, flags); | 220 | spin_lock_irqsave(&desc->lock, flags); |
232 | set_icu1(MKIUINTREG, mask); | 221 | icu1_set(MKIUINTREG, mask); |
233 | spin_unlock_irqrestore(&desc->lock, flags); | 222 | spin_unlock_irqrestore(&desc->lock, flags); |
234 | } | 223 | } |
235 | } | 224 | } |
@@ -244,7 +233,7 @@ void vr41xx_disable_kiuint(uint16_t mask) | |||
244 | if (current_cpu_data.cputype == CPU_VR4111 || | 233 | if (current_cpu_data.cputype == CPU_VR4111 || |
245 | current_cpu_data.cputype == CPU_VR4121) { | 234 | current_cpu_data.cputype == CPU_VR4121) { |
246 | spin_lock_irqsave(&desc->lock, flags); | 235 | spin_lock_irqsave(&desc->lock, flags); |
247 | clear_icu1(MKIUINTREG, mask); | 236 | icu1_clear(MKIUINTREG, mask); |
248 | spin_unlock_irqrestore(&desc->lock, flags); | 237 | spin_unlock_irqrestore(&desc->lock, flags); |
249 | } | 238 | } |
250 | } | 239 | } |
@@ -257,7 +246,7 @@ void vr41xx_enable_dsiuint(uint16_t mask) | |||
257 | unsigned long flags; | 246 | unsigned long flags; |
258 | 247 | ||
259 | spin_lock_irqsave(&desc->lock, flags); | 248 | spin_lock_irqsave(&desc->lock, flags); |
260 | set_icu1(MDSIUINTREG, mask); | 249 | icu1_set(MDSIUINTREG, mask); |
261 | spin_unlock_irqrestore(&desc->lock, flags); | 250 | spin_unlock_irqrestore(&desc->lock, flags); |
262 | } | 251 | } |
263 | 252 | ||
@@ -269,7 +258,7 @@ void vr41xx_disable_dsiuint(uint16_t mask) | |||
269 | unsigned long flags; | 258 | unsigned long flags; |
270 | 259 | ||
271 | spin_lock_irqsave(&desc->lock, flags); | 260 | spin_lock_irqsave(&desc->lock, flags); |
272 | clear_icu1(MDSIUINTREG, mask); | 261 | icu1_clear(MDSIUINTREG, mask); |
273 | spin_unlock_irqrestore(&desc->lock, flags); | 262 | spin_unlock_irqrestore(&desc->lock, flags); |
274 | } | 263 | } |
275 | 264 | ||
@@ -281,7 +270,7 @@ void vr41xx_enable_firint(uint16_t mask) | |||
281 | unsigned long flags; | 270 | unsigned long flags; |
282 | 271 | ||
283 | spin_lock_irqsave(&desc->lock, flags); | 272 | spin_lock_irqsave(&desc->lock, flags); |
284 | set_icu2(MFIRINTREG, mask); | 273 | icu2_set(MFIRINTREG, mask); |
285 | spin_unlock_irqrestore(&desc->lock, flags); | 274 | spin_unlock_irqrestore(&desc->lock, flags); |
286 | } | 275 | } |
287 | 276 | ||
@@ -293,7 +282,7 @@ void vr41xx_disable_firint(uint16_t mask) | |||
293 | unsigned long flags; | 282 | unsigned long flags; |
294 | 283 | ||
295 | spin_lock_irqsave(&desc->lock, flags); | 284 | spin_lock_irqsave(&desc->lock, flags); |
296 | clear_icu2(MFIRINTREG, mask); | 285 | icu2_clear(MFIRINTREG, mask); |
297 | spin_unlock_irqrestore(&desc->lock, flags); | 286 | spin_unlock_irqrestore(&desc->lock, flags); |
298 | } | 287 | } |
299 | 288 | ||
@@ -308,7 +297,7 @@ void vr41xx_enable_pciint(void) | |||
308 | current_cpu_data.cputype == CPU_VR4131 || | 297 | current_cpu_data.cputype == CPU_VR4131 || |
309 | current_cpu_data.cputype == CPU_VR4133) { | 298 | current_cpu_data.cputype == CPU_VR4133) { |
310 | spin_lock_irqsave(&desc->lock, flags); | 299 | spin_lock_irqsave(&desc->lock, flags); |
311 | write_icu2(PCIINT0, MPCIINTREG); | 300 | icu2_write(MPCIINTREG, PCIINT0); |
312 | spin_unlock_irqrestore(&desc->lock, flags); | 301 | spin_unlock_irqrestore(&desc->lock, flags); |
313 | } | 302 | } |
314 | } | 303 | } |
@@ -324,7 +313,7 @@ void vr41xx_disable_pciint(void) | |||
324 | current_cpu_data.cputype == CPU_VR4131 || | 313 | current_cpu_data.cputype == CPU_VR4131 || |
325 | current_cpu_data.cputype == CPU_VR4133) { | 314 | current_cpu_data.cputype == CPU_VR4133) { |
326 | spin_lock_irqsave(&desc->lock, flags); | 315 | spin_lock_irqsave(&desc->lock, flags); |
327 | write_icu2(0, MPCIINTREG); | 316 | icu2_write(MPCIINTREG, 0); |
328 | spin_unlock_irqrestore(&desc->lock, flags); | 317 | spin_unlock_irqrestore(&desc->lock, flags); |
329 | } | 318 | } |
330 | } | 319 | } |
@@ -340,7 +329,7 @@ void vr41xx_enable_scuint(void) | |||
340 | current_cpu_data.cputype == CPU_VR4131 || | 329 | current_cpu_data.cputype == CPU_VR4131 || |
341 | current_cpu_data.cputype == CPU_VR4133) { | 330 | current_cpu_data.cputype == CPU_VR4133) { |
342 | spin_lock_irqsave(&desc->lock, flags); | 331 | spin_lock_irqsave(&desc->lock, flags); |
343 | write_icu2(SCUINT0, MSCUINTREG); | 332 | icu2_write(MSCUINTREG, SCUINT0); |
344 | spin_unlock_irqrestore(&desc->lock, flags); | 333 | spin_unlock_irqrestore(&desc->lock, flags); |
345 | } | 334 | } |
346 | } | 335 | } |
@@ -356,7 +345,7 @@ void vr41xx_disable_scuint(void) | |||
356 | current_cpu_data.cputype == CPU_VR4131 || | 345 | current_cpu_data.cputype == CPU_VR4131 || |
357 | current_cpu_data.cputype == CPU_VR4133) { | 346 | current_cpu_data.cputype == CPU_VR4133) { |
358 | spin_lock_irqsave(&desc->lock, flags); | 347 | spin_lock_irqsave(&desc->lock, flags); |
359 | write_icu2(0, MSCUINTREG); | 348 | icu2_write(MSCUINTREG, 0); |
360 | spin_unlock_irqrestore(&desc->lock, flags); | 349 | spin_unlock_irqrestore(&desc->lock, flags); |
361 | } | 350 | } |
362 | } | 351 | } |
@@ -372,7 +361,7 @@ void vr41xx_enable_csiint(uint16_t mask) | |||
372 | current_cpu_data.cputype == CPU_VR4131 || | 361 | current_cpu_data.cputype == CPU_VR4131 || |
373 | current_cpu_data.cputype == CPU_VR4133) { | 362 | current_cpu_data.cputype == CPU_VR4133) { |
374 | spin_lock_irqsave(&desc->lock, flags); | 363 | spin_lock_irqsave(&desc->lock, flags); |
375 | set_icu2(MCSIINTREG, mask); | 364 | icu2_set(MCSIINTREG, mask); |
376 | spin_unlock_irqrestore(&desc->lock, flags); | 365 | spin_unlock_irqrestore(&desc->lock, flags); |
377 | } | 366 | } |
378 | } | 367 | } |
@@ -388,7 +377,7 @@ void vr41xx_disable_csiint(uint16_t mask) | |||
388 | current_cpu_data.cputype == CPU_VR4131 || | 377 | current_cpu_data.cputype == CPU_VR4131 || |
389 | current_cpu_data.cputype == CPU_VR4133) { | 378 | current_cpu_data.cputype == CPU_VR4133) { |
390 | spin_lock_irqsave(&desc->lock, flags); | 379 | spin_lock_irqsave(&desc->lock, flags); |
391 | clear_icu2(MCSIINTREG, mask); | 380 | icu2_clear(MCSIINTREG, mask); |
392 | spin_unlock_irqrestore(&desc->lock, flags); | 381 | spin_unlock_irqrestore(&desc->lock, flags); |
393 | } | 382 | } |
394 | } | 383 | } |
@@ -404,7 +393,7 @@ void vr41xx_enable_bcuint(void) | |||
404 | current_cpu_data.cputype == CPU_VR4131 || | 393 | current_cpu_data.cputype == CPU_VR4131 || |
405 | current_cpu_data.cputype == CPU_VR4133) { | 394 | current_cpu_data.cputype == CPU_VR4133) { |
406 | spin_lock_irqsave(&desc->lock, flags); | 395 | spin_lock_irqsave(&desc->lock, flags); |
407 | write_icu2(BCUINTR, MBCUINTREG); | 396 | icu2_write(MBCUINTREG, BCUINTR); |
408 | spin_unlock_irqrestore(&desc->lock, flags); | 397 | spin_unlock_irqrestore(&desc->lock, flags); |
409 | } | 398 | } |
410 | } | 399 | } |
@@ -420,30 +409,28 @@ void vr41xx_disable_bcuint(void) | |||
420 | current_cpu_data.cputype == CPU_VR4131 || | 409 | current_cpu_data.cputype == CPU_VR4131 || |
421 | current_cpu_data.cputype == CPU_VR4133) { | 410 | current_cpu_data.cputype == CPU_VR4133) { |
422 | spin_lock_irqsave(&desc->lock, flags); | 411 | spin_lock_irqsave(&desc->lock, flags); |
423 | write_icu2(0, MBCUINTREG); | 412 | icu2_write(MBCUINTREG, 0); |
424 | spin_unlock_irqrestore(&desc->lock, flags); | 413 | spin_unlock_irqrestore(&desc->lock, flags); |
425 | } | 414 | } |
426 | } | 415 | } |
427 | 416 | ||
428 | EXPORT_SYMBOL(vr41xx_disable_bcuint); | 417 | EXPORT_SYMBOL(vr41xx_disable_bcuint); |
429 | 418 | ||
430 | /*=======================================================================*/ | ||
431 | |||
432 | static unsigned int startup_sysint1_irq(unsigned int irq) | 419 | static unsigned int startup_sysint1_irq(unsigned int irq) |
433 | { | 420 | { |
434 | set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq)); | 421 | icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq)); |
435 | 422 | ||
436 | return 0; /* never anything pending */ | 423 | return 0; /* never anything pending */ |
437 | } | 424 | } |
438 | 425 | ||
439 | static void shutdown_sysint1_irq(unsigned int irq) | 426 | static void shutdown_sysint1_irq(unsigned int irq) |
440 | { | 427 | { |
441 | clear_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq)); | 428 | icu1_clear(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq)); |
442 | } | 429 | } |
443 | 430 | ||
444 | static void enable_sysint1_irq(unsigned int irq) | 431 | static void enable_sysint1_irq(unsigned int irq) |
445 | { | 432 | { |
446 | set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq)); | 433 | icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq)); |
447 | } | 434 | } |
448 | 435 | ||
449 | #define disable_sysint1_irq shutdown_sysint1_irq | 436 | #define disable_sysint1_irq shutdown_sysint1_irq |
@@ -452,7 +439,7 @@ static void enable_sysint1_irq(unsigned int irq) | |||
452 | static void end_sysint1_irq(unsigned int irq) | 439 | static void end_sysint1_irq(unsigned int irq) |
453 | { | 440 | { |
454 | if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) | 441 | if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) |
455 | set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq)); | 442 | icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq)); |
456 | } | 443 | } |
457 | 444 | ||
458 | static struct hw_interrupt_type sysint1_irq_type = { | 445 | static struct hw_interrupt_type sysint1_irq_type = { |
@@ -465,23 +452,21 @@ static struct hw_interrupt_type sysint1_irq_type = { | |||
465 | .end = end_sysint1_irq, | 452 | .end = end_sysint1_irq, |
466 | }; | 453 | }; |
467 | 454 | ||
468 | /*=======================================================================*/ | ||
469 | |||
470 | static unsigned int startup_sysint2_irq(unsigned int irq) | 455 | static unsigned int startup_sysint2_irq(unsigned int irq) |
471 | { | 456 | { |
472 | set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq)); | 457 | icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq)); |
473 | 458 | ||
474 | return 0; /* never anything pending */ | 459 | return 0; /* never anything pending */ |
475 | } | 460 | } |
476 | 461 | ||
477 | static void shutdown_sysint2_irq(unsigned int irq) | 462 | static void shutdown_sysint2_irq(unsigned int irq) |
478 | { | 463 | { |
479 | clear_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq)); | 464 | icu2_clear(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq)); |
480 | } | 465 | } |
481 | 466 | ||
482 | static void enable_sysint2_irq(unsigned int irq) | 467 | static void enable_sysint2_irq(unsigned int irq) |
483 | { | 468 | { |
484 | set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq)); | 469 | icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq)); |
485 | } | 470 | } |
486 | 471 | ||
487 | #define disable_sysint2_irq shutdown_sysint2_irq | 472 | #define disable_sysint2_irq shutdown_sysint2_irq |
@@ -490,7 +475,7 @@ static void enable_sysint2_irq(unsigned int irq) | |||
490 | static void end_sysint2_irq(unsigned int irq) | 475 | static void end_sysint2_irq(unsigned int irq) |
491 | { | 476 | { |
492 | if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) | 477 | if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) |
493 | set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq)); | 478 | icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq)); |
494 | } | 479 | } |
495 | 480 | ||
496 | static struct hw_interrupt_type sysint2_irq_type = { | 481 | static struct hw_interrupt_type sysint2_irq_type = { |
@@ -503,8 +488,6 @@ static struct hw_interrupt_type sysint2_irq_type = { | |||
503 | .end = end_sysint2_irq, | 488 | .end = end_sysint2_irq, |
504 | }; | 489 | }; |
505 | 490 | ||
506 | /*=======================================================================*/ | ||
507 | |||
508 | static inline int set_sysint1_assign(unsigned int irq, unsigned char assign) | 491 | static inline int set_sysint1_assign(unsigned int irq, unsigned char assign) |
509 | { | 492 | { |
510 | irq_desc_t *desc = irq_desc + irq; | 493 | irq_desc_t *desc = irq_desc + irq; |
@@ -515,8 +498,8 @@ static inline int set_sysint1_assign(unsigned int irq, unsigned char assign) | |||
515 | 498 | ||
516 | spin_lock_irq(&desc->lock); | 499 | spin_lock_irq(&desc->lock); |
517 | 500 | ||
518 | intassign0 = read_icu1(INTASSIGN0); | 501 | intassign0 = icu1_read(INTASSIGN0); |
519 | intassign1 = read_icu1(INTASSIGN1); | 502 | intassign1 = icu1_read(INTASSIGN1); |
520 | 503 | ||
521 | switch (pin) { | 504 | switch (pin) { |
522 | case 0: | 505 | case 0: |
@@ -556,8 +539,8 @@ static inline int set_sysint1_assign(unsigned int irq, unsigned char assign) | |||
556 | } | 539 | } |
557 | 540 | ||
558 | sysint1_assign[pin] = assign; | 541 | sysint1_assign[pin] = assign; |
559 | write_icu1(intassign0, INTASSIGN0); | 542 | icu1_write(INTASSIGN0, intassign0); |
560 | write_icu1(intassign1, INTASSIGN1); | 543 | icu1_write(INTASSIGN1, intassign1); |
561 | 544 | ||
562 | spin_unlock_irq(&desc->lock); | 545 | spin_unlock_irq(&desc->lock); |
563 | 546 | ||
@@ -574,8 +557,8 @@ static inline int set_sysint2_assign(unsigned int irq, unsigned char assign) | |||
574 | 557 | ||
575 | spin_lock_irq(&desc->lock); | 558 | spin_lock_irq(&desc->lock); |
576 | 559 | ||
577 | intassign2 = read_icu1(INTASSIGN2); | 560 | intassign2 = icu1_read(INTASSIGN2); |
578 | intassign3 = read_icu1(INTASSIGN3); | 561 | intassign3 = icu1_read(INTASSIGN3); |
579 | 562 | ||
580 | switch (pin) { | 563 | switch (pin) { |
581 | case 0: | 564 | case 0: |
@@ -623,8 +606,8 @@ static inline int set_sysint2_assign(unsigned int irq, unsigned char assign) | |||
623 | } | 606 | } |
624 | 607 | ||
625 | sysint2_assign[pin] = assign; | 608 | sysint2_assign[pin] = assign; |
626 | write_icu1(intassign2, INTASSIGN2); | 609 | icu1_write(INTASSIGN2, intassign2); |
627 | write_icu1(intassign3, INTASSIGN3); | 610 | icu1_write(INTASSIGN3, intassign3); |
628 | 611 | ||
629 | spin_unlock_irq(&desc->lock); | 612 | spin_unlock_irq(&desc->lock); |
630 | 613 | ||
@@ -651,88 +634,92 @@ int vr41xx_set_intassign(unsigned int irq, unsigned char intassign) | |||
651 | 634 | ||
652 | EXPORT_SYMBOL(vr41xx_set_intassign); | 635 | EXPORT_SYMBOL(vr41xx_set_intassign); |
653 | 636 | ||
654 | /*=======================================================================*/ | 637 | static int icu_get_irq(unsigned int irq, struct pt_regs *regs) |
655 | |||
656 | asmlinkage void irq_dispatch(unsigned char intnum, struct pt_regs *regs) | ||
657 | { | 638 | { |
658 | uint16_t pend1, pend2; | 639 | uint16_t pend1, pend2; |
659 | uint16_t mask1, mask2; | 640 | uint16_t mask1, mask2; |
660 | int i; | 641 | int i; |
661 | 642 | ||
662 | pend1 = read_icu1(SYSINT1REG); | 643 | pend1 = icu1_read(SYSINT1REG); |
663 | mask1 = read_icu1(MSYSINT1REG); | 644 | mask1 = icu1_read(MSYSINT1REG); |
664 | 645 | ||
665 | pend2 = read_icu2(SYSINT2REG); | 646 | pend2 = icu2_read(SYSINT2REG); |
666 | mask2 = read_icu2(MSYSINT2REG); | 647 | mask2 = icu2_read(MSYSINT2REG); |
667 | 648 | ||
668 | mask1 &= pend1; | 649 | mask1 &= pend1; |
669 | mask2 &= pend2; | 650 | mask2 &= pend2; |
670 | 651 | ||
671 | if (mask1) { | 652 | if (mask1) { |
672 | for (i = 0; i < 16; i++) { | 653 | for (i = 0; i < 16; i++) { |
673 | if (intnum == sysint1_assign[i] && | 654 | if (irq == INT_TO_IRQ(sysint1_assign[i]) && (mask1 & (1 << i))) |
674 | (mask1 & ((uint16_t)1 << i))) { | 655 | return SYSINT1_IRQ(i); |
675 | if (i == 8) | ||
676 | giuint_irq_dispatch(regs); | ||
677 | else | ||
678 | do_IRQ(SYSINT1_IRQ(i), regs); | ||
679 | return; | ||
680 | } | ||
681 | } | 656 | } |
682 | } | 657 | } |
683 | 658 | ||
684 | if (mask2) { | 659 | if (mask2) { |
685 | for (i = 0; i < 16; i++) { | 660 | for (i = 0; i < 16; i++) { |
686 | if (intnum == sysint2_assign[i] && | 661 | if (irq == INT_TO_IRQ(sysint2_assign[i]) && (mask2 & (1 << i))) |
687 | (mask2 & ((uint16_t)1 << i))) { | 662 | return SYSINT2_IRQ(i); |
688 | do_IRQ(SYSINT2_IRQ(i), regs); | ||
689 | return; | ||
690 | } | ||
691 | } | 663 | } |
692 | } | 664 | } |
693 | 665 | ||
694 | printk(KERN_ERR "spurious ICU interrupt: %04x,%04x\n", pend1, pend2); | 666 | printk(KERN_ERR "spurious ICU interrupt: %04x,%04x\n", pend1, pend2); |
695 | 667 | ||
696 | atomic_inc(&irq_err_count); | 668 | atomic_inc(&irq_err_count); |
697 | } | ||
698 | 669 | ||
699 | /*=======================================================================*/ | 670 | return -1; |
671 | } | ||
700 | 672 | ||
701 | static int __init vr41xx_icu_init(void) | 673 | static int __init vr41xx_icu_init(void) |
702 | { | 674 | { |
675 | unsigned long icu1_start, icu2_start; | ||
676 | int i; | ||
677 | |||
703 | switch (current_cpu_data.cputype) { | 678 | switch (current_cpu_data.cputype) { |
704 | case CPU_VR4111: | 679 | case CPU_VR4111: |
705 | case CPU_VR4121: | 680 | case CPU_VR4121: |
706 | icu1_base = SYSINT1REG_TYPE1; | 681 | icu1_start = ICU1_TYPE1_BASE; |
707 | icu2_base = SYSINT2REG_TYPE1; | 682 | icu2_start = ICU2_TYPE1_BASE; |
708 | break; | 683 | break; |
709 | case CPU_VR4122: | 684 | case CPU_VR4122: |
710 | case CPU_VR4131: | 685 | case CPU_VR4131: |
711 | case CPU_VR4133: | 686 | case CPU_VR4133: |
712 | icu1_base = SYSINT1REG_TYPE2; | 687 | icu1_start = ICU1_TYPE2_BASE; |
713 | icu2_base = SYSINT2REG_TYPE2; | 688 | icu2_start = ICU2_TYPE2_BASE; |
714 | break; | 689 | break; |
715 | default: | 690 | default: |
716 | printk(KERN_ERR "ICU: Unexpected CPU of NEC VR4100 series\n"); | 691 | printk(KERN_ERR "ICU: Unexpected CPU of NEC VR4100 series\n"); |
717 | return -EINVAL; | 692 | return -ENODEV; |
718 | } | 693 | } |
719 | 694 | ||
720 | write_icu1(0, MSYSINT1REG); | 695 | if (request_mem_region(icu1_start, ICU1_SIZE, "ICU") == NULL) |
721 | write_icu1(0xffff, MGIUINTLREG); | 696 | return -EBUSY; |
722 | 697 | ||
723 | write_icu2(0, MSYSINT2REG); | 698 | if (request_mem_region(icu2_start, ICU2_SIZE, "ICU") == NULL) { |
724 | write_icu2(0xffff, MGIUINTHREG); | 699 | release_mem_region(icu1_start, ICU1_SIZE); |
700 | return -EBUSY; | ||
701 | } | ||
725 | 702 | ||
726 | return 0; | 703 | icu1_base = ioremap(icu1_start, ICU1_SIZE); |
727 | } | 704 | if (icu1_base == NULL) { |
705 | release_mem_region(icu1_start, ICU1_SIZE); | ||
706 | release_mem_region(icu2_start, ICU2_SIZE); | ||
707 | return -ENOMEM; | ||
708 | } | ||
728 | 709 | ||
729 | early_initcall(vr41xx_icu_init); | 710 | icu2_base = ioremap(icu2_start, ICU2_SIZE); |
711 | if (icu2_base == NULL) { | ||
712 | iounmap(icu1_base); | ||
713 | release_mem_region(icu1_start, ICU1_SIZE); | ||
714 | release_mem_region(icu2_start, ICU2_SIZE); | ||
715 | return -ENOMEM; | ||
716 | } | ||
730 | 717 | ||
731 | /*=======================================================================*/ | 718 | icu1_write(MSYSINT1REG, 0); |
719 | icu1_write(MGIUINTLREG, 0xffff); | ||
732 | 720 | ||
733 | static inline void init_vr41xx_icu_irq(void) | 721 | icu2_write(MSYSINT2REG, 0); |
734 | { | 722 | icu2_write(MGIUINTHREG, 0xffff); |
735 | int i; | ||
736 | 723 | ||
737 | for (i = SYSINT1_IRQ_BASE; i <= SYSINT1_IRQ_LAST; i++) | 724 | for (i = SYSINT1_IRQ_BASE; i <= SYSINT1_IRQ_LAST; i++) |
738 | irq_desc[i].handler = &sysint1_irq_type; | 725 | irq_desc[i].handler = &sysint1_irq_type; |
@@ -740,18 +727,13 @@ static inline void init_vr41xx_icu_irq(void) | |||
740 | for (i = SYSINT2_IRQ_BASE; i <= SYSINT2_IRQ_LAST; i++) | 727 | for (i = SYSINT2_IRQ_BASE; i <= SYSINT2_IRQ_LAST; i++) |
741 | irq_desc[i].handler = &sysint2_irq_type; | 728 | irq_desc[i].handler = &sysint2_irq_type; |
742 | 729 | ||
743 | setup_irq(INT0_CASCADE_IRQ, &icu_cascade); | 730 | cascade_irq(INT0_IRQ, icu_get_irq); |
744 | setup_irq(INT1_CASCADE_IRQ, &icu_cascade); | 731 | cascade_irq(INT1_IRQ, icu_get_irq); |
745 | setup_irq(INT2_CASCADE_IRQ, &icu_cascade); | 732 | cascade_irq(INT2_IRQ, icu_get_irq); |
746 | setup_irq(INT3_CASCADE_IRQ, &icu_cascade); | 733 | cascade_irq(INT3_IRQ, icu_get_irq); |
747 | setup_irq(INT4_CASCADE_IRQ, &icu_cascade); | 734 | cascade_irq(INT4_IRQ, icu_get_irq); |
748 | } | ||
749 | 735 | ||
750 | void __init arch_init_irq(void) | 736 | return 0; |
751 | { | ||
752 | mips_cpu_irq_init(MIPS_CPU_IRQ_BASE); | ||
753 | init_vr41xx_icu_irq(); | ||
754 | init_vr41xx_giuint_irq(); | ||
755 | |||
756 | set_except_vector(0, vr41xx_handle_interrupt); | ||
757 | } | 737 | } |
738 | |||
739 | core_initcall(vr41xx_icu_init); | ||
diff --git a/arch/mips/vr41xx/common/int-handler.S b/arch/mips/vr41xx/common/int-handler.S index 38ff89b505f2..272c13aee4fd 100644 --- a/arch/mips/vr41xx/common/int-handler.S +++ b/arch/mips/vr41xx/common/int-handler.S | |||
@@ -71,24 +71,24 @@ | |||
71 | 71 | ||
72 | andi t1, t0, CAUSEF_IP3 # check for Int1 | 72 | andi t1, t0, CAUSEF_IP3 # check for Int1 |
73 | bnez t1, handle_int | 73 | bnez t1, handle_int |
74 | li a0, 1 | 74 | li a0, 3 |
75 | 75 | ||
76 | andi t1, t0, CAUSEF_IP4 # check for Int2 | 76 | andi t1, t0, CAUSEF_IP4 # check for Int2 |
77 | bnez t1, handle_int | 77 | bnez t1, handle_int |
78 | li a0, 2 | 78 | li a0, 4 |
79 | 79 | ||
80 | andi t1, t0, CAUSEF_IP5 # check for Int3 | 80 | andi t1, t0, CAUSEF_IP5 # check for Int3 |
81 | bnez t1, handle_int | 81 | bnez t1, handle_int |
82 | li a0, 3 | 82 | li a0, 5 |
83 | 83 | ||
84 | andi t1, t0, CAUSEF_IP6 # check for Int4 | 84 | andi t1, t0, CAUSEF_IP6 # check for Int4 |
85 | bnez t1, handle_int | 85 | bnez t1, handle_int |
86 | li a0, 4 | 86 | li a0, 6 |
87 | 87 | ||
88 | 1: | 88 | 1: |
89 | andi t1, t0, CAUSEF_IP2 # check for Int0 | 89 | andi t1, t0, CAUSEF_IP2 # check for Int0 |
90 | bnez t1, handle_int | 90 | bnez t1, handle_int |
91 | li a0, 0 | 91 | li a0, 2 |
92 | 92 | ||
93 | andi t1, t0, CAUSEF_IP0 # check for IP0 | 93 | andi t1, t0, CAUSEF_IP0 # check for IP0 |
94 | bnez t1, handle_irq | 94 | bnez t1, handle_irq |
diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c new file mode 100644 index 000000000000..43b214d39438 --- /dev/null +++ b/arch/mips/vr41xx/common/irq.c | |||
@@ -0,0 +1,94 @@ | |||
1 | /* | ||
2 | * Interrupt handing routines for NEC VR4100 series. | ||
3 | * | ||
4 | * Copyright (C) 2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/module.h> | ||
22 | |||
23 | #include <asm/irq_cpu.h> | ||
24 | #include <asm/system.h> | ||
25 | #include <asm/vr41xx/vr41xx.h> | ||
26 | |||
27 | typedef struct irq_cascade { | ||
28 | int (*get_irq)(unsigned int, struct pt_regs *); | ||
29 | } irq_cascade_t; | ||
30 | |||
31 | static irq_cascade_t irq_cascade[NR_IRQS] __cacheline_aligned; | ||
32 | |||
33 | static struct irqaction cascade_irqaction = { | ||
34 | .handler = no_action, | ||
35 | .mask = CPU_MASK_NONE, | ||
36 | .name = "cascade", | ||
37 | }; | ||
38 | |||
39 | int cascade_irq(unsigned int irq, int (*get_irq)(unsigned int, struct pt_regs *)) | ||
40 | { | ||
41 | int retval = 0; | ||
42 | |||
43 | if (irq >= NR_IRQS) | ||
44 | return -EINVAL; | ||
45 | |||
46 | if (irq_cascade[irq].get_irq != NULL) | ||
47 | free_irq(irq, NULL); | ||
48 | |||
49 | irq_cascade[irq].get_irq = get_irq; | ||
50 | |||
51 | if (get_irq != NULL) { | ||
52 | retval = setup_irq(irq, &cascade_irqaction); | ||
53 | if (retval < 0) | ||
54 | irq_cascade[irq].get_irq = NULL; | ||
55 | } | ||
56 | |||
57 | return retval; | ||
58 | } | ||
59 | |||
60 | EXPORT_SYMBOL_GPL(cascade_irq); | ||
61 | |||
62 | asmlinkage void irq_dispatch(unsigned int irq, struct pt_regs *regs) | ||
63 | { | ||
64 | irq_cascade_t *cascade; | ||
65 | irq_desc_t *desc; | ||
66 | |||
67 | if (irq >= NR_IRQS) { | ||
68 | atomic_inc(&irq_err_count); | ||
69 | return; | ||
70 | } | ||
71 | |||
72 | cascade = irq_cascade + irq; | ||
73 | if (cascade->get_irq != NULL) { | ||
74 | unsigned int source_irq = irq; | ||
75 | desc = irq_desc + source_irq; | ||
76 | desc->handler->ack(source_irq); | ||
77 | irq = cascade->get_irq(irq, regs); | ||
78 | if (irq < 0) | ||
79 | atomic_inc(&irq_err_count); | ||
80 | else | ||
81 | irq_dispatch(irq, regs); | ||
82 | desc->handler->end(source_irq); | ||
83 | } else | ||
84 | do_IRQ(irq, regs); | ||
85 | } | ||
86 | |||
87 | extern asmlinkage void vr41xx_handle_interrupt(void); | ||
88 | |||
89 | void __init arch_init_irq(void) | ||
90 | { | ||
91 | mips_cpu_irq_init(MIPS_CPU_IRQ_BASE); | ||
92 | |||
93 | set_except_vector(0, vr41xx_handle_interrupt); | ||
94 | } | ||