]>
Commit | Line | Data |
---|---|---|
f780aa2a WD |
1 | /* |
2 | * (C) Copyright 2000-2002 | |
3 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
4 | * | |
5 | * (C) Copyright 2002 (440 port) | |
6 | * Scott McNutt, Artesyn Communication Producs, smcnutt@artsyncp.com | |
7 | * | |
ba56f625 WD |
8 | * (C) Copyright 2003 (440GX port) |
9 | * Travis B. Sawyer, Sandburst Corporation, tsawyer@sandburst.com | |
10 | * | |
f780aa2a WD |
11 | * See file CREDITS for list of people who contributed to this |
12 | * project. | |
13 | * | |
14 | * This program is free software; you can redistribute it and/or | |
15 | * modify it under the terms of the GNU General Public License as | |
16 | * published by the Free Software Foundation; either version 2 of | |
17 | * the License, or (at your option) any later version. | |
18 | * | |
19 | * This program is distributed in the hope that it will be useful, | |
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
22 | * GNU General Public License for more details. | |
23 | * | |
24 | * You should have received a copy of the GNU General Public License | |
25 | * along with this program; if not, write to the Free Software | |
26 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
27 | * MA 02111-1307 USA | |
28 | */ | |
29 | ||
30 | #include <common.h> | |
31 | #include <watchdog.h> | |
32 | #include <command.h> | |
f780aa2a WD |
33 | #include <asm/processor.h> |
34 | #include <ppc4xx.h> | |
35 | #include <ppc_asm.tmpl> | |
36 | #include <commproc.h> | |
37 | #include "vecnum.h" | |
38 | ||
d87080b7 WD |
39 | DECLARE_GLOBAL_DATA_PTR; |
40 | ||
f780aa2a WD |
41 | /****************************************************************************/ |
42 | ||
f780aa2a WD |
43 | /* |
44 | * CPM interrupt vector functions. | |
45 | */ | |
46 | struct irq_action { | |
47 | interrupt_handler_t *handler; | |
48 | void *arg; | |
49 | int count; | |
50 | }; | |
51 | ||
52 | static struct irq_action irq_vecs[32]; | |
6c5879f3 | 53 | void uic0_interrupt( void * parms); /* UIC0 handler */ |
f780aa2a WD |
54 | |
55 | #if defined(CONFIG_440) | |
56 | static struct irq_action irq_vecs1[32]; /* For UIC1 */ | |
57 | ||
58 | void uic1_interrupt( void * parms); /* UIC1 handler */ | |
ba56f625 | 59 | |
887e2ec9 SR |
60 | #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ |
61 | defined(CONFIG_440EPX) || defined(CONFIG_440GRX) | |
ba56f625 | 62 | static struct irq_action irq_vecs2[32]; /* For UIC2 */ |
ba56f625 | 63 | void uic2_interrupt( void * parms); /* UIC2 handler */ |
6c5879f3 MB |
64 | #endif /* CONFIG_440GX CONFIG_440SPE */ |
65 | ||
887e2ec9 | 66 | #if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) |
6c5879f3 MB |
67 | static struct irq_action irq_vecs3[32]; /* For UIC3 */ |
68 | void uic3_interrupt( void * parms); /* UIC3 handler */ | |
69 | #endif /* CONFIG_440SPE */ | |
ba56f625 WD |
70 | |
71 | #endif /* CONFIG_440 */ | |
f780aa2a WD |
72 | |
73 | /****************************************************************************/ | |
f780aa2a WD |
74 | #if defined(CONFIG_440) |
75 | ||
76 | /* SPRN changed in 440 */ | |
77 | static __inline__ void set_evpr(unsigned long val) | |
78 | { | |
79 | asm volatile("mtspr 0x03f,%0" : : "r" (val)); | |
80 | } | |
81 | ||
82 | #else /* !defined(CONFIG_440) */ | |
83 | ||
f780aa2a WD |
84 | static __inline__ void set_pit(unsigned long val) |
85 | { | |
86 | asm volatile("mtpit %0" : : "r" (val)); | |
87 | } | |
88 | ||
89 | ||
90 | static __inline__ void set_tcr(unsigned long val) | |
91 | { | |
92 | asm volatile("mttcr %0" : : "r" (val)); | |
93 | } | |
94 | ||
95 | ||
96 | static __inline__ void set_evpr(unsigned long val) | |
97 | { | |
98 | asm volatile("mtevpr %0" : : "r" (val)); | |
99 | } | |
100 | #endif /* defined(CONFIG_440 */ | |
101 | ||
f780aa2a WD |
102 | /****************************************************************************/ |
103 | ||
a8c7c708 | 104 | int interrupt_init_cpu (unsigned *decrementer_count) |
f780aa2a | 105 | { |
f780aa2a WD |
106 | int vec; |
107 | unsigned long val; | |
108 | ||
a8c7c708 WD |
109 | /* decrementer is automatically reloaded */ |
110 | *decrementer_count = 0; | |
d4ca31c4 | 111 | |
f780aa2a WD |
112 | /* |
113 | * Mark all irqs as free | |
114 | */ | |
115 | for (vec=0; vec<32; vec++) { | |
116 | irq_vecs[vec].handler = NULL; | |
117 | irq_vecs[vec].arg = NULL; | |
118 | irq_vecs[vec].count = 0; | |
119 | #if defined(CONFIG_440) | |
120 | irq_vecs1[vec].handler = NULL; | |
121 | irq_vecs1[vec].arg = NULL; | |
122 | irq_vecs1[vec].count = 0; | |
887e2ec9 SR |
123 | #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ |
124 | defined(CONFIG_440EPX) || defined(CONFIG_440GRX) | |
ba56f625 WD |
125 | irq_vecs2[vec].handler = NULL; |
126 | irq_vecs2[vec].arg = NULL; | |
127 | irq_vecs2[vec].count = 0; | |
846b0dd2 | 128 | #endif /* CONFIG_440GX */ |
887e2ec9 | 129 | #if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) |
6c5879f3 MB |
130 | irq_vecs3[vec].handler = NULL; |
131 | irq_vecs3[vec].arg = NULL; | |
132 | irq_vecs3[vec].count = 0; | |
133 | #endif /* CONFIG_440SPE */ | |
f780aa2a WD |
134 | #endif |
135 | } | |
136 | ||
137 | #ifdef CONFIG_4xx | |
138 | /* | |
139 | * Init PIT | |
140 | */ | |
141 | #if defined(CONFIG_440) | |
142 | val = mfspr( tcr ); | |
143 | val &= (~0x04400000); /* clear DIS & ARE */ | |
144 | mtspr( tcr, val ); | |
145 | mtspr( dec, 0 ); /* Prevent exception after TSR clear*/ | |
146 | mtspr( decar, 0 ); /* clear reload */ | |
147 | mtspr( tsr, 0x08000000 ); /* clear DEC status */ | |
68e0236f | 148 | val = gd->bd->bi_intfreq/1000; /* 1 msec */ |
f780aa2a WD |
149 | mtspr( decar, val ); /* Set auto-reload value */ |
150 | mtspr( dec, val ); /* Set inital val */ | |
151 | #else | |
152 | set_pit(gd->bd->bi_intfreq / 1000); | |
153 | #endif | |
154 | #endif /* CONFIG_4xx */ | |
155 | ||
156 | #ifdef CONFIG_ADCIOP | |
157 | /* | |
158 | * Init PIT | |
159 | */ | |
160 | set_pit(66000); | |
161 | #endif | |
162 | ||
163 | /* | |
164 | * Enable PIT | |
165 | */ | |
166 | val = mfspr(tcr); | |
167 | val |= 0x04400000; | |
168 | mtspr(tcr, val); | |
169 | ||
170 | /* | |
171 | * Set EVPR to 0 | |
172 | */ | |
173 | set_evpr(0x00000000); | |
174 | ||
175 | #if defined(CONFIG_440) | |
846b0dd2 | 176 | #if !defined(CONFIG_440GX) |
f780aa2a WD |
177 | /* Install the UIC1 handlers */ |
178 | irq_install_handler(VECNUM_UIC1NC, uic1_interrupt, 0); | |
179 | irq_install_handler(VECNUM_UIC1C, uic1_interrupt, 0); | |
180 | #endif | |
ba56f625 WD |
181 | #endif |
182 | ||
846b0dd2 | 183 | #if defined(CONFIG_440GX) |
aaf224ab WD |
184 | /* Take the GX out of compatibility mode |
185 | * Travis Sawyer, 9 Mar 2004 | |
186 | * NOTE: 440gx user manual inconsistency here | |
187 | * Compatibility mode and Ethernet Clock select are not | |
188 | * correct in the manual | |
189 | */ | |
190 | mfsdr(sdr_mfr, val); | |
191 | val &= ~0x10000000; | |
192 | mtsdr(sdr_mfr,val); | |
193 | ||
ba56f625 | 194 | /* Enable UIC interrupts via UIC Base Enable Register */ |
aaf224ab WD |
195 | mtdcr(uicb0sr, UICB0_ALL); |
196 | mtdcr(uicb0er, 0x54000000); | |
197 | /* None are critical */ | |
198 | mtdcr(uicb0cr, 0); | |
ba56f625 | 199 | #endif |
f780aa2a WD |
200 | |
201 | return (0); | |
202 | } | |
203 | ||
204 | /****************************************************************************/ | |
205 | ||
206 | /* | |
207 | * Handle external interrupts | |
208 | */ | |
846b0dd2 | 209 | #if defined(CONFIG_440GX) |
ba56f625 WD |
210 | void external_interrupt(struct pt_regs *regs) |
211 | { | |
212 | ulong uic_msr; | |
213 | ||
214 | /* | |
215 | * Read masked interrupt status register to determine interrupt source | |
216 | */ | |
217 | /* 440 GX uses base uic register */ | |
218 | uic_msr = mfdcr(uicb0msr); | |
219 | ||
aaf224ab WD |
220 | if ( (UICB0_UIC0CI & uic_msr) || (UICB0_UIC0NCI & uic_msr) ) |
221 | uic0_interrupt(0); | |
ba56f625 | 222 | |
aaf224ab WD |
223 | if ( (UICB0_UIC1CI & uic_msr) || (UICB0_UIC1NCI & uic_msr) ) |
224 | uic1_interrupt(0); | |
225 | ||
226 | if ( (UICB0_UIC2CI & uic_msr) || (UICB0_UIC2NCI & uic_msr) ) | |
227 | uic2_interrupt(0); | |
228 | ||
229 | mtdcr(uicb0sr, uic_msr); | |
ba56f625 WD |
230 | |
231 | return; | |
232 | ||
846b0dd2 | 233 | } /* external_interrupt CONFIG_440GX */ |
ba56f625 | 234 | |
887e2ec9 SR |
235 | #elif defined(CONFIG_440EPX) || defined(CONFIG_440GRX) |
236 | void external_interrupt(struct pt_regs *regs) | |
237 | { | |
238 | ulong uic_msr; | |
239 | ||
240 | /* | |
241 | * Read masked interrupt status register to determine interrupt source | |
242 | */ | |
243 | /* 440 SPe uses base uic register */ | |
244 | uic_msr = mfdcr(uic0msr); | |
245 | ||
246 | if ( (UICB0_UIC1CI & uic_msr) || (UICB0_UIC1NCI & uic_msr) ) | |
247 | uic1_interrupt(0); | |
248 | ||
249 | if ( (UICB0_UIC2CI & uic_msr) || (UICB0_UIC2NCI & uic_msr) ) | |
250 | uic2_interrupt(0); | |
251 | ||
252 | if (uic_msr & ~(UICB0_ALL)) | |
253 | uic0_interrupt(0); | |
254 | ||
255 | mtdcr(uic0sr, uic_msr); | |
256 | ||
257 | return; | |
258 | ||
259 | } /* external_interrupt CONFIG_440EPX & CONFIG_440GRX */ | |
260 | ||
6c5879f3 MB |
261 | #elif defined(CONFIG_440SPE) |
262 | void external_interrupt(struct pt_regs *regs) | |
263 | { | |
264 | ulong uic_msr; | |
265 | ||
266 | /* | |
267 | * Read masked interrupt status register to determine interrupt source | |
268 | */ | |
269 | /* 440 SPe uses base uic register */ | |
270 | uic_msr = mfdcr(uic0msr); | |
271 | ||
272 | if ( (UICB0_UIC1CI & uic_msr) || (UICB0_UIC1NCI & uic_msr) ) | |
273 | uic1_interrupt(0); | |
274 | ||
275 | if ( (UICB0_UIC2CI & uic_msr) || (UICB0_UIC2NCI & uic_msr) ) | |
276 | uic2_interrupt(0); | |
277 | ||
278 | if ( (UICB0_UIC3CI & uic_msr) || (UICB0_UIC3NCI & uic_msr) ) | |
279 | uic3_interrupt(0); | |
280 | ||
281 | if (uic_msr & ~(UICB0_ALL)) | |
282 | uic0_interrupt(0); | |
283 | ||
284 | mtdcr(uic0sr, uic_msr); | |
285 | ||
286 | return; | |
287 | } /* external_interrupt CONFIG_440SPE */ | |
288 | ||
ba56f625 WD |
289 | #else |
290 | ||
f780aa2a WD |
291 | void external_interrupt(struct pt_regs *regs) |
292 | { | |
293 | ulong uic_msr; | |
294 | ulong msr_shift; | |
295 | int vec; | |
296 | ||
297 | /* | |
298 | * Read masked interrupt status register to determine interrupt source | |
299 | */ | |
300 | uic_msr = mfdcr(uicmsr); | |
301 | msr_shift = uic_msr; | |
302 | vec = 0; | |
303 | ||
304 | while (msr_shift != 0) { | |
305 | if (msr_shift & 0x80000000) { | |
306 | /* | |
307 | * Increment irq counter (for debug purpose only) | |
308 | */ | |
309 | irq_vecs[vec].count++; | |
310 | ||
311 | if (irq_vecs[vec].handler != NULL) { | |
312 | /* call isr */ | |
313 | (*irq_vecs[vec].handler)(irq_vecs[vec].arg); | |
314 | } else { | |
315 | mtdcr(uicer, mfdcr(uicer) & ~(0x80000000 >> vec)); | |
316 | printf ("Masking bogus interrupt vector 0x%x\n", vec); | |
317 | } | |
318 | ||
319 | /* | |
320 | * After servicing the interrupt, we have to remove the status indicator. | |
321 | */ | |
322 | mtdcr(uicsr, (0x80000000 >> vec)); | |
323 | } | |
324 | ||
325 | /* | |
326 | * Shift msr to next position and increment vector | |
327 | */ | |
328 | msr_shift <<= 1; | |
329 | vec++; | |
330 | } | |
331 | } | |
ba56f625 WD |
332 | #endif |
333 | ||
887e2ec9 SR |
334 | #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ |
335 | defined(CONFIG_440EPX) || defined(CONFIG_440GRX) | |
ba56f625 WD |
336 | /* Handler for UIC0 interrupt */ |
337 | void uic0_interrupt( void * parms) | |
338 | { | |
339 | ulong uic_msr; | |
340 | ulong msr_shift; | |
341 | int vec; | |
342 | ||
343 | /* | |
344 | * Read masked interrupt status register to determine interrupt source | |
345 | */ | |
346 | uic_msr = mfdcr(uicmsr); | |
347 | msr_shift = uic_msr; | |
348 | vec = 0; | |
349 | ||
350 | while (msr_shift != 0) { | |
351 | if (msr_shift & 0x80000000) { | |
352 | /* | |
353 | * Increment irq counter (for debug purpose only) | |
354 | */ | |
355 | irq_vecs[vec].count++; | |
356 | ||
357 | if (irq_vecs[vec].handler != NULL) { | |
358 | /* call isr */ | |
359 | (*irq_vecs[vec].handler)(irq_vecs[vec].arg); | |
360 | } else { | |
361 | mtdcr(uicer, mfdcr(uicer) & ~(0x80000000 >> vec)); | |
362 | printf ("Masking bogus interrupt vector (uic0) 0x%x\n", vec); | |
363 | } | |
364 | ||
365 | /* | |
366 | * After servicing the interrupt, we have to remove the status indicator. | |
367 | */ | |
368 | mtdcr(uicsr, (0x80000000 >> vec)); | |
369 | } | |
370 | ||
371 | /* | |
372 | * Shift msr to next position and increment vector | |
373 | */ | |
374 | msr_shift <<= 1; | |
375 | vec++; | |
376 | } | |
377 | } | |
378 | ||
846b0dd2 | 379 | #endif /* CONFIG_440GX */ |
f780aa2a WD |
380 | |
381 | #if defined(CONFIG_440) | |
382 | /* Handler for UIC1 interrupt */ | |
383 | void uic1_interrupt( void * parms) | |
384 | { | |
385 | ulong uic1_msr; | |
386 | ulong msr_shift; | |
387 | int vec; | |
388 | ||
389 | /* | |
390 | * Read masked interrupt status register to determine interrupt source | |
391 | */ | |
392 | uic1_msr = mfdcr(uic1msr); | |
393 | msr_shift = uic1_msr; | |
394 | vec = 0; | |
395 | ||
396 | while (msr_shift != 0) { | |
397 | if (msr_shift & 0x80000000) { | |
398 | /* | |
399 | * Increment irq counter (for debug purpose only) | |
400 | */ | |
401 | irq_vecs1[vec].count++; | |
402 | ||
403 | if (irq_vecs1[vec].handler != NULL) { | |
404 | /* call isr */ | |
405 | (*irq_vecs1[vec].handler)(irq_vecs1[vec].arg); | |
406 | } else { | |
407 | mtdcr(uic1er, mfdcr(uic1er) & ~(0x80000000 >> vec)); | |
408 | printf ("Masking bogus interrupt vector (uic1) 0x%x\n", vec); | |
409 | } | |
410 | ||
411 | /* | |
412 | * After servicing the interrupt, we have to remove the status indicator. | |
413 | */ | |
414 | mtdcr(uic1sr, (0x80000000 >> vec)); | |
415 | } | |
416 | ||
417 | /* | |
418 | * Shift msr to next position and increment vector | |
419 | */ | |
420 | msr_shift <<= 1; | |
421 | vec++; | |
422 | } | |
423 | } | |
424 | #endif /* defined(CONFIG_440) */ | |
425 | ||
887e2ec9 SR |
426 | #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ |
427 | defined(CONFIG_440EPX) || defined(CONFIG_440GRX) | |
6c5879f3 | 428 | /* Handler for UIC2 interrupt */ |
ba56f625 WD |
429 | void uic2_interrupt( void * parms) |
430 | { | |
431 | ulong uic2_msr; | |
432 | ulong msr_shift; | |
433 | int vec; | |
434 | ||
435 | /* | |
436 | * Read masked interrupt status register to determine interrupt source | |
437 | */ | |
438 | uic2_msr = mfdcr(uic2msr); | |
439 | msr_shift = uic2_msr; | |
440 | vec = 0; | |
441 | ||
442 | while (msr_shift != 0) { | |
443 | if (msr_shift & 0x80000000) { | |
444 | /* | |
445 | * Increment irq counter (for debug purpose only) | |
446 | */ | |
447 | irq_vecs2[vec].count++; | |
448 | ||
449 | if (irq_vecs2[vec].handler != NULL) { | |
450 | /* call isr */ | |
451 | (*irq_vecs2[vec].handler)(irq_vecs2[vec].arg); | |
452 | } else { | |
453 | mtdcr(uic2er, mfdcr(uic2er) & ~(0x80000000 >> vec)); | |
6c5879f3 | 454 | printf ("Masking bogus interrupt vector (uic2) 0x%x\n", vec); |
ba56f625 WD |
455 | } |
456 | ||
457 | /* | |
458 | * After servicing the interrupt, we have to remove the status indicator. | |
459 | */ | |
460 | mtdcr(uic2sr, (0x80000000 >> vec)); | |
461 | } | |
462 | ||
463 | /* | |
464 | * Shift msr to next position and increment vector | |
465 | */ | |
466 | msr_shift <<= 1; | |
467 | vec++; | |
468 | } | |
469 | } | |
846b0dd2 | 470 | #endif /* defined(CONFIG_440GX) */ |
ba56f625 | 471 | |
6c5879f3 MB |
472 | #if defined(CONFIG_440SPE) |
473 | /* Handler for UIC3 interrupt */ | |
474 | void uic3_interrupt( void * parms) | |
475 | { | |
476 | ulong uic3_msr; | |
477 | ulong msr_shift; | |
478 | int vec; | |
479 | ||
480 | /* | |
481 | * Read masked interrupt status register to determine interrupt source | |
482 | */ | |
483 | uic3_msr = mfdcr(uic3msr); | |
484 | msr_shift = uic3_msr; | |
485 | vec = 0; | |
486 | ||
487 | while (msr_shift != 0) { | |
488 | if (msr_shift & 0x80000000) { | |
489 | /* | |
490 | * Increment irq counter (for debug purpose only) | |
491 | */ | |
492 | irq_vecs3[vec].count++; | |
493 | ||
494 | if (irq_vecs3[vec].handler != NULL) { | |
495 | /* call isr */ | |
496 | (*irq_vecs3[vec].handler)(irq_vecs3[vec].arg); | |
497 | } else { | |
498 | mtdcr(uic3er, mfdcr(uic3er) & ~(0x80000000 >> vec)); | |
499 | printf ("Masking bogus interrupt vector (uic3) 0x%x\n", vec); | |
500 | } | |
501 | ||
502 | /* | |
503 | * After servicing the interrupt, we have to remove the status indicator. | |
504 | */ | |
505 | mtdcr(uic3sr, (0x80000000 >> vec)); | |
506 | } | |
507 | ||
508 | /* | |
509 | * Shift msr to next position and increment vector | |
510 | */ | |
511 | msr_shift <<= 1; | |
512 | vec++; | |
513 | } | |
514 | } | |
515 | #endif /* defined(CONFIG_440SPE) */ | |
516 | ||
f780aa2a WD |
517 | /****************************************************************************/ |
518 | ||
519 | /* | |
520 | * Install and free a interrupt handler. | |
521 | */ | |
522 | ||
ba56f625 | 523 | void irq_install_handler (int vec, interrupt_handler_t * handler, void *arg) |
f780aa2a WD |
524 | { |
525 | struct irq_action *irqa = irq_vecs; | |
ba56f625 | 526 | int i = vec; |
f780aa2a WD |
527 | |
528 | #if defined(CONFIG_440) | |
887e2ec9 SR |
529 | #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ |
530 | defined(CONFIG_440EPX) || defined(CONFIG_440GRX) | |
ba56f625 WD |
531 | if ((vec > 31) && (vec < 64)) { |
532 | i = vec - 32; | |
533 | irqa = irq_vecs1; | |
534 | } else if (vec > 63) { | |
535 | i = vec - 64; | |
536 | irqa = irq_vecs2; | |
537 | } | |
846b0dd2 | 538 | #else /* CONFIG_440GX */ |
f780aa2a WD |
539 | if (vec > 31) { |
540 | i = vec - 32; | |
541 | irqa = irq_vecs1; | |
542 | } | |
846b0dd2 | 543 | #endif /* CONFIG_440GX */ |
ba56f625 | 544 | #endif /* CONFIG_440 */ |
f780aa2a | 545 | |
c157d8e2 SR |
546 | /* |
547 | * print warning when replacing with a different irq vector | |
548 | */ | |
549 | if ((irqa[i].handler != NULL) && (irqa[i].handler != handler)) { | |
f780aa2a | 550 | printf ("Interrupt vector %d: handler 0x%x replacing 0x%x\n", |
ba56f625 | 551 | vec, (uint) handler, (uint) irqa[i].handler); |
f780aa2a WD |
552 | } |
553 | irqa[i].handler = handler; | |
ba56f625 | 554 | irqa[i].arg = arg; |
f780aa2a WD |
555 | |
556 | #if defined(CONFIG_440) | |
887e2ec9 SR |
557 | #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ |
558 | defined(CONFIG_440EPX) || defined(CONFIG_440GRX) | |
ba56f625 WD |
559 | if ((vec > 31) && (vec < 64)) |
560 | mtdcr (uic1er, mfdcr (uic1er) | (0x80000000 >> i)); | |
561 | else if (vec > 63) | |
562 | mtdcr (uic2er, mfdcr (uic2er) | (0x80000000 >> i)); | |
563 | else | |
846b0dd2 | 564 | #endif /* CONFIG_440GX */ |
ba56f625 WD |
565 | if (vec > 31) |
566 | mtdcr (uic1er, mfdcr (uic1er) | (0x80000000 >> i)); | |
f780aa2a WD |
567 | else |
568 | #endif | |
ba56f625 | 569 | mtdcr (uicer, mfdcr (uicer) | (0x80000000 >> i)); |
f780aa2a WD |
570 | #if 0 |
571 | printf ("Install interrupt for vector %d ==> %p\n", vec, handler); | |
572 | #endif | |
573 | } | |
574 | ||
ba56f625 | 575 | void irq_free_handler (int vec) |
f780aa2a WD |
576 | { |
577 | struct irq_action *irqa = irq_vecs; | |
ba56f625 | 578 | int i = vec; |
f780aa2a WD |
579 | |
580 | #if defined(CONFIG_440) | |
887e2ec9 SR |
581 | #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ |
582 | defined(CONFIG_440EPX) || defined(CONFIG_440GRX) | |
ba56f625 WD |
583 | if ((vec > 31) && (vec < 64)) { |
584 | irqa = irq_vecs1; | |
585 | i = vec - 32; | |
586 | } else if (vec > 63) { | |
587 | irqa = irq_vecs2; | |
588 | i = vec - 64; | |
589 | } | |
846b0dd2 | 590 | #endif /* CONFIG_440GX */ |
f780aa2a WD |
591 | if (vec > 31) { |
592 | irqa = irq_vecs1; | |
593 | i = vec - 32; | |
594 | } | |
595 | #endif | |
596 | ||
597 | #if 0 | |
598 | printf ("Free interrupt for vector %d ==> %p\n", | |
599 | vec, irq_vecs[vec].handler); | |
600 | #endif | |
601 | ||
602 | #if defined(CONFIG_440) | |
887e2ec9 SR |
603 | #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ |
604 | defined(CONFIG_440EPX) || defined(CONFIG_440GRX) | |
ba56f625 WD |
605 | if ((vec > 31) && (vec < 64)) |
606 | mtdcr (uic1er, mfdcr (uic1er) & ~(0x80000000 >> i)); | |
607 | else if (vec > 63) | |
608 | mtdcr (uic2er, mfdcr (uic2er) & ~(0x80000000 >> i)); | |
609 | else | |
846b0dd2 | 610 | #endif /* CONFIG_440GX */ |
f780aa2a | 611 | if (vec > 31) |
ba56f625 | 612 | mtdcr (uic1er, mfdcr (uic1er) & ~(0x80000000 >> i)); |
f780aa2a WD |
613 | else |
614 | #endif | |
ba56f625 | 615 | mtdcr (uicer, mfdcr (uicer) & ~(0x80000000 >> i)); |
f780aa2a WD |
616 | |
617 | irqa[i].handler = NULL; | |
ba56f625 | 618 | irqa[i].arg = NULL; |
f780aa2a WD |
619 | } |
620 | ||
621 | /****************************************************************************/ | |
622 | ||
a8c7c708 | 623 | void timer_interrupt_cpu (struct pt_regs *regs) |
f780aa2a | 624 | { |
a8c7c708 WD |
625 | /* nothing to do here */ |
626 | return; | |
f780aa2a WD |
627 | } |
628 | ||
629 | /****************************************************************************/ | |
630 | ||
f780aa2a WD |
631 | #if (CONFIG_COMMANDS & CFG_CMD_IRQ) |
632 | ||
633 | /******************************************************************************* | |
634 | * | |
635 | * irqinfo - print information about PCI devices | |
636 | * | |
637 | */ | |
638 | int | |
639 | do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) | |
640 | { | |
641 | int vec; | |
642 | ||
643 | printf ("\nInterrupt-Information:\n"); | |
644 | #if defined(CONFIG_440) | |
645 | printf ("\nUIC 0\n"); | |
646 | #endif | |
647 | printf ("Nr Routine Arg Count\n"); | |
648 | ||
649 | for (vec=0; vec<32; vec++) { | |
650 | if (irq_vecs[vec].handler != NULL) { | |
651 | printf ("%02d %08lx %08lx %d\n", | |
652 | vec, | |
653 | (ulong)irq_vecs[vec].handler, | |
654 | (ulong)irq_vecs[vec].arg, | |
655 | irq_vecs[vec].count); | |
656 | } | |
657 | } | |
658 | ||
659 | #if defined(CONFIG_440) | |
660 | printf ("\nUIC 1\n"); | |
661 | printf ("Nr Routine Arg Count\n"); | |
662 | ||
ba56f625 | 663 | for (vec=0; vec<32; vec++) { |
f780aa2a WD |
664 | if (irq_vecs1[vec].handler != NULL) |
665 | printf ("%02d %08lx %08lx %d\n", | |
666 | vec+31, (ulong)irq_vecs1[vec].handler, | |
667 | (ulong)irq_vecs1[vec].arg, irq_vecs1[vec].count); | |
668 | } | |
669 | printf("\n"); | |
670 | #endif | |
f780aa2a | 671 | |
887e2ec9 SR |
672 | #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ |
673 | defined(CONFIG_440EPX) || defined(CONFIG_440GRX) | |
ba56f625 WD |
674 | printf ("\nUIC 2\n"); |
675 | printf ("Nr Routine Arg Count\n"); | |
f780aa2a | 676 | |
ba56f625 WD |
677 | for (vec=0; vec<32; vec++) { |
678 | if (irq_vecs2[vec].handler != NULL) | |
679 | printf ("%02d %08lx %08lx %d\n", | |
680 | vec+63, (ulong)irq_vecs2[vec].handler, | |
681 | (ulong)irq_vecs2[vec].arg, irq_vecs2[vec].count); | |
682 | } | |
683 | printf("\n"); | |
684 | #endif | |
685 | ||
6c5879f3 MB |
686 | #if defined(CONFIG_440SPE) |
687 | printf ("\nUIC 3\n"); | |
688 | printf ("Nr Routine Arg Count\n"); | |
689 | ||
690 | for (vec=0; vec<32; vec++) { | |
691 | if (irq_vecs3[vec].handler != NULL) | |
692 | printf ("%02d %08lx %08lx %d\n", | |
693 | vec+63, (ulong)irq_vecs3[vec].handler, | |
694 | (ulong)irq_vecs3[vec].arg, irq_vecs3[vec].count); | |
695 | } | |
696 | printf("\n"); | |
697 | #endif | |
698 | ||
ba56f625 WD |
699 | return 0; |
700 | } | |
f780aa2a | 701 | #endif /* CONFIG_COMMANDS & CFG_CMD_IRQ */ |