* (C) Copyright 2002 (440 port)
* Scott McNutt, Artesyn Communication Producs, smcnutt@artsyncp.com
*
+ * (C) Copyright 2003 (440GX port)
+ * Travis B. Sawyer, Sandburst Corporation, tsawyer@sandburst.com
+ *
+ * (C) Copyright 2008 (PPC440X05 port for Virtex 5 FX)
+ * Ricardo Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es
+ * Work supported by Qtechnology (htpp://qtec.com)
+ *
* See file CREDITS for list of people who contributed to this
* project.
*
#include <watchdog.h>
#include <command.h>
#include <asm/processor.h>
+#include <asm/interrupt.h>
#include <ppc4xx.h>
#include <ppc_asm.tmpl>
#include <commproc.h>
-#include "vecnum.h"
-/****************************************************************************/
+DECLARE_GLOBAL_DATA_PTR;
/*
* CPM interrupt vector functions.
void *arg;
int count;
};
-
-static struct irq_action irq_vecs[32];
+static struct irq_action irq_vecs[IRQ_MAX];
-#if defined(CONFIG_440)
-static struct irq_action irq_vecs1[32]; /* For UIC1 */
-
-void uic1_interrupt( void * parms); /* UIC1 handler */
-#endif
-
-/****************************************************************************/
#if defined(CONFIG_440)
/* SPRN changed in 440 */
}
#endif /* defined(CONFIG_440 */
-/****************************************************************************/
-
int interrupt_init_cpu (unsigned *decrementer_count)
{
- DECLARE_GLOBAL_DATA_PTR;
-
int vec;
unsigned long val;
/* decrementer is automatically reloaded */
*decrementer_count = 0;
-
+
/*
* Mark all irqs as free
*/
- for (vec=0; vec<32; vec++) {
+ for (vec = 0; vec < IRQ_MAX; vec++) {
irq_vecs[vec].handler = NULL;
irq_vecs[vec].arg = NULL;
irq_vecs[vec].count = 0;
-#if defined(CONFIG_440)
- irq_vecs1[vec].handler = NULL;
- irq_vecs1[vec].arg = NULL;
- irq_vecs1[vec].count = 0;
-#endif
}
#ifdef CONFIG_4xx
mtspr( dec, 0 ); /* Prevent exception after TSR clear*/
mtspr( decar, 0 ); /* clear reload */
mtspr( tsr, 0x08000000 ); /* clear DEC status */
- val = gd->bd->bi_intfreq/100; /* 10 msec */
+ val = gd->bd->bi_intfreq/1000; /* 1 msec */
mtspr( decar, val ); /* Set auto-reload value */
mtspr( dec, val ); /* Set inital val */
#else
*/
set_evpr(0x00000000);
-#if defined(CONFIG_440)
- /* Install the UIC1 handlers */
- irq_install_handler(VECNUM_UIC1NC, uic1_interrupt, 0);
- irq_install_handler(VECNUM_UIC1C, uic1_interrupt, 0);
-#endif
-
- return (0);
-}
-
-/****************************************************************************/
-
-/*
- * Handle external interrupts
- */
-void external_interrupt(struct pt_regs *regs)
-{
- ulong uic_msr;
- ulong msr_shift;
- int vec;
-
/*
- * Read masked interrupt status register to determine interrupt source
+ * Call uic or xilinx_irq pic_enable
*/
- uic_msr = mfdcr(uicmsr);
- msr_shift = uic_msr;
- vec = 0;
-
- while (msr_shift != 0) {
- if (msr_shift & 0x80000000) {
- /*
- * Increment irq counter (for debug purpose only)
- */
- irq_vecs[vec].count++;
-
- if (irq_vecs[vec].handler != NULL) {
- /* call isr */
- (*irq_vecs[vec].handler)(irq_vecs[vec].arg);
- } else {
- mtdcr(uicer, mfdcr(uicer) & ~(0x80000000 >> vec));
- printf ("Masking bogus interrupt vector 0x%x\n", vec);
- }
-
- /*
- * After servicing the interrupt, we have to remove the status indicator.
- */
- mtdcr(uicsr, (0x80000000 >> vec));
- }
+ pic_enable();
- /*
- * Shift msr to next position and increment vector
- */
- msr_shift <<= 1;
- vec++;
- }
+ return (0);
}
-#if defined(CONFIG_440)
-/* Handler for UIC1 interrupt */
-void uic1_interrupt( void * parms)
+void timer_interrupt_cpu(struct pt_regs *regs)
{
- ulong uic1_msr;
- ulong msr_shift;
- int vec;
-
- /*
- * Read masked interrupt status register to determine interrupt source
- */
- uic1_msr = mfdcr(uic1msr);
- msr_shift = uic1_msr;
- vec = 0;
-
- while (msr_shift != 0) {
- if (msr_shift & 0x80000000) {
- /*
- * Increment irq counter (for debug purpose only)
- */
- irq_vecs1[vec].count++;
-
- if (irq_vecs1[vec].handler != NULL) {
- /* call isr */
- (*irq_vecs1[vec].handler)(irq_vecs1[vec].arg);
- } else {
- mtdcr(uic1er, mfdcr(uic1er) & ~(0x80000000 >> vec));
- printf ("Masking bogus interrupt vector (uic1) 0x%x\n", vec);
- }
-
- /*
- * After servicing the interrupt, we have to remove the status indicator.
- */
- mtdcr(uic1sr, (0x80000000 >> vec));
- }
-
- /*
- * Shift msr to next position and increment vector
- */
- msr_shift <<= 1;
- vec++;
- }
+ /* nothing to do here */
+ return;
}
-#endif /* defined(CONFIG_440) */
-
-/****************************************************************************/
-
-/*
- * Install and free a interrupt handler.
- */
-void
-irq_install_handler(int vec, interrupt_handler_t *handler, void *arg)
+void interrupt_run_handler(int vec)
{
- struct irq_action *irqa = irq_vecs;
- int i = vec;
-
-#if defined(CONFIG_440)
- if (vec > 31) {
- i = vec - 32;
- irqa = irq_vecs1;
- }
-#endif
-
- if (irqa[i].handler != NULL) {
- printf ("Interrupt vector %d: handler 0x%x replacing 0x%x\n",
- vec, (uint)handler, (uint)irqa[i].handler);
+ irq_vecs[vec].count++;
+
+ if (irq_vecs[vec].handler != NULL) {
+ /* call isr */
+ (*irq_vecs[vec].handler) (irq_vecs[vec].arg);
+ } else {
+ pic_irq_disable(vec);
+ printf("Masking bogus interrupt vector %d\n", vec);
}
- irqa[i].handler = handler;
- irqa[i].arg = arg;
-#if defined(CONFIG_440)
- if( vec > 31 )
- mtdcr(uic1er, mfdcr(uic1er) | (0x80000000 >> i));
- else
-#endif
- mtdcr(uicer, mfdcr(uicer) | (0x80000000 >> i));
-#if 0
- printf ("Install interrupt for vector %d ==> %p\n", vec, handler);
-#endif
+ pic_irq_ack(vec);
+ return;
}
-void
-irq_free_handler(int vec)
+void irq_install_handler(int vec, interrupt_handler_t * handler, void *arg)
{
- struct irq_action *irqa = irq_vecs;
- int i = vec;
-
-#if defined(CONFIG_440)
- if (vec > 31) {
- irqa = irq_vecs1;
- i = vec - 32;
+ /*
+ * Print warning when replacing with a different irq vector
+ */
+ if ((irq_vecs[vec].handler != NULL) && (irq_vecs[vec].handler != handler)) {
+ printf("Interrupt vector %d: handler 0x%x replacing 0x%x\n",
+ vec, (uint) handler, (uint) irq_vecs[vec].handler);
}
-#endif
-
-#if 0
- printf ("Free interrupt for vector %d ==> %p\n",
- vec, irq_vecs[vec].handler);
-#endif
+ irq_vecs[vec].handler = handler;
+ irq_vecs[vec].arg = arg;
-#if defined(CONFIG_440)
- if (vec > 31)
- mtdcr(uic1er, mfdcr(uic1er) & ~(0x80000000 >> i));
- else
-#endif
- mtdcr(uicer, mfdcr(uicer) & ~(0x80000000 >> i));
-
- irqa[i].handler = NULL;
- irqa[i].arg = NULL;
+ pic_irq_enable(vec);
+ return;
}
-/****************************************************************************/
-
-void timer_interrupt_cpu (struct pt_regs *regs)
+void irq_free_handler(int vec)
{
- /* nothing to do here */
- return;
-}
+ debug("Free interrupt for vector %d ==> %p\n",
+ vec, irq_vecs[vec].handler);
-/****************************************************************************/
+ pic_irq_disable(vec);
-#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
+ irq_vecs[vec].handler = NULL;
+ irq_vecs[vec].arg = NULL;
+ return;
+}
-/*******************************************************************************
- *
- * irqinfo - print information about PCI devices
- *
- */
-int
-do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+#if defined(CONFIG_CMD_IRQ)
+int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
int vec;
- printf ("\nInterrupt-Information:\n");
-#if defined(CONFIG_440)
- printf ("\nUIC 0\n");
-#endif
+ printf ("Interrupt-Information:\n");
printf ("Nr Routine Arg Count\n");
- for (vec=0; vec<32; vec++) {
+ for (vec = 0; vec < IRQ_MAX; vec++) {
if (irq_vecs[vec].handler != NULL) {
printf ("%02d %08lx %08lx %d\n",
vec,
}
}
-#if defined(CONFIG_440)
- printf ("\nUIC 1\n");
- printf ("Nr Routine Arg Count\n");
-
- for (vec=0; vec<32; vec++)
- {
- if (irq_vecs1[vec].handler != NULL)
- printf ("%02d %08lx %08lx %d\n",
- vec+31, (ulong)irq_vecs1[vec].handler,
- (ulong)irq_vecs1[vec].arg, irq_vecs1[vec].count);
- }
- printf("\n");
-#endif
return 0;
}
-
-
-#endif /* CONFIG_COMMANDS & CFG_CMD_IRQ */
+#endif