diff options
Diffstat (limited to 'cpu/ppc4xx/interrupts.c')
| -rw-r--r-- | cpu/ppc4xx/interrupts.c | 235 | 
1 files changed, 28 insertions, 207 deletions
| diff --git a/cpu/ppc4xx/interrupts.c b/cpu/ppc4xx/interrupts.c index 8620e2b48..494bd8c9e 100644 --- a/cpu/ppc4xx/interrupts.c +++ b/cpu/ppc4xx/interrupts.c @@ -8,6 +8,10 @@   * (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.   * @@ -31,31 +35,14 @@  #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 <asm/ppc4xx-intvec.h>  DECLARE_GLOBAL_DATA_PTR;  /* - * Define the number of UIC's - */ -#if defined(CONFIG_440SPE) || \ -    defined(CONFIG_460EX) || defined(CONFIG_460GT) -#define UIC_MAX		4 -#elif defined(CONFIG_440GX) || \ -    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ -    defined(CONFIG_405EX) -#define UIC_MAX		3 -#elif defined(CONFIG_440GP) || defined(CONFIG_440SP) || \ -    defined(CONFIG_440EP) || defined(CONFIG_440GR) -#define UIC_MAX		2 -#else -#define UIC_MAX		1 -#endif - -/*   * CPM interrupt vector functions.   */  struct	irq_action { @@ -63,15 +50,7 @@ struct	irq_action {  	void *arg;  	int count;  }; - -static struct irq_action irq_vecs[UIC_MAX * 32]; - -u32 get_dcr(u16); -void set_dcr(u16, u32); - -#if (UIC_MAX > 1) && !defined(CONFIG_440GX) -static void uic_cascade_interrupt(void *para); -#endif +static struct irq_action irq_vecs[IRQ_MAX];  #if defined(CONFIG_440) @@ -112,7 +91,7 @@ int interrupt_init_cpu (unsigned *decrementer_count)  	/*  	 * Mark all irqs as free  	 */ -	for (vec = 0; vec < (UIC_MAX * 32); vec++) { +	for (vec = 0; vec < IRQ_MAX; vec++) {  		irq_vecs[vec].handler = NULL;  		irq_vecs[vec].arg = NULL;  		irq_vecs[vec].count = 0; @@ -156,160 +135,38 @@ int interrupt_init_cpu (unsigned *decrementer_count)  	 */  	set_evpr(0x00000000); -#if !defined(CONFIG_440GX) -#if (UIC_MAX > 1) -	/* Install the UIC1 handlers */ -	irq_install_handler(VECNUM_UIC1NC, uic_cascade_interrupt, 0); -	irq_install_handler(VECNUM_UIC1C, uic_cascade_interrupt, 0); -#endif -#if (UIC_MAX > 2) -	irq_install_handler(VECNUM_UIC2NC, uic_cascade_interrupt, 0); -	irq_install_handler(VECNUM_UIC2C, uic_cascade_interrupt, 0); -#endif -#if (UIC_MAX > 3) -	irq_install_handler(VECNUM_UIC3NC, uic_cascade_interrupt, 0); -	irq_install_handler(VECNUM_UIC3C, uic_cascade_interrupt, 0); -#endif -#else /* !defined(CONFIG_440GX) */ -	/* Take the GX out of compatibility mode -	 * Travis Sawyer, 9 Mar 2004 -	 * NOTE: 440gx user manual inconsistency here -	 *       Compatibility mode and Ethernet Clock select are not -	 *       correct in the manual +	/* +	 * Call uic or xilinx_irq pic_enable  	 */ -	mfsdr(sdr_mfr, val); -	val &= ~0x10000000; -	mtsdr(sdr_mfr,val); - -	/* Enable UIC interrupts via UIC Base Enable Register */ -	mtdcr(uicb0sr, UICB0_ALL); -	mtdcr(uicb0er, 0x54000000); -	/* None are critical */ -	mtdcr(uicb0cr, 0); -#endif /* !defined(CONFIG_440GX) */ +	pic_enable();  	return (0);  } -/* Handler for UIC interrupt */ -static void uic_interrupt(u32 uic_base, int vec_base) +void timer_interrupt_cpu(struct pt_regs *regs)  { -	u32 uic_msr; -	u32 msr_shift; -	int vec; - -	/* -	 * Read masked interrupt status register to determine interrupt source -	 */ -	uic_msr = get_dcr(uic_base + UIC_MSR); -	msr_shift = uic_msr; -	vec = vec_base; - -	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 { -				set_dcr(uic_base + UIC_ER, -					get_dcr(uic_base + UIC_ER) & -					~(0x80000000 >> (vec & 0x1f))); -				printf("Masking bogus interrupt vector %d" -				       " (UIC_BASE=0x%x)\n", vec, uic_base); -			} - -			/* -			 * After servicing the interrupt, we have to remove the -			 * status indicator -			 */ -			set_dcr(uic_base + UIC_SR, (0x80000000 >> (vec & 0x1f))); -		} - -		/* -		 * Shift msr to next position and increment vector -		 */ -		msr_shift <<= 1; -		vec++; -	} +	/* nothing to do here */ +	return;  } -#if (UIC_MAX > 1) && !defined(CONFIG_440GX) -static void uic_cascade_interrupt(void *para) +void interrupt_run_handler(int vec)  { -	external_interrupt(para); -} -#endif - -#if defined(CONFIG_440) -#if defined(CONFIG_440GX) -/* 440GX uses base uic register */ -#define UIC_BMSR	uicb0msr -#define UIC_BSR		uicb0sr -#else -#define UIC_BMSR	uic0msr -#define UIC_BSR		uic0sr -#endif -#else /* CONFIG_440 */ -#define UIC_BMSR	uicmsr -#define UIC_BSR		uicsr -#endif /* CONFIG_440 */ +	irq_vecs[vec].count++; -/* - * Handle external interrupts - */ -void external_interrupt(struct pt_regs *regs) -{ -	u32 uic_msr; - -	/* -	 * Read masked interrupt status register to determine interrupt source -	 */ -	uic_msr = mfdcr(UIC_BMSR); - -#if (UIC_MAX > 1) -	if ((UICB0_UIC1CI & uic_msr) || (UICB0_UIC1NCI & uic_msr)) -		uic_interrupt(UIC1_DCR_BASE, 32); -#endif - -#if (UIC_MAX > 2) -	if ((UICB0_UIC2CI & uic_msr) || (UICB0_UIC2NCI & uic_msr)) -		uic_interrupt(UIC2_DCR_BASE, 64); -#endif - -#if (UIC_MAX > 3) -	if ((UICB0_UIC3CI & uic_msr) || (UICB0_UIC3NCI & uic_msr)) -		uic_interrupt(UIC3_DCR_BASE, 96); -#endif - -#if defined(CONFIG_440) -#if !defined(CONFIG_440GX) -	if (uic_msr & ~(UICB0_ALL)) -		uic_interrupt(UIC0_DCR_BASE, 0); -#else -	if ((UICB0_UIC0CI & uic_msr) || (UICB0_UIC0NCI & uic_msr)) -		uic_interrupt(UIC0_DCR_BASE, 0); -#endif -#else /* CONFIG_440 */ -	uic_interrupt(UIC0_DCR_BASE, 0); -#endif /* CONFIG_440 */ - -	mtdcr(UIC_BSR, uic_msr); +	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); +	} +	pic_irq_ack(vec);  	return;  } -/* - * Install and free a interrupt handler. - */  void irq_install_handler(int vec, interrupt_handler_t * handler, void *arg)  { -	int i; -  	/*  	 * Print warning when replacing with a different irq vector  	 */ @@ -320,55 +177,19 @@ void irq_install_handler(int vec, interrupt_handler_t * handler, void *arg)  	irq_vecs[vec].handler = handler;  	irq_vecs[vec].arg = arg; -	i = vec & 0x1f; -	if ((vec >= 0) && (vec < 32)) -		mtdcr(uicer, mfdcr(uicer) | (0x80000000 >> i)); -#if (UIC_MAX > 1) -	else if ((vec >= 32) && (vec < 64)) -		mtdcr(uic1er, mfdcr(uic1er) | (0x80000000 >> i)); -#endif -#if (UIC_MAX > 2) -	else if ((vec >= 64) && (vec < 96)) -		mtdcr(uic2er, mfdcr(uic2er) | (0x80000000 >> i)); -#endif -#if (UIC_MAX > 3) -	else if (vec >= 96) -		mtdcr(uic3er, mfdcr(uic3er) | (0x80000000 >> i)); -#endif - -	debug("Install interrupt for vector %d ==> %p\n", vec, handler); +	pic_irq_enable(vec); +	return;  } -void irq_free_handler (int vec) +void irq_free_handler(int vec)  { -	int i; -  	debug("Free interrupt for vector %d ==> %p\n",  	      vec, irq_vecs[vec].handler); -	i = vec & 0x1f; -	if ((vec >= 0) && (vec < 32)) -		mtdcr(uicer, mfdcr(uicer) & ~(0x80000000 >> i)); -#if (UIC_MAX > 1) -	else if ((vec >= 32) && (vec < 64)) -		mtdcr(uic1er, mfdcr(uic1er) & ~(0x80000000 >> i)); -#endif -#if (UIC_MAX > 2) -	else if ((vec >= 64) && (vec < 96)) -		mtdcr(uic2er, mfdcr(uic2er) & ~(0x80000000 >> i)); -#endif -#if (UIC_MAX > 3) -	else if (vec >= 96) -		mtdcr(uic3er, mfdcr(uic3er) & ~(0x80000000 >> i)); -#endif +	pic_irq_disable(vec);  	irq_vecs[vec].handler = NULL;  	irq_vecs[vec].arg = NULL; -} - -void timer_interrupt_cpu (struct pt_regs *regs) -{ -	/* nothing to do here */  	return;  } @@ -380,7 +201,7 @@ int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	printf ("Interrupt-Information:\n");  	printf ("Nr  Routine   Arg       Count\n"); -	for (vec = 0; vec < (UIC_MAX * 32); vec++) { +	for (vec = 0; vec < IRQ_MAX; vec++) {  		if (irq_vecs[vec].handler != NULL) {  			printf ("%02d  %08lx  %08lx  %d\n",  				vec, |