[U-Boot-Users] [PATCH] CPU PPC440x5 on Virtex5 FX

Ricardo Ribalda Delgado ricardo.ribalda at uam.es
Fri Jul 11 13:35:00 CEST 2008


This patchs gives support for the embbedded ppc440
on the Virtex5 FPGAs
---
 cpu/ppc4xx/4xx_enet.c       |    3 +-
 cpu/ppc4xx/4xx_uart.c       |    3 +
 cpu/ppc4xx/cpu.c            |    4 +
 cpu/ppc4xx/gpio.c           |    5 +
 cpu/ppc4xx/interrupts.c     |  238 ++++++++++++++++++++++++++++++++++++-------
 cpu/ppc4xx/miiphy.c         |    5 +
 cpu/ppc4xx/speed.c          |    6 +-
 include/asm-ppc/processor.h |    3 +-
 net/eth.c                   |    3 +-
 9 files changed, 228 insertions(+), 42 deletions(-)

diff --git a/cpu/ppc4xx/4xx_enet.c b/cpu/ppc4xx/4xx_enet.c
index 4e863dc..cf26237 100644
--- a/cpu/ppc4xx/4xx_enet.c
+++ b/cpu/ppc4xx/4xx_enet.c
@@ -97,7 +97,8 @@
  * network support enabled.
  * Remark: CONFIG_405 describes Xilinx PPC405 FPGA without EMAC controller!
  */
-#if defined(CONFIG_CMD_NET) && !defined(CONFIG_405) && !defined(CONFIG_IOP480)
+#if defined(CONFIG_CMD_NET) && !defined(CONFIG_405) && !defined(CONFIG_IOP480) \
+	&& !defined(CONFIG_440_VIRTEX5)
 
 #if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
 #error "CONFIG_MII has to be defined!"
diff --git a/cpu/ppc4xx/4xx_uart.c b/cpu/ppc4xx/4xx_uart.c
index a7587d4..37d3dbc 100644
--- a/cpu/ppc4xx/4xx_uart.c
+++ b/cpu/ppc4xx/4xx_uart.c
@@ -48,6 +48,7 @@
 #include <watchdog.h>
 #include <asm/ppc4xx-intvec.h>
 
+#if !defined(CONFIG_440_VIRTEX5)
 #ifdef CONFIG_SERIAL_MULTI
 #include <serial.h>
 #endif
@@ -873,3 +874,5 @@ int serial_tstc(void)
 #endif /* CONFIG_SERIAL_MULTI */
 
 #endif	/* CONFIG_405GP || CONFIG_405CR */
+
+#endif
diff --git a/cpu/ppc4xx/cpu.c b/cpu/ppc4xx/cpu.c
index 39f439d..f510cdd 100644
--- a/cpu/ppc4xx/cpu.c
+++ b/cpu/ppc4xx/cpu.c
@@ -508,6 +508,10 @@ int checkcpu (void)
 		puts("GT Rev. A");
 		strcpy(addstr, "Security/Kasumi support");
 		break;
+	
+	case PVR_VIRTEX5:
+		printf(" VIRTEX5");
+		break;
 
 	default:
 		printf (" UNKNOWN (PVR=%08x)", pvr);
diff --git a/cpu/ppc4xx/gpio.c b/cpu/ppc4xx/gpio.c
index df99f53..59159ee 100644
--- a/cpu/ppc4xx/gpio.c
+++ b/cpu/ppc4xx/gpio.c
@@ -26,6 +26,9 @@
 #include <asm/io.h>
 #include <asm/gpio.h>
 
+
+#if !defined(CONFIG_440_VIRTEX5)
+
 #if defined(CFG_4xx_GPIO_TABLE)
 gpio_param_s const gpio_tab[GPIO_GROUP_MAX][GPIO_MAX] = CFG_4xx_GPIO_TABLE;
 #endif
@@ -253,3 +256,5 @@ void gpio_set_chip_configuration(void)
 	}
 }
 #endif /* CFG_4xx_GPIO_TABLE */
+
+#endif
diff --git a/cpu/ppc4xx/interrupts.c b/cpu/ppc4xx/interrupts.c
index 8620e2b..4648f52 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 at sandburst.com
  *
