blob: 2f3dc326b4667fe6b78b1eb8856325ab40d058b1 [file] [log] [blame]
wdenkf780aa22002-09-18 19:21:21 +00001/*
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 *
wdenk544e9732004-02-06 23:19:44 +00008 * (C) Copyright 2003 (440GX port)
9 * Travis B. Sawyer, Sandburst Corporation, tsawyer@sandburst.com
10 *
wdenkf780aa22002-09-18 19:21:21 +000011 * 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>
wdenkf780aa22002-09-18 19:21:21 +000033#include <asm/processor.h>
34#include <ppc4xx.h>
35#include <ppc_asm.tmpl>
36#include <commproc.h>
Matthias Fuchs0d548f92008-01-08 15:50:49 +010037#include <asm/ppc4xx-intvec.h>
wdenkf780aa22002-09-18 19:21:21 +000038
Wolfgang Denk6405a152006-03-31 18:32:53 +020039DECLARE_GLOBAL_DATA_PTR;
40
wdenkf780aa22002-09-18 19:21:21 +000041/****************************************************************************/
42
wdenkf780aa22002-09-18 19:21:21 +000043/*
44 * CPM interrupt vector functions.
45 */
46struct irq_action {
47 interrupt_handler_t *handler;
48 void *arg;
49 int count;
50};
51
52static struct irq_action irq_vecs[32];
Marian Balakowicz49d0eee2006-06-30 16:30:46 +020053void uic0_interrupt( void * parms); /* UIC0 handler */
wdenkf780aa22002-09-18 19:21:21 +000054
Stefan Roese153b3e22007-10-05 17:10:59 +020055#if defined(CONFIG_440) || defined(CONFIG_405EX)
wdenkf780aa22002-09-18 19:21:21 +000056static struct irq_action irq_vecs1[32]; /* For UIC1 */
57
58void uic1_interrupt( void * parms); /* UIC1 handler */
wdenk544e9732004-02-06 23:19:44 +000059
Stefan Roese42fbddd2006-09-07 11:51:23 +020060#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
61 defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
wdenk544e9732004-02-06 23:19:44 +000062static struct irq_action irq_vecs2[32]; /* For UIC2 */
wdenk544e9732004-02-06 23:19:44 +000063void uic2_interrupt( void * parms); /* UIC2 handler */
Marian Balakowicz49d0eee2006-06-30 16:30:46 +020064#endif /* CONFIG_440GX CONFIG_440SPE */
65
Stefan Roese42fbddd2006-09-07 11:51:23 +020066#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
Marian Balakowicz49d0eee2006-06-30 16:30:46 +020067static struct irq_action irq_vecs3[32]; /* For UIC3 */
68void uic3_interrupt( void * parms); /* UIC3 handler */
69#endif /* CONFIG_440SPE */
wdenk544e9732004-02-06 23:19:44 +000070
71#endif /* CONFIG_440 */
wdenkf780aa22002-09-18 19:21:21 +000072
73/****************************************************************************/
wdenkf780aa22002-09-18 19:21:21 +000074#if defined(CONFIG_440)
75
76/* SPRN changed in 440 */
77static __inline__ void set_evpr(unsigned long val)
78{
79 asm volatile("mtspr 0x03f,%0" : : "r" (val));
80}
81
82#else /* !defined(CONFIG_440) */
83
wdenkf780aa22002-09-18 19:21:21 +000084static __inline__ void set_pit(unsigned long val)
85{
86 asm volatile("mtpit %0" : : "r" (val));
87}
88
89
90static __inline__ void set_tcr(unsigned long val)
91{
92 asm volatile("mttcr %0" : : "r" (val));
93}
94
95
96static __inline__ void set_evpr(unsigned long val)
97{
98 asm volatile("mtevpr %0" : : "r" (val));
99}
100#endif /* defined(CONFIG_440 */
101
wdenkf780aa22002-09-18 19:21:21 +0000102/****************************************************************************/
103
wdenkc0aa5c52003-12-06 19:49:23 +0000104int interrupt_init_cpu (unsigned *decrementer_count)
wdenkf780aa22002-09-18 19:21:21 +0000105{
wdenkf780aa22002-09-18 19:21:21 +0000106 int vec;
107 unsigned long val;
108
wdenkc0aa5c52003-12-06 19:49:23 +0000109 /* decrementer is automatically reloaded */
110 *decrementer_count = 0;
wdenk1ebf41e2004-01-02 14:00:00 +0000111
wdenkf780aa22002-09-18 19:21:21 +0000112 /*
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;
Stefan Roese153b3e22007-10-05 17:10:59 +0200119#if defined(CONFIG_440) || defined(CONFIG_405EX)
wdenkf780aa22002-09-18 19:21:21 +0000120 irq_vecs1[vec].handler = NULL;
121 irq_vecs1[vec].arg = NULL;
122 irq_vecs1[vec].count = 0;
Stefan Roese42fbddd2006-09-07 11:51:23 +0200123#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
124 defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
wdenk544e9732004-02-06 23:19:44 +0000125 irq_vecs2[vec].handler = NULL;
126 irq_vecs2[vec].arg = NULL;
127 irq_vecs2[vec].count = 0;
Stefan Roeseb30f2a12005-08-08 12:42:22 +0200128#endif /* CONFIG_440GX */
Stefan Roese42fbddd2006-09-07 11:51:23 +0200129#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
Marian Balakowicz49d0eee2006-06-30 16:30:46 +0200130 irq_vecs3[vec].handler = NULL;
131 irq_vecs3[vec].arg = NULL;
132 irq_vecs3[vec].count = 0;
133#endif /* CONFIG_440SPE */
wdenkf780aa22002-09-18 19:21:21 +0000134#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 */
stroese4b31de82005-04-07 05:32:44 +0000148 val = gd->bd->bi_intfreq/1000; /* 1 msec */
wdenkf780aa22002-09-18 19:21:21 +0000149 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
Stefan Roese153b3e22007-10-05 17:10:59 +0200175#if defined(CONFIG_440) || defined(CONFIG_405EX)
Stefan Roeseb30f2a12005-08-08 12:42:22 +0200176#if !defined(CONFIG_440GX)
wdenkf780aa22002-09-18 19:21:21 +0000177 /* Install the UIC1 handlers */
178 irq_install_handler(VECNUM_UIC1NC, uic1_interrupt, 0);
179 irq_install_handler(VECNUM_UIC1C, uic1_interrupt, 0);
180#endif
wdenk544e9732004-02-06 23:19:44 +0000181#endif
182
Stefan Roeseb30f2a12005-08-08 12:42:22 +0200183#if defined(CONFIG_440GX)
wdenke28cf632004-03-14 15:20:55 +0000184 /* 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
wdenk544e9732004-02-06 23:19:44 +0000194 /* Enable UIC interrupts via UIC Base Enable Register */
wdenke28cf632004-03-14 15:20:55 +0000195 mtdcr(uicb0sr, UICB0_ALL);
196 mtdcr(uicb0er, 0x54000000);
197 /* None are critical */
198 mtdcr(uicb0cr, 0);
wdenk544e9732004-02-06 23:19:44 +0000199#endif
wdenkf780aa22002-09-18 19:21:21 +0000200
201 return (0);
202}
203
204/****************************************************************************/
205
206/*
207 * Handle external interrupts
208 */
Stefan Roeseb30f2a12005-08-08 12:42:22 +0200209#if defined(CONFIG_440GX)
wdenkf780aa22002-09-18 19:21:21 +0000210void external_interrupt(struct pt_regs *regs)
211{
212 ulong uic_msr;
wdenk544e9732004-02-06 23:19:44 +0000213
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
wdenke28cf632004-03-14 15:20:55 +0000220 if ( (UICB0_UIC0CI & uic_msr) || (UICB0_UIC0NCI & uic_msr) )
221 uic0_interrupt(0);
wdenk544e9732004-02-06 23:19:44 +0000222
wdenke28cf632004-03-14 15:20:55 +0000223 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);
wdenk544e9732004-02-06 23:19:44 +0000230
231 return;
232
Stefan Roeseb30f2a12005-08-08 12:42:22 +0200233} /* external_interrupt CONFIG_440GX */
wdenk544e9732004-02-06 23:19:44 +0000234
Stefan Roese42fbddd2006-09-07 11:51:23 +0200235#elif defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
236void 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
Marian Balakowicz49d0eee2006-06-30 16:30:46 +0200261#elif defined(CONFIG_440SPE)
262void 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
wdenk544e9732004-02-06 23:19:44 +0000289#else
290
291void external_interrupt(struct pt_regs *regs)
292{
293 ulong uic_msr;
wdenkf780aa22002-09-18 19:21:21 +0000294 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}
wdenk544e9732004-02-06 23:19:44 +0000332#endif
333
Stefan Roese42fbddd2006-09-07 11:51:23 +0200334#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
335 defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
wdenk544e9732004-02-06 23:19:44 +0000336/* Handler for UIC0 interrupt */
337void 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
Stefan Roeseb30f2a12005-08-08 12:42:22 +0200379#endif /* CONFIG_440GX */
wdenkf780aa22002-09-18 19:21:21 +0000380
Stefan Roese153b3e22007-10-05 17:10:59 +0200381#if defined(CONFIG_440) || defined(CONFIG_405EX)
wdenkf780aa22002-09-18 19:21:21 +0000382/* Handler for UIC1 interrupt */
383void 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
Stefan Roese42fbddd2006-09-07 11:51:23 +0200426#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
427 defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
Marian Balakowicz49d0eee2006-06-30 16:30:46 +0200428/* Handler for UIC2 interrupt */
wdenk544e9732004-02-06 23:19:44 +0000429void 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));
Marian Balakowicz49d0eee2006-06-30 16:30:46 +0200454 printf ("Masking bogus interrupt vector (uic2) 0x%x\n", vec);
wdenk544e9732004-02-06 23:19:44 +0000455 }
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}
Stefan Roeseb30f2a12005-08-08 12:42:22 +0200470#endif /* defined(CONFIG_440GX) */
wdenk544e9732004-02-06 23:19:44 +0000471
Marian Balakowicz49d0eee2006-06-30 16:30:46 +0200472#if defined(CONFIG_440SPE)
473/* Handler for UIC3 interrupt */
474void 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
wdenkf780aa22002-09-18 19:21:21 +0000517/****************************************************************************/
518
519/*
520 * Install and free a interrupt handler.
521 */
522
wdenk544e9732004-02-06 23:19:44 +0000523void irq_install_handler (int vec, interrupt_handler_t * handler, void *arg)
wdenkf780aa22002-09-18 19:21:21 +0000524{
525 struct irq_action *irqa = irq_vecs;
wdenk544e9732004-02-06 23:19:44 +0000526 int i = vec;
wdenkf780aa22002-09-18 19:21:21 +0000527
Stefan Roese153b3e22007-10-05 17:10:59 +0200528#if defined(CONFIG_440) || defined(CONFIG_405EX)
Stefan Roese42fbddd2006-09-07 11:51:23 +0200529#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
530 defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
wdenk544e9732004-02-06 23:19:44 +0000531 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 }
Stefan Roeseb30f2a12005-08-08 12:42:22 +0200538#else /* CONFIG_440GX */
wdenkf780aa22002-09-18 19:21:21 +0000539 if (vec > 31) {
540 i = vec - 32;
541 irqa = irq_vecs1;
542 }
Stefan Roeseb30f2a12005-08-08 12:42:22 +0200543#endif /* CONFIG_440GX */
wdenk544e9732004-02-06 23:19:44 +0000544#endif /* CONFIG_440 */
wdenkf780aa22002-09-18 19:21:21 +0000545
Stefan Roese326c9712005-08-01 16:41:48 +0200546 /*
547 * print warning when replacing with a different irq vector
548 */
549 if ((irqa[i].handler != NULL) && (irqa[i].handler != handler)) {
wdenkf780aa22002-09-18 19:21:21 +0000550 printf ("Interrupt vector %d: handler 0x%x replacing 0x%x\n",
wdenk544e9732004-02-06 23:19:44 +0000551 vec, (uint) handler, (uint) irqa[i].handler);
wdenkf780aa22002-09-18 19:21:21 +0000552 }
553 irqa[i].handler = handler;
wdenk544e9732004-02-06 23:19:44 +0000554 irqa[i].arg = arg;
wdenkf780aa22002-09-18 19:21:21 +0000555
Stefan Roese153b3e22007-10-05 17:10:59 +0200556#if defined(CONFIG_440) || defined(CONFIG_405EX)
Stefan Roese42fbddd2006-09-07 11:51:23 +0200557#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
558 defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
wdenk544e9732004-02-06 23:19:44 +0000559 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
Stefan Roeseb30f2a12005-08-08 12:42:22 +0200564#endif /* CONFIG_440GX */
wdenk544e9732004-02-06 23:19:44 +0000565 if (vec > 31)
566 mtdcr (uic1er, mfdcr (uic1er) | (0x80000000 >> i));
wdenkf780aa22002-09-18 19:21:21 +0000567 else
568#endif
wdenk544e9732004-02-06 23:19:44 +0000569 mtdcr (uicer, mfdcr (uicer) | (0x80000000 >> i));
wdenkf780aa22002-09-18 19:21:21 +0000570#if 0
571 printf ("Install interrupt for vector %d ==> %p\n", vec, handler);
572#endif
573}
574
wdenk544e9732004-02-06 23:19:44 +0000575void irq_free_handler (int vec)
wdenkf780aa22002-09-18 19:21:21 +0000576{
577 struct irq_action *irqa = irq_vecs;
wdenk544e9732004-02-06 23:19:44 +0000578 int i = vec;
wdenkf780aa22002-09-18 19:21:21 +0000579
Stefan Roese153b3e22007-10-05 17:10:59 +0200580#if defined(CONFIG_440) || defined(CONFIG_405EX)
Stefan Roese42fbddd2006-09-07 11:51:23 +0200581#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
582 defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
wdenk544e9732004-02-06 23:19:44 +0000583 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 }
Stefan Roeseb30f2a12005-08-08 12:42:22 +0200590#endif /* CONFIG_440GX */
wdenkf780aa22002-09-18 19:21:21 +0000591 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
Stefan Roese153b3e22007-10-05 17:10:59 +0200602#if defined(CONFIG_440) || defined(CONFIG_405EX)
Stefan Roese42fbddd2006-09-07 11:51:23 +0200603#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
604 defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
wdenk544e9732004-02-06 23:19:44 +0000605 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
Stefan Roeseb30f2a12005-08-08 12:42:22 +0200610#endif /* CONFIG_440GX */
wdenkf780aa22002-09-18 19:21:21 +0000611 if (vec > 31)
wdenk544e9732004-02-06 23:19:44 +0000612 mtdcr (uic1er, mfdcr (uic1er) & ~(0x80000000 >> i));
wdenkf780aa22002-09-18 19:21:21 +0000613 else
614#endif
wdenk544e9732004-02-06 23:19:44 +0000615 mtdcr (uicer, mfdcr (uicer) & ~(0x80000000 >> i));
wdenkf780aa22002-09-18 19:21:21 +0000616
617 irqa[i].handler = NULL;
wdenk544e9732004-02-06 23:19:44 +0000618 irqa[i].arg = NULL;
wdenkf780aa22002-09-18 19:21:21 +0000619}
620
621/****************************************************************************/
622
wdenkc0aa5c52003-12-06 19:49:23 +0000623void timer_interrupt_cpu (struct pt_regs *regs)
wdenkf780aa22002-09-18 19:21:21 +0000624{
wdenkc0aa5c52003-12-06 19:49:23 +0000625 /* nothing to do here */
626 return;
wdenkf780aa22002-09-18 19:21:21 +0000627}
628
629/****************************************************************************/
630
Jon Loeligera5217742007-07-09 18:57:22 -0500631#if defined(CONFIG_CMD_IRQ)
wdenkf780aa22002-09-18 19:21:21 +0000632
633/*******************************************************************************
634 *
635 * irqinfo - print information about PCI devices
636 *
637 */
638int
639do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
640{
641 int vec;
642
643 printf ("\nInterrupt-Information:\n");
Stefan Roese153b3e22007-10-05 17:10:59 +0200644#if defined(CONFIG_440) || defined(CONFIG_405EX)
wdenkf780aa22002-09-18 19:21:21 +0000645 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
Stefan Roese153b3e22007-10-05 17:10:59 +0200659#if defined(CONFIG_440) || defined(CONFIG_405EX)
wdenkf780aa22002-09-18 19:21:21 +0000660 printf ("\nUIC 1\n");
661 printf ("Nr Routine Arg Count\n");
662
wdenk544e9732004-02-06 23:19:44 +0000663 for (vec=0; vec<32; vec++) {
wdenkf780aa22002-09-18 19:21:21 +0000664 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
wdenkf780aa22002-09-18 19:21:21 +0000671
Stefan Roese42fbddd2006-09-07 11:51:23 +0200672#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
673 defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
wdenk544e9732004-02-06 23:19:44 +0000674 printf ("\nUIC 2\n");
675 printf ("Nr Routine Arg Count\n");
wdenkf780aa22002-09-18 19:21:21 +0000676
wdenk544e9732004-02-06 23:19:44 +0000677 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
Marian Balakowicz49d0eee2006-06-30 16:30:46 +0200686#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
wdenk544e9732004-02-06 23:19:44 +0000699 return 0;
700}
Jon Loeligera5217742007-07-09 18:57:22 -0500701#endif