diff options
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r-- | arch/powerpc/sysdev/Makefile | 1 | ||||
-rw-r--r-- | arch/powerpc/sysdev/ipic.c | 646 | ||||
-rw-r--r-- | arch/powerpc/sysdev/ipic.h | 49 |
3 files changed, 696 insertions, 0 deletions
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 6b7efcfc352a..b3e3636a57b0 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile | |||
@@ -6,3 +6,4 @@ obj-$(CONFIG_BOOKE) += dcr.o | |||
6 | obj-$(CONFIG_40x) += dcr.o | 6 | obj-$(CONFIG_40x) += dcr.o |
7 | obj-$(CONFIG_U3_DART) += u3_iommu.o | 7 | obj-$(CONFIG_U3_DART) += u3_iommu.o |
8 | obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o | 8 | obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o |
9 | obj-$(CONFIG_83xx) += ipic.o | ||
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c new file mode 100644 index 000000000000..8f01e0f1d847 --- /dev/null +++ b/arch/powerpc/sysdev/ipic.c | |||
@@ -0,0 +1,646 @@ | |||
1 | /* | ||
2 | * include/asm-ppc/ipic.c | ||
3 | * | ||
4 | * IPIC routines implementations. | ||
5 | * | ||
6 | * Copyright 2005 Freescale Semiconductor, Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/reboot.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/stddef.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/signal.h> | ||
21 | #include <linux/sysdev.h> | ||
22 | #include <asm/irq.h> | ||
23 | #include <asm/io.h> | ||
24 | #include <asm/ipic.h> | ||
25 | #include <asm/mpc83xx.h> | ||
26 | |||
27 | #include "ipic.h" | ||
28 | |||
29 | static struct ipic p_ipic; | ||
30 | static struct ipic * primary_ipic; | ||
31 | |||
32 | static struct ipic_info ipic_info[] = { | ||
33 | [9] = { | ||
34 | .pend = IPIC_SIPNR_H, | ||
35 | .mask = IPIC_SIMSR_H, | ||
36 | .prio = IPIC_SIPRR_D, | ||
37 | .force = IPIC_SIFCR_H, | ||
38 | .bit = 24, | ||
39 | .prio_mask = 0, | ||
40 | }, | ||
41 | [10] = { | ||
42 | .pend = IPIC_SIPNR_H, | ||
43 | .mask = IPIC_SIMSR_H, | ||
44 | .prio = IPIC_SIPRR_D, | ||
45 | .force = IPIC_SIFCR_H, | ||
46 | .bit = 25, | ||
47 | .prio_mask = 1, | ||
48 | }, | ||
49 | [11] = { | ||
50 | .pend = IPIC_SIPNR_H, | ||
51 | .mask = IPIC_SIMSR_H, | ||
52 | .prio = IPIC_SIPRR_D, | ||
53 | .force = IPIC_SIFCR_H, | ||
54 | .bit = 26, | ||
55 | .prio_mask = 2, | ||
56 | }, | ||
57 | [14] = { | ||
58 | .pend = IPIC_SIPNR_H, | ||
59 | .mask = IPIC_SIMSR_H, | ||
60 | .prio = IPIC_SIPRR_D, | ||
61 | .force = IPIC_SIFCR_H, | ||
62 | .bit = 29, | ||
63 | .prio_mask = 5, | ||
64 | }, | ||
65 | [15] = { | ||
66 | .pend = IPIC_SIPNR_H, | ||
67 | .mask = IPIC_SIMSR_H, | ||
68 | .prio = IPIC_SIPRR_D, | ||
69 | .force = IPIC_SIFCR_H, | ||
70 | .bit = 30, | ||
71 | .prio_mask = 6, | ||
72 | }, | ||
73 | [16] = { | ||
74 | .pend = IPIC_SIPNR_H, | ||
75 | .mask = IPIC_SIMSR_H, | ||
76 | .prio = IPIC_SIPRR_D, | ||
77 | .force = IPIC_SIFCR_H, | ||
78 | .bit = 31, | ||
79 | .prio_mask = 7, | ||
80 | }, | ||
81 | [17] = { | ||
82 | .pend = IPIC_SEPNR, | ||
83 | .mask = IPIC_SEMSR, | ||
84 | .prio = IPIC_SMPRR_A, | ||
85 | .force = IPIC_SEFCR, | ||
86 | .bit = 1, | ||
87 | .prio_mask = 5, | ||
88 | }, | ||
89 | [18] = { | ||
90 | .pend = IPIC_SEPNR, | ||
91 | .mask = IPIC_SEMSR, | ||
92 | .prio = IPIC_SMPRR_A, | ||
93 | .force = IPIC_SEFCR, | ||
94 | .bit = 2, | ||
95 | .prio_mask = 6, | ||
96 | }, | ||
97 | [19] = { | ||
98 | .pend = IPIC_SEPNR, | ||
99 | .mask = IPIC_SEMSR, | ||
100 | .prio = IPIC_SMPRR_A, | ||
101 | .force = IPIC_SEFCR, | ||
102 | .bit = 3, | ||
103 | .prio_mask = 7, | ||
104 | }, | ||
105 | [20] = { | ||
106 | .pend = IPIC_SEPNR, | ||
107 | .mask = IPIC_SEMSR, | ||
108 | .prio = IPIC_SMPRR_B, | ||
109 | .force = IPIC_SEFCR, | ||
110 | .bit = 4, | ||
111 | .prio_mask = 4, | ||
112 | }, | ||
113 | [21] = { | ||
114 | .pend = IPIC_SEPNR, | ||
115 | .mask = IPIC_SEMSR, | ||
116 | .prio = IPIC_SMPRR_B, | ||
117 | .force = IPIC_SEFCR, | ||
118 | .bit = 5, | ||
119 | .prio_mask = 5, | ||
120 | }, | ||
121 | [22] = { | ||
122 | .pend = IPIC_SEPNR, | ||
123 | .mask = IPIC_SEMSR, | ||
124 | .prio = IPIC_SMPRR_B, | ||
125 | .force = IPIC_SEFCR, | ||
126 | .bit = 6, | ||
127 | .prio_mask = 6, | ||
128 | }, | ||
129 | [23] = { | ||
130 | .pend = IPIC_SEPNR, | ||
131 | .mask = IPIC_SEMSR, | ||
132 | .prio = IPIC_SMPRR_B, | ||
133 | .force = IPIC_SEFCR, | ||
134 | .bit = 7, | ||
135 | .prio_mask = 7, | ||
136 | }, | ||
137 | [32] = { | ||
138 | .pend = IPIC_SIPNR_H, | ||
139 | .mask = IPIC_SIMSR_H, | ||
140 | .prio = IPIC_SIPRR_A, | ||
141 | .force = IPIC_SIFCR_H, | ||
142 | .bit = 0, | ||
143 | .prio_mask = 0, | ||
144 | }, | ||
145 | [33] = { | ||
146 | .pend = IPIC_SIPNR_H, | ||
147 | .mask = IPIC_SIMSR_H, | ||
148 | .prio = IPIC_SIPRR_A, | ||
149 | .force = IPIC_SIFCR_H, | ||
150 | .bit = 1, | ||
151 | .prio_mask = 1, | ||
152 | }, | ||
153 | [34] = { | ||
154 | .pend = IPIC_SIPNR_H, | ||
155 | .mask = IPIC_SIMSR_H, | ||
156 | .prio = IPIC_SIPRR_A, | ||
157 | .force = IPIC_SIFCR_H, | ||
158 | .bit = 2, | ||
159 | .prio_mask = 2, | ||
160 | }, | ||
161 | [35] = { | ||
162 | .pend = IPIC_SIPNR_H, | ||
163 | .mask = IPIC_SIMSR_H, | ||
164 | .prio = IPIC_SIPRR_A, | ||
165 | .force = IPIC_SIFCR_H, | ||
166 | .bit = 3, | ||
167 | .prio_mask = 3, | ||
168 | }, | ||
169 | [36] = { | ||
170 | .pend = IPIC_SIPNR_H, | ||
171 | .mask = IPIC_SIMSR_H, | ||
172 | .prio = IPIC_SIPRR_A, | ||
173 | .force = IPIC_SIFCR_H, | ||
174 | .bit = 4, | ||
175 | .prio_mask = 4, | ||
176 | }, | ||
177 | [37] = { | ||
178 | .pend = IPIC_SIPNR_H, | ||
179 | .mask = IPIC_SIMSR_H, | ||
180 | .prio = IPIC_SIPRR_A, | ||
181 | .force = IPIC_SIFCR_H, | ||
182 | .bit = 5, | ||
183 | .prio_mask = 5, | ||
184 | }, | ||
185 | [38] = { | ||
186 | .pend = IPIC_SIPNR_H, | ||
187 | .mask = IPIC_SIMSR_H, | ||
188 | .prio = IPIC_SIPRR_A, | ||
189 | .force = IPIC_SIFCR_H, | ||
190 | .bit = 6, | ||
191 | .prio_mask = 6, | ||
192 | }, | ||
193 | [39] = { | ||
194 | .pend = IPIC_SIPNR_H, | ||
195 | .mask = IPIC_SIMSR_H, | ||
196 | .prio = IPIC_SIPRR_A, | ||
197 | .force = IPIC_SIFCR_H, | ||
198 | .bit = 7, | ||
199 | .prio_mask = 7, | ||
200 | }, | ||
201 | [48] = { | ||
202 | .pend = IPIC_SEPNR, | ||
203 | .mask = IPIC_SEMSR, | ||
204 | .prio = IPIC_SMPRR_A, | ||
205 | .force = IPIC_SEFCR, | ||
206 | .bit = 0, | ||
207 | .prio_mask = 4, | ||
208 | }, | ||
209 | [64] = { | ||
210 | .pend = IPIC_SIPNR_H, | ||
211 | .mask = IPIC_SIMSR_L, | ||
212 | .prio = IPIC_SMPRR_A, | ||
213 | .force = IPIC_SIFCR_L, | ||
214 | .bit = 0, | ||
215 | .prio_mask = 0, | ||
216 | }, | ||
217 | [65] = { | ||
218 | .pend = IPIC_SIPNR_H, | ||
219 | .mask = IPIC_SIMSR_L, | ||
220 | .prio = IPIC_SMPRR_A, | ||
221 | .force = IPIC_SIFCR_L, | ||
222 | .bit = 1, | ||
223 | .prio_mask = 1, | ||
224 | }, | ||
225 | [66] = { | ||
226 | .pend = IPIC_SIPNR_H, | ||
227 | .mask = IPIC_SIMSR_L, | ||
228 | .prio = IPIC_SMPRR_A, | ||
229 | .force = IPIC_SIFCR_L, | ||
230 | .bit = 2, | ||
231 | .prio_mask = 2, | ||
232 | }, | ||
233 | [67] = { | ||
234 | .pend = IPIC_SIPNR_H, | ||
235 | .mask = IPIC_SIMSR_L, | ||
236 | .prio = IPIC_SMPRR_A, | ||
237 | .force = IPIC_SIFCR_L, | ||
238 | .bit = 3, | ||
239 | .prio_mask = 3, | ||
240 | }, | ||
241 | [68] = { | ||
242 | .pend = IPIC_SIPNR_H, | ||
243 | .mask = IPIC_SIMSR_L, | ||
244 | .prio = IPIC_SMPRR_B, | ||
245 | .force = IPIC_SIFCR_L, | ||
246 | .bit = 4, | ||
247 | .prio_mask = 0, | ||
248 | }, | ||
249 | [69] = { | ||
250 | .pend = IPIC_SIPNR_H, | ||
251 | .mask = IPIC_SIMSR_L, | ||
252 | .prio = IPIC_SMPRR_B, | ||
253 | .force = IPIC_SIFCR_L, | ||
254 | .bit = 5, | ||
255 | .prio_mask = 1, | ||
256 | }, | ||
257 | [70] = { | ||
258 | .pend = IPIC_SIPNR_H, | ||
259 | .mask = IPIC_SIMSR_L, | ||
260 | .prio = IPIC_SMPRR_B, | ||
261 | .force = IPIC_SIFCR_L, | ||
262 | .bit = 6, | ||
263 | .prio_mask = 2, | ||
264 | }, | ||
265 | [71] = { | ||
266 | .pend = IPIC_SIPNR_H, | ||
267 | .mask = IPIC_SIMSR_L, | ||
268 | .prio = IPIC_SMPRR_B, | ||
269 | .force = IPIC_SIFCR_L, | ||
270 | .bit = 7, | ||
271 | .prio_mask = 3, | ||
272 | }, | ||
273 | [72] = { | ||
274 | .pend = IPIC_SIPNR_H, | ||
275 | .mask = IPIC_SIMSR_L, | ||
276 | .prio = 0, | ||
277 | .force = IPIC_SIFCR_L, | ||
278 | .bit = 8, | ||
279 | }, | ||
280 | [73] = { | ||
281 | .pend = IPIC_SIPNR_H, | ||
282 | .mask = IPIC_SIMSR_L, | ||
283 | .prio = 0, | ||
284 | .force = IPIC_SIFCR_L, | ||
285 | .bit = 9, | ||
286 | }, | ||
287 | [74] = { | ||
288 | .pend = IPIC_SIPNR_H, | ||
289 | .mask = IPIC_SIMSR_L, | ||
290 | .prio = 0, | ||
291 | .force = IPIC_SIFCR_L, | ||
292 | .bit = 10, | ||
293 | }, | ||
294 | [75] = { | ||
295 | .pend = IPIC_SIPNR_H, | ||
296 | .mask = IPIC_SIMSR_L, | ||
297 | .prio = 0, | ||
298 | .force = IPIC_SIFCR_L, | ||
299 | .bit = 11, | ||
300 | }, | ||
301 | [76] = { | ||
302 | .pend = IPIC_SIPNR_H, | ||
303 | .mask = IPIC_SIMSR_L, | ||
304 | .prio = 0, | ||
305 | .force = IPIC_SIFCR_L, | ||
306 | .bit = 12, | ||
307 | }, | ||
308 | [77] = { | ||
309 | .pend = IPIC_SIPNR_H, | ||
310 | .mask = IPIC_SIMSR_L, | ||
311 | .prio = 0, | ||
312 | .force = IPIC_SIFCR_L, | ||
313 | .bit = 13, | ||
314 | }, | ||
315 | [78] = { | ||
316 | .pend = IPIC_SIPNR_H, | ||
317 | .mask = IPIC_SIMSR_L, | ||
318 | .prio = 0, | ||
319 | .force = IPIC_SIFCR_L, | ||
320 | .bit = 14, | ||
321 | }, | ||
322 | [79] = { | ||
323 | .pend = IPIC_SIPNR_H, | ||
324 | .mask = IPIC_SIMSR_L, | ||
325 | .prio = 0, | ||
326 | .force = IPIC_SIFCR_L, | ||
327 | .bit = 15, | ||
328 | }, | ||
329 | [80] = { | ||
330 | .pend = IPIC_SIPNR_H, | ||
331 | .mask = IPIC_SIMSR_L, | ||
332 | .prio = 0, | ||
333 | .force = IPIC_SIFCR_L, | ||
334 | .bit = 16, | ||
335 | }, | ||
336 | [84] = { | ||
337 | .pend = IPIC_SIPNR_H, | ||
338 | .mask = IPIC_SIMSR_L, | ||
339 | .prio = 0, | ||
340 | .force = IPIC_SIFCR_L, | ||
341 | .bit = 20, | ||
342 | }, | ||
343 | [85] = { | ||
344 | .pend = IPIC_SIPNR_H, | ||
345 | .mask = IPIC_SIMSR_L, | ||
346 | .prio = 0, | ||
347 | .force = IPIC_SIFCR_L, | ||
348 | .bit = 21, | ||
349 | }, | ||
350 | [90] = { | ||
351 | .pend = IPIC_SIPNR_H, | ||
352 | .mask = IPIC_SIMSR_L, | ||
353 | .prio = 0, | ||
354 | .force = IPIC_SIFCR_L, | ||
355 | .bit = 26, | ||
356 | }, | ||
357 | [91] = { | ||
358 | .pend = IPIC_SIPNR_H, | ||
359 | .mask = IPIC_SIMSR_L, | ||
360 | .prio = 0, | ||
361 | .force = IPIC_SIFCR_L, | ||
362 | .bit = 27, | ||
363 | }, | ||
364 | }; | ||
365 | |||
366 | static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg) | ||
367 | { | ||
368 | return in_be32(base + (reg >> 2)); | ||
369 | } | ||
370 | |||
371 | static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value) | ||
372 | { | ||
373 | out_be32(base + (reg >> 2), value); | ||
374 | } | ||
375 | |||
376 | static inline struct ipic * ipic_from_irq(unsigned int irq) | ||
377 | { | ||
378 | return primary_ipic; | ||
379 | } | ||
380 | |||
381 | static void ipic_enable_irq(unsigned int irq) | ||
382 | { | ||
383 | struct ipic *ipic = ipic_from_irq(irq); | ||
384 | unsigned int src = irq - ipic->irq_offset; | ||
385 | u32 temp; | ||
386 | |||
387 | temp = ipic_read(ipic->regs, ipic_info[src].mask); | ||
388 | temp |= (1 << (31 - ipic_info[src].bit)); | ||
389 | ipic_write(ipic->regs, ipic_info[src].mask, temp); | ||
390 | } | ||
391 | |||
392 | static void ipic_disable_irq(unsigned int irq) | ||
393 | { | ||
394 | struct ipic *ipic = ipic_from_irq(irq); | ||
395 | unsigned int src = irq - ipic->irq_offset; | ||
396 | u32 temp; | ||
397 | |||
398 | temp = ipic_read(ipic->regs, ipic_info[src].mask); | ||
399 | temp &= ~(1 << (31 - ipic_info[src].bit)); | ||
400 | ipic_write(ipic->regs, ipic_info[src].mask, temp); | ||
401 | } | ||
402 | |||
403 | static void ipic_disable_irq_and_ack(unsigned int irq) | ||
404 | { | ||
405 | struct ipic *ipic = ipic_from_irq(irq); | ||
406 | unsigned int src = irq - ipic->irq_offset; | ||
407 | u32 temp; | ||
408 | |||
409 | ipic_disable_irq(irq); | ||
410 | |||
411 | temp = ipic_read(ipic->regs, ipic_info[src].pend); | ||
412 | temp |= (1 << (31 - ipic_info[src].bit)); | ||
413 | ipic_write(ipic->regs, ipic_info[src].pend, temp); | ||
414 | } | ||
415 | |||
416 | static void ipic_end_irq(unsigned int irq) | ||
417 | { | ||
418 | if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) | ||
419 | ipic_enable_irq(irq); | ||
420 | } | ||
421 | |||
422 | struct hw_interrupt_type ipic = { | ||
423 | .typename = " IPIC ", | ||
424 | .enable = ipic_enable_irq, | ||
425 | .disable = ipic_disable_irq, | ||
426 | .ack = ipic_disable_irq_and_ack, | ||
427 | .end = ipic_end_irq, | ||
428 | }; | ||
429 | |||
430 | void __init ipic_init(phys_addr_t phys_addr, | ||
431 | unsigned int flags, | ||
432 | unsigned int irq_offset, | ||
433 | unsigned char *senses, | ||
434 | unsigned int senses_count) | ||
435 | { | ||
436 | u32 i, temp = 0; | ||
437 | |||
438 | primary_ipic = &p_ipic; | ||
439 | primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE); | ||
440 | |||
441 | primary_ipic->irq_offset = irq_offset; | ||
442 | |||
443 | ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0); | ||
444 | |||
445 | /* default priority scheme is grouped. If spread mode is required | ||
446 | * configure SICFR accordingly */ | ||
447 | if (flags & IPIC_SPREADMODE_GRP_A) | ||
448 | temp |= SICFR_IPSA; | ||
449 | if (flags & IPIC_SPREADMODE_GRP_D) | ||
450 | temp |= SICFR_IPSD; | ||
451 | if (flags & IPIC_SPREADMODE_MIX_A) | ||
452 | temp |= SICFR_MPSA; | ||
453 | if (flags & IPIC_SPREADMODE_MIX_B) | ||
454 | temp |= SICFR_MPSB; | ||
455 | |||
456 | ipic_write(primary_ipic->regs, IPIC_SICNR, temp); | ||
457 | |||
458 | /* handle MCP route */ | ||
459 | temp = 0; | ||
460 | if (flags & IPIC_DISABLE_MCP_OUT) | ||
461 | temp = SERCR_MCPR; | ||
462 | ipic_write(primary_ipic->regs, IPIC_SERCR, temp); | ||
463 | |||
464 | /* handle routing of IRQ0 to MCP */ | ||
465 | temp = ipic_read(primary_ipic->regs, IPIC_SEMSR); | ||
466 | |||
467 | if (flags & IPIC_IRQ0_MCP) | ||
468 | temp |= SEMSR_SIRQ0; | ||
469 | else | ||
470 | temp &= ~SEMSR_SIRQ0; | ||
471 | |||
472 | ipic_write(primary_ipic->regs, IPIC_SEMSR, temp); | ||
473 | |||
474 | for (i = 0 ; i < NR_IPIC_INTS ; i++) { | ||
475 | irq_desc[i+irq_offset].handler = &ipic; | ||
476 | irq_desc[i+irq_offset].status = IRQ_LEVEL; | ||
477 | } | ||
478 | |||
479 | temp = 0; | ||
480 | for (i = 0 ; i < senses_count ; i++) { | ||
481 | if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) { | ||
482 | temp |= 1 << (15 - i); | ||
483 | if (i != 0) | ||
484 | irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0; | ||
485 | else | ||
486 | irq_desc[irq_offset + MPC83xx_IRQ_EXT0].status = 0; | ||
487 | } | ||
488 | } | ||
489 | ipic_write(primary_ipic->regs, IPIC_SECNR, temp); | ||
490 | |||
491 | printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS, | ||
492 | senses_count, primary_ipic->regs); | ||
493 | } | ||
494 | |||
495 | int ipic_set_priority(unsigned int irq, unsigned int priority) | ||
496 | { | ||
497 | struct ipic *ipic = ipic_from_irq(irq); | ||
498 | unsigned int src = irq - ipic->irq_offset; | ||
499 | u32 temp; | ||
500 | |||
501 | if (priority > 7) | ||
502 | return -EINVAL; | ||
503 | if (src > 127) | ||
504 | return -EINVAL; | ||
505 | if (ipic_info[src].prio == 0) | ||
506 | return -EINVAL; | ||
507 | |||
508 | temp = ipic_read(ipic->regs, ipic_info[src].prio); | ||
509 | |||
510 | if (priority < 4) { | ||
511 | temp &= ~(0x7 << (20 + (3 - priority) * 3)); | ||
512 | temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3); | ||
513 | } else { | ||
514 | temp &= ~(0x7 << (4 + (7 - priority) * 3)); | ||
515 | temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3); | ||
516 | } | ||
517 | |||
518 | ipic_write(ipic->regs, ipic_info[src].prio, temp); | ||
519 | |||
520 | return 0; | ||
521 | } | ||
522 | |||
523 | void ipic_set_highest_priority(unsigned int irq) | ||
524 | { | ||
525 | struct ipic *ipic = ipic_from_irq(irq); | ||
526 | unsigned int src = irq - ipic->irq_offset; | ||
527 | u32 temp; | ||
528 | |||
529 | temp = ipic_read(ipic->regs, IPIC_SICFR); | ||
530 | |||
531 | /* clear and set HPI */ | ||
532 | temp &= 0x7f000000; | ||
533 | temp |= (src & 0x7f) << 24; | ||
534 | |||
535 | ipic_write(ipic->regs, IPIC_SICFR, temp); | ||
536 | } | ||
537 | |||
538 | void ipic_set_default_priority(void) | ||
539 | { | ||
540 | ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0); | ||
541 | ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1); | ||
542 | ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2); | ||
543 | ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3); | ||
544 | ipic_set_priority(MPC83xx_IRQ_TSEC2_RX, 4); | ||
545 | ipic_set_priority(MPC83xx_IRQ_TSEC2_ERROR, 5); | ||
546 | ipic_set_priority(MPC83xx_IRQ_USB2_DR, 6); | ||
547 | ipic_set_priority(MPC83xx_IRQ_USB2_MPH, 7); | ||
548 | |||
549 | ipic_set_priority(MPC83xx_IRQ_UART1, 0); | ||
550 | ipic_set_priority(MPC83xx_IRQ_UART2, 1); | ||
551 | ipic_set_priority(MPC83xx_IRQ_SEC2, 2); | ||
552 | ipic_set_priority(MPC83xx_IRQ_IIC1, 5); | ||
553 | ipic_set_priority(MPC83xx_IRQ_IIC2, 6); | ||
554 | ipic_set_priority(MPC83xx_IRQ_SPI, 7); | ||
555 | ipic_set_priority(MPC83xx_IRQ_RTC_SEC, 0); | ||
556 | ipic_set_priority(MPC83xx_IRQ_PIT, 1); | ||
557 | ipic_set_priority(MPC83xx_IRQ_PCI1, 2); | ||
558 | ipic_set_priority(MPC83xx_IRQ_PCI2, 3); | ||
559 | ipic_set_priority(MPC83xx_IRQ_EXT0, 4); | ||
560 | ipic_set_priority(MPC83xx_IRQ_EXT1, 5); | ||
561 | ipic_set_priority(MPC83xx_IRQ_EXT2, 6); | ||
562 | ipic_set_priority(MPC83xx_IRQ_EXT3, 7); | ||
563 | ipic_set_priority(MPC83xx_IRQ_RTC_ALR, 0); | ||
564 | ipic_set_priority(MPC83xx_IRQ_MU, 1); | ||
565 | ipic_set_priority(MPC83xx_IRQ_SBA, 2); | ||
566 | ipic_set_priority(MPC83xx_IRQ_DMA, 3); | ||
567 | ipic_set_priority(MPC83xx_IRQ_EXT4, 4); | ||
568 | ipic_set_priority(MPC83xx_IRQ_EXT5, 5); | ||
569 | ipic_set_priority(MPC83xx_IRQ_EXT6, 6); | ||
570 | ipic_set_priority(MPC83xx_IRQ_EXT7, 7); | ||
571 | } | ||
572 | |||
573 | void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq) | ||
574 | { | ||
575 | struct ipic *ipic = primary_ipic; | ||
576 | u32 temp; | ||
577 | |||
578 | temp = ipic_read(ipic->regs, IPIC_SERMR); | ||
579 | temp |= (1 << (31 - mcp_irq)); | ||
580 | ipic_write(ipic->regs, IPIC_SERMR, temp); | ||
581 | } | ||
582 | |||
583 | void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq) | ||
584 | { | ||
585 | struct ipic *ipic = primary_ipic; | ||
586 | u32 temp; | ||
587 | |||
588 | temp = ipic_read(ipic->regs, IPIC_SERMR); | ||
589 | temp &= (1 << (31 - mcp_irq)); | ||
590 | ipic_write(ipic->regs, IPIC_SERMR, temp); | ||
591 | } | ||
592 | |||
593 | u32 ipic_get_mcp_status(void) | ||
594 | { | ||
595 | return ipic_read(primary_ipic->regs, IPIC_SERMR); | ||
596 | } | ||
597 | |||
598 | void ipic_clear_mcp_status(u32 mask) | ||
599 | { | ||
600 | ipic_write(primary_ipic->regs, IPIC_SERMR, mask); | ||
601 | } | ||
602 | |||
603 | /* Return an interrupt vector or -1 if no interrupt is pending. */ | ||
604 | int ipic_get_irq(struct pt_regs *regs) | ||
605 | { | ||
606 | int irq; | ||
607 | |||
608 | irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f; | ||
609 | |||
610 | if (irq == 0) /* 0 --> no irq is pending */ | ||
611 | irq = -1; | ||
612 | |||
613 | return irq; | ||
614 | } | ||
615 | |||
616 | static struct sysdev_class ipic_sysclass = { | ||
617 | set_kset_name("ipic"), | ||
618 | }; | ||
619 | |||
620 | static struct sys_device device_ipic = { | ||
621 | .id = 0, | ||
622 | .cls = &ipic_sysclass, | ||
623 | }; | ||
624 | |||
625 | static int __init init_ipic_sysfs(void) | ||
626 | { | ||
627 | int rc; | ||
628 | |||
629 | if (!primary_ipic->regs) | ||
630 | return -ENODEV; | ||
631 | printk(KERN_DEBUG "Registering ipic with sysfs...\n"); | ||
632 | |||
633 | rc = sysdev_class_register(&ipic_sysclass); | ||
634 | if (rc) { | ||
635 | printk(KERN_ERR "Failed registering ipic sys class\n"); | ||
636 | return -ENODEV; | ||
637 | } | ||
638 | rc = sysdev_register(&device_ipic); | ||
639 | if (rc) { | ||
640 | printk(KERN_ERR "Failed registering ipic sys device\n"); | ||
641 | return -ENODEV; | ||
642 | } | ||
643 | return 0; | ||
644 | } | ||
645 | |||
646 | subsys_initcall(init_ipic_sysfs); | ||
diff --git a/arch/powerpc/sysdev/ipic.h b/arch/powerpc/sysdev/ipic.h new file mode 100644 index 000000000000..a7ce7da8785c --- /dev/null +++ b/arch/powerpc/sysdev/ipic.h | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * arch/ppc/kernel/ipic.h | ||
3 | * | ||
4 | * IPIC private definitions and structure. | ||
5 | * | ||
6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> | ||
7 | * | ||
8 | * Copyright 2005 Freescale Semiconductor, Inc | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | */ | ||
15 | #ifndef __IPIC_H__ | ||
16 | #define __IPIC_H__ | ||
17 | |||
18 | #include <asm/ipic.h> | ||
19 | |||
20 | #define MPC83xx_IPIC_SIZE (0x00100) | ||
21 | |||
22 | /* System Global Interrupt Configuration Register */ | ||
23 | #define SICFR_IPSA 0x00010000 | ||
24 | #define SICFR_IPSD 0x00080000 | ||
25 | #define SICFR_MPSA 0x00200000 | ||
26 | #define SICFR_MPSB 0x00400000 | ||
27 | |||
28 | /* System External Interrupt Mask Register */ | ||
29 | #define SEMSR_SIRQ0 0x00008000 | ||
30 | |||
31 | /* System Error Control Register */ | ||
32 | #define SERCR_MCPR 0x00000001 | ||
33 | |||
34 | struct ipic { | ||
35 | volatile u32 __iomem *regs; | ||
36 | unsigned int irq_offset; | ||
37 | }; | ||
38 | |||
39 | struct ipic_info { | ||
40 | u8 pend; /* pending register offset from base */ | ||
41 | u8 mask; /* mask register offset from base */ | ||
42 | u8 prio; /* priority register offset from base */ | ||
43 | u8 force; /* force register offset from base */ | ||
44 | u8 bit; /* register bit position (as per doc) | ||
45 | bit mask = 1 << (31 - bit) */ | ||
46 | u8 prio_mask; /* priority mask value */ | ||
47 | }; | ||
48 | |||
49 | #endif /* __IPIC_H__ */ | ||