[U-Boot-Users] [PATCH] CPU PPC440x5 on Virtex5 FX
Michal Simek
Monstr at seznam.cz
Fri Jul 11 14:09:25 CEST 2008
Some days ago a sent to mailing list patch (currently is in) where I rename
CONFIG_XILINX_ML300 -> CONFIG_XILINX_405.
I would like to see if you can use the same style for 440 -> CONFIG_XILINX_440.
I have no detail information about ppc440 but IMHO only virtex5 fx (or whatever) support it ->
make no sense to me use virtex5 in name.
SR: Do you agree with me?
There is big part of code relate with interrupt controller which is the same with microblaze.
This should be handled in the same way. Any suggestion? (Do generic driver?)
M
BTW: some comments in code.
author
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;
why you use printf here? puts is enough.
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
:-( no use this loooooooooooooong value which comes from generated xparameters.h.
SR:Am I understand correctly that 405 or 440 use 32 bits (64...) wide interrupt controllers?
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 */
IMHO coding style issue
#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) */
coding style
/* 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) */
coding style
+
+#else
+ /*
+ * Enable xilinx pic
+ */
+ xilinx_pic_enable();
so big comment
+#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 */
CS
#define UIC_BMSR uicmsr
#define UIC_BSR uicsr
-#endif /* CONFIG_440 */
+#endif /* CONFIG_440 */
CS
/*
* 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 */
these look weird to me - have defines value in the middle of source code -> maybe header.
this looks like duplication with MB where I use interrupt controller.
+#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
-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08
_______________________________________________
U-Boot-Users mailing list
U-Boot-Users at lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/u-boot-users
More information about the U-Boot
mailing list