+ * (C) Copyright 2008 (PPC440X05 port for Virtex 5 FX)
+ * Ricardo Ribalda, Universidad Autonoma de Madrid, ricardo.ribalda at uam.es
+ * Work supported by Qtechnology (htpp://qtec.com)
+ *
  * See file CREDITS for list of people who contributed to this
  * project.
  *
@@ -41,6 +45,7 @@ DECLARE_GLOBAL_DATA_PTR;
 /*
  * Define the number of UIC's
  */
+#if !defined(CONFIG_440_VIRTEX5)
 #if defined(CONFIG_440SPE) || \
     defined(CONFIG_460EX) || defined(CONFIG_460GT)
 #define UIC_MAX		4
@@ -54,17 +59,23 @@ DECLARE_GLOBAL_DATA_PTR;
 #else
 #define UIC_MAX		1
 #endif
-
+#else
+void xilinx_pic_enable(void);
+#endif
 /*
  * CPM interrupt vector functions.
  */
-struct	irq_action {
+struct irq_action {
 	interrupt_handler_t *handler;
 	void *arg;
 	int count;
 };
 
+#if !defined(CONFIG_440_VIRTEX5)
 static struct irq_action irq_vecs[UIC_MAX * 32];
+#else
+static struct irq_action irq_vecs[XPAR_INTC_MAX_NUM_INTR_INPUTS];
+#endif
 
 u32 get_dcr(u16);
 void set_dcr(u16, u32);
@@ -81,27 +92,25 @@ static __inline__ void set_evpr(unsigned long val)
 	asm volatile("mtspr 0x03f,%0" : : "r" (val));
 }
 
-#else /* !defined(CONFIG_440) */
+#else				/* !defined(CONFIG_440) */
 
 static __inline__ void set_pit(unsigned long val)
 {
 	asm volatile("mtpit %0" : : "r" (val));
 }
 
-
 static __inline__ void set_tcr(unsigned long val)
 {
 	asm volatile("mttcr %0" : : "r" (val));
 }
 
-
 static __inline__ void set_evpr(unsigned long val)
 {
 	asm volatile("mtevpr %0" : : "r" (val));
 }
-#endif /* defined(CONFIG_440 */
+#endif				/* defined(CONFIG_440 */
 
-int interrupt_init_cpu (unsigned *decrementer_count)
+int interrupt_init_cpu(unsigned *decrementer_count)
 {
 	int vec;
 	unsigned long val;
@@ -112,7 +121,11 @@ int interrupt_init_cpu (unsigned *decrementer_count)
 	/*
 	 * Mark all irqs as free
 	 */
+#if !defined (CONFIG_440_VIRTEX5)
 	for (vec = 0; vec < (UIC_MAX * 32); vec++) {
+#else
+	for (vec = 0; vec < XPAR_INTC_MAX_NUM_INTR_INPUTS; vec++) {
+#endif
 		irq_vecs[vec].handler = NULL;
 		irq_vecs[vec].arg = NULL;
 		irq_vecs[vec].count = 0;
@@ -123,19 +136,19 @@ int interrupt_init_cpu (unsigned *decrementer_count)
 	 * Init PIT
 	 */
 #if defined(CONFIG_440)
-	val = mfspr( tcr );
-	val &= (~0x04400000);		/* clear DIS & ARE */
-	mtspr( tcr, val );
-	mtspr( dec, 0 );		/* Prevent exception after TSR clear*/
-	mtspr( decar, 0 );		/* clear reload */
-	mtspr( tsr, 0x08000000 );	/* clear DEC status */
-	val = gd->bd->bi_intfreq/1000;	/* 1 msec */
-	mtspr( decar, val );		/* Set auto-reload value */
-	mtspr( dec, val );		/* Set inital val */
+	val = mfspr(tcr);
+	val &= (~0x04400000);	/* clear DIS & ARE */
+	mtspr(tcr, val);
+	mtspr(dec, 0);		/* Prevent exception after TSR clear */
+	mtspr(decar, 0);	/* clear reload */
+	mtspr(tsr, 0x08000000);	/* clear DEC status */
+	val = gd->bd->bi_intfreq / 1000;	/* 1 msec */
+	mtspr(decar, val);	/* Set auto-reload value */
+	mtspr(dec, val);	/* Set inital val */
 #else
 	set_pit(gd->bd->bi_intfreq / 1000);
 #endif
-#endif  /* CONFIG_4xx */
+#endif				/* CONFIG_4xx */
 
 #ifdef CONFIG_ADCIOP
 	/*
@@ -156,6 +169,8 @@ int interrupt_init_cpu (unsigned *decrementer_count)
 	 */
 	set_evpr(0x00000000);
 
+#if !defined (CONFIG_440_VIRTEX5)
+
 #if !defined(CONFIG_440GX)
 #if (UIC_MAX > 1)
 	/* Install the UIC1 handlers */
@@ -170,7 +185,7 @@ int interrupt_init_cpu (unsigned *decrementer_count)
 	irq_install_handler(VECNUM_UIC3NC, uic_cascade_interrupt, 0);
 	irq_install_handler(VECNUM_UIC3C, uic_cascade_interrupt, 0);
 #endif
-#else /* !defined(CONFIG_440GX) */
+#else				/* !defined(CONFIG_440GX) */
 	/* Take the GX out of compatibility mode
 	 * Travis Sawyer, 9 Mar 2004
 	 * NOTE: 440gx user manual inconsistency here
@@ -179,18 +194,27 @@ int interrupt_init_cpu (unsigned *decrementer_count)
 	 */
 	mfsdr(sdr_mfr, val);
 	val &= ~0x10000000;
-	mtsdr(sdr_mfr,val);
+	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) */
+#endif				/* !defined(CONFIG_440GX) */
+
+#else
+	/*
+	 * Enable xilinx pic
+	 */
+	xilinx_pic_enable();
+
+#endif
 
 	return (0);
 }
 
+#if !defined(CONFIG_440_VIRTEX5)
 /* Handler for UIC interrupt */
 static void uic_interrupt(u32 uic_base, int vec_base)
 {
@@ -214,7 +238,7 @@ static void uic_interrupt(u32 uic_base, int vec_base)
 
 			if (irq_vecs[vec].handler != NULL) {
 				/* call isr */
-				(*irq_vecs[vec].handler)(irq_vecs[vec].arg);
+				(*irq_vecs[vec].handler) (irq_vecs[vec].arg);
 			} else {
 				set_dcr(uic_base + UIC_ER,
 					get_dcr(uic_base + UIC_ER) &
@@ -227,7 +251,8 @@ static void uic_interrupt(u32 uic_base, int vec_base)
 			 * After servicing the interrupt, we have to remove the
 			 * status indicator
 			 */
-			set_dcr(uic_base + UIC_SR, (0x80000000 >> (vec & 0x1f)));
+			set_dcr(uic_base + UIC_SR,
+				(0x80000000 >> (vec & 0x1f)));
 		}
 
 		/*
@@ -254,10 +279,10 @@ static void uic_cascade_interrupt(void *para)
 #define UIC_BMSR	uic0msr
 #define UIC_BSR		uic0sr
 #endif
-#else /* CONFIG_440 */
+#else				/* CONFIG_440 */
 #define UIC_BMSR	uicmsr
 #define UIC_BSR		uicsr
-#endif /* CONFIG_440 */
+#endif				/* CONFIG_440 */
 
 /*
  * Handle external interrupts
@@ -294,9 +319,9 @@ void external_interrupt(struct pt_regs *regs)
 	if ((UICB0_UIC0CI & uic_msr) || (UICB0_UIC0NCI & uic_msr))
 		uic_interrupt(UIC0_DCR_BASE, 0);
 #endif
-#else /* CONFIG_440 */
+#else				/* CONFIG_440 */
 	uic_interrupt(UIC0_DCR_BASE, 0);
-#endif /* CONFIG_440 */
+#endif				/* CONFIG_440 */
 
 	mtdcr(UIC_BSR, uic_msr);
 
@@ -313,7 +338,8 @@ void irq_install_handler(int vec, interrupt_handler_t * handler, void *arg)
 	/*
 	 * Print warning when replacing with a different irq vector
 	 */
-	if ((irq_vecs[vec].handler != NULL) && (irq_vecs[vec].handler != handler)) {
+	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);
 	}
@@ -339,7 +365,7 @@ void irq_install_handler(int vec, interrupt_handler_t * handler, void *arg)
 	debug("Install interrupt for vector %d ==> %p\n", vec, handler);
 }
 
-void irq_free_handler (int vec)
+void irq_free_handler(int vec)
 {
 	int i;
 
@@ -365,28 +391,166 @@ void irq_free_handler (int vec)
 	irq_vecs[vec].handler = NULL;
 	irq_vecs[vec].arg = NULL;
 }
+#else
+
+#define intc    XPAR_INTC_0_BASEADDR
+#define ISR (0*4)		/* Interrupt Status Register */
+#define IPR (1*4)		/* Interrupt Pending Register */
+#define IER (2*4)		/* Interrupt Enable Register */
+#define IAR (3*4)		/* Interrupt Acknowledge Register */
+#define SIE (4*4)		/* Set Interrupt Enable bits */
+#define CIE (5*4)		/* Clear Interrupt Enable bits */
+#define IVR (6*4)		/* Interrupt Vector Register */
+#define MER (7*4)		/* Master Enable Register */
+
+#define intc_out_be32(addr, mask)     out32((addr), (mask))
+#define intc_in_be32(addr)            in32((addr))
+
+void xilinx_pic_enable(void)
+{
+
+	printf("Xilinx PIC at 0x%8x\n", intc);
+
+	/*
+	 * Disable all external interrupts until they are
+	 * explicitly requested.
+	 */
+	intc_out_be32(intc + IER, 0);
+
+	/* Acknowledge any pending interrupts just in case. */
+	intc_out_be32(intc + IAR, ~(u32) 0);
+
+	/* Turn on the Master Enable. */
+	intc_out_be32(intc + MER, 0x3UL);
+
+	return;
+
+}
+
+int xilinx_pic_irq_get(void)
+{
+	u32 irq;
+	irq = intc_in_be32(intc + IVR);
+
+	/* If no interrupt is pending then all bits of the IVR are set to 1. As
+	 * the IVR is as many bits wide as numbers of inputs are available.
+	 * Therefore, if all bits of the IVR are set to one, its content will
+	 * be bigger than XPAR_INTC_MAX_NUM_INTR_INPUTS.
+	 */
+	if (irq >= XPAR_INTC_MAX_NUM_INTR_INPUTS)
+		irq = -1;	/* report no pending interrupt. */
+
+	debug("get_irq: %d\n", irq);
+	return (irq);
+}
+
+static void xilinx_pic_irq_enable(unsigned int irq)
+{
+	unsigned long mask = (0x00000001 << (irq & 31));
+	debug("enable: %d\n", irq);
+	intc_out_be32(intc + SIE, mask);
+}
+
+static void xilinx_pic_irq_disable(unsigned int irq)
+{
+	unsigned long mask = (0x00000001 << (irq & 31));
+	debug("disable: %d\n", irq);
+	intc_out_be32(intc + CIE, mask);
+}
+
+static void xilinx_pic_irq_ack(unsigned int irq)
+{
+	unsigned long mask = (0x00000001 << (irq & 31));
+	debug("ack: %d\n", irq);
+	intc_out_be32(intc + IAR, mask);
+}
+
+static void xilinx_pic_interrupt(void)
+{
+	int irq;
+
+	irq = xilinx_pic_irq_get();
+	if (irq < 0)
+		return;
+
+	irq_vecs[irq].count++;
+
+	if (irq_vecs[irq].handler != NULL) {
+		/* call isr */
+		(*irq_vecs[irq].handler) (irq_vecs[irq].arg);
+
+	} else {
+		xilinx_pic_irq_disable(irq);
+		printf("Masking bogus interrupt %d\n", irq);
+	}
+
+	xilinx_pic_irq_ack(irq);
+	return;
+}
+
+void external_interrupt(struct pt_regs *regs)
+{
+	xilinx_pic_interrupt();
+}
+
+/*
+ * Install and free a interrupt handler.
+ */
+void irq_install_handler(int vec, interrupt_handler_t * handler, void *arg)
+{
+	/*
+	 * 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);
+	}
+	irq_vecs[vec].handler = handler;
+	irq_vecs[vec].arg = arg;
+
+	xilinx_pic_irq_enable(vec);
+
+	debug("Install interrupt for vector %d ==> %p\n", vec, handler);
+}
+
+void irq_free_handler(int vec)
+{
+	debug("Free interrupt for vector %d ==> %p\n",
+	      vec, irq_vecs[vec].handler);
+
+	xilinx_pic_irq_disable(vec);
+
+	irq_vecs[vec].handler = NULL;
+	irq_vecs[vec].arg = NULL;
+}
+
+#endif
 
-void timer_interrupt_cpu (struct pt_regs *regs)
+void timer_interrupt_cpu(struct pt_regs *regs)
 {
 	/* nothing to do here */
 	return;
 }
 
 #if defined(CONFIG_CMD_IRQ)
-int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+int do_irqinfo(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 {
 	int vec;
 
-	printf ("Interrupt-Information:\n");
-	printf ("Nr  Routine   Arg       Count\n");
+	printf("Interrupt-Information:\n");
+	printf("Nr  Routine   Arg       Count\n");
 
+#if !defined (CONFIG_440_VIRTEX5)
 	for (vec = 0; vec < (UIC_MAX * 32); vec++) {
+#else
+	for (vec = 0; vec < XPAR_INTC_MAX_NUM_INTR_INPUTS; vec++) {
+#endif
 		if (irq_vecs[vec].handler != NULL) {
-			printf ("%02d  %08lx  %08lx  %d\n",
-				vec,
-				(ulong)irq_vecs[vec].handler,
-				(ulong)irq_vecs[vec].arg,
-				irq_vecs[vec].count);
+			printf("%02d  %08lx  %08lx  %d\n",
+			       vec,
+			       (ulong) irq_vecs[vec].handler,
+			       (ulong) irq_vecs[vec].arg, irq_vecs[vec].count);
 		}
 	}
 
diff --git a/cpu/ppc4xx/miiphy.c b/cpu/ppc4xx/miiphy.c
index c882720..172fbcd 100644
--- a/cpu/ppc4xx/miiphy.c
+++ b/cpu/ppc4xx/miiphy.c
@@ -43,6 +43,9 @@
 #include <405_mal.h>
 #include <miiphy.h>
 
+
+#if !defined(CONFIG_440_VIRTEX5)
+
 #if !defined(CONFIG_PHY_CLK_FREQ)
 #define CONFIG_PHY_CLK_FREQ	0
 #endif
@@ -331,3 +334,5 @@ int emac4xx_miiphy_write (char *devname, unsigned char addr, unsigned char reg,
 {
 	return emac_miiphy_command(addr, reg, EMAC_STACR_WRITE, value);
 }
+
+#endif
diff --git a/cpu/ppc4xx/speed.c b/cpu/ppc4xx/speed.c
index 34bd721..d1681e4 100644
--- a/cpu/ppc4xx/speed.c
+++ b/cpu/ppc4xx/speed.c
@@ -415,7 +415,8 @@ ulong get_PCI_freq (void)
 	return sys_info.freqPCI;
 }
 
-#elif !defined(CONFIG_440GX) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE)
+#elif !defined(CONFIG_440GX) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE)\
+	&&!defined(CONFIG_440_VIRTEX5)
 void get_sys_info (sys_info_t * sysInfo)
 {
 	unsigned long strp0;
@@ -448,6 +449,8 @@ void get_sys_info (sys_info_t * sysInfo)
 	sysInfo->freqUART = sysInfo->freqPLB;
 }
 #else
+
+#if !defined(CONFIG_440_VIRTEX5)
 void get_sys_info (sys_info_t * sysInfo)
 {
 	unsigned long strp0;
@@ -534,6 +537,7 @@ void get_sys_info (sys_info_t * sysInfo)
 }
 
 #endif
+#endif
 
 #if defined(CONFIG_YUCCA)
 unsigned long determine_sysper(void)
diff --git a/include/asm-ppc/processor.h b/include/asm-ppc/processor.h
index 10fd478..88f193a 100644
--- a/include/asm-ppc/processor.h
+++ b/include/asm-ppc/processor.h
@@ -827,13 +827,12 @@
 #define PVR_7400	0x000C0000
 #define PVR_7410	0x800C0000
 #define PVR_7450	0x80000000
-
 #define PVR_85xx	0x80200000
 #define PVR_85xx_REV1	(PVR_85xx | 0x0010)
 #define PVR_85xx_REV2	(PVR_85xx | 0x0020)
-
 #define PVR_86xx	0x80040000
 #define PVR_86xx_REV1	(PVR_86xx | 0x0010)
+#define PVR_VIRTEX5     0x7ff21912
 
 /*
  * For the 8xx processors, all of them report the same PVR family for
diff --git a/net/eth.c b/net/eth.c
index 7fc9aee..54b59b8 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -621,7 +621,8 @@ int eth_initialize(bd_t *bis)
 	at91rm9200_miiphy_initialize(bis);
 #endif
 #if defined(CONFIG_4xx) && !defined(CONFIG_IOP480) \
-	&& !defined(CONFIG_AP1000) && !defined(CONFIG_405)
+	&& !defined(CONFIG_AP1000) && !defined(CONFIG_405) \
+	&& !defined(CONFIG_440_VIRTEX5)
 	emac4xx_miiphy_initialize(bis);
 #endif
 #if defined(CONFIG_MCF52x2)
-- 
1.5.6.2





More information about the U-Boot mailing list