summaryrefslogtreecommitdiffstats
path: root/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'cpu')
-rw-r--r--cpu/arm920t/at91rm9200/serial.c2
-rw-r--r--cpu/arm920t/s3c24x0/usb_ohci.c66
-rw-r--r--cpu/arm920t/s3c24x0/usb_ohci.h2
-rw-r--r--cpu/mips/config.mk12
-rw-r--r--cpu/mpc5xxx/serial.c4
-rw-r--r--cpu/mpc5xxx/usb_ohci.c58
-rw-r--r--cpu/mpc5xxx/usb_ohci.h1
-rw-r--r--cpu/mpc8260/config.mk2
-rw-r--r--cpu/mpc8260/cpu.c4
-rw-r--r--cpu/mpc8260/ether_fcc.c7
-rw-r--r--cpu/mpc8260/serial_smc.c4
-rw-r--r--cpu/mpc83xx/Makefile53
-rw-r--r--cpu/mpc83xx/config.mk26
-rw-r--r--cpu/mpc83xx/cpu.c151
-rw-r--r--cpu/mpc83xx/cpu_init.c163
-rw-r--r--cpu/mpc83xx/i2c.c251
-rw-r--r--cpu/mpc83xx/interrupts.c94
-rw-r--r--cpu/mpc83xx/pci.c252
-rw-r--r--cpu/mpc83xx/resetvec.S6
-rw-r--r--cpu/mpc83xx/spd_sdram.c408
-rw-r--r--cpu/mpc83xx/speed.c421
-rw-r--r--cpu/mpc83xx/start.S1093
-rw-r--r--cpu/mpc83xx/traps.c274
-rw-r--r--cpu/mpc85xx/Makefile2
-rw-r--r--cpu/mpc85xx/commproc.c4
-rw-r--r--cpu/mpc85xx/cpu.c21
-rw-r--r--cpu/mpc85xx/cpu_init.c53
-rw-r--r--cpu/mpc85xx/ether_fcc.c4
-rw-r--r--cpu/mpc85xx/serial_scc.c4
-rw-r--r--cpu/mpc85xx/spd_sdram.c1096
-rw-r--r--cpu/mpc85xx/speed.c4
-rw-r--r--cpu/mpc85xx/start.S18
-rw-r--r--cpu/mpc85xx/tsec.c1048
-rw-r--r--cpu/mpc85xx/tsec.h486
-rw-r--r--cpu/mpc8xx/lcd.c11
-rw-r--r--cpu/mpc8xx/speed.c2
-rw-r--r--cpu/ppc4xx/405gp_enet.c57
-rw-r--r--cpu/ppc4xx/405gp_pci.c8
-rw-r--r--cpu/ppc4xx/440gx_enet.c166
-rw-r--r--cpu/ppc4xx/Makefile2
-rw-r--r--cpu/ppc4xx/cpu.c42
-rw-r--r--cpu/ppc4xx/cpu_init.c4
-rw-r--r--cpu/ppc4xx/interrupts.c49
-rw-r--r--cpu/ppc4xx/miiphy_440.c8
-rw-r--r--cpu/ppc4xx/serial.c23
-rw-r--r--cpu/ppc4xx/spd_sdram.c2365
-rw-r--r--cpu/ppc4xx/speed.c95
-rw-r--r--cpu/ppc4xx/start.S267
-rw-r--r--cpu/ppc4xx/usb_ohci.c1642
-rw-r--r--cpu/ppc4xx/usb_ohci.h410
-rw-r--r--cpu/ppc4xx/usbdev.c214
-rw-r--r--cpu/ppc4xx/usbdev.h31
-rw-r--r--cpu/ppc4xx/vecnum.h1
53 files changed, 8223 insertions, 3268 deletions
diff --git a/cpu/arm920t/at91rm9200/serial.c b/cpu/arm920t/at91rm9200/serial.c
index b529cfa41b..a281932b77 100644
--- a/cpu/arm920t/at91rm9200/serial.c
+++ b/cpu/arm920t/at91rm9200/serial.c
@@ -56,7 +56,7 @@ void serial_setbrg (void)
if ((baudrate = gd->baudrate) <= 0)
baudrate = CONFIG_BAUDRATE;
/* MASTER_CLOCK/(16 * baudrate) */
- us->US_BRGR = (AT91C_MASTER_CLOCK >> 4)/baudrate;
+ us->US_BRGR = (AT91C_MASTER_CLOCK >> 4) / (unsigned)baudrate;
}
int serial_init (void)
diff --git a/cpu/arm920t/s3c24x0/usb_ohci.c b/cpu/arm920t/s3c24x0/usb_ohci.c
index c5dac27680..b4cc74476b 100644
--- a/cpu/arm920t/s3c24x0/usb_ohci.c
+++ b/cpu/arm920t/s3c24x0/usb_ohci.c
@@ -94,6 +94,8 @@ urb_priv_t urb_priv;
int got_rhsc;
/* device which was disconnected */
struct usb_device *devgone;
+/* flag guarding URB transation */
+int urb_finished = 0;
/*-------------------------------------------------------------------------*/
@@ -398,6 +400,16 @@ int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer,
return -1;
}
+ /* if we have an unfinished URB from previous transaction let's
+ * fail and scream as quickly as possible so as not to corrupt
+ * further communication */
+ if (!urb_finished) {
+ err("sohci_submit_job: URB NOT FINISHED");
+ return -1;
+ }
+ /* we're about to begin a new transaction here so mark the URB unfinished */
+ urb_finished = 0;
+
/* every endpoint has a ed, locate and fill it */
if (!(ed = ep_add_ed (dev, pipe))) {
err("sohci_submit_job: ENOMEM");
@@ -658,7 +670,6 @@ static void td_fill (ohci_t *ohci, unsigned int info,
else
td->hwBE = 0;
td->hwNextTD = m32_swap (td_pt);
- td->hwPSW [0] = m16_swap (((__u32)data & 0x0FFF) | 0xE000);
/* append to queue */
td->ed->hwTailP = td->hwNextTD;
@@ -793,6 +804,7 @@ static td_t * dl_reverse_done_list (ohci_t *ohci)
td_rev = td_list;
td_list_hc = m32_swap (td_list->hwNextTD) & 0xfffffff0;
}
+
return td_list;
}
@@ -826,6 +838,17 @@ static int dl_done_list (ohci_t *ohci, td_t *td_list)
stat = cc_to_error[cc];
}
+ /* see if this done list makes for all TD's of current URB,
+ * and mark the URB finished if so */
+ if (++(lurb_priv->td_cnt) == lurb_priv->length) {
+ if ((ed->state & (ED_OPER | ED_UNLINK)))
+ urb_finished = 1;
+ else
+ dbg("dl_done_list: strange.., ED state %x, ed->state\n");
+ } else
+ dbg("dl_done_list: processing TD %x, len %x\n", lurb_priv->td_cnt,
+ lurb_priv->length);
+
if (ed->state != ED_NEW) {
edHeadP = m32_swap (ed->hwHeadP) & 0xfffffff0;
edTailP = m32_swap (ed->hwTailP);
@@ -1245,22 +1268,41 @@ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
for (;;) {
/* check whether the controller is done */
stat = hc_interrupt();
+
if (stat < 0) {
stat = USB_ST_CRC_ERR;
break;
}
- if (stat >= 0 && stat != 0xff) {
+
+ /* NOTE: since we are not interrupt driven in U-Boot and always
+ * handle only one URB at a time, we cannot assume the
+ * transaction finished on the first successful return from
+ * hc_interrupt().. unless the flag for current URB is set,
+ * meaning that all TD's to/from device got actually
+ * transferred and processed. If the current URB is not
+ * finished we need to re-iterate this loop so as
+ * hc_interrupt() gets called again as there needs to be some
+ * more TD's to process still */
+ if ((stat >= 0) && (stat != 0xff) && (urb_finished)) {
/* 0xff is returned for an SF-interrupt */
break;
}
+
if (--timeout) {
wait_ms(1);
+ if (!urb_finished)
+ dbg("\%");
+
} else {
err("CTL:TIMEOUT ");
+ dbg("submit_common_msg: TO status %x\n", stat);
stat = USB_ST_CRC_ERR;
+ urb_finished = 1;
break;
}
}
+
+#if 0
/* we got an Root Hub Status Change interrupt */
if (got_rhsc) {
#ifdef DEBUG
@@ -1282,6 +1324,7 @@ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
devgone = dev;
}
}
+#endif
dev->status = stat;
dev->act_len = transfer_len;
@@ -1457,16 +1500,26 @@ hc_interrupt (void)
int ints;
int stat = -1;
- if ((ohci->hcca->done_head != 0) && !(m32_swap (ohci->hcca->done_head) & 0x01)) {
+ if ((ohci->hcca->done_head != 0) &&
+ !(m32_swap (ohci->hcca->done_head) & 0x01)) {
+
ints = OHCI_INTR_WDH;
- } else {
- ints = readl (&regs->intrstatus);
+
+ } else if ((ints = readl (&regs->intrstatus)) == ~(u32)0) {
+ ohci->disabled++;
+ err ("%s device removed!", ohci->slot_name);
+ return -1;
+
+ } else if ((ints &= readl (&regs->intrenable)) == 0) {
+ dbg("hc_interrupt: returning..\n");
+ return 0xff;
}
/* dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); */
if (ints & OHCI_INTR_RHSC) {
got_rhsc = 1;
+ stat = 0xff;
}
if (ints & OHCI_INTR_UE) {
@@ -1490,6 +1543,7 @@ hc_interrupt (void)
if (ints & OHCI_INTR_WDH) {
wait_ms(1);
+
writel (OHCI_INTR_WDH, &regs->intrdisable);
stat = dl_done_list (&gohci, dl_reverse_done_list (&gohci));
writel (OHCI_INTR_WDH, &regs->intrenable);
@@ -1610,6 +1664,8 @@ int usb_lowlevel_init(void)
wait_ms(1);
#endif
ohci_inited = 1;
+ urb_finished = 1;
+
return 0;
}
diff --git a/cpu/arm920t/s3c24x0/usb_ohci.h b/cpu/arm920t/s3c24x0/usb_ohci.h
index fab0e65a38..5e9a0fdfc4 100644
--- a/cpu/arm920t/s3c24x0/usb_ohci.h
+++ b/cpu/arm920t/s3c24x0/usb_ohci.h
@@ -30,7 +30,6 @@ static int cc_to_error[16] = {
};
/* ED States */
-
#define ED_NEW 0x00
#define ED_UNLINK 0x01
#define ED_OPER 0x02
@@ -104,7 +103,6 @@ struct td {
__u32 hwNextTD; /* Next TD Pointer */
__u32 hwBE; /* Memory Buffer End Pointer */
- __u16 hwPSW[MAXPSW];
__u8 unused;
__u8 index;
struct ed *ed;
diff --git a/cpu/mips/config.mk b/cpu/mips/config.mk
index 3c9aab8dfe..fd10747aa3 100644
--- a/cpu/mips/config.mk
+++ b/cpu/mips/config.mk
@@ -24,9 +24,17 @@ v=$(shell \
mips-linux-as --version|grep "GNU assembler"|awk '{print $$3}'|awk -F . '{print $$2}')
MIPSFLAGS=$(shell \
if [ "$v" -lt "14" ]; then \
- echo "-mcpu=4kc -EB -mabicalls"; \
+ echo "-mcpu=4kc"; \
else \
- echo "-march=4kc -mtune=4kc -Wa,-mips_allow_branch_to_undefined -EB -mabicalls"; \
+ echo "-march=4kc -mtune=4kc -Wa,-mips_allow_branch_to_undefined"; \
fi)
+ifneq (,$(findstring 4KCle,$(CROSS_COMPILE)))
+ENDIANNESS = -EL
+else
+ENDIANNESS = -EB
+endif
+
+MIPSFLAGS += $(ENDIANNESS) -mabicalls
+
PLATFORM_CPPFLAGS += $(MIPSFLAGS)
diff --git a/cpu/mpc5xxx/serial.c b/cpu/mpc5xxx/serial.c
index f463d2cf07..1e9628c511 100644
--- a/cpu/mpc5xxx/serial.c
+++ b/cpu/mpc5xxx/serial.c
@@ -154,11 +154,11 @@ serial_setbrg(void)
#if defined(CONFIG_MGT5100)
baseclk = CFG_MPC5XXX_CLKIN / 32;
#elif defined(CONFIG_MPC5200)
- baseclk = gd->ipb_clk / 32;
+ baseclk = (gd->ipb_clk + 16) / 32;
#endif
/* set up UART divisor */
- div = baseclk / gd->baudrate;
+ div = (baseclk + (gd->baudrate/2)) / gd->baudrate;
psc->ctur = div >> 8;
psc->ctlr = div & 0xff;
}
diff --git a/cpu/mpc5xxx/usb_ohci.c b/cpu/mpc5xxx/usb_ohci.c
index 8806826206..c774da36d1 100644
--- a/cpu/mpc5xxx/usb_ohci.c
+++ b/cpu/mpc5xxx/usb_ohci.c
@@ -98,6 +98,8 @@ urb_priv_t urb_priv;
int got_rhsc;
/* device which was disconnected */
struct usb_device *devgone;
+/* flag guarding URB transation */
+int urb_finished = 0;
/*-------------------------------------------------------------------------*/
@@ -402,6 +404,16 @@ int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer,
return -1;
}
+ /* if we have an unfinished URB from previous transaction let's
+ * fail and scream as quickly as possible so as not to corrupt
+ * further communication */
+ if (!urb_finished) {
+ err("sohci_submit_job: URB NOT FINISHED");
+ return -1;
+ }
+ /* we're about to begin a new transaction here so mark the URB unfinished */
+ urb_finished = 0;
+
/* every endpoint has a ed, locate and fill it */
if (!(ed = ep_add_ed (dev, pipe))) {
err("sohci_submit_job: ENOMEM");
@@ -664,7 +676,6 @@ static void td_fill (ohci_t *ohci, unsigned int info,
else
td->hwBE = 0;
td->hwNextTD = ohci_cpu_to_le32 ((unsigned long)td_pt);
- td->hwPSW [0] = ohci_cpu_to_le16 (((__u32)data & 0x0FFF) | 0xE000);
/* append to queue */
td->ed->hwTailP = td->hwNextTD;
@@ -673,7 +684,6 @@ static void td_fill (ohci_t *ohci, unsigned int info,
/*-------------------------------------------------------------------------*/
/* prepare all TDs of a transfer */
-
static void td_submit_job (struct usb_device *dev, unsigned long pipe, void *buffer,
int transfer_len, struct devrequest *setup, urb_priv_t *urb, int interval)
{
@@ -813,7 +823,7 @@ static int dl_done_list (ohci_t *ohci, td_t *td_list)
td_t *td_list_next = NULL;
ed_t *ed;
int cc = 0;
- int stat = 0xff;
+ int stat = 0;
/* urb_t *urb; */
urb_priv_t *lurb_priv;
__u32 tdINFO, edHeadP, edTailP;
@@ -835,6 +845,7 @@ static int dl_done_list (ohci_t *ohci, td_t *td_list)
&& (lurb_priv->state != URB_DEL)) {
dbg("ConditionCode %#x", cc);
stat = cc_to_error[cc];
+ urb_finished = 1;
}
}
@@ -1250,18 +1261,35 @@ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
stat = USB_ST_CRC_ERR;
break;
}
- if (stat >= 0 && stat < 0xff) {
+
+ /* NOTE: since we are not interrupt driven in U-Boot and always
+ * handle only one URB at a time, we cannot assume the
+ * transaction finished on the first successful return from
+ * hc_interrupt().. unless the flag for current URB is set,
+ * meaning that all TD's to/from device got actually
+ * transferred and processed. If the current URB is not
+ * finished we need to re-iterate this loop so as
+ * hc_interrupt() gets called again as there needs to be some
+ * more TD's to process still */
+ if ((stat >= 0) && (stat != 0xff) && (urb_finished)) {
/* 0xff is returned for an SF-interrupt */
break;
}
+
if (--timeout) {
wait_ms(1);
+ if (!urb_finished)
+ dbg("\%");
+
} else {
err("CTL:TIMEOUT ");
+ dbg("submit_common_msg: TO status %x\n", stat);
stat = USB_ST_CRC_ERR;
+ urb_finished = 1;
break;
}
}
+#if 0
/* we got an Root Hub Status Change interrupt */
if (got_rhsc) {
#ifdef DEBUG
@@ -1283,6 +1311,7 @@ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
devgone = dev;
}
}
+#endif
dev->status = stat;
dev->act_len = transfer_len;
@@ -1455,16 +1484,26 @@ hc_interrupt (void)
int ints;
int stat = -1;
- if ((ohci->hcca->done_head != 0) && !(ohci_cpu_to_le32 (ohci->hcca->done_head) & 0x01)) {
- ints = OHCI_INTR_WDH;
- } else {
- ints = readl (&regs->intrstatus);
+ if ((ohci->hcca->done_head != 0) &&
+ !(ohci_cpu_to_le32(ohci->hcca->done_head) & 0x01)) {
+
+ ints = OHCI_INTR_WDH;
+
+ } else if ((ints = readl (&regs->intrstatus)) == ~(u32)0) {
+ ohci->disabled++;
+ err ("%s device removed!", ohci->slot_name);
+ return -1;
+
+ } else if ((ints &= readl (&regs->intrenable)) == 0) {
+ dbg("hc_interrupt: returning..\n");
+ return 0xff;
}
/* dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); */
if (ints & OHCI_INTR_RHSC) {
got_rhsc = 1;
+ stat = 0xff;
}
if (ints & OHCI_INTR_UE) {
@@ -1499,6 +1538,7 @@ hc_interrupt (void)
/* FIXME: this assumes SOF (1/ms) interrupts don't get lost... */
if (ints & OHCI_INTR_SF) {
unsigned int frame = ohci_cpu_to_le16 (ohci->hcca->frame_no) & 1;
+ wait_ms(1);
writel (OHCI_INTR_SF, &regs->intrdisable);
if (ohci->ed_rm_list[frame] != NULL)
writel (OHCI_INTR_SF, &regs->intrenable);
@@ -1589,6 +1629,8 @@ int usb_lowlevel_init(void)
ohci_dump (&gohci, 1);
#endif
ohci_inited = 1;
+ urb_finished = 1;
+
return 0;
}
diff --git a/cpu/mpc5xxx/usb_ohci.h b/cpu/mpc5xxx/usb_ohci.h
index 11b361af04..884f1d5e51 100644
--- a/cpu/mpc5xxx/usb_ohci.h
+++ b/cpu/mpc5xxx/usb_ohci.h
@@ -104,7 +104,6 @@ struct td {
__u32 hwNextTD; /* Next TD Pointer */
__u32 hwBE; /* Memory Buffer End Pointer */
- __u16 hwPSW[MAXPSW];
__u8 unused;
__u8 index;
struct ed *ed;
diff --git a/cpu/mpc8260/config.mk b/cpu/mpc8260/config.mk
index 3b2892481d..dd7a71fdf3 100644
--- a/cpu/mpc8260/config.mk
+++ b/cpu/mpc8260/config.mk
@@ -23,5 +23,5 @@
PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi
-PLATFORM_CPPFLAGS += -DCONFIG_8260 -ffixed-r2 -ffixed-r29 \
+PLATFORM_CPPFLAGS += -DCONFIG_8260 -DCONFIG_CPM2 -ffixed-r2 -ffixed-r29 \
-mstring -mcpu=603e -mmultiple
diff --git a/cpu/mpc8260/cpu.c b/cpu/mpc8260/cpu.c
index a34386f7c2..5d979330a3 100644
--- a/cpu/mpc8260/cpu.c
+++ b/cpu/mpc8260/cpu.c
@@ -137,13 +137,13 @@ int checkcpu (void)
puts ("0.0 0K50M");
break;
case 0x0C10:
- puts ("1.0 0K50M");
+ puts ("1.0 1K50M");
break;
case 0x0D00:
puts ("0.0 0K50M");
break;
case 0x0D10:
- puts ("1.0 0K50M");
+ puts ("1.0 1K50M");
break;
default:
printf ("unknown [immr=0x%04x,k=0x%04x]", m, k);
diff --git a/cpu/mpc8260/ether_fcc.c b/cpu/mpc8260/ether_fcc.c
index 82f7390709..0393afabc2 100644
--- a/cpu/mpc8260/ether_fcc.c
+++ b/cpu/mpc8260/ether_fcc.c
@@ -628,6 +628,9 @@ swap16 (unsigned short x)
return (((x & 0xff) << 8) | ((x & 0xff00) >> 8));
}
+/* broadcast is not an error - we send them like that */
+#define BD_ENET_RX_ERRS (BD_ENET_RX_STATS & ~BD_ENET_RX_BC)
+
void
eth_loopback_test (void)
{
@@ -1002,7 +1005,7 @@ eth_loopback_test (void)
ecp->rxeacc._f++;
}
- if (sc & BD_ENET_RX_STATS) {
+ if (sc & BD_ENET_RX_ERRS) {
ulong n;
/*
@@ -1033,7 +1036,7 @@ eth_loopback_test (void)
ecp->rxeacc.cl++;
bdp->cbd_sc &= \
- ~BD_ENET_RX_STATS;
+ ~BD_ENET_RX_ERRS;
}
else {
ushort datlen = bdp->cbd_datlen;
diff --git a/cpu/mpc8260/serial_smc.c b/cpu/mpc8260/serial_smc.c
index 0873319339..b486f8385e 100644
--- a/cpu/mpc8260/serial_smc.c
+++ b/cpu/mpc8260/serial_smc.c
@@ -360,10 +360,10 @@ kgdb_serial_init (void)
/* Set up the baud rate generator.
*/
#if defined(CONFIG_KGDB_USE_EXTC)
- m8260_cpm_extcbrg(KGDB_SMC_INDEX, speed,
+ m8260_cpm_extcbrg(brg_map[KGDB_SMC_INDEX], speed,
CONFIG_KGDB_EXTC_RATE, CONFIG_KGDB_EXTC_PINSEL);
#else
- m8260_cpm_setbrg(KGDB_SMC_INDEX, speed);
+ m8260_cpm_setbrg(brg_map[KGDB_SMC_INDEX], speed);
#endif
/* Make the first buffer the only buffer.
diff --git a/cpu/mpc83xx/Makefile b/cpu/mpc83xx/Makefile
new file mode 100644
index 0000000000..14574f45e2
--- /dev/null
+++ b/cpu/mpc83xx/Makefile
@@ -0,0 +1,53 @@
+#
+# Copyright 2004 Freescale Semiconductor, Inc.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = lib$(CPU).a
+
+START = start.o \
+ resetvec.o
+
+COBJS = traps.o \
+ cpu.o \
+ cpu_init.o \
+ speed.o \
+ interrupts.o \
+ pci.o \
+ i2c.o \
+ spd_sdram.o
+
+OBJS = $(COBJS)
+
+all: .depend $(START) $(LIB)
+
+$(LIB): $(OBJS)
+ $(AR) crv $@ $(OBJS)
+
+#########################################################################
+
+.depend: Makefile $(START:.o=.S) $(AOBJS:.o=.S) $(COBJS:.o=.c)
+ $(CC) -M $(CFLAGS) $(START:.o=.S) $(COBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################
diff --git a/cpu/mpc83xx/config.mk b/cpu/mpc83xx/config.mk
new file mode 100644
index 0000000000..8b4ff92b19
--- /dev/null
+++ b/cpu/mpc83xx/config.mk
@@ -0,0 +1,26 @@
+#
+# Copyright 2004 Freescale Semiconductor, Inc.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi
+
+PLATFORM_CPPFLAGS += -DCONFIG_MPC83XX -DCONFIG_E300 \
+ -ffixed-r2 -ffixed-r29 -msoft-float
diff --git a/cpu/mpc83xx/cpu.c b/cpu/mpc83xx/cpu.c
new file mode 100644
index 0000000000..c84aeb4df0
--- /dev/null
+++ b/cpu/mpc83xx/cpu.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2004 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Change log:
+ *
+ * 20050101: Eran Liberty (liberty@freescale.com)
+ * Initial file creating (porting from 85XX & 8260)
+ */
+
+/*
+ * CPU specific code for the MPC83xx family.
+ *
+ * Derived from the MPC8260 and MPC85xx.
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <mpc83xx.h>
+#include <asm/processor.h>
+
+
+int checkcpu(void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+ ulong clock = gd->cpu_clk;
+ u32 pvr = get_pvr();
+ char buf[32];
+
+ if ((pvr & 0xFFFF0000) != PVR_83xx) {
+ puts("Not MPC83xx Family!!!\n");
+ return -1;
+ }
+
+ puts("CPU: MPC83xx, ");
+ switch(pvr) {
+ case PVR_8349_REV10:
+ break;
+ case PVR_8349_REV11:
+ break;
+ default:
+ puts("Rev: Unknown\n");
+ return -1; /* Not sure what this is */
+ }
+ printf("Rev: %02x at %s MHz\n",pvr & 0x0000FFFF, strmhz(buf, clock));
+ return 0;
+}
+
+
+void upmconfig (uint upm, uint *table, uint size)
+{
+ hang(); /* FIXME: upconfig() needed? */
+}
+
+
+int
+do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+ ulong msr;
+#ifndef MPC83xx_RESET
+ ulong addr;
+#endif
+
+ volatile immap_t *immap = (immap_t *) CFG_IMMRBAR;
+
+#ifdef MPC83xx_RESET
+ /* Interrupts and MMU off */
+ __asm__ __volatile__ ("mfmsr %0":"=r" (msr):);
+
+ msr &= ~( MSR_EE | MSR_IR | MSR_DR);
+ __asm__ __volatile__ ("mtmsr %0"::"r" (msr));
+
+ /* enable Reset Control Reg */
+ immap->reset.rpr = 0x52535445;
+
+ /* confirm Reset Control Reg is enabled */
+ while(!((immap->reset.rcer) & RCER_CRE));
+
+ printf("Resetting the board.");
+ printf("\n");
+
+ udelay(200);
+
+ /* perform reset, only one bit */
+ immap->reset.rcr = RCR_SWHR;
+
+#else /* ! MPC83xx_RESET */
+
+ immap->reset.rmr = RMR_CSRE; /* Checkstop Reset enable */
+
+ /* Interrupts and MMU off */
+ __asm__ __volatile__ ("mfmsr %0":"=r" (msr):);
+
+ msr &= ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR);
+ __asm__ __volatile__ ("mtmsr %0"::"r" (msr));
+
+ /*
+ * Trying to execute the next instruction at a non-existing address
+ * should cause a machine check, resulting in reset
+ */
+ addr = CFG_RESET_ADDRESS;
+
+ printf("resetting the board.");
+ printf("\n");
+ ((void (*)(void)) addr) ();
+#endif /* MPC83xx_RESET */
+
+ return 1;
+}
+
+
+/*
+ * Get timebase clock frequency (like cpu_clk in Hz)
+ */
+
+unsigned long get_tbclk(void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ ulong tbclk;
+
+ tbclk = (gd->bus_clk + 3L) / 4L;
+
+ return tbclk;
+}
+
+
+#if defined(CONFIG_WATCHDOG)
+void watchdog_reset (void)
+{
+ hang(); /* FIXME: implement watchdog_reset()? */
+}
+#endif /* CONFIG_WATCHDOG */
diff --git a/cpu/mpc83xx/cpu_init.c b/cpu/mpc83xx/cpu_init.c
new file mode 100644
index 0000000000..dcb34457b1
--- /dev/null
+++ b/cpu/mpc83xx/cpu_init.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2004 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Change log:
+ *
+ * 20050101: Eran Liberty (liberty@freescale.com)
+ * Initial file creating (porting from 85XX & 8260)
+ */
+
+#include <common.h>
+#include <mpc83xx.h>
+#include <ioports.h>
+
+/*
+ * Breathe some life into the CPU...
+ *
+ * Set up the memory map,
+ * initialize a bunch of registers,
+ * initialize the UPM's
+ */
+void cpu_init_f (volatile immap_t * im)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ /* Pointer is writable since we allocated a register for it */
+ gd = (gd_t *) (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET);
+
+ /* Clear initial global data */
+ memset ((void *) gd, 0, sizeof (gd_t));
+
+ /* RSR - Reset Status Register - clear all status (4.6.1.3) */
+ gd->reset_status = im->reset.rsr;
+ im->reset.rsr = ~(RSR_RES);
+
+ /*
+ * RMR - Reset Mode Register
+ * contains checkstop reset enable (4.6.1.4)
+ */
+ im->reset.rmr = (RMR_CSRE & (1<<RMR_CSRE_SHIFT));
+
+ /* LCRR - Clock Ratio Register (10.3.1.16) */
+ im->lbus.lcrr = CFG_LCRR;
+
+ /* Enable Time Base & Decrimenter ( so we will have udelay() )*/
+ im->sysconf.spcr |= SPCR_TBEN;
+
+ /* System General Purpose Register */
+ im->sysconf.sicrh = SICRH_TSOBI1;
+ im->sysconf.sicrl = SICRL_LDP_A;
+
+ /*
+ * Memory Controller:
+ */
+
+ /* Map banks 0 and 1 to the FLASH banks 0 and 1 at preliminary
+ * addresses - these have to be modified later when FLASH size
+ * has been determined
+ */
+
+#if defined(CFG_BR0_PRELIM) \
+ && defined(CFG_OR0_PRELIM) \
+ && defined(CFG_LBLAWBAR0_PRELIM) \
+ && defined(CFG_LBLAWAR0_PRELIM)
+ im->lbus.bank[0].br = CFG_BR0_PRELIM;
+ im->lbus.bank[0].or = CFG_OR0_PRELIM;
+ im->sysconf.lblaw[0].bar = CFG_LBLAWBAR0_PRELIM;
+ im->sysconf.lblaw[0].ar = CFG_LBLAWAR0_PRELIM;
+#else
+#error CFG_BR0_PRELIM, CFG_OR0_PRELIM, CFG_LBLAWBAR0_PRELIM & CFG_LBLAWAR0_PRELIM must be defined
+#endif
+
+#if defined(CFG_BR1_PRELIM) \
+ && defined(CFG_OR1_PRELIM) \
+ && defined(CFG_LBLAWBAR1_PRELIM) \
+ && defined(CFG_LBLAWAR1_PRELIM)
+ im->lbus.bank[1].br = CFG_BR1_PRELIM;
+ im->lbus.bank[1].or = CFG_OR1_PRELIM;
+ im->sysconf.lblaw[1].bar = CFG_LBLAWBAR1_PRELIM;
+ im->sysconf.lblaw[1].ar = CFG_LBLAWAR1_PRELIM;
+#endif
+#if defined(CFG_BR2_PRELIM) \
+ && defined(CFG_OR2_PRELIM) \
+ && defined(CFG_LBLAWBAR2_PRELIM) \
+ && defined(CFG_LBLAWAR2_PRELIM)
+ im->lbus.bank[2].br = CFG_BR2_PRELIM;
+ im->lbus.bank[2].or = CFG_OR2_PRELIM;
+ im->sysconf.lblaw[2].bar = CFG_LBLAWBAR2_PRELIM;
+ im->sysconf.lblaw[2].ar = CFG_LBLAWAR2_PRELIM;
+#endif
+#if defined(CFG_BR3_PRELIM) \
+ && defined(CFG_OR3_PRELIM) \
+ && defined(CFG_LBLAWBAR3_PRELIM) \
+ && defined(CFG_LBLAWAR3_PRELIM)
+ im->lbus.bank[3].br = CFG_BR3_PRELIM;
+ im->lbus.bank[3].or = CFG_OR3_PRELIM;
+ im->sysconf.lblaw[3].bar = CFG_LBLAWBAR3_PRELIM;
+ im->sysconf.lblaw[3].ar = CFG_LBLAWAR3_PRELIM;
+#endif
+#if defined(CFG_BR4_PRELIM) \
+ && defined(CFG_OR4_PRELIM) \
+ && defined(CFG_LBLAWBAR4_PRELIM) \
+ && defined(CFG_LBLAWAR4_PRELIM)
+ im->lbus.bank[4].br = CFG_BR4_PRELIM;
+ im->lbus.bank[4].or = CFG_OR4_PRELIM;
+ im->sysconf.lblaw[4].bar = CFG_LBLAWBAR4_PRELIM;
+ im->sysconf.lblaw[4].ar = CFG_LBLAWAR4_PRELIM;
+#endif
+#if defined(CFG_BR5_PRELIM) \
+ && defined(CFG_OR5_PRELIM) \
+ && defined(CFG_LBLAWBAR5_PRELIM) \
+ && defined(CFG_LBLAWAR5_PRELIM)
+ im->lbus.bank[5].br = CFG_BR5_PRELIM;
+ im->lbus.bank[5].or = CFG_OR5_PRELIM;
+ im->sysconf.lblaw[5].bar = CFG_LBLAWBAR5_PRELIM;
+ im->sysconf.lblaw[5].ar = CFG_LBLAWAR5_PRELIM;
+#endif
+#if defined(CFG_BR6_PRELIM) \
+ && defined(CFG_OR6_PRELIM) \
+ && defined(CFG_LBLAWBAR6_PRELIM) \
+ && defined(CFG_LBLAWAR6_PRELIM)
+ im->lbus.bank[6].br = CFG_BR6_PRELIM;
+ im->lbus.bank[6].or = CFG_OR6_PRELIM;
+ im->sysconf.lblaw[6].bar = CFG_LBLAWBAR6_PRELIM;
+ im->sysconf.lblaw[6].ar = CFG_LBLAWAR6_PRELIM;
+#endif
+#if defined(CFG_BR7_PRELIM) \
+ && defined(CFG_OR7_PRELIM) \
+ && defined(CFG_LBLAWBAR7_PRELIM) \
+ && defined(CFG_LBLAWAR7_PRELIM)
+ im->lbus.bank[7].br = CFG_BR7_PRELIM;
+ im->lbus.bank[7].or = CFG_OR7_PRELIM;
+ im->sysconf.lblaw[7].bar = CFG_LBLAWBAR7_PRELIM;
+ im->sysconf.lblaw[7].ar = CFG_LBLAWAR7_PRELIM;
+#endif
+}
+
+
+/*
+ * Initialize higher level parts of CPU like time base and timers.
+ */
+
+int cpu_init_r (void)
+{
+ return 0;
+}
diff --git a/cpu/mpc83xx/i2c.c b/cpu/mpc83xx/i2c.c
new file mode 100644
index 0000000000..3db7d2cbcd
--- /dev/null
+++ b/cpu/mpc83xx/i2c.c
@@ -0,0 +1,251 @@
+/*
+ * (C) Copyright 2003,Motorola Inc.
+ * Xianghua Xiao <x.xiao@motorola.com>
+ * Adapted for Motorola 85xx chip.
+ *
+ * (C) Copyright 2003
+ * Gleb Natapov <gnatapov@mrv.com>
+ * Some bits are taken from linux driver writen by adrian@humboldt.co.uk
+ *
+ * Hardware I2C driver for MPC107 PCI bridge.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Change log:
+ *
+ * 20050101: Eran Liberty (liberty@freescale.com)
+ * Initial file creating (porting from 85XX & 8260)
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_HARD_I2C
+#include <i2c.h>
+#include <asm/i2c.h>
+
+#ifdef CONFIG_MPC8349ADS
+i2c_t * mpc8349_i2c = (i2c_t*)(CFG_IMMRBAR + CFG_I2C_OFFSET);
+#endif
+
+void
+i2c_init(int speed, int slaveadd)
+{
+ /* stop I2C controller */
+ writeb(0x00 , &I2C->cr);
+
+ /* set clock */
+ writeb(0x3f, &I2C->fdr);
+
+ /* set default filter */
+ writeb(0x10,&I2C->dfsrr);
+
+ /* write slave address */
+ writeb(slaveadd, &I2C->adr);
+
+ /* clear status register */
+ writeb(0x00, &I2C->sr);
+
+ /* start I2C controller */
+ writeb(I2C_CR_MEN, &I2C->cr);
+}
+
+static __inline__ int
+i2c_wait4bus (void)
+{
+ ulong timeval = get_timer (0);
+ while (readb(&I2C->sr) & I2C_SR_MBB) {
+ if (get_timer (timeval) > I2C_TIMEOUT) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static __inline__ int
+i2c_wait (int write)
+{
+ u32 csr;
+ ulong timeval = get_timer(0);
+ do {
+ csr = readb(&I2C->sr);
+
+ if (!(csr & I2C_SR_MIF))
+ continue;
+
+ writeb(0x0, &I2C->sr);
+
+ if (csr & I2C_SR_MAL) {
+ debug("i2c_wait: MAL\n");
+ return -1;
+ }
+
+ if (!(csr & I2C_SR_MCF)) {
+ debug("i2c_wait: unfinished\n");
+ return -1;
+ }
+
+ if (write == I2C_WRITE && (csr & I2C_SR_RXAK)) {
+ debug("i2c_wait: No RXACK\n");
+ return -1;
+ }
+
+ return 0;
+ } while (get_timer (timeval) < I2C_TIMEOUT);
+ debug("i2c_wait: timed out\n");
+}
+
+static __inline__ int
+i2c_write_addr (u8 dev, u8 dir, int rsta)
+{
+ writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_MTX |
+ (rsta?I2C_CR_RSTA:0),
+ &I2C->cr);
+
+ writeb((dev << 1) | dir, &I2C->dr);
+
+ if (i2c_wait (I2C_WRITE) < 0)
+ return 0;
+ return 1;
+}
+
+static __inline__ int
+__i2c_write (u8 *data, int length)
+{
+ int i;
+
+ writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_MTX,
+ &I2C->cr);
+
+ for (i=0; i < length; i++) {
+ writeb(data[i], &I2C->dr);
+
+ if (i2c_wait (I2C_WRITE) < 0)
+ break;
+ }
+ return i;
+}
+
+static __inline__ int
+__i2c_read (u8 *data, int length)
+{
+ int i;
+
+ writeb(I2C_CR_MEN | I2C_CR_MSTA |
+ ((length == 1) ? I2C_CR_TXAK : 0),
+ &I2C->cr);
+
+ /* dummy read */
+ readb(&I2C->dr);
+
+ for (i=0; i < length; i++) {
+ if (i2c_wait (I2C_READ) < 0)
+ break;
+
+ /* Generate ack on last next to last byte */
+ if (i == length - 2)
+ writeb(I2C_CR_MEN | I2C_CR_MSTA |
+ I2C_CR_TXAK,
+ &I2C->cr);
+
+ /* Generate stop on last byte */
+ if (i == length - 1)
+ writeb(I2C_CR_MEN | I2C_CR_TXAK, &I2C->cr);
+
+ data[i] = readb(&I2C->dr);
+ }
+ return i;
+}
+
+int
+i2c_read (u8 dev, uint addr, int alen, u8 *data, int length)
+{
+ int i = 0;
+ u8 *a = (u8*)&addr;
+
+ if (i2c_wait4bus () < 0)
+ goto exit;
+
+ if (i2c_write_addr (dev, I2C_WRITE, 0) == 0)
+ goto exit;
+
+ if (__i2c_write (&a[4 - alen], alen) != alen)
+ goto exit;
+
+ if (i2c_write_addr (dev, I2C_READ, 1) == 0)
+ goto exit;
+
+ i = __i2c_read (data, length);
+
+ exit:
+ writeb(I2C_CR_MEN, &I2C->cr);
+ return !(i == length);
+}
+
+int
+i2c_write (u8 dev, uint addr, int alen, u8 *data, int length)
+{
+ int i = 0;
+ u8 *a = (u8*)&addr;
+
+ if (i2c_wait4bus () < 0)
+ goto exit;
+
+ if (i2c_write_addr (dev, I2C_WRITE, 0) == 0)
+ goto exit;
+
+ if (__i2c_write (&a[4 - alen], alen) != alen)
+ goto exit;
+
+ i = __i2c_write (data, length);
+
+ exit:
+ writeb(I2C_CR_MEN, &I2C->cr);
+ return !(i == length);
+}
+
+int i2c_probe (uchar chip)
+{
+ int tmp;
+
+ /*
+ * Try to read the first location of the chip. The underlying
+ * driver doesn't appear to support sending just the chip address
+ * and looking for an <ACK> back.
+ */
+ udelay(10000);
+ return i2c_read (chip, 0, 1, (char *)&tmp, 1);
+}
+
+uchar i2c_reg_read (uchar i2c_addr, uchar reg)
+{
+ char buf[1];
+
+ i2c_read (i2c_addr, reg, 1, buf, 1);
+
+ return (buf[0]);
+}
+
+void i2c_reg_write (uchar i2c_addr, uchar reg, uchar val)
+{
+ i2c_write (i2c_addr, reg, 1, &val, 1);
+}
+
+#endif /* CONFIG_HARD_I2C */
diff --git a/cpu/mpc83xx/interrupts.c b/cpu/mpc83xx/interrupts.c
new file mode 100644
index 0000000000..53474f60c9
--- /dev/null
+++ b/cpu/mpc83xx/interrupts.c
@@ -0,0 +1,94 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright 2004 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Change log:
+ *
+ * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 22-Oct-00
+ *
+ * 20050101: Eran Liberty (liberty@freescale.com)
+ * Initial file creating (porting from 85XX & 8260)
+ */
+
+#include <common.h>
+#include <command.h>
+#include <mpc83xx.h>
+#include <asm/processor.h>
+
+struct irq_action {
+ interrupt_handler_t *handler;
+ void *arg;
+ ulong count;
+};
+
+int interrupt_init_cpu (unsigned *decrementer_count)
+{
+ return 0;
+}
+
+
+/*
+ * Handle external interrupts
+ */
+
+void external_interrupt (struct pt_regs *regs)
+{
+}
+
+
+/*
+ * Install and free an interrupt handler.
+ */
+
+void
+irq_install_handler (int irq, interrupt_handler_t * handler, void *arg)
+{
+}
+
+
+void irq_free_handler (int irq)
+{
+}
+
+
+void timer_interrupt_cpu (struct pt_regs *regs)
+{
+ /* nothing to do here */
+ return;
+}
+
+
+#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
+
+/* ripped this out of ppc4xx/interrupts.c */
+
+/*
+ * irqinfo - print information about PCI devices
+ */
+
+void
+do_irqinfo(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+}
+
+#endif /* CONFIG_COMMANDS & CFG_CMD_IRQ */
diff --git a/cpu/mpc83xx/pci.c b/cpu/mpc83xx/pci.c
new file mode 100644
index 0000000000..d5fa811edf
--- /dev/null
+++ b/cpu/mpc83xx/pci.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2004 Freescale Semiconductor.
+ * Copyright (C) 2003 Motorola Inc.
+ * Xianghua Xiao (x.xiao@motorola.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Change log:
+ *
+ * 20050101: Eran Liberty (liberty@freescale.com)
+ * Initial file creating (porting from 85XX & 8260)
+ */
+
+/*
+ * PCI Configuration space access support for MPC85xx PCI Bridge
+ */
+#include <asm/mmu.h>
+#include <asm/io.h>
+#include <common.h>
+#include <pci.h>
+
+#ifdef CONFIG_MPC8349ADS
+#include <asm/i2c.h>
+#endif
+
+#if defined(CONFIG_PCI)
+
+void
+pci_mpc83xx_init(volatile struct pci_controller *hose)
+{
+ volatile immap_t * immr;
+ volatile clk8349_t * clk;
+ volatile law8349_t * pci_law;
+ volatile pot8349_t * pci_pot;
+ volatile pcictrl8349_t * pci_ctrl;
+ volatile pciconf8349_t * pci_conf;
+
+ u8 val8,tmp8,ret;
+ u16 reg16,tmp16;
+ u32 val32,tmp32;
+
+ immr = (immap_t *)CFG_IMMRBAR;
+ clk = (clk8349_t *)&immr->clk;
+ pci_law = immr->sysconf.pcilaw;
+ pci_pot = immr->ios.pot;
+ pci_ctrl = immr->pci_ctrl;
+ pci_conf = immr->pci_conf;
+
+ /*
+ * Configure PCI controller and PCI_CLK_OUTPUT both in 66M mode
+ */
+ val32 = clk->occr;
+ udelay(2000);
+ clk->occr = 0xff000000;
+ udelay(2000);
+
+ /*
+ * Configure PCI Local Access Windows
+ */
+ pci_law[0].bar = CFG_PCI1_MEM_PHYS & LAWBAR_BAR;
+ pci_law[0].ar = LAWAR_EN | LAWAR_SIZE_1G;
+ pci_law[1].bar = CFG_PCI1_IO_PHYS & LAWBAR_BAR;
+ pci_law[1].ar = LAWAR_EN | LAWAR_SIZE_32M;
+
+ /*
+ * Configure PCI Outbound Translation Windows
+ */
+ pci_pot[0].potar = (CFG_PCI1_MEM_BASE >> 12) & POTAR_TA_MASK;
+ pci_pot[0].pobar = (CFG_PCI1_MEM_PHYS >> 12) & POBAR_BA_MASK;
+ pci_pot[0].pocmr = POCMR_EN | (POCMR_CM_512M & POCMR_CM_MASK);
+
+ /* mapped to PCI1 IO space 0x0 to local 0xe2000000 */
+ pci_pot[1].potar = (CFG_PCI1_IO_BASE >> 12) & POTAR_TA_MASK;
+ pci_pot[1].pobar = (CFG_PCI1_IO_PHYS >> 12) & POBAR_BA_MASK;
+ pci_pot[1].pocmr = POCMR_EN | POCMR_IO | (POCMR_CM_16M & POCMR_CM_MASK);
+
+ pci_pot[3].potar = (CFG_PCI2_MEM_BASE >> 12) & POTAR_TA_MASK;
+ pci_pot[3].pobar = (CFG_PCI2_MEM_PHYS >> 12) & POBAR_BA_MASK;
+ pci_pot[3].pocmr = POCMR_EN | POCMR_DST | (POCMR_CM_512M & POCMR_CM_MASK);
+
+ /* mapped to PCI2 IO space 0x0 to local 0xe3000000 */
+ pci_pot[4].potar = (CFG_PCI2_IO_BASE >> 12) & POTAR_TA_MASK;
+ pci_pot[4].pobar = (CFG_PCI2_IO_PHYS >> 12) & POBAR_BA_MASK;
+ pci_pot[4].pocmr = POCMR_EN | POCMR_DST | POCMR_IO | (POCMR_CM_16M & POCMR_CM_MASK);
+
+ /*
+ * Configure PCI Inbound Translation Windows
+ */
+ pci_ctrl[0].pitar1 = 0x0;
+ pci_ctrl[0].pibar1 = 0x0;
+ pci_ctrl[0].piebar1 = 0x0;
+ pci_ctrl[0].piwar1 = PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP | PIWAR_WTT_SNOOP | PIWAR_IWS_2G;
+
+ pci_ctrl[1].pitar1 = 0x0;
+ pci_ctrl[1].pibar1 = 0x0;
+ pci_ctrl[1].piebar1 = 0x0;
+ pci_ctrl[1].piwar1 = PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP | PIWAR_WTT_SNOOP | PIWAR_IWS_2G;
+ /*
+ * Assign PIB PMC slot to desired PCI bus
+ */
+#ifdef CONFIG_MPC8349ADS
+ mpc8349_i2c = (i2c_t*)(CFG_IMMRBAR + CFG_I2C2_OFFSET);
+ i2c_init(CFG_I2C_SPEED,CFG_I2C_SLAVE);
+#endif
+ val8 = 0;
+ ret = i2c_write(0x23,0x6,1,&val8,1);
+ ret = i2c_write(0x23,0x7,1,&val8,1);
+ val8 = 0xff;
+ ret = i2c_write(0x23,0x2,1,&val8,1);
+ ret = i2c_write(0x23,0x3,1,&val8,1);
+
+ val8 = 0;
+ ret = i2c_write(0x26,0x6,1,&val8,1);
+ val8 = 0x34;
+ ret = i2c_write(0x26,0x7,1,&val8,1);
+#if defined(PCI_64BIT)
+ val8 = 0xf4; /* PMC2<->PCI1 64bit */
+#elif defined(PCI_ALL_PCI1)
+ val8 = 0xf3; /* PMC1<->PCI1,PMC2<->PCI1,PMC3<->PCI1 32bit */
+#elif defined(PCI_ONE_PCI1)
+ val8 = 0xf9; /* PMC1<->PCI1,PMC2<->PCI2,PMC3<->PCI2 32bit */
+#elif defined(PCI_TWO_PCI1)
+ val8 = 0xf5; /* PMC1<->PCI1,PMC2<->PCI1,PMC3<->PCI2 32bit */
+#else
+ val8 = 0xf5;
+#endif
+ ret = i2c_write(0x26,0x2,1,&val8,1);
+ val8 = 0xff;
+ ret = i2c_write(0x26,0x3,1,&val8,1);
+ val8 = 0;
+ ret = i2c_write(0x27,0x6,1,&val8,1);
+ ret = i2c_write(0x27,0x7,1,&val8,1);
+ val8 = 0xff;
+ ret = i2c_write(0x27,0x2,1,&val8,1);
+ val8 = 0xef;
+ ret = i2c_write(0x27,0x3,1,&val8,1);
+ asm("eieio");
+
+ /*
+ * Release PCI RST Output signal
+ */
+ udelay(2000);
+ pci_ctrl[0].gcr = 1;
+#ifndef PCI_64BIT
+ pci_ctrl[1].gcr = 1;
+#endif
+ udelay(2000);
+
+ hose[0].first_busno = 0;
+ hose[0].last_busno = 0xff;
+
+ pci_set_region(hose[0].regions + 0,
+ CFG_PCI1_MEM_BASE,
+ CFG_PCI1_MEM_PHYS,
+ CFG_PCI1_MEM_SIZE,
+ PCI_REGION_MEM);
+
+ pci_set_region(hose[0].regions + 1,
+ CFG_PCI1_IO_BASE,
+ CFG_PCI1_IO_PHYS,
+ CFG_PCI1_IO_SIZE,
+ PCI_REGION_IO);
+
+ hose[0].region_count = 2;
+
+ pci_setup_indirect(&hose[0],
+ (CFG_IMMRBAR+0x8300),
+ (CFG_IMMRBAR+0x8304));
+#define PCI_CLASS_BRIDGE 0x06
+ reg16 = 0xff;
+ tmp32 = 0xffff;
+ pci_hose_write_config_byte(&hose[0],PCI_BDF(0,0,0),PCI_CLASS_CODE,PCI_CLASS_BRIDGE);
+
+ pci_hose_read_config_word (&hose[0],PCI_BDF(0,0,0),PCI_COMMAND, &reg16);
+ reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ pci_hose_write_config_word(&hose[0],PCI_BDF(0,0,0), PCI_COMMAND, reg16);
+
+ /*
+ * Clear non-reserved bits in status register.
+ */
+ pci_hose_write_config_word(&hose[0],PCI_BDF(0,0,0), PCI_STATUS, 0xffff);
+ pci_hose_write_config_byte(&hose[0],PCI_BDF(0,0,0), PCI_LATENCY_TIMER,0x80);
+#ifndef PCI_64BIT
+ hose[1].first_busno = 0;
+ hose[1].last_busno = 0xff;
+
+ pci_set_region(hose[1].regions + 0,
+ CFG_PCI2_MEM_BASE,
+ CFG_PCI2_MEM_PHYS,
+ CFG_PCI2_MEM_SIZE,
+ PCI_REGION_MEM);
+
+ pci_set_region(hose[1].regions + 1,
+ CFG_PCI2_IO_BASE,
+ CFG_PCI2_IO_PHYS,
+ CFG_PCI2_IO_SIZE,
+ PCI_REGION_IO);
+
+ hose[1].region_count = 2;
+
+ pci_setup_indirect(&hose[1],
+ (CFG_IMMRBAR+0x8380),
+ (CFG_IMMRBAR+0x8384));
+
+ pci_hose_write_config_byte(&hose[1],PCI_BDF(0,0,0),PCI_CLASS_CODE,PCI_CLASS_BRIDGE);
+ pci_hose_read_config_word (&hose[1],PCI_BDF(0,0,0), PCI_COMMAND, &reg16);
+ reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ pci_hose_write_config_word(&hose[1],PCI_BDF(0,0,0), PCI_COMMAND, reg16);
+
+ /*
+ * Clear non-reserved bits in status register.
+ */
+ pci_hose_write_config_word(&hose[1],PCI_BDF(0,0,0), PCI_STATUS, 0xffff);
+ pci_hose_write_config_byte(&hose[1],PCI_BDF(0,0,0), PCI_LATENCY_TIMER,0x80);
+#endif
+
+#if defined(PCI_64BIT)
+ printf("PCI1 64bit on PMC2\n");
+#elif defined(PCI_ALL_PCI1)
+ printf("PCI1 32bit on PMC1 & PMC2 & PMC3\n");
+#elif defined(PCI_ONE_PCI1)
+ printf("PCI1 32bit on PMC1,PCI2 32bit on PMC2 & PMC3\n");
+#else
+ printf("PCI1 32bit on PMC1 & PMC2 & PMC3 in default\n");
+#endif
+
+#if 1
+ /*
+ * Hose scan.
+ */
+ pci_register_hose(hose);
+ hose->last_busno = pci_hose_scan(hose);
+#endif
+}
+
+#endif /* CONFIG_PCI */
diff --git a/cpu/mpc83xx/resetvec.S b/cpu/mpc83xx/resetvec.S
new file mode 100644
index 0000000000..3dfcd0dcd5
--- /dev/null
+++ b/cpu/mpc83xx/resetvec.S
@@ -0,0 +1,6 @@
+ .section .resetvec,"ax"
+#ifndef FIXME
+#if 0
+ b _start_e500
+#endif
+#endif
diff --git a/cpu/mpc83xx/spd_sdram.c b/cpu/mpc83xx/spd_sdram.c
new file mode 100644
index 0000000000..63dcd664be
--- /dev/null
+++ b/cpu/mpc83xx/spd_sdram.c
@@ -0,0 +1,408 @@
+/*
+ * Copyright 2004 Freescale Semiconductor.
+ * (C) Copyright 2003 Motorola Inc.
+ * Xianghua Xiao (X.Xiao@motorola.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Change log:
+ *
+ * 20050101: Eran Liberty (liberty@freescale.com)
+ * Initial file creating (porting from 85XX & 8260)
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <i2c.h>
+#include <spd.h>
+#include <asm/mmu.h>
+#include <spd_sdram.h>
+
+#ifdef CONFIG_SPD_EEPROM
+
+#if defined(CONFIG_DDR_ECC)
+extern void dma_init(void);
+extern uint dma_check(void);
+extern int dma_xfer(void *dest, uint count, void *src);
+#endif
+
+#ifndef CFG_READ_SPD
+#define CFG_READ_SPD i2c_read
+#endif
+
+/*
+ * Convert picoseconds into clock cycles (rounding up if needed).
+ */
+
+int
+picos_to_clk(int picos)
+{
+ int clks;
+
+ clks = picos / (2000000000 / (get_bus_freq(0) / 1000));
+ if (picos % (2000000000 / (get_bus_freq(0) / 1000)) != 0) {
+ clks++;
+ }
+
+ return clks;
+}
+
+unsigned int
+banksize(unsigned char row_dens)
+{
+ return ((row_dens >> 2) | ((row_dens & 3) << 6)) << 24;
+}
+
+long int spd_sdram(int(read_spd)(uint addr))
+{
+ volatile immap_t *immap = (immap_t *)CFG_IMMRBAR;
+ volatile ddr8349_t *ddr = &immap->ddr;
+ volatile law8349_t *ecm = &immap->sysconf.ddrlaw[0];
+ spd_eeprom_t spd;
+ unsigned tmp, tmp1;
+ unsigned int memsize;
+ unsigned int law_size;
+ unsigned char caslat;
+ unsigned int trfc, trfc_clk, trfc_low;
+
+#warning Current spd_sdram does not fit its usage... adjust implementation or API...
+
+ CFG_READ_SPD(SPD_EEPROM_ADDRESS, 0, 1, (uchar *) & spd, sizeof (spd));
+
+ if (spd.nrows > 2) {
+ puts("DDR:Only two chip selects are supported on ADS.\n");
+ return 0;
+ }
+
+ if (spd.nrow_addr < 12
+ || spd.nrow_addr > 14
+ || spd.ncol_addr < 8
+ || spd.ncol_addr > 11) {
+ puts("DDR:Row or Col number unsupported.\n");
+ return 0;
+ }
+
+ ddr->csbnds[2].csbnds = (banksize(spd.row_dens) >> 24) - 1;
+ ddr->cs_config[2] = ( 1 << 31
+ | (spd.nrow_addr - 12) << 8
+ | (spd.ncol_addr - 8) );
+ debug("\n");
+ debug("cs2_bnds = 0x%08x\n",ddr->csbnds[2].csbnds);
+ debug("cs2_config = 0x%08x\n",ddr->cs_config[2]);
+
+ if (spd.nrows == 2) {
+ ddr->csbnds[3].csbnds = ( (banksize(spd.row_dens) >> 8)
+ | ((banksize(spd.row_dens) >> 23) - 1) );
+ ddr->cs_config[3] = ( 1<<31
+ | (spd.nrow_addr-12) << 8
+ | (spd.ncol_addr-8) );
+ debug("cs3_bnds = 0x%08x\n",ddr->csbnds[3].csbnds);
+ debug("cs3_config = 0x%08x\n",ddr->cs_config[3]);
+ }
+
+ if (spd.mem_type != 0x07) {
+ puts("No DDR module found!\n");
+ return 0;
+ }
+
+ /*
+ * Figure out memory size in Megabytes.
+ */
+ memsize = spd.nrows * banksize(spd.row_dens) / 0x100000;
+
+ /*
+ * First supported LAW size is 16M, at LAWAR_SIZE_16M == 23.
+ */
+ law_size = 19 + __ilog2(memsize);
+
+ /*
+ * Set up LAWBAR for all of DDR.
+ */
+ ecm->bar = ((CFG_DDR_SDRAM_BASE>>12) & 0xfffff);
+ ecm->ar = (LAWAR_EN | LAWAR_TRGT_IF_DDR | (LAWAR_SIZE & law_size));
+ debug("DDR:bar=0x%08x\n", ecm->bar);
+ debug("DDR:ar=0x%08x\n", ecm->ar);
+
+ /*
+ * find the largest CAS
+ */
+ if(spd.cas_lat & 0x40) {
+ caslat = 7;
+ } else if (spd.cas_lat & 0x20) {
+ caslat = 6;
+ } else if (spd.cas_lat & 0x10) {
+ caslat = 5;
+ } else if (spd.cas_lat & 0x08) {
+ caslat = 4;
+ } else if (spd.cas_lat & 0x04) {
+ caslat = 3;
+ } else if (spd.cas_lat & 0x02) {
+ caslat = 2;
+ } else if (spd.cas_lat & 0x01) {
+ caslat = 1;
+ } else {
+ puts("DDR:no valid CAS Latency information.\n");
+ return 0;
+ }
+
+ tmp = 20000 / (((spd.clk_cycle & 0xF0) >> 4) * 10
+ + (spd.clk_cycle & 0x0f));
+ debug("DDR:Module maximum data rate is: %dMhz\n", tmp);
+
+ tmp1 = get_bus_freq(0) / 1000000;
+ if (tmp1 < 230 && tmp1 >= 90 && tmp >= 230) {
+ /* 90~230 range, treated as DDR 200 */
+ if (spd.clk_cycle3 == 0xa0)
+ caslat -= 2;
+ else if(spd.clk_cycle2 == 0xa0)
+ caslat--;
+ } else if (tmp1 < 280 && tmp1 >= 230 && tmp >= 280) {
+ /* 230-280 range, treated as DDR 266 */
+ if (spd.clk_cycle3 == 0x75)
+ caslat -= 2;
+ else if (spd.clk_cycle2 == 0x75)
+ caslat--;
+ } else if (tmp1 < 350 && tmp1 >= 280 && tmp >= 350) {
+ /* 280~350 range, treated as DDR 333 */
+ if (spd.clk_cycle3 == 0x60)
+ caslat -= 2;
+ else if (spd.clk_cycle2 == 0x60)
+ caslat--;
+ } else if (tmp1 < 90 || tmp1 >= 350) {
+ /* DDR rate out-of-range */
+ puts("DDR:platform frequency is not fit for DDR rate\n");
+ return 0;
+ }
+
+ /*
+ * note: caslat must also be programmed into ddr->sdram_mode
+ * register.
+ *
+ * note: WRREC(Twr) and WRTORD(Twtr) are not in SPD,
+ * use conservative value here.
+ */
+ trfc = spd.trfc * 1000; /* up to ps */
+ trfc_clk = picos_to_clk(trfc);
+ trfc_low = (trfc_clk - 8) & 0xf;
+
+ ddr->timing_cfg_1 =
+ (((picos_to_clk(spd.trp * 250) & 0x07) << 28 ) |
+ ((picos_to_clk(spd.tras * 1000) & 0x0f ) << 24 ) |
+ ((picos_to_clk(spd.trcd * 250) & 0x07) << 20 ) |
+ ((caslat & 0x07) << 16 ) |
+ (trfc_low << 12 ) |
+ ( 0x300 ) |
+ ((picos_to_clk(spd.trrd * 250) & 0x07) << 4) | 1);
+
+ ddr->timing_cfg_2 = 0x00000800;
+
+ debug("DDR:timing_cfg_1=0x%08x\n", ddr->timing_cfg_1);
+ debug("DDR:timing_cfg_2=0x%08x\n", ddr->timing_cfg_2);
+
+ /*
+ * Only DDR I is supported
+ * DDR I and II have different mode-register-set definition
+ */
+
+ /* burst length is always 4 */
+ switch(caslat) {
+ case 2:
+ ddr->sdram_mode = 0x52; /* 1.5 */
+ break;
+ case 3:
+ ddr->sdram_mode = 0x22; /* 2.0 */
+ break;
+ case 4:
+ ddr->sdram_mode = 0x62; /* 2.5 */
+ break;
+ case 5:
+ ddr->sdram_mode = 0x32; /* 3.0 */
+ break;
+ default:
+ puts("DDR:only CAS Latency 1.5, 2.0, 2.5, 3.0 is supported.\n");
+ return 0;
+ }
+ debug("DDR:sdram_mode=0x%08x\n", ddr->sdram_mode);
+
+ switch(spd.refresh) {
+ case 0x00:
+ case 0x80:
+ tmp = picos_to_clk(15625000);
+ break;
+ case 0x01:
+ case 0x81:
+ tmp = picos_to_clk(3900000);
+ break;
+ case 0x02:
+ case 0x82:
+ tmp = picos_to_clk(7800000);
+ break;
+ case 0x03:
+ case 0x83:
+ tmp = picos_to_clk(31300000);
+ break;
+ case 0x04:
+ case 0x84:
+ tmp = picos_to_clk(62500000);
+ break;
+ case 0x05:
+ case 0x85:
+ tmp = picos_to_clk(125000000);
+ break;
+ default:
+ tmp = 0x512;
+ break;
+ }
+
+ /*
+ * Set BSTOPRE to 0x100 for page mode
+ * If auto-charge is used, set BSTOPRE = 0
+ */
+ ddr->sdram_interval = ((tmp & 0x3fff) << 16) | 0x100;
+ debug("DDR:sdram_interval=0x%08x\n", ddr->sdram_interval);
+
+ /*
+ * Is this an ECC DDR chip?
+ */
+#if defined(CONFIG_DDR_ECC)
+ if (spd.config == 0x02) {
+ ddr->err_disable = 0x0000000d;
+ ddr->err_sbe = 0x00ff0000;
+ }
+ debug("DDR:err_disable=0x%08x\n", ddr->err_disable);
+ debug("DDR:err_sbe=0x%08x\n", ddr->err_sbe);
+#endif
+ asm("sync;isync");
+
+ udelay(500);
+
+ /*
+ * SS_EN=1,
+ * CLK_ADJST = 2-MCK/MCK_B, is lauched 1/2 of one SDRAM
+ * clock cycle after address/command
+ */
+ ddr->sdram_clk_cntl = 0x82000000;
+
+ /*
+ * Figure out the settings for the sdram_cfg register. Build up
+ * the entire register in 'tmp' before writing since the write into
+ * the register will actually enable the memory controller, and all
+ * settings must be done before enabling.
+ *
+ * sdram_cfg[0] = 1 (ddr sdram logic enable)
+ * sdram_cfg[1] = 1 (self-refresh-enable)
+ * sdram_cfg[6:7] = 2 (SDRAM type = DDR SDRAM)
+ */
+ tmp = 0xc2000000;
+
+ /*
+ * sdram_cfg[3] = RD_EN - registered DIMM enable
+ * A value of 0x26 indicates micron registered DIMMS (micron.com)
+ */
+ if (spd.mod_attr == 0x26) {
+ tmp |= 0x10000000;
+ }
+
+#if defined(CONFIG_DDR_ECC)
+ /*
+ * If the user wanted ECC (enabled via sdram_cfg[2])
+ */
+ if (spd.config == 0x02) {
+ tmp |= 0x20000000;
+ }
+#endif
+
+#if defined(CONFIG_DDR_2T_TIMING)
+ /*
+ * Enable 2T timing by setting sdram_cfg[16].
+ */
+ tmp |= SDRAM_CFG_2T_EN;
+#endif
+
+ ddr->sdram_cfg = tmp;
+ asm("sync;isync");
+ udelay(500);
+
+ debug("DDR:sdram_cfg=0x%08x\n", ddr->sdram_cfg);
+
+ return memsize;/*in MBytes*/
+}
+#endif /* CONFIG_SPD_EEPROM */
+
+
+#if defined(CONFIG_DDR_ECC)
+/*
+ * Initialize all of memory for ECC, then enable errors.
+ */
+
+void
+ddr_enable_ecc(unsigned int dram_size)
+{
+#ifndef FIXME
+ uint *p = 0;
+ uint i = 0;
+ volatile immap_t *immap = (immap_t *)CFG_IMMRBAR;
+ volatile ccsr_ddr_t *ddr= &immap->im_ddr;
+
+ dma_init();
+
+ for (*p = 0; p < (uint *)(8 * 1024); p++) {
+ if (((unsigned int)p & 0x1f) == 0) {
+ ppcDcbz((unsigned long) p);
+ }
+ *p = (unsigned int)0xdeadbeef;
+ if (((unsigned int)p & 0x1c) == 0x1c) {
+ ppcDcbf((unsigned long) p);
+ }
+ }
+
+ /* 8K */
+ dma_xfer((uint *)0x2000, 0x2000, (uint *)0);
+ /* 16K */
+ dma_xfer((uint *)0x4000, 0x4000, (uint *)0);
+ /* 32K */
+ dma_xfer((uint *)0x8000, 0x8000, (uint *)0);
+ /* 64K */
+ dma_xfer((uint *)0x10000, 0x10000, (uint *)0);
+ /* 128k */
+ dma_xfer((uint *)0x20000, 0x20000, (uint *)0);
+ /* 256k */
+ dma_xfer((uint *)0x40000, 0x40000, (uint *)0);
+ /* 512k */
+ dma_xfer((uint *)0x80000, 0x80000, (uint *)0);
+ /* 1M */
+ dma_xfer((uint *)0x100000, 0x100000, (uint *)0);
+ /* 2M */
+ dma_xfer((uint *)0x200000, 0x200000, (uint *)0);
+ /* 4M */
+ dma_xfer((uint *)0x400000, 0x400000, (uint *)0);
+
+ for (i = 1; i < dram_size / 0x800000; i++) {
+ dma_xfer((uint *)(0x800000*i), 0x800000, (uint *)0);
+ }
+
+ /*
+ * Enable errors for ECC.
+ */
+ ddr->err_disable = 0x00000000;
+ asm("sync;isync");
+#endif
+}
+
+#endif /* CONFIG_DDR_ECC */
diff --git a/cpu/mpc83xx/speed.c b/cpu/mpc83xx/speed.c
new file mode 100644
index 0000000000..260137da82
--- /dev/null
+++ b/cpu/mpc83xx/speed.c
@@ -0,0 +1,421 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright 2004 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Change log:
+ *
+ * 20050101: Eran Liberty (liberty@freescale.com)
+ * Initial file creating (porting from 85XX & 8260)
+ */
+
+#include <common.h>
+#include <mpc83xx.h>
+#include <asm/processor.h>
+
+/* ----------------------------------------------------------------- */
+
+typedef enum {
+ _unk,
+ _off,
+ _byp,
+ _x8,
+ _x4,
+ _x2,
+ _x1,
+ _1x,
+ _1_5x,
+ _2x,
+ _2_5x,
+ _3x
+} mult_t;
+
+typedef struct {
+ mult_t core_csb_ratio;
+ mult_t vco_divider;
+} corecnf_t;
+
+corecnf_t corecnf_tab[] = {
+ { _byp, _byp}, /* 0x00 */
+ { _byp, _byp}, /* 0x01 */
+ { _byp, _byp}, /* 0x02 */
+ { _byp, _byp}, /* 0x03 */
+ { _byp, _byp}, /* 0x04 */
+ { _byp, _byp}, /* 0x05 */
+ { _byp, _byp}, /* 0x06 */
+ { _byp, _byp}, /* 0x07 */
+ { _1x, _x2}, /* 0x08 */
+ { _1x, _x4}, /* 0x09 */
+ { _1x, _x8}, /* 0x0A */
+ { _1x, _x8}, /* 0x0B */
+ {_1_5x, _x2}, /* 0x0C */
+ {_1_5x, _x4}, /* 0x0D */
+ {_1_5x, _x8}, /* 0x0E */
+ {_1_5x, _x8}, /* 0x0F */
+ { _2x, _x2}, /* 0x10 */
+ { _2x, _x4}, /* 0x11 */
+ { _2x, _x8}, /* 0x12 */
+ { _2x, _x8}, /* 0x13 */
+ {_2_5x, _x2}, /* 0x14 */
+ {_2_5x, _x4}, /* 0x15 */
+ {_2_5x, _x8}, /* 0x16 */
+ {_2_5x, _x8}, /* 0x17 */
+ { _3x, _x2}, /* 0x18 */
+ { _3x, _x4}, /* 0x19 */
+ { _3x, _x8}, /* 0x1A */
+ { _3x, _x8}, /* 0x1B */
+};
+
+/* ----------------------------------------------------------------- */
+
+/*
+ *
+ */
+int get_clocks (void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+ volatile immap_t *im = (immap_t *)CFG_IMMRBAR;
+ u32 pci_sync_in;
+ u8 spmf;
+ u8 clkin_div;
+ u32 sccr;
+ u32 corecnf_tab_index;
+ u8 corepll;
+ u32 lcrr;
+
+ u32 csb_clk;
+ u32 tsec1_clk;
+ u32 tsec2_clk;
+ u32 core_clk;
+ u32 usbmph_clk;
+ u32 usbdr_clk;
+ u32 i2c_clk;
+ u32 enc_clk;
+ u32 lbiu_clk;
+ u32 lclk_clk;
+ u32 ddr_clk;
+
+ if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32)im)
+ return -1;
+
+#ifndef CFG_HRCW_HIGH
+# error "CFG_HRCW_HIGH must be defined in include/configs/MCP83XXADS.h"
+#endif /* CFG_HCWD_HIGH */
+
+#if (CFG_HRCW_HIGH & HRCWH_PCI_HOST)
+# ifndef CONFIG_83XX_CLKIN
+# error "In PCI Host Mode, CONFIG_83XX_CLKIN must be defined in include/configs/MCP83XXADS.h"
+# endif /* CONFIG_83XX_CLKIN */
+# ifdef CONFIG_83XX_PCICLK
+# warning "In PCI Host Mode, CONFIG_83XX_PCICLK in include/configs/MCP83XXADS.h is igonred."
+# endif /* CONFIG_83XX_PCICLK */
+/* PCI Host Mode */
+ if (!(im->reset.rcwh & RCWH_PCIHOST)) {
+ /* though RCWH_PCIHOST is defined in CFG_HRCW_HIGH the im->reset.rcwhr PCI Host Mode is disabled */
+ /* FIXME: findout if there is a way to issue some warning */
+ return -2;
+ }
+ if (im->clk.spmr & SPMR_CKID) {
+ pci_sync_in = CONFIG_83XX_CLKIN / 2; /* PCI Clock is half CONFIG_83XX_CLKIN */
+ }
+ else {
+ pci_sync_in = CONFIG_83XX_CLKIN;
+ }
+#else
+# ifdef CONFIG_83XX_CLKIN
+# warning "In PCI Agent Mode, CONFIG_83XX_CLKIN in include/configs/MCP83XXADS.h is igonred."
+# endif /* CONFIG_83XX_CLKIN */
+# ifndef CONFIG_83XX_PCICLK
+# error "In PCI Agent Mode, CONFIG_83XX_PCICLK must be defined in include/configs/MCP83XXADS.h"
+# endif /* CONFIG_83XX_PCICLK */
+/* PCI Agent Mode */
+ if (im->reset.rcwh & RCWH_PCIHOST) {
+ /* though RCWH_PCIHOST is not defined in CFG_HRCW_HIGH the im->reset.rcwhr PCI Host Mode is enabled */
+ return -3;
+ }
+ pci_sync_in = CONFIG_83XX_PCICLK;
+#endif /* (CFG_HRCW_HIGH | RCWH_PCIHOST) */
+
+ /* we have up to date pci_sync_in */
+ spmf = ((im->reset.rcwl & RCWL_SPMF) >> RCWL_SPMF_SHIFT);
+ clkin_div = ((im->clk.spmr & SPMR_CKID) >> SPMR_CKID_SHIFT);
+
+ if ((im->reset.rcwl & RCWL_LBIUCM) || (im->reset.rcwl & RCWL_DDRCM)) {
+ csb_clk = (pci_sync_in * spmf * (1 + clkin_div)) / 2;
+ }
+ else {
+ csb_clk = pci_sync_in * spmf * (1 + clkin_div);
+ }
+
+ sccr = im->clk.sccr;
+ switch ((sccr & SCCR_TSEC1CM) >> SCCR_TSEC1CM_SHIFT) {
+ case 0:
+ tsec1_clk = 0;
+ break;
+ case 1:
+ tsec1_clk = csb_clk;
+ break;
+ case 2:
+ tsec1_clk = csb_clk / 2;
+ break;
+ case 3:
+ tsec1_clk = csb_clk / 3;
+ break;
+ default:
+ /* unkown SCCR_TSEC1CM value */
+ return -4;
+ }
+
+ switch ((sccr & SCCR_TSEC2CM) >> SCCR_TSEC2CM_SHIFT) {
+ case 0:
+ tsec2_clk = 0;
+ break;
+ case 1:
+ tsec2_clk = csb_clk;
+ break;
+ case 2:
+ tsec2_clk = csb_clk / 2;
+ break;
+ case 3:
+ tsec2_clk = csb_clk / 3;
+ break;
+ default:
+ /* unkown SCCR_TSEC2CM value */
+ return -5;
+ }
+ i2c_clk = tsec2_clk;
+
+ switch ((sccr & SCCR_ENCCM) >> SCCR_ENCCM_SHIFT) {
+ case 0:
+ enc_clk = 0;
+ break;
+ case 1:
+ enc_clk = csb_clk;
+ break;
+ case 2:
+ enc_clk = csb_clk / 2;
+ break;
+ case 3:
+ enc_clk = csb_clk / 3;
+ break;
+ default:
+ /* unkown SCCR_ENCCM value */
+ return -6;
+ }
+
+ switch ((sccr & SCCR_USBMPHCM) >> SCCR_USBMPHCM_SHIFT) {
+ case 0:
+ usbmph_clk = 0;
+ break;
+ case 1:
+ usbmph_clk = csb_clk;
+ break;
+ case 2:
+ usbmph_clk = csb_clk / 2;
+ break;
+ case 3:
+ usbmph_clk = csb_clk / 3;
+ break;
+ default:
+ /* unkown SCCR_USBMPHCM value */
+ return -7;
+ }
+
+ switch ((sccr & SCCR_USBDRCM) >> SCCR_USBDRCM_SHIFT) {
+ case 0:
+ usbdr_clk = 0;
+ break;
+ case 1:
+ usbdr_clk = csb_clk;
+ break;
+ case 2:
+ usbdr_clk = csb_clk / 2;
+ break;
+ case 3:
+ usbdr_clk = csb_clk / 3;
+ break;
+ default:
+ /* unkown SCCR_USBDRCM value */
+ return -8;
+ }
+
+ if (usbmph_clk != 0
+ && usbdr_clk != 0
+ && usbmph_clk != usbdr_clk ) {
+ /* if USB MPH clock is not disabled and USB DR clock is not disabled than USB MPH & USB DR must have the same rate */
+ return -9;
+ }
+
+ lbiu_clk = csb_clk * (1 + ((im->reset.rcwl & RCWL_LBIUCM) >> RCWL_LBIUCM_SHIFT));
+ lcrr = (im->lbus.lcrr & LCRR_CLKDIV) >> LCRR_CLKDIV_SHIFT;
+ switch (lcrr) {
+ case 2:
+ case 4:
+ case 8:
+ lclk_clk = lbiu_clk / lcrr;
+ break;
+ default:
+ /* unknown lcrr */
+ return -10;
+ }
+
+ ddr_clk = csb_clk * (1 + ((im->reset.rcwl & RCWL_DDRCM) >> RCWL_DDRCM_SHIFT));
+
+ corepll = (im->reset.rcwl & RCWL_COREPLL) >> RCWL_COREPLL_SHIFT;
+ corecnf_tab_index = ((corepll & 0x1F) << 2) | ((corepll & 0x60) >> 5);
+ if (corecnf_tab_index > (sizeof(corecnf_tab)/sizeof(corecnf_t)) ) {
+ /* corecnf_tab_index is too high, possibly worng value */
+ return -11;
+ }
+ switch (corecnf_tab[corecnf_tab_index].core_csb_ratio) {
+ case _byp:
+ case _x1:
+ case _1x:
+ core_clk = csb_clk;
+ break;
+ case _1_5x:
+ core_clk = (3 * csb_clk) / 2;
+ break;
+ case _2x:
+ core_clk = 2 * csb_clk;
+ break;
+ case _2_5x:
+ core_clk = ( 5 * csb_clk) / 2;
+ break;
+ case _3x:
+ core_clk = 3 * csb_clk;
+ break;
+ default:
+ /* unkown core to csb ratio */
+ return -12;
+ }
+
+ gd->csb_clk = csb_clk ;
+ gd->tsec1_clk = tsec1_clk ;
+ gd->tsec2_clk = tsec2_clk ;
+ gd->core_clk = core_clk ;
+ gd->usbmph_clk = usbmph_clk;
+ gd->usbdr_clk = usbdr_clk ;
+ gd->i2c_clk = i2c_clk ;
+ gd->enc_clk = enc_clk ;
+ gd->lbiu_clk = lbiu_clk ;
+ gd->lclk_clk = lclk_clk ;
+ gd->ddr_clk = ddr_clk ;
+
+ gd->cpu_clk = gd->core_clk;
+ gd->bus_clk = gd->lbiu_clk;
+ return 0;
+}
+
+/********************************************
+ * get_bus_freq
+ * return system bus freq in Hz
+ *********************************************/
+ulong get_bus_freq (ulong dummy)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+ return gd->csb_clk;
+}
+
+int print_clock_conf (void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ printf("Clock configuration:\n");
+ printf(" Coherent System Bus: %4d MHz\n",gd->csb_clk/1000000);
+ printf(" Core: %4d MHz\n",gd->core_clk/1000000);
+ printf(" Local Bus Controller:%4d MHz\n",gd->lbiu_clk/1000000);
+ printf(" Local Bus: %4d MHz\n",gd->lclk_clk/1000000);
+ printf(" DDR: %4d MHz\n",gd->ddr_clk/1000000);
+ printf(" I2C: %4d MHz\n",gd->i2c_clk/1000000);
+ printf(" TSEC1: %4d MHz\n",gd->tsec1_clk/1000000);
+ printf(" TSEC2: %4d MHz\n",gd->tsec2_clk/1000000);
+ printf(" USB MPH: %4d MHz\n",gd->usbmph_clk/1000000);
+ printf(" USB DR: %4d MHz\n",gd->usbdr_clk/1000000);
+
+#if 0
+ DECLARE_GLOBAL_DATA_PTR;
+
+ volatile immap_t *immap = (immap_t *) CFG_IMMR;
+ ulong sccr, dfbrg;
+ ulong scmr, corecnf, busdf, cpmdf, plldf, pllmf;
+ corecnf_t *cp;
+
+ sccr = immap->im_clkrst.car_sccr;
+ dfbrg = (sccr & SCCR_DFBRG_MSK) >> SCCR_DFBRG_SHIFT;
+
+ scmr = immap->im_clkrst.car_scmr;
+ corecnf = (scmr & SCMR_CORECNF_MSK) >> SCMR_CORECNF_SHIFT;
+ busdf = (scmr & SCMR_BUSDF_MSK) >> SCMR_BUSDF_SHIFT;
+ cpmdf = (scmr & SCMR_CPMDF_MSK) >> SCMR_CPMDF_SHIFT;
+ plldf = (scmr & SCMR_PLLDF) ? 1 : 0;
+ pllmf = (scmr & SCMR_PLLMF_MSK) >> SCMR_PLLMF_SHIFT;
+
+ cp = &corecnf_tab[corecnf];
+
+ puts (CPU_ID_STR " Clock Configuration\n - Bus-to-Core Mult ");
+
+ switch (cp->b2c_mult) {
+ case _byp:
+ puts ("BYPASS");
+ break;
+
+ case _off:
+ puts ("OFF");
+ break;
+
+ case _unk:
+ puts ("UNKNOWN");
+ break;
+
+ default:
+ printf ("%d%sx",
+ cp->b2c_mult / 2,
+ (cp->b2c_mult % 2) ? ".5" : "");
+ break;
+ }
+
+ printf (", VCO Div %d, 60x Bus Freq %s, Core Freq %s\n",
+ cp->vco_div, cp->freq_60x, cp->freq_core);
+
+ printf (" - dfbrg %ld, corecnf 0x%02lx, busdf %ld, cpmdf %ld, "
+ "plldf %ld, pllmf %ld\n", dfbrg, corecnf, busdf, cpmdf, plldf,
+ pllmf);
+
+ printf (" - vco_out %10ld, scc_clk %10ld, brg_clk %10ld\n",
+ gd->vco_out, gd->scc_clk, gd->brg_clk);
+
+ printf (" - cpu_clk %10ld, cpm_clk %10ld, bus_clk %10ld\n",
+ gd->cpu_clk, gd->cpm_clk, gd->bus_clk);
+
+ if (sccr & SCCR_PCI_MODE) {
+ uint pci_div;
+
+ pci_div = ( (sccr & SCCR_PCI_MODCK) ? 2 : 1) *
+ ( ( (sccr & SCCR_PCIDF_MSK) >> SCCR_PCIDF_SHIFT) + 1);
+
+ printf (" - pci_clk %10ld\n", (gd->cpm_clk * 2) / pci_div);
+ }
+ putc ('\n');
+#endif
+ return 0;
+}
diff --git a/cpu/mpc83xx/start.S b/cpu/mpc83xx/start.S
new file mode 100644
index 0000000000..fb001a654c
--- /dev/null
+++ b/cpu/mpc83xx/start.S
@@ -0,0 +1,1093 @@
+/*
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ * Copyright (C) 2000, 2001,2002 Wolfgang Denk <wd@denx.de>
+ * Copyright 2004 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * U-Boot - Startup Code for MPC83xx PowerPC based Embedded Boards
+ */
+
+#include <config.h>
+#include <mpc83xx.h>
+#include <version.h>
+
+#define CONFIG_83XX 1 /* needed for Linux kernel header files*/
+#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#ifndef CONFIG_IDENT_STRING
+#define CONFIG_IDENT_STRING "MPC83XX"
+#endif
+
+/* We don't want the MMU yet.
+ */
+#undef MSR_KERNEL
+
+/*
+ * Floating Point enable, Machine Check and Recoverable Interr.
+ */
+#ifdef DEBUG
+#define MSR_KERNEL (MSR_FP|MSR_RI)
+#else
+#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
+#endif
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r14 to access the GOT
+ */
+ START_GOT
+ GOT_ENTRY(_GOT2_TABLE_)
+ GOT_ENTRY(_FIXUP_TABLE_)
+
+ GOT_ENTRY(_start)
+ GOT_ENTRY(_start_of_vectors)
+ GOT_ENTRY(_end_of_vectors)
+ GOT_ENTRY(transfer_to_handler)
+
+ GOT_ENTRY(__init_end)
+ GOT_ENTRY(_end)
+ GOT_ENTRY(__bss_start)
+ END_GOT
+
+/*
+ * Version string - must be in data segment because MPC83xx uses the
+ * first 256 bytes for the Hard Reset Configuration Word table (see
+ * below). Similarly, can't have the U-Boot Magic Number as the first
+ * thing in the image - don't know how this will affect the image tools,
+ * but I guess I'll find out soon.
+ */
+ .data
+ .globl version_string
+version_string:
+ .ascii U_BOOT_VERSION
+ .ascii " (", __DATE__, " - ", __TIME__, ")"
+ .ascii " ", CONFIG_IDENT_STRING, "\0"
+
+ .text
+#define _HRCW_TABLE_ENTRY(w) \
+ .fill 8,1,(((w)>>24)&0xff); \
+ .fill 8,1,(((w)>>16)&0xff); \
+ .fill 8,1,(((w)>> 8)&0xff); \
+ .fill 8,1,(((w) )&0xff)
+
+ _HRCW_TABLE_ENTRY(CFG_HRCW_LOW)
+ _HRCW_TABLE_ENTRY(CFG_HRCW_HIGH)
+
+
+#ifndef CONFIG_DEFAULT_IMMR
+#error CONFIG_DEFAULT_IMMR must be defined
+#endif /* CFG_DEFAULT_IMMR */
+#ifndef CFG_IMMRBAR
+#define CFG_IMMRBAR CONFIG_DEFAULT_IMMR
+#endif /* CFG_IMMRBAR */
+
+/*
+ * After configuration, a system reset exception is executed using the
+ * vector at offset 0x100 relative to the base set by MSR[IP]. If
+ * MSR[IP] is 0, the base address is 0x00000000. If MSR[IP] is 1, the
+ * base address is 0xfff00000. In the case of a Power On Reset or Hard
+ * Reset, the value of MSR[IP] is determined by the CIP field in the
+ * HRCW.
+ *
+ * Other bits in the HRCW set up the Base Address and Port Size in BR0.
+ * This determines the location of the boot ROM (flash or EPROM) in the
+ * processor's address space at boot time. As long as the HRCW is set up
+ * so that we eventually end up executing the code below when the
+ * processor executes the reset exception, the actual values used should
+ * not matter.
+ *
+ * Once we have got here, the address mask in OR0 is cleared so that the
+ * bottom 32K of the boot ROM is effectively repeated all throughout the
+ * processor's address space, after which we can jump to the absolute
+ * address at which the boot ROM was linked at compile time, and proceed
+ * to initialise the memory controller without worrying if the rug will
+ * be pulled out from under us, so to speak (it will be fine as long as
+ * we configure BR0 with the same boot ROM link address).
+ */
+ . = EXC_OFF_SYS_RESET
+
+ .globl _start
+_start: /* time t 0 */
+ li r21, BOOTFLAG_COLD /* Normal Power-On: Boot from FLASH*/
+ nop
+ b boot_cold
+
+ . = EXC_OFF_SYS_RESET + 0x10
+
+ .globl _start_warm
+_start_warm:
+ li r21, BOOTFLAG_WARM /* Software reboot */
+ b boot_warm
+
+
+boot_cold: /* time t 3 */
+ lis r4, CONFIG_DEFAULT_IMMR@h
+ nop
+boot_warm: /* time t 5 */
+ mfmsr r5 /* save msr contents */
+ lis r3, CFG_IMMRBAR@h
+ ori r3, r3, CFG_IMMRBAR@l
+ stw r3, IMMRBAR(r4)
+
+ /* Initialise the E300 processor core */
+ /*------------------------------------------*/
+
+ bl init_e300_core
+
+#ifndef CFG_RAMBOOT
+
+ /* Inflate flash location so it appears everywhere, calculate */
+ /* the absolute address in final location of the FLASH, jump */
+ /* there and deflate the flash size back to minimal size */
+ /*------------------------------------------------------------*/
+ bl map_flash_by_law1
+ lis r4, (CFG_MONITOR_BASE)@h
+ ori r4, r4, (CFG_MONITOR_BASE)@l
+ addi r5, r4, in_flash - _start + EXC_OFF_SYS_RESET
+ mtlr r5
+ blr
+in_flash:
+#if 1 /* Remapping flash with LAW0. */
+ bl remap_flash_by_law0
+#endif
+#endif /* CFG_RAMBOOT */
+
+ bl setup_stack_in_data_cache_on_r1
+
+ /* let the C-code set up the rest */
+ /* */
+ /* Be careful to keep code relocatable & stack humble */
+ /*------------------------------------------------------*/
+
+ GET_GOT /* initialize GOT access */
+
+ /* r3: IMMR */
+ lis r3, CFG_IMMRBAR@h
+ /* run low-level CPU init code (in Flash)*/
+ bl cpu_init_f
+
+ /* r3: BOOTFLAG */
+ mr r3, r21
+ /* run 1st part of board init code (in Flash)*/
+ bl board_init_f
+
+/*
+ * Vector Table
+ */
+
+ .globl _start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+ STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. */
+ STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. */
+ STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+#ifndef FIXME
+ STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
+#endif
+
+/* Alignment exception. */
+ . = 0x600
+Alignment:
+ EXCEPTION_PROLOG
+ mfspr r4,DAR
+ stw r4,_DAR(r21)
+ mfspr r5,DSISR
+ stw r5,_DSISR(r21)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r20,MSR_KERNEL
+ rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
+ rlwimi r20,r23,0,25,25 /* copy IP bit from saved MSR */
+ lwz r6,GOT(transfer_to_handler)
+ mtlr r6
+ blrl
+.L_Alignment:
+ .long AlignmentException - _start + EXC_OFF_SYS_RESET
+ .long int_return - _start + EXC_OFF_SYS_RESET
+
+/* Program check exception */
+ . = 0x700
+ProgramCheck:
+ EXCEPTION_PROLOG
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r20,MSR_KERNEL
+ rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
+ rlwimi r20,r23,0,25,25 /* copy IP bit from saved MSR */
+ lwz r6,GOT(transfer_to_handler)
+ mtlr r6
+ blrl
+.L_ProgramCheck:
+ .long ProgramCheckException - _start + EXC_OFF_SYS_RESET
+ .long int_return - _start + EXC_OFF_SYS_RESET
+
+ STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+ /* I guess we could implement decrementer, and may have
+ * to someday for timekeeping.
+ */
+ STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+
+ STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+ STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+ STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+ STD_EXCEPTION(0xd00, SingleStep, UnknownException)
+
+ STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+ STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+
+ STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
+#ifdef DEBUG
+ . = 0x1300
+ /*
+ * This exception occurs when the program counter matches the
+ * Instruction Address Breakpoint Register (IABR).
+ *
+ * I want the cpu to halt if this occurs so I can hunt around
+ * with the debugger and look at things.
+ *
+ * When DEBUG is defined, both machine check enable (in the MSR)
+ * and checkstop reset enable (in the reset mode register) are
+ * turned off and so a checkstop condition will result in the cpu
+ * halting.
+ *
+ * I force the cpu into a checkstop condition by putting an illegal
+ * instruction here (at least this is the theory).
+ *
+ * well - that didnt work, so just do an infinite loop!
+ */
+1: b 1b
+#else
+ STD_EXCEPTION(0x1300, InstructionBreakpoint, DebugException)
+#endif
+ STD_EXCEPTION(0x1400, SMI, UnknownException)
+
+ STD_EXCEPTION(0x1500, Trap_15, UnknownException)
+ STD_EXCEPTION(0x1600, Trap_16, UnknownException)
+ STD_EXCEPTION(0x1700, Trap_17, UnknownException)
+ STD_EXCEPTION(0x1800, Trap_18, UnknownException)
+ STD_EXCEPTION(0x1900, Trap_19, UnknownException)
+ STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
+ STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
+ STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
+ STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
+ STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
+ STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
+ STD_EXCEPTION(0x2000, Trap_20, UnknownException)
+ STD_EXCEPTION(0x2100, Trap_21, UnknownException)
+ STD_EXCEPTION(0x2200, Trap_22, UnknownException)
+ STD_EXCEPTION(0x2300, Trap_23, UnknownException)
+ STD_EXCEPTION(0x2400, Trap_24, UnknownException)
+ STD_EXCEPTION(0x2500, Trap_25, UnknownException)
+ STD_EXCEPTION(0x2600, Trap_26, UnknownException)
+ STD_EXCEPTION(0x2700, Trap_27, UnknownException)
+ STD_EXCEPTION(0x2800, Trap_28, UnknownException)
+ STD_EXCEPTION(0x2900, Trap_29, UnknownException)
+ STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
+ STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
+ STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
+ STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
+ STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
+ STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
+
+
+ .globl _end_of_vectors
+_end_of_vectors:
+
+ . = 0x3000
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+ .globl transfer_to_handler
+transfer_to_handler:
+ stw r22,_NIP(r21)
+ lis r22,MSR_POW@h
+ andc r23,r23,r22
+ stw r23,_MSR(r21)
+ SAVE_GPR(7, r21)
+ SAVE_4GPRS(8, r21)
+ SAVE_8GPRS(12, r21)
+ SAVE_8GPRS(24, r21)
+ mflr r23
+ andi. r24,r23,0x3f00 /* get vector offset */
+ stw r24,TRAP(r21)
+ li r22,0
+ stw r22,RESULT(r21)
+ lwz r24,0(r23) /* virtual address of handler */
+ lwz r23,4(r23) /* where to go when done */
+ mtspr SRR0,r24
+ mtspr SRR1,r20
+ mtlr r23
+ SYNC
+ rfi /* jump to handler, enable MMU */
+
+int_return:
+ mfmsr r28 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r28,r28,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r28
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SRR0,r2
+ mtspr SRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfi
+
+/*
+ * This code initialises the E300 processor core
+ * (conforms to PowerPC 603e spec)
+ * Note: expects original MSR contents to be in r5.
+ */
+ .globl init_e300_core
+init_e300_core: /* time t 10 */
+ /* Initialize machine status; enable machine check interrupt */
+ /*-----------------------------------------------------------*/
+
+ li r3, MSR_KERNEL /* Set ME and RI flags */
+ rlwimi r3, r5, 0, 25, 25 /* preserve IP bit set by HRCW */
+#ifdef DEBUG
+ rlwimi r3, r5, 0, 21, 22 /* debugger might set SE & BE bits */
+#endif
+ SYNC /* Some chip revs need this... */
+ mtmsr r3
+ SYNC
+ mtspr SRR1, r3 /* Make SRR1 match MSR */
+
+
+ lis r3, CFG_IMMRBAR@h
+#if defined(CONFIG_WATCHDOG)
+ /* Initialise the Wathcdog values and reset it (if req) */
+ /*------------------------------------------------------*/
+ lis r4, CFG_WATCHDOG_VALUE
+ ori r4, r4, (SWCRR_SWEN | SWCRR_SWRI | SWCRR_SWPR)
+ stw r4, SWCRR(r3)
+
+ /* and reset it */
+
+ li r4, 0x556C
+ sth r4, SWSRR@l(r3)
+ li r4, 0xAA39
+ sth r4, SWSRR@l(r3)
+#else
+ /* Disable Wathcdog */
+ /*-------------------*/
+ xor r4, r4, r4
+ stw r4, SWCRR(r3)
+#endif /* CONFIG_WATCHDOG */
+
+ /* Initialize the Hardware Implementation-dependent Registers */
+ /* HID0 also contains cache control */
+ /*------------------------------------------------------*/
+
+ lis r3, CFG_HID0_INIT@h
+ ori r3, r3, CFG_HID0_INIT@l
+ SYNC
+ mtspr HID0, r3
+
+ lis r3, CFG_HID0_FINAL@h
+ ori r3, r3, CFG_HID0_FINAL@l
+ SYNC
+ mtspr HID0, r3
+
+ lis r3, CFG_HID2@h
+ ori r3, r3, CFG_HID2@l
+ SYNC
+ mtspr HID2, r3
+
+ /* clear all BAT's */
+ /*----------------------------------*/
+
+ xor r0, r0, r0
+ mtspr DBAT0U, r0
+ mtspr DBAT0L, r0
+ mtspr DBAT1U, r0
+ mtspr DBAT1L, r0
+ mtspr DBAT2U, r0
+ mtspr DBAT2L, r0
+ mtspr DBAT3U, r0
+ mtspr DBAT3L, r0
+ mtspr IBAT0U, r0
+ mtspr IBAT0L, r0
+ mtspr IBAT1U, r0
+ mtspr IBAT1L, r0
+ mtspr IBAT2U, r0
+ mtspr IBAT2L, r0
+ mtspr IBAT3U, r0
+ mtspr IBAT3L, r0
+ SYNC
+
+ /* invalidate all tlb's
+ *
+ * From the 603e User Manual: "The 603e provides the ability to
+ * invalidate a TLB entry. The TLB Invalidate Entry (tlbie)
+ * instruction invalidates the TLB entry indexed by the EA, and
+ * operates on both the instruction and data TLBs simultaneously
+ * invalidating four TLB entries (both sets in each TLB). The
+ * index corresponds to bits 15-19 of the EA. To invalidate all
+ * entries within both TLBs, 32 tlbie instructions should be
+ * issued, incrementing this field by one each time."
+ *
+ * "Note that the tlbia instruction is not implemented on the
+ * 603e."
+ *
+ * bits 15-19 correspond to addresses 0x00000000 to 0x0001F000
+ * incrementing by 0x1000 each time. The code below is sort of
+ * based on code in "flush_tlbs" from arch/ppc/kernel/head.S
+ *
+ */
+
+ li r3, 32
+ mtctr r3
+ li r3, 0
+1: tlbie r3
+ addi r3, r3, 0x1000
+ bdnz 1b
+ SYNC
+
+ /* Done! */
+ /*------------------------------*/
+ blr
+
+/* Cache functions.
+ *
+ * Note: requires that all cache bits in
+ * HID0 are in the low half word.
+ */
+ .globl icache_enable
+icache_enable:
+ mfspr r3, HID0
+ ori r3, r3, HID0_ICE
+ lis r4, 0
+ ori r4, r4, HID0_ILOCK
+ andc r3, r3, r4
+ ori r4, r3, HID0_ICFI
+ isync
+ mtspr HID0, r4 /* sets enable and invalidate, clears lock */
+ isync
+ mtspr HID0, r3 /* clears invalidate */
+ blr
+
+ .globl icache_disable
+icache_disable:
+ mfspr r3, HID0
+ lis r4, 0
+ ori r4, r4, HID0_ICE|HID0_ILOCK
+ andc r3, r3, r4
+ ori r4, r3, HID0_ICFI
+ isync
+ mtspr HID0, r4 /* sets invalidate, clears enable and lock*/
+ isync
+ mtspr HID0, r3 /* clears invalidate */
+ blr
+
+ .globl icache_status
+icache_status:
+ mfspr r3, HID0
+ rlwinm r3, r3, HID0_ICE_SHIFT, 31, 31
+ blr
+
+ .globl dcache_enable
+dcache_enable:
+ mfspr r3, HID0
+ ori r3, r3, HID0_ENABLE_DATA_CACHE
+ lis r4, 0
+ ori r4, r4, HID0_LOCK_DATA_CACHE
+ andc r3, r3, r4
+ ori r4, r3, HID0_LOCK_INSTRUCTION_CACHE
+ sync
+ mtspr HID0, r4 /* sets enable and invalidate, clears lock */
+ sync
+ mtspr HID0, r3 /* clears invalidate */
+ blr
+
+ .globl dcache_disable
+dcache_disable:
+ mfspr r3, HID0
+ lis r4, 0
+ ori r4, r4, HID0_ENABLE_DATA_CACHE|HID0_LOCK_DATA_CACHE
+ andc r3, r3, r4
+ ori r4, r3, HID0_INVALIDATE_DATA_CACHE
+ sync
+ mtspr HID0, r4 /* sets invalidate, clears enable and lock */
+ sync
+ mtspr HID0, r3 /* clears invalidate */
+ blr
+
+ .globl dcache_status
+dcache_status:
+ mfspr r3, HID0
+ rlwinm r3, r3, HID0_DCE_SHIFT, 31, 31
+ blr
+
+ .globl get_pvr
+get_pvr:
+ mfspr r3, PVR
+ blr
+
+/*-------------------------------------------------------------------*/
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+ .globl relocate_code
+relocate_code:
+ mr r1, r3 /* Set new stack pointer */
+ mr r9, r4 /* Save copy of Global Data pointer */
+ mr r10, r5 /* Save copy of Destination Address */
+
+ mr r3, r5 /* Destination Address */
+ lis r4, CFG_MONITOR_BASE@h /* Source Address */
+ ori r4, r4, CFG_MONITOR_BASE@l
+ lwz r5, GOT(__init_end)
+ sub r5, r5, r4
+ li r6, CFG_CACHELINE_SIZE /* Cache Line Size */
+
+ /*
+ * Fix GOT pointer:
+ *
+ * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE)
+ * + Destination Address
+ *
+ * Offset:
+ */
+ sub r15, r10, r4
+
+ /* First our own GOT */
+ add r14, r14, r15
+ /* then the one used by the C code */
+ add r30, r30, r15
+
+ /*
+ * Now relocate code
+ */
+
+ cmplw cr1,r3,r4
+ addi r0,r5,3
+ srwi. r0,r0,2
+ beq cr1,4f /* In place copy is not necessary */
+ beq 7f /* Protect against 0 count */
+ mtctr r0
+ bge cr1,2f
+ la r8,-4(r4)
+ la r7,-4(r3)
+
+ /* copy */
+1: lwzu r0,4(r8)
+ stwu r0,4(r7)
+ bdnz 1b
+
+ addi r0,r5,3
+ srwi. r0,r0,2
+ mtctr r0
+ la r8,-4(r4)
+ la r7,-4(r3)
+
+ /* and compare */
+20: lwzu r20,4(r8)
+ lwzu r21,4(r7)
+ xor. r22, r20, r21
+ bne 30f
+ bdnz 20b
+ b 4f
+
+ /* compare failed */
+30: li r3, 0
+ blr
+
+2: slwi r0,r0,2 /* re copy in reverse order ... y do we needed it? */
+ add r8,r4,r0
+ add r7,r3,r0
+3: lwzu r0,-4(r8)
+ stwu r0,-4(r7)
+ bdnz 3b
+
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4:
+ bl un_setup_stack_in_data_cache
+ mr r7, r3
+ mr r8, r4
+ bl dcache_disable
+ mr r3, r7
+ mr r4, r8
+
+ cmpwi r6,0
+ add r5,r3,r5
+ beq 7f /* Always flush prefetch queue in any case */
+ subi r0,r6,1
+ andc r3,r3,r0
+ mfspr r7,HID0 /* don't do dcbst if dcache is disabled*/
+ rlwinm r7,r7,HID0_DCE_SHIFT,31,31
+ cmpwi r7,0
+ beq 9f
+ mr r4,r3
+5: dcbst 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 5b
+ sync /* Wait for all dcbst to complete on bus */
+9: mfspr r7,HID0 /* don't do icbi if icache is disabled */
+ rlwinm r7,r7,HID0_DCE_SHIFT,31,31
+ cmpwi r7,0
+ beq 7f
+ mr r4,r3
+6: icbi 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 6b
+7: sync /* Wait for all icbi to complete on bus */
+ isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+
+ addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+ mtlr r0
+ blr
+
+in_ram:
+
+ /*
+ * Relocation Function, r14 point to got2+0x8000
+ *
+ * Adjust got2 pointers, no need to check for 0, this code
+ * already puts a few entries in the table.
+ */
+ li r0,__got2_entries@sectoff@l
+ la r3,GOT(_GOT2_TABLE_)
+ lwz r11,GOT(_GOT2_TABLE_)
+ mtctr r0
+ sub r11,r3,r11
+ addi r3,r3,-4
+1: lwzu r0,4(r3)
+ add r0,r0,r11
+ stw r0,0(r3)
+ bdnz 1b
+
+ /*
+ * Now adjust the fixups and the pointers to the fixups
+ * in case we need to move ourselves again.
+ */
+2: li r0,__fixup_entries@sectoff@l
+ lwz r3,GOT(_FIXUP_TABLE_)
+ cmpwi r0,0
+ mtctr r0
+ addi r3,r3,-4
+ beq 4f
+3: lwzu r4,4(r3)
+ lwzux r0,r4,r11
+ add r0,r0,r11
+ stw r10,0(r3)
+ stw r0,0(r4)
+ bdnz 3b
+4:
+clear_bss:
+ /*
+ * Now clear BSS segment
+ */
+ lwz r3,GOT(__bss_start)
+#if defined(CONFIG_HYMOD)
+ /*
+ * For HYMOD - the environment is the very last item in flash.
+ * The real .bss stops just before environment starts, so only
+ * clear up to that point.
+ *
+ * taken from mods for FADS board
+ */
+ lwz r4,GOT(environment)
+#else
+ lwz r4,GOT(_end)
+#endif
+
+ cmplw 0, r3, r4
+ beq 6f
+
+ li r0, 0
+5:
+ stw r0, 0(r3)
+ addi r3, r3, 4
+ cmplw 0, r3, r4
+ bne 5b
+6:
+
+ mr r3, r9 /* Global Data pointer */
+ mr r4, r10 /* Destination Address */
+ bl board_init_r
+
+ /*
+ * Copy exception vector code to low memory
+ *
+ * r3: dest_addr
+ * r7: source address, r8: end address, r9: target address
+ */
+ .globl trap_init
+trap_init:
+ lwz r7, GOT(_start)
+ lwz r8, GOT(_end_of_vectors)
+
+ li r9, 0x100 /* reset vector always at 0x100 */
+
+ cmplw 0, r7, r8
+ bgelr /* return if r7>=r8 - just in case */
+
+ mflr r4 /* save link register */
+1:
+ lwz r0, 0(r7)
+ stw r0, 0(r9)
+ addi r7, r7, 4
+ addi r9, r9, 4
+ cmplw 0, r7, r8
+ bne 1b
+
+ /*
+ * relocate `hdlr' and `int_return' entries
+ */
+ li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+ li r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 2b
+
+ li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+ li r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 3b
+
+ li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
+ li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 4b
+
+ mfmsr r3 /* now that the vectors have */
+ lis r7, MSR_IP@h /* relocated into low memory */
+ ori r7, r7, MSR_IP@l /* MSR[IP] can be turned off */
+ andc r3, r3, r7 /* (if it was on) */
+ SYNC /* Some chip revs need this... */
+ mtmsr r3
+ SYNC
+
+ mtlr r4 /* restore link register */
+ blr
+
+ /*
+ * Function: relocate entries for one exception vector
+ */
+trap_reloc:
+ lwz r0, 0(r7) /* hdlr ... */
+ add r0, r0, r3 /* ... += dest_addr */
+ stw r0, 0(r7)
+
+ lwz r0, 4(r7) /* int_return ... */
+ add r0, r0, r3 /* ... += dest_addr */
+ stw r0, 4(r7)
+
+ blr
+
+#ifdef CFG_INIT_RAM_LOCK
+.globl unlock_ram_in_cache
+unlock_ram_in_cache:
+ /* invalidate the INIT_RAM section */
+ lis r3, (CFG_INIT_RAM_ADDR & ~31)@h
+ ori r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
+ li r2,512
+ mtctr r2
+1: icbi r0, r3
+ dcbi r0, r3
+ addi r3, r3, 32
+ bdnz 1b
+ sync /* Wait for all icbi to complete on bus */
+ isync
+ blr
+#endif
+
+map_flash_by_law1:
+ /* When booting from ROM (Flash or EPROM), clear the */
+ /* Address Mask in OR0 so ROM appears everywhere */
+ /*----------------------------------------------------*/
+ lis r3, (CFG_IMMRBAR)@h /* r3 <= CFG_IMMRBAR */
+ lwz r4, OR0@l(r3)
+ li r5, 0x7fff /* r5 <= 0x00007FFFF */
+ and r4, r4, r5
+ stw r4, OR0@l(r3) /* OR0 <= OR0 & 0x00007FFFF */
+
+ /* As MPC8349E User's Manual presented, when RCW[BMS] is set to 0,
+ * system will boot from 0x0000_0100, and the LBLAWBAR0[BASE_ADDR]
+ * reset value is 0x00000; when RCW[BMS] is set to 1, system will boot
+ * from 0xFFF0_0100, and the LBLAWBAR0[BASE_ADDR] reset value is
+ * 0xFF800. From the hard resetting to here, the processor fetched and
+ * executed the instructions one by one. There is not absolutely
+ * jumping happened. Laterly, the u-boot code has to do an absolutely
+ * jumping to tell the CPU instruction fetching component what the
+ * u-boot TEXT base address is. Because the TEXT base resides in the
+ * boot ROM memory space, to garantee the code can run smoothly after
+ * that jumping, we must map in the entire boot ROM by Local Access
+ * Window. Sometimes, we desire an non-0x00000 or non-0xFF800 starting
+ * address for boot ROM, such as 0xFE000000. In this case, the default
+ * LBIU Local Access Widow 0 will not cover this memory space. So, we
+ * need another window to map in it.
+ */
+ lis r4, (CFG_FLASH_BASE)@h
+ ori r4, r4, (CFG_FLASH_BASE)@l
+ stw r4, LBLAWBAR1(r3) /* LBLAWBAR1 <= CFG_FLASH_BASE */
+ lis r4, (0x80000016)@h
+ ori r4, r4, (0x80000016)@l
+ stw r4, LBLAWAR1(r3) /* LBLAWAR1 <= 8MB Flash Size */
+ blr
+
+ /* Though all the LBIU Local Access Windows and LBC Banks will be
+ * initialized in the C code, we'd better configure boot ROM's
+ * window 0 and bank 0 correctly at here.
+ */
+remap_flash_by_law0:
+ /* Initialize the BR0 with the boot ROM starting address. */
+ lwz r4, BR0(r3)
+ li r5, 0x7FFF
+ and r4, r4, r5
+ lis r5, (CFG_FLASH_BASE & 0xFFFF8000)@h
+ ori r5, r5, (CFG_FLASH_BASE & 0xFFFF8000)@l
+ or r5, r5, r4
+ stw r5, BR0(r3) /* r5 <= (CFG_FLASH_BASE & 0xFFFF8000) | (BR0 & 0x00007FFF) */
+
+ lwz r4, OR0(r3)
+ lis r5, 0xFF80 /* 8M */
+ or r4, r4, r5
+ stw r4, OR0(r3) /* OR0 <= OR0 | 0xFF800000 */
+
+ lis r4, (CFG_FLASH_BASE)@h
+ ori r4, r4, (CFG_FLASH_BASE)@l
+ stw r4, LBLAWBAR0(r3) /* LBLAWBAR0 <= CFG_FLASH_BASE */
+
+ lis r4, (0x80000016)@h
+ ori r4, r4, (0x80000016)@l
+ stw r4, LBLAWAR0(r3) /* LBLAWAR0 <= 8MB Flash Size */
+
+ xor r4, r4, r4
+ stw r4, LBLAWBAR1(r3)
+ stw r4, LBLAWAR1(r3) /* Off LBIU LAW1 */
+ blr
+
+setup_stack_in_data_cache_on_r1:
+ lis r3, (CFG_IMMRBAR)@h
+
+ /* setup D-BAT for the D-Cache (with out real memory backup) */
+
+ lis r4, (CFG_INIT_RAM_ADDR & 0xFFFE0000)@h
+ mtspr DBAT0U, r4
+ ori r4, r4, 0x0002
+ mtspr DBAT0L, r4
+ isync
+
+#if 0
+ /* Enable MMU */
+ mfmsr r4
+ ori r4, r4, (MSR_DR | MSR_IR)@l
+ mtmsr r4
+#endif
+
+ /* Enable and invalidate data cache. */
+ mfspr r4, HID0
+ mr r5, r4
+ ori r4, r4, HID0_DCE | HID0_DCI
+ ori r5, r5, HID0_DCE
+ sync
+ mtspr HID0, r4
+ mtspr HID0, r5
+ sync
+
+ /* Allocate Initial RAM in data cache.*/
+ li r0, 0
+ lis r4, (CFG_INIT_RAM_ADDR)@h
+ ori r4, r4, (CFG_INIT_RAM_ADDR)@l
+ li r5, 128*8 /* 128*8*32=32Kb */
+ mtctr r5
+1:
+ dcbz r0, r4
+ addi r4, r4, 32
+ bdnz 1b
+ isync
+
+ /* Lock all the D-cache, basically leaving the reset of the program without dcache */
+ mfspr r4, HID0
+ ori r4, r4, (HID0_DLOCK)@l
+ sync
+ mtspr HID0 , r4
+
+ /* setup the stack pointer in r1 */
+ lis r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@h
+ ori r1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@l
+ li r0, 0 /* Make room for stack frame header and */
+
+ stwu r0, -4(r1) /* clear final stack frame so that */
+ stwu r0, -4(r1) /* stack backtraces terminate cleanly */
+
+ blr
+
+un_setup_stack_in_data_cache:
+ blr
+ mr r14, r4
+ mr r15, r5
+
+
+ lis r4, (CFG_INIT_RAM_ADDR & 0xFFFE0000)@h
+ mtspr DBAT0U, r4
+ ori r4, r4, 0x0002
+ mtspr DBAT0L, r4
+ isync
+
+ /* un lock all the D-cache */
+ mfspr r4, HID0
+ lis r5, (~(HID0_DLOCK))@h
+ ori r5, r5, (~(HID0_DLOCK))@l
+ and r4, r4, r5
+ sync
+ mtspr HID0 , r4
+
+ /* Re - Allocate Initial RAM in data cache.*/
+ li r0, 0
+ lis r4, (CFG_INIT_RAM_ADDR)@h
+ ori r4, r4, (CFG_INIT_RAM_ADDR)@l
+ li r5, 128*8 /* 128*8*32=32Kb */
+ mtctr r5
+1:
+ dcbz r0, r4
+ addi r4, r4, 32
+ bdnz 1b
+ isync
+
+ mflr r16
+ bl dcache_disable
+ mtlr r16
+
+ blr
+
+#if 0
+#define GREEN_LIGHT 0x2B0D4046
+#define RED_LIGHT 0x250D4046
+#define LIB_CNT 0x4FFF
+
+/*
+ * Lib Light
+ */
+
+ .globl liblight
+liblight:
+ lis r3, CFG_IMMRBAR@h
+ ori r3, r3, CFG_IMMRBAR@l
+ li r4, 0x3002
+ mtmsr r4
+ xor r4, r4, r4
+ mtspr HID0, r4
+ mtspr HID2, r4
+ lis r4, 0xF8000000@h
+ ori r4, r4, 0xF8000000@l
+ stw r4, LBLAWBAR1(r3)
+ lis r4, 0x8000000E@h
+ ori r4, r4, 0x8000000E@l
+ stw r4, LBLAWAR1(r3)
+ lis r4, 0xF8000801@h
+ ori r4, r4, 0xF8000801@l
+ stw r4, BR1(r3)
+ lis r4, 0xFFFFE8f0@h
+ ori r4, r4, 0xFFFFE8f0@l
+ stw r4, OR1(r3)
+
+ lis r4, 0xF8000000@h
+ ori r4, r4, 0xF8000000@l
+ lis r5, GREEN_LIGHT@h
+ ori r5, r5, GREEN_LIGHT@l
+ lis r6, RED_LIGHT@h
+ ori r6, r6, RED_LIGHT@l
+ lis r7, LIB_CNT@h
+ ori r7, r7, LIB_CNT@l
+
+1:
+ stw r5, 0(r4)
+ mtctr r7
+2: bdnz 2b
+ stw r6, 0(r4)
+ mtctr r7
+3: bdnz 3b
+ b 1b
+
+#endif
diff --git a/cpu/mpc83xx/traps.c b/cpu/mpc83xx/traps.c
new file mode 100644
index 0000000000..c7a56386e8
--- /dev/null
+++ b/cpu/mpc83xx/traps.c
@@ -0,0 +1,274 @@
+/*
+ * linux/arch/ppc/kernel/traps.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Change log:
+ *
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 20050101: Eran Liberty (liberty@freescale.com)
+ * Initial file creating (porting from 85XX & 8260)
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware
+ * exceptions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/processor.h>
+#include <asm/mpc8349_pci.h>
+
+/* Returns 0 if exception not found and fixup otherwise. */
+extern unsigned long search_exception_table(unsigned long);
+
+#define END_OF_MEM (gd->bd->bi_memstart + gd->bd->bi_memsize)
+
+/*
+ * Trap & Exception support
+ */
+
+void
+print_backtrace(unsigned long *sp)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+ int cnt = 0;
+ unsigned long i;
+
+ puts ("Call backtrace: ");
+ while (sp) {
+ if ((uint)sp > END_OF_MEM)
+ break;
+
+ i = sp[1];
+ if (cnt++ % 7 == 0)
+ putc ('\n');
+ printf("%08lX ", i);
+ if (cnt > 32) break;
+ sp = (unsigned long *)*sp;
+ }
+ putc ('\n');
+}
+
+void show_regs(struct pt_regs * regs)
+{
+ int i;
+
+ printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
+ regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+ printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
+ regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
+ regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
+ regs->msr&MSR_IR ? 1 : 0,
+ regs->msr&MSR_DR ? 1 : 0);
+
+ putc ('\n');
+ for (i = 0; i < 32; i++) {
+ if ((i % 8) == 0) {
+ printf("GPR%02d: ", i);
+ }
+
+ printf("%08lX ", regs->gpr[i]);
+ if ((i % 8) == 7) {
+ putc ('\n');
+ }
+ }
+}
+
+
+void
+_exception(int signr, struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
+}
+
+#ifdef CONFIG_PCI
+void dump_pci (void)
+{
+/*
+ volatile immap_t *immap = (immap_t *) CFG_IMMR;
+ printf ("PCI: err status %x err mask %x err ctrl %x\n",
+ le32_to_cpu (immap->im_pci.pci_esr),
+ le32_to_cpu (immap->im_pci.pci_emr),
+ le32_to_cpu (immap->im_pci.pci_ecr));
+ printf (" error address %x error data %x ctrl %x\n",
+ le32_to_cpu (immap->im_pci.pci_eacr),
+ le32_to_cpu (immap->im_pci.pci_edcr),
+ le32_to_cpu (immap->im_pci.pci_eccr));
+*/
+}
+#endif
+
+void
+MachineCheckException(struct pt_regs *regs)
+{
+ unsigned long fixup;
+
+ /* Probing PCI using config cycles cause this exception
+ * when a device is not present. Catch it and return to
+ * the PCI exception handler.
+ */
+#ifdef CONFIG_PCI
+#if 0
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+#ifdef DEBUG
+ dump_pci();
+#endif
+ /* clear the error in the error status register */
+ if(immap->im_pci.pci_esr & cpu_to_le32(PCI_ERROR_PCI_NO_RSP)) {
+ immap->im_pci.pci_esr = cpu_to_le32(PCI_ERROR_PCI_NO_RSP);
+ return;
+ }
+#endif
+#endif /* CONFIG_PCI */
+ if ((fixup = search_exception_table(regs->nip)) != 0) {
+ regs->nip = fixup;
+ return;
+ }
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ puts ("Machine check in kernel mode.\n"
+ "Caused by (from msr): ");
+ printf("regs %p ",regs);
+ switch( regs->msr & 0x000F0000) {
+ case (0x80000000>>12):
+ puts ("Machine check signal - probably due to mm fault\n"
+ "with mmu off\n");
+ break;
+ case (0x80000000>>13):
+ puts ("Transfer error ack signal\n");
+ break;
+ case (0x80000000>>14):
+ puts ("Data parity signal\n");
+ break;
+ case (0x80000000>>15):
+ puts ("Address parity signal\n");
+ break;
+ default:
+ puts ("Unknown values in msr\n");
+ }
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+#ifdef CONFIG_PCI
+ dump_pci();
+#endif
+ panic("machine check");
+}
+
+void
+AlignmentException(struct pt_regs *regs)
+{
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Alignment Exception");
+}
+
+void
+ProgramCheckException(struct pt_regs *regs)
+{
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Program Check Exception");
+}
+
+void
+SoftEmuException(struct pt_regs *regs)
+{
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Software Emulation Exception");
+}
+
+
+void
+UnknownException(struct pt_regs *regs)
+{
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+ regs->nip, regs->msr, regs->trap);
+ _exception(0, regs);
+}
+
+#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+extern void do_bedbug_breakpoint(struct pt_regs *);
+#endif
+
+void
+DebugException(struct pt_regs *regs)
+{
+ printf("Debugger trap at @ %lx\n", regs->nip );
+ show_regs(regs);
+#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+ do_bedbug_breakpoint( regs );
+#endif
+}
+
+/* Probe an address by reading. If not present, return -1, otherwise
+ * return 0.
+ */
+int
+addr_probe(uint *addr)
+{
+#if 0
+ int retval;
+
+ __asm__ __volatile__( \
+ "1: lwz %0,0(%1)\n" \
+ " eieio\n" \
+ " li %0,0\n" \
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "3: li %0,-1\n" \
+ " b 2b\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 2\n" \
+ " .long 1b,3b\n" \
+ ".text" \
+ : "=r" (retval) : "r"(addr));
+
+ return (retval);
+#endif
+ return 0;
+}
diff --git a/cpu/mpc85xx/Makefile b/cpu/mpc85xx/Makefile
index 996915e11c..5298dc113f 100644
--- a/cpu/mpc85xx/Makefile
+++ b/cpu/mpc85xx/Makefile
@@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk
LIB = lib$(CPU).a
START = start.o resetvec.o
-COBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o tsec.o \
+COBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o \
pci.o serial_scc.o commproc.o ether_fcc.o i2c.o spd_sdram.o
OBJS = $(COBJS)
diff --git a/cpu/mpc85xx/commproc.c b/cpu/mpc85xx/commproc.c
index df11052f2a..aa8a5a57ba 100644
--- a/cpu/mpc85xx/commproc.c
+++ b/cpu/mpc85xx/commproc.c
@@ -24,7 +24,7 @@
#include <common.h>
#include <asm/cpm_85xx.h>
-#if defined(CONFIG_MPC8560)
+#if defined(CONFIG_CPM2)
/*
* because we have stack and init data in dual port ram
* we must reduce the size
@@ -211,4 +211,4 @@ ulong post_word_load (void)
#endif /* CONFIG_POST */
-#endif /* CONFIG_MPC8560 */
+#endif /* CONFIG_CPM2 */
diff --git a/cpu/mpc85xx/cpu.c b/cpu/mpc85xx/cpu.c
index 4a1ccb05ba..f7fe22e3e1 100644
--- a/cpu/mpc85xx/cpu.c
+++ b/cpu/mpc85xx/cpu.c
@@ -38,6 +38,7 @@ int checkcpu (void)
uint lcrr; /* local bus clock ratio register */
uint clkdiv; /* clock divider portion of lcrr */
uint pvr, svr;
+ uint fam;
uint ver;
uint major, minor;
@@ -60,6 +61,12 @@ int checkcpu (void)
case SVR_8560:
puts("8560");
break;
+ case SVR_8548:
+ puts("8548");
+ break;
+ case SVR_8548_E:
+ puts("8548_E");
+ break;
default:
puts("Unknown");
break;
@@ -67,13 +74,14 @@ int checkcpu (void)
printf(", Version: %d.%d, (0x%08x)\n", major, minor, svr);
pvr = get_pvr();
+ fam = PVR_FAM(pvr);
ver = PVR_VER(pvr);
major = PVR_MAJ(pvr);
minor = PVR_MIN(pvr);
printf("Core: ");
- switch (ver) {
- case PVR_VER(PVR_85xx):
+ switch (fam) {
+ case PVR_FAM(PVR_85xx):
puts("E500");
break;
default:
@@ -84,7 +92,7 @@ int checkcpu (void)
get_sys_info(&sysinfo);
- puts("Clocks Configuration:\n");
+ puts("Clock Configuration:\n");
printf(" CPU:%4lu MHz, ", sysinfo.freqProcessor / 1000000);
printf("CCB:%4lu MHz,\n", sysinfo.freqSystemBus / 1000000);
printf(" DDR:%4lu MHz, ", sysinfo.freqSystemBus / 2000000);
@@ -101,6 +109,13 @@ int checkcpu (void)
#endif
clkdiv = lcrr & 0x0f;
if (clkdiv == 2 || clkdiv == 4 || clkdiv == 8) {
+#ifdef CONFIG_MPC8548
+ /*
+ * Yes, the entire PQ38 family use the same
+ * bit-representation for twice the clock divider values.
+ */
+ clkdiv *= 2;
+#endif
printf("LBC:%4lu MHz\n",
sysinfo.freqSystemBus / 1000000 / clkdiv);
} else {
diff --git a/cpu/mpc85xx/cpu_init.c b/cpu/mpc85xx/cpu_init.c
index ee2f79feef..efde9cc31a 100644
--- a/cpu/mpc85xx/cpu_init.c
+++ b/cpu/mpc85xx/cpu_init.c
@@ -30,7 +30,7 @@
#include <ioports.h>
#include <asm/io.h>
-#ifdef CONFIG_MPC8560
+#ifdef CONFIG_CPM2
static void config_8560_ioports (volatile immap_t * immr)
{
int portnum;
@@ -115,7 +115,7 @@ void cpu_init_f (void)
memset ((void *) gd, 0, sizeof (gd_t));
-#ifdef CONFIG_MPC8560
+#ifdef CONFIG_CPM2
config_8560_ioports(immap);
#endif
@@ -173,32 +173,63 @@ void cpu_init_f (void)
memctl->br7 = CFG_BR7_PRELIM;
#endif
-#if defined(CONFIG_MPC8560)
+#if defined(CONFIG_CPM2)
m8560_cpm_reset();
#endif
}
+
/*
- * We initialize L2 as cache here.
+ * Initialize L2 as cache.
+ *
+ * The newer 8548, etc, parts have twice as much cache, but
+ * use the same bit-encoding as the older 8555, etc, parts.
+ *
+ * FIXME: Use PVR_VER(pvr) == 1 test here instead of SVR_VER()?
*/
-int cpu_init_r (void)
+
+int cpu_init_r(void)
{
#if defined(CONFIG_L2_CACHE)
- volatile immap_t *immap = (immap_t *)CFG_IMMR;
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
volatile ccsr_l2cache_t *l2cache = &immap->im_l2cache;
- volatile uint temp;
+ volatile uint cache_ctl;
+ uint svr, ver;
+
+ svr = get_svr();
+ ver = SVR_VER(svr);
+
+ asm("msync;isync");
+ cache_ctl = l2cache->l2ctl;
+
+ switch (cache_ctl & 0x30000000) {
+ case 0x20000000:
+ if (ver == SVR_8548 || ver == SVR_8548_E) {
+ printf ("L2 cache 512KB:");
+ } else {
+ printf ("L2 cache 256KB:");
+ }
+ break;
+ case 0x00000000:
+ case 0x10000000:
+ case 0x30000000:
+ default:
+ printf ("L2 cache unknown size (0x%08x)\n", cache_ctl);
+ return -1;
+ }
asm("msync;isync");
l2cache->l2ctl = 0x68000000; /* invalidate */
- temp = l2cache->l2ctl;
+ cache_ctl = l2cache->l2ctl;
asm("msync;isync");
+
l2cache->l2ctl = 0xa8000000; /* enable 256KB L2 cache */
- temp = l2cache->l2ctl;
+ cache_ctl = l2cache->l2ctl;
asm("msync;isync");
- printf("L2: 256 kB enabled\n");
+ printf(" enabled\n");
#else
- printf("L2: disabled.\n");
+ printf("L2 cache: disabled\n");
#endif
return 0;
diff --git a/cpu/mpc85xx/ether_fcc.c b/cpu/mpc85xx/ether_fcc.c
index 122ca870c8..cbbb3a4020 100644
--- a/cpu/mpc85xx/ether_fcc.c
+++ b/cpu/mpc85xx/ether_fcc.c
@@ -48,7 +48,7 @@
#include <config.h>
#include <net.h>
-#if defined(CONFIG_MPC8560)
+#if defined(CONFIG_CPM2)
#if defined(CONFIG_ETHER_ON_FCC) && (CONFIG_COMMANDS & CFG_CMD_NET) && \
defined(CONFIG_NET_MULTI)
@@ -458,4 +458,4 @@ int fec_initialize(bd_t *bis)
#endif /* CONFIG_ETHER_ON_FCC && CFG_CMD_NET && CONFIG_NET_MULTI */
-#endif /* CONFIG_MPC8560 */
+#endif /* CONFIG_CPM2 */
diff --git a/cpu/mpc85xx/serial_scc.c b/cpu/mpc85xx/serial_scc.c
index ea82761465..cf060d6890 100644
--- a/cpu/mpc85xx/serial_scc.c
+++ b/cpu/mpc85xx/serial_scc.c
@@ -35,7 +35,7 @@
#include <common.h>
#include <asm/cpm_85xx.h>
-#if defined(CONFIG_MPC8560)
+#if defined(CONFIG_CPM2)
#if defined(CONFIG_CONS_ON_SCC)
#if CONFIG_CONS_INDEX == 1 /* Console on SCC1 */
@@ -271,4 +271,4 @@ serial_tstc()
#endif /* CONFIG_CONS_ON_SCC */
-#endif /* CONFIG_MPC8560 */
+#endif /* CONFIG_CPM2 */
diff --git a/cpu/mpc85xx/spd_sdram.c b/cpu/mpc85xx/spd_sdram.c
index 5a1dbe2b53..af99282dd9 100644
--- a/cpu/mpc85xx/spd_sdram.c
+++ b/cpu/mpc85xx/spd_sdram.c
@@ -28,10 +28,11 @@
#include <spd.h>
#include <asm/mmu.h>
-#if defined(CONFIG_DDR_ECC)
-extern void dma_init (void);
+
+#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
+extern void dma_init(void);
extern uint dma_check(void);
-extern int dma_xfer (void *dest, uint count, void *src);
+extern int dma_xfer(void *dest, uint count, void *src);
#endif
#ifdef CONFIG_SPD_EEPROM
@@ -40,6 +41,9 @@ extern int dma_xfer (void *dest, uint count, void *src);
#define CFG_READ_SPD i2c_read
#endif
+static unsigned int setup_laws_and_tlbs(unsigned int memsize);
+
+
/*
* Convert picoseconds into clock cycles (rounding up if needed).
*/
@@ -57,311 +61,829 @@ picos_to_clk(int picos)
return clks;
}
+
+/*
+ * Calculate the Density of each Physical Rank.
+ * Returned size is in bytes.
+ *
+ * Study these table from Byte 31 of JEDEC SPD Spec.
+ *
+ * DDR I DDR II
+ * Bit Size Size
+ * --- ----- ------
+ * 7 high 512MB 512MB
+ * 6 256MB 256MB
+ * 5 128MB 128MB
+ * 4 64MB 16GB
+ * 3 32MB 8GB
+ * 2 16MB 4GB
+ * 1 2GB 2GB
+ * 0 low 1GB 1GB
+ *
+ * Reorder Table to be linear by stripping the bottom
+ * 2 or 5 bits off and shifting them up to the top.
+ */
+
+unsigned int
+compute_banksize(unsigned int mem_type, unsigned char row_dens)
+{
+ unsigned int bsize;
+
+ if (mem_type == SPD_MEMTYPE_DDR) {
+ /* Bottom 2 bits up to the top. */
+ bsize = ((row_dens >> 2) | ((row_dens & 3) << 6)) << 24;
+ debug("DDR: DDR I rank density = 0x%08x\n", bsize);
+ } else {
+ /* Bottom 5 bits up to the top. */
+ bsize = ((row_dens >> 5) | ((row_dens & 31) << 3)) << 27;
+ debug("DDR: DDR II rank density = 0x%08x\n", bsize);
+ }
+ return bsize;
+}
+
+
+/*
+ * Convert a two-nibble BCD value into a cycle time.
+ * While the spec calls for nano-seconds, picos are returned.
+ *
+ * This implements the tables for bytes 9, 23 and 25 for both
+ * DDR I and II. No allowance for distinguishing the invalid
+ * fields absent for DDR I yet present in DDR II is made.
+ * (That is, cycle times of .25, .33, .66 and .75 ns are
+ * allowed for both DDR II and I.)
+ */
+
unsigned int
-banksize(unsigned char row_dens)
+convert_bcd_tenths_to_cycle_time_ps(unsigned int spd_val)
{
- return ((row_dens >> 2) | ((row_dens & 3) << 6)) << 24;
+ /*
+ * Table look up the lower nibble, allow DDR I & II.
+ */
+ unsigned int tenths_ps[16] = {
+ 0,
+ 100,
+ 200,
+ 300,
+ 400,
+ 500,
+ 600,
+ 700,
+ 800,
+ 900,
+ 250,
+ 330, /* FIXME: Is 333 better/valid? */
+ 660, /* FIXME: Is 667 better/valid? */
+ 750,
+ 0, /* undefined */
+ 0 /* undefined */
+ };
+
+ unsigned int whole_ns = (spd_val & 0xF0) >> 4;
+ unsigned int tenth_ns = spd_val & 0x0F;
+ unsigned int ps = whole_ns * 1000 + tenths_ps[tenth_ns];
+
+ return ps;
}
+
long int
spd_sdram(void)
{
volatile immap_t *immap = (immap_t *)CFG_IMMR;
volatile ccsr_ddr_t *ddr = &immap->im_ddr;
- volatile ccsr_local_ecm_t *ecm = &immap->im_local_ecm;
+ volatile ccsr_gur_t *gur = &immap->im_gur;
spd_eeprom_t spd;
- unsigned tmp, tmp1;
+ unsigned int n_ranks;
+ unsigned int rank_density;
+ unsigned int odt_rd_cfg, odt_wr_cfg;
+ unsigned int odt_cfg, mode_odt_enable;
+ unsigned int dqs_cfg;
+ unsigned char twr_clk, twtr_clk, twr_auto_clk;
+ unsigned int tCKmin_ps, tCKmax_ps;
+ unsigned int max_data_rate, effective_data_rate;
+ unsigned int busfreq;
+ unsigned sdram_cfg;
unsigned int memsize;
- unsigned int tlb_size;
- unsigned int law_size;
- unsigned char caslat;
- unsigned int ram_tlb_index;
- unsigned int ram_tlb_address;
+ unsigned char caslat, caslat_ctrl;
+ unsigned int trfc, trfc_clk, trfc_low, trfc_high;
+ unsigned int trcd_clk;
+ unsigned int trtp_clk;
+ unsigned char cke_min_clk;
+ unsigned char add_lat;
+ unsigned char wr_lat;
+ unsigned char wr_data_delay;
+ unsigned char four_act;
+ unsigned char cpo;
+ unsigned char burst_len;
+ unsigned int mode_caslat;
+ unsigned char sdram_type;
+ unsigned char d_init;
- CFG_READ_SPD(SPD_EEPROM_ADDRESS, 0, 1, (uchar *) & spd, sizeof (spd));
+ /*
+ * Read SPD information.
+ */
+ CFG_READ_SPD(SPD_EEPROM_ADDRESS, 0, 1, (uchar *) &spd, sizeof(spd));
- if (spd.nrows > 2) {
- puts("DDR:Only two chip selects are supported on ADS.\n");
+ /*
+ * Check for supported memory module types.
+ */
+ if (spd.mem_type != SPD_MEMTYPE_DDR &&
+ spd.mem_type != SPD_MEMTYPE_DDR2) {
+ printf("Unable to locate DDR I or DDR II module.\n"
+ " Fundamental memory type is 0x%0x\n",
+ spd.mem_type);
return 0;
}
- if (spd.nrow_addr < 12
- || spd.nrow_addr > 14
- || spd.ncol_addr < 8
- || spd.ncol_addr > 11) {
- puts("DDR:Row or Col number unsupported.\n");
+ /*
+ * These test gloss over DDR I and II differences in interpretation
+ * of bytes 3 and 4, but irrelevantly. Multiple asymmetric banks
+ * are not supported on DDR I; and not encoded on DDR II.
+ *
+ * Also note that the 8548 controller can support:
+ * 12 <= nrow <= 16
+ * and
+ * 8 <= ncol <= 11 (still, for DDR)
+ * 6 <= ncol <= 9 (for FCRAM)
+ */
+ if (spd.nrow_addr < 12 || spd.nrow_addr > 14) {
+ printf("DDR: Unsupported number of Row Addr lines: %d.\n",
+ spd.nrow_addr);
+ return 0;
+ }
+ if (spd.ncol_addr < 8 || spd.ncol_addr > 11) {
+ printf("DDR: Unsupported number of Column Addr lines: %d.\n",
+ spd.ncol_addr);
return 0;
}
- ddr->cs0_bnds = (banksize(spd.row_dens) >> 24) - 1;
- ddr->cs0_config = ( 1 << 31
- | (spd.nrow_addr - 12) << 8
- | (spd.ncol_addr - 8) );
- debug("\n");
- debug("cs0_bnds = 0x%08x\n",ddr->cs0_bnds);
- debug("cs0_config = 0x%08x\n",ddr->cs0_config);
-
- if (spd.nrows == 2) {
- ddr->cs1_bnds = ( (banksize(spd.row_dens) >> 8)
- | ((banksize(spd.row_dens) >> 23) - 1) );
- ddr->cs1_config = ( 1<<31
- | (spd.nrow_addr-12) << 8
- | (spd.ncol_addr-8) );
- debug("cs1_bnds = 0x%08x\n",ddr->cs1_bnds);
- debug("cs1_config = 0x%08x\n",ddr->cs1_config);
+ /*
+ * Determine the number of physical banks controlled by
+ * different Chip Select signals. This is not quite the
+ * same as the number of DIMM modules on the board. Feh.
+ */
+ if (spd.mem_type == SPD_MEMTYPE_DDR) {
+ n_ranks = spd.nrows;
+ } else {
+ n_ranks = (spd.nrows & 0x7) + 1;
}
- if (spd.mem_type != 0x07) {
- puts("No DDR module found!\n");
+ debug("DDR: number of ranks = %d\n", n_ranks);
+
+ if (n_ranks > 2) {
+ printf("DDR: Only 2 chip selects are supported: %d\n",
+ n_ranks);
return 0;
}
/*
- * Figure out memory size in Megabytes.
+ * Adjust DDR II IO voltage biasing. It just makes it work.
*/
- memsize = spd.nrows * banksize(spd.row_dens) / 0x100000;
+ if (spd.mem_type == SPD_MEMTYPE_DDR2) {
+ gur->ddrioovcr = (0
+ | 0x80000000 /* Enable */
+ | 0x10000000 /* VSEL to 1.8V */
+ );
+ }
/*
- * First supported LAW size is 16M, at LAWAR_SIZE_16M == 23. Fnord.
+ * Determine the size of each Rank in bytes.
*/
- law_size = 19 + __ilog2(memsize);
+ rank_density = compute_banksize(spd.mem_type, spd.row_dens);
+
/*
- * Determine size of each TLB1 entry.
+ * Eg: Bounds: 0x0000_0000 to 0x0f000_0000 first 256 Meg
*/
- switch (memsize) {
- case 16:
- case 32:
- tlb_size = BOOKE_PAGESZ_16M;
- break;
- case 64:
- case 128:
- tlb_size = BOOKE_PAGESZ_64M;
- break;
- case 256:
- case 512:
- case 1024:
- case 2048:
- tlb_size = BOOKE_PAGESZ_256M;
- break;
- default:
- puts("DDR: only 16M,32M,64M,128M,256M,512M,1G and 2G DDR I are supported.\n");
- return 0;
- break;
- }
+ ddr->cs0_bnds = (rank_density >> 24) - 1;
/*
- * Configure DDR TLB1 entries.
- * Starting at TLB1 8, use no more than 8 TLB1 entries.
+ * ODT configuration recommendation from DDR Controller Chapter.
*/
- ram_tlb_index = 8;
- ram_tlb_address = (unsigned int)CFG_DDR_SDRAM_BASE;
- while (ram_tlb_address < (memsize * 1024 * 1024)
- && ram_tlb_index < 16) {
- mtspr(MAS0, TLB1_MAS0(1, ram_tlb_index, 0));
- mtspr(MAS1, TLB1_MAS1(1, 1, 0, 0, tlb_size));
- mtspr(MAS2, TLB1_MAS2(E500_TLB_EPN(ram_tlb_address),
- 0, 0, 0, 0, 0, 0, 0, 0));
- mtspr(MAS3, TLB1_MAS3(E500_TLB_RPN(ram_tlb_address),
- 0, 0, 0, 0, 0, 1, 0, 1, 0, 1));
- asm volatile("isync;msync;tlbwe;isync");
+ odt_rd_cfg = 0; /* Never assert ODT */
+ odt_wr_cfg = 0; /* Never assert ODT */
+ if (spd.mem_type == SPD_MEMTYPE_DDR2) {
+ odt_wr_cfg = 1; /* Assert ODT on writes to CS0 */
+#if 0
+ /* FIXME: How to determine the number of dimm modules? */
+ if (n_dimm_modules == 2) {
+ odt_rd_cfg = 1; /* Assert ODT on reads to CS0 */
+ }
+#endif
+ }
- debug("DDR:MAS0=0x%08x\n", TLB1_MAS0(1, ram_tlb_index, 0));
- debug("DDR:MAS1=0x%08x\n", TLB1_MAS1(1, 1, 0, 0, tlb_size));
- debug("DDR:MAS2=0x%08x\n",
- TLB1_MAS2(E500_TLB_EPN(ram_tlb_address),
- 0, 0, 0, 0, 0, 0, 0, 0));
- debug("DDR:MAS3=0x%08x\n",
- TLB1_MAS3(E500_TLB_RPN(ram_tlb_address),
- 0, 0, 0, 0, 0, 1, 0, 1, 0, 1));
+ ddr->cs0_config = ( 1 << 31
+ | (odt_rd_cfg << 20)
+ | (odt_wr_cfg << 16)
+ | (spd.nrow_addr - 12) << 8
+ | (spd.ncol_addr - 8) );
+ debug("\n");
+ debug("DDR: cs0_bnds = 0x%08x\n", ddr->cs0_bnds);
+ debug("DDR: cs0_config = 0x%08x\n", ddr->cs0_config);
- ram_tlb_address += (0x1000 << ((tlb_size - 1) * 2));
- ram_tlb_index++;
+ if (n_ranks == 2) {
+ /*
+ * Eg: Bounds: 0x0f00_0000 to 0x1e0000_0000, second 256 Meg
+ */
+ ddr->cs1_bnds = ( (rank_density >> 8)
+ | ((rank_density >> (24 - 1)) - 1) );
+ ddr->cs1_config = ( 1<<31
+ | (odt_rd_cfg << 20)
+ | (odt_wr_cfg << 16)
+ | (spd.nrow_addr - 12) << 8
+ | (spd.ncol_addr - 8) );
+ debug("DDR: cs1_bnds = 0x%08x\n", ddr->cs1_bnds);
+ debug("DDR: cs1_config = 0x%08x\n", ddr->cs1_config);
}
+
/*
- * Set up LAWBAR for all of DDR.
+ * Find the largest CAS by locating the highest 1 bit
+ * in the spd.cas_lat field. Translate it to a DDR
+ * controller field value:
+ *
+ * CAS Lat DDR I DDR II Ctrl
+ * Clocks SPD Bit SPD Bit Value
+ * ------- ------- ------- -----
+ * 1.0 0 0001
+ * 1.5 1 0010
+ * 2.0 2 2 0011
+ * 2.5 3 0100
+ * 3.0 4 3 0101
+ * 3.5 5 0110
+ * 4.0 4 0111
+ * 4.5 1000
+ * 5.0 5 1001
*/
- ecm->lawbar1 = ((CFG_DDR_SDRAM_BASE>>12) & 0xfffff);
- ecm->lawar1 = (LAWAR_EN | LAWAR_TRGT_IF_DDR | (LAWAR_SIZE & law_size));
- debug("DDR:LAWBAR1=0x%08x\n", ecm->lawbar1);
- debug("DDR:LARAR1=0x%08x\n", ecm->lawar1);
-
- /*
- * find the largest CAS
- */
- if(spd.cas_lat & 0x40) {
- caslat = 7;
- } else if (spd.cas_lat & 0x20) {
- caslat = 6;
- } else if (spd.cas_lat & 0x10) {
- caslat = 5;
- } else if (spd.cas_lat & 0x08) {
- caslat = 4;
- } else if (spd.cas_lat & 0x04) {
- caslat = 3;
- } else if (spd.cas_lat & 0x02) {
- caslat = 2;
- } else if (spd.cas_lat & 0x01) {
- caslat = 1;
- } else {
- puts("DDR:no valid CAS Latency information.\n");
+ caslat = __ilog2(spd.cas_lat);
+ if ((spd.mem_type == SPD_MEMTYPE_DDR)
+ && (caslat > 5)) {
+ printf("DDR I: Invalid SPD CAS Latency: 0x%x.\n", spd.cas_lat);
+ return 0;
+
+ } else if (spd.mem_type == SPD_MEMTYPE_DDR2
+ && (caslat < 2 || caslat > 5)) {
+ printf("DDR II: Invalid SPD CAS Latency: 0x%x.\n",
+ spd.cas_lat);
return 0;
}
+ debug("DDR: caslat SPD bit is %d\n", caslat);
+
+ /*
+ * Calculate the Maximum Data Rate based on the Minimum Cycle time.
+ * The SPD clk_cycle field (tCKmin) is measured in tenths of
+ * nanoseconds and represented as BCD.
+ */
+ tCKmin_ps = convert_bcd_tenths_to_cycle_time_ps(spd.clk_cycle);
+ debug("DDR: tCKmin = %d ps\n", tCKmin_ps);
+
+ /*
+ * Double-data rate, scaled 1000 to picoseconds, and back down to MHz.
+ */
+ max_data_rate = 2 * 1000 * 1000 / tCKmin_ps;
+ debug("DDR: Module max data rate = %d Mhz\n", max_data_rate);
+
- tmp = 20000 / (((spd.clk_cycle & 0xF0) >> 4) * 10
- + (spd.clk_cycle & 0x0f));
- debug("DDR:Module maximum data rate is: %dMhz\n", tmp);
+ /*
+ * Adjust the CAS Latency to allow for bus speeds that
+ * are slower than the DDR module.
+ */
+ busfreq = get_bus_freq(0) / 1000000; /* MHz */
- tmp1 = get_bus_freq(0) / 1000000;
- if (tmp1 < 230 && tmp1 >= 90 && tmp >= 230) {
- /* 90~230 range, treated as DDR 200 */
- if (spd.clk_cycle3 == 0xa0)
+ effective_data_rate = max_data_rate;
+ if (busfreq < 90) {
+ /* DDR rate out-of-range */
+ puts("DDR: platform frequency is not fit for DDR rate\n");
+ return 0;
+
+ } else if (90 <= busfreq && busfreq < 230 && max_data_rate >= 230) {
+ /*
+ * busfreq 90~230 range, treated as DDR 200.
+ */
+ effective_data_rate = 200;
+ if (spd.clk_cycle3 == 0xa0) /* 10 ns */
caslat -= 2;
- else if(spd.clk_cycle2 == 0xa0)
+ else if (spd.clk_cycle2 == 0xa0)
caslat--;
- } else if (tmp1 < 280 && tmp1 >= 230 && tmp >= 280) {
- /* 230-280 range, treated as DDR 266 */
- if (spd.clk_cycle3 == 0x75)
+
+ } else if (230 <= busfreq && busfreq < 280 && max_data_rate >= 280) {
+ /*
+ * busfreq 230~280 range, treated as DDR 266.
+ */
+ effective_data_rate = 266;
+ if (spd.clk_cycle3 == 0x75) /* 7.5 ns */
caslat -= 2;
else if (spd.clk_cycle2 == 0x75)
caslat--;
- } else if (tmp1 < 350 && tmp1 >= 280 && tmp >= 350) {
- /* 280~350 range, treated as DDR 333 */
- if (spd.clk_cycle3 == 0x60)
+
+ } else if (280 <= busfreq && busfreq < 350 && max_data_rate >= 350) {
+ /*
+ * busfreq 280~350 range, treated as DDR 333.
+ */
+ effective_data_rate = 333;
+ if (spd.clk_cycle3 == 0x60) /* 6.0 ns */
caslat -= 2;
else if (spd.clk_cycle2 == 0x60)
caslat--;
- } else if (tmp1 < 90 || tmp1 >= 350) {
- /* DDR rate out-of-range */
- puts("DDR:platform frequency is not fit for DDR rate\n");
+
+ } else if (350 <= busfreq && busfreq < 460 && max_data_rate >= 460) {
+ /*
+ * busfreq 350~460 range, treated as DDR 400.
+ */
+ effective_data_rate = 400;
+ if (spd.clk_cycle3 == 0x50) /* 5.0 ns */
+ caslat -= 2;
+ else if (spd.clk_cycle2 == 0x50)
+ caslat--;
+
+ } else if (460 <= busfreq && busfreq < 560 && max_data_rate >= 560) {
+ /*
+ * busfreq 460~560 range, treated as DDR 533.
+ */
+ effective_data_rate = 533;
+ if (spd.clk_cycle3 == 0x3D) /* 3.75 ns */
+ caslat -= 2;
+ else if (spd.clk_cycle2 == 0x3D)
+ caslat--;
+
+ } else if (560 <= busfreq && busfreq < 700 && max_data_rate >= 700) {
+ /*
+ * busfreq 560~700 range, treated as DDR 667.
+ */
+ effective_data_rate = 667;
+ if (spd.clk_cycle3 == 0x30) /* 3.0 ns */
+ caslat -= 2;
+ else if (spd.clk_cycle2 == 0x30)
+ caslat--;
+
+ } else if (700 <= busfreq) {
+ /*
+ * DDR rate out-of-range
+ */
+ printf("DDR: Bus freq %d MHz is not fit for DDR rate %d MHz\n",
+ busfreq, max_data_rate);
return 0;
}
+
/*
- * note: caslat must also be programmed into ddr->sdram_mode
- * register.
- *
- * note: WRREC(Twr) and WRTORD(Twtr) are not in SPD,
- * use conservative value here.
+ * Convert caslat clocks to DDR controller value.
+ * Force caslat_ctrl to be DDR Controller field-sized.
+ */
+ if (spd.mem_type == SPD_MEMTYPE_DDR) {
+ caslat_ctrl = (caslat + 1) & 0x07;
+ } else {
+ caslat_ctrl = (2 * caslat - 1) & 0x0f;
+ }
+
+ debug("DDR: effective data rate is %d MHz\n", effective_data_rate);
+ debug("DDR: caslat SPD bit is %d, controller field is 0x%x\n",
+ caslat, caslat_ctrl);
+
+ /*
+ * Timing Config 0.
+ * Avoid writing for DDR I. The new PQ38 DDR controller
+ * dreams up non-zero default values to be backwards compatible.
*/
+ if (spd.mem_type == SPD_MEMTYPE_DDR2) {
+ unsigned char taxpd_clk = 8; /* By the book. */
+ unsigned char tmrd_clk = 2; /* By the book. */
+ unsigned char act_pd_exit = 2; /* Empirical? */
+ unsigned char pre_pd_exit = 6; /* Empirical? */
+
+ ddr->timing_cfg_0 = (0
+ | ((act_pd_exit & 0x7) << 20) /* ACT_PD_EXIT */
+ | ((pre_pd_exit & 0x7) << 16) /* PRE_PD_EXIT */
+ | ((taxpd_clk & 0xf) << 8) /* ODT_PD_EXIT */
+ | ((tmrd_clk & 0xf) << 0) /* MRS_CYC */
+ );
+#if 0
+ ddr->timing_cfg_0 |= 0xaa000000; /* extra cycles */
+#endif
+ debug("DDR: timing_cfg_0 = 0x%08x\n", ddr->timing_cfg_0);
+
+ } else {
+#if 0
+ /*
+ * Force extra cycles with 0xaa bits.
+ * Incidentally supply the dreamt-up backwards compat value!
+ */
+ ddr->timing_cfg_0 = 0x00110105; /* backwards compat value */
+ ddr->timing_cfg_0 |= 0xaa000000; /* extra cycles */
+ debug("DDR: HACK timing_cfg_0 = 0x%08x\n", ddr->timing_cfg_0);
+#endif
+ }
+
+
+ /*
+ * Some Timing Config 1 values now.
+ * Sneak Extended Refresh Recovery in here too.
+ */
+
+ /*
+ * For DDR I, WRREC(Twr) and WRTORD(Twtr) are not in SPD,
+ * use conservative value.
+ * For DDR II, they are bytes 36 and 37, in quarter nanos.
+ */
+
+ if (spd.mem_type == SPD_MEMTYPE_DDR) {
+ twr_clk = 3; /* Clocks */
+ twtr_clk = 1; /* Clocks */
+ } else {
+ twr_clk = picos_to_clk(spd.twr * 250);
+ twtr_clk = picos_to_clk(spd.twtr * 250);
+ }
+
+ /*
+ * Calculate Trfc, in picos.
+ * DDR I: Byte 42 straight up in ns.
+ * DDR II: Byte 40 and 42 swizzled some, in ns.
+ */
+ if (spd.mem_type == SPD_MEMTYPE_DDR) {
+ trfc = spd.trfc * 1000; /* up to ps */
+ } else {
+ unsigned int byte40_table_ps[8] = {
+ 0,
+ 250,
+ 330,
+ 500,
+ 660,
+ 750,
+ 0,
+ 0
+ };
+
+ trfc = (((spd.trctrfc_ext & 0x1) * 256) + spd.trfc) * 1000
+ + byte40_table_ps[(spd.trctrfc_ext >> 1) & 0x7];
+ }
+ trfc_clk = picos_to_clk(trfc);
+
+ /*
+ * Trcd, Byte 29, from quarter nanos to ps and clocks.
+ */
+ trcd_clk = picos_to_clk(spd.trcd * 250) & 0x7;
+
+ /*
+ * Convert trfc_clk to DDR controller fields. DDR I should
+ * fit in the REFREC field (16-19) of TIMING_CFG_1, but the
+ * 8548 controller has an extended REFREC field of three bits.
+ * The controller automatically adds 8 clocks to this value,
+ * so preadjust it down 8 first before splitting it up.
+ */
+ trfc_low = (trfc_clk - 8) & 0xf;
+ trfc_high = ((trfc_clk - 8) >> 4) & 0x3;
+
+ /*
+ * Sneak in some Extended Refresh Recovery.
+ */
+ ddr->ext_refrec = (trfc_high << 16);
+ debug("DDR: ext_refrec = 0x%08x\n", ddr->ext_refrec);
+
ddr->timing_cfg_1 =
- (((picos_to_clk(spd.trp * 250) & 0x07) << 28 ) |
- ((picos_to_clk(spd.tras * 1000) & 0x0f ) << 24 ) |
- ((picos_to_clk(spd.trcd * 250) & 0x07) << 20 ) |
- ((caslat & 0x07) << 16 ) |
- (((picos_to_clk(spd.sset[6] * 1000) - 8) & 0x0f) << 12 ) |
- ( 0x300 ) |
- ((picos_to_clk(spd.trrd * 250) & 0x07) << 4) | 1);
+ (0
+ | ((picos_to_clk(spd.trp * 250) & 0x07) << 28) /* PRETOACT */
+ | ((picos_to_clk(spd.tras * 1000) & 0x0f ) << 24) /* ACTTOPRE */
+ | (trcd_clk << 20) /* ACTTORW */
+ | (caslat_ctrl << 16) /* CASLAT */
+ | (trfc_low << 12) /* REFEC */
+ | ((twr_clk & 0x07) << 8) /* WRRREC */
+ | ((picos_to_clk(spd.trrd * 250) & 0x07) << 4) /* ACTTOACT */
+ | ((twtr_clk & 0x07) << 0) /* WRTORD */
+ );
- ddr->timing_cfg_2 = 0x00000800;
+ debug("DDR: timing_cfg_1 = 0x%08x\n", ddr->timing_cfg_1);
- debug("DDR:timing_cfg_1=0x%08x\n", ddr->timing_cfg_1);
- debug("DDR:timing_cfg_2=0x%08x\n", ddr->timing_cfg_2);
/*
- * Only DDR I is supported
- * DDR I and II have different mode-register-set definition
+ * Timing_Config_2
+ * Was: 0x00000800;
*/
- /* burst length is always 4 */
- switch(caslat) {
- case 2:
- ddr->sdram_mode = 0x52; /* 1.5 */
- break;
- case 3:
- ddr->sdram_mode = 0x22; /* 2.0 */
- break;
- case 4:
- ddr->sdram_mode = 0x62; /* 2.5 */
- break;
- case 5:
- ddr->sdram_mode = 0x32; /* 3.0 */
- break;
- default:
- puts("DDR:only CAS Latency 1.5, 2.0, 2.5, 3.0 is supported.\n");
- return 0;
+ /*
+ * Additive Latency
+ * For DDR I, 0.
+ * For DDR II, with ODT enabled, use "a value" less than ACTTORW,
+ * which comes from Trcd, and also note that:
+ * add_lat + caslat must be >= 4
+ */
+ add_lat = 0;
+ if (spd.mem_type == SPD_MEMTYPE_DDR2
+ && (odt_wr_cfg || odt_rd_cfg)
+ && (caslat < 4)) {
+ add_lat = 4 - caslat;
+ if (add_lat > trcd_clk) {
+ add_lat = trcd_clk - 1;
+ }
}
- debug("DDR:sdram_mode=0x%08x\n", ddr->sdram_mode);
- switch(spd.refresh) {
- case 0x00:
- case 0x80:
- tmp = picos_to_clk(15625000);
- break;
- case 0x01:
- case 0x81:
- tmp = picos_to_clk(3900000);
- break;
- case 0x02:
- case 0x82:
- tmp = picos_to_clk(7800000);
- break;
- case 0x03:
- case 0x83:
- tmp = picos_to_clk(31300000);
- break;
- case 0x04:
- case 0x84:
- tmp = picos_to_clk(62500000);
- break;
- case 0x05:
- case 0x85:
- tmp = picos_to_clk(125000000);
- break;
- default:
- tmp = 0x512;
- break;
+ /*
+ * Write Data Delay
+ * Historically 0x2 == 4/8 clock delay.
+ * Empirically, 0x3 == 6/8 clock delay is suggested for DDR I 266.
+ */
+ wr_data_delay = 3;
+
+ /*
+ * Write Latency
+ * Read to Precharge
+ * Minimum CKE Pulse Width.
+ * Four Activate Window
+ */
+ if (spd.mem_type == SPD_MEMTYPE_DDR) {
+ /*
+ * This is a lie. It should really be 1, but if it is
+ * set to 1, bits overlap into the old controller's
+ * otherwise unused ACSM field. If we leave it 0, then
+ * the HW will magically treat it as 1 for DDR 1. Oh Yea.
+ */
+ wr_lat = 0;
+
+ trtp_clk = 2; /* By the book. */
+ cke_min_clk = 1; /* By the book. */
+ four_act = 1; /* By the book. */
+
+ } else {
+ wr_lat = caslat - 1;
+
+ /* Convert SPD value from quarter nanos to picos. */
+ trtp_clk = picos_to_clk(spd.trtp * 250);
+
+ cke_min_clk = 3; /* By the book. */
+ four_act = picos_to_clk(37500); /* By the book. 1k pages? */
+ }
+
+ /*
+ * Empirically set ~MCAS-to-preamble override for DDR 2.
+ * Your milage will vary.
+ */
+ cpo = 0;
+ if (spd.mem_type == SPD_MEMTYPE_DDR2) {
+ if (effective_data_rate == 266 || effective_data_rate == 333) {
+ cpo = 0x7; /* READ_LAT + 5/4 */
+ } else if (effective_data_rate == 400) {
+ cpo = 0x9; /* READ_LAT + 7/4 */
+ } else {
+ /* Pure speculation */
+ cpo = 0xb;
+ }
+ }
+
+ ddr->timing_cfg_2 = (0
+ | ((add_lat & 0x7) << 28) /* ADD_LAT */
+ | ((cpo & 0x1f) << 23) /* CPO */
+ | ((wr_lat & 0x7) << 19) /* WR_LAT */
+ | ((trtp_clk & 0x7) << 13) /* RD_TO_PRE */
+ | ((wr_data_delay & 0x7) << 10) /* WR_DATA_DELAY */
+ | ((cke_min_clk & 0x7) << 6) /* CKE_PLS */
+ | ((four_act & 0x1f) << 0) /* FOUR_ACT */
+ );
+
+ debug("DDR: timing_cfg_2 = 0x%08x\n", ddr->timing_cfg_2);
+
+
+ /*
+ * Determine the Mode Register Set.
+ *
+ * This is nominally part specific, but it appears to be
+ * consistent for all DDR I devices, and for all DDR II devices.
+ *
+ * caslat must be programmed
+ * burst length is always 4
+ * burst type is sequential
+ *
+ * For DDR I:
+ * operating mode is "normal"
+ *
+ * For DDR II:
+ * other stuff
+ */
+
+ mode_caslat = 0;
+
+ /*
+ * Table lookup from DDR I or II Device Operation Specs.
+ */
+ if (spd.mem_type == SPD_MEMTYPE_DDR) {
+ if (1 <= caslat && caslat <= 4) {
+ unsigned char mode_caslat_table[4] = {
+ 0x5, /* 1.5 clocks */
+ 0x2, /* 2.0 clocks */
+ 0x6, /* 2.5 clocks */
+ 0x3 /* 3.0 clocks */
+ };
+ mode_caslat = mode_caslat_table[caslat - 1];
+ } else {
+ puts("DDR I: Only CAS Latencies of 1.5, 2.0, "
+ "2.5 and 3.0 clocks are supported.\n");
+ return 0;
+ }
+
+ } else {
+ if (2 <= caslat && caslat <= 5) {
+ mode_caslat = caslat;
+ } else {
+ puts("DDR II: Only CAS Latencies of 2.0, 3.0, "
+ "4.0 and 5.0 clocks are supported.\n");
+ return 0;
+ }
+ }
+
+ /*
+ * Encoded Burst Lenght of 4.
+ */
+ burst_len = 2; /* Fiat. */
+
+ if (spd.mem_type == SPD_MEMTYPE_DDR) {
+ twr_auto_clk = 0; /* Historical */
+ } else {
+ /*
+ * Determine tCK max in picos. Grab tWR and convert to picos.
+ * Auto-precharge write recovery is:
+ * WR = roundup(tWR_ns/tCKmax_ns).
+ *
+ * Ponder: Is twr_auto_clk different than twr_clk?
+ */
+ tCKmax_ps = convert_bcd_tenths_to_cycle_time_ps(spd.tckmax);
+ twr_auto_clk = (spd.twr * 250 + tCKmax_ps - 1) / tCKmax_ps;
+ }
+
+
+ /*
+ * Mode Reg in bits 16 ~ 31,
+ * Extended Mode Reg 1 in bits 0 ~ 15.
+ */
+ mode_odt_enable = 0x0; /* Default disabled */
+ if (odt_wr_cfg || odt_rd_cfg) {
+ /*
+ * Bits 6 and 2 in Extended MRS(1)
+ * Bit 2 == 0x04 == 75 Ohm, with 2 DIMM modules.
+ * Bit 6 == 0x40 == 150 Ohm, with 1 DIMM module.
+ */
+ mode_odt_enable = 0x40; /* 150 Ohm */
}
+ ddr->sdram_mode =
+ (0
+ | (add_lat << (16 + 3)) /* Additive Latency in EMRS1 */
+ | (mode_odt_enable << 16) /* ODT Enable in EMRS1 */
+ | (twr_auto_clk << 9) /* Write Recovery Autopre */
+ | (mode_caslat << 4) /* caslat */
+ | (burst_len << 0) /* Burst length */
+ );
+
+ debug("DDR: sdram_mode = 0x%08x\n", ddr->sdram_mode);
+
+
+ /*
+ * Clear EMRS2 and EMRS3.
+ */
+ ddr->sdram_mode_2 = 0;
+ debug("DDR: sdram_mode_2 = 0x%08x\n", ddr->sdram_mode_2);
+
+
/*
- * Set BSTOPRE to 0x100 for page mode
- * If auto-charge is used, set BSTOPRE = 0
+ * Determine Refresh Rate. Ignore self refresh bit on DDR I.
+ * Table from SPD Spec, Byte 12, converted to picoseconds and
+ * filled in with "default" normal values.
*/
- ddr->sdram_interval = ((tmp & 0x3fff) << 16) | 0x100;
- debug("DDR:sdram_interval=0x%08x\n", ddr->sdram_interval);
+ {
+ unsigned int refresh_clk;
+ unsigned int refresh_time_ns[8] = {
+ 15625000, /* 0 Normal 1.00x */
+ 3900000, /* 1 Reduced .25x */
+ 7800000, /* 2 Extended .50x */
+ 31300000, /* 3 Extended 2.00x */
+ 62500000, /* 4 Extended 4.00x */
+ 125000000, /* 5 Extended 8.00x */
+ 15625000, /* 6 Normal 1.00x filler */
+ 15625000, /* 7 Normal 1.00x filler */
+ };
+
+ refresh_clk = picos_to_clk(refresh_time_ns[spd.refresh & 0x7]);
+
+ /*
+ * Set BSTOPRE to 0x100 for page mode
+ * If auto-charge is used, set BSTOPRE = 0
+ */
+ ddr->sdram_interval =
+ (0
+ | (refresh_clk & 0x3fff) << 16
+ | 0x100
+ );
+ debug("DDR: sdram_interval = 0x%08x\n", ddr->sdram_interval);
+ }
/*
* Is this an ECC DDR chip?
+ * But don't mess with it if the DDR controller will init mem.
*/
-#if defined(CONFIG_DDR_ECC)
+#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
if (spd.config == 0x02) {
ddr->err_disable = 0x0000000d;
ddr->err_sbe = 0x00ff0000;
}
- debug("DDR:err_disable=0x%08x\n", ddr->err_disable);
- debug("DDR:err_sbe=0x%08x\n", ddr->err_sbe);
+ debug("DDR: err_disable = 0x%08x\n", ddr->err_disable);
+ debug("DDR: err_sbe = 0x%08x\n", ddr->err_sbe);
#endif
- asm("sync;isync;msync");
+ asm("sync;isync;msync");
udelay(500);
-#ifdef MPC85xx_DDR_SDRAM_CLK_CNTL
- /* Setup the clock control (8555 and later)
- * SDRAM_CLK_CNTL[0] = Source synchronous enable == 1
- * SDRAM_CLK_CNTL[5-7] = Clock Adjust == 3 (3/4 cycle late)
+ /*
+ * SDRAM Cfg 2
+ */
+
+ /*
+ * When ODT is enabled, Chap 9 suggests asserting ODT to
+ * internal IOs only during reads.
+ */
+ odt_cfg = 0;
+ if (odt_rd_cfg | odt_wr_cfg) {
+ odt_cfg = 0x2; /* ODT to IOs during reads */
+ }
+
+ /*
+ * Try to use differential DQS with DDR II.
*/
- ddr->sdram_clk_cntl = 0x83000000;
+ if (spd.mem_type == SPD_MEMTYPE_DDR) {
+ dqs_cfg = 0; /* No Differential DQS for DDR I */
+ } else {
+ dqs_cfg = 0x1; /* Differential DQS for DDR II */
+ }
+
+#if defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
+ /*
+ * Use the DDR controller to auto initialize memory.
+ */
+ d_init = 1;
+ ddr->sdram_data_init = CONFIG_MEM_INIT_VALUE;
+ debug("DDR: ddr_data_init = 0x%08x\n", ddr->sdram_data_init);
+#else
+ /*
+ * Memory will be initialized via DMA, or not at all.
+ */
+ d_init = 0;
+#endif
+
+ ddr->sdram_cfg_2 = (0
+ | (dqs_cfg << 26) /* Differential DQS */
+ | (odt_cfg << 21) /* ODT */
+ | (d_init << 4) /* D_INIT auto init DDR */
+ );
+
+ debug("DDR: sdram_cfg_2 = 0x%08x\n", ddr->sdram_cfg_2);
+
+
+#ifdef MPC85xx_DDR_SDRAM_CLK_CNTL
+ {
+ unsigned char clk_adjust;
+
+ /*
+ * Setup the clock control.
+ * SDRAM_CLK_CNTL[0] = Source synchronous enable == 1
+ * SDRAM_CLK_CNTL[5-7] = Clock Adjust
+ * 0110 3/4 cycle late
+ * 0111 7/8 cycle late
+ */
+ if (spd.mem_type == SPD_MEMTYPE_DDR) {
+ clk_adjust = 0x6;
+ } else {
+ clk_adjust = 0x7;
+ }
+
+ ddr->sdram_clk_cntl = (0
+ | 0x80000000
+ | (clk_adjust << 23)
+ );
+ debug("DDR: sdram_clk_cntl = 0x%08x\n", ddr->sdram_clk_cntl);
+ }
#endif
/*
- * Figure out the settings for the sdram_cfg register. Build up
- * the entire register in 'tmp' before writing since the write into
- * the register will actually enable the memory controller, and all
- * settings must be done before enabling.
+ * Figure out the settings for the sdram_cfg register.
+ * Build up the entire register in 'sdram_cfg' before writing
+ * since the write into the register will actually enable the
+ * memory controller; all settings must be done before enabling.
*
* sdram_cfg[0] = 1 (ddr sdram logic enable)
* sdram_cfg[1] = 1 (self-refresh-enable)
- * sdram_cfg[6:7] = 2 (SDRAM type = DDR SDRAM)
+ * sdram_cfg[5:7] = (SDRAM type = DDR SDRAM)
+ * 010 DDR 1 SDRAM
+ * 011 DDR 2 SDRAM
*/
- tmp = 0xc2000000;
+ sdram_type = (spd.mem_type == SPD_MEMTYPE_DDR) ? 2 : 3;
+ sdram_cfg = (0
+ | (1 << 31) /* Enable */
+ | (1 << 30) /* Self refresh */
+ | (sdram_type << 24) /* SDRAM type */
+ );
/*
* sdram_cfg[3] = RD_EN - registered DIMM enable
* A value of 0x26 indicates micron registered DIMMS (micron.com)
*/
- if (spd.mod_attr == 0x26) {
- tmp |= 0x10000000;
+ if (spd.mem_type == SPD_MEMTYPE_DDR && spd.mod_attr == 0x26) {
+ sdram_cfg |= 0x10000000; /* RD_EN */
}
#if defined(CONFIG_DDR_ECC)
@@ -369,7 +891,7 @@ spd_sdram(void)
* If the user wanted ECC (enabled via sdram_cfg[2])
*/
if (spd.config == 0x02) {
- tmp |= 0x20000000;
+ sdram_cfg |= 0x20000000; /* ECC_EN */
}
#endif
@@ -385,27 +907,160 @@ spd_sdram(void)
/*
* Enable 2T timing by setting sdram_cfg[16].
*/
- tmp |= 0x8000;
+ sdram_cfg |= 0x8000; /* 2T_EN */
#endif
}
}
- ddr->sdram_cfg = tmp;
+ /*
+ * 200 painful micro-seconds must elapse between
+ * the DDR clock setup and the DDR config enable.
+ */
+ udelay(200);
+
+ /*
+ * Go!
+ */
+ ddr->sdram_cfg = sdram_cfg;
asm("sync;isync;msync");
udelay(500);
- debug("DDR:sdram_cfg=0x%08x\n", ddr->sdram_cfg);
+ debug("DDR: sdram_cfg = 0x%08x\n", ddr->sdram_cfg);
+
+
+#if defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
+ /*
+ * Poll until memory is initialized.
+ * 512 Meg at 400 might hit this 200 times or so.
+ */
+ while ((ddr->sdram_cfg_2 & (d_init << 4)) != 0) {
+ udelay(1000);
+ }
+#endif
+
+
+ /*
+ * Figure out memory size in Megabytes.
+ */
+ memsize = n_ranks * rank_density / 0x100000;
+
+ /*
+ * Establish Local Access Window and TLB mappings for DDR memory.
+ */
+ memsize = setup_laws_and_tlbs(memsize);
+ if (memsize == 0) {
+ return 0;
+ }
return memsize * 1024 * 1024;
}
+
+
+/*
+ * Setup Local Access Window and TLB1 mappings for the requested
+ * amount of memory. Returns the amount of memory actually mapped
+ * (usually the original request size), or 0 on error.
+ */
+
+static unsigned int
+setup_laws_and_tlbs(unsigned int memsize)
+{
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+ volatile ccsr_local_ecm_t *ecm = &immap->im_local_ecm;
+ unsigned int tlb_size;
+ unsigned int law_size;
+ unsigned int ram_tlb_index;
+ unsigned int ram_tlb_address;
+
+ /*
+ * Determine size of each TLB1 entry.
+ */
+ switch (memsize) {
+ case 16:
+ case 32:
+ tlb_size = BOOKE_PAGESZ_16M;
+ break;
+ case 64:
+ case 128:
+ tlb_size = BOOKE_PAGESZ_64M;
+ break;
+ case 256:
+ case 512:
+ case 1024:
+ case 2048:
+ tlb_size = BOOKE_PAGESZ_256M;
+ break;
+ default:
+ puts("DDR: only 16M,32M,64M,128M,256M,512M,1G and 2G are supported.\n");
+
+ /*
+ * The memory was not able to be mapped.
+ */
+ return 0;
+ break;
+ }
+
+ /*
+ * Configure DDR TLB1 entries.
+ * Starting at TLB1 8, use no more than 8 TLB1 entries.
+ */
+ ram_tlb_index = 8;
+ ram_tlb_address = (unsigned int)CFG_DDR_SDRAM_BASE;
+ while (ram_tlb_address < (memsize * 1024 * 1024)
+ && ram_tlb_index < 16) {
+ mtspr(MAS0, TLB1_MAS0(1, ram_tlb_index, 0));
+ mtspr(MAS1, TLB1_MAS1(1, 1, 0, 0, tlb_size));
+ mtspr(MAS2, TLB1_MAS2(E500_TLB_EPN(ram_tlb_address),
+ 0, 0, 0, 0, 0, 0, 0, 0));
+ mtspr(MAS3, TLB1_MAS3(E500_TLB_RPN(ram_tlb_address),
+ 0, 0, 0, 0, 0, 1, 0, 1, 0, 1));
+ asm volatile("isync;msync;tlbwe;isync");
+
+ debug("DDR: MAS0=0x%08x\n", TLB1_MAS0(1, ram_tlb_index, 0));
+ debug("DDR: MAS1=0x%08x\n", TLB1_MAS1(1, 1, 0, 0, tlb_size));
+ debug("DDR: MAS2=0x%08x\n",
+ TLB1_MAS2(E500_TLB_EPN(ram_tlb_address),
+ 0, 0, 0, 0, 0, 0, 0, 0));
+ debug("DDR: MAS3=0x%08x\n",
+ TLB1_MAS3(E500_TLB_RPN(ram_tlb_address),
+ 0, 0, 0, 0, 0, 1, 0, 1, 0, 1));
+
+ ram_tlb_address += (0x1000 << ((tlb_size - 1) * 2));
+ ram_tlb_index++;
+ }
+
+
+ /*
+ * First supported LAW size is 16M, at LAWAR_SIZE_16M == 23. Fnord.
+ */
+ law_size = 19 + __ilog2(memsize);
+
+ /*
+ * Set up LAWBAR for all of DDR.
+ */
+ ecm->lawbar1 = ((CFG_DDR_SDRAM_BASE >> 12) & 0xfffff);
+ ecm->lawar1 = (LAWAR_EN
+ | LAWAR_TRGT_IF_DDR
+ | (LAWAR_SIZE & law_size));
+ debug("DDR: LAWBAR1=0x%08x\n", ecm->lawbar1);
+ debug("DDR: LARAR1=0x%08x\n", ecm->lawar1);
+
+ /*
+ * Confirm that the requested amount of memory was mapped.
+ */
+ return memsize;
+}
+
#endif /* CONFIG_SPD_EEPROM */
-#if defined(CONFIG_DDR_ECC)
+#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
+
/*
* Initialize all of memory for ECC, then enable errors.
*/
+
void
ddr_enable_ecc(unsigned int dram_size)
{
@@ -420,7 +1075,7 @@ ddr_enable_ecc(unsigned int dram_size)
if (((unsigned int)p & 0x1f) == 0) {
ppcDcbz((unsigned long) p);
}
- *p = (unsigned int)0xdeadbeef;
+ *p = (unsigned int)CONFIG_MEM_INIT_VALUE;
if (((unsigned int)p & 0x1c) == 0x1c) {
ppcDcbf((unsigned long) p);
}
@@ -454,7 +1109,10 @@ ddr_enable_ecc(unsigned int dram_size)
/*
* Enable errors for ECC.
*/
+ debug("DMA DDR: err_disable = 0x%08x\n", ddr->err_disable);
ddr->err_disable = 0x00000000;
asm("sync;isync;msync");
+ debug("DMA DDR: err_disable = 0x%08x\n", ddr->err_disable);
}
-#endif /* CONFIG_DDR_ECC */
+
+#endif /* CONFIG_DDR_ECC && ! CONFIG_ECC_INIT_VIA_DDRCONTROLLER */
diff --git a/cpu/mpc85xx/speed.c b/cpu/mpc85xx/speed.c
index 787f7fadc9..d736742f62 100644
--- a/cpu/mpc85xx/speed.c
+++ b/cpu/mpc85xx/speed.c
@@ -82,7 +82,7 @@ int get_clocks (void)
{
DECLARE_GLOBAL_DATA_PTR;
sys_info_t sys_info;
-#if defined(CONFIG_MPC8560)
+#if defined(CONFIG_CPM2)
volatile immap_t *immap = (immap_t *) CFG_IMMR;
uint sccr, dfbrg;
@@ -94,7 +94,7 @@ int get_clocks (void)
get_sys_info (&sys_info);
gd->cpu_clk = sys_info.freqProcessor;
gd->bus_clk = sys_info.freqSystemBus;
-#if defined(CONFIG_MPC8560)
+#if defined(CONFIG_CPM2)
gd->vco_out = 2*sys_info.freqSystemBus;
gd->cpm_clk = gd->vco_out / 2;
gd->scc_clk = gd->vco_out / 4;
diff --git a/cpu/mpc85xx/start.S b/cpu/mpc85xx/start.S
index 7bca008b58..5f75bc1aff 100644
--- a/cpu/mpc85xx/start.S
+++ b/cpu/mpc85xx/start.S
@@ -155,11 +155,13 @@ _start_e500:
mtspr MCSR,r0
mtspr DEAR,r0
- mtspr DBCR0,r0
+ /* not needed and conflicts with some debuggers */
+ /* mtspr DBCR0,r0 */
mtspr DBCR1,r0
mtspr DBCR2,r0
- mtspr IAC1,r0
- mtspr IAC2,r0
+ /* not needed and conflicts with some debuggers */
+ /* mtspr IAC1,r0 */
+ /* mtspr IAC2,r0 */
mtspr DAC1,r0
mtspr DAC2,r0
@@ -174,6 +176,9 @@ _start_e500:
mtspr BUCSR,r0 /* disable branch prediction */
mtspr MAS4,r0
mtspr MAS6,r0
+#if defined(CONFIG_ENABLE_36BIT_PHYS)
+ mtspr MAS7,r0
+#endif
isync
/* Setup interrupt vectors */
@@ -204,8 +209,8 @@ _start_e500:
li r1,0x0b00
mtspr IVOR11,r1 /* 11: Interval timer */
li r1,0x0c00
- mtspr IVOR12,r1 /* 11: Watchdog timer */
- li r10,0x0d00
+ mtspr IVOR12,r1 /* 12: Watchdog timer */
+ li r1,0x0d00
mtspr IVOR13,r1 /* 13: Data TLB error */
li r1,0x0e00
mtspr IVOR14,r1 /* 14: Instruction TLB error */
@@ -358,6 +363,9 @@ _start:
/* Enable Time Base and Select Time Base Clock */
lis r0,HID0_EMCP@h /* Enable machine check */
ori r0,r0,0x4000 /* time base is processor clock */
+#if defined(CONFIG_ENABLE_36BIT_PHYS)
+ ori r0,r0,0x0080 /* enable MAS7 updates */
+#endif
mtspr HID0,r0
#if defined(CONFIG_ADDR_STREAMING)
diff --git a/cpu/mpc85xx/tsec.c b/cpu/mpc85xx/tsec.c
deleted file mode 100644
index d327a6decb..0000000000
--- a/cpu/mpc85xx/tsec.c
+++ /dev/null
@@ -1,1048 +0,0 @@
-/*
- * tsec.c
- * Freescale Three Speed Ethernet Controller driver
- *
- * This software may be used and distributed according to the
- * terms of the GNU Public License, Version 2, incorporated
- * herein by reference.
- *
- * Copyright 2004 Freescale Semiconductor.
- * (C) Copyright 2003, Motorola, Inc.
- * maintained by Jon Loeliger (loeliger@freescale.com)
- * author Andy Fleming
- *
- */
-
-#include <config.h>
-#include <mpc85xx.h>
-#include <common.h>
-#include <malloc.h>
-#include <net.h>
-#include <command.h>
-
-#if defined(CONFIG_TSEC_ENET)
-#include "tsec.h"
-
-#define TX_BUF_CNT 2
-
-static uint rxIdx; /* index of the current RX buffer */
-static uint txIdx; /* index of the current TX buffer */
-
-typedef volatile struct rtxbd {
- txbd8_t txbd[TX_BUF_CNT];
- rxbd8_t rxbd[PKTBUFSRX];
-} RTXBD;
-
-struct tsec_info_struct {
- unsigned int phyaddr;
- unsigned int gigabit;
- unsigned int phyregidx;
-};
-
-
-/* The tsec_info structure contains 3 values which the
- * driver uses to determine how to operate a given ethernet
- * device. For now, the structure is initialized with the
- * knowledge that all current implementations have 2 TSEC
- * devices, and one FEC. The information needed is:
- * phyaddr - The address of the PHY which is attached to
- * the given device.
- *
- * gigabit - This variable indicates whether the device
- * supports gigabit speed ethernet
- *
- * phyregidx - This variable specifies which ethernet device
- * controls the MII Management registers which are connected
- * to the PHY. For 8540/8560, only TSEC1 (index 0) has
- * access to the PHYs, so all of the entries have "0".
- *
- * The values specified in the table are taken from the board's
- * config file in include/configs/. When implementing a new
- * board with ethernet capability, it is necessary to define:
- * TSEC1_PHY_ADDR
- * TSEC1_PHYIDX
- * TSEC2_PHY_ADDR
- * TSEC2_PHYIDX
- *
- * and for 8560:
- * FEC_PHY_ADDR
- * FEC_PHYIDX
- */
-static struct tsec_info_struct tsec_info[] = {
-#ifdef CONFIG_MPC85XX_TSEC1
- {TSEC1_PHY_ADDR, 1, TSEC1_PHYIDX},
-#else
- { 0, 0, 0},
-#endif
-#ifdef CONFIG_MPC85XX_TSEC2
- {TSEC2_PHY_ADDR, 1, TSEC2_PHYIDX},
-#else
- { 0, 0, 0},
-#endif
-#ifdef CONFIG_MPC85XX_FEC
- {FEC_PHY_ADDR, 0, FEC_PHYIDX},
-#else
- { 0, 0, 0},
-#endif
-};
-
-#define MAXCONTROLLERS 3
-
-static int relocated = 0;
-
-static struct tsec_private *privlist[MAXCONTROLLERS];
-
-#ifdef __GNUC__
-static RTXBD rtx __attribute__ ((aligned(8)));
-#else
-#error "rtx must be 64-bit aligned"
-#endif
-
-static int tsec_send(struct eth_device* dev, volatile void *packet, int length);
-static int tsec_recv(struct eth_device* dev);
-static int tsec_init(struct eth_device* dev, bd_t * bd);
-static void tsec_halt(struct eth_device* dev);
-static void init_registers(volatile tsec_t *regs);
-static void startup_tsec(struct eth_device *dev);
-static int init_phy(struct eth_device *dev);
-void write_phy_reg(struct tsec_private *priv, uint regnum, uint value);
-uint read_phy_reg(struct tsec_private *priv, uint regnum);
-struct phy_info * get_phy_info(struct eth_device *dev);
-void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd);
-static void adjust_link(struct eth_device *dev);
-static void relocate_cmds(void);
-
-/* Initialize device structure. Returns success if PHY
- * initialization succeeded (i.e. if it recognizes the PHY)
- */
-int tsec_initialize(bd_t *bis, int index)
-{
- struct eth_device* dev;
- int i;
- struct tsec_private *priv;
-
- dev = (struct eth_device*) malloc(sizeof *dev);
-
- if(NULL == dev)
- return 0;
-
- memset(dev, 0, sizeof *dev);
-
- priv = (struct tsec_private *) malloc(sizeof(*priv));
-
- if(NULL == priv)
- return 0;
-
- privlist[index] = priv;
- priv->regs = (volatile tsec_t *)(TSEC_BASE_ADDR + index*TSEC_SIZE);
- priv->phyregs = (volatile tsec_t *)(TSEC_BASE_ADDR +
- tsec_info[index].phyregidx*TSEC_SIZE);
-
- priv->phyaddr = tsec_info[index].phyaddr;
- priv->gigabit = tsec_info[index].gigabit;
-
- sprintf(dev->name, "ENET%d", index);
- dev->iobase = 0;
- dev->priv = priv;
- dev->init = tsec_init;
- dev->halt = tsec_halt;
- dev->send = tsec_send;
- dev->recv = tsec_recv;
-
- /* Tell u-boot to get the addr from the env */
- for(i=0;i<6;i++)
- dev->enetaddr[i] = 0;
-
- eth_register(dev);
-
-
- /* Reset the MAC */
- priv->regs->maccfg1 |= MACCFG1_SOFT_RESET;
- priv->regs->maccfg1 &= ~(MACCFG1_SOFT_RESET);
-
- /* Try to initialize PHY here, and return */
- return init_phy(dev);
-}
-
-
-/* Initializes data structures and registers for the controller,
- * and brings the interface up. Returns the link status, meaning
- * that it returns success if the link is up, failure otherwise.
- * This allows u-boot to find the first active controller. */
-int tsec_init(struct eth_device* dev, bd_t * bd)
-{
- uint tempval;
- char tmpbuf[MAC_ADDR_LEN];
- int i;
- struct tsec_private *priv = (struct tsec_private *)dev->priv;
- volatile tsec_t *regs = priv->regs;
-
- /* Make sure the controller is stopped */
- tsec_halt(dev);
-
- /* Init MACCFG2. Defaults to GMII */
- regs->maccfg2 = MACCFG2_INIT_SETTINGS;
-
- /* Init ECNTRL */
- regs->ecntrl = ECNTRL_INIT_SETTINGS;
-
- /* Copy the station address into the address registers.
- * Backwards, because little endian MACS are dumb */
- for(i=0;i<MAC_ADDR_LEN;i++) {
- tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->enetaddr[i];
- }
- (uint)(regs->macstnaddr1) = *((uint *)(tmpbuf));
-
- tempval = *((uint *)(tmpbuf +4));
-
- (uint)(regs->macstnaddr2) = tempval;
-
- /* reset the indices to zero */
- rxIdx = 0;
- txIdx = 0;
-
- /* Clear out (for the most part) the other registers */
- init_registers(regs);
-
- /* Ready the device for tx/rx */
- startup_tsec(dev);
-
- /* If there's no link, fail */
- return priv->link;
-
-}
-
-
-/* Write value to the device's PHY through the registers
- * specified in priv, modifying the register specified in regnum.
- * It will wait for the write to be done (or for a timeout to
- * expire) before exiting
- */
-void write_phy_reg(struct tsec_private *priv, uint regnum, uint value)
-{
- volatile tsec_t *regbase = priv->phyregs;
- uint phyid = priv->phyaddr;
- int timeout=1000000;
-
- regbase->miimadd = (phyid << 8) | regnum;
- regbase->miimcon = value;
- asm("msync");
-
- timeout=1000000;
- while((regbase->miimind & MIIMIND_BUSY) && timeout--);
-}
-
-
-/* Reads register regnum on the device's PHY through the
- * registers specified in priv. It lowers and raises the read
- * command, and waits for the data to become valid (miimind
- * notvalid bit cleared), and the bus to cease activity (miimind
- * busy bit cleared), and then returns the value
- */
-uint read_phy_reg(struct tsec_private *priv, uint regnum)
-{
- uint value;
- volatile tsec_t *regbase = priv->phyregs;
- uint phyid = priv->phyaddr;
-
- /* Put the address of the phy, and the register
- * number into MIIMADD */
- regbase->miimadd = (phyid << 8) | regnum;
-
- /* Clear the command register, and wait */
- regbase->miimcom = 0;
- asm("msync");
-
- /* Initiate a read command, and wait */
- regbase->miimcom = MIIM_READ_COMMAND;
- asm("msync");
-
- /* Wait for the the indication that the read is done */
- while((regbase->miimind & (MIIMIND_NOTVALID | MIIMIND_BUSY)));
-
- /* Grab the value read from the PHY */
- value = regbase->miimstat;
-
- return value;
-}
-
-
-/* Discover which PHY is attached to the device, and configure it
- * properly. If the PHY is not recognized, then return 0
- * (failure). Otherwise, return 1
- */
-static int init_phy(struct eth_device *dev)
-{
- struct tsec_private *priv = (struct tsec_private *)dev->priv;
- struct phy_info *curphy;
-
- /* Assign a Physical address to the TBI */
-
- {
- volatile tsec_t *regs = (volatile tsec_t *)(TSEC_BASE_ADDR);
- regs->tbipa = TBIPA_VALUE;
- regs = (volatile tsec_t *)(TSEC_BASE_ADDR + TSEC_SIZE);
- regs->tbipa = TBIPA_VALUE;
- asm("msync");
- }
-
- /* Reset MII (due to new addresses) */
- priv->phyregs->miimcfg = MIIMCFG_RESET;
- asm("msync");
- priv->phyregs->miimcfg = MIIMCFG_INIT_VALUE;
- asm("msync");
- while(priv->phyregs->miimind & MIIMIND_BUSY);
-
- if(0 == relocated)
- relocate_cmds();
-
- /* Get the cmd structure corresponding to the attached
- * PHY */
- curphy = get_phy_info(dev);
-
- if(NULL == curphy) {
- printf("%s: No PHY found\n", dev->name);
-
- return 0;
- }
-
- priv->phyinfo = curphy;
-
- phy_run_commands(priv, priv->phyinfo->config);
-
- return 1;
-}
-
-
-/* Returns which value to write to the control register. */
-/* For 10/100, the value is slightly different */
-uint mii_cr_init(uint mii_reg, struct tsec_private *priv)
-{
- if(priv->gigabit)
- return MIIM_CONTROL_INIT;
- else
- return MIIM_CR_INIT;
-}
-
-
-/* Parse the status register for link, and then do
- * auto-negotiation */
-uint mii_parse_sr(uint mii_reg, struct tsec_private *priv)
-{
- uint timeout = TSEC_TIMEOUT;
-
- if(mii_reg & MIIM_STATUS_LINK)
- priv->link = 1;
- else
- priv->link = 0;
-
- if(priv->link) {
- while((!(mii_reg & MIIM_STATUS_AN_DONE)) && timeout--)
- mii_reg = read_phy_reg(priv, MIIM_STATUS);
- }
-
- return 0;
-}
-
-
-/* Parse the 88E1011's status register for speed and duplex
- * information */
-uint mii_parse_88E1011_psr(uint mii_reg, struct tsec_private *priv)
-{
- uint speed;
-
- if(mii_reg & MIIM_88E1011_PHYSTAT_DUPLEX)
- priv->duplexity = 1;
- else
- priv->duplexity = 0;
-
- speed = (mii_reg &MIIM_88E1011_PHYSTAT_SPEED);
-
- switch(speed) {
- case MIIM_88E1011_PHYSTAT_GBIT:
- priv->speed = 1000;
- break;
- case MIIM_88E1011_PHYSTAT_100:
- priv->speed = 100;
- break;
- default:
- priv->speed = 10;
- }
-
- return 0;
-}
-
-
-/* Parse the cis8201's status register for speed and duplex
- * information */
-uint mii_parse_cis8201(uint mii_reg, struct tsec_private *priv)
-{
- uint speed;
-
- if(mii_reg & MIIM_CIS8201_AUXCONSTAT_DUPLEX)
- priv->duplexity = 1;
- else
- priv->duplexity = 0;
-
- speed = mii_reg & MIIM_CIS8201_AUXCONSTAT_SPEED;
- switch(speed) {
- case MIIM_CIS8201_AUXCONSTAT_GBIT:
- priv->speed = 1000;
- break;
- case MIIM_CIS8201_AUXCONSTAT_100:
- priv->speed = 100;
- break;
- default:
- priv->speed = 10;
- break;
- }
-
- return 0;
-}
-
-
-/* Parse the DM9161's status register for speed and duplex
- * information */
-uint mii_parse_dm9161_scsr(uint mii_reg, struct tsec_private *priv)
-{
- if(mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_100H))
- priv->speed = 100;
- else
- priv->speed = 10;
-
- if(mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_10F))
- priv->duplexity = 1;
- else
- priv->duplexity = 0;
-
- return 0;
-}
-
-
-/* Hack to write all 4 PHYs with the LED values */
-uint mii_cis8204_fixled(uint mii_reg, struct tsec_private *priv)
-{
- uint phyid;
- volatile tsec_t *regbase = priv->phyregs;
- int timeout=1000000;
-
- for(phyid=0;phyid<4;phyid++) {
- regbase->miimadd = (phyid << 8) | mii_reg;
- regbase->miimcon = MIIM_CIS8204_SLEDCON_INIT;
- asm("msync");
-
- timeout=1000000;
- while((regbase->miimind & MIIMIND_BUSY) && timeout--);
- }
-
- return MIIM_CIS8204_SLEDCON_INIT;
-}
-
-
-/* Initialized required registers to appropriate values, zeroing
- * those we don't care about (unless zero is bad, in which case,
- * choose a more appropriate value) */
-static void init_registers(volatile tsec_t *regs)
-{
- /* Clear IEVENT */
- regs->ievent = IEVENT_INIT_CLEAR;
-
- regs->imask = IMASK_INIT_CLEAR;
-
- regs->hash.iaddr0 = 0;
- regs->hash.iaddr1 = 0;
- regs->hash.iaddr2 = 0;
- regs->hash.iaddr3 = 0;
- regs->hash.iaddr4 = 0;
- regs->hash.iaddr5 = 0;
- regs->hash.iaddr6 = 0;
- regs->hash.iaddr7 = 0;
-
- regs->hash.gaddr0 = 0;
- regs->hash.gaddr1 = 0;
- regs->hash.gaddr2 = 0;
- regs->hash.gaddr3 = 0;
- regs->hash.gaddr4 = 0;
- regs->hash.gaddr5 = 0;
- regs->hash.gaddr6 = 0;
- regs->hash.gaddr7 = 0;
-
- regs->rctrl = 0x00000000;
-
- /* Init RMON mib registers */
- memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t));
-
- regs->rmon.cam1 = 0xffffffff;
- regs->rmon.cam2 = 0xffffffff;
-
- regs->mrblr = MRBLR_INIT_SETTINGS;
-
- regs->minflr = MINFLR_INIT_SETTINGS;
-
- regs->attr = ATTR_INIT_SETTINGS;
- regs->attreli = ATTRELI_INIT_SETTINGS;
-
-}
-
-
-/* Configure maccfg2 based on negotiated speed and duplex
- * reported by PHY handling code */
-static void adjust_link(struct eth_device *dev)
-{
- struct tsec_private *priv = (struct tsec_private *)dev->priv;
- volatile tsec_t *regs = priv->regs;
-
- if(priv->link) {
- if(priv->duplexity != 0)
- regs->maccfg2 |= MACCFG2_FULL_DUPLEX;
- else
- regs->maccfg2 &= ~(MACCFG2_FULL_DUPLEX);
-
- switch(priv->speed) {
- case 1000:
- regs->maccfg2 = ((regs->maccfg2&~(MACCFG2_IF))
- | MACCFG2_GMII);
- break;
- case 100:
- case 10:
- regs->maccfg2 = ((regs->maccfg2&~(MACCFG2_IF))
- | MACCFG2_MII);
- break;
- default:
- printf("%s: Speed was bad\n", dev->name);
- break;
- }
-
- printf("Speed: %d, %s duplex\n", priv->speed,
- (priv->duplexity) ? "full" : "half");
-
- } else {
- printf("%s: No link.\n", dev->name);
- }
-}
-
-
-/* Set up the buffers and their descriptors, and bring up the
- * interface */
-static void startup_tsec(struct eth_device *dev)
-{
- int i;
- struct tsec_private *priv = (struct tsec_private *)dev->priv;
- volatile tsec_t *regs = priv->regs;
-
- /* Point to the buffer descriptors */
- regs->tbase = (unsigned int)(&rtx.txbd[txIdx]);
- regs->rbase = (unsigned int)(&rtx.rxbd[rxIdx]);
-
- /* Initialize the Rx Buffer descriptors */
- for (i = 0; i < PKTBUFSRX; i++) {
- rtx.rxbd[i].status = RXBD_EMPTY;
- rtx.rxbd[i].length = 0;
- rtx.rxbd[i].bufPtr = (uint)NetRxPackets[i];
- }
- rtx.rxbd[PKTBUFSRX -1].status |= RXBD_WRAP;
-
- /* Initialize the TX Buffer Descriptors */
- for(i=0; i<TX_BUF_CNT; i++) {
- rtx.txbd[i].status = 0;
- rtx.txbd[i].length = 0;
- rtx.txbd[i].bufPtr = 0;
- }
- rtx.txbd[TX_BUF_CNT -1].status |= TXBD_WRAP;
-
- /* Start up the PHY */
- phy_run_commands(priv, priv->phyinfo->startup);
- adjust_link(dev);
-
- /* Enable Transmit and Receive */
- regs->maccfg1 |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
-
- /* Tell the DMA it is clear to go */
- regs->dmactrl |= DMACTRL_INIT_SETTINGS;
- regs->tstat = TSTAT_CLEAR_THALT;
- regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
-}
-
-/* This returns the status bits of the device. The return value
- * is never checked, and this is what the 8260 driver did, so we
- * do the same. Presumably, this would be zero if there were no
- * errors */
-static int tsec_send(struct eth_device* dev, volatile void *packet, int length)
-{
- int i;
- int result = 0;
- struct tsec_private *priv = (struct tsec_private *)dev->priv;
- volatile tsec_t *regs = priv->regs;
-
- /* Find an empty buffer descriptor */
- for(i=0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
- if (i >= TOUT_LOOP) {
- debug ("%s: tsec: tx buffers full\n", dev->name);
- return result;
- }
- }
-
- rtx.txbd[txIdx].bufPtr = (uint)packet;
- rtx.txbd[txIdx].length = length;
- rtx.txbd[txIdx].status |= (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT);
-
- /* Tell the DMA to go */
- regs->tstat = TSTAT_CLEAR_THALT;
-
- /* Wait for buffer to be transmitted */
- for(i=0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
- if (i >= TOUT_LOOP) {
- debug ("%s: tsec: tx error\n", dev->name);
- return result;
- }
- }
-
- txIdx = (txIdx + 1) % TX_BUF_CNT;
- result = rtx.txbd[txIdx].status & TXBD_STATS;
-
- return result;
-}
-
-static int tsec_recv(struct eth_device* dev)
-{
- int length;
- struct tsec_private *priv = (struct tsec_private *)dev->priv;
- volatile tsec_t *regs = priv->regs;
-
- while(!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) {
-
- length = rtx.rxbd[rxIdx].length;
-
- /* Send the packet up if there were no errors */
- if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) {
- NetReceive(NetRxPackets[rxIdx], length - 4);
- } else {
- printf("Got error %x\n",
- (rtx.rxbd[rxIdx].status & RXBD_STATS));
- }
-
- rtx.rxbd[rxIdx].length = 0;
-
- /* Set the wrap bit if this is the last element in the list */
- rtx.rxbd[rxIdx].status = RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0);
-
- rxIdx = (rxIdx + 1) % PKTBUFSRX;
- }
-
- if(regs->ievent&IEVENT_BSY) {
- regs->ievent = IEVENT_BSY;
- regs->rstat = RSTAT_CLEAR_RHALT;
- }
-
- return -1;
-
-}
-
-
-/* Stop the interface */
-static void tsec_halt(struct eth_device* dev)
-{
- struct tsec_private *priv = (struct tsec_private *)dev->priv;
- volatile tsec_t *regs = priv->regs;
-
- regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
- regs->dmactrl |= (DMACTRL_GRS | DMACTRL_GTS);
-
- while(!(regs->ievent & (IEVENT_GRSC | IEVENT_GTSC)));
-
- regs->maccfg1 &= ~(MACCFG1_TX_EN | MACCFG1_RX_EN);
-
- /* Shut down the PHY, as needed */
- phy_run_commands(priv, priv->phyinfo->shutdown);
-}
-
-
-struct phy_info phy_info_M88E1011S = {
- 0x01410c6,
- "Marvell 88E1011S",
- 4,
- (struct phy_cmd[]) { /* config */
- /* Reset and configure the PHY */
- {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
- {0x1d, 0x1f, NULL},
- {0x1e, 0x200c, NULL},
- {0x1d, 0x5, NULL},
- {0x1e, 0x0, NULL},
- {0x1e, 0x100, NULL},
- {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
- {MIIM_ANAR, MIIM_ANAR_INIT, NULL},
- {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
- {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
- {miim_end,}
- },
- (struct phy_cmd[]) { /* startup */
- /* Status is read once to clear old link state */
- {MIIM_STATUS, miim_read, NULL},
- /* Auto-negotiate */
- {MIIM_STATUS, miim_read, &mii_parse_sr},
- /* Read the status */
- {MIIM_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr},
- {miim_end,}
- },
- (struct phy_cmd[]) { /* shutdown */
- {miim_end,}
- },
-};
-
-struct phy_info phy_info_M88E1111S = {
- 0x01410cc,
- "Marvell 88E1111S",
- 4,
- (struct phy_cmd[]) { /* config */
- /* Reset and configure the PHY */
- {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
- {0x1d, 0x1f, NULL},
- {0x1e, 0x200c, NULL},
- {0x1d, 0x5, NULL},
- {0x1e, 0x0, NULL},
- {0x1e, 0x100, NULL},
- {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
- {MIIM_ANAR, MIIM_ANAR_INIT, NULL},
- {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
- {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
- {miim_end,}
- },
- (struct phy_cmd[]) { /* startup */
- /* Status is read once to clear old link state */
- {MIIM_STATUS, miim_read, NULL},
- /* Auto-negotiate */
- {MIIM_STATUS, miim_read, &mii_parse_sr},
- /* Read the status */
- {MIIM_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr},
- {miim_end,}
- },
- (struct phy_cmd[]) { /* shutdown */
- {miim_end,}
- },
-};
-
-struct phy_info phy_info_cis8204 = {
- 0x3f11,
- "Cicada Cis8204",
- 6,
- (struct phy_cmd[]) { /* config */
- /* Override PHY config settings */
- {MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
- /* Configure some basic stuff */
- {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
- {MIIM_CIS8204_SLED_CON, MIIM_CIS8204_SLEDCON_INIT, &mii_cis8204_fixled},
- {MIIM_CIS8204_EPHY_CON, MIIM_CIS8204_EPHYCON_INIT, NULL},
- {miim_end,}
- },
- (struct phy_cmd[]) { /* startup */
- /* Read the Status (2x to make sure link is right) */
- {MIIM_STATUS, miim_read, NULL},
- /* Auto-negotiate */
- {MIIM_STATUS, miim_read, &mii_parse_sr},
- /* Read the status */
- {MIIM_CIS8201_AUX_CONSTAT, miim_read, &mii_parse_cis8201},
- {miim_end,}
- },
- (struct phy_cmd[]) { /* shutdown */
- {miim_end,}
- },
-};
-
-/* Cicada 8201 */
-struct phy_info phy_info_cis8201 = {
- 0xfc41,
- "CIS8201",
- 4,
- (struct phy_cmd[]) { /* config */
- /* Override PHY config settings */
- {MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
- /* Set up the interface mode */
- {MIIM_CIS8201_EXT_CON1, MIIM_CIS8201_EXTCON1_INIT, NULL},
- /* Configure some basic stuff */
- {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
- {miim_end,}
- },
- (struct phy_cmd[]) { /* startup */
- /* Read the Status (2x to make sure link is right) */
- {MIIM_STATUS, miim_read, NULL},
- /* Auto-negotiate */
- {MIIM_STATUS, miim_read, &mii_parse_sr},
- /* Read the status */
- {MIIM_CIS8201_AUX_CONSTAT, miim_read, &mii_parse_cis8201},
- {miim_end,}
- },
- (struct phy_cmd[]) { /* shutdown */
- {miim_end,}
- },
-};
-
-
-struct phy_info phy_info_dm9161 = {
- 0x0181b88,
- "Davicom DM9161E",
- 4,
- (struct phy_cmd[]) { /* config */
- {MIIM_CONTROL, MIIM_DM9161_CR_STOP, NULL},
- /* Do not bypass the scrambler/descrambler */
- {MIIM_DM9161_SCR, MIIM_DM9161_SCR_INIT, NULL},
- /* Clear 10BTCSR to default */
- {MIIM_DM9161_10BTCSR, MIIM_DM9161_10BTCSR_INIT, NULL},
- /* Configure some basic stuff */
- {MIIM_CONTROL, MIIM_CR_INIT, NULL},
- /* Restart Auto Negotiation */
- {MIIM_CONTROL, MIIM_DM9161_CR_RSTAN, NULL},
- {miim_end,}
- },
- (struct phy_cmd[]) { /* startup */
- /* Status is read once to clear old link state */
- {MIIM_STATUS, miim_read, NULL},
- /* Auto-negotiate */
- {MIIM_STATUS, miim_read, &mii_parse_sr},
- /* Read the status */
- {MIIM_DM9161_SCSR, miim_read, &mii_parse_dm9161_scsr},
- {miim_end,}
- },
- (struct phy_cmd[]) { /* shutdown */
- {miim_end,}
- },
-};
-
-uint mii_parse_lxt971_sr2(uint mii_reg, struct tsec_private *priv)
-{
- unsigned int speed;
- if (priv->link) {
- speed = mii_reg & MIIM_LXT971_SR2_SPEED_MASK;
-
- switch (speed) {
- case MIIM_LXT971_SR2_10HDX:
- priv->speed = 10;
- priv->duplexity = 0;
- break;
- case MIIM_LXT971_SR2_10FDX:
- priv->speed = 10;
- priv->duplexity = 1;
- break;
- case MIIM_LXT971_SR2_100HDX:
- priv->speed = 100;
- priv->duplexity = 0;
- default:
- priv->speed = 100;
- priv->duplexity = 1;
- break;
- }
- } else {
- priv->speed = 0;
- priv->duplexity = 0;
- }
-
- return 0;
-}
-
-static struct phy_info phy_info_lxt971 = {
- 0x0001378e,
- "LXT971",
- 4,
- (struct phy_cmd []) { /* config */
- { MIIM_CR, MIIM_CR_INIT, mii_cr_init }, /* autonegotiate */
- { miim_end, }
- },
- (struct phy_cmd []) { /* startup - enable interrupts */
- /* { 0x12, 0x00f2, NULL }, */
- { MIIM_STATUS, miim_read, NULL },
- { MIIM_STATUS, miim_read, &mii_parse_sr },
- { MIIM_LXT971_SR2, miim_read, &mii_parse_lxt971_sr2 },
- { miim_end, }
- },
- (struct phy_cmd []) { /* shutdown - disable interrupts */
- { miim_end, }
- },
-};
-
-struct phy_info *phy_info[] = {
-#if 0
- &phy_info_cis8201,
-#endif
- &phy_info_cis8204,
- &phy_info_M88E1011S,
- &phy_info_M88E1111S,
- &phy_info_dm9161,
- &phy_info_lxt971,
- NULL
-};
-
-
-/* Grab the identifier of the device's PHY, and search through
- * all of the known PHYs to see if one matches. If so, return
- * it, if not, return NULL */
-struct phy_info * get_phy_info(struct eth_device *dev)
-{
- struct tsec_private *priv = (struct tsec_private *)dev->priv;
- uint phy_reg, phy_ID;
- int i;
- struct phy_info *theInfo = NULL;
-
- /* Grab the bits from PHYIR1, and put them in the upper half */
- phy_reg = read_phy_reg(priv, MIIM_PHYIR1);
- phy_ID = (phy_reg & 0xffff) << 16;
-
- /* Grab the bits from PHYIR2, and put them in the lower half */
- phy_reg = read_phy_reg(priv, MIIM_PHYIR2);
- phy_ID |= (phy_reg & 0xffff);
-
- /* loop through all the known PHY types, and find one that */
- /* matches the ID we read from the PHY. */
- for(i=0; phy_info[i]; i++) {
- if(phy_info[i]->id == (phy_ID >> phy_info[i]->shift))
- theInfo = phy_info[i];
- }
-
- if(theInfo == NULL)
- {
- printf("%s: PHY id %x is not supported!\n", dev->name, phy_ID);
- return NULL;
- } else {
- printf("%s: PHY is %s (%x)\n", dev->name, theInfo->name,
- phy_ID);
- }
-
- return theInfo;
-}
-
-
-/* Execute the given series of commands on the given device's
- * PHY, running functions as necessary*/
-void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd)
-{
- int i;
- uint result;
- volatile tsec_t *phyregs = priv->phyregs;
-
- phyregs->miimcfg = MIIMCFG_RESET;
-
- phyregs->miimcfg = MIIMCFG_INIT_VALUE;
-
- while(phyregs->miimind & MIIMIND_BUSY);
-
- for(i=0;cmd->mii_reg != miim_end;i++) {
- if(cmd->mii_data == miim_read) {
- result = read_phy_reg(priv, cmd->mii_reg);
-
- if(cmd->funct != NULL)
- (*(cmd->funct))(result, priv);
-
- } else {
- if(cmd->funct != NULL)
- result = (*(cmd->funct))(cmd->mii_reg, priv);
- else
- result = cmd->mii_data;
-
- write_phy_reg(priv, cmd->mii_reg, result);
-
- }
- cmd++;
- }
-}
-
-
-/* Relocate the function pointers in the phy cmd lists */
-static void relocate_cmds(void)
-{
- struct phy_cmd **cmdlistptr;
- struct phy_cmd *cmd;
- int i,j,k;
- DECLARE_GLOBAL_DATA_PTR;
-
- for(i=0; phy_info[i]; i++) {
- /* First thing's first: relocate the pointers to the
- * PHY command structures (the structs were done) */
- phy_info[i] = (struct phy_info *) ((uint)phy_info[i]
- + gd->reloc_off);
- phy_info[i]->name += gd->reloc_off;
- phy_info[i]->config =
- (struct phy_cmd *)((uint)phy_info[i]->config
- + gd->reloc_off);
- phy_info[i]->startup =
- (struct phy_cmd *)((uint)phy_info[i]->startup
- + gd->reloc_off);
- phy_info[i]->shutdown =
- (struct phy_cmd *)((uint)phy_info[i]->shutdown
- + gd->reloc_off);
-
- cmdlistptr = &phy_info[i]->config;
- j=0;
- for(;cmdlistptr <= &phy_info[i]->shutdown;cmdlistptr++) {
- k=0;
- for(cmd=*cmdlistptr;cmd->mii_reg != miim_end;cmd++) {
- /* Only relocate non-NULL pointers */
- if(cmd->funct)
- cmd->funct += gd->reloc_off;
-
- k++;
- }
- j++;
- }
- }
-
- relocated = 1;
-}
-
-
-#ifndef CONFIG_BITBANGMII
-
-struct tsec_private * get_priv_for_phy(unsigned char phyaddr)
-{
- int i;
-
- for(i=0;i<MAXCONTROLLERS;i++) {
- if(privlist[i]->phyaddr == phyaddr)
- return privlist[i];
- }
-
- return NULL;
-}
-
-/*
- * Read a MII PHY register.
- *
- * Returns:
- * 0 on success
- */
-int miiphy_read(unsigned char addr, unsigned char reg, unsigned short *value)
-{
- unsigned short ret;
- struct tsec_private *priv = get_priv_for_phy(addr);
-
- if(NULL == priv) {
- printf("Can't read PHY at address %d\n", addr);
- return -1;
- }
-
- ret = (unsigned short)read_phy_reg(priv, reg);
- *value = ret;
-
- return 0;
-}
-
-/*
- * Write a MII PHY register.
- *
- * Returns:
- * 0 on success
- */
-int miiphy_write(unsigned char addr, unsigned char reg, unsigned short value)
-{
- struct tsec_private *priv = get_priv_for_phy(addr);
-
- if(NULL == priv) {
- printf("Can't write PHY at address %d\n", addr);
- return -1;
- }
-
- write_phy_reg(priv, reg, value);
-
- return 0;
-}
-
-#endif /* CONFIG_BITBANGMII */
-
-#endif /* CONFIG_TSEC_ENET */
diff --git a/cpu/mpc85xx/tsec.h b/cpu/mpc85xx/tsec.h
deleted file mode 100644
index e24351a2e9..0000000000
--- a/cpu/mpc85xx/tsec.h
+++ /dev/null
@@ -1,486 +0,0 @@
-/*
- * tsec.h
- *
- * Driver for the Motorola Triple Speed Ethernet Controller
- *
- * This software may be used and distributed according to the
- * terms of the GNU Public License, Version 2, incorporated
- * herein by reference.
- *
- * Copyright 2004 Freescale Semiconductor.
- * (C) Copyright 2003, Motorola, Inc.
- * maintained by Xianghua Xiao (x.xiao@motorola.com)
- * author Andy Fleming
- *
- */
-
-#ifndef __TSEC_H
-#define __TSEC_H
-
-#include <net.h>
-#include <mpc85xx.h>
-
-#define TSEC_BASE_ADDR (CFG_IMMR + 0x24000)
-#define TSEC_SIZE 0x01000
-
-#define MAC_ADDR_LEN 6
-
-/* #define TSEC_TIMEOUT 1000000 */
-#define TSEC_TIMEOUT 1000
-#define TOUT_LOOP 1000000
-
-/* MAC register bits */
-#define MACCFG1_SOFT_RESET 0x80000000
-#define MACCFG1_RESET_RX_MC 0x00080000
-#define MACCFG1_RESET_TX_MC 0x00040000
-#define MACCFG1_RESET_RX_FUN 0x00020000
-#define MACCFG1_RESET_TX_FUN 0x00010000
-#define MACCFG1_LOOPBACK 0x00000100
-#define MACCFG1_RX_FLOW 0x00000020
-#define MACCFG1_TX_FLOW 0x00000010
-#define MACCFG1_SYNCD_RX_EN 0x00000008
-#define MACCFG1_RX_EN 0x00000004
-#define MACCFG1_SYNCD_TX_EN 0x00000002
-#define MACCFG1_TX_EN 0x00000001
-
-#define MACCFG2_INIT_SETTINGS 0x00007205
-#define MACCFG2_FULL_DUPLEX 0x00000001
-#define MACCFG2_IF 0x00000300
-#define MACCFG2_GMII 0x00000200
-#define MACCFG2_MII 0x00000100
-
-#define ECNTRL_INIT_SETTINGS 0x00001000
-#define ECNTRL_TBI_MODE 0x00000020
-
-#define miim_end -2
-#define miim_read -1
-
-#define TBIPA_VALUE 0x1f
-#define MIIMCFG_INIT_VALUE 0x00000003
-#define MIIMCFG_RESET 0x80000000
-
-#define MIIMIND_BUSY 0x00000001
-#define MIIMIND_NOTVALID 0x00000004
-
-#define MIIM_CONTROL 0x00
-#define MIIM_CONTROL_RESET 0x00009140
-#define MIIM_CONTROL_INIT 0x00001140
-#define MIIM_ANEN 0x00001000
-
-#define MIIM_CR 0x00
-#define MIIM_CR_RST 0x00008000
-#define MIIM_CR_INIT 0x00001000
-
-#define MIIM_STATUS 0x1
-#define MIIM_STATUS_AN_DONE 0x00000020
-#define MIIM_STATUS_LINK 0x0004
-
-#define MIIM_PHYIR1 0x2
-#define MIIM_PHYIR2 0x3
-
-#define MIIM_ANAR 0x4
-#define MIIM_ANAR_INIT 0x1e1
-
-#define MIIM_TBI_ANLPBPA 0x5
-#define MIIM_TBI_ANLPBPA_HALF 0x00000040
-#define MIIM_TBI_ANLPBPA_FULL 0x00000020
-
-#define MIIM_TBI_ANEX 0x6
-#define MIIM_TBI_ANEX_NP 0x00000004
-#define MIIM_TBI_ANEX_PRX 0x00000002
-
-#define MIIM_GBIT_CONTROL 0x9
-#define MIIM_GBIT_CONTROL_INIT 0xe00
-
-/* Cicada Auxiliary Control/Status Register */
-#define MIIM_CIS8201_AUX_CONSTAT 0x1c
-#define MIIM_CIS8201_AUXCONSTAT_INIT 0x0004
-#define MIIM_CIS8201_AUXCONSTAT_DUPLEX 0x0020
-#define MIIM_CIS8201_AUXCONSTAT_SPEED 0x0018
-#define MIIM_CIS8201_AUXCONSTAT_GBIT 0x0010
-#define MIIM_CIS8201_AUXCONSTAT_100 0x0008
-
-/* Cicada Extended Control Register 1 */
-#define MIIM_CIS8201_EXT_CON1 0x17
-#define MIIM_CIS8201_EXTCON1_INIT 0x0000
-
-/* Cicada 8204 Extended PHY Control Register 1 */
-#define MIIM_CIS8204_EPHY_CON 0x17
-#define MIIM_CIS8204_EPHYCON_INIT 0x0006
-
-/* Cicada 8204 Serial LED Control Register */
-#define MIIM_CIS8204_SLED_CON 0x1b
-#define MIIM_CIS8204_SLEDCON_INIT 0x1115
-
-#define MIIM_GBIT_CON 0x09
-#define MIIM_GBIT_CON_ADVERT 0x0e00
-
-/* 88E1011 PHY Status Register */
-#define MIIM_88E1011_PHY_STATUS 0x11
-#define MIIM_88E1011_PHYSTAT_SPEED 0xc000
-#define MIIM_88E1011_PHYSTAT_GBIT 0x8000
-#define MIIM_88E1011_PHYSTAT_100 0x4000
-#define MIIM_88E1011_PHYSTAT_DUPLEX 0x2000
-#define MIIM_88E1011_PHYSTAT_SPDDONE 0x0800
-#define MIIM_88E1011_PHYSTAT_LINK 0x0400
-
-/* DM9161 Control register values */
-#define MIIM_DM9161_CR_STOP 0x0400
-#define MIIM_DM9161_CR_RSTAN 0x1200
-
-#define MIIM_DM9161_SCR 0x10
-#define MIIM_DM9161_SCR_INIT 0x0610
-
-/* DM9161 Specified Configuration and Status Register */
-#define MIIM_DM9161_SCSR 0x11
-#define MIIM_DM9161_SCSR_100F 0x8000
-#define MIIM_DM9161_SCSR_100H 0x4000
-#define MIIM_DM9161_SCSR_10F 0x2000
-#define MIIM_DM9161_SCSR_10H 0x1000
-
-/* DM9161 10BT Configuration/Status */
-#define MIIM_DM9161_10BTCSR 0x12
-#define MIIM_DM9161_10BTCSR_INIT 0x7800
-
-/* LXT971 Status 2 registers */
-#define MIIM_LXT971_SR2 17 /* Status Register 2 */
-#define MIIM_LXT971_SR2_SPEED_MASK 0xf000
-#define MIIM_LXT971_SR2_10HDX 0x1000 /* 10 Mbit half duplex selected */
-#define MIIM_LXT971_SR2_10FDX 0x2000 /* 10 Mbit full duplex selected */
-#define MIIM_LXT971_SR2_100HDX 0x4000 /* 100 Mbit half duplex selected */
-#define MIIM_LXT971_SR2_100FDX 0x8000 /* 100 Mbit full duplex selected */
-
-#define MIIM_READ_COMMAND 0x00000001
-
-#define MRBLR_INIT_SETTINGS PKTSIZE_ALIGN
-
-#define MINFLR_INIT_SETTINGS 0x00000040
-
-#define DMACTRL_INIT_SETTINGS 0x000000c3
-#define DMACTRL_GRS 0x00000010
-#define DMACTRL_GTS 0x00000008
-
-#define TSTAT_CLEAR_THALT 0x80000000
-#define RSTAT_CLEAR_RHALT 0x00800000
-
-
-#define IEVENT_INIT_CLEAR 0xffffffff
-#define IEVENT_BABR 0x80000000
-#define IEVENT_RXC 0x40000000
-#define IEVENT_BSY 0x20000000
-#define IEVENT_EBERR 0x10000000
-#define IEVENT_MSRO 0x04000000
-#define IEVENT_GTSC 0x02000000
-#define IEVENT_BABT 0x01000000
-#define IEVENT_TXC 0x00800000
-#define IEVENT_TXE 0x00400000
-#define IEVENT_TXB 0x00200000
-#define IEVENT_TXF 0x00100000
-#define IEVENT_IE 0x00080000
-#define IEVENT_LC 0x00040000
-#define IEVENT_CRL 0x00020000
-#define IEVENT_XFUN 0x00010000
-#define IEVENT_RXB0 0x00008000
-#define IEVENT_GRSC 0x00000100
-#define IEVENT_RXF0 0x00000080
-
-#define IMASK_INIT_CLEAR 0x00000000
-#define IMASK_TXEEN 0x00400000
-#define IMASK_TXBEN 0x00200000
-#define IMASK_TXFEN 0x00100000
-#define IMASK_RXFEN0 0x00000080
-
-
-/* Default Attribute fields */
-#define ATTR_INIT_SETTINGS 0x000000c0
-#define ATTRELI_INIT_SETTINGS 0x00000000
-
-
-/* TxBD status field bits */
-#define TXBD_READY 0x8000
-#define TXBD_PADCRC 0x4000
-#define TXBD_WRAP 0x2000
-#define TXBD_INTERRUPT 0x1000
-#define TXBD_LAST 0x0800
-#define TXBD_CRC 0x0400
-#define TXBD_DEF 0x0200
-#define TXBD_HUGEFRAME 0x0080
-#define TXBD_LATECOLLISION 0x0080
-#define TXBD_RETRYLIMIT 0x0040
-#define TXBD_RETRYCOUNTMASK 0x003c
-#define TXBD_UNDERRUN 0x0002
-#define TXBD_STATS 0x03ff
-
-/* RxBD status field bits */
-#define RXBD_EMPTY 0x8000
-#define RXBD_RO1 0x4000
-#define RXBD_WRAP 0x2000
-#define RXBD_INTERRUPT 0x1000
-#define RXBD_LAST 0x0800
-#define RXBD_FIRST 0x0400
-#define RXBD_MISS 0x0100
-#define RXBD_BROADCAST 0x0080
-#define RXBD_MULTICAST 0x0040
-#define RXBD_LARGE 0x0020
-#define RXBD_NONOCTET 0x0010
-#define RXBD_SHORT 0x0008
-#define RXBD_CRCERR 0x0004
-#define RXBD_OVERRUN 0x0002
-#define RXBD_TRUNCATED 0x0001
-#define RXBD_STATS 0x003f
-
-typedef struct txbd8
-{
- ushort status; /* Status Fields */
- ushort length; /* Buffer length */
- uint bufPtr; /* Buffer Pointer */
-} txbd8_t;
-
-typedef struct rxbd8
-{
- ushort status; /* Status Fields */
- ushort length; /* Buffer Length */
- uint bufPtr; /* Buffer Pointer */
-} rxbd8_t;
-
-typedef struct rmon_mib
-{
- /* Transmit and Receive Counters */
- uint tr64; /* Transmit and Receive 64-byte Frame Counter */
- uint tr127; /* Transmit and Receive 65-127 byte Frame Counter */
- uint tr255; /* Transmit and Receive 128-255 byte Frame Counter */
- uint tr511; /* Transmit and Receive 256-511 byte Frame Counter */
- uint tr1k; /* Transmit and Receive 512-1023 byte Frame Counter */
- uint trmax; /* Transmit and Receive 1024-1518 byte Frame Counter */
- uint trmgv; /* Transmit and Receive 1519-1522 byte Good VLAN Frame */
- /* Receive Counters */
- uint rbyt; /* Receive Byte Counter */
- uint rpkt; /* Receive Packet Counter */
- uint rfcs; /* Receive FCS Error Counter */
- uint rmca; /* Receive Multicast Packet (Counter) */
- uint rbca; /* Receive Broadcast Packet */
- uint rxcf; /* Receive Control Frame Packet */
- uint rxpf; /* Receive Pause Frame Packet */
- uint rxuo; /* Receive Unknown OP Code */
- uint raln; /* Receive Alignment Error */
- uint rflr; /* Receive Frame Length Error */
- uint rcde; /* Receive Code Error */
- uint rcse; /* Receive Carrier Sense Error */
- uint rund; /* Receive Undersize Packet */
- uint rovr; /* Receive Oversize Packet */
- uint rfrg; /* Receive Fragments */
- uint rjbr; /* Receive Jabber */
- uint rdrp; /* Receive Drop */
- /* Transmit Counters */
- uint tbyt; /* Transmit Byte Counter */
- uint tpkt; /* Transmit Packet */
- uint tmca; /* Transmit Multicast Packet */
- uint tbca; /* Transmit Broadcast Packet */
- uint txpf; /* Transmit Pause Control Frame */
- uint tdfr; /* Transmit Deferral Packet */
- uint tedf; /* Transmit Excessive Deferral Packet */
- uint tscl; /* Transmit Single Collision Packet */
- /* (0x2_n700) */
- uint tmcl; /* Transmit Multiple Collision Packet */
- uint tlcl; /* Transmit Late Collision Packet */
- uint txcl; /* Transmit Excessive Collision Packet */
- uint tncl; /* Transmit Total Collision */
-
- uint res2;
-
- uint tdrp; /* Transmit Drop Frame */
- uint tjbr; /* Transmit Jabber Frame */
- uint tfcs; /* Transmit FCS Error */
- uint txcf; /* Transmit Control Frame */
- uint tovr; /* Transmit Oversize Frame */
- uint tund; /* Transmit Undersize Frame */
- uint tfrg; /* Transmit Fragments Frame */
- /* General Registers */
- uint car1; /* Carry Register One */
- uint car2; /* Carry Register Two */
- uint cam1; /* Carry Register One Mask */
- uint cam2; /* Carry Register Two Mask */
-} rmon_mib_t;
-
-typedef struct tsec_hash_regs
-{
- uint iaddr0; /* Individual Address Register 0 */
- uint iaddr1; /* Individual Address Register 1 */
- uint iaddr2; /* Individual Address Register 2 */
- uint iaddr3; /* Individual Address Register 3 */
- uint iaddr4; /* Individual Address Register 4 */
- uint iaddr5; /* Individual Address Register 5 */
- uint iaddr6; /* Individual Address Register 6 */
- uint iaddr7; /* Individual Address Register 7 */
- uint res1[24];
- uint gaddr0; /* Group Address Register 0 */
- uint gaddr1; /* Group Address Register 1 */
- uint gaddr2; /* Group Address Register 2 */
- uint gaddr3; /* Group Address Register 3 */
- uint gaddr4; /* Group Address Register 4 */
- uint gaddr5; /* Group Address Register 5 */
- uint gaddr6; /* Group Address Register 6 */
- uint gaddr7; /* Group Address Register 7 */
- uint res2[24];
-} tsec_hash_t;
-
-typedef struct tsec
-{
- /* General Control and Status Registers (0x2_n000) */
- uint res000[4];
-
- uint ievent; /* Interrupt Event */
- uint imask; /* Interrupt Mask */
- uint edis; /* Error Disabled */
- uint res01c;
- uint ecntrl; /* Ethernet Control */
- uint minflr; /* Minimum Frame Length */
- uint ptv; /* Pause Time Value */
- uint dmactrl; /* DMA Control */
- uint tbipa; /* TBI PHY Address */
-
- uint res034[3];
- uint res040[48];
-
- /* Transmit Control and Status Registers (0x2_n100) */
- uint tctrl; /* Transmit Control */
- uint tstat; /* Transmit Status */
- uint res108;
- uint tbdlen; /* Tx BD Data Length */
- uint res110[5];
- uint ctbptr; /* Current TxBD Pointer */
- uint res128[23];
- uint tbptr; /* TxBD Pointer */
- uint res188[30];
- /* (0x2_n200) */
- uint res200;
- uint tbase; /* TxBD Base Address */
- uint res208[42];
- uint ostbd; /* Out of Sequence TxBD */
- uint ostbdp; /* Out of Sequence Tx Data Buffer Pointer */
- uint res2b8[18];
-
- /* Receive Control and Status Registers (0x2_n300) */
- uint rctrl; /* Receive Control */
- uint rstat; /* Receive Status */
- uint res308;
- uint rbdlen; /* RxBD Data Length */
- uint res310[4];
- uint res320;
- uint crbptr; /* Current Receive Buffer Pointer */
- uint res328[6];
- uint mrblr; /* Maximum Receive Buffer Length */
- uint res344[16];
- uint rbptr; /* RxBD Pointer */
- uint res388[30];
- /* (0x2_n400) */
- uint res400;
- uint rbase; /* RxBD Base Address */
- uint res408[62];
-
- /* MAC Registers (0x2_n500) */
- uint maccfg1; /* MAC Configuration #1 */
- uint maccfg2; /* MAC Configuration #2 */
- uint ipgifg; /* Inter Packet Gap/Inter Frame Gap */
- uint hafdup; /* Half-duplex */
- uint maxfrm; /* Maximum Frame */
- uint res514;
- uint res518;
-
- uint res51c;
-
- uint miimcfg; /* MII Management: Configuration */
- uint miimcom; /* MII Management: Command */
- uint miimadd; /* MII Management: Address */
- uint miimcon; /* MII Management: Control */
- uint miimstat; /* MII Management: Status */
- uint miimind; /* MII Management: Indicators */
-
- uint res538;
-
- uint ifstat; /* Interface Status */
- uint macstnaddr1; /* Station Address, part 1 */
- uint macstnaddr2; /* Station Address, part 2 */
- uint res548[46];
-
- /* (0x2_n600) */
- uint res600[32];
-
- /* RMON MIB Registers (0x2_n680-0x2_n73c) */
- rmon_mib_t rmon;
- uint res740[48];
-
- /* Hash Function Registers (0x2_n800) */
- tsec_hash_t hash;
-
- uint res900[128];
-
- /* Pattern Registers (0x2_nb00) */
- uint resb00[62];
- uint attr; /* Default Attribute Register */
- uint attreli; /* Default Attribute Extract Length and Index */
-
- /* TSEC Future Expansion Space (0x2_nc00-0x2_nffc) */
- uint resc00[256];
-} tsec_t;
-
-struct tsec_private {
- volatile tsec_t *regs;
- volatile tsec_t *phyregs;
- struct phy_info *phyinfo;
- uint phyaddr;
- uint gigabit;
- uint link;
- uint duplexity;
- uint speed;
-};
-
-
-/*
- * struct phy_cmd: A command for reading or writing a PHY register
- *
- * mii_reg: The register to read or write
- *
- * mii_data: For writes, the value to put in the register.
- * A value of -1 indicates this is a read.
- *
- * funct: A function pointer which is invoked for each command.
- * For reads, this function will be passed the value read
- * from the PHY, and process it.
- * For writes, the result of this function will be written
- * to the PHY register
- */
-struct phy_cmd {
- uint mii_reg;
- uint mii_data;
- uint (*funct) (uint mii_reg, struct tsec_private* priv);
-};
-
-/* struct phy_info: a structure which defines attributes for a PHY
- *
- * id will contain a number which represents the PHY. During
- * startup, the driver will poll the PHY to find out what its
- * UID--as defined by registers 2 and 3--is. The 32-bit result
- * gotten from the PHY will be shifted right by "shift" bits to
- * discard any bits which may change based on revision numbers
- * unimportant to functionality
- *
- * The struct phy_cmd entries represent pointers to an arrays of
- * commands which tell the driver what to do to the PHY.
- */
-struct phy_info {
- uint id;
- char *name;
- uint shift;
- /* Called to configure the PHY, and modify the controller
- * based on the results */
- struct phy_cmd *config;
-
- /* Called when starting up the controller */
- struct phy_cmd *startup;
-
- /* Called when bringing down the controller */
- struct phy_cmd *shutdown;
-};
-
-#endif /* __TSEC_H */
diff --git a/cpu/mpc8xx/lcd.c b/cpu/mpc8xx/lcd.c
index cc58676868..3c64a9ba4e 100644
--- a/cpu/mpc8xx/lcd.c
+++ b/cpu/mpc8xx/lcd.c
@@ -46,12 +46,13 @@
/************************************************************************/
/* ** CONFIG STUFF -- should be moved to board config file */
/************************************************************************/
-#define CONFIG_LCD_LOGO
-#define LCD_INFO /* Display Logo, (C) and system info */
+#ifndef CONFIG_LCD_INFO
+#define CONFIG_LCD_INFO /* Display Logo, (C) and system info */
+#endif
#if defined(CONFIG_V37) || defined(CONFIG_EDT32F10)
#undef CONFIG_LCD_LOGO
-#undef LCD_INFO
+#undef CONFIG_LCD_INFO
#endif
/*----------------------------------------------------------------------*/
@@ -155,7 +156,7 @@ vidinfo_t panel_info = {
3, 0, 0, 1, 1, 15, 4, 0, 3
/* wbl, vpw, lcdac, wbf */
};
-#define LCD_INFO_BELOW_LOGO
+#define CONFIG_LCD_INFO_BELOW_LOGO
#endif /* CONFIG_SHARP_LQ057Q3DC02 */
/*----------------------------------------------------------------------*/
@@ -179,7 +180,7 @@ vidinfo_t panel_info = {
3, 0, 0, 1, 1, 248, 4, 0, 35
/* wbl, vpw, lcdac, wbf */
};
-#define LCD_INFO_BELOW_LOGO
+#define CONFIG_LCD_INFO_BELOW_LOGO
#endif /* CONFIG_SHARP_LQ065T9DR51U */
#ifdef CONFIG_SHARP_LQ084V1DG21
diff --git a/cpu/mpc8xx/speed.c b/cpu/mpc8xx/speed.c
index 95003ed9c1..f03831617c 100644
--- a/cpu/mpc8xx/speed.c
+++ b/cpu/mpc8xx/speed.c
@@ -25,7 +25,7 @@
#include <mpc8xx.h>
#include <asm/processor.h>
-#if !defined(CONFIG_8xx_CPUCLK_DEFAULT) || defined(CFG_MEASURE_CPUCLK)
+#if !defined(CONFIG_8xx_CPUCLK_DEFAULT) || defined(CFG_MEASURE_CPUCLK) || defined(DEBUG)
#define PITC_SHIFT 16
#define PITR_SHIFT 16
diff --git a/cpu/ppc4xx/405gp_enet.c b/cpu/ppc4xx/405gp_enet.c
index 9d8e2b6ded..968f0ced44 100644
--- a/cpu/ppc4xx/405gp_enet.c
+++ b/cpu/ppc4xx/405gp_enet.c
@@ -166,7 +166,6 @@ static void ppc_4xx_eth_halt (struct eth_device *dev)
failsafe--;
if (failsafe == 0)
break;
-
}
/* EMAC RESET */
@@ -223,13 +222,19 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
#endif
/* MAL RESET */
- mtdcr (malmcr, MAL_CR_MMSR);
- /* wait for reset */
- while (mfdcr (malmcr) & MAL_CR_MMSR) {
- };
-#if defined(CONFIG_440)
- /* set RMII mode */
- out32 (ZMII_FER, ZMII_RMII | ZMII_MDI0);
+ mtdcr (malmcr, MAL_CR_MMSR);
+ /* wait for reset */
+ while (mfdcr (malmcr) & MAL_CR_MMSR) {
+ };
+
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+ out32 (ZMII_FER, 0);
+ udelay(100);
+ /* set RII mode */
+ out32 (ZMII_FER, ZMII_RMII | ZMII_MDI0);
+#elif defined(CONFIG_440)
+ /* set RMII mode */
+ out32 (ZMII_FER, ZMII_RMII | ZMII_MDI0);
#endif /* CONFIG_440 */
/* MAL Channel RESET */
@@ -319,14 +324,11 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
(int) speed, (duplex == HALF) ? "HALF" : "FULL");
}
-#if defined(CONFIG_440)
- /* Errata 1.12: MAL_1 -- Disable MAL bursting */
- if( get_pvr() == PVR_440GP_RB)
- mtdcr (malmcr, MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT);
- else
-#else
mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT);
-#endif
+ /* Errata 1.12: MAL_1 -- Disable MAL bursting */
+ if (get_pvr() == PVR_440GP_RB) {
+ mtdcr (malmcr, mfdcr(malmcr) & ~MAL_CR_PLBB);
+ }
/* Free "old" buffers */
if (hw_p->alloc_tx_buf)
@@ -413,6 +415,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
reg |= dev->enetaddr[5];
out32 (EMAC_IAL + hw_p->hw_addr, reg);
+
switch (devnum) {
#if defined(CONFIG_NET_MULTI)
case 1:
@@ -461,6 +464,18 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
out32(ZMII_SSR, in32(ZMII_SSR) | 0x10000000);
else
out32(ZMII_SSR, in32(ZMII_SSR) & ~0x10000000);
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+ mfsdr(sdr_mfr, reg);
+ /* set speed */
+ if (speed == _100BASET) {
+ out32(ZMII_SSR, in32(ZMII_SSR) | 0x10000000);
+ reg = (reg & ~SDR0_MFR_ZMII_MODE_MASK) | SDR0_MFR_ZMII_MODE_RMII_100M;
+ } else {
+ reg = (reg & ~SDR0_MFR_ZMII_MODE_MASK) | SDR0_MFR_ZMII_MODE_RMII_10M;
+ out32(ZMII_SSR, in32(ZMII_SSR) & ~0x10000000);
+ }
+ mtsdr(sdr_mfr, reg);
+#endif
#endif
/* Enable broadcast and indvidual address */
@@ -481,7 +496,6 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
out32 (EMAC_RX_HI_LO_WMARK + hw_p->hw_addr, 0x0f002000);
#endif
-
/* Frame gap set */
out32 (EMAC_I_FRAME_GAP_REG + hw_p->hw_addr, 0x00000008);
@@ -498,11 +512,6 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
/*
* Connect interrupt service routines
*/
-#if !defined(CONFIG_405EP)
- /* 405EP has one EWU interrupt */
- irq_install_handler (VECNUM_EWU0 + (hw_p->devnum * 2),
- (interrupt_handler_t *) enetInt, dev);
-#endif
irq_install_handler (VECNUM_ETH0 + (hw_p->devnum * 2),
(interrupt_handler_t *) enetInt, dev);
}
@@ -993,12 +1002,6 @@ int ppc_4xx_eth_initialize (bd_t * bis)
mtdcr (malrxdeir, 0xffffffff); /* clear pending interrupts */
mtdcr (malier, mal_ier);
-#if defined(CONFIG_405EP)
- /* 405EP has one EWU interrupt */
- irq_install_handler (VECNUM_EWU0,
- (interrupt_handler_t *) enetInt,
- dev);
-#endif
/* install MAL interrupt handler */
irq_install_handler (VECNUM_MS,
(interrupt_handler_t *) enetInt,
diff --git a/cpu/ppc4xx/405gp_pci.c b/cpu/ppc4xx/405gp_pci.c
index 4f1754ade3..89be137a86 100644
--- a/cpu/ppc4xx/405gp_pci.c
+++ b/cpu/ppc4xx/405gp_pci.c
@@ -437,7 +437,7 @@ void pci_440_init (struct pci_controller *hose)
* The PCI initialization sequence enable bit must be set ... if not abort
* pci setup since updating the bit requires chip reset.
*--------------------------------------------------------------------------*/
-#if defined (CONFIG_440_GX)
+#if defined (CONFIG_440GX) || defined (CONFIG_440EP) || defined(CONFIG_440GR)
mfsdr(sdr_sdstp1,strap);
if ( (strap & 0x00010000) == 0 ){
printf("PCI: SDR0_STRP1[PISE] not set.\n");
@@ -495,10 +495,10 @@ void pci_440_init (struct pci_controller *hose)
out16r( PCIX0_CLS, 0x00060000 ); /* Bridge, host bridge */
#endif
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX)
out32r( PCIX0_BRDGOPT1, 0x04000060 ); /* PLB Rq pri highest */
out32r( PCIX0_BRDGOPT2, in32(PCIX0_BRDGOPT2) | 0x83 ); /* Enable host config, clear Timeout, ensure int src1 */
-#else
+#elif defined(PCIX0_BRDGOPT1)
out32r( PCIX0_BRDGOPT1, 0x10000060 ); /* PLB Rq pri highest */
out32r( PCIX0_BRDGOPT2, in32(PCIX0_BRDGOPT2) | 1 ); /* Enable host config */
#endif
@@ -531,7 +531,9 @@ void pci_440_init (struct pci_controller *hose)
#ifdef CONFIG_PCI_SCAN_SHOW
printf("PCI: Bus Dev VenId DevId Class Int\n");
#endif
+#if !defined(CONFIG_440EP) && !defined(CONFIG_440GR)
out16r( PCIX0_CMD, in16r( PCIX0_CMD ) | PCI_COMMAND_MASTER);
+#endif
hose->last_busno = pci_hose_scan(hose);
}
}
diff --git a/cpu/ppc4xx/440gx_enet.c b/cpu/ppc4xx/440gx_enet.c
index 871f83b96e..d0b6c15864 100644
--- a/cpu/ppc4xx/440gx_enet.c
+++ b/cpu/ppc4xx/440gx_enet.c
@@ -167,13 +167,15 @@ static void ppc_440x_eth_halt (struct eth_device *dev)
/* EMAC RESET */
out32 (EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST);
+ hw_p->print_speed = 1; /* print speed message again next time */
+
return;
}
extern int phy_setup_aneg (unsigned char addr);
extern int miiphy_reset (unsigned char addr);
-#if defined (CONFIG_440_GX)
+#if defined (CONFIG_440GX)
int ppc_440x_eth_setup_bridge(int devnum, bd_t * bis)
{
unsigned long pfc1;
@@ -267,7 +269,7 @@ int ppc_440x_eth_setup_bridge(int devnum, bd_t * bis)
static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
{
- int i;
+ int i, j;
unsigned long reg;
unsigned long msr;
unsigned long speed;
@@ -277,7 +279,9 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
unsigned short devnum;
unsigned short reg_short;
sys_info_t sysinfo;
+#if defined(CONFIG_440GX)
int ethgroup;
+#endif
EMAC_440GX_HW_PST hw_p = dev->priv;
@@ -289,7 +293,6 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
/* Need to get the OPB frequency so we can access the PHY */
get_sys_info (&sysinfo);
-
msr = mfmsr ();
mtmsr (msr & ~(MSR_EE)); /* disable interrupts */
@@ -320,7 +323,12 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
/* MAL Channel RESET */
/* 1st reset MAL channel */
/* Note: writing a 0 to a channel has no effect */
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+ mtdcr (maltxcarr, (MAL_TXRX_CASR >> (hw_p->devnum*2)));
+#else
mtdcr (maltxcarr, (MAL_TXRX_CASR >> hw_p->devnum));
+#endif
+
mtdcr (malrxcarr, (MAL_TXRX_CASR >> hw_p->devnum));
/* wait for reset */
@@ -354,7 +362,9 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
out32 (ZMII_FER, 0);
udelay (100);
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+ out32 (ZMII_FER, (ZMII_FER_RMII | ZMII_FER_MDI) << ZMII_FER_V (devnum));
+#elif defined(CONFIG_440GX)
ethgroup = ppc_440x_eth_setup_bridge(devnum, bis);
#else
if ((devnum == 0) || (devnum == 1)) {
@@ -365,8 +375,8 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
out32 (RGMII_FER, ((RGMII_FER_RGMII << RGMII_FER_V (2)) |
(RGMII_FER_RGMII << RGMII_FER_V (3))));
}
-
#endif
+
out32 (ZMII_SSR, ZMII_SSR_SP << ZMII_SSR_V(devnum));
__asm__ volatile ("eieio");
@@ -381,6 +391,7 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
failsafe--;
}
+#if defined(CONFIG_440GX)
/* Whack the M1 register */
mode_reg = 0x0;
mode_reg &= ~0x00000038;
@@ -395,7 +406,7 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
mode_reg |= EMAC_M1_OBCI_GT100;
out32 (EMAC_M1 + hw_p->hw_addr, mode_reg);
-
+#endif /* defined(CONFIG_440GX) */
/* wait for PHY to complete auto negotiation */
reg_short = 0;
@@ -407,7 +418,7 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
case 1:
reg = CONFIG_PHY1_ADDR;
break;
-#if defined (CONFIG_440_GX)
+#if defined (CONFIG_440GX)
case 2:
reg = CONFIG_PHY2_ADDR;
break;
@@ -422,6 +433,7 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
bis->bi_phynum[devnum] = reg;
+#ifndef CONFIG_NO_PHY_RESET
/*
* Reset the phy, only if its the first time through
* otherwise, just check the speeds & feeds
@@ -429,37 +441,42 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
if (hw_p->first_init == 0) {
miiphy_reset (reg);
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX)
#if defined(CONFIG_CIS8201_PHY)
- /*
- * Cicada 8201 PHY needs to have an extended register whacked
- * for RGMII mode.
- */
- if ( ((devnum == 2) || (devnum ==3)) && (4 == ethgroup) ) {
- miiphy_write (reg, 23, 0x1200);
/*
- * Vitesse VSC8201/Cicada CIS8201 errata:
- * Interoperability problem with Intel 82547EI phys
- * This work around (provided by Vitesse) changes
- * the default timer convergence from 8ms to 12ms
+ * Cicada 8201 PHY needs to have an extended register whacked
+ * for RGMII mode.
*/
- miiphy_write (reg, 0x1f, 0x2a30);
- miiphy_write (reg, 0x08, 0x0200);
- miiphy_write (reg, 0x1f, 0x52b5);
- miiphy_write (reg, 0x02, 0x0004);
- miiphy_write (reg, 0x01, 0x0671);
- miiphy_write (reg, 0x00, 0x8fae);
- miiphy_write (reg, 0x1f, 0x2a30);
- miiphy_write (reg, 0x08, 0x0000);
- miiphy_write (reg, 0x1f, 0x0000);
- /* end Vitesse/Cicada errata */
- }
+ if ( ((devnum == 2) || (devnum ==3)) && (4 == ethgroup) ) {
+#if defined(CONFIG_CIS8201_SHORT_ETCH)
+ miiphy_write (reg, 23, 0x1300);
+#else
+ miiphy_write (reg, 23, 0x1000);
+#endif
+ /*
+ * Vitesse VSC8201/Cicada CIS8201 errata:
+ * Interoperability problem with Intel 82547EI phys
+ * This work around (provided by Vitesse) changes
+ * the default timer convergence from 8ms to 12ms
+ */
+ miiphy_write (reg, 0x1f, 0x2a30);
+ miiphy_write (reg, 0x08, 0x0200);
+ miiphy_write (reg, 0x1f, 0x52b5);
+ miiphy_write (reg, 0x02, 0x0004);
+ miiphy_write (reg, 0x01, 0x0671);
+ miiphy_write (reg, 0x00, 0x8fae);
+ miiphy_write (reg, 0x1f, 0x2a30);
+ miiphy_write (reg, 0x08, 0x0000);
+ miiphy_write (reg, 0x1f, 0x0000);
+ /* end Vitesse/Cicada errata */
+ }
#endif
#endif
/* Start/Restart autonegotiation */
phy_setup_aneg (reg);
udelay (1000);
}
+#endif /* CONFIG_NO_PHY_RESET */
miiphy_read (reg, PHY_BMSR, &reg_short);
@@ -499,13 +516,22 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
(int) speed, (duplex == HALF) ? "HALF" : "FULL");
}
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+ mfsdr(sdr_mfr, reg);
+ if (speed == 100) {
+ reg = (reg & ~SDR0_MFR_ZMII_MODE_MASK) | SDR0_MFR_ZMII_MODE_RMII_100M;
+ } else {
+ reg = (reg & ~SDR0_MFR_ZMII_MODE_MASK) | SDR0_MFR_ZMII_MODE_RMII_10M;
+ }
+ mtsdr(sdr_mfr, reg);
+#endif
+
/* Set ZMII/RGMII speed according to the phy link speed */
reg = in32 (ZMII_SSR);
if ( (speed == 100) || (speed == 1000) )
out32 (ZMII_SSR, reg | (ZMII_SSR_SP << ZMII_SSR_V (devnum)));
else
- out32 (ZMII_SSR,
- reg & (~(ZMII_SSR_SP << ZMII_SSR_V (devnum))));
+ out32 (ZMII_SSR, reg & (~(ZMII_SSR_SP << ZMII_SSR_V (devnum))));
if ((devnum == 2) || (devnum == 3)) {
if (speed == 1000)
@@ -519,14 +545,16 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
}
/* set the Mal configuration reg */
+#if defined(CONFIG_440GX)
+ mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA |
+ MAL_CR_PLBLT_DEFAULT | MAL_CR_EOPIE | 0x00330000);
+#else
+ mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT);
/* Errata 1.12: MAL_1 -- Disable MAL bursting */
- if (get_pvr () == PVR_440GP_RB)
- mtdcr (malmcr,
- MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT);
- else
- mtdcr (malmcr,
- MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA |
- MAL_CR_PLBLT_DEFAULT | MAL_CR_EOPIE | 0x00330000);
+ if (get_pvr() == PVR_440GP_RB) {
+ mtdcr (malmcr, mfdcr(malmcr) & ~MAL_CR_PLBB);
+ }
+#endif
/* Free "old" buffers */
if (hw_p->alloc_tx_buf)
@@ -543,6 +571,8 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
hw_p->alloc_tx_buf =
(mal_desc_t *) malloc ((sizeof (mal_desc_t) * NUM_TX_BUFF) +
((2 * CFG_CACHELINE_SIZE) - 2));
+ if (NULL == hw_p->alloc_tx_buf)
+ return -1;
if (((int) hw_p->alloc_tx_buf & CACHELINE_MASK) != 0) {
hw_p->tx =
(mal_desc_t *) ((int) hw_p->alloc_tx_buf +
@@ -556,6 +586,12 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
hw_p->alloc_rx_buf =
(mal_desc_t *) malloc ((sizeof (mal_desc_t) * NUM_RX_BUFF) +
((2 * CFG_CACHELINE_SIZE) - 2));
+ if (NULL == hw_p->alloc_rx_buf) {
+ free(hw_p->alloc_tx_buf);
+ hw_p->alloc_tx_buf = NULL;
+ return -1;
+ }
+
if (((int) hw_p->alloc_rx_buf & CACHELINE_MASK) != 0) {
hw_p->rx =
(mal_desc_t *) ((int) hw_p->alloc_rx_buf +
@@ -569,9 +605,20 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
for (i = 0; i < NUM_TX_BUFF; i++) {
hw_p->tx[i].ctrl = 0;
hw_p->tx[i].data_len = 0;
- if (hw_p->first_init == 0)
+ if (hw_p->first_init == 0) {
hw_p->txbuf_ptr =
(char *) malloc (ENET_MAX_MTU_ALIGNED);
+ if (NULL == hw_p->txbuf_ptr) {
+ free(hw_p->alloc_rx_buf);
+ free(hw_p->alloc_tx_buf);
+ hw_p->alloc_rx_buf = NULL;
+ hw_p->alloc_tx_buf = NULL;
+ for(j = 0; j < i; j++) {
+ free(hw_p->tx[i].data_ptr);
+ hw_p->tx[i].data_ptr = NULL;
+ }
+ }
+ }
hw_p->tx[i].data_ptr = hw_p->txbuf_ptr;
if ((NUM_TX_BUFF - 1) == i)
hw_p->tx[i].ctrl |= MAL_TX_CTRL_WRAP;
@@ -618,14 +665,18 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
switch (devnum) {
case 1:
/* setup MAL tx & rx channel pointers */
- mtdcr (maltxbattr, 0x0);
+#if defined (CONFIG_440EP) || defined (CONFIG_440GR)
+ mtdcr (maltxctp2r, hw_p->tx);
+#else
mtdcr (maltxctp1r, hw_p->tx);
+#endif
+ mtdcr (maltxbattr, 0x0);
mtdcr (malrxbattr, 0x0);
mtdcr (malrxctp1r, hw_p->rx);
/* set RX buffer size */
mtdcr (malrcbs1, ENET_MAX_MTU_ALIGNED / 16);
break;
-#if defined (CONFIG_440_GX)
+#if defined (CONFIG_440GX)
case 2:
/* setup MAL tx & rx channel pointers */
mtdcr (maltxbattr, 0x0);
@@ -644,7 +695,7 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
/* set RX buffer size */
mtdcr (malrcbs3, ENET_MAX_MTU_ALIGNED / 16);
break;
-#endif /*CONFIG_440_GX */
+#endif /* CONFIG_440GX */
case 0:
default:
/* setup MAL tx & rx channel pointers */
@@ -658,7 +709,11 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
}
/* Enable MAL transmit and receive channels */
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+ mtdcr (maltxcasr, (MAL_TXRX_CASR >> (hw_p->devnum*2)));
+#else
mtdcr (maltxcasr, (MAL_TXRX_CASR >> hw_p->devnum));
+#endif
mtdcr (malrxcasr, (MAL_TXRX_CASR >> hw_p->devnum));
/* set transmit enable & receive enable */
@@ -804,7 +859,7 @@ int enetInt (struct eth_device *dev)
unsigned long mal_rx_eob;
unsigned long my_uic0msr, my_uic1msr;
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX)
unsigned long my_uic2msr;
#endif
EMAC_440GX_HW_PST hw_p;
@@ -824,7 +879,7 @@ int enetInt (struct eth_device *dev)
my_uic0msr = mfdcr (uic0msr);
my_uic1msr = mfdcr (uic1msr);
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX)
my_uic2msr = mfdcr (uic2msr);
#endif
if (!(my_uic0msr & (UIC_MRE | UIC_MTE))
@@ -834,7 +889,7 @@ int enetInt (struct eth_device *dev)
/* not for us */
return (rc);
}
-#if defined (CONFIG_440_GX)
+#if defined (CONFIG_440GX)
if (!(my_uic0msr & (UIC_MRE | UIC_MTE))
&& !(my_uic2msr & (UIC_ETH2 | UIC_ETH3))) {
/* not for us */
@@ -890,7 +945,7 @@ int enetInt (struct eth_device *dev)
return (rc); /* we had errors so get out */
}
}
-#if defined (CONFIG_440_GX)
+#if defined (CONFIG_440GX)
if (hw_p->devnum == 2) {
if (UIC_ETH2 & my_uic2msr) { /* look for EMAC errors */
emac_isr = in32 (EMAC_ISR + hw_p->hw_addr);
@@ -926,7 +981,7 @@ int enetInt (struct eth_device *dev)
return (rc); /* we had errors so get out */
}
}
-#endif /* CONFIG_440_GX */
+#endif /* CONFIG_440GX */
/* handle MAX TX EOB interrupt from a tx */
if (my_uic0msr & UIC_MTE) {
mal_rx_eob = mfdcr (maltxeobisr);
@@ -955,14 +1010,14 @@ int enetInt (struct eth_device *dev)
case 1:
mtdcr (uic1sr, UIC_ETH1);
break;
-#if defined (CONFIG_440_GX)
+#if defined (CONFIG_440GX)
case 2:
mtdcr (uic2sr, UIC_ETH2);
break;
case 3:
mtdcr (uic2sr, UIC_ETH3);
break;
-#endif /* CONFIG_440_GX */
+#endif /* CONFIG_440GX */
default:
break;
}
@@ -1148,19 +1203,24 @@ static int ppc_440x_eth_rx (struct eth_device *dev)
int ppc_440x_eth_initialize (bd_t * bis)
{
static int virgin = 0;
- unsigned long pfc1;
struct eth_device *dev;
int eth_num = 0;
-
EMAC_440GX_HW_PST hw = NULL;
+#if defined(CONFIG_440GX)
+ unsigned long pfc1;
+
mfsdr (sdr_pfc1, pfc1);
pfc1 &= ~(0x01e00000);
pfc1 |= 0x01200000;
mtsdr (sdr_pfc1, pfc1);
+#endif
/* set phy num and mode */
bis->bi_phynum[0] = CONFIG_PHY_ADDR;
+#if defined(CONFIG_PHY1_ADDR)
bis->bi_phynum[1] = CONFIG_PHY1_ADDR;
+#endif
+#if defined(CONFIG_440GX)
bis->bi_phynum[2] = CONFIG_PHY2_ADDR;
bis->bi_phynum[3] = CONFIG_PHY3_ADDR;
bis->bi_phymode[0] = 0;
@@ -1168,9 +1228,10 @@ int ppc_440x_eth_initialize (bd_t * bis)
bis->bi_phymode[2] = 2;
bis->bi_phymode[3] = 2;
-#if defined (CONFIG_440_GX)
+#if defined (CONFIG_440GX)
ppc_440x_eth_setup_bridge(0, bis);
#endif
+#endif
for (eth_num = 0; eth_num < EMAC_NUM_DEV; eth_num++) {
@@ -1256,6 +1317,7 @@ int ppc_440x_eth_initialize (bd_t * bis)
}
hw->devnum = eth_num;
+ hw->print_speed = 1;
sprintf (dev->name, "ppc_440x_eth%d", eth_num);
dev->priv = (void *) hw;
diff --git a/cpu/ppc4xx/Makefile b/cpu/ppc4xx/Makefile
index a841109e8d..5b16754c50 100644
--- a/cpu/ppc4xx/Makefile
+++ b/cpu/ppc4xx/Makefile
@@ -31,7 +31,7 @@ COBJS = 405gp_enet.o 405gp_pci.o 440gx_enet.o \
bedbug_405.o commproc.o \
cpu.o cpu_init.o i2c.o interrupts.o \
miiphy.o miiphy_440.o sdram.o serial.o \
- spd_sdram.o speed.o traps.o
+ spd_sdram.o speed.o traps.o usb_ohci.o usbdev.o
OBJS = $(AOBJS) $(COBJS)
diff --git a/cpu/ppc4xx/cpu.c b/cpu/ppc4xx/cpu.c
index 06acb8162e..a9bb89ad0a 100644
--- a/cpu/ppc4xx/cpu.c
+++ b/cpu/ppc4xx/cpu.c
@@ -71,17 +71,17 @@ int checkcpu (void)
get_sys_info(&sys_info);
#ifdef CONFIG_405GP
- puts ("IBM PowerPC 405GP");
+ puts ("AMCC PowerPC 405GP");
if (pvr == PVR_405GPR_RB) {
putc('r');
}
puts (" Rev. ");
#endif
#ifdef CONFIG_405CR
- puts ("IBM PowerPC 405CR Rev. ");
+ puts ("AMCC PowerPC 405CR Rev. ");
#endif
#ifdef CONFIG_405EP
- puts ("IBM PowerPC 405EP Rev. ");
+ puts ("AMCC PowerPC 405EP Rev. ");
#endif
switch (pvr) {
case PVR_405GP_RB:
@@ -152,10 +152,10 @@ int checkcpu (void)
#endif
#if defined(CONFIG_440)
- puts ("IBM PowerPC 440 G");
+ puts ("AMCC PowerPC 440");
switch(pvr) {
case PVR_440GP_RB:
- puts("P Rev. B");
+ puts("GP Rev. B");
/* See errata 1.12: CHIP_4 */
if ((mfdcr(cpc0_sys0) != mfdcr(cpc0_strp0)) ||
(mfdcr(cpc0_sys1) != mfdcr(cpc0_strp1)) ){
@@ -167,17 +167,33 @@ int checkcpu (void)
}
break;
case PVR_440GP_RC:
- puts("P Rev. C");
+ puts("GP Rev. C");
break;
case PVR_440GX_RA:
- puts("X Rev. A");
+ puts("GX Rev. A");
break;
case PVR_440GX_RB:
- puts("X Rev. B");
+ puts("GX Rev. B");
break;
case PVR_440GX_RC:
- puts("X Rev. C");
+ puts("GX Rev. C");
break;
+#if defined(CONFIG_440GR)
+ case PVR_440EP_RA:
+ puts("GR Rev. A");
+ break;
+ case PVR_440EP_RB:
+ puts("GR Rev. B");
+ break;
+#else
+ case PVR_440EP_RA:
+ puts("EP Rev. A");
+ break;
+ case PVR_440EP_RB:
+ puts("EP Rev. B");
+ break;
+#endif
+
default:
printf (" UNKNOWN (PVR=%08x)", pvr);
break;
@@ -193,6 +209,12 @@ int checkcpu (void)
int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
+#if defined(CONFIG_YOSEMITE) || defined(CONFIG_YELLOWSTONE)
+ /*give reset to BCSR*/
+ *(unsigned char*)(CFG_BCSR_BASE | 0x06) = 0x09;
+
+#else
+
/*
* Initiate system reset in debug control register DBCR
*/
@@ -202,6 +224,8 @@ int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
#else
__asm__ __volatile__("mtspr 0x3f2, 3");
#endif
+
+#endif/* defined(CONFIG_YOSEMITE) || defined(CONFIG_YELLOWSTONE)*/
return 1;
}
diff --git a/cpu/ppc4xx/cpu_init.c b/cpu/ppc4xx/cpu_init.c
index 25508e7505..68e1a450ca 100644
--- a/cpu/ppc4xx/cpu_init.c
+++ b/cpu/ppc4xx/cpu_init.c
@@ -188,7 +188,11 @@ cpu_init_f (void)
unsigned long val;
val = mfspr(tcr);
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+ val |= 0xb8000000; /* generate system reset after 1.34 seconds */
+#else
val |= 0xf0000000; /* generate system reset after 2.684 seconds */
+#endif
mtspr(tcr, val);
val = mfspr(tsr);
diff --git a/cpu/ppc4xx/interrupts.c b/cpu/ppc4xx/interrupts.c
index 90899dd1e5..1d8dc7c221 100644
--- a/cpu/ppc4xx/interrupts.c
+++ b/cpu/ppc4xx/interrupts.c
@@ -54,12 +54,12 @@ static struct irq_action irq_vecs1[32]; /* For UIC1 */
void uic1_interrupt( void * parms); /* UIC1 handler */
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX)
static struct irq_action irq_vecs2[32]; /* For UIC2 */
void uic0_interrupt( void * parms); /* UIC0 handler */
void uic2_interrupt( void * parms); /* UIC2 handler */
-#endif /* CONFIG_440_GX */
+#endif /* CONFIG_440GX */
#endif /* CONFIG_440 */
@@ -115,11 +115,11 @@ int interrupt_init_cpu (unsigned *decrementer_count)
irq_vecs1[vec].handler = NULL;
irq_vecs1[vec].arg = NULL;
irq_vecs1[vec].count = 0;
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX)
irq_vecs2[vec].handler = NULL;
irq_vecs2[vec].arg = NULL;
irq_vecs2[vec].count = 0;
-#endif /* CONFIG_440_GX */
+#endif /* CONFIG_440GX */
#endif
}
@@ -162,14 +162,14 @@ int interrupt_init_cpu (unsigned *decrementer_count)
set_evpr(0x00000000);
#if defined(CONFIG_440)
-#if !defined(CONFIG_440_GX)
+#if !defined(CONFIG_440GX)
/* Install the UIC1 handlers */
irq_install_handler(VECNUM_UIC1NC, uic1_interrupt, 0);
irq_install_handler(VECNUM_UIC1C, uic1_interrupt, 0);
#endif
#endif
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX)
/* Take the GX out of compatibility mode
* Travis Sawyer, 9 Mar 2004
* NOTE: 440gx user manual inconsistency here
@@ -195,7 +195,7 @@ int interrupt_init_cpu (unsigned *decrementer_count)
/*
* Handle external interrupts
*/
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX)
void external_interrupt(struct pt_regs *regs)
{
ulong uic_msr;
@@ -219,7 +219,7 @@ void external_interrupt(struct pt_regs *regs)
return;
-} /* external_interrupt CONFIG_440_GX */
+} /* external_interrupt CONFIG_440GX */
#else
@@ -266,7 +266,7 @@ void external_interrupt(struct pt_regs *regs)
}
#endif
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX)
/* Handler for UIC0 interrupt */
void uic0_interrupt( void * parms)
{
@@ -310,7 +310,7 @@ void uic0_interrupt( void * parms)
}
}
-#endif /* CONFIG_440_GX */
+#endif /* CONFIG_440GX */
#if defined(CONFIG_440)
/* Handler for UIC1 interrupt */
@@ -357,7 +357,7 @@ void uic1_interrupt( void * parms)
}
#endif /* defined(CONFIG_440) */
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX)
/* Handler for UIC1 interrupt */
void uic2_interrupt( void * parms)
{
@@ -400,7 +400,7 @@ void uic2_interrupt( void * parms)
vec++;
}
}
-#endif /* defined(CONFIG_440_GX) */
+#endif /* defined(CONFIG_440GX) */
/****************************************************************************/
@@ -414,7 +414,7 @@ void irq_install_handler (int vec, interrupt_handler_t * handler, void *arg)
int i = vec;
#if defined(CONFIG_440)
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX)
if ((vec > 31) && (vec < 64)) {
i = vec - 32;
irqa = irq_vecs1;
@@ -422,15 +422,18 @@ void irq_install_handler (int vec, interrupt_handler_t * handler, void *arg)
i = vec - 64;
irqa = irq_vecs2;
}
-#else /* CONFIG_440_GX */
+#else /* CONFIG_440GX */
if (vec > 31) {
i = vec - 32;
irqa = irq_vecs1;
}
-#endif /* CONFIG_440_GX */
+#endif /* CONFIG_440GX */
#endif /* CONFIG_440 */
- if (irqa[i].handler != NULL) {
+ /*
+ * print warning when replacing with a different irq vector
+ */
+ if ((irqa[i].handler != NULL) && (irqa[i].handler != handler)) {
printf ("Interrupt vector %d: handler 0x%x replacing 0x%x\n",
vec, (uint) handler, (uint) irqa[i].handler);
}
@@ -438,13 +441,13 @@ void irq_install_handler (int vec, interrupt_handler_t * handler, void *arg)
irqa[i].arg = arg;
#if defined(CONFIG_440)
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX)
if ((vec > 31) && (vec < 64))
mtdcr (uic1er, mfdcr (uic1er) | (0x80000000 >> i));
else if (vec > 63)
mtdcr (uic2er, mfdcr (uic2er) | (0x80000000 >> i));
else
-#endif /* CONFIG_440_GX */
+#endif /* CONFIG_440GX */
if (vec > 31)
mtdcr (uic1er, mfdcr (uic1er) | (0x80000000 >> i));
else
@@ -461,7 +464,7 @@ void irq_free_handler (int vec)
int i = vec;
#if defined(CONFIG_440)
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX)
if ((vec > 31) && (vec < 64)) {
irqa = irq_vecs1;
i = vec - 32;
@@ -469,7 +472,7 @@ void irq_free_handler (int vec)
irqa = irq_vecs2;
i = vec - 64;
}
-#endif /* CONFIG_440_GX */
+#endif /* CONFIG_440GX */
if (vec > 31) {
irqa = irq_vecs1;
i = vec - 32;
@@ -482,13 +485,13 @@ void irq_free_handler (int vec)
#endif
#if defined(CONFIG_440)
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX)
if ((vec > 31) && (vec < 64))
mtdcr (uic1er, mfdcr (uic1er) & ~(0x80000000 >> i));
else if (vec > 63)
mtdcr (uic2er, mfdcr (uic2er) & ~(0x80000000 >> i));
else
-#endif /* CONFIG_440_GX */
+#endif /* CONFIG_440GX */
if (vec > 31)
mtdcr (uic1er, mfdcr (uic1er) & ~(0x80000000 >> i));
else
@@ -550,7 +553,7 @@ do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
printf("\n");
#endif
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX)
printf ("\nUIC 2\n");
printf ("Nr Routine Arg Count\n");
diff --git a/cpu/ppc4xx/miiphy_440.c b/cpu/ppc4xx/miiphy_440.c
index bbe535acf9..6320feaba7 100644
--- a/cpu/ppc4xx/miiphy_440.c
+++ b/cpu/ppc4xx/miiphy_440.c
@@ -165,13 +165,13 @@ int miiphy_read (unsigned char addr, unsigned char reg, unsigned short *value)
}
sta_reg = reg; /* reg address */
/* set clock (50Mhz) and read flags */
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX)
sta_reg |= EMAC_STACR_READ;
#else
sta_reg = (sta_reg | EMAC_STACR_READ) & ~EMAC_STACR_CLK_100MHZ;
#endif
-#if defined(CONFIG_PHY_CLK_FREQ) && !defined(CONFIG_440_GX)
+#if defined(CONFIG_PHY_CLK_FREQ) && !defined(CONFIG_440GX)
sta_reg = sta_reg | CONFIG_PHY_CLK_FREQ;
#endif
sta_reg = sta_reg | (addr << 5); /* Phy address */
@@ -225,13 +225,13 @@ int miiphy_write (unsigned char addr, unsigned char reg, unsigned short value)
sta_reg = 0;
sta_reg = reg; /* reg address */
/* set clock (50Mhz) and read flags */
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX)
sta_reg |= EMAC_STACR_WRITE;
#else
sta_reg = (sta_reg | EMAC_STACR_WRITE) & ~EMAC_STACR_CLK_100MHZ;
#endif
-#if defined(CONFIG_PHY_CLK_FREQ) && !defined(CONFIG_440_GX)
+#if defined(CONFIG_PHY_CLK_FREQ) && !defined(CONFIG_440GX)
sta_reg = sta_reg | CONFIG_PHY_CLK_FREQ; /* Set clock frequency (PLB freq. dependend) */
#endif
sta_reg = sta_reg | ((unsigned long) addr << 5); /* Phy address */
diff --git a/cpu/ppc4xx/serial.c b/cpu/ppc4xx/serial.c
index 4abd3fc493..8cf7dab3a2 100644
--- a/cpu/ppc4xx/serial.c
+++ b/cpu/ppc4xx/serial.c
@@ -269,9 +269,14 @@ int serial_tstc ()
#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_440) || defined(CONFIG_405EP)
#if defined(CONFIG_440)
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+#define UART0_BASE CFG_PERIPHERAL_BASE + 0x00000300
+#define UART1_BASE CFG_PERIPHERAL_BASE + 0x00000400
+#else
#define UART0_BASE CFG_PERIPHERAL_BASE + 0x00000200
#define UART1_BASE CFG_PERIPHERAL_BASE + 0x00000300
-#if defined(CONFIG_440_GX)
+#endif
+#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || defined(CONFIG_440GR)
#define CR0_MASK 0xdfffffff
#define CR0_EXTCLK_ENA 0x00800000
#define CR0_UDIV_POS 0
@@ -279,7 +284,7 @@ int serial_tstc ()
#define CR0_MASK 0x3fff0000
#define CR0_EXTCLK_ENA 0x00600000
#define CR0_UDIV_POS 16
-#endif /* CONFIG_440_GX */
+#endif /* CONFIG_440GX */
#elif defined(CONFIG_405EP)
#define UART0_BASE 0xef600300
#define UART1_BASE 0xef600400
@@ -301,17 +306,17 @@ int serial_tstc ()
#if defined(CONFIG_UART1_CONSOLE)
#define ACTING_UART0_BASE UART1_BASE
#define ACTING_UART1_BASE UART0_BASE
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || defined(CONFIG_440GR)
#define UART0_SDR sdr_uart1
#define UART1_SDR sdr_uart0
-#endif /* CONFIG_440_GX */
+#endif /* CONFIG_440GX */
#else
#define ACTING_UART0_BASE UART0_BASE
#define ACTING_UART1_BASE UART1_BASE
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || defined(CONFIG_440GR)
#define UART0_SDR sdr_uart0
#define UART1_SDR sdr_uart1
-#endif /* CONFIG_440_GX */
+#endif /* CONFIG_440GX */
#endif
#if defined(CONFIG_405EP) && defined(CFG_EXT_SERIAL_CLOCK)
@@ -431,7 +436,7 @@ int serial_init(void)
unsigned long tmp;
#endif
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX)
#if defined(CONFIG_SERIAL_MULTI)
if (UART0_BASE == dev_base) {
mfsdr(UART0_SDR,reg);
@@ -446,7 +451,7 @@ int serial_init(void)
#endif
#else
reg = mfdcr(cntrl0) & ~CR0_MASK;
-#endif /* CONFIG_440_GX */
+#endif /* CONFIG_440GX */
#ifdef CFG_EXT_SERIAL_CLOCK
reg |= CR0_EXTCLK_ENA;
udiv = 1;
@@ -460,7 +465,7 @@ int serial_init(void)
serial_divs (gd->baudrate, &udiv, &bdiv);
#endif
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || defined(CONFIG_440GR)
reg |= udiv << CR0_UDIV_POS; /* set the UART divisor */
#if defined(CONFIG_SERIAL_MULTI)
if (UART0_BASE == dev_base) {
diff --git a/cpu/ppc4xx/spd_sdram.c b/cpu/ppc4xx/spd_sdram.c
index 794a72c8b5..a8cfcd4e75 100644
--- a/cpu/ppc4xx/spd_sdram.c
+++ b/cpu/ppc4xx/spd_sdram.c
@@ -16,6 +16,9 @@
* Jun Gu, Artesyn Technology, jung@artesyncp.com
* Support for IBM 440 based on OpenBIOS draminit.c from IBM.
*
+ * (C) Copyright 2005
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
* See file CREDITS for list of people who contributed to this
* project.
*
@@ -53,7 +56,9 @@
#define CFG_I2C_SLAVE 0xFE
#endif
-#ifndef CONFIG_440 /* for 405 WALNUT board */
+#define ONE_BILLION 1000000000
+
+#ifndef CONFIG_440 /* for 405 WALNUT/SYCAMORE/BUBINGA boards */
#define SDRAM0_CFG_DCE 0x80000000
#define SDRAM0_CFG_SRE 0x40000000
@@ -111,7 +116,7 @@ int spd_read(uint addr);
long int spd_sdram(int(read_spd)(uint addr))
{
- int bus_period,tmp,row,col;
+ int tmp,row,col;
int total_size,bank_size,bank_code;
int ecc_on;
int mode;
@@ -141,226 +146,189 @@ long int spd_sdram(int(read_spd)(uint addr))
int t_rc;
int min_cas;
- if(read_spd == 0){
- read_spd=spd_read;
- /*
- * Make sure I2C controller is initialized
- * before continuing.
- */
- i2c_init(CFG_I2C_SPEED, CFG_I2C_SLAVE);
- }
-
+ PPC405_SYS_INFO sys_info;
+ unsigned long bus_period_x_10;
/*
- * Calculate the bus period, we do it this
- * way to minimize stack utilization.
+ * get the board info
*/
-#ifndef CONFIG_405EP
- tmp = (mfdcr(pllmd) >> (31-6)) & 0xf; /* get FBDV bits */
- tmp = CONFIG_SYS_CLK_FREQ * tmp; /* get plb freq */
-#else
- {
- unsigned long freqCPU;
- unsigned long pllmr0;
- unsigned long pllmr1;
- unsigned long pllFbkDiv;
- unsigned long pllPlbDiv;
- unsigned long pllmr0_ccdv;
-
- /*
- * Read PLL Mode registers
- */
- pllmr0 = mfdcr (cpc0_pllmr0);
- pllmr1 = mfdcr (cpc0_pllmr1);
-
- pllFbkDiv = ((pllmr1 & PLLMR1_FBMUL_MASK) >> 20);
- if (pllFbkDiv == 0) {
- pllFbkDiv = 16;
- }
- pllPlbDiv = ((pllmr0 & PLLMR0_CPU_TO_PLB_MASK) >> 16) + 1;
-
- /*
- * Determine CPU clock frequency
- */
- pllmr0_ccdv = ((pllmr0 & PLLMR0_CPU_DIV_MASK) >> 20) + 1;
- if (pllmr1 & PLLMR1_SSCS_MASK) {
- freqCPU = (CONFIG_SYS_CLK_FREQ * pllFbkDiv) / pllmr0_ccdv;
- } else {
- freqCPU = CONFIG_SYS_CLK_FREQ / pllmr0_ccdv;
- }
+ get_sys_info(&sys_info);
+ bus_period_x_10 = ONE_BILLION / (sys_info.freqPLB / 10);
+ if (read_spd == 0){
+ read_spd=spd_read;
/*
- * Determine PLB clock frequency
+ * Make sure I2C controller is initialized
+ * before continuing.
*/
- tmp = freqCPU / pllPlbDiv;
+ i2c_init(CFG_I2C_SPEED, CFG_I2C_SLAVE);
}
-#endif
- bus_period = sdram_HZ_to_ns(tmp); /* get sdram speed */
/* Make shure we are using SDRAM */
- if (read_spd(2) != 0x04){
- SPD_ERR("SDRAM - non SDRAM memory module found\n");
- }
-
-/*------------------------------------------------------------------
- configure memory timing register
+ if (read_spd(2) != 0x04) {
+ SPD_ERR("SDRAM - non SDRAM memory module found\n");
+ }
- data from DIMM:
- 27 IN Row Precharge Time ( t RP)
- 29 MIN RAS to CAS Delay ( t RCD)
- 127 Component and Clock Detail ,clk0-clk3, junction temp, CAS
- -------------------------------------------------------------------*/
+ /* ------------------------------------------------------------------
+ * configure memory timing register
+ *
+ * data from DIMM:
+ * 27 IN Row Precharge Time ( t RP)
+ * 29 MIN RAS to CAS Delay ( t RCD)
+ * 127 Component and Clock Detail ,clk0-clk3, junction temp, CAS
+ * -------------------------------------------------------------------*/
- /*
- * first figure out which cas latency mode to use
- * use the min supported mode
- */
+ /*
+ * first figure out which cas latency mode to use
+ * use the min supported mode
+ */
tmp = read_spd(127) & 0x6;
- if(tmp == 0x02){ /* only cas = 2 supported */
- min_cas = 2;
+ if (tmp == 0x02){ /* only cas = 2 supported */
+ min_cas = 2;
/* t_ck = read_spd(9); */
/* t_ac = read_spd(10); */
- }
- else if (tmp == 0x04){ /* only cas = 3 supported */
- min_cas = 3;
+ } else if (tmp == 0x04) { /* only cas = 3 supported */
+ min_cas = 3;
/* t_ck = read_spd(9); */
/* t_ac = read_spd(10); */
- }
- else if (tmp == 0x06){ /* 2,3 supported, so use 2 */
- min_cas = 2;
+ } else if (tmp == 0x06) { /* 2,3 supported, so use 2 */
+ min_cas = 2;
/* t_ck = read_spd(23); */
/* t_ac = read_spd(24); */
- }
- else {
- SPD_ERR("SDRAM - unsupported CAS latency \n");
+ } else {
+ SPD_ERR("SDRAM - unsupported CAS latency \n");
}
- /* get some timing values, t_rp,t_rcd,t_ras,t_rc
- */
- t_rp = read_spd(27);
- t_rcd = read_spd(29);
- t_ras = read_spd(30);
- t_rc = t_ras + t_rp;
-
- /* The following timing calcs subtract 1 before deviding.
- * this has effect of using ceiling instead of floor rounding,
- * and also subtracting 1 to convert number to reg value
- */
- /* set up CASL */
- sdram0_tr = (min_cas - 1) << SDRAM0_TR_CASL_SHIFT;
- /* set up PTA */
- sdram0_tr |= (((t_rp - 1)/bus_period) & 0x3) << SDRAM0_TR_PTA_SHIFT;
- /* set up CTP */
- tmp = ((t_rc - t_rcd - t_rp -1) / bus_period) & 0x3;
- if(tmp<1) tmp=1;
- sdram0_tr |= tmp << SDRAM0_TR_CTP_SHIFT;
- /* set LDF = 2 cycles, reg value = 1 */
- sdram0_tr |= 1 << SDRAM0_TR_LDF_SHIFT;
- /* set RFTA = t_rfc/bus_period, use t_rfc = t_rc */
- tmp = ( (t_rc - 1) / bus_period)-3;
- if(tmp<0)tmp=0;
- if(tmp>6)tmp=6;
+ /* get some timing values, t_rp,t_rcd,t_ras,t_rc
+ */
+ t_rp = read_spd(27);
+ t_rcd = read_spd(29);
+ t_ras = read_spd(30);
+ t_rc = t_ras + t_rp;
+
+ /* The following timing calcs subtract 1 before deviding.
+ * this has effect of using ceiling instead of floor rounding,
+ * and also subtracting 1 to convert number to reg value
+ */
+ /* set up CASL */
+ sdram0_tr = (min_cas - 1) << SDRAM0_TR_CASL_SHIFT;
+ /* set up PTA */
+ sdram0_tr |= ((((t_rp - 1) * 10)/bus_period_x_10) & 0x3) << SDRAM0_TR_PTA_SHIFT;
+ /* set up CTP */
+ tmp = (((t_rc - t_rcd - t_rp -1) * 10) / bus_period_x_10) & 0x3;
+ if (tmp < 1)
+ tmp = 1;
+ sdram0_tr |= tmp << SDRAM0_TR_CTP_SHIFT;
+ /* set LDF = 2 cycles, reg value = 1 */
+ sdram0_tr |= 1 << SDRAM0_TR_LDF_SHIFT;
+ /* set RFTA = t_rfc/bus_period, use t_rfc = t_rc */
+ tmp = (((t_rc - 1) * 10) / bus_period_x_10) - 3;
+ if (tmp < 0)
+ tmp = 0;
+ if (tmp > 6)
+ tmp = 6;
sdram0_tr |= tmp << SDRAM0_TR_RFTA_SHIFT;
- /* set RCD = t_rcd/bus_period*/
- sdram0_tr |= (((t_rcd - 1) / bus_period) &0x3) << SDRAM0_TR_RCD_SHIFT ;
+ /* set RCD = t_rcd/bus_period*/
+ sdram0_tr |= ((((t_rcd - 1) * 10) / bus_period_x_10) &0x3) << SDRAM0_TR_RCD_SHIFT ;
-/*------------------------------------------------------------------
- configure RTR register
- -------------------------------------------------------------------*/
- row = read_spd(3);
- col = read_spd(4);
- tmp = read_spd(12) & 0x7f ; /* refresh type less self refresh bit */
- switch(tmp){
+ /*------------------------------------------------------------------
+ * configure RTR register
+ * -------------------------------------------------------------------*/
+ row = read_spd(3);
+ col = read_spd(4);
+ tmp = read_spd(12) & 0x7f ; /* refresh type less self refresh bit */
+ switch (tmp) {
case 0x00:
- tmp=15625;
- break;
+ tmp = 15625;
+ break;
case 0x01:
- tmp=15625/4;
- break;
+ tmp = 15625 / 4;
+ break;
case 0x02:
- tmp=15625/2;
- break;
+ tmp = 15625 / 2;
+ break;
case 0x03:
- tmp=15625*2;
- break;
+ tmp = 15625 * 2;
+ break;
case 0x04:
- tmp=15625*4;
- break;
+ tmp = 15625 * 4;
+ break;
case 0x05:
- tmp=15625*8;
- break;
+ tmp = 15625 * 8;
+ break;
default:
- SPD_ERR("SDRAM - Bad refresh period \n");
+ SPD_ERR("SDRAM - Bad refresh period \n");
}
/* convert from nsec to bus cycles */
- tmp = tmp/bus_period;
- sdram0_rtr = (tmp & 0x3ff8)<< SDRAM0_RTR_SHIFT;
+ tmp = (tmp * 10) / bus_period_x_10;
+ sdram0_rtr = (tmp & 0x3ff8) << SDRAM0_RTR_SHIFT;
-/*------------------------------------------------------------------
- determine the number of banks used
- -------------------------------------------------------------------*/
+ /*------------------------------------------------------------------
+ * determine the number of banks used
+ * -------------------------------------------------------------------*/
/* byte 7:6 is module data width */
- if(read_spd(7) != 0)
- SPD_ERR("SDRAM - unsupported module width\n");
+ if (read_spd(7) != 0)
+ SPD_ERR("SDRAM - unsupported module width\n");
tmp = read_spd(6);
if (tmp < 32)
- SPD_ERR("SDRAM - unsupported module width\n");
+ SPD_ERR("SDRAM - unsupported module width\n");
else if (tmp < 64)
- bank_cnt=1; /* one bank per sdram side */
+ bank_cnt = 1; /* one bank per sdram side */
else if (tmp < 73)
- bank_cnt=2; /* need two banks per side */
+ bank_cnt = 2; /* need two banks per side */
else if (tmp < 161)
- bank_cnt=4; /* need four banks per side */
+ bank_cnt = 4; /* need four banks per side */
else
- SPD_ERR("SDRAM - unsupported module width\n");
+ SPD_ERR("SDRAM - unsupported module width\n");
/* byte 5 is the module row count (refered to as dimm "sides") */
tmp = read_spd(5);
- if(tmp==1);
- else if(tmp==2) bank_cnt *=2;
- else if(tmp==4) bank_cnt *=4;
- else bank_cnt = 8; /* 8 is an error code */
+ if (tmp == 1)
+ ;
+ else if (tmp==2)
+ bank_cnt *= 2;
+ else if (tmp==4)
+ bank_cnt *= 4;
+ else
+ bank_cnt = 8; /* 8 is an error code */
- if(bank_cnt > 4) /* we only have 4 banks to work with */
- SPD_ERR("SDRAM - unsupported module rows for this width\n");
+ if (bank_cnt > 4) /* we only have 4 banks to work with */
+ SPD_ERR("SDRAM - unsupported module rows for this width\n");
/* now check for ECC ability of module. We only support ECC
* on 32 bit wide devices with 8 bit ECC.
*/
- if ( (read_spd(11)==2) && (read_spd(6)==40) && (read_spd(14)==8) ){
- sdram0_ecccfg=0xf<<SDRAM0_ECCCFG_SHIFT;
- ecc_on = 1;
- }
- else{
- sdram0_ecccfg=0;
- ecc_on = 0;
+ if ((read_spd(11)==2) && (read_spd(6)==40) && (read_spd(14)==8)) {
+ sdram0_ecccfg = 0xf << SDRAM0_ECCCFG_SHIFT;
+ ecc_on = 1;
+ } else {
+ sdram0_ecccfg = 0;
+ ecc_on = 0;
}
-/*------------------------------------------------------------------
- calculate total size
- -------------------------------------------------------------------*/
+ /*------------------------------------------------------------------
+ * calculate total size
+ * -------------------------------------------------------------------*/
/* calculate total size and do sanity check */
tmp = read_spd(31);
- total_size=1<<22; /* total_size = 4MB */
+ total_size = 1 << 22; /* total_size = 4MB */
/* now multiply 4M by the smallest device row density */
/* note that we don't support asymetric rows */
- while (((tmp & 0x0001) == 0) && (tmp != 0)){
- total_size= total_size<<1;
- tmp = tmp>>1;
- }
+ while (((tmp & 0x0001) == 0) && (tmp != 0)) {
+ total_size = total_size << 1;
+ tmp = tmp >> 1;
+ }
total_size *= read_spd(5); /* mult by module rows (dimm sides) */
-/*------------------------------------------------------------------
- map rows * cols * banks to a mode
- -------------------------------------------------------------------*/
+ /*------------------------------------------------------------------
+ * map rows * cols * banks to a mode
+ * -------------------------------------------------------------------*/
- switch( row )
- {
+ switch (row) {
case 11:
- switch ( col )
- {
+ switch (col) {
case 8:
mode=4; /* mode 5 */
break;
@@ -369,12 +337,11 @@ long int spd_sdram(int(read_spd)(uint addr))
mode=0; /* mode 1 */
break;
default:
- SPD_ERR("SDRAM - unsupported mode\n");
+ SPD_ERR("SDRAM - unsupported mode\n");
}
break;
case 12:
- switch ( col )
- {
+ switch (col) {
case 8:
mode=3; /* mode 4 */
break;
@@ -383,37 +350,36 @@ long int spd_sdram(int(read_spd)(uint addr))
mode=1; /* mode 2 */
break;
default:
- SPD_ERR("SDRAM - unsupported mode\n");
+ SPD_ERR("SDRAM - unsupported mode\n");
}
break;
case 13:
- switch ( col )
- {
+ switch (col) {
case 8:
mode=5; /* mode 6 */
break;
case 9:
case 10:
- if (read_spd(17) ==2 )
- mode=6; /* mode 7 */
+ if (read_spd(17) == 2)
+ mode = 6; /* mode 7 */
else
- mode=2; /* mode 3 */
+ mode = 2; /* mode 3 */
break;
case 11:
- mode=2; /* mode 3 */
+ mode = 2; /* mode 3 */
break;
default:
- SPD_ERR("SDRAM - unsupported mode\n");
+ SPD_ERR("SDRAM - unsupported mode\n");
}
break;
default:
- SPD_ERR("SDRAM - unsupported mode\n");
+ SPD_ERR("SDRAM - unsupported mode\n");
}
-/*------------------------------------------------------------------
- using the calculated values, compute the bank
- config register values.
- -------------------------------------------------------------------*/
+ /*------------------------------------------------------------------
+ * using the calculated values, compute the bank
+ * config register values.
+ * -------------------------------------------------------------------*/
sdram0_b1cr = 0;
sdram0_b2cr = 0;
sdram0_b3cr = 0;
@@ -421,44 +387,46 @@ long int spd_sdram(int(read_spd)(uint addr))
/* compute the size of each bank */
bank_size = total_size / bank_cnt;
/* convert bank size to bank size code for ppc4xx
- by takeing log2(bank_size) - 22 */
- tmp=bank_size; /* start with tmp = bank_size */
- bank_code=0; /* and bank_code = 0 */
- while (tmp>1){ /* this takes log2 of tmp */
+ by takeing log2(bank_size) - 22 */
+ tmp = bank_size; /* start with tmp = bank_size */
+ bank_code = 0; /* and bank_code = 0 */
+ while (tmp > 1) { /* this takes log2 of tmp */
bank_code++; /* and stores result in bank_code */
- tmp=tmp>>1;
- } /* bank_code is now log2(bank_size) */
- bank_code-=22; /* subtract 22 to get the code */
+ tmp = tmp >> 1;
+ } /* bank_code is now log2(bank_size) */
+ bank_code -= 22; /* subtract 22 to get the code */
tmp = SDRAM0_BXCR_SZ(bank_code) | SDRAM0_BXCR_AM(mode) | 1;
- sdram0_b0cr = (bank_size) * 0 | tmp;
+ sdram0_b0cr = (bank_size * 0) | tmp;
#ifndef CONFIG_405EP /* not on PPC405EP */
- if(bank_cnt>1) sdram0_b2cr = (bank_size) * 1 | tmp;
- if(bank_cnt>2) sdram0_b1cr = (bank_size) * 2 | tmp;
- if(bank_cnt>3) sdram0_b3cr = (bank_size) * 3 | tmp;
+ if (bank_cnt > 1)
+ sdram0_b2cr = (bank_size * 1) | tmp;
+ if (bank_cnt > 2)
+ sdram0_b1cr = (bank_size * 2) | tmp;
+ if (bank_cnt > 3)
+ sdram0_b3cr = (bank_size * 3) | tmp;
#else
/* PPC405EP chip only supports two SDRAM banks */
- if(bank_cnt>1) sdram0_b1cr = (bank_size) * 1 | tmp;
- if(bank_cnt>2) total_size -= (bank_size) * (bank_cnt - 2);
+ if (bank_cnt > 1)
+ sdram0_b1cr = (bank_size * 1) | tmp;
+ if (bank_cnt > 2)
+ total_size = 2 * bank_size;
#endif
-
/*
* enable sdram controller DCE=1
* enable burst read prefetch to 32 bytes BRPF=2
* leave other functions off
*/
-/*------------------------------------------------------------------
- now that we've done our calculations, we are ready to
- program all the registers.
- -------------------------------------------------------------------*/
-
+ /*------------------------------------------------------------------
+ * now that we've done our calculations, we are ready to
+ * program all the registers.
+ * -------------------------------------------------------------------*/
#define mtsdram0(reg, data) mtdcr(memcfga,reg);mtdcr(memcfgd,data)
/* disable memcontroller so updates work */
- sdram0_cfg = 0;
- mtsdram0( mem_mcopt1, sdram0_cfg );
+ mtsdram0( mem_mcopt1, 0 );
#ifndef CONFIG_405EP /* not on PPC405EP */
mtsdram0( mem_besra , sdram0_besr0 );
@@ -479,15 +447,10 @@ long int spd_sdram(int(read_spd)(uint addr))
/* SDRAM have a power on delay, 500 micro should do */
udelay(500);
sdram0_cfg = SDRAM0_CFG_DCE | SDRAM0_CFG_BRPF(1) | SDRAM0_CFG_ECCDD | SDRAM0_CFG_EMDULR;
- if(ecc_on) sdram0_cfg |= SDRAM0_CFG_MEMCHK;
- mtsdram0( mem_mcopt1, sdram0_cfg );
-
+ if (ecc_on)
+ sdram0_cfg |= SDRAM0_CFG_MEMCHK;
+ mtsdram0(mem_mcopt1, sdram0_cfg);
- /* kernel 2.4.2 from mvista has a bug with memory over 128MB */
-#ifdef MVISTA_MEM_BUG
- if (total_size > 128*1024*1024 )
- total_size=128*1024*1024;
-#endif
return (total_size);
}
@@ -504,8 +467,8 @@ int spd_read(uint addr)
#else /* CONFIG_440 */
/*-----------------------------------------------------------------------------
-| Memory Controller Options 0
-+-----------------------------------------------------------------------------*/
+ | Memory Controller Options 0
+ +-----------------------------------------------------------------------------*/
#define SDRAM_CFG0_DCEN 0x80000000 /* SDRAM Controller Enable */
#define SDRAM_CFG0_MCHK_MASK 0x30000000 /* Memory data errchecking mask */
#define SDRAM_CFG0_MCHK_NON 0x00000000 /* No ECC generation */
@@ -520,39 +483,39 @@ int spd_read(uint addr)
#define SDRAM_CFG0_PDP 0x00200000 /* Page deallocation policy */
/*-----------------------------------------------------------------------------
-| Memory Controller Options 1
-+-----------------------------------------------------------------------------*/
+ | Memory Controller Options 1
+ +-----------------------------------------------------------------------------*/
#define SDRAM_CFG1_SRE 0x80000000 /* Self-Refresh Entry */
#define SDRAM_CFG1_PMEN 0x40000000 /* Power Management Enable */
/*-----------------------------------------------------------------------------+
-| SDRAM DEVPOT Options
-+-----------------------------------------------------------------------------*/
+ | SDRAM DEVPOT Options
+ +-----------------------------------------------------------------------------*/
#define SDRAM_DEVOPT_DLL 0x80000000
#define SDRAM_DEVOPT_DS 0x40000000
/*-----------------------------------------------------------------------------+
-| SDRAM MCSTS Options
-+-----------------------------------------------------------------------------*/
+ | SDRAM MCSTS Options
+ +-----------------------------------------------------------------------------*/
#define SDRAM_MCSTS_MRSC 0x80000000
#define SDRAM_MCSTS_SRMS 0x40000000
#define SDRAM_MCSTS_CIS 0x20000000
/*-----------------------------------------------------------------------------
-| SDRAM Refresh Timer Register
-+-----------------------------------------------------------------------------*/
+ | SDRAM Refresh Timer Register
+ +-----------------------------------------------------------------------------*/
#define SDRAM_RTR_RINT_MASK 0xFFFF0000
#define SDRAM_RTR_RINT_ENCODE(n) (((n) << 16) & SDRAM_RTR_RINT_MASK)
#define sdram_HZ_to_ns(hertz) (1000000000/(hertz))
/*-----------------------------------------------------------------------------+
-| SDRAM UABus Base Address Reg
-+-----------------------------------------------------------------------------*/
+ | SDRAM UABus Base Address Reg
+ +-----------------------------------------------------------------------------*/
#define SDRAM_UABBA_UBBA_MASK 0x0000000F
/*-----------------------------------------------------------------------------+
-| Memory Bank 0-7 configuration
-+-----------------------------------------------------------------------------*/
+ | Memory Bank 0-7 configuration
+ +-----------------------------------------------------------------------------*/
#define SDRAM_BXCR_SDBA_MASK 0xff800000 /* Base address */
#define SDRAM_BXCR_SDSZ_MASK 0x000e0000 /* Size */
#define SDRAM_BXCR_SDSZ_8 0x00020000 /* 8M */
@@ -570,8 +533,8 @@ int spd_read(uint addr)
#define SDRAM_BXCR_SDBE 0x00000001 /* Memory Bank Enable */
/*-----------------------------------------------------------------------------+
-| SDRAM TR0 Options
-+-----------------------------------------------------------------------------*/
+ | SDRAM TR0 Options
+ +-----------------------------------------------------------------------------*/
#define SDRAM_TR0_SDWR_MASK 0x80000000
#define SDRAM_TR0_SDWR_2_CLK 0x00000000
#define SDRAM_TR0_SDWR_3_CLK 0x80000000
@@ -609,8 +572,8 @@ int spd_read(uint addr)
#define SDRAM_TR0_SDRD_4_CLK 0x00000003
/*-----------------------------------------------------------------------------+
-| SDRAM TR1 Options
-+-----------------------------------------------------------------------------*/
+ | SDRAM TR1 Options
+ +-----------------------------------------------------------------------------*/
#define SDRAM_TR1_RDSS_MASK 0xC0000000
#define SDRAM_TR1_RDSS_TR0 0x00000000
#define SDRAM_TR1_RDSS_TR1 0x40000000
@@ -630,8 +593,8 @@ int spd_read(uint addr)
#define SDRAM_TR1_RDCT_MAX 0x000001FF
/*-----------------------------------------------------------------------------+
-| SDRAM WDDCTR Options
-+-----------------------------------------------------------------------------*/
+ | SDRAM WDDCTR Options
+ +-----------------------------------------------------------------------------*/
#define SDRAM_WDDCTR_WRCP_MASK 0xC0000000
#define SDRAM_WDDCTR_WRCP_0DEG 0x00000000
#define SDRAM_WDDCTR_WRCP_90DEG 0x40000000
@@ -639,8 +602,8 @@ int spd_read(uint addr)
#define SDRAM_WDDCTR_DCD_MASK 0x000001FF
/*-----------------------------------------------------------------------------+
-| SDRAM CLKTR Options
-+-----------------------------------------------------------------------------*/
+ | SDRAM CLKTR Options
+ +-----------------------------------------------------------------------------*/
#define SDRAM_CLKTR_CLKP_MASK 0xC0000000
#define SDRAM_CLKTR_CLKP_0DEG 0x00000000
#define SDRAM_CLKTR_CLKP_90DEG 0x40000000
@@ -648,18 +611,17 @@ int spd_read(uint addr)
#define SDRAM_CLKTR_DCDT_MASK 0x000001FF
/*-----------------------------------------------------------------------------+
-| SDRAM DLYCAL Options
-+-----------------------------------------------------------------------------*/
+ | SDRAM DLYCAL Options
+ +-----------------------------------------------------------------------------*/
#define SDRAM_DLYCAL_DLCV_MASK 0x000003FC
#define SDRAM_DLYCAL_DLCV_ENCODE(x) (((x)<<2) & SDRAM_DLYCAL_DLCV_MASK)
#define SDRAM_DLYCAL_DLCV_DECODE(x) (((x) & SDRAM_DLYCAL_DLCV_MASK)>>2)
/*-----------------------------------------------------------------------------+
-| General Definition
-+-----------------------------------------------------------------------------*/
+ | General Definition
+ +-----------------------------------------------------------------------------*/
#define DEFAULT_SPD_ADDR1 0x53
#define DEFAULT_SPD_ADDR2 0x52
-#define ONE_BILLION 1000000000
#define MAXBANKS 4 /* at most 4 dimm banks */
#define MAX_SPD_BYTES 256
#define NUMHALFCYCLES 4
@@ -670,22 +632,22 @@ int spd_read(uint addr)
#define FALSE 0
const unsigned long test[NUMMEMTESTS][NUMMEMWORDS] = {
- {0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
- 0xFFFFFFFF, 0xFFFFFFFF},
- {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
- 0x00000000, 0x00000000},
- {0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
- 0x55555555, 0x55555555},
- {0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
- 0xAAAAAAAA, 0xAAAAAAAA},
- {0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
- 0x5A5A5A5A, 0x5A5A5A5A},
- {0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
- 0xA5A5A5A5, 0xA5A5A5A5},
- {0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
- 0x55AA55AA, 0x55AA55AA},
- {0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
- 0xAA55AA55, 0xAA55AA55}
+ {0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+ 0xFFFFFFFF, 0xFFFFFFFF},
+ {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x00000000, 0x00000000},
+ {0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+ 0x55555555, 0x55555555},
+ {0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+ 0xAAAAAAAA, 0xAAAAAAAA},
+ {0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
+ 0x5A5A5A5A, 0x5A5A5A5A},
+ {0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
+ 0xA5A5A5A5, 0xA5A5A5A5},
+ {0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
+ 0x55AA55AA, 0x55AA55AA},
+ {0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
+ 0xAA55AA55, 0xAA55AA55}
};
@@ -696,14 +658,14 @@ void get_spd_info(unsigned long* dimm_populated,
unsigned long num_dimm_banks);
void check_mem_type
- (unsigned long* dimm_populated,
- unsigned char* iic0_dimm_addr,
- unsigned long num_dimm_banks);
+(unsigned long* dimm_populated,
+ unsigned char* iic0_dimm_addr,
+ unsigned long num_dimm_banks);
void check_volt_type
- (unsigned long* dimm_populated,
- unsigned char* iic0_dimm_addr,
- unsigned long num_dimm_banks);
+(unsigned long* dimm_populated,
+ unsigned char* iic0_dimm_addr,
+ unsigned long num_dimm_banks);
void program_cfg0(unsigned long* dimm_populated,
unsigned char* iic0_dimm_addr,
@@ -741,14 +703,14 @@ long program_bxcr(unsigned long* dimm_populated,
*/
long int spd_sdram(void) {
- unsigned char iic0_dimm_addr[] = SPD_EEPROM_ADDRESS;
- unsigned long dimm_populated[sizeof(iic0_dimm_addr)];
- unsigned long total_size;
- unsigned long cfg0;
- unsigned long mcsts;
- unsigned long num_dimm_banks; /* on board dimm banks */
+ unsigned char iic0_dimm_addr[] = SPD_EEPROM_ADDRESS;
+ unsigned long dimm_populated[sizeof(iic0_dimm_addr)];
+ unsigned long total_size;
+ unsigned long cfg0;
+ unsigned long mcsts;
+ unsigned long num_dimm_banks; /* on board dimm banks */
- num_dimm_banks = sizeof(iic0_dimm_addr);
+ num_dimm_banks = sizeof(iic0_dimm_addr);
/*
* Make sure I2C controller is initialized
@@ -756,90 +718,90 @@ long int spd_sdram(void) {
*/
i2c_init(CFG_I2C_SPEED, CFG_I2C_SLAVE);
- /*
- * Read the SPD information using I2C interface. Check to see if the
- * DIMM slots are populated.
- */
- get_spd_info(dimm_populated, iic0_dimm_addr, num_dimm_banks);
-
- /*
- * Check the memory type for the dimms plugged.
- */
- check_mem_type(dimm_populated, iic0_dimm_addr, num_dimm_banks);
-
- /*
- * Check the voltage type for the dimms plugged.
- */
- check_volt_type(dimm_populated, iic0_dimm_addr, num_dimm_banks);
-
-#if defined(CONFIG_440_GX)
- /*
- * Soft-reset SDRAM controller.
- */
- mtsdr(sdr_srst, SDR0_SRST_DMC);
- mtsdr(sdr_srst, 0x00000000);
+ /*
+ * Read the SPD information using I2C interface. Check to see if the
+ * DIMM slots are populated.
+ */
+ get_spd_info(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+ /*
+ * Check the memory type for the dimms plugged.
+ */
+ check_mem_type(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+ /*
+ * Check the voltage type for the dimms plugged.
+ */
+ check_volt_type(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+#if defined(CONFIG_440GX)
+ /*
+ * Soft-reset SDRAM controller.
+ */
+ mtsdr(sdr_srst, SDR0_SRST_DMC);
+ mtsdr(sdr_srst, 0x00000000);
#endif
- /*
- * program 440GP SDRAM controller options (SDRAM0_CFG0)
- */
- program_cfg0(dimm_populated, iic0_dimm_addr, num_dimm_banks);
-
- /*
- * program 440GP SDRAM controller options (SDRAM0_CFG1)
- */
- program_cfg1(dimm_populated, iic0_dimm_addr, num_dimm_banks);
-
- /*
- * program SDRAM refresh register (SDRAM0_RTR)
- */
- program_rtr(dimm_populated, iic0_dimm_addr, num_dimm_banks);
-
- /*
- * program SDRAM Timing Register 0 (SDRAM0_TR0)
- */
- program_tr0(dimm_populated, iic0_dimm_addr, num_dimm_banks);
-
- /*
- * program the BxCR registers to find out total sdram installed
- */
- total_size = program_bxcr(dimm_populated, iic0_dimm_addr,
- num_dimm_banks);
-
- /*
- * program SDRAM Clock Timing Register (SDRAM0_CLKTR)
- */
- mtsdram(mem_clktr, 0x40000000);
-
- /*
- * delay to ensure 200 usec has elapsed
- */
- udelay(400);
-
- /*
- * enable the memory controller
- */
- mfsdram(mem_cfg0, cfg0);
- mtsdram(mem_cfg0, cfg0 | SDRAM_CFG0_DCEN);
-
- /*
- * wait for SDRAM_CFG0_DC_EN to complete
- */
- while(1) {
- mfsdram(mem_mcsts, mcsts);
- if ((mcsts & SDRAM_MCSTS_MRSC) != 0) {
- break;
+ /*
+ * program 440GP SDRAM controller options (SDRAM0_CFG0)
+ */
+ program_cfg0(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+ /*
+ * program 440GP SDRAM controller options (SDRAM0_CFG1)
+ */
+ program_cfg1(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+ /*
+ * program SDRAM refresh register (SDRAM0_RTR)
+ */
+ program_rtr(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+ /*
+ * program SDRAM Timing Register 0 (SDRAM0_TR0)
+ */
+ program_tr0(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+ /*
+ * program the BxCR registers to find out total sdram installed
+ */
+ total_size = program_bxcr(dimm_populated, iic0_dimm_addr,
+ num_dimm_banks);
+
+ /*
+ * program SDRAM Clock Timing Register (SDRAM0_CLKTR)
+ */
+ mtsdram(mem_clktr, 0x40000000);
+
+ /*
+ * delay to ensure 200 usec has elapsed
+ */
+ udelay(400);
+
+ /*
+ * enable the memory controller
+ */
+ mfsdram(mem_cfg0, cfg0);
+ mtsdram(mem_cfg0, cfg0 | SDRAM_CFG0_DCEN);
+
+ /*
+ * wait for SDRAM_CFG0_DC_EN to complete
+ */
+ while (1) {
+ mfsdram(mem_mcsts, mcsts);
+ if ((mcsts & SDRAM_MCSTS_MRSC) != 0) {
+ break;
+ }
}
- }
- /*
- * program SDRAM Timing Register 1, adding some delays
- */
- program_tr1();
+ /*
+ * program SDRAM Timing Register 1, adding some delays
+ */
+ program_tr1();
- /*
- * if ECC is enabled, initialize parity bits
- */
+ /*
+ * if ECC is enabled, initialize parity bits
+ */
return total_size;
}
@@ -847,76 +809,78 @@ long int spd_sdram(void) {
unsigned char spd_read(uchar chip, uint addr) {
unsigned char data[2];
- if (i2c_read(chip, addr, 1, data, 1) == 0)
- return data[0];
- else
- return 0;
+ if (i2c_probe(chip) == 0) {
+ if (i2c_read(chip, addr, 1, data, 1) == 0) {
+ return data[0];
+ }
+ }
+
+ return 0;
}
void get_spd_info(unsigned long* dimm_populated,
unsigned char* iic0_dimm_addr,
unsigned long num_dimm_banks)
{
- unsigned long dimm_num;
- unsigned long dimm_found;
- unsigned char num_of_bytes;
- unsigned char total_size;
-
- dimm_found = FALSE;
- for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
- num_of_bytes = 0;
- total_size = 0;
-
- num_of_bytes = spd_read(iic0_dimm_addr[dimm_num], 0);
- total_size = spd_read(iic0_dimm_addr[dimm_num], 1);
-
- if ((num_of_bytes != 0) && (total_size != 0)) {
- dimm_populated[dimm_num] = TRUE;
- dimm_found = TRUE;
+ unsigned long dimm_num;
+ unsigned long dimm_found;
+ unsigned char num_of_bytes;
+ unsigned char total_size;
+
+ dimm_found = FALSE;
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ num_of_bytes = 0;
+ total_size = 0;
+
+ num_of_bytes = spd_read(iic0_dimm_addr[dimm_num], 0);
+ total_size = spd_read(iic0_dimm_addr[dimm_num], 1);
+
+ if ((num_of_bytes != 0) && (total_size != 0)) {
+ dimm_populated[dimm_num] = TRUE;
+ dimm_found = TRUE;
#if 0
- printf("DIMM slot %lu: populated\n", dimm_num);
+ printf("DIMM slot %lu: populated\n", dimm_num);
#endif
- }
- else {
- dimm_populated[dimm_num] = FALSE;
+ } else {
+ dimm_populated[dimm_num] = FALSE;
#if 0
- printf("DIMM slot %lu: Not populated\n", dimm_num);
+ printf("DIMM slot %lu: Not populated\n", dimm_num);
#endif
+ }
}
- }
- if (dimm_found == FALSE) {
- printf("ERROR - No memory installed. Install a DDR-SDRAM DIMM.\n\n");
- hang();
- }
+ if (dimm_found == FALSE) {
+ printf("ERROR - No memory installed. Install a DDR-SDRAM DIMM.\n\n");
+ hang();
+ }
}
void check_mem_type(unsigned long* dimm_populated,
unsigned char* iic0_dimm_addr,
unsigned long num_dimm_banks)
{
- unsigned long dimm_num;
- unsigned char dimm_type;
-
- for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
- if (dimm_populated[dimm_num] == TRUE) {
- dimm_type = spd_read(iic0_dimm_addr[dimm_num], 2);
- switch (dimm_type) {
- case 7:
+ unsigned long dimm_num;
+ unsigned char dimm_type;
+
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ if (dimm_populated[dimm_num] == TRUE) {
+ dimm_type = spd_read(iic0_dimm_addr[dimm_num], 2);
+ switch (dimm_type) {
+ case 7:
#if 0
- printf("DIMM slot %lu: DDR SDRAM detected\n", dimm_num);
+ printf("DIMM slot %lu: DDR SDRAM detected\n", dimm_num);
#endif
- break;
- default:
- printf("ERROR: Unsupported DIMM detected in slot %lu.\n",
- dimm_num);
- printf("Only DDR SDRAM DIMMs are supported.\n");
- printf("Replace the DIMM module with a supported DIMM.\n\n");
- hang();
- break;
- }
+ break;
+ default:
+ printf("ERROR: Unsupported DIMM detected in slot %lu.\n",
+ dimm_num);
+ printf("Only DDR SDRAM DIMMs are supported.\n");
+ printf("Replace the DIMM module with a supported DIMM.\n\n");
+ hang();
+ break;
+ }
+ }
}
- }
}
@@ -924,894 +888,891 @@ void check_volt_type(unsigned long* dimm_populated,
unsigned char* iic0_dimm_addr,
unsigned long num_dimm_banks)
{
- unsigned long dimm_num;
- unsigned long voltage_type;
-
- for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
- if (dimm_populated[dimm_num] == TRUE) {
- voltage_type = spd_read(iic0_dimm_addr[dimm_num], 8);
- if (voltage_type != 0x04) {
- printf("ERROR: DIMM %lu with unsupported voltage level.\n",
- dimm_num);
- hang();
- }
- else {
+ unsigned long dimm_num;
+ unsigned long voltage_type;
+
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ if (dimm_populated[dimm_num] == TRUE) {
+ voltage_type = spd_read(iic0_dimm_addr[dimm_num], 8);
+ if (voltage_type != 0x04) {
+ printf("ERROR: DIMM %lu with unsupported voltage level.\n",
+ dimm_num);
+ hang();
+ } else {
#if 0
- printf("DIMM %lu voltage level supported.\n", dimm_num);
+ printf("DIMM %lu voltage level supported.\n", dimm_num);
#endif
- }
- break;
+ }
+ break;
+ }
}
- }
}
void program_cfg0(unsigned long* dimm_populated,
unsigned char* iic0_dimm_addr,
unsigned long num_dimm_banks)
{
- unsigned long dimm_num;
- unsigned long cfg0;
- unsigned long ecc_enabled;
- unsigned char ecc;
- unsigned char attributes;
- unsigned long data_width;
- unsigned long dimm_32bit;
- unsigned long dimm_64bit;
-
- /*
- * get Memory Controller Options 0 data
- */
- mfsdram(mem_cfg0, cfg0);
-
- /*
- * clear bits
- */
- cfg0 &= ~(SDRAM_CFG0_DCEN | SDRAM_CFG0_MCHK_MASK |
- SDRAM_CFG0_RDEN | SDRAM_CFG0_PMUD |
- SDRAM_CFG0_DMWD_MASK |
- SDRAM_CFG0_UIOS_MASK | SDRAM_CFG0_PDP);
-
-
- /*
- * FIXME: assume the DDR SDRAMs in both banks are the same
- */
- ecc_enabled = TRUE;
- for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
- if (dimm_populated[dimm_num] == TRUE) {
- ecc = spd_read(iic0_dimm_addr[dimm_num], 11);
- if (ecc != 0x02) {
- ecc_enabled = FALSE;
- }
-
- /*
- * program Registered DIMM Enable
- */
- attributes = spd_read(iic0_dimm_addr[dimm_num], 21);
- if ((attributes & 0x02) != 0x00) {
- cfg0 |= SDRAM_CFG0_RDEN;
- }
-
- /*
- * program DDR SDRAM Data Width
- */
- data_width =
- (unsigned long)spd_read(iic0_dimm_addr[dimm_num],6) +
- (((unsigned long)spd_read(iic0_dimm_addr[dimm_num],7)) << 8);
- if (data_width == 64 || data_width == 72) {
- dimm_64bit = TRUE;
- cfg0 |= SDRAM_CFG0_DMWD_64;
- }
- else if (data_width == 32 || data_width == 40) {
- dimm_32bit = TRUE;
- cfg0 |= SDRAM_CFG0_DMWD_32;
- }
- else {
- printf("WARNING: DIMM with datawidth of %lu bits.\n",
- data_width);
- printf("Only DIMMs with 32 or 64 bit datawidths supported.\n");
- hang();
- }
- break;
+ unsigned long dimm_num;
+ unsigned long cfg0;
+ unsigned long ecc_enabled;
+ unsigned char ecc;
+ unsigned char attributes;
+ unsigned long data_width;
+ unsigned long dimm_32bit;
+ unsigned long dimm_64bit;
+
+ /*
+ * get Memory Controller Options 0 data
+ */
+ mfsdram(mem_cfg0, cfg0);
+
+ /*
+ * clear bits
+ */
+ cfg0 &= ~(SDRAM_CFG0_DCEN | SDRAM_CFG0_MCHK_MASK |
+ SDRAM_CFG0_RDEN | SDRAM_CFG0_PMUD |
+ SDRAM_CFG0_DMWD_MASK |
+ SDRAM_CFG0_UIOS_MASK | SDRAM_CFG0_PDP);
+
+
+ /*
+ * FIXME: assume the DDR SDRAMs in both banks are the same
+ */
+ ecc_enabled = TRUE;
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ if (dimm_populated[dimm_num] == TRUE) {
+ ecc = spd_read(iic0_dimm_addr[dimm_num], 11);
+ if (ecc != 0x02) {
+ ecc_enabled = FALSE;
+ }
+
+ /*
+ * program Registered DIMM Enable
+ */
+ attributes = spd_read(iic0_dimm_addr[dimm_num], 21);
+ if ((attributes & 0x02) != 0x00) {
+ cfg0 |= SDRAM_CFG0_RDEN;
+ }
+
+ /*
+ * program DDR SDRAM Data Width
+ */
+ data_width =
+ (unsigned long)spd_read(iic0_dimm_addr[dimm_num],6) +
+ (((unsigned long)spd_read(iic0_dimm_addr[dimm_num],7)) << 8);
+ if (data_width == 64 || data_width == 72) {
+ dimm_64bit = TRUE;
+ cfg0 |= SDRAM_CFG0_DMWD_64;
+ } else if (data_width == 32 || data_width == 40) {
+ dimm_32bit = TRUE;
+ cfg0 |= SDRAM_CFG0_DMWD_32;
+ } else {
+ printf("WARNING: DIMM with datawidth of %lu bits.\n",
+ data_width);
+ printf("Only DIMMs with 32 or 64 bit datawidths supported.\n");
+ hang();
+ }
+ break;
+ }
}
- }
-
- /*
- * program Memory Data Error Checking
- */
- if (ecc_enabled == TRUE) {
- cfg0 |= SDRAM_CFG0_MCHK_GEN;
- }
- else {
- cfg0 |= SDRAM_CFG0_MCHK_NON;
- }
-
- /*
- * program Page Management Unit
- */
- cfg0 |= SDRAM_CFG0_PMUD;
-
- /*
- * program Memory Controller Options 0
- * Note: DCEN must be enabled after all DDR SDRAM controller
- * configuration registers get initialized.
- */
- mtsdram(mem_cfg0, cfg0);
+
+ /*
+ * program Memory Data Error Checking
+ */
+ if (ecc_enabled == TRUE) {
+ cfg0 |= SDRAM_CFG0_MCHK_GEN;
+ } else {
+ cfg0 |= SDRAM_CFG0_MCHK_NON;
+ }
+
+ /*
+ * program Page Management Unit
+ */
+ cfg0 |= SDRAM_CFG0_PMUD;
+
+ /*
+ * program Memory Controller Options 0
+ * Note: DCEN must be enabled after all DDR SDRAM controller
+ * configuration registers get initialized.
+ */
+ mtsdram(mem_cfg0, cfg0);
}
void program_cfg1(unsigned long* dimm_populated,
unsigned char* iic0_dimm_addr,
unsigned long num_dimm_banks)
{
- unsigned long cfg1;
- mfsdram(mem_cfg1, cfg1);
-
- /*
- * Self-refresh exit, disable PM
- */
- cfg1 &= ~(SDRAM_CFG1_SRE | SDRAM_CFG1_PMEN);
-
- /*
- * program Memory Controller Options 1
- */
- mtsdram(mem_cfg1, cfg1);
+ unsigned long cfg1;
+ mfsdram(mem_cfg1, cfg1);
+
+ /*
+ * Self-refresh exit, disable PM
+ */
+ cfg1 &= ~(SDRAM_CFG1_SRE | SDRAM_CFG1_PMEN);
+
+ /*
+ * program Memory Controller Options 1
+ */
+ mtsdram(mem_cfg1, cfg1);
}
void program_rtr (unsigned long* dimm_populated,
unsigned char* iic0_dimm_addr,
unsigned long num_dimm_banks)
{
- unsigned long dimm_num;
- unsigned long bus_period_x_10;
- unsigned long refresh_rate = 0;
- unsigned char refresh_rate_type;
- unsigned long refresh_interval;
- unsigned long sdram_rtr;
- PPC440_SYS_INFO sys_info;
-
- /*
- * get the board info
- */
- get_sys_info(&sys_info);
- bus_period_x_10 = ONE_BILLION / (sys_info.freqPLB / 10);
-
-
- for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
- if (dimm_populated[dimm_num] == TRUE) {
- refresh_rate_type = 0x7F & spd_read(iic0_dimm_addr[dimm_num], 12);
- switch (refresh_rate_type) {
- case 0x00:
- refresh_rate = 15625;
- break;
- case 0x01:
- refresh_rate = 15625/4;
- break;
- case 0x02:
- refresh_rate = 15625/2;
- break;
- case 0x03:
- refresh_rate = 15626*2;
- break;
- case 0x04:
- refresh_rate = 15625*4;
- break;
- case 0x05:
- refresh_rate = 15625*8;
- break;
- default:
- printf("ERROR: DIMM %lu, unsupported refresh rate/type.\n",
- dimm_num);
- printf("Replace the DIMM module with a supported DIMM.\n");
- break;
- }
+ unsigned long dimm_num;
+ unsigned long bus_period_x_10;
+ unsigned long refresh_rate = 0;
+ unsigned char refresh_rate_type;
+ unsigned long refresh_interval;
+ unsigned long sdram_rtr;
+ PPC440_SYS_INFO sys_info;
- break;
+ /*
+ * get the board info
+ */
+ get_sys_info(&sys_info);
+ bus_period_x_10 = ONE_BILLION / (sys_info.freqPLB / 10);
+
+
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ if (dimm_populated[dimm_num] == TRUE) {
+ refresh_rate_type = 0x7F & spd_read(iic0_dimm_addr[dimm_num], 12);
+ switch (refresh_rate_type) {
+ case 0x00:
+ refresh_rate = 15625;
+ break;
+ case 0x01:
+ refresh_rate = 15625/4;
+ break;
+ case 0x02:
+ refresh_rate = 15625/2;
+ break;
+ case 0x03:
+ refresh_rate = 15626*2;
+ break;
+ case 0x04:
+ refresh_rate = 15625*4;
+ break;
+ case 0x05:
+ refresh_rate = 15625*8;
+ break;
+ default:
+ printf("ERROR: DIMM %lu, unsupported refresh rate/type.\n",
+ dimm_num);
+ printf("Replace the DIMM module with a supported DIMM.\n");
+ break;
+ }
+
+ break;
+ }
}
- }
- refresh_interval = refresh_rate * 10 / bus_period_x_10;
- sdram_rtr = (refresh_interval & 0x3ff8) << 16;
+ refresh_interval = refresh_rate * 10 / bus_period_x_10;
+ sdram_rtr = (refresh_interval & 0x3ff8) << 16;
- /*
- * program Refresh Timer Register (SDRAM0_RTR)
- */
- mtsdram(mem_rtr, sdram_rtr);
+ /*
+ * program Refresh Timer Register (SDRAM0_RTR)
+ */
+ mtsdram(mem_rtr, sdram_rtr);
}
void program_tr0 (unsigned long* dimm_populated,
unsigned char* iic0_dimm_addr,
unsigned long num_dimm_banks)
{
- unsigned long dimm_num;
- unsigned long tr0;
- unsigned char wcsbc;
- unsigned char t_rp_ns;
- unsigned char t_rcd_ns;
- unsigned char t_ras_ns;
- unsigned long t_rp_clk;
- unsigned long t_ras_rcd_clk;
- unsigned long t_rcd_clk;
- unsigned long t_rfc_clk;
- unsigned long plb_check;
- unsigned char cas_bit;
- unsigned long cas_index;
- unsigned char cas_2_0_available;
- unsigned char cas_2_5_available;
- unsigned char cas_3_0_available;
- unsigned long cycle_time_ns_x_10[3];
- unsigned long tcyc_3_0_ns_x_10;
- unsigned long tcyc_2_5_ns_x_10;
- unsigned long tcyc_2_0_ns_x_10;
- unsigned long tcyc_reg;
- unsigned long bus_period_x_10;
- PPC440_SYS_INFO sys_info;
- unsigned long residue;
-
- /*
- * get the board info
- */
- get_sys_info(&sys_info);
- bus_period_x_10 = ONE_BILLION / (sys_info.freqPLB / 10);
-
- /*
- * get SDRAM Timing Register 0 (SDRAM_TR0) and clear bits
- */
- mfsdram(mem_tr0, tr0);
- tr0 &= ~(SDRAM_TR0_SDWR_MASK | SDRAM_TR0_SDWD_MASK |
- SDRAM_TR0_SDCL_MASK | SDRAM_TR0_SDPA_MASK |
- SDRAM_TR0_SDCP_MASK | SDRAM_TR0_SDLD_MASK |
- SDRAM_TR0_SDRA_MASK | SDRAM_TR0_SDRD_MASK);
-
- /*
- * initialization
- */
- wcsbc = 0;
- t_rp_ns = 0;
- t_rcd_ns = 0;
- t_ras_ns = 0;
- cas_2_0_available = TRUE;
- cas_2_5_available = TRUE;
- cas_3_0_available = TRUE;
- tcyc_2_0_ns_x_10 = 0;
- tcyc_2_5_ns_x_10 = 0;
- tcyc_3_0_ns_x_10 = 0;
-
- for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
- if (dimm_populated[dimm_num] == TRUE) {
- wcsbc = spd_read(iic0_dimm_addr[dimm_num], 15);
- t_rp_ns = spd_read(iic0_dimm_addr[dimm_num], 27) >> 2;
- t_rcd_ns = spd_read(iic0_dimm_addr[dimm_num], 29) >> 2;
- t_ras_ns = spd_read(iic0_dimm_addr[dimm_num], 30);
- cas_bit = spd_read(iic0_dimm_addr[dimm_num], 18);
-
- for (cas_index = 0; cas_index < 3; cas_index++) {
- switch (cas_index) {
- case 0:
- tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 9);
- break;
- case 1:
- tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 23);
- break;
- default:
- tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 25);
- break;
- }
+ unsigned long dimm_num;
+ unsigned long tr0;
+ unsigned char wcsbc;
+ unsigned char t_rp_ns;
+ unsigned char t_rcd_ns;
+ unsigned char t_ras_ns;
+ unsigned long t_rp_clk;
+ unsigned long t_ras_rcd_clk;
+ unsigned long t_rcd_clk;
+ unsigned long t_rfc_clk;
+ unsigned long plb_check;
+ unsigned char cas_bit;
+ unsigned long cas_index;
+ unsigned char cas_2_0_available;
+ unsigned char cas_2_5_available;
+ unsigned char cas_3_0_available;
+ unsigned long cycle_time_ns_x_10[3];
+ unsigned long tcyc_3_0_ns_x_10;
+ unsigned long tcyc_2_5_ns_x_10;
+ unsigned long tcyc_2_0_ns_x_10;
+ unsigned long tcyc_reg;
+ unsigned long bus_period_x_10;
+ PPC440_SYS_INFO sys_info;
+ unsigned long residue;
- if ((tcyc_reg & 0x0F) >= 10) {
- printf("ERROR: Tcyc incorrect for DIMM in slot %lu\n",
- dimm_num);
- hang();
- }
+ /*
+ * get the board info
+ */
+ get_sys_info(&sys_info);
+ bus_period_x_10 = ONE_BILLION / (sys_info.freqPLB / 10);
- cycle_time_ns_x_10[cas_index] =
- (((tcyc_reg & 0xF0) >> 4) * 10) + (tcyc_reg & 0x0F);
- }
-
- cas_index = 0;
-
- if ((cas_bit & 0x80) != 0) {
- cas_index += 3;
- }
- else if ((cas_bit & 0x40) != 0) {
- cas_index += 2;
- }
- else if ((cas_bit & 0x20) != 0) {
- cas_index += 1;
- }
-
- if (((cas_bit & 0x10) != 0) && (cas_index < 3)) {
- tcyc_3_0_ns_x_10 = cycle_time_ns_x_10[cas_index];
- cas_index++;
- }
- else {
- if (cas_index != 0) {
- cas_index++;
- }
- cas_3_0_available = FALSE;
- }
-
- if (((cas_bit & 0x08) != 0) || (cas_index < 3)) {
- tcyc_2_5_ns_x_10 = cycle_time_ns_x_10[cas_index];
- cas_index++;
- }
- else {
- if (cas_index != 0) {
- cas_index++;
- }
- cas_2_5_available = FALSE;
- }
-
- if (((cas_bit & 0x04) != 0) || (cas_index < 3)) {
- tcyc_2_0_ns_x_10 = cycle_time_ns_x_10[cas_index];
- cas_index++;
- }
- else {
- if (cas_index != 0) {
- cas_index++;
+ /*
+ * get SDRAM Timing Register 0 (SDRAM_TR0) and clear bits
+ */
+ mfsdram(mem_tr0, tr0);
+ tr0 &= ~(SDRAM_TR0_SDWR_MASK | SDRAM_TR0_SDWD_MASK |
+ SDRAM_TR0_SDCL_MASK | SDRAM_TR0_SDPA_MASK |
+ SDRAM_TR0_SDCP_MASK | SDRAM_TR0_SDLD_MASK |
+ SDRAM_TR0_SDRA_MASK | SDRAM_TR0_SDRD_MASK);
+
+ /*
+ * initialization
+ */
+ wcsbc = 0;
+ t_rp_ns = 0;
+ t_rcd_ns = 0;
+ t_ras_ns = 0;
+ cas_2_0_available = TRUE;
+ cas_2_5_available = TRUE;
+ cas_3_0_available = TRUE;
+ tcyc_2_0_ns_x_10 = 0;
+ tcyc_2_5_ns_x_10 = 0;
+ tcyc_3_0_ns_x_10 = 0;
+
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ if (dimm_populated[dimm_num] == TRUE) {
+ wcsbc = spd_read(iic0_dimm_addr[dimm_num], 15);
+ t_rp_ns = spd_read(iic0_dimm_addr[dimm_num], 27) >> 2;
+ t_rcd_ns = spd_read(iic0_dimm_addr[dimm_num], 29) >> 2;
+ t_ras_ns = spd_read(iic0_dimm_addr[dimm_num], 30);
+ cas_bit = spd_read(iic0_dimm_addr[dimm_num], 18);
+
+ for (cas_index = 0; cas_index < 3; cas_index++) {
+ switch (cas_index) {
+ case 0:
+ tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 9);
+ break;
+ case 1:
+ tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 23);
+ break;
+ default:
+ tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 25);
+ break;
+ }
+
+ if ((tcyc_reg & 0x0F) >= 10) {
+ printf("ERROR: Tcyc incorrect for DIMM in slot %lu\n",
+ dimm_num);
+ hang();
+ }
+
+ cycle_time_ns_x_10[cas_index] =
+ (((tcyc_reg & 0xF0) >> 4) * 10) + (tcyc_reg & 0x0F);
+ }
+
+ cas_index = 0;
+
+ if ((cas_bit & 0x80) != 0) {
+ cas_index += 3;
+ } else if ((cas_bit & 0x40) != 0) {
+ cas_index += 2;
+ } else if ((cas_bit & 0x20) != 0) {
+ cas_index += 1;
+ }
+
+ if (((cas_bit & 0x10) != 0) && (cas_index < 3)) {
+ tcyc_3_0_ns_x_10 = cycle_time_ns_x_10[cas_index];
+ cas_index++;
+ } else {
+ if (cas_index != 0) {
+ cas_index++;
+ }
+ cas_3_0_available = FALSE;
+ }
+
+ if (((cas_bit & 0x08) != 0) || (cas_index < 3)) {
+ tcyc_2_5_ns_x_10 = cycle_time_ns_x_10[cas_index];
+ cas_index++;
+ } else {
+ if (cas_index != 0) {
+ cas_index++;
+ }
+ cas_2_5_available = FALSE;
+ }
+
+ if (((cas_bit & 0x04) != 0) || (cas_index < 3)) {
+ tcyc_2_0_ns_x_10 = cycle_time_ns_x_10[cas_index];
+ cas_index++;
+ } else {
+ if (cas_index != 0) {
+ cas_index++;
+ }
+ cas_2_0_available = FALSE;
+ }
+
+ break;
}
- cas_2_0_available = FALSE;
- }
+ }
+
+ /*
+ * Program SD_WR and SD_WCSBC fields
+ */
+ tr0 |= SDRAM_TR0_SDWR_2_CLK; /* Write Recovery: 2 CLK */
+ switch (wcsbc) {
+ case 0:
+ tr0 |= SDRAM_TR0_SDWD_0_CLK;
+ break;
+ default:
+ tr0 |= SDRAM_TR0_SDWD_1_CLK;
+ break;
+ }
+
+ /*
+ * Program SD_CASL field
+ */
+ if ((cas_2_0_available == TRUE) &&
+ (bus_period_x_10 >= tcyc_2_0_ns_x_10)) {
+ tr0 |= SDRAM_TR0_SDCL_2_0_CLK;
+ } else if ((cas_2_5_available == TRUE) &&
+ (bus_period_x_10 >= tcyc_2_5_ns_x_10)) {
+ tr0 |= SDRAM_TR0_SDCL_2_5_CLK;
+ } else if ((cas_3_0_available == TRUE) &&
+ (bus_period_x_10 >= tcyc_3_0_ns_x_10)) {
+ tr0 |= SDRAM_TR0_SDCL_3_0_CLK;
+ } else {
+ printf("ERROR: No supported CAS latency with the installed DIMMs.\n");
+ printf("Only CAS latencies of 2.0, 2.5, and 3.0 are supported.\n");
+ printf("Make sure the PLB speed is within the supported range.\n");
+ hang();
+ }
+
+ /*
+ * Calculate Trp in clock cycles and round up if necessary
+ * Program SD_PTA field
+ */
+ t_rp_clk = sys_info.freqPLB * t_rp_ns / ONE_BILLION;
+ plb_check = ONE_BILLION * t_rp_clk / t_rp_ns;
+ if (sys_info.freqPLB != plb_check) {
+ t_rp_clk++;
+ }
+ switch ((unsigned long)t_rp_clk) {
+ case 0:
+ case 1:
+ case 2:
+ tr0 |= SDRAM_TR0_SDPA_2_CLK;
+ break;
+ case 3:
+ tr0 |= SDRAM_TR0_SDPA_3_CLK;
+ break;
+ default:
+ tr0 |= SDRAM_TR0_SDPA_4_CLK;
+ break;
+ }
+
+ /*
+ * Program SD_CTP field
+ */
+ t_ras_rcd_clk = sys_info.freqPLB * (t_ras_ns - t_rcd_ns) / ONE_BILLION;
+ plb_check = ONE_BILLION * t_ras_rcd_clk / (t_ras_ns - t_rcd_ns);
+ if (sys_info.freqPLB != plb_check) {
+ t_ras_rcd_clk++;
+ }
+ switch (t_ras_rcd_clk) {
+ case 0:
+ case 1:
+ case 2:
+ tr0 |= SDRAM_TR0_SDCP_2_CLK;
+ break;
+ case 3:
+ tr0 |= SDRAM_TR0_SDCP_3_CLK;
+ break;
+ case 4:
+ tr0 |= SDRAM_TR0_SDCP_4_CLK;
+ break;
+ default:
+ tr0 |= SDRAM_TR0_SDCP_5_CLK;
+ break;
+ }
- break;
+ /*
+ * Program SD_LDF field
+ */
+ tr0 |= SDRAM_TR0_SDLD_2_CLK;
+
+ /*
+ * Program SD_RFTA field
+ * FIXME tRFC hardcoded as 75 nanoseconds
+ */
+ t_rfc_clk = sys_info.freqPLB / (ONE_BILLION / 75);
+ residue = sys_info.freqPLB % (ONE_BILLION / 75);
+ if (residue >= (ONE_BILLION / 150)) {
+ t_rfc_clk++;
+ }
+ switch (t_rfc_clk) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ tr0 |= SDRAM_TR0_SDRA_6_CLK;
+ break;
+ case 7:
+ tr0 |= SDRAM_TR0_SDRA_7_CLK;
+ break;
+ case 8:
+ tr0 |= SDRAM_TR0_SDRA_8_CLK;
+ break;
+ case 9:
+ tr0 |= SDRAM_TR0_SDRA_9_CLK;
+ break;
+ case 10:
+ tr0 |= SDRAM_TR0_SDRA_10_CLK;
+ break;
+ case 11:
+ tr0 |= SDRAM_TR0_SDRA_11_CLK;
+ break;
+ case 12:
+ tr0 |= SDRAM_TR0_SDRA_12_CLK;
+ break;
+ default:
+ tr0 |= SDRAM_TR0_SDRA_13_CLK;
+ break;
+ }
+
+ /*
+ * Program SD_RCD field
+ */
+ t_rcd_clk = sys_info.freqPLB * t_rcd_ns / ONE_BILLION;
+ plb_check = ONE_BILLION * t_rcd_clk / t_rcd_ns;
+ if (sys_info.freqPLB != plb_check) {
+ t_rcd_clk++;
+ }
+ switch (t_rcd_clk) {
+ case 0:
+ case 1:
+ case 2:
+ tr0 |= SDRAM_TR0_SDRD_2_CLK;
+ break;
+ case 3:
+ tr0 |= SDRAM_TR0_SDRD_3_CLK;
+ break;
+ default:
+ tr0 |= SDRAM_TR0_SDRD_4_CLK;
+ break;
}
- }
-
- /*
- * Program SD_WR and SD_WCSBC fields
- */
- tr0 |= SDRAM_TR0_SDWR_2_CLK; /* Write Recovery: 2 CLK */
- switch (wcsbc) {
- case 0:
- tr0 |= SDRAM_TR0_SDWD_0_CLK;
- break;
- default:
- tr0 |= SDRAM_TR0_SDWD_1_CLK;
- break;
- }
-
- /*
- * Program SD_CASL field
- */
- if ((cas_2_0_available == TRUE) &&
- (bus_period_x_10 >= tcyc_2_0_ns_x_10)) {
- tr0 |= SDRAM_TR0_SDCL_2_0_CLK;
- }
- else if((cas_2_5_available == TRUE) &&
- (bus_period_x_10 >= tcyc_2_5_ns_x_10)) {
- tr0 |= SDRAM_TR0_SDCL_2_5_CLK;
- }
- else if((cas_3_0_available == TRUE) &&
- (bus_period_x_10 >= tcyc_3_0_ns_x_10)) {
- tr0 |= SDRAM_TR0_SDCL_3_0_CLK;
- }
- else {
- printf("ERROR: No supported CAS latency with the installed DIMMs.\n");
- printf("Only CAS latencies of 2.0, 2.5, and 3.0 are supported.\n");
- printf("Make sure the PLB speed is within the supported range.\n");
- hang();
- }
-
- /*
- * Calculate Trp in clock cycles and round up if necessary
- * Program SD_PTA field
- */
- t_rp_clk = sys_info.freqPLB * t_rp_ns / ONE_BILLION;
- plb_check = ONE_BILLION * t_rp_clk / t_rp_ns;
- if (sys_info.freqPLB != plb_check) {
- t_rp_clk++;
- }
- switch ((unsigned long)t_rp_clk) {
- case 0:
- case 1:
- case 2:
- tr0 |= SDRAM_TR0_SDPA_2_CLK;
- break;
- case 3:
- tr0 |= SDRAM_TR0_SDPA_3_CLK;
- break;
- default:
- tr0 |= SDRAM_TR0_SDPA_4_CLK;
- break;
- }
-
- /*
- * Program SD_CTP field
- */
- t_ras_rcd_clk = sys_info.freqPLB * (t_ras_ns - t_rcd_ns) / ONE_BILLION;
- plb_check = ONE_BILLION * t_ras_rcd_clk / (t_ras_ns - t_rcd_ns);
- if (sys_info.freqPLB != plb_check) {
- t_ras_rcd_clk++;
- }
- switch (t_ras_rcd_clk) {
- case 0:
- case 1:
- case 2:
- tr0 |= SDRAM_TR0_SDCP_2_CLK;
- break;
- case 3:
- tr0 |= SDRAM_TR0_SDCP_3_CLK;
- break;
- case 4:
- tr0 |= SDRAM_TR0_SDCP_4_CLK;
- break;
- default:
- tr0 |= SDRAM_TR0_SDCP_5_CLK;
- break;
- }
-
- /*
- * Program SD_LDF field
- */
- tr0 |= SDRAM_TR0_SDLD_2_CLK;
-
- /*
- * Program SD_RFTA field
- * FIXME tRFC hardcoded as 75 nanoseconds
- */
- t_rfc_clk = sys_info.freqPLB / (ONE_BILLION / 75);
- residue = sys_info.freqPLB % (ONE_BILLION / 75);
- if (residue >= (ONE_BILLION / 150)) {
- t_rfc_clk++;
- }
- switch (t_rfc_clk) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- tr0 |= SDRAM_TR0_SDRA_6_CLK;
- break;
- case 7:
- tr0 |= SDRAM_TR0_SDRA_7_CLK;
- break;
- case 8:
- tr0 |= SDRAM_TR0_SDRA_8_CLK;
- break;
- case 9:
- tr0 |= SDRAM_TR0_SDRA_9_CLK;
- break;
- case 10:
- tr0 |= SDRAM_TR0_SDRA_10_CLK;
- break;
- case 11:
- tr0 |= SDRAM_TR0_SDRA_11_CLK;
- break;
- case 12:
- tr0 |= SDRAM_TR0_SDRA_12_CLK;
- break;
- default:
- tr0 |= SDRAM_TR0_SDRA_13_CLK;
- break;
- }
-
- /*
- * Program SD_RCD field
- */
- t_rcd_clk = sys_info.freqPLB * t_rcd_ns / ONE_BILLION;
- plb_check = ONE_BILLION * t_rcd_clk / t_rcd_ns;
- if (sys_info.freqPLB != plb_check) {
- t_rcd_clk++;
- }
- switch (t_rcd_clk) {
- case 0:
- case 1:
- case 2:
- tr0 |= SDRAM_TR0_SDRD_2_CLK;
- break;
- case 3:
- tr0 |= SDRAM_TR0_SDRD_3_CLK;
- break;
- default:
- tr0 |= SDRAM_TR0_SDRD_4_CLK;
- break;
- }
#if 0
- printf("tr0: %x\n", tr0);
+ printf("tr0: %x\n", tr0);
#endif
- mtsdram(mem_tr0, tr0);
+ mtsdram(mem_tr0, tr0);
}
void program_tr1 (void)
{
- unsigned long tr0;
- unsigned long tr1;
- unsigned long cfg0;
- unsigned long ecc_temp;
- unsigned long dlycal;
- unsigned long dly_val;
- unsigned long i, j, k;
- unsigned long bxcr_num;
- unsigned long max_pass_length;
- unsigned long current_pass_length;
- unsigned long current_fail_length;
- unsigned long current_start;
- unsigned long rdclt;
- unsigned long rdclt_offset;
- long max_start;
- long max_end;
- long rdclt_average;
- unsigned char window_found;
- unsigned char fail_found;
- unsigned char pass_found;
- unsigned long * membase;
- PPC440_SYS_INFO sys_info;
-
- /*
- * get the board info
- */
- get_sys_info(&sys_info);
-
- /*
- * get SDRAM Timing Register 0 (SDRAM_TR0) and clear bits
- */
- mfsdram(mem_tr1, tr1);
- tr1 &= ~(SDRAM_TR1_RDSS_MASK | SDRAM_TR1_RDSL_MASK |
- SDRAM_TR1_RDCD_MASK | SDRAM_TR1_RDCT_MASK);
-
- mfsdram(mem_tr0, tr0);
- if (((tr0 & SDRAM_TR0_SDCL_MASK) == SDRAM_TR0_SDCL_2_5_CLK) &&
- (sys_info.freqPLB > 100000000)) {
- tr1 |= SDRAM_TR1_RDSS_TR2;
- tr1 |= SDRAM_TR1_RDSL_STAGE3;
- tr1 |= SDRAM_TR1_RDCD_RCD_1_2;
- }
- else {
- tr1 |= SDRAM_TR1_RDSS_TR1;
- tr1 |= SDRAM_TR1_RDSL_STAGE2;
- tr1 |= SDRAM_TR1_RDCD_RCD_0_0;
- }
-
- /*
- * save CFG0 ECC setting to a temporary variable and turn ECC off
- */
- mfsdram(mem_cfg0, cfg0);
- ecc_temp = cfg0 & SDRAM_CFG0_MCHK_MASK;
- mtsdram(mem_cfg0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) | SDRAM_CFG0_MCHK_NON);
-
- /*
- * get the delay line calibration register value
- */
- mfsdram(mem_dlycal, dlycal);
- dly_val = SDRAM_DLYCAL_DLCV_DECODE(dlycal) << 2;
-
- max_pass_length = 0;
- max_start = 0;
- max_end = 0;
- current_pass_length = 0;
- current_fail_length = 0;
- current_start = 0;
- rdclt_offset = 0;
- window_found = FALSE;
- fail_found = FALSE;
- pass_found = FALSE;
+ unsigned long tr0;
+ unsigned long tr1;
+ unsigned long cfg0;
+ unsigned long ecc_temp;
+ unsigned long dlycal;
+ unsigned long dly_val;
+ unsigned long i, j, k;
+ unsigned long bxcr_num;
+ unsigned long max_pass_length;
+ unsigned long current_pass_length;
+ unsigned long current_fail_length;
+ unsigned long current_start;
+ unsigned long rdclt;
+ unsigned long rdclt_offset;
+ long max_start;
+ long max_end;
+ long rdclt_average;
+ unsigned char window_found;
+ unsigned char fail_found;
+ unsigned char pass_found;
+ unsigned long * membase;
+ PPC440_SYS_INFO sys_info;
+
+ /*
+ * get the board info
+ */
+ get_sys_info(&sys_info);
+
+ /*
+ * get SDRAM Timing Register 0 (SDRAM_TR0) and clear bits
+ */
+ mfsdram(mem_tr1, tr1);
+ tr1 &= ~(SDRAM_TR1_RDSS_MASK | SDRAM_TR1_RDSL_MASK |
+ SDRAM_TR1_RDCD_MASK | SDRAM_TR1_RDCT_MASK);
+
+ mfsdram(mem_tr0, tr0);
+ if (((tr0 & SDRAM_TR0_SDCL_MASK) == SDRAM_TR0_SDCL_2_5_CLK) &&
+ (sys_info.freqPLB > 100000000)) {
+ tr1 |= SDRAM_TR1_RDSS_TR2;
+ tr1 |= SDRAM_TR1_RDSL_STAGE3;
+ tr1 |= SDRAM_TR1_RDCD_RCD_1_2;
+ } else {
+ tr1 |= SDRAM_TR1_RDSS_TR1;
+ tr1 |= SDRAM_TR1_RDSL_STAGE2;
+ tr1 |= SDRAM_TR1_RDCD_RCD_0_0;
+ }
+
+ /*
+ * save CFG0 ECC setting to a temporary variable and turn ECC off
+ */
+ mfsdram(mem_cfg0, cfg0);
+ ecc_temp = cfg0 & SDRAM_CFG0_MCHK_MASK;
+ mtsdram(mem_cfg0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) | SDRAM_CFG0_MCHK_NON);
+
+ /*
+ * get the delay line calibration register value
+ */
+ mfsdram(mem_dlycal, dlycal);
+ dly_val = SDRAM_DLYCAL_DLCV_DECODE(dlycal) << 2;
+
+ max_pass_length = 0;
+ max_start = 0;
+ max_end = 0;
+ current_pass_length = 0;
+ current_fail_length = 0;
+ current_start = 0;
+ rdclt_offset = 0;
+ window_found = FALSE;
+ fail_found = FALSE;
+ pass_found = FALSE;
#ifdef DEBUG
- printf("Starting memory test ");
+ printf("Starting memory test ");
#endif
- for (k = 0; k < NUMHALFCYCLES; k++) {
- for (rdclt = 0; rdclt < dly_val; rdclt++) {
- /*
- * Set the timing reg for the test.
- */
- mtsdram(mem_tr1, (tr1 | SDRAM_TR1_RDCT_ENCODE(rdclt)));
-
- for (bxcr_num = 0; bxcr_num < MAXBXCR; bxcr_num++) {
- mtdcr(memcfga, mem_b0cr + (bxcr_num<<2));
- if ((mfdcr(memcfgd) & SDRAM_BXCR_SDBE) == SDRAM_BXCR_SDBE) {
- /* Bank is enabled */
- membase = (unsigned long*)
- (mfdcr(memcfgd) & SDRAM_BXCR_SDBA_MASK);
-
- /*
- * Run the short memory test
- */
- for (i = 0; i < NUMMEMTESTS; i++) {
- for (j = 0; j < NUMMEMWORDS; j++) {
- membase[j] = test[i][j];
- ppcDcbf((unsigned long)&(membase[j]));
+ for (k = 0; k < NUMHALFCYCLES; k++) {
+ for (rdclt = 0; rdclt < dly_val; rdclt++) {
+ /*
+ * Set the timing reg for the test.
+ */
+ mtsdram(mem_tr1, (tr1 | SDRAM_TR1_RDCT_ENCODE(rdclt)));
+
+ for (bxcr_num = 0; bxcr_num < MAXBXCR; bxcr_num++) {
+ mtdcr(memcfga, mem_b0cr + (bxcr_num<<2));
+ if ((mfdcr(memcfgd) & SDRAM_BXCR_SDBE) == SDRAM_BXCR_SDBE) {
+ /* Bank is enabled */
+ membase = (unsigned long*)
+ (mfdcr(memcfgd) & SDRAM_BXCR_SDBA_MASK);
+
+ /*
+ * Run the short memory test
+ */
+ for (i = 0; i < NUMMEMTESTS; i++) {
+ for (j = 0; j < NUMMEMWORDS; j++) {
+ membase[j] = test[i][j];
+ ppcDcbf((unsigned long)&(membase[j]));
+ }
+
+ for (j = 0; j < NUMMEMWORDS; j++) {
+ if (membase[j] != test[i][j]) {
+ ppcDcbf((unsigned long)&(membase[j]));
+ break;
+ }
+ ppcDcbf((unsigned long)&(membase[j]));
+ }
+
+ if (j < NUMMEMWORDS) {
+ break;
+ }
+ }
+
+ /*
+ * see if the rdclt value passed
+ */
+ if (i < NUMMEMTESTS) {
+ break;
+ }
+ }
}
- for (j = 0; j < NUMMEMWORDS; j++) {
- if (membase[j] != test[i][j]) {
- ppcDcbf((unsigned long)&(membase[j]));
- break;
- }
- ppcDcbf((unsigned long)&(membase[j]));
- }
-
- if (j < NUMMEMWORDS) {
- break;
+ if (bxcr_num == MAXBXCR) {
+ if (fail_found == TRUE) {
+ pass_found = TRUE;
+ if (current_pass_length == 0) {
+ current_start = rdclt_offset + rdclt;
+ }
+
+ current_fail_length = 0;
+ current_pass_length++;
+
+ if (current_pass_length > max_pass_length) {
+ max_pass_length = current_pass_length;
+ max_start = current_start;
+ max_end = rdclt_offset + rdclt;
+ }
+ }
+ } else {
+ current_pass_length = 0;
+ current_fail_length++;
+
+ if (current_fail_length >= (dly_val>>2)) {
+ if (fail_found == FALSE) {
+ fail_found = TRUE;
+ } else if (pass_found == TRUE) {
+ window_found = TRUE;
+ break;
+ }
+ }
}
- }
-
- /*
- * see if the rdclt value passed
- */
- if (i < NUMMEMTESTS) {
- break;
- }
- }
- }
-
- if (bxcr_num == MAXBXCR) {
- if (fail_found == TRUE) {
- pass_found = TRUE;
- if (current_pass_length == 0) {
- current_start = rdclt_offset + rdclt;
- }
-
- current_fail_length = 0;
- current_pass_length++;
-
- if (current_pass_length > max_pass_length) {
- max_pass_length = current_pass_length;
- max_start = current_start;
- max_end = rdclt_offset + rdclt;
- }
}
- }
- else {
- current_pass_length = 0;
- current_fail_length++;
-
- if (current_fail_length >= (dly_val>>2)) {
- if (fail_found == FALSE) {
- fail_found = TRUE;
- }
- else if (pass_found == TRUE) {
- window_found = TRUE;
+#ifdef DEBUG
+ printf(".");
+#endif
+ if (window_found == TRUE) {
break;
- }
}
- }
+
+ tr1 = tr1 ^ SDRAM_TR1_RDCD_MASK;
+ rdclt_offset += dly_val;
}
#ifdef DEBUG
- printf(".");
+ printf("\n");
#endif
- if (window_found == TRUE) {
- break;
+
+ /*
+ * make sure we find the window
+ */
+ if (window_found == FALSE) {
+ printf("ERROR: Cannot determine a common read delay.\n");
+ hang();
}
- tr1 = tr1 ^ SDRAM_TR1_RDCD_MASK;
- rdclt_offset += dly_val;
- }
-#ifdef DEBUG
- printf("\n");
-#endif
+ /*
+ * restore the orignal ECC setting
+ */
+ mtsdram(mem_cfg0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) | ecc_temp);
- /*
- * make sure we find the window
- */
- if (window_found == FALSE) {
- printf("ERROR: Cannot determine a common read delay.\n");
- hang();
- }
-
- /*
- * restore the orignal ECC setting
- */
- mtsdram(mem_cfg0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) | ecc_temp);
-
- /*
- * set the SDRAM TR1 RDCD value
- */
- tr1 &= ~SDRAM_TR1_RDCD_MASK;
- if ((tr0 & SDRAM_TR0_SDCL_MASK) == SDRAM_TR0_SDCL_2_5_CLK) {
- tr1 |= SDRAM_TR1_RDCD_RCD_1_2;
- }
- else {
- tr1 |= SDRAM_TR1_RDCD_RCD_0_0;
- }
-
- /*
- * set the SDRAM TR1 RDCLT value
- */
- tr1 &= ~SDRAM_TR1_RDCT_MASK;
- while (max_end >= (dly_val<<1)) {
- max_end -= (dly_val<<1);
- max_start -= (dly_val<<1);
- }
-
- rdclt_average = ((max_start + max_end) >> 1);
- if (rdclt_average >= 0x60)
- while(1);
-
- if (rdclt_average < 0) {
- rdclt_average = 0;
- }
-
- if (rdclt_average >= dly_val) {
- rdclt_average -= dly_val;
- tr1 = tr1 ^ SDRAM_TR1_RDCD_MASK;
- }
- tr1 |= SDRAM_TR1_RDCT_ENCODE(rdclt_average);
+ /*
+ * set the SDRAM TR1 RDCD value
+ */
+ tr1 &= ~SDRAM_TR1_RDCD_MASK;
+ if ((tr0 & SDRAM_TR0_SDCL_MASK) == SDRAM_TR0_SDCL_2_5_CLK) {
+ tr1 |= SDRAM_TR1_RDCD_RCD_1_2;
+ } else {
+ tr1 |= SDRAM_TR1_RDCD_RCD_0_0;
+ }
+
+ /*
+ * set the SDRAM TR1 RDCLT value
+ */
+ tr1 &= ~SDRAM_TR1_RDCT_MASK;
+ while (max_end >= (dly_val << 1)) {
+ max_end -= (dly_val << 1);
+ max_start -= (dly_val << 1);
+ }
+
+ rdclt_average = ((max_start + max_end) >> 1);
+ if (rdclt_average >= 0x60)
+ while (1)
+ ;
+
+ if (rdclt_average < 0) {
+ rdclt_average = 0;
+ }
+
+ if (rdclt_average >= dly_val) {
+ rdclt_average -= dly_val;
+ tr1 = tr1 ^ SDRAM_TR1_RDCD_MASK;
+ }
+ tr1 |= SDRAM_TR1_RDCT_ENCODE(rdclt_average);
#if 0
- printf("tr1: %x\n", tr1);
+ printf("tr1: %x\n", tr1);
#endif
- /*
- * program SDRAM Timing Register 1 TR1
- */
- mtsdram(mem_tr1, tr1);
+ /*
+ * program SDRAM Timing Register 1 TR1
+ */
+ mtsdram(mem_tr1, tr1);
}
unsigned long program_bxcr(unsigned long* dimm_populated,
unsigned char* iic0_dimm_addr,
unsigned long num_dimm_banks)
{
- unsigned long dimm_num;
- unsigned long bxcr_num;
- unsigned long bank_base_addr;
- unsigned long bank_size_bytes;
- unsigned long cr;
- unsigned long i;
- unsigned long temp;
- unsigned char num_row_addr;
- unsigned char num_col_addr;
- unsigned char num_banks;
- unsigned char bank_size_id;
-
-
- /*
- * Set the BxCR regs. First, wipe out the bank config registers.
- */
- for (bxcr_num = 0; bxcr_num < MAXBXCR; bxcr_num++) {
- mtdcr(memcfga, mem_b0cr + (bxcr_num << 2));
- mtdcr(memcfgd, 0x00000000);
- }
-
- /*
- * reset the bank_base address
- */
- bank_base_addr = CFG_SDRAM_BASE;
-
- for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
- if (dimm_populated[dimm_num] == TRUE) {
- num_row_addr = spd_read(iic0_dimm_addr[dimm_num], 3);
- num_col_addr = spd_read(iic0_dimm_addr[dimm_num], 4);
- num_banks = spd_read(iic0_dimm_addr[dimm_num], 5);
- bank_size_id = spd_read(iic0_dimm_addr[dimm_num], 31);
-
- /*
- * Set the SDRAM0_BxCR regs
- */
- cr = 0;
- bank_size_bytes = 4 * 1024 * 1024 * bank_size_id;
- switch (bank_size_id) {
- case 0x02:
- cr |= SDRAM_BXCR_SDSZ_8;
- break;
- case 0x04:
- cr |= SDRAM_BXCR_SDSZ_16;
- break;
- case 0x08:
- cr |= SDRAM_BXCR_SDSZ_32;
- break;
- case 0x10:
- cr |= SDRAM_BXCR_SDSZ_64;
- break;
- case 0x20:
- cr |= SDRAM_BXCR_SDSZ_128;
- break;
- case 0x40:
- cr |= SDRAM_BXCR_SDSZ_256;
- break;
- case 0x80:
- cr |= SDRAM_BXCR_SDSZ_512;
- break;
- default:
- printf("DDR-SDRAM: DIMM %lu BxCR configuration.\n",
- dimm_num);
- printf("ERROR: Unsupported value for the banksize: %d.\n",
- bank_size_id);
- printf("Replace the DIMM module with a supported DIMM.\n\n");
- hang();
- }
+ unsigned long dimm_num;
+ unsigned long bank_base_addr;
+ unsigned long bank_size_bytes;
+ unsigned long cr;
+ unsigned long i;
+ unsigned long temp;
+ unsigned char num_row_addr;
+ unsigned char num_col_addr;
+ unsigned char num_banks;
+ unsigned char bank_size_id;
+
+#ifndef CONFIG_BAMBOO
+ unsigned long bxcr_num;
- switch (num_col_addr) {
- case 0x08:
- cr |= SDRAM_BXCR_SDAM_1;
- break;
- case 0x09:
- cr |= SDRAM_BXCR_SDAM_2;
- break;
- case 0x0A:
- cr |= SDRAM_BXCR_SDAM_3;
- break;
- case 0x0B:
- cr |= SDRAM_BXCR_SDAM_4;
- break;
- default:
- printf("DDR-SDRAM: DIMM %lu BxCR configuration.\n",
- dimm_num);
- printf("ERROR: Unsupported value for number of "
- "column addresses: %d.\n", num_col_addr);
- printf("Replace the DIMM module with a supported DIMM.\n\n");
- hang();
- }
-
- /*
- * enable the bank
- */
- cr |= SDRAM_BXCR_SDBE;
-
- /*------------------------------------------------------------------
- | This next section is hardware dependent and must be programmed
- | to match the hardware.
- +-----------------------------------------------------------------*/
- if (dimm_num == 0) {
- for (i = 0; i < num_banks; i++) {
- mtdcr(memcfga, mem_b0cr + (i << 2));
- temp = mfdcr(memcfgd) & ~(SDRAM_BXCR_SDBA_MASK |
- SDRAM_BXCR_SDSZ_MASK |
- SDRAM_BXCR_SDAM_MASK |
- SDRAM_BXCR_SDBE);
- cr |= temp;
- cr |= bank_base_addr & SDRAM_BXCR_SDBA_MASK;
- mtdcr(memcfgd, cr);
- bank_base_addr += bank_size_bytes;
- }
- }
- else {
- for (i = 0; i < num_banks; i++) {
- mtdcr(memcfga, mem_b2cr + (i << 2));
- temp = mfdcr(memcfgd) & ~(SDRAM_BXCR_SDBA_MASK |
- SDRAM_BXCR_SDSZ_MASK |
- SDRAM_BXCR_SDAM_MASK |
- SDRAM_BXCR_SDBE);
- cr |= temp;
- cr |= bank_base_addr & SDRAM_BXCR_SDBA_MASK;
- mtdcr(memcfgd, cr);
- bank_base_addr += bank_size_bytes;
+ /*
+ * Set the BxCR regs. First, wipe out the bank config registers.
+ */
+ for (bxcr_num = 0; bxcr_num < MAXBXCR; bxcr_num++) {
+ mtdcr(memcfga, mem_b0cr + (bxcr_num << 2));
+ mtdcr(memcfgd, 0x00000000);
+ }
+#endif
+
+ /*
+ * reset the bank_base address
+ */
+#ifndef CONFIG_BAMBOO
+ bank_base_addr = CFG_SDRAM_BASE;
+#else
+ bank_base_addr = CFG_SDRAM_ONBOARD_SIZE;
+#endif
+
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ if (dimm_populated[dimm_num] == TRUE) {
+ num_row_addr = spd_read(iic0_dimm_addr[dimm_num], 3);
+ num_col_addr = spd_read(iic0_dimm_addr[dimm_num], 4);
+ num_banks = spd_read(iic0_dimm_addr[dimm_num], 5);
+ bank_size_id = spd_read(iic0_dimm_addr[dimm_num], 31);
+
+ /*
+ * Set the SDRAM0_BxCR regs
+ */
+ cr = 0;
+ bank_size_bytes = 4 * 1024 * 1024 * bank_size_id;
+ switch (bank_size_id) {
+ case 0x02:
+ cr |= SDRAM_BXCR_SDSZ_8;
+ break;
+ case 0x04:
+ cr |= SDRAM_BXCR_SDSZ_16;
+ break;
+ case 0x08:
+ cr |= SDRAM_BXCR_SDSZ_32;
+ break;
+ case 0x10:
+ cr |= SDRAM_BXCR_SDSZ_64;
+ break;
+ case 0x20:
+ cr |= SDRAM_BXCR_SDSZ_128;
+ break;
+ case 0x40:
+ cr |= SDRAM_BXCR_SDSZ_256;
+ break;
+ case 0x80:
+ cr |= SDRAM_BXCR_SDSZ_512;
+ break;
+ default:
+ printf("DDR-SDRAM: DIMM %lu BxCR configuration.\n",
+ dimm_num);
+ printf("ERROR: Unsupported value for the banksize: %d.\n",
+ bank_size_id);
+ printf("Replace the DIMM module with a supported DIMM.\n\n");
+ hang();
+ }
+
+ switch (num_col_addr) {
+ case 0x08:
+ cr |= SDRAM_BXCR_SDAM_1;
+ break;
+ case 0x09:
+ cr |= SDRAM_BXCR_SDAM_2;
+ break;
+ case 0x0A:
+ cr |= SDRAM_BXCR_SDAM_3;
+ break;
+ case 0x0B:
+ cr |= SDRAM_BXCR_SDAM_4;
+ break;
+ default:
+ printf("DDR-SDRAM: DIMM %lu BxCR configuration.\n",
+ dimm_num);
+ printf("ERROR: Unsupported value for number of "
+ "column addresses: %d.\n", num_col_addr);
+ printf("Replace the DIMM module with a supported DIMM.\n\n");
+ hang();
+ }
+
+ /*
+ * enable the bank
+ */
+ cr |= SDRAM_BXCR_SDBE;
+
+ /*------------------------------------------------------------------
+ | This next section is hardware dependent and must be programmed
+ | to match the hardware.
+ +-----------------------------------------------------------------*/
+ if (dimm_num == 0) {
+ for (i = 0; i < num_banks; i++) {
+#ifndef CONFIG_BAMBOO
+ mtdcr(memcfga, mem_b0cr + (i << 2));
+#else
+ mtdcr(memcfga, mem_b1cr + (i << 2));
+#endif
+ temp = mfdcr(memcfgd) & ~(SDRAM_BXCR_SDBA_MASK |
+ SDRAM_BXCR_SDSZ_MASK |
+ SDRAM_BXCR_SDAM_MASK |
+ SDRAM_BXCR_SDBE);
+ cr |= temp;
+ cr |= bank_base_addr & SDRAM_BXCR_SDBA_MASK;
+ mtdcr(memcfgd, cr);
+ bank_base_addr += bank_size_bytes;
+ }
+ } else {
+ for (i = 0; i < num_banks; i++) {
+#ifndef CONFIG_BAMBOO
+ mtdcr(memcfga, mem_b2cr + (i << 2));
+#else
+ mtdcr(memcfga, mem_b3cr + (i << 2));
+#endif
+ temp = mfdcr(memcfgd) & ~(SDRAM_BXCR_SDBA_MASK |
+ SDRAM_BXCR_SDSZ_MASK |
+ SDRAM_BXCR_SDAM_MASK |
+ SDRAM_BXCR_SDBE);
+ cr |= temp;
+ cr |= bank_base_addr & SDRAM_BXCR_SDBA_MASK;
+ mtdcr(memcfgd, cr);
+ bank_base_addr += bank_size_bytes;
+ }
+ }
}
- }
}
- }
- return(bank_base_addr);
+ return(bank_base_addr);
}
void program_ecc (unsigned long num_bytes)
{
- unsigned long bank_base_addr;
- unsigned long current_address;
- unsigned long end_address;
- unsigned long address_increment;
- unsigned long cfg0;
-
- /*
- * get Memory Controller Options 0 data
- */
- mfsdram(mem_cfg0, cfg0);
-
- /*
- * reset the bank_base address
- */
- bank_base_addr = CFG_SDRAM_BASE;
-
- if ((cfg0 & SDRAM_CFG0_MCHK_MASK) != SDRAM_CFG0_MCHK_NON) {
- mtsdram(mem_cfg0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) |
- SDRAM_CFG0_MCHK_GEN);
-
- if ((cfg0 & SDRAM_CFG0_DMWD_MASK) == SDRAM_CFG0_DMWD_32) {
- address_increment = 4;
- }
- else {
- address_increment = 8;
- }
+ unsigned long bank_base_addr;
+ unsigned long current_address;
+ unsigned long end_address;
+ unsigned long address_increment;
+ unsigned long cfg0;
+
+ /*
+ * get Memory Controller Options 0 data
+ */
+ mfsdram(mem_cfg0, cfg0);
- current_address = (unsigned long)(bank_base_addr);
- end_address = (unsigned long)(bank_base_addr) + num_bytes;
+ /*
+ * reset the bank_base address
+ */
+ bank_base_addr = CFG_SDRAM_BASE;
- while (current_address < end_address) {
- *((unsigned long*)current_address) = 0x00000000;
- current_address += address_increment;
- }
+ if ((cfg0 & SDRAM_CFG0_MCHK_MASK) != SDRAM_CFG0_MCHK_NON) {
+ mtsdram(mem_cfg0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) |
+ SDRAM_CFG0_MCHK_GEN);
- mtsdram(mem_cfg0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) |
- SDRAM_CFG0_MCHK_CHK);
- }
+ if ((cfg0 & SDRAM_CFG0_DMWD_MASK) == SDRAM_CFG0_DMWD_32) {
+ address_increment = 4;
+ } else {
+ address_increment = 8;
+ }
+
+ current_address = (unsigned long)(bank_base_addr);
+ end_address = (unsigned long)(bank_base_addr) + num_bytes;
+
+ while (current_address < end_address) {
+ *((unsigned long*)current_address) = 0x00000000;
+ current_address += address_increment;
+ }
+
+ mtsdram(mem_cfg0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) |
+ SDRAM_CFG0_MCHK_CHK);
+ }
}
#endif /* CONFIG_440 */
diff --git a/cpu/ppc4xx/speed.c b/cpu/ppc4xx/speed.c
index 0d6d88a2ab..469f97d6f0 100644
--- a/cpu/ppc4xx/speed.c
+++ b/cpu/ppc4xx/speed.c
@@ -194,7 +194,96 @@ ulong get_PCI_freq (void)
#elif defined(CONFIG_440)
-#if !defined(CONFIG_440_GX)
+
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+void get_sys_info (sys_info_t *sysInfo)
+{
+ unsigned long temp;
+ unsigned long reg;
+ unsigned long lfdiv;
+ unsigned long m;
+ unsigned long prbdv0;
+ /*
+ WARNING: ASSUMES the following:
+ ENG=1
+ PRADV0=1
+ PRBDV0=1
+ */
+
+ /* Decode CPR0_PLLD0 for divisors */
+ mfclk(clk_plld, reg);
+ temp = (reg & PLLD_FWDVA_MASK) >> 16;
+ sysInfo->pllFwdDivA = temp ? temp : 16;
+ temp = (reg & PLLD_FWDVB_MASK) >> 8;
+ sysInfo->pllFwdDivB = temp ? temp: 8 ;
+ temp = (reg & PLLD_FBDV_MASK) >> 24;
+ sysInfo->pllFbkDiv = temp ? temp : 32;
+ lfdiv = reg & PLLD_LFBDV_MASK;
+
+ mfclk(clk_opbd, reg);
+ temp = (reg & OPBDDV_MASK) >> 24;
+ sysInfo->pllOpbDiv = temp ? temp : 4;
+
+ mfclk(clk_perd, reg);
+ temp = (reg & PERDV_MASK) >> 24;
+ sysInfo->pllExtBusDiv = temp ? temp : 8;
+
+ mfclk(clk_primbd, reg);
+ temp = (reg & PRBDV_MASK) >> 24;
+ prbdv0 = temp ? temp : 8;
+
+ mfclk(clk_spcid, reg);
+ temp = (reg & SPCID_MASK) >> 24;
+ sysInfo->pllPciDiv = temp ? temp : 4;
+
+ /* Calculate 'M' based on feedback source */
+ mfsdr(sdr_sdstp0, reg);
+ temp = (reg & PLLSYS0_SEL_MASK) >> 27;
+ if (temp == 0) { /* PLL output */
+ /* Figure which pll to use */
+ mfclk(clk_pllc, reg);
+ temp = (reg & PLLC_SRC_MASK) >> 29;
+ if (!temp) /* PLLOUTA */
+ m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivA;
+ else /* PLLOUTB */
+ m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivB;
+ }
+ else if (temp == 1) /* CPU output */
+ m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA;
+ else /* PerClk */
+ m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
+
+ /* Now calculate the individual clocks */
+ sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m>>1);
+ sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
+ sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB/prbdv0;
+ sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
+ sysInfo->freqEPB = sysInfo->freqPLB/sysInfo->pllExtBusDiv;
+ sysInfo->freqPCI = sysInfo->freqPLB/sysInfo->pllPciDiv;
+
+ /* Figure which timer source to use */
+ if (mfspr(ccr1) & 0x0080) { /* External Clock, assume same as SYS_CLK */
+ temp = sysInfo->freqProcessor / 2; /* Max extern clock speed */
+ if (CONFIG_SYS_CLK_FREQ > temp)
+ sysInfo->freqTmrClk = temp;
+ else
+ sysInfo->freqTmrClk = CONFIG_SYS_CLK_FREQ;
+ }
+ else /* Internal clock */
+ sysInfo->freqTmrClk = sysInfo->freqProcessor;
+}
+/********************************************
+ * get_PCI_freq
+ * return PCI bus freq in Hz
+ *********************************************/
+ulong get_PCI_freq (void)
+{
+ sys_info_t sys_info;
+ get_sys_info (&sys_info);
+ return sys_info.freqPCI;
+}
+
+#elif !defined(CONFIG_440GX)
void get_sys_info (sys_info_t * sysInfo)
{
unsigned long strp0;
@@ -220,8 +309,8 @@ void get_sys_info (sys_info_t * sysInfo)
sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m>>1);
sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB;
- if( get_pvr() == PVR_440GP_RB ) /* Rev B divs an extra 2 -- geez! */
- sysInfo->freqPLB >>= 1;
+ if( get_pvr() == PVR_440GP_RB ) /* Rev B divs an extra 2 -- geez! */
+ sysInfo->freqPLB >>= 1;
sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
sysInfo->freqEPB = sysInfo->freqOPB/sysInfo->pllExtBusDiv;
diff --git a/cpu/ppc4xx/start.S b/cpu/ppc4xx/start.S
index 3473baafc5..003c5b6bf1 100644
--- a/cpu/ppc4xx/start.S
+++ b/cpu/ppc4xx/start.S
@@ -158,19 +158,19 @@ _start_440:
/*----------------------------------------------------------------*/
/* Clear and set up some registers. */
/*----------------------------------------------------------------*/
- iccci r0,r0 /* NOTE: operands not used for 440 */
- dccci r0,r0 /* NOTE: operands not used for 440 */
+ iccci r0,r0 /* NOTE: operands not used for 440 */
+ dccci r0,r0 /* NOTE: operands not used for 440 */
sync
li r0,0
mtspr srr0,r0
mtspr srr1,r0
mtspr csrr0,r0
mtspr csrr1,r0
-#if defined (CONFIG_440_GX) /* NOTE: 440GX adds machine check status regs */
- mtspr mcsrr0,r0
- mtspr mcsrr1,r0
- mfspr r1, mcsr
- mtspr mcsr,r1
+#if defined (CONFIG_440GX) /* NOTE: 440GX adds machine check status regs */
+ mtspr mcsrr0,r0
+ mtspr mcsrr1,r0
+ mfspr r1, mcsr
+ mtspr mcsr,r1
#endif
/*----------------------------------------------------------------*/
/* Initialize debug */
@@ -204,13 +204,13 @@ _start_440:
/* Setup interrupt vectors */
/*----------------------------------------------------------------*/
mtspr ivpr,r0 /* Vectors start at 0x0000_0000 */
- li r1,0x0100
+ li r1,0x0100
mtspr ivor0,r1 /* Critical input */
- li r1,0x0200
+ li r1,0x0200
mtspr ivor1,r1 /* Machine check */
- li r1,0x0300
+ li r1,0x0300
mtspr ivor2,r1 /* Data storage */
- li r1,0x0400
+ li r1,0x0400
mtspr ivor3,r1 /* Instruction storage */
li r1,0x0500
mtspr ivor4,r1 /* External interrupt */
@@ -340,17 +340,17 @@ _start:
mtspr tcr,r0 /* disable all */
mtspr esr,r0 /* clear exception syndrome register */
mtxer r0 /* clear integer exception register */
-#if !defined(CONFIG_440_GX)
+#if !defined(CONFIG_440GX)
lis r1,0x0002 /* set CE bit (Critical Exceptions) */
ori r1,r1,0x1000 /* set ME bit (Machine Exceptions) */
mtmsr r1 /* change MSR */
-#else
+#elif !defined(CONFIG_440EP) && !defined(CONFIG_440GR)
bl __440gx_msr_set
b __440gx_msr_continue
__440gx_msr_set:
- lis r1, 0x0002 /* set CE bit (Critical Exceptions) */
- ori r1,r1,0x1000 /* set ME bit (Machine Exceptions) */
+ lis r1, 0x0002 /* set CE bit (Critical Exceptions) */
+ ori r1,r1,0x1000 /* set ME bit (Machine Exceptions) */
mtspr srr1,r1
mflr r1
mtspr srr0,r1
@@ -377,8 +377,25 @@ __440gx_msr_continue:
/* Setup the internal SRAM */
/*----------------------------------------------------------------*/
li r0,0
-#if defined (CONFIG_440_GX)
- mtdcr l2_cache_cfg,r0 /* Ensure L2 Cache is off */
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+ /* Clear Dcache to use as RAM */
+ addis r3,r0,CFG_INIT_RAM_ADDR@h
+ ori r3,r3,CFG_INIT_RAM_ADDR@l
+ addis r4,r0,CFG_INIT_RAM_END@h
+ ori r4,r4,CFG_INIT_RAM_END@l
+ rlwinm. r5,r4,0,27,31
+ rlwinm r5,r4,27,5,31
+ beq ..d_ran
+ addi r5,r5,0x0001
+..d_ran:
+ mtctr r5
+..d_ag:
+ dcbz r0,r3
+ addi r3,r3,32
+ bdnz ..d_ag
+#else
+#if defined (CONFIG_440GX)
+ mtdcr l2_cache_cfg,r0 /* Ensure L2 Cache is off */
#endif
mtdcr isram0_sb1cr,r0 /* Disable bank 1 */
@@ -392,22 +409,23 @@ __440gx_msr_continue:
mtdcr isram0_pmeg,r1
lis r1,0x8000 /* BAS = 8000_0000 */
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX)
ori r1,r1,0x0980 /* first 64k */
- mtdcr isram0_sb0cr,r1
+ mtdcr isram0_sb0cr,r1
lis r1,0x8001
ori r1,r1,0x0980 /* second 64k */
- mtdcr isram0_sb1cr,r1
+ mtdcr isram0_sb1cr,r1
lis r1, 0x8002
ori r1,r1, 0x0980 /* third 64k */
- mtdcr isram0_sb2cr,r1
+ mtdcr isram0_sb2cr,r1
lis r1, 0x8003
ori r1,r1, 0x0980 /* fourth 64k */
- mtdcr isram0_sb3cr,r1
+ mtdcr isram0_sb3cr,r1
#else
ori r1,r1,0x0380 /* 8k rw */
mtdcr isram0_sb0cr,r1
#endif
+#endif
/*----------------------------------------------------------------*/
/* Setup the stack in internal SRAM */
@@ -592,11 +610,11 @@ __440gx_msr_continue:
/*----------------------------------------------------------------------- */
/* DMA Status, clear to come up clean */
/*----------------------------------------------------------------------- */
- addis r3,r0, 0xFFFF /* Clear all existing DMA status */
- ori r3,r3, 0xFFFF
- mtdcr dmasr, r3
+ addis r3,r0, 0xFFFF /* Clear all existing DMA status */
+ ori r3,r3, 0xFFFF
+ mtdcr dmasr, r3
- bl ppc405ep_init /* do ppc405ep specific init */
+ bl ppc405ep_init /* do ppc405ep specific init */
#endif /* CONFIG_405EP */
#if defined(CFG_OCM_DATA_ADDR) && defined(CFG_OCM_DATA_SIZE)
@@ -606,7 +624,7 @@ __440gx_msr_continue:
/* Setup OCM */
lis r0, 0x7FFF
ori r0, r0, 0xFFFF
- mfdcr r3, ocmiscntl /* get instr-side IRAM config */
+ mfdcr r3, ocmiscntl /* get instr-side IRAM config */
mfdcr r4, ocmdscntl /* get data-side IRAM config */
and r3, r3, r0 /* disable data-side IRAM */
and r4, r4, r0 /* disable data-side IRAM */
@@ -648,13 +666,13 @@ __440gx_msr_continue:
/* set stack pointer and clear stack to known value */
lis r1,CFG_INIT_RAM_ADDR@h
- ori r1,r1,CFG_INIT_SP_OFFSET@l
+ ori r1,r1,CFG_INIT_SP_OFFSET@l
li r4,2048 /* we store 2048 words to stack */
mtctr r4
lis r2,CFG_INIT_RAM_ADDR@h /* we also clear data area */
- ori r2,r2,CFG_INIT_RAM_END@l /* so cant copy value from r1 */
+ ori r2,r2,CFG_INIT_RAM_END@l /* so cant copy value from r1 */
lis r4,0xdead /* we store 0xdeaddead in the stack */
ori r4,r4,0xdead
@@ -703,7 +721,7 @@ __440gx_msr_continue:
#endif /* CFG_INIT_DCACHE_CS */
/*----------------------------------------------------------------------- */
- /* Initialize SDRAM Controller */
+ /* Initialize SDRAM Controller */
/*----------------------------------------------------------------------- */
bl sdram_init
@@ -729,11 +747,11 @@ __440gx_msr_continue:
ori r0, r0, RESET_VECTOR@l
stwu r1, -8(r1) /* Save back chain and move SP */
stw r0, +12(r1) /* Save return addr (underflow vect) */
-#endif /* !(CFG_INIT_DCACHE_CS || !CFG_TEM_STACK_OCM) */
+#endif /* !(CFG_INIT_DCACHE_CS || !CFG_TEM_STACK_OCM) */
GET_GOT /* initialize GOT access */
- bl cpu_init_f /* run low-level CPU init code (from Flash) */
+ bl cpu_init_f /* run low-level CPU init code (from Flash) */
/* NEVER RETURNS! */
bl board_init_f /* run first part of init code (from Flash) */
@@ -957,9 +975,9 @@ invalidate_icache:
invalidate_dcache:
addi r6,0,0x0000 /* clear GPR 6 */
/* Do loop for # of dcache congruence classes. */
-#if defined(CONFIG_440_GX)
- lis r7, (CFG_DCACHE_SIZE / CFG_CACHELINE_SIZE / 2)@ha /* TBS for large sized cache */
- ori r7, r7, (CFG_DCACHE_SIZE / CFG_CACHELINE_SIZE / 2)@l
+#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || defined(CONFIG_440GR)
+ lis r7, (CFG_DCACHE_SIZE / CFG_CACHELINE_SIZE / 2)@ha /* TBS for large sized cache */
+ ori r7, r7, (CFG_DCACHE_SIZE / CFG_CACHELINE_SIZE / 2)@l
#else
addi r7,r0, (CFG_DCACHE_SIZE / CFG_CACHELINE_SIZE / 2)
#endif
@@ -983,17 +1001,17 @@ flush_dcache:
mtdccr r10
/* do loop for # of congruence classes. */
-#if defined(CONFIG_440_GX)
- lis r10,(CFG_DCACHE_SIZE / CFG_CACHELINE_SIZE / 2)@ha /* TBS: for large cache sizes */
- ori r10,r10,(CFG_DCACHE_SIZE / CFG_CACHELINE_SIZE / 2)@l
- lis r11,(CFG_DCACHE_SIZE / 2)@ha /* D cache set size - 2 way sets */
- ori r11,r11,(CFG_DCACHE_SIZE / 2)@l /* D cache set size - 2 way sets */
+#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || defined(CONFIG_440GR)
+ lis r10,(CFG_DCACHE_SIZE / CFG_CACHELINE_SIZE / 2)@ha /* TBS: for large cache sizes */
+ ori r10,r10,(CFG_DCACHE_SIZE / CFG_CACHELINE_SIZE / 2)@l
+ lis r11,(CFG_DCACHE_SIZE / 2)@ha /* D cache set size - 2 way sets */
+ ori r11,r11,(CFG_DCACHE_SIZE / 2)@l /* D cache set size - 2 way sets */
#else
addi r10,r0,(CFG_DCACHE_SIZE / CFG_CACHELINE_SIZE / 2)
addi r11,r0,(CFG_DCACHE_SIZE / 2) /* D cache set size - 2 way sets */
#endif
mtctr r10
- addi r10,r0,(0xE000-0x10000) /* start at 0xFFFFE000 */
+ addi r10,r0,(0xE000-0x10000) /* start at 0xFFFFE000 */
add r11,r10,r11 /* add to get to other side of cache line */
..flush_dcache_loop:
lwz r3,0(r10) /* least recently used side */
@@ -1210,6 +1228,15 @@ ppcSync:
*/
.globl relocate_code
relocate_code:
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+ dccci 0,0 /* Invalidate data cache, now no longer our stack */
+ sync
+ addi r1,r0,0x0000 /* Tlb entry #0 */
+ tlbre r0,r1,0x0002 /* Read contents */
+ ori r0,r0,0x0c00 /* Or in the inhibit, write through bit */
+ tlbwe r0,r1,0x0002 /* Save it out */
+ isync
+#endif
mr r1, r3 /* Set new stack pointer */
mr r9, r4 /* Save copy of Init Data pointer */
mr r10, r5 /* Save copy of Destination Address */
@@ -1428,12 +1455,12 @@ trap_reloc:
/**************************************************************************/
-/* PPC405EP specific stuff */
+/* PPC405EP specific stuff */
/**************************************************************************/
#ifdef CONFIG_405EP
ppc405ep_init:
-#ifdef CONFIG_BUBINGA405EP
+#ifdef CONFIG_BUBINGA
/*
* Initialize EBC chip selects 1 & 4 and GPIO pins (for alternate
* function) to support FPGA and NVRAM accesses below.
@@ -1512,43 +1539,43 @@ ppc405ep_init:
mtdcr ebccfgd,r3
#endif
- addi r3,0,CPC0_PCI_HOST_CFG_EN
-#ifdef CONFIG_BUBINGA405EP
+ addi r3,0,CPC0_PCI_HOST_CFG_EN
+#ifdef CONFIG_BUBINGA
/*
!-----------------------------------------------------------------------
! Check FPGA for PCI internal/external arbitration
! If board is set to internal arbitration, update cpc0_pci
!-----------------------------------------------------------------------
*/
- addis r5,r0,FPGA_REG1@h /* set offset for FPGA_REG1 */
- ori r5,r5,FPGA_REG1@l
- lbz r5,0x0(r5) /* read to get PCI arb selection */
- andi. r6,r5,FPGA_REG1_PCI_INT_ARB /* using internal arbiter ?*/
- beq ..pci_cfg_set /* if not set, then bypass reg write*/
+ addis r5,r0,FPGA_REG1@h /* set offset for FPGA_REG1 */
+ ori r5,r5,FPGA_REG1@l
+ lbz r5,0x0(r5) /* read to get PCI arb selection */
+ andi. r6,r5,FPGA_REG1_PCI_INT_ARB /* using internal arbiter ?*/
+ beq ..pci_cfg_set /* if not set, then bypass reg write*/
#endif
- ori r3,r3,CPC0_PCI_ARBIT_EN
+ ori r3,r3,CPC0_PCI_ARBIT_EN
..pci_cfg_set:
- mtdcr CPC0_PCI, r3 /* Enable internal arbiter*/
+ mtdcr CPC0_PCI, r3 /* Enable internal arbiter*/
/*
!-----------------------------------------------------------------------
! Check to see if chip is in bypass mode.
! If so, write stored CPC0_PLLMR0 and CPC0_PLLMR1 values and perform a
! CPU reset Otherwise, skip this step and keep going.
- ! Note: Running BIOS in bypass mode is not supported since PLB speed
- ! will not be fast enough for the SDRAM (min 66MHz)
+ ! Note: Running BIOS in bypass mode is not supported since PLB speed
+ ! will not be fast enough for the SDRAM (min 66MHz)
!-----------------------------------------------------------------------
*/
- mfdcr r5, CPC0_PLLMR1
- rlwinm r4,r5,1,0x1 /* get system clock source (SSCS) */
- cmpi cr0,0,r4,0x1
+ mfdcr r5, CPC0_PLLMR1
+ rlwinm r4,r5,1,0x1 /* get system clock source (SSCS) */
+ cmpi cr0,0,r4,0x1
- beq pll_done /* if SSCS =b'1' then PLL has */
+ beq pll_done /* if SSCS =b'1' then PLL has */
/* already been set */
/* and CPU has been reset */
/* so skip to next section */
-#ifdef CONFIG_BUBINGA405EP
+#ifdef CONFIG_BUBINGA
/*
!-----------------------------------------------------------------------
! Read NVRAM to get value to write in PLLMR.
@@ -1557,40 +1584,40 @@ ppc405ep_init:
! See CPU_DEFAULT_200 and CPU_DEFAULT_266 above.
!
! WARNING: This code assumes the first three words in the nvram_t
- ! structure in openbios.h. Changing the beginning of
- ! the structure will break this code.
+ ! structure in openbios.h. Changing the beginning of
+ ! the structure will break this code.
!
!-----------------------------------------------------------------------
*/
- addis r3,0,NVRAM_BASE@h
- addi r3,r3,NVRAM_BASE@l
-
- lwz r4, 0(r3)
- addis r5,0,NVRVFY1@h
- addi r5,r5,NVRVFY1@l
- cmp cr0,0,r4,r5 /* Compare 1st NVRAM Magic number*/
- bne ..no_pllset
- addi r3,r3,4
- lwz r4, 0(r3)
- addis r5,0,NVRVFY2@h
- addi r5,r5,NVRVFY2@l
- cmp cr0,0,r4,r5 /* Compare 2 NVRAM Magic number */
- bne ..no_pllset
- addi r3,r3,8 /* Skip over conf_size */
- lwz r4, 4(r3) /* Load PLLMR1 value from NVRAM */
- lwz r3, 0(r3) /* Load PLLMR0 value from NVRAM */
- rlwinm r5,r4,1,0x1 /* get system clock source (SSCS) */
- cmpi cr0,0,r5,1 /* See if PLL is locked */
- beq pll_write
+ addis r3,0,NVRAM_BASE@h
+ addi r3,r3,NVRAM_BASE@l
+
+ lwz r4, 0(r3)
+ addis r5,0,NVRVFY1@h
+ addi r5,r5,NVRVFY1@l
+ cmp cr0,0,r4,r5 /* Compare 1st NVRAM Magic number*/
+ bne ..no_pllset
+ addi r3,r3,4
+ lwz r4, 0(r3)
+ addis r5,0,NVRVFY2@h
+ addi r5,r5,NVRVFY2@l
+ cmp cr0,0,r4,r5 /* Compare 2 NVRAM Magic number */
+ bne ..no_pllset
+ addi r3,r3,8 /* Skip over conf_size */
+ lwz r4, 4(r3) /* Load PLLMR1 value from NVRAM */
+ lwz r3, 0(r3) /* Load PLLMR0 value from NVRAM */
+ rlwinm r5,r4,1,0x1 /* get system clock source (SSCS) */
+ cmpi cr0,0,r5,1 /* See if PLL is locked */
+ beq pll_write
..no_pllset:
-#endif /* CONFIG_BUBINGA405EP */
+#endif /* CONFIG_BUBINGA */
- addis r3,0,PLLMR0_DEFAULT@h /* PLLMR0 default value */
- ori r3,r3,PLLMR0_DEFAULT@l /* */
- addis r4,0,PLLMR1_DEFAULT@h /* PLLMR1 default value */
- ori r4,r4,PLLMR1_DEFAULT@l /* */
+ addis r3,0,PLLMR0_DEFAULT@h /* PLLMR0 default value */
+ ori r3,r3,PLLMR0_DEFAULT@l /* */
+ addis r4,0,PLLMR1_DEFAULT@h /* PLLMR1 default value */
+ ori r4,r4,PLLMR1_DEFAULT@l /* */
- b pll_write /* Write the CPC0_PLLMR with new value */
+ b pll_write /* Write the CPC0_PLLMR with new value */
pll_done:
/*
@@ -1599,27 +1626,27 @@ pll_done:
! This is needed to enable PCI if not booting from serial EPROM
!-----------------------------------------------------------------------
*/
- addi r3, 0, 0x0
- mtdcr CPC0_SRR, r3
+ addi r3, 0, 0x0
+ mtdcr CPC0_SRR, r3
- addis r3,0,0x0010
- mtctr r3
+ addis r3,0,0x0010
+ mtctr r3
pci_wait:
- bdnz pci_wait
+ bdnz pci_wait
blr /* return to main code */
/*
!-----------------------------------------------------------------------------
-! Function: pll_write
-! Description: Updates the value of the CPC0_PLLMR according to CMOS27E documentation
-! That is:
-! 1. Pll is first disabled (de-activated by putting in bypass mode)
-! 2. PLL is reset
-! 3. Clock dividers are set while PLL is held in reset and bypassed
-! 4. PLL Reset is cleared
-! 5. Wait 100us for PLL to lock
-! 6. A core reset is performed
+! Function: pll_write
+! Description: Updates the value of the CPC0_PLLMR according to CMOS27E documentation
+! That is:
+! 1. Pll is first disabled (de-activated by putting in bypass mode)
+! 2. PLL is reset
+! 3. Clock dividers are set while PLL is held in reset and bypassed
+! 4. PLL Reset is cleared
+! 5. Wait 100us for PLL to lock
+! 6. A core reset is performed
! Input: r3 = Value to write to CPC0_PLLMR0
! Input: r4 = Value to write to CPC0_PLLMR1
! Output r3 = none
@@ -1628,41 +1655,41 @@ pci_wait:
pll_write:
mfdcr r5, CPC0_UCR
andis. r5,r5,0xFFFF
- ori r5,r5,0x0101 /* Stop the UART clocks */
- mtdcr CPC0_UCR,r5 /* Before changing PLL */
+ ori r5,r5,0x0101 /* Stop the UART clocks */
+ mtdcr CPC0_UCR,r5 /* Before changing PLL */
mfdcr r5, CPC0_PLLMR1
- rlwinm r5,r5,0,0x7FFFFFFF /* Disable PLL */
- mtdcr CPC0_PLLMR1,r5
- oris r5,r5,0x4000 /* Set PLL Reset */
- mtdcr CPC0_PLLMR1,r5
-
- mtdcr CPC0_PLLMR0,r3 /* Set clock dividers */
- rlwinm r5,r4,0,0x3FFFFFFF /* Reset & Bypass new PLL dividers */
- oris r5,r5,0x4000 /* Set PLL Reset */
- mtdcr CPC0_PLLMR1,r5 /* Set clock dividers */
- rlwinm r5,r5,0,0xBFFFFFFF /* Clear PLL Reset */
- mtdcr CPC0_PLLMR1,r5
+ rlwinm r5,r5,0,0x7FFFFFFF /* Disable PLL */
+ mtdcr CPC0_PLLMR1,r5
+ oris r5,r5,0x4000 /* Set PLL Reset */
+ mtdcr CPC0_PLLMR1,r5
+
+ mtdcr CPC0_PLLMR0,r3 /* Set clock dividers */
+ rlwinm r5,r4,0,0x3FFFFFFF /* Reset & Bypass new PLL dividers */
+ oris r5,r5,0x4000 /* Set PLL Reset */
+ mtdcr CPC0_PLLMR1,r5 /* Set clock dividers */
+ rlwinm r5,r5,0,0xBFFFFFFF /* Clear PLL Reset */
+ mtdcr CPC0_PLLMR1,r5
/*
! Wait min of 100us for PLL to lock.
! See CMOS 27E databook for more info.
! At 200MHz, that means waiting 20,000 instructions
*/
- addi r3,0,20000 /* 2000 = 0x4e20 */
- mtctr r3
+ addi r3,0,20000 /* 2000 = 0x4e20 */
+ mtctr r3
pll_wait:
- bdnz pll_wait
+ bdnz pll_wait
- oris r5,r5,0x8000 /* Enable PLL */
- mtdcr CPC0_PLLMR1,r5 /* Engage */
+ oris r5,r5,0x8000 /* Enable PLL */
+ mtdcr CPC0_PLLMR1,r5 /* Engage */
/*
* Reset CPU to guarantee timings are OK
* Not sure if this is needed...
*/
addis r3,0,0x1000
- mtspr dbcr0,r3 /* This will cause a CPU core reset, and */
+ mtspr dbcr0,r3 /* This will cause a CPU core reset, and */
/* execution will continue from the poweron */
/* vector of 0xfffffffc */
#endif /* CONFIG_405EP */
diff --git a/cpu/ppc4xx/usb_ohci.c b/cpu/ppc4xx/usb_ohci.c
new file mode 100644
index 0000000000..bb5765891f
--- /dev/null
+++ b/cpu/ppc4xx/usb_ohci.c
@@ -0,0 +1,1642 @@
+/*
+ * URB OHCI HCD (Host Controller Driver) for USB on the PPC440EP.
+ *
+ * (C) Copyright 2003-2004
+ * Gary Jennejohn, DENX Software Engineering <gj@denx.de>
+ *
+ * (C) Copyright 2004
+ * Pierre Aubert, Staubli Faverges <p.aubert@staubli.com>
+ *
+ * Note: Much of this code has been derived from Linux 2.4
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2002 David Brownell
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+/*
+ * IMPORTANT NOTES
+ * 1 - this driver is intended for use with USB Mass Storage Devices
+ * (BBB) ONLY. There is NO support for Interrupt or Isochronous pipes!
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_USB_OHCI
+
+#include <malloc.h>
+#include <usb.h>
+#include "usb_ohci.h"
+
+#include "usbdev.h"
+
+#define OHCI_USE_NPS /* force NoPowerSwitching mode */
+#undef OHCI_VERBOSE_DEBUG /* not always helpful */
+#undef DEBUG
+#undef SHOW_INFO
+#undef OHCI_FILL_TRACE
+
+/* For initializing controller (mask in an HCFS mode too) */
+#define OHCI_CONTROL_INIT \
+ (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
+
+#define readl(a) (*((vu_long *)(a)))
+#define writel(a, b) (*((vu_long *)(b)) = ((vu_long)a))
+
+#define min_t(type,x,y) ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
+
+#ifdef DEBUG
+#define dbg(format, arg...) printf("DEBUG: " format "\n", ## arg)
+#else
+#define dbg(format, arg...) do {} while(0)
+#endif /* DEBUG */
+#define err(format, arg...) printf("ERROR: " format "\n", ## arg)
+#ifdef SHOW_INFO
+#define info(format, arg...) printf("INFO: " format "\n", ## arg)
+#else
+#define info(format, arg...) do {} while(0)
+#endif
+
+#define m16_swap(x) swap_16(x)
+#define m32_swap(x) swap_32(x)
+
+#ifdef CONFIG_440EP
+#define ohci_cpu_to_le16(x) (x)
+#define ohci_cpu_to_le32(x) (x)
+#else
+#define ohci_cpu_to_le16(x) swap_16(x)
+#define ohci_cpu_to_le32(x) swap_32(x)
+#endif
+
+/* global ohci_t */
+static ohci_t gohci;
+/* this must be aligned to a 256 byte boundary */
+struct ohci_hcca ghcca[1];
+/* a pointer to the aligned storage */
+struct ohci_hcca *phcca;
+/* this allocates EDs for all possible endpoints */
+struct ohci_device ohci_dev;
+/* urb_priv */
+urb_priv_t urb_priv;
+/* RHSC flag */
+int got_rhsc;
+/* device which was disconnected */
+struct usb_device *devgone;
+/* flag guarding URB transation */
+int urb_finished = 0;
+
+/*-------------------------------------------------------------------------*/
+
+/* AMD-756 (D2 rev) reports corrupt register contents in some cases.
+ * The erratum (#4) description is incorrect. AMD's workaround waits
+ * till some bits (mostly reserved) are clear; ok for all revs.
+ */
+#define OHCI_QUIRK_AMD756 0xabcd
+#define read_roothub(hc, register, mask) ({ \
+ u32 temp = readl (&hc->regs->roothub.register); \
+ if (hc->flags & OHCI_QUIRK_AMD756) \
+ while (temp & mask) \
+ temp = readl (&hc->regs->roothub.register); \
+ temp; })
+
+static u32 roothub_a (struct ohci *hc)
+ { return read_roothub (hc, a, 0xfc0fe000); }
+static inline u32 roothub_b (struct ohci *hc)
+ { return readl (&hc->regs->roothub.b); }
+static inline u32 roothub_status (struct ohci *hc)
+ { return readl (&hc->regs->roothub.status); }
+static u32 roothub_portstatus (struct ohci *hc, int i)
+ { return read_roothub (hc, portstatus [i], 0xffe0fce0); }
+
+
+/* forward declaration */
+static int hc_interrupt (void);
+static void
+td_submit_job (struct usb_device * dev, unsigned long pipe, void * buffer,
+ int transfer_len, struct devrequest * setup, urb_priv_t * urb, int interval);
+
+/*-------------------------------------------------------------------------*
+ * URB support functions
+ *-------------------------------------------------------------------------*/
+
+/* free HCD-private data associated with this URB */
+
+static void urb_free_priv (urb_priv_t * urb)
+{
+ int i;
+ int last;
+ struct td * td;
+
+ last = urb->length - 1;
+ if (last >= 0) {
+ for (i = 0; i <= last; i++) {
+ td = urb->td[i];
+ if (td) {
+ td->usb_dev = NULL;
+ urb->td[i] = NULL;
+ }
+ }
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef DEBUG
+static int sohci_get_current_frame_number (struct usb_device * dev);
+
+/* debug| print the main components of an URB
+ * small: 0) header + data packets 1) just header */
+
+static void pkt_print (struct usb_device * dev, unsigned long pipe, void * buffer,
+ int transfer_len, struct devrequest * setup, char * str, int small)
+{
+ urb_priv_t * purb = &urb_priv;
+
+ dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d/%d stat:%#lx",
+ str,
+ sohci_get_current_frame_number (dev),
+ usb_pipedevice (pipe),
+ usb_pipeendpoint (pipe),
+ usb_pipeout (pipe)? 'O': 'I',
+ usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"):
+ (usb_pipecontrol (pipe)? "CTRL": "BULK"),
+ purb->actual_length,
+ transfer_len, dev->status);
+#ifdef OHCI_VERBOSE_DEBUG
+ if (!small) {
+ int i, len;
+
+ if (usb_pipecontrol (pipe)) {
+ printf (__FILE__ ": cmd(8):");
+ for (i = 0; i < 8 ; i++)
+ printf (" %02x", ((__u8 *) setup) [i]);
+ printf ("\n");
+ }
+ if (transfer_len > 0 && buffer) {
+ printf (__FILE__ ": data(%d/%d):",
+ purb->actual_length,
+ transfer_len);
+ len = usb_pipeout (pipe)?
+ transfer_len: purb->actual_length;
+ for (i = 0; i < 16 && i < len; i++)
+ printf (" %02x", ((__u8 *) buffer) [i]);
+ printf ("%s\n", i < len? "...": "");
+ }
+ }
+#endif
+}
+
+/* just for debugging; prints non-empty branches of the int ed tree inclusive iso eds*/
+void ep_print_int_eds (ohci_t *ohci, char * str) {
+ int i, j;
+ __u32 * ed_p;
+ for (i= 0; i < 32; i++) {
+ j = 5;
+ ed_p = &(ohci->hcca->int_table [i]);
+ if (*ed_p == 0)
+ continue;
+ printf (__FILE__ ": %s branch int %2d(%2x):", str, i, i);
+ while (*ed_p != 0 && j--) {
+ ed_t *ed = (ed_t *)ohci_cpu_to_le32(ed_p);
+ printf (" ed: %4x;", ed->hwINFO);
+ ed_p = &ed->hwNextED;
+ }
+ printf ("\n");
+ }
+}
+
+static void ohci_dump_intr_mask (char *label, __u32 mask)
+{
+ dbg ("%s: 0x%08x%s%s%s%s%s%s%s%s%s",
+ label,
+ mask,
+ (mask & OHCI_INTR_MIE) ? " MIE" : "",
+ (mask & OHCI_INTR_OC) ? " OC" : "",
+ (mask & OHCI_INTR_RHSC) ? " RHSC" : "",
+ (mask & OHCI_INTR_FNO) ? " FNO" : "",
+ (mask & OHCI_INTR_UE) ? " UE" : "",
+ (mask & OHCI_INTR_RD) ? " RD" : "",
+ (mask & OHCI_INTR_SF) ? " SF" : "",
+ (mask & OHCI_INTR_WDH) ? " WDH" : "",
+ (mask & OHCI_INTR_SO) ? " SO" : ""
+ );
+}
+
+static void maybe_print_eds (char *label, __u32 value)
+{
+ ed_t *edp = (ed_t *)value;
+
+ if (value) {
+ dbg ("%s %08x", label, value);
+ dbg ("%08x", edp->hwINFO);
+ dbg ("%08x", edp->hwTailP);
+ dbg ("%08x", edp->hwHeadP);
+ dbg ("%08x", edp->hwNextED);
+ }
+}
+
+static char * hcfs2string (int state)
+{
+ switch (state) {
+ case OHCI_USB_RESET: return "reset";
+ case OHCI_USB_RESUME: return "resume";
+ case OHCI_USB_OPER: return "operational";
+ case OHCI_USB_SUSPEND: return "suspend";
+ }
+ return "?";
+}
+
+/* dump control and status registers */
+static void ohci_dump_status (ohci_t *controller)
+{
+ struct ohci_regs *regs = controller->regs;
+ __u32 temp;
+
+ temp = readl (&regs->revision) & 0xff;
+ if (temp != 0x10)
+ dbg ("spec %d.%d", (temp >> 4), (temp & 0x0f));
+
+ temp = readl (&regs->control);
+ dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp,
+ (temp & OHCI_CTRL_RWE) ? " RWE" : "",
+ (temp & OHCI_CTRL_RWC) ? " RWC" : "",
+ (temp & OHCI_CTRL_IR) ? " IR" : "",
+ hcfs2string (temp & OHCI_CTRL_HCFS),
+ (temp & OHCI_CTRL_BLE) ? " BLE" : "",
+ (temp & OHCI_CTRL_CLE) ? " CLE" : "",
+ (temp & OHCI_CTRL_IE) ? " IE" : "",
+ (temp & OHCI_CTRL_PLE) ? " PLE" : "",
+ temp & OHCI_CTRL_CBSR
+ );
+
+ temp = readl (&regs->cmdstatus);
+ dbg ("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp,
+ (temp & OHCI_SOC) >> 16,
+ (temp & OHCI_OCR) ? " OCR" : "",
+ (temp & OHCI_BLF) ? " BLF" : "",
+ (temp & OHCI_CLF) ? " CLF" : "",
+ (temp & OHCI_HCR) ? " HCR" : ""
+ );
+
+ ohci_dump_intr_mask ("intrstatus", readl (&regs->intrstatus));
+ ohci_dump_intr_mask ("intrenable", readl (&regs->intrenable));
+
+ maybe_print_eds ("ed_periodcurrent", readl (&regs->ed_periodcurrent));
+
+ maybe_print_eds ("ed_controlhead", readl (&regs->ed_controlhead));
+ maybe_print_eds ("ed_controlcurrent", readl (&regs->ed_controlcurrent));
+
+ maybe_print_eds ("ed_bulkhead", readl (&regs->ed_bulkhead));
+ maybe_print_eds ("ed_bulkcurrent", readl (&regs->ed_bulkcurrent));
+
+ maybe_print_eds ("donehead", readl (&regs->donehead));
+}
+
+static void ohci_dump_roothub (ohci_t *controller, int verbose)
+{
+ __u32 temp, ndp, i;
+
+ temp = roothub_a (controller);
+ ndp = (temp & RH_A_NDP);
+
+ if (verbose) {
+ dbg ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp,
+ ((temp & RH_A_POTPGT) >> 24) & 0xff,
+ (temp & RH_A_NOCP) ? " NOCP" : "",
+ (temp & RH_A_OCPM) ? " OCPM" : "",
+ (temp & RH_A_DT) ? " DT" : "",
+ (temp & RH_A_NPS) ? " NPS" : "",
+ (temp & RH_A_PSM) ? " PSM" : "",
+ ndp
+ );
+ temp = roothub_b (controller);
+ dbg ("roothub.b: %08x PPCM=%04x DR=%04x",
+ temp,
+ (temp & RH_B_PPCM) >> 16,
+ (temp & RH_B_DR)
+ );
+ temp = roothub_status (controller);
+ dbg ("roothub.status: %08x%s%s%s%s%s%s",
+ temp,
+ (temp & RH_HS_CRWE) ? " CRWE" : "",
+ (temp & RH_HS_OCIC) ? " OCIC" : "",
+ (temp & RH_HS_LPSC) ? " LPSC" : "",
+ (temp & RH_HS_DRWE) ? " DRWE" : "",
+ (temp & RH_HS_OCI) ? " OCI" : "",
+ (temp & RH_HS_LPS) ? " LPS" : ""
+ );
+ }
+
+ for (i = 0; i < ndp; i++) {
+ temp = roothub_portstatus (controller, i);
+ dbg ("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s",
+ i,
+ temp,
+ (temp & RH_PS_PRSC) ? " PRSC" : "",
+ (temp & RH_PS_OCIC) ? " OCIC" : "",
+ (temp & RH_PS_PSSC) ? " PSSC" : "",
+ (temp & RH_PS_PESC) ? " PESC" : "",
+ (temp & RH_PS_CSC) ? " CSC" : "",
+
+ (temp & RH_PS_LSDA) ? " LSDA" : "",
+ (temp & RH_PS_PPS) ? " PPS" : "",
+ (temp & RH_PS_PRS) ? " PRS" : "",
+ (temp & RH_PS_POCI) ? " POCI" : "",
+ (temp & RH_PS_PSS) ? " PSS" : "",
+
+ (temp & RH_PS_PES) ? " PES" : "",
+ (temp & RH_PS_CCS) ? " CCS" : ""
+ );
+ }
+}
+
+static void ohci_dump (ohci_t *controller, int verbose)
+{
+ dbg ("OHCI controller usb-%s state", controller->slot_name);
+
+ /* dumps some of the state we know about */
+ ohci_dump_status (controller);
+ if (verbose)
+ ep_print_int_eds (controller, "hcca");
+ dbg ("hcca frame #%04x", controller->hcca->frame_no);
+ ohci_dump_roothub (controller, 1);
+}
+
+
+#endif /* DEBUG */
+
+/*-------------------------------------------------------------------------*
+ * Interface functions (URB)
+ *-------------------------------------------------------------------------*/
+
+/* get a transfer request */
+
+int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int transfer_len, struct devrequest *setup, int interval)
+{
+ ohci_t *ohci;
+ ed_t * ed;
+ urb_priv_t *purb_priv;
+ int i, size = 0;
+
+ ohci = &gohci;
+
+ /* when controller's hung, permit only roothub cleanup attempts
+ * such as powering down ports */
+ if (ohci->disabled) {
+ err("sohci_submit_job: EPIPE");
+ return -1;
+ }
+
+ /* if we have an unfinished URB from previous transaction let's
+ * fail and scream as quickly as possible so as not to corrupt
+ * further communication */
+ if (!urb_finished) {
+ err("sohci_submit_job: URB NOT FINISHED");
+ return -1;
+ }
+ /* we're about to begin a new transaction here so mark the URB unfinished */
+ urb_finished = 0;
+
+ /* every endpoint has a ed, locate and fill it */
+ if (!(ed = ep_add_ed (dev, pipe))) {
+ err("sohci_submit_job: ENOMEM");
+ return -1;
+ }
+
+ /* for the private part of the URB we need the number of TDs (size) */
+ switch (usb_pipetype (pipe)) {
+ case PIPE_BULK: /* one TD for every 4096 Byte */
+ size = (transfer_len - 1) / 4096 + 1;
+ break;
+ case PIPE_CONTROL: /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */
+ size = (transfer_len == 0)? 2:
+ (transfer_len - 1) / 4096 + 3;
+ break;
+ }
+
+ if (size >= (N_URB_TD - 1)) {
+ err("need %d TDs, only have %d", size, N_URB_TD);
+ return -1;
+ }
+ purb_priv = &urb_priv;
+ purb_priv->pipe = pipe;
+
+ /* fill the private part of the URB */
+ purb_priv->length = size;
+ purb_priv->ed = ed;
+ purb_priv->actual_length = 0;
+
+ /* allocate the TDs */
+ /* note that td[0] was allocated in ep_add_ed */
+ for (i = 0; i < size; i++) {
+ purb_priv->td[i] = td_alloc (dev);
+ if (!purb_priv->td[i]) {
+ purb_priv->length = i;
+ urb_free_priv (purb_priv);
+ err("sohci_submit_job: ENOMEM");
+ return -1;
+ }
+ }
+
+ if (ed->state == ED_NEW || (ed->state & ED_DEL)) {
+ urb_free_priv (purb_priv);
+ err("sohci_submit_job: EINVAL");
+ return -1;
+ }
+
+ /* link the ed into a chain if is not already */
+ if (ed->state != ED_OPER)
+ ep_link (ohci, ed);
+
+ /* fill the TDs and link it to the ed */
+ td_submit_job(dev, pipe, buffer, transfer_len, setup, purb_priv, interval);
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef DEBUG
+/* tell us the current USB frame number */
+
+static int sohci_get_current_frame_number (struct usb_device *usb_dev)
+{
+ ohci_t *ohci = &gohci;
+
+ return ohci_cpu_to_le16 (ohci->hcca->frame_no);
+}
+#endif
+
+/*-------------------------------------------------------------------------*
+ * ED handling functions
+ *-------------------------------------------------------------------------*/
+
+/* link an ed into one of the HC chains */
+
+static int ep_link (ohci_t *ohci, ed_t *edi)
+{
+ volatile ed_t *ed = edi;
+
+ ed->state = ED_OPER;
+
+ switch (ed->type) {
+ case PIPE_CONTROL:
+ ed->hwNextED = 0;
+ if (ohci->ed_controltail == NULL) {
+ writel (ed, &ohci->regs->ed_controlhead);
+ } else {
+ ohci->ed_controltail->hwNextED = ohci_cpu_to_le32 ((unsigned long)ed);
+ }
+ ed->ed_prev = ohci->ed_controltail;
+ if (!ohci->ed_controltail && !ohci->ed_rm_list[0] &&
+ !ohci->ed_rm_list[1] && !ohci->sleeping) {
+ ohci->hc_control |= OHCI_CTRL_CLE;
+ writel (ohci->hc_control, &ohci->regs->control);
+ }
+ ohci->ed_controltail = edi;
+ break;
+
+ case PIPE_BULK:
+ ed->hwNextED = 0;
+ if (ohci->ed_bulktail == NULL) {
+ writel (ed, &ohci->regs->ed_bulkhead);
+ } else {
+ ohci->ed_bulktail->hwNextED = ohci_cpu_to_le32 ((unsigned long)ed);
+ }
+ ed->ed_prev = ohci->ed_bulktail;
+ if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] &&
+ !ohci->ed_rm_list[1] && !ohci->sleeping) {
+ ohci->hc_control |= OHCI_CTRL_BLE;
+ writel (ohci->hc_control, &ohci->regs->control);
+ }
+ ohci->ed_bulktail = edi;
+ break;
+ }
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* unlink an ed from one of the HC chains.
+ * just the link to the ed is unlinked.
+ * the link from the ed still points to another operational ed or 0
+ * so the HC can eventually finish the processing of the unlinked ed */
+
+static int ep_unlink (ohci_t *ohci, ed_t *edi)
+{
+ volatile ed_t *ed = edi;
+
+ ed->hwINFO |= ohci_cpu_to_le32 (OHCI_ED_SKIP);
+
+ switch (ed->type) {
+ case PIPE_CONTROL:
+ if (ed->ed_prev == NULL) {
+ if (!ed->hwNextED) {
+ ohci->hc_control &= ~OHCI_CTRL_CLE;
+ writel (ohci->hc_control, &ohci->regs->control);
+ }
+ writel (ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_controlhead);
+ } else {
+ ed->ed_prev->hwNextED = ed->hwNextED;
+ }
+ if (ohci->ed_controltail == ed) {
+ ohci->ed_controltail = ed->ed_prev;
+ } else {
+ ((ed_t *)ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev;
+ }
+ break;
+
+ case PIPE_BULK:
+ if (ed->ed_prev == NULL) {
+ if (!ed->hwNextED) {
+ ohci->hc_control &= ~OHCI_CTRL_BLE;
+ writel (ohci->hc_control, &ohci->regs->control);
+ }
+ writel (ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_bulkhead);
+ } else {
+ ed->ed_prev->hwNextED = ed->hwNextED;
+ }
+ if (ohci->ed_bulktail == ed) {
+ ohci->ed_bulktail = ed->ed_prev;
+ } else {
+ ((ed_t *)ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev;
+ }
+ break;
+ }
+ ed->state = ED_UNLINK;
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+/* add/reinit an endpoint; this should be done once at the usb_set_configuration command,
+ * but the USB stack is a little bit stateless so we do it at every transaction
+ * if the state of the ed is ED_NEW then a dummy td is added and the state is changed to ED_UNLINK
+ * in all other cases the state is left unchanged
+ * the ed info fields are setted anyway even though most of them should not change */
+
+static ed_t * ep_add_ed (struct usb_device *usb_dev, unsigned long pipe)
+{
+ td_t *td;
+ ed_t *ed_ret;
+ volatile ed_t *ed;
+
+ ed = ed_ret = &ohci_dev.ed[(usb_pipeendpoint (pipe) << 1) |
+ (usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))];
+
+ if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) {
+ err("ep_add_ed: pending delete");
+ /* pending delete request */
+ return NULL;
+ }
+
+ if (ed->state == ED_NEW) {
+ ed->hwINFO = ohci_cpu_to_le32 (OHCI_ED_SKIP); /* skip ed */
+ /* dummy td; end of td list for ed */
+ td = td_alloc (usb_dev);
+ ed->hwTailP = ohci_cpu_to_le32 ((unsigned long)td);
+ ed->hwHeadP = ed->hwTailP;
+ ed->state = ED_UNLINK;
+ ed->type = usb_pipetype (pipe);
+ ohci_dev.ed_cnt++;
+ }
+
+ ed->hwINFO = ohci_cpu_to_le32 (usb_pipedevice (pipe)
+ | usb_pipeendpoint (pipe) << 7
+ | (usb_pipeisoc (pipe)? 0x8000: 0)
+ | (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000))
+ | usb_pipeslow (pipe) << 13
+ | usb_maxpacket (usb_dev, pipe) << 16);
+
+ return ed_ret;
+}
+
+/*-------------------------------------------------------------------------*
+ * TD handling functions
+ *-------------------------------------------------------------------------*/
+
+/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */
+
+static void td_fill (ohci_t *ohci, unsigned int info,
+ void *data, int len,
+ struct usb_device *dev, int index, urb_priv_t *urb_priv)
+{
+ volatile td_t *td, *td_pt;
+#ifdef OHCI_FILL_TRACE
+ int i;
+#endif
+
+ if (index > urb_priv->length) {
+ err("index > length");
+ return;
+ }
+ /* use this td as the next dummy */
+ td_pt = urb_priv->td [index];
+ td_pt->hwNextTD = 0;
+
+ /* fill the old dummy TD */
+ td = urb_priv->td [index] = (td_t *)(ohci_cpu_to_le32 (urb_priv->ed->hwTailP) & ~0xf);
+
+ td->ed = urb_priv->ed;
+ td->next_dl_td = NULL;
+ td->index = index;
+ td->data = (__u32)data;
+#ifdef OHCI_FILL_TRACE
+ if ((usb_pipetype(urb_priv->pipe) == PIPE_BULK) && usb_pipeout(urb_priv->pipe)) {
+ for (i = 0; i < len; i++)
+ printf("td->data[%d] %#2x ",i, ((unsigned char *)td->data)[i]);
+ printf("\n");
+ }
+#endif
+ if (!len)
+ data = 0;
+
+ td->hwINFO = ohci_cpu_to_le32 (info);
+ td->hwCBP = ohci_cpu_to_le32 ((unsigned long)data);
+ if (data)
+ td->hwBE = ohci_cpu_to_le32 ((unsigned long)(data + len - 1));
+ else
+ td->hwBE = 0;
+ td->hwNextTD = ohci_cpu_to_le32 ((unsigned long)td_pt);
+
+ /* append to queue */
+ td->ed->hwTailP = td->hwNextTD;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* prepare all TDs of a transfer */
+static void td_submit_job (struct usb_device *dev, unsigned long pipe, void *buffer,
+ int transfer_len, struct devrequest *setup, urb_priv_t *urb, int interval)
+{
+ ohci_t *ohci = &gohci;
+ int data_len = transfer_len;
+ void *data;
+ int cnt = 0;
+ __u32 info = 0;
+ unsigned int toggle = 0;
+
+ /* OHCI handles the DATA-toggles itself, we just use the USB-toggle bits for reseting */
+ if(usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) {
+ toggle = TD_T_TOGGLE;
+ } else {
+ toggle = TD_T_DATA0;
+ usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 1);
+ }
+ urb->td_cnt = 0;
+ if (data_len)
+ data = buffer;
+ else
+ data = 0;
+
+ switch (usb_pipetype (pipe)) {
+ case PIPE_BULK:
+ info = usb_pipeout (pipe)?
+ TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ;
+ while(data_len > 4096) {
+ td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, 4096, dev, cnt, urb);
+ data += 4096; data_len -= 4096; cnt++;
+ }
+ info = usb_pipeout (pipe)?
+ TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ;
+ td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, data_len, dev, cnt, urb);
+ cnt++;
+
+ if (!ohci->sleeping)
+ writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
+ break;
+
+ case PIPE_CONTROL:
+ info = TD_CC | TD_DP_SETUP | TD_T_DATA0;
+ td_fill (ohci, info, setup, 8, dev, cnt++, urb);
+ if (data_len > 0) {
+ info = usb_pipeout (pipe)?
+ TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1;
+ /* NOTE: mishandles transfers >8K, some >4K */
+ td_fill (ohci, info, data, data_len, dev, cnt++, urb);
+ }
+ info = usb_pipeout (pipe)?
+ TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1;
+ td_fill (ohci, info, data, 0, dev, cnt++, urb);
+ if (!ohci->sleeping)
+ writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
+ break;
+ }
+ if (urb->length != cnt)
+ dbg("TD LENGTH %d != CNT %d", urb->length, cnt);
+}
+
+/*-------------------------------------------------------------------------*
+ * Done List handling functions
+ *-------------------------------------------------------------------------*/
+
+
+/* calculate the transfer length and update the urb */
+
+static void dl_transfer_length(td_t * td)
+{
+ __u32 tdINFO, tdBE, tdCBP;
+ urb_priv_t *lurb_priv = &urb_priv;
+
+ tdINFO = ohci_cpu_to_le32 (td->hwINFO);
+ tdBE = ohci_cpu_to_le32 (td->hwBE);
+ tdCBP = ohci_cpu_to_le32 (td->hwCBP);
+
+
+ if (!(usb_pipetype (lurb_priv->pipe) == PIPE_CONTROL &&
+ ((td->index == 0) || (td->index == lurb_priv->length - 1)))) {
+ if (tdBE != 0) {
+ if (td->hwCBP == 0)
+ lurb_priv->actual_length += tdBE - td->data + 1;
+ else
+ lurb_priv->actual_length += tdCBP - td->data;
+ }
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* replies to the request have to be on a FIFO basis so
+ * we reverse the reversed done-list */
+
+static td_t * dl_reverse_done_list (ohci_t *ohci)
+{
+ __u32 td_list_hc;
+ td_t *td_rev = NULL;
+ td_t *td_list = NULL;
+ urb_priv_t *lurb_priv = NULL;
+
+ td_list_hc = ohci_cpu_to_le32 (ohci->hcca->done_head) & 0xfffffff0;
+ ohci->hcca->done_head = 0;
+
+ while (td_list_hc) {
+ td_list = (td_t *)td_list_hc;
+
+ if (TD_CC_GET (ohci_cpu_to_le32 (td_list->hwINFO))) {
+ lurb_priv = &urb_priv;
+ dbg(" USB-error/status: %x : %p",
+ TD_CC_GET (ohci_cpu_to_le32 (td_list->hwINFO)), td_list);
+ if (td_list->ed->hwHeadP & ohci_cpu_to_le32 (0x1)) {
+ if (lurb_priv && ((td_list->index + 1) < lurb_priv->length)) {
+ td_list->ed->hwHeadP =
+ (lurb_priv->td[lurb_priv->length - 1]->hwNextTD & ohci_cpu_to_le32 (0xfffffff0)) |
+ (td_list->ed->hwHeadP & ohci_cpu_to_le32 (0x2));
+ lurb_priv->td_cnt += lurb_priv->length - td_list->index - 1;
+ } else
+ td_list->ed->hwHeadP &= ohci_cpu_to_le32 (0xfffffff2);
+ }
+#ifdef CONFIG_MPC5200
+ td_list->hwNextTD = 0;
+#endif
+ }
+
+ td_list->next_dl_td = td_rev;
+ td_rev = td_list;
+ td_list_hc = ohci_cpu_to_le32 (td_list->hwNextTD) & 0xfffffff0;
+ }
+ return td_list;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* td done list */
+static int dl_done_list (ohci_t *ohci, td_t *td_list)
+{
+ td_t *td_list_next = NULL;
+ ed_t *ed;
+ int cc = 0;
+ int stat = 0;
+ /* urb_t *urb; */
+ urb_priv_t *lurb_priv;
+ __u32 tdINFO, edHeadP, edTailP;
+
+ while (td_list) {
+ td_list_next = td_list->next_dl_td;
+
+ lurb_priv = &urb_priv;
+ tdINFO = ohci_cpu_to_le32 (td_list->hwINFO);
+
+ ed = td_list->ed;
+
+ dl_transfer_length(td_list);
+
+ /* error code of transfer */
+ cc = TD_CC_GET (tdINFO);
+ if (++(lurb_priv->td_cnt) == lurb_priv->length) {
+ if ((ed->state & (ED_OPER | ED_UNLINK))
+ && (lurb_priv->state != URB_DEL)) {
+ dbg("ConditionCode %#x", cc);
+ stat = cc_to_error[cc];
+ urb_finished = 1;
+ }
+ }
+
+ if (ed->state != ED_NEW) {
+ edHeadP = ohci_cpu_to_le32 (ed->hwHeadP) & 0xfffffff0;
+ edTailP = ohci_cpu_to_le32 (ed->hwTailP);
+
+ /* unlink eds if they are not busy */
+ if ((edHeadP == edTailP) && (ed->state == ED_OPER))
+ ep_unlink (ohci, ed);
+ }
+
+ td_list = td_list_next;
+ }
+ return stat;
+}
+
+/*-------------------------------------------------------------------------*
+ * Virtual Root Hub
+ *-------------------------------------------------------------------------*/
+
+/* Device descriptor */
+static __u8 root_hub_dev_des[] =
+{
+ 0x12, /* __u8 bLength; */
+ 0x01, /* __u8 bDescriptorType; Device */
+ 0x10, /* __u16 bcdUSB; v1.1 */
+ 0x01,
+ 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 bDeviceSubClass; */
+ 0x00, /* __u8 bDeviceProtocol; */
+ 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
+ 0x00, /* __u16 idVendor; */
+ 0x00,
+ 0x00, /* __u16 idProduct; */
+ 0x00,
+ 0x00, /* __u16 bcdDevice; */
+ 0x00,
+ 0x00, /* __u8 iManufacturer; */
+ 0x01, /* __u8 iProduct; */
+ 0x00, /* __u8 iSerialNumber; */
+ 0x01 /* __u8 bNumConfigurations; */
+};
+
+
+/* Configuration descriptor */
+static __u8 root_hub_config_des[] =
+{
+ 0x09, /* __u8 bLength; */
+ 0x02, /* __u8 bDescriptorType; Configuration */
+ 0x19, /* __u16 wTotalLength; */
+ 0x00,
+ 0x01, /* __u8 bNumInterfaces; */
+ 0x01, /* __u8 bConfigurationValue; */
+ 0x00, /* __u8 iConfiguration; */
+ 0x40, /* __u8 bmAttributes;
+ Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
+ 0x00, /* __u8 MaxPower; */
+
+ /* interface */
+ 0x09, /* __u8 if_bLength; */
+ 0x04, /* __u8 if_bDescriptorType; Interface */
+ 0x00, /* __u8 if_bInterfaceNumber; */
+ 0x00, /* __u8 if_bAlternateSetting; */
+ 0x01, /* __u8 if_bNumEndpoints; */
+ 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 if_bInterfaceSubClass; */
+ 0x00, /* __u8 if_bInterfaceProtocol; */
+ 0x00, /* __u8 if_iInterface; */
+
+ /* endpoint */
+ 0x07, /* __u8 ep_bLength; */
+ 0x05, /* __u8 ep_bDescriptorType; Endpoint */
+ 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
+ 0x03, /* __u8 ep_bmAttributes; Interrupt */
+ 0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
+ 0x00,
+ 0xff /* __u8 ep_bInterval; 255 ms */
+};
+
+static unsigned char root_hub_str_index0[] =
+{
+ 0x04, /* __u8 bLength; */
+ 0x03, /* __u8 bDescriptorType; String-descriptor */
+ 0x09, /* __u8 lang ID */
+ 0x04, /* __u8 lang ID */
+};
+
+static unsigned char root_hub_str_index1[] =
+{
+ 28, /* __u8 bLength; */
+ 0x03, /* __u8 bDescriptorType; String-descriptor */
+ 'O', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'H', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'C', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'I', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ ' ', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'R', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'o', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'o', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 't', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ ' ', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'H', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'u', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'b', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+};
+
+/* Hub class-specific descriptor is constructed dynamically */
+
+
+/*-------------------------------------------------------------------------*/
+
+#define OK(x) len = (x); break
+#ifdef DEBUG
+#define WR_RH_STAT(x) {info("WR:status %#8x", (x));writel((x), &gohci.regs->roothub.status);}
+#define WR_RH_PORTSTAT(x) {info("WR:portstatus[%d] %#8x", wIndex-1, (x));writel((x), &gohci.regs->roothub.portstatus[wIndex-1]);}
+#else
+#define WR_RH_STAT(x) writel((x), &gohci.regs->roothub.status)
+#define WR_RH_PORTSTAT(x) writel((x), &gohci.regs->roothub.portstatus[wIndex-1])
+#endif
+#define RD_RH_STAT roothub_status(&gohci)
+#define RD_RH_PORTSTAT roothub_portstatus(&gohci,wIndex-1)
+
+/* request to virtual root hub */
+
+int rh_check_port_status(ohci_t *controller)
+{
+ __u32 temp, ndp, i;
+ int res;
+
+ res = -1;
+ temp = roothub_a (controller);
+ ndp = (temp & RH_A_NDP);
+ for (i = 0; i < ndp; i++) {
+ temp = roothub_portstatus (controller, i);
+ /* check for a device disconnect */
+ if (((temp & (RH_PS_PESC | RH_PS_CSC)) ==
+ (RH_PS_PESC | RH_PS_CSC)) &&
+ ((temp & RH_PS_CCS) == 0)) {
+ res = i;
+ break;
+ }
+ }
+ return res;
+}
+
+static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
+ void *buffer, int transfer_len, struct devrequest *cmd)
+{
+ void * data = buffer;
+ int leni = transfer_len;
+ int len = 0;
+ int stat = 0;
+ __u32 datab[4];
+ __u8 *data_buf = (__u8 *)datab;
+ __u16 bmRType_bReq;
+ __u16 wValue;
+ __u16 wIndex;
+ __u16 wLength;
+
+#ifdef DEBUG
+urb_priv.actual_length = 0;
+pkt_print(dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe));
+#endif
+ if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) {
+ info("Root-Hub submit IRQ: NOT implemented");
+ return 0;
+ }
+
+ bmRType_bReq = cmd->requesttype | (cmd->request << 8);
+ wValue = m16_swap (cmd->value);
+ wIndex = m16_swap (cmd->index);
+ wLength = m16_swap (cmd->length);
+
+ info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x",
+ dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength);
+
+ switch (bmRType_bReq) {
+ /* Request Destination:
+ without flags: Device,
+ RH_INTERFACE: interface,
+ RH_ENDPOINT: endpoint,
+ RH_CLASS means HUB here,
+ RH_OTHER | RH_CLASS almost ever means HUB_PORT here
+ */
+
+ case RH_GET_STATUS:
+ *(__u16 *) data_buf = m16_swap (1); OK (2);
+ case RH_GET_STATUS | RH_INTERFACE:
+ *(__u16 *) data_buf = m16_swap (0); OK (2);
+ case RH_GET_STATUS | RH_ENDPOINT:
+ *(__u16 *) data_buf = m16_swap (0); OK (2);
+ case RH_GET_STATUS | RH_CLASS:
+ *(__u32 *) data_buf = m32_swap (
+ RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE));
+ OK (4);
+ case RH_GET_STATUS | RH_OTHER | RH_CLASS:
+ *(__u32 *) data_buf = m32_swap (RD_RH_PORTSTAT); OK (4);
+
+ case RH_CLEAR_FEATURE | RH_ENDPOINT:
+ switch (wValue) {
+ case (RH_ENDPOINT_STALL): OK (0);
+ }
+ break;
+
+ case RH_CLEAR_FEATURE | RH_CLASS:
+ switch (wValue) {
+ case RH_C_HUB_LOCAL_POWER:
+ OK(0);
+ case (RH_C_HUB_OVER_CURRENT):
+ WR_RH_STAT(RH_HS_OCIC); OK (0);
+ }
+ break;
+
+ case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+ switch (wValue) {
+ case (RH_PORT_ENABLE):
+ WR_RH_PORTSTAT (RH_PS_CCS ); OK (0);
+ case (RH_PORT_SUSPEND):
+ WR_RH_PORTSTAT (RH_PS_POCI); OK (0);
+ case (RH_PORT_POWER):
+ WR_RH_PORTSTAT (RH_PS_LSDA); OK (0);
+ case (RH_C_PORT_CONNECTION):
+ WR_RH_PORTSTAT (RH_PS_CSC ); OK (0);
+ case (RH_C_PORT_ENABLE):
+ WR_RH_PORTSTAT (RH_PS_PESC); OK (0);
+ case (RH_C_PORT_SUSPEND):
+ WR_RH_PORTSTAT (RH_PS_PSSC); OK (0);
+ case (RH_C_PORT_OVER_CURRENT):
+ WR_RH_PORTSTAT (RH_PS_OCIC); OK (0);
+ case (RH_C_PORT_RESET):
+ WR_RH_PORTSTAT (RH_PS_PRSC); OK (0);
+ }
+ break;
+
+ case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+ switch (wValue) {
+ case (RH_PORT_SUSPEND):
+ WR_RH_PORTSTAT (RH_PS_PSS ); OK (0);
+ case (RH_PORT_RESET): /* BUG IN HUP CODE *********/
+ if (RD_RH_PORTSTAT & RH_PS_CCS)
+ WR_RH_PORTSTAT (RH_PS_PRS);
+ OK (0);
+ case (RH_PORT_POWER):
+ WR_RH_PORTSTAT (RH_PS_PPS ); OK (0);
+ case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/
+ if (RD_RH_PORTSTAT & RH_PS_CCS)
+ WR_RH_PORTSTAT (RH_PS_PES );
+ OK (0);
+ }
+ break;
+
+ case RH_SET_ADDRESS: gohci.rh.devnum = wValue; OK(0);
+
+ case RH_GET_DESCRIPTOR:
+ switch ((wValue & 0xff00) >> 8) {
+ case (0x01): /* device descriptor */
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof (root_hub_dev_des),
+ wLength));
+ data_buf = root_hub_dev_des; OK(len);
+ case (0x02): /* configuration descriptor */
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof (root_hub_config_des),
+ wLength));
+ data_buf = root_hub_config_des; OK(len);
+ case (0x03): /* string descriptors */
+ if(wValue==0x0300) {
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof (root_hub_str_index0),
+ wLength));
+ data_buf = root_hub_str_index0;
+ OK(len);
+ }
+ if(wValue==0x0301) {
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof (root_hub_str_index1),
+ wLength));
+ data_buf = root_hub_str_index1;
+ OK(len);
+ }
+ default:
+ stat = USB_ST_STALLED;
+ }
+ break;
+
+ case RH_GET_DESCRIPTOR | RH_CLASS:
+ {
+ __u32 temp = roothub_a (&gohci);
+
+ data_buf [0] = 9; /* min length; */
+ data_buf [1] = 0x29;
+ data_buf [2] = temp & RH_A_NDP;
+ data_buf [3] = 0;
+ if (temp & RH_A_PSM) /* per-port power switching? */
+ data_buf [3] |= 0x1;
+ if (temp & RH_A_NOCP) /* no overcurrent reporting? */
+ data_buf [3] |= 0x10;
+ else if (temp & RH_A_OCPM) /* per-port overcurrent reporting? */
+ data_buf [3] |= 0x8;
+
+ /* corresponds to data_buf[4-7] */
+ datab [1] = 0;
+ data_buf [5] = (temp & RH_A_POTPGT) >> 24;
+ temp = roothub_b (&gohci);
+ data_buf [7] = temp & RH_B_DR;
+ if (data_buf [2] < 7) {
+ data_buf [8] = 0xff;
+ } else {
+ data_buf [0] += 2;
+ data_buf [8] = (temp & RH_B_DR) >> 8;
+ data_buf [10] = data_buf [9] = 0xff;
+ }
+
+ len = min_t(unsigned int, leni,
+ min_t(unsigned int, data_buf [0], wLength));
+ OK (len);
+ }
+
+ case RH_GET_CONFIGURATION: *(__u8 *) data_buf = 0x01; OK (1);
+
+ case RH_SET_CONFIGURATION: WR_RH_STAT (0x10000); OK (0);
+
+ default:
+ dbg ("unsupported root hub command");
+ stat = USB_ST_STALLED;
+ }
+
+#ifdef DEBUG
+ ohci_dump_roothub (&gohci, 1);
+#endif
+
+ len = min_t(int, len, leni);
+ if (data != data_buf)
+ memcpy (data, data_buf, len);
+ dev->act_len = len;
+ dev->status = stat;
+
+#ifdef DEBUG
+ if (transfer_len)
+ urb_priv.actual_length = transfer_len;
+ pkt_print(dev, pipe, buffer, transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/);
+#endif
+
+ return stat;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* common code for handling submit messages - used for all but root hub */
+/* accesses. */
+int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int transfer_len, struct devrequest *setup, int interval)
+{
+ int stat = 0;
+ int maxsize = usb_maxpacket(dev, pipe);
+ int timeout;
+
+ /* device pulled? Shortcut the action. */
+ if (devgone == dev) {
+ dev->status = USB_ST_CRC_ERR;
+ return 0;
+ }
+
+#ifdef DEBUG
+ urb_priv.actual_length = 0;
+ pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe));
+#endif
+ if (!maxsize) {
+ err("submit_common_message: pipesize for pipe %lx is zero",
+ pipe);
+ return -1;
+ }
+
+ if (sohci_submit_job(dev, pipe, buffer, transfer_len, setup, interval) < 0) {
+ err("sohci_submit_job failed");
+ return -1;
+ }
+
+ /* allow more time for a BULK device to react - some are slow */
+#define BULK_TO 5000 /* timeout in milliseconds */
+ if (usb_pipetype (pipe) == PIPE_BULK)
+ timeout = BULK_TO;
+ else
+ timeout = 100;
+
+ /* wait for it to complete */
+ for (;;) {
+ /* check whether the controller is done */
+ stat = hc_interrupt();
+ if (stat < 0) {
+ stat = USB_ST_CRC_ERR;
+ break;
+ }
+
+ /* NOTE: since we are not interrupt driven in U-Boot and always
+ * handle only one URB at a time, we cannot assume the
+ * transaction finished on the first successful return from
+ * hc_interrupt().. unless the flag for current URB is set,
+ * meaning that all TD's to/from device got actually
+ * transferred and processed. If the current URB is not
+ * finished we need to re-iterate this loop so as
+ * hc_interrupt() gets called again as there needs to be some
+ * more TD's to process still */
+ if ((stat >= 0) && (stat != 0xff) && (urb_finished)) {
+ /* 0xff is returned for an SF-interrupt */
+ break;
+ }
+
+ if (--timeout) {
+ wait_ms(1);
+ if (!urb_finished)
+ dbg("\%");
+
+ } else {
+ err("CTL:TIMEOUT ");
+ dbg("submit_common_msg: TO status %x\n", stat);
+ stat = USB_ST_CRC_ERR;
+ urb_finished = 1;
+ break;
+ }
+ }
+#if 0
+ /* we got an Root Hub Status Change interrupt */
+ if (got_rhsc) {
+#ifdef DEBUG
+ ohci_dump_roothub (&gohci, 1);
+#endif
+ got_rhsc = 0;
+ /* abuse timeout */
+ timeout = rh_check_port_status(&gohci);
+ if (timeout >= 0) {
+#if 0 /* this does nothing useful, but leave it here in case that changes */
+ /* the called routine adds 1 to the passed value */
+ usb_hub_port_connect_change(gohci.rh.dev, timeout - 1);
+#endif
+ /*
+ * XXX
+ * This is potentially dangerous because it assumes
+ * that only one device is ever plugged in!
+ */
+ devgone = dev;
+ }
+ }
+#endif
+
+ dev->status = stat;
+ dev->act_len = transfer_len;
+
+#ifdef DEBUG
+ pkt_print(dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", usb_pipein(pipe));
+#endif
+
+ /* free TDs in urb_priv */
+ urb_free_priv (&urb_priv);
+ return 0;
+}
+
+/* submit routines called from usb.c */
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int transfer_len)
+{
+ info("submit_bulk_msg");
+ return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, 0);
+}
+
+int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int transfer_len, struct devrequest *setup)
+{
+ int maxsize = usb_maxpacket(dev, pipe);
+
+ info("submit_control_msg");
+#ifdef DEBUG
+ urb_priv.actual_length = 0;
+ pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe));
+#endif
+ if (!maxsize) {
+ err("submit_control_message: pipesize for pipe %lx is zero",
+ pipe);
+ return -1;
+ }
+ if (((pipe >> 8) & 0x7f) == gohci.rh.devnum) {
+ gohci.rh.dev = dev;
+ /* root hub - redirect */
+ return ohci_submit_rh_msg(dev, pipe, buffer, transfer_len,
+ setup);
+ }
+
+ return submit_common_msg(dev, pipe, buffer, transfer_len, setup, 0);
+}
+
+int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int transfer_len, int interval)
+{
+ info("submit_int_msg");
+ return -1;
+}
+
+/*-------------------------------------------------------------------------*
+ * HC functions
+ *-------------------------------------------------------------------------*/
+
+/* reset the HC and BUS */
+
+static int hc_reset (ohci_t *ohci)
+{
+ int timeout = 30;
+ int smm_timeout = 50; /* 0,5 sec */
+
+ if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */
+ writel (OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */
+ info("USB HC TakeOver from SMM");
+ while (readl (&ohci->regs->control) & OHCI_CTRL_IR) {
+ wait_ms (10);
+ if (--smm_timeout == 0) {
+ err("USB HC TakeOver failed!");
+ return -1;
+ }
+ }
+ }
+
+ /* Disable HC interrupts */
+ writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
+
+ dbg("USB HC reset_hc usb-%s: ctrl = 0x%X ;",
+ ohci->slot_name,
+ readl (&ohci->regs->control));
+
+ /* Reset USB (needed by some controllers) */
+ ohci->hc_control = 0;
+ writel (ohci->hc_control, &ohci->regs->control);
+
+ /* HC Reset requires max 10 us delay */
+ writel (OHCI_HCR, &ohci->regs->cmdstatus);
+ while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
+ if (--timeout == 0) {
+ err("USB HC reset timed out!");
+ return -1;
+ }
+ udelay (1);
+ }
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Start an OHCI controller, set the BUS operational
+ * enable interrupts
+ * connect the virtual root hub */
+
+static int hc_start (ohci_t * ohci)
+{
+ __u32 mask;
+ unsigned int fminterval;
+
+ ohci->disabled = 1;
+
+ /* Tell the controller where the control and bulk lists are
+ * The lists are empty now. */
+
+ writel (0, &ohci->regs->ed_controlhead);
+ writel (0, &ohci->regs->ed_bulkhead);
+
+ writel ((__u32)ohci->hcca, &ohci->regs->hcca); /* a reset clears this */
+
+ fminterval = 0x2edf;
+ writel ((fminterval * 9) / 10, &ohci->regs->periodicstart);
+ fminterval |= ((((fminterval - 210) * 6) / 7) << 16);
+ writel (fminterval, &ohci->regs->fminterval);
+ writel (0x628, &ohci->regs->lsthresh);
+
+ /* start controller operations */
+ ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
+ ohci->disabled = 0;
+ writel (ohci->hc_control, &ohci->regs->control);
+
+ /* disable all interrupts */
+ mask = (OHCI_INTR_SO | OHCI_INTR_WDH | OHCI_INTR_SF | OHCI_INTR_RD |
+ OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC |
+ OHCI_INTR_OC | OHCI_INTR_MIE);
+ writel (mask, &ohci->regs->intrdisable);
+ /* clear all interrupts */
+ mask &= ~OHCI_INTR_MIE;
+ writel (mask, &ohci->regs->intrstatus);
+ /* Choose the interrupts we care about now - but w/o MIE */
+ mask = OHCI_INTR_RHSC | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO;
+ writel (mask, &ohci->regs->intrenable);
+
+#ifdef OHCI_USE_NPS
+ /* required for AMD-756 and some Mac platforms */
+ writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM,
+ &ohci->regs->roothub.a);
+ writel (RH_HS_LPSC, &ohci->regs->roothub.status);
+#endif /* OHCI_USE_NPS */
+
+#define mdelay(n) ({unsigned long msec=(n); while (msec--) udelay(1000);})
+ /* POTPGT delay is bits 24-31, in 2 ms units. */
+ mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
+
+ /* connect the virtual root hub */
+ ohci->rh.devnum = 0;
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* an interrupt happens */
+
+static int
+hc_interrupt (void)
+{
+ ohci_t *ohci = &gohci;
+ struct ohci_regs *regs = ohci->regs;
+ int ints;
+ int stat = -1;
+
+ if ((ohci->hcca->done_head != 0) &&
+ !(ohci_cpu_to_le32(ohci->hcca->done_head) & 0x01)) {
+
+ ints = OHCI_INTR_WDH;
+
+ } else if ((ints = readl (&regs->intrstatus)) == ~(u32)0) {
+ ohci->disabled++;
+ err ("%s device removed!", ohci->slot_name);
+ return -1;
+
+ } else if ((ints &= readl (&regs->intrenable)) == 0) {
+ dbg("hc_interrupt: returning..\n");
+ return 0xff;
+ }
+
+ /* dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); */
+
+ if (ints & OHCI_INTR_RHSC) {
+ got_rhsc = 1;
+ stat = 0xff;
+ }
+
+ if (ints & OHCI_INTR_UE) {
+ ohci->disabled++;
+ err ("OHCI Unrecoverable Error, controller usb-%s disabled",
+ ohci->slot_name);
+ /* e.g. due to PCI Master/Target Abort */
+
+#ifdef DEBUG
+ ohci_dump (ohci, 1);
+#endif
+ /* FIXME: be optimistic, hope that bug won't repeat often. */
+ /* Make some non-interrupt context restart the controller. */
+ /* Count and limit the retries though; either hardware or */
+ /* software errors can go forever... */
+ hc_reset (ohci);
+ return -1;
+ }
+
+ if (ints & OHCI_INTR_WDH) {
+ writel (OHCI_INTR_WDH, &regs->intrdisable);
+ stat = dl_done_list (&gohci, dl_reverse_done_list (&gohci));
+ writel (OHCI_INTR_WDH, &regs->intrenable);
+ }
+
+ if (ints & OHCI_INTR_SO) {
+ dbg("USB Schedule overrun\n");
+ writel (OHCI_INTR_SO, &regs->intrenable);
+ stat = -1;
+ }
+
+ /* FIXME: this assumes SOF (1/ms) interrupts don't get lost... */
+ if (ints & OHCI_INTR_SF) {
+ unsigned int frame = ohci_cpu_to_le16 (ohci->hcca->frame_no) & 1;
+ wait_ms(1);
+ writel (OHCI_INTR_SF, &regs->intrdisable);
+ if (ohci->ed_rm_list[frame] != NULL)
+ writel (OHCI_INTR_SF, &regs->intrenable);
+ stat = 0xff;
+ }
+
+ writel (ints, &regs->intrstatus);
+ return stat;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------*/
+
+/* De-allocate all resources.. */
+
+static void hc_release_ohci (ohci_t *ohci)
+{
+ dbg ("USB HC release ohci usb-%s", ohci->slot_name);
+
+ if (!ohci->disabled)
+ hc_reset (ohci);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * low level initalisation routine, called from usb.c
+ */
+static char ohci_inited = 0;
+
+int usb_lowlevel_init(void)
+{
+ memset (&gohci, 0, sizeof (ohci_t));
+ memset (&urb_priv, 0, sizeof (urb_priv_t));
+
+ /* align the storage */
+ if ((__u32)&ghcca[0] & 0xff) {
+ err("HCCA not aligned!!");
+ return -1;
+ }
+ phcca = &ghcca[0];
+ info("aligned ghcca %p", phcca);
+ memset(&ohci_dev, 0, sizeof(struct ohci_device));
+ if ((__u32)&ohci_dev.ed[0] & 0x7) {
+ err("EDs not aligned!!");
+ return -1;
+ }
+ memset(gtd, 0, sizeof(td_t) * (NUM_TD + 1));
+ if ((__u32)gtd & 0x7) {
+ err("TDs not aligned!!");
+ return -1;
+ }
+ ptd = gtd;
+ gohci.hcca = phcca;
+ memset (phcca, 0, sizeof (struct ohci_hcca));
+
+ gohci.disabled = 1;
+ gohci.sleeping = 0;
+ gohci.irq = -1;
+ gohci.regs = (struct ohci_regs *)(CFG_PERIPHERAL_BASE | 0x1000);
+
+ gohci.flags = 0;
+ gohci.slot_name = "ppc440";
+
+ if (hc_reset (&gohci) < 0) {
+ hc_release_ohci (&gohci);
+ return -1;
+ }
+
+ if (hc_start (&gohci) < 0) {
+ err ("can't start usb-%s", gohci.slot_name);
+ hc_release_ohci (&gohci);
+ return -1;
+ }
+
+#ifdef DEBUG
+ ohci_dump (&gohci, 1);
+#endif
+ ohci_inited = 1;
+ urb_finished = 1;
+
+ /* init the device driver */
+ usb_dev_init();
+
+ return 0;
+}
+
+int usb_lowlevel_stop(void)
+{
+ /* this gets called really early - before the controller has */
+ /* even been initialized! */
+ if (!ohci_inited)
+ return 0;
+ /* TODO release any interrupts, etc. */
+ /* call hc_release_ohci() here ? */
+ hc_reset (&gohci);
+ return 0;
+}
+
+#endif /* CONFIG_USB_OHCI */
diff --git a/cpu/ppc4xx/usb_ohci.h b/cpu/ppc4xx/usb_ohci.h
new file mode 100644
index 0000000000..706e05ea21
--- /dev/null
+++ b/cpu/ppc4xx/usb_ohci.h
@@ -0,0 +1,410 @@
+/*
+ * URB OHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net>
+ *
+ * usb-ohci.h
+ */
+
+static int cc_to_error[16] = {
+
+/* mapping of the OHCI CC status to error codes */
+ /* No Error */ 0,
+ /* CRC Error */ USB_ST_CRC_ERR,
+ /* Bit Stuff */ USB_ST_BIT_ERR,
+ /* Data Togg */ USB_ST_CRC_ERR,
+ /* Stall */ USB_ST_STALLED,
+ /* DevNotResp */ -1,
+ /* PIDCheck */ USB_ST_BIT_ERR,
+ /* UnExpPID */ USB_ST_BIT_ERR,
+ /* DataOver */ USB_ST_BUF_ERR,
+ /* DataUnder */ USB_ST_BUF_ERR,
+ /* reservd */ -1,
+ /* reservd */ -1,
+ /* BufferOver */ USB_ST_BUF_ERR,
+ /* BuffUnder */ USB_ST_BUF_ERR,
+ /* Not Access */ -1,
+ /* Not Access */ -1
+};
+
+/* ED States */
+
+#define ED_NEW 0x00
+#define ED_UNLINK 0x01
+#define ED_OPER 0x02
+#define ED_DEL 0x04
+#define ED_URB_DEL 0x08
+
+/* usb_ohci_ed */
+struct ed {
+ __u32 hwINFO;
+ __u32 hwTailP;
+ __u32 hwHeadP;
+ __u32 hwNextED;
+
+ struct ed *ed_prev;
+ __u8 int_period;
+ __u8 int_branch;
+ __u8 int_load;
+ __u8 int_interval;
+ __u8 state;
+ __u8 type;
+ __u16 last_iso;
+ struct ed *ed_rm_list;
+
+ struct usb_device *usb_dev;
+ __u32 unused[3];
+} __attribute((aligned(16)));
+typedef struct ed ed_t;
+
+/* TD info field */
+#define TD_CC 0xf0000000
+#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f)
+#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28)
+#define TD_EC 0x0C000000
+#define TD_T 0x03000000
+#define TD_T_DATA0 0x02000000
+#define TD_T_DATA1 0x03000000
+#define TD_T_TOGGLE 0x00000000
+#define TD_R 0x00040000
+#define TD_DI 0x00E00000
+#define TD_DI_SET(X) (((X) & 0x07)<< 21)
+#define TD_DP 0x00180000
+#define TD_DP_SETUP 0x00000000
+#define TD_DP_IN 0x00100000
+#define TD_DP_OUT 0x00080000
+
+#define TD_ISO 0x00010000
+#define TD_DEL 0x00020000
+
+/* CC Codes */
+#define TD_CC_NOERROR 0x00
+#define TD_CC_CRC 0x01
+#define TD_CC_BITSTUFFING 0x02
+#define TD_CC_DATATOGGLEM 0x03
+#define TD_CC_STALL 0x04
+#define TD_DEVNOTRESP 0x05
+#define TD_PIDCHECKFAIL 0x06
+#define TD_UNEXPECTEDPID 0x07
+#define TD_DATAOVERRUN 0x08
+#define TD_DATAUNDERRUN 0x09
+#define TD_BUFFEROVERRUN 0x0C
+#define TD_BUFFERUNDERRUN 0x0D
+#define TD_NOTACCESSED 0x0F
+
+#define MAXPSW 1
+
+struct td {
+ __u32 hwINFO;
+ __u32 hwCBP; /* Current Buffer Pointer */
+ __u32 hwNextTD; /* Next TD Pointer */
+ __u32 hwBE; /* Memory Buffer End Pointer */
+
+ __u16 hwPSW[MAXPSW];
+ __u8 unused;
+ __u8 index;
+ struct ed *ed;
+ struct td *next_dl_td;
+ struct usb_device *usb_dev;
+ int transfer_len;
+ __u32 data;
+
+ __u32 unused2[2];
+} __attribute((aligned(32)));
+typedef struct td td_t;
+
+#define OHCI_ED_SKIP (1 << 14)
+
+/*
+ * The HCCA (Host Controller Communications Area) is a 256 byte
+ * structure defined in the OHCI spec. that the host controller is
+ * told the base address of. It must be 256-byte aligned.
+ */
+
+#define NUM_INTS 32 /* part of the OHCI standard */
+struct ohci_hcca {
+ __u32 int_table[NUM_INTS]; /* Interrupt ED table */
+#if defined(CONFIG_MPC5200)
+ __u16 pad1; /* set to 0 on each frame_no change */
+ __u16 frame_no; /* current frame number */
+#else
+ __u16 frame_no; /* current frame number */
+ __u16 pad1; /* set to 0 on each frame_no change */
+#endif
+ __u32 done_head; /* info returned for an interrupt */
+ u8 reserved_for_hc[116];
+} __attribute((aligned(256)));
+
+/*
+ * Maximum number of root hub ports.
+ */
+#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports */
+
+/*
+ * This is the structure of the OHCI controller's memory mapped I/O
+ * region. This is Memory Mapped I/O. You must use the readl() and
+ * writel() macros defined in asm/io.h to access these!!
+ */
+struct ohci_regs {
+ /* control and status registers */
+ __u32 revision;
+ __u32 control;
+ __u32 cmdstatus;
+ __u32 intrstatus;
+ __u32 intrenable;
+ __u32 intrdisable;
+ /* memory pointers */
+ __u32 hcca;
+ __u32 ed_periodcurrent;
+ __u32 ed_controlhead;
+ __u32 ed_controlcurrent;
+ __u32 ed_bulkhead;
+ __u32 ed_bulkcurrent;
+ __u32 donehead;
+ /* frame counters */
+ __u32 fminterval;
+ __u32 fmremaining;
+ __u32 fmnumber;
+ __u32 periodicstart;
+ __u32 lsthresh;
+ /* Root hub ports */
+ struct ohci_roothub_regs {
+ __u32 a;
+ __u32 b;
+ __u32 status;
+ __u32 portstatus[MAX_ROOT_PORTS];
+ } roothub;
+} __attribute((aligned(32)));
+
+/* OHCI CONTROL AND STATUS REGISTER MASKS */
+
+/*
+ * HcControl (control) register masks
+ */
+#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */
+#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */
+#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */
+#define OHCI_CTRL_CLE (1 << 4) /* control list enable */
+#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */
+#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */
+#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */
+#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */
+#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */
+
+/* pre-shifted values for HCFS */
+# define OHCI_USB_RESET (0 << 6)
+# define OHCI_USB_RESUME (1 << 6)
+# define OHCI_USB_OPER (2 << 6)
+# define OHCI_USB_SUSPEND (3 << 6)
+
+/*
+ * HcCommandStatus (cmdstatus) register masks
+ */
+#define OHCI_HCR (1 << 0) /* host controller reset */
+#define OHCI_CLF (1 << 1) /* control list filled */
+#define OHCI_BLF (1 << 2) /* bulk list filled */
+#define OHCI_OCR (1 << 3) /* ownership change request */
+#define OHCI_SOC (3 << 16) /* scheduling overrun count */
+
+/*
+ * masks used with interrupt registers:
+ * HcInterruptStatus (intrstatus)
+ * HcInterruptEnable (intrenable)
+ * HcInterruptDisable (intrdisable)
+ */
+#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */
+#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */
+#define OHCI_INTR_SF (1 << 2) /* start frame */
+#define OHCI_INTR_RD (1 << 3) /* resume detect */
+#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */
+#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */
+#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */
+#define OHCI_INTR_OC (1 << 30) /* ownership change */
+#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */
+
+/* Virtual Root HUB */
+struct virt_root_hub {
+ int devnum; /* Address of Root Hub endpoint */
+ void *dev; /* was urb */
+ void *int_addr;
+ int send;
+ int interval;
+};
+
+/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */
+
+/* destination of request */
+#define RH_INTERFACE 0x01
+#define RH_ENDPOINT 0x02
+#define RH_OTHER 0x03
+
+#define RH_CLASS 0x20
+#define RH_VENDOR 0x40
+
+/* Requests: bRequest << 8 | bmRequestType */
+#define RH_GET_STATUS 0x0080
+#define RH_CLEAR_FEATURE 0x0100
+#define RH_SET_FEATURE 0x0300
+#define RH_SET_ADDRESS 0x0500
+#define RH_GET_DESCRIPTOR 0x0680
+#define RH_SET_DESCRIPTOR 0x0700
+#define RH_GET_CONFIGURATION 0x0880
+#define RH_SET_CONFIGURATION 0x0900
+#define RH_GET_STATE 0x0280
+#define RH_GET_INTERFACE 0x0A80
+#define RH_SET_INTERFACE 0x0B00
+#define RH_SYNC_FRAME 0x0C80
+/* Our Vendor Specific Request */
+#define RH_SET_EP 0x2000
+
+/* Hub port features */
+#define RH_PORT_CONNECTION 0x00
+#define RH_PORT_ENABLE 0x01
+#define RH_PORT_SUSPEND 0x02
+#define RH_PORT_OVER_CURRENT 0x03
+#define RH_PORT_RESET 0x04
+#define RH_PORT_POWER 0x08
+#define RH_PORT_LOW_SPEED 0x09
+
+#define RH_C_PORT_CONNECTION 0x10
+#define RH_C_PORT_ENABLE 0x11
+#define RH_C_PORT_SUSPEND 0x12
+#define RH_C_PORT_OVER_CURRENT 0x13
+#define RH_C_PORT_RESET 0x14
+
+/* Hub features */
+#define RH_C_HUB_LOCAL_POWER 0x00
+#define RH_C_HUB_OVER_CURRENT 0x01
+
+#define RH_DEVICE_REMOTE_WAKEUP 0x00
+#define RH_ENDPOINT_STALL 0x01
+
+#define RH_ACK 0x01
+#define RH_REQ_ERR -1
+#define RH_NACK 0x00
+
+/* OHCI ROOT HUB REGISTER MASKS */
+
+/* roothub.portstatus [i] bits */
+#define RH_PS_CCS 0x00000001 /* current connect status */
+#define RH_PS_PES 0x00000002 /* port enable status */
+#define RH_PS_PSS 0x00000004 /* port suspend status */
+#define RH_PS_POCI 0x00000008 /* port over current indicator */
+#define RH_PS_PRS 0x00000010 /* port reset status */
+#define RH_PS_PPS 0x00000100 /* port power status */
+#define RH_PS_LSDA 0x00000200 /* low speed device attached */
+#define RH_PS_CSC 0x00010000 /* connect status change */
+#define RH_PS_PESC 0x00020000 /* port enable status change */
+#define RH_PS_PSSC 0x00040000 /* port suspend status change */
+#define RH_PS_OCIC 0x00080000 /* over current indicator change */
+#define RH_PS_PRSC 0x00100000 /* port reset status change */
+
+/* roothub.status bits */
+#define RH_HS_LPS 0x00000001 /* local power status */
+#define RH_HS_OCI 0x00000002 /* over current indicator */
+#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */
+#define RH_HS_LPSC 0x00010000 /* local power status change */
+#define RH_HS_OCIC 0x00020000 /* over current indicator change */
+#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */
+
+/* roothub.b masks */
+#define RH_B_DR 0x0000ffff /* device removable flags */
+#define RH_B_PPCM 0xffff0000 /* port power control mask */
+
+/* roothub.a masks */
+#define RH_A_NDP (0xff << 0) /* number of downstream ports */
+#define RH_A_PSM (1 << 8) /* power switching mode */
+#define RH_A_NPS (1 << 9) /* no power switching */
+#define RH_A_DT (1 << 10) /* device type (mbz) */
+#define RH_A_OCPM (1 << 11) /* over current protection mode */
+#define RH_A_NOCP (1 << 12) /* no over current protection */
+#define RH_A_POTPGT (0xff << 24) /* power on to power good time */
+
+/* urb */
+#define N_URB_TD 48
+typedef struct {
+ ed_t *ed;
+ __u16 length; /* number of tds associated with this request */
+ __u16 td_cnt; /* number of tds already serviced */
+ int state;
+ unsigned long pipe;
+ int actual_length;
+ td_t *td[N_URB_TD]; /* list pointer to all corresponding TDs associated with this request */
+} urb_priv_t;
+#define URB_DEL 1
+
+/*
+ * This is the full ohci controller description
+ *
+ * Note how the "proper" USB information is just
+ * a subset of what the full implementation needs. (Linus)
+ */
+
+typedef struct ohci {
+ struct ohci_hcca *hcca; /* hcca */
+ /*dma_addr_t hcca_dma; */
+
+ int irq;
+ int disabled; /* e.g. got a UE, we're hung */
+ int sleeping;
+ unsigned long flags; /* for HC bugs */
+
+ struct ohci_regs *regs; /* OHCI controller's memory */
+
+ ed_t *ed_rm_list[2]; /* lists of all endpoints to be removed */
+ ed_t *ed_bulktail; /* last endpoint of bulk list */
+ ed_t *ed_controltail; /* last endpoint of control list */
+ int intrstatus;
+ __u32 hc_control; /* copy of the hc control reg */
+ struct usb_device *dev[32];
+ struct virt_root_hub rh;
+
+ const char *slot_name;
+} ohci_t;
+
+#define NUM_EDS 8 /* num of preallocated endpoint descriptors */
+
+struct ohci_device {
+ ed_t ed[NUM_EDS];
+ int ed_cnt;
+};
+
+/* hcd */
+/* endpoint */
+static int ep_link(ohci_t * ohci, ed_t * ed);
+static int ep_unlink(ohci_t * ohci, ed_t * ed);
+static ed_t *ep_add_ed(struct usb_device *usb_dev, unsigned long pipe);
+
+/*-------------------------------------------------------------------------*/
+
+/* we need more TDs than EDs */
+#define NUM_TD 64
+
+/* +1 so we can align the storage */
+td_t gtd[NUM_TD + 1];
+/* pointers to aligned storage */
+td_t *ptd;
+
+/* TDs ... */
+static inline struct td *td_alloc(struct usb_device *usb_dev)
+{
+ int i;
+ struct td *td;
+
+ td = NULL;
+ for (i = 0; i < NUM_TD; i++) {
+ if (ptd[i].usb_dev == NULL) {
+ td = &ptd[i];
+ td->usb_dev = usb_dev;
+ break;
+ }
+ }
+
+ return td;
+}
+
+static inline void ed_free(struct ed *ed)
+{
+ ed->usb_dev = NULL;
+}
diff --git a/cpu/ppc4xx/usbdev.c b/cpu/ppc4xx/usbdev.c
new file mode 100644
index 0000000000..8262c54bef
--- /dev/null
+++ b/cpu/ppc4xx/usbdev.c
@@ -0,0 +1,214 @@
+/*USB 1.1,2.0 device*/
+
+#include <common.h>
+#include <asm/processor.h>
+
+#ifdef CONFIG_440EP
+
+#include <usb.h>
+#include "usbdev.h"
+#include "vecnum.h"
+
+#define USB_DT_DEVICE 0x01
+#define USB_DT_CONFIG 0x02
+#define USB_DT_STRING 0x03
+#define USB_DT_INTERFACE 0x04
+#define USB_DT_ENDPOINT 0x05
+
+int set_value = -1;
+
+void process_endpoints(unsigned short usb2d0_intrin)
+{
+ /*will hold the packet received */
+ struct usb_device_descriptor usb_device_packet;
+ struct usb_config_descriptor usb_config_packet;
+ struct usb_string_descriptor usb_string_packet;
+ struct devrequest setup_packet;
+ unsigned int *setup_packet_pt;
+ unsigned char *packet_pt = NULL;
+ int temp, temp1;
+
+ int i;
+
+ /*printf("{USB device} - endpoint 0x%X \n", usb2d0_intrin); */
+
+ /*set usb address, seems to not work unless it is done in the next
+ interrupt, so that is why it is done this way */
+ if (set_value != -1)
+ *(unsigned char *)USB2D0_FADDR_8 = (unsigned char)set_value;
+
+ /*endpoint 1 */
+ if (usb2d0_intrin & 0x01) {
+ setup_packet_pt = (unsigned int *)&setup_packet;
+
+ /*copy packet */
+ setup_packet_pt[0] = *(unsigned int *)USB2D0_FIFO_0;
+ setup_packet_pt[1] = *(unsigned int *)USB2D0_FIFO_0;
+ temp = *(unsigned int *)USB2D0_FIFO_0;
+ temp1 = *(unsigned int *)USB2D0_FIFO_0;
+
+ /*do some swapping */
+ setup_packet.value = swap_16(setup_packet.value);
+ setup_packet.index = swap_16(setup_packet.index);
+ setup_packet.length = swap_16(setup_packet.length);
+
+ /*clear rx packet */
+ *(unsigned short *)USB2D0_INCSR0_8 = 0x48;
+
+ /*printf("0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X\n", setup_packet.requesttype,
+ setup_packet.request, setup_packet.value,
+ setup_packet.index, setup_packet.length, temp, temp1 ); */
+
+ switch (setup_packet.request) {
+ case USB_REQ_GET_DESCRIPTOR:
+
+ switch (setup_packet.value >> 8) {
+ case USB_DT_DEVICE:
+ /*create packet */
+ usb_device_packet.bLength = 18;
+ usb_device_packet.bDescriptorType =
+ USB_DT_DEVICE;
+#ifdef USB_2_0_DEVICE
+ usb_device_packet.bcdUSB = swap_16(0x200);
+#else
+ usb_device_packet.bcdUSB = swap_16(0x110);
+#endif
+ usb_device_packet.bDeviceClass = 0xff;
+ usb_device_packet.bDeviceSubClass = 0;
+ usb_device_packet.bDeviceProtocol = 0;
+ usb_device_packet.bMaxPacketSize0 = 32;
+ usb_device_packet.idVendor = swap_16(1);
+ usb_device_packet.idProduct = swap_16(2);
+ usb_device_packet.bcdDevice = swap_16(0x300);
+ usb_device_packet.iManufacturer = 1;
+ usb_device_packet.iProduct = 1;
+ usb_device_packet.iSerialNumber = 1;
+ usb_device_packet.bNumConfigurations = 1;
+
+ /*put packet in fifo */
+ packet_pt = (unsigned char *)&usb_device_packet;
+ break;
+
+ case USB_DT_CONFIG:
+ /*create packet */
+ usb_config_packet.bLength = 9;
+ usb_config_packet.bDescriptorType =
+ USB_DT_CONFIG;
+ usb_config_packet.wTotalLength = swap_16(25);
+ usb_config_packet.bNumInterfaces = 1;
+ usb_config_packet.bConfigurationValue = 1;
+ usb_config_packet.iConfiguration = 0;
+ usb_config_packet.bmAttributes = 0x40;
+ usb_config_packet.MaxPower = 0;
+
+ /*put packet in fifo */
+ packet_pt = (unsigned char *)&usb_config_packet;
+ break;
+
+ case USB_DT_STRING:
+ /*create packet */
+ usb_string_packet.bLength = 2;
+ usb_string_packet.bDescriptorType =
+ USB_DT_STRING;
+ usb_string_packet.wData[0] = 0x0094;
+
+ /*put packet in fifo */
+ packet_pt = (unsigned char *)&usb_string_packet;
+ break;
+ }
+
+ /*put packet in fifo */
+ for (i = 0; i < (setup_packet.length); i++) {
+ *(unsigned char *)USB2D0_FIFO_0 = packet_pt[i];
+ }
+
+ /*give tx command */
+ *(unsigned short *)USB2D0_INCSR0_8 = 0x0a;
+
+ break;
+
+ case USB_REQ_SET_ADDRESS:
+
+ /*copy usb address */
+ set_value = setup_packet.value;
+
+ break;
+ }
+
+ }
+}
+
+void process_other(unsigned char usb2d0_intrusb)
+{
+
+ /*check for sof */
+ if (usb2d0_intrusb & 0x08) {
+ /*printf("{USB device} - sof detected\n"); */
+ }
+
+ /*check for reset */
+ if (usb2d0_intrusb & 0x04) {
+ /*printf("{USB device} - reset detected\n"); */
+
+ /*copy usb address of zero, need to do this when usb reset */
+ set_value = 0;
+ }
+
+ if (usb2d0_intrusb & 0x02) {
+ /*printf("{USB device} - resume detected\n"); */
+ }
+
+ if (usb2d0_intrusb & 0x01) {
+ /*printf("{USB device} - suspend detected\n"); */
+ }
+}
+
+int usbInt(void)
+{
+ /*Must read these 2 registers and use values to clear interrupts. If you
+ do not read them then the interrupt will not be cleared. If you do not
+ use the variable the optimizer will not do a read. */
+ volatile unsigned short usb2d0_intrin =
+ *(unsigned short *)USB2D0_INTRIN_16;
+ volatile unsigned char usb2d0_intrusb =
+ *(unsigned char *)USB2D0_INTRUSB_8;
+
+ /*check if there was an endpoint interrupt */
+ if (usb2d0_intrin != 0) {
+ process_endpoints(usb2d0_intrin);
+ }
+
+ /*check for other interrupts */
+ if (usb2d0_intrusb != 0) {
+ process_other(usb2d0_intrusb);
+ }
+
+ return 0;
+}
+
+void usb_dev_init()
+{
+#ifdef USB_2_0_DEVICE
+ printf("USB 2.0 Device init\n");
+ /*select 2.0 device */
+ mtsdr(sdr_usb0, 0x0); /* 2.0 */
+
+ /*usb dev init */
+ *(unsigned char *)USB2D0_POWER_8 = 0xa1; /* 2.0 */
+#else
+ printf("USB 1.1 Device init\n");
+ /*select 1.1 device */
+ mtsdr(sdr_usb0, 0x2); /* 1.1 */
+
+ /*usb dev init */
+ *(unsigned char *)USB2D0_POWER_8 = 0xc0; /* 1.1 */
+#endif
+
+ /*enable interrupts */
+ *(unsigned char *)USB2D0_INTRUSBE_8 = 0x0f;
+
+ irq_install_handler(VECNUM_USBDEV, (interrupt_handler_t *) usbInt,
+ NULL);
+}
+
+#endif /*CONFIG_440EP */
diff --git a/cpu/ppc4xx/usbdev.h b/cpu/ppc4xx/usbdev.h
new file mode 100644
index 0000000000..3446d9893d
--- /dev/null
+++ b/cpu/ppc4xx/usbdev.h
@@ -0,0 +1,31 @@
+#include <config.h>
+
+/*Common Registers*/
+#define USB2D0_INTRIN_16 (CFG_USB_DEVICE | 0x100)
+#define USB2D0_POWER_8 (CFG_USB_DEVICE | 0x102)
+#define USB2D0_FADDR_8 (CFG_USB_DEVICE | 0x103)
+#define USB2D0_INTRINE_16 (CFG_USB_DEVICE | 0x104)
+#define USB2D0_INTROUT_16 (CFG_USB_DEVICE | 0x106)
+#define USB2D0_INTRUSBE_8 (CFG_USB_DEVICE | 0x108)
+#define USB2D0_INTRUSB_8 (CFG_USB_DEVICE | 0x109)
+#define USB2D0_INTROUTE_16 (CFG_USB_DEVICE | 0x10a)
+#define USB2D0_TSTMODE_8 (CFG_USB_DEVICE | 0x10c)
+#define USB2D0_INDEX_8 (CFG_USB_DEVICE | 0x10d)
+#define USB2D0_FRAME_16 (CFG_USB_DEVICE | 0x10e)
+
+/*Indexed Registers*/
+#define USB2D0_INCSR0_8 (CFG_USB_DEVICE | 0x110)
+#define USB2D0_INCSR_16 (CFG_USB_DEVICE | 0x110)
+#define USB2D0_INMAXP_16 (CFG_USB_DEVICE | 0x112)
+#define USB2D0_OUTCSR_16 (CFG_USB_DEVICE | 0x114)
+#define USB2D0_OUTMAXP_16 (CFG_USB_DEVICE | 0x116)
+#define USB2D0_OUTCOUNT0_8 (CFG_USB_DEVICE | 0x11a)
+#define USB2D0_OUTCOUNT_16 (CFG_USB_DEVICE | 0x11a)
+
+/*FIFOs*/
+#define USB2D0_FIFO_0 (CFG_USB_DEVICE | 0x120)
+#define USB2D0_FIFO_1 (CFG_USB_DEVICE | 0x124)
+#define USB2D0_FIFO_2 (CFG_USB_DEVICE | 0x128)
+#define USB2D0_FIFO_3 (CFG_USB_DEVICE | 0x12c)
+
+void usb_dev_init(void);
diff --git a/cpu/ppc4xx/vecnum.h b/cpu/ppc4xx/vecnum.h
index d493a5dd8f..1038975a2d 100644
--- a/cpu/ppc4xx/vecnum.h
+++ b/cpu/ppc4xx/vecnum.h
@@ -69,6 +69,7 @@
#define VECNUM_MS (32 + 0 ) /* MAL SERR */
#define VECNUM_TXDE (32 + 1 ) /* MAL TXDE */
#define VECNUM_RXDE (32 + 2 ) /* MAL RXDE */
+#define VECNUM_USBDEV (32 + 23) /* USB 1.1/USB 2.0 Device */
#define VECNUM_ETH0 (32 + 28) /* Ethernet 0 interrupt status */
#define VECNUM_EWU0 (32 + 29) /* Ethernet 0 wakeup */