summaryrefslogtreecommitdiff
path: root/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'cpu')
-rw-r--r--cpu/74xx_7xx/kgdb.S4
-rw-r--r--cpu/74xx_7xx/traps.c12
-rw-r--r--cpu/arm920t/at91rm9200/Makefile2
-rw-r--r--cpu/arm920t/at91rm9200/bcm5221.c4
-rw-r--r--cpu/arm920t/at91rm9200/dm9161.c4
-rw-r--r--cpu/arm920t/at91rm9200/ether.c10
-rw-r--r--cpu/arm920t/at91rm9200/lxt972.c4
-rw-r--r--cpu/arm920t/at91rm9200/usb.c53
-rw-r--r--cpu/arm920t/at91rm9200/usb_ohci.c1635
-rw-r--r--cpu/arm920t/at91rm9200/usb_ohci.h419
-rw-r--r--cpu/arm920t/s3c24x0/Makefile2
-rw-r--r--cpu/arm920t/s3c24x0/usb.c72
-rw-r--r--cpu/arm926ejs/davinci/Makefile49
-rw-r--r--cpu/arm926ejs/davinci/dp83848.c156
-rw-r--r--cpu/arm926ejs/davinci/ether.c650
-rw-r--r--cpu/arm926ejs/davinci/i2c.c351
-rw-r--r--cpu/arm926ejs/davinci/lowlevel_init.S707
-rw-r--r--cpu/arm926ejs/davinci/lxt972.c142
-rw-r--r--cpu/arm926ejs/davinci/nand.c389
-rw-r--r--cpu/arm926ejs/davinci/reset.S77
-rw-r--r--cpu/arm926ejs/davinci/timer.c165
-rw-r--r--cpu/at32ap/atmel_mci.c80
-rw-r--r--cpu/at32ap/atmel_mci.h4
-rw-r--r--cpu/at32ap/interrupts.c2
-rw-r--r--cpu/i386/serial.c4
-rw-r--r--cpu/ixp/cpu.c2
-rw-r--r--cpu/ixp/npe/npe.c2
-rw-r--r--cpu/mcf52x2/fec.c16
-rw-r--r--[-rwxr-xr-x]cpu/microblaze/cache.c2
-rw-r--r--[-rwxr-xr-x]cpu/microblaze/interrupts.c4
-rw-r--r--[-rwxr-xr-x]cpu/microblaze/irq.S0
-rw-r--r--cpu/mips/au1x00_eth.c8
-rw-r--r--cpu/mpc512x/Makefile46
-rw-r--r--cpu/mpc512x/config.mk25
-rw-r--r--cpu/mpc512x/cpu.c127
-rw-r--r--cpu/mpc512x/cpu_init.c87
-rw-r--r--cpu/mpc512x/fec.c801
-rw-r--r--cpu/mpc512x/fec.h224
-rw-r--r--cpu/mpc512x/i2c.c431
-rw-r--r--cpu/mpc512x/interrupts.c61
-rw-r--r--cpu/mpc512x/serial.c197
-rw-r--r--cpu/mpc512x/speed.c135
-rw-r--r--cpu/mpc512x/start.S780
-rw-r--r--cpu/mpc512x/traps.c205
-rw-r--r--cpu/mpc5xx/config.mk5
-rw-r--r--cpu/mpc5xx/interrupts.c4
-rw-r--r--cpu/mpc5xx/traps.c16
-rw-r--r--cpu/mpc5xx/u-boot.lds139
-rw-r--r--cpu/mpc5xxx/Makefile2
-rw-r--r--cpu/mpc5xxx/config.mk5
-rw-r--r--cpu/mpc5xxx/cpu_init.c2
-rw-r--r--cpu/mpc5xxx/fec.c8
-rw-r--r--cpu/mpc5xxx/ide.c4
-rw-r--r--cpu/mpc5xxx/interrupts.c2
-rw-r--r--cpu/mpc5xxx/traps.c16
-rw-r--r--cpu/mpc5xxx/u-boot-customlayout.lds135
-rw-r--r--cpu/mpc5xxx/u-boot.lds124
-rw-r--r--cpu/mpc5xxx/usb.c54
-rw-r--r--cpu/mpc8220/config.mk5
-rw-r--r--cpu/mpc8220/cpu_init.c2
-rw-r--r--cpu/mpc8220/fec.c6
-rw-r--r--cpu/mpc8220/traps.c16
-rw-r--r--cpu/mpc8220/u-boot.lds124
-rw-r--r--cpu/mpc824x/config.mk5
-rw-r--r--cpu/mpc824x/traps.c4
-rw-r--r--cpu/mpc824x/u-boot.lds124
-rw-r--r--cpu/mpc8260/bedbug_603e.c3
-rw-r--r--cpu/mpc8260/config.mk5
-rw-r--r--cpu/mpc8260/cpu_init.c2
-rw-r--r--cpu/mpc8260/ether_fcc.c8
-rw-r--r--cpu/mpc8260/ether_scc.c4
-rw-r--r--cpu/mpc8260/interrupts.c4
-rw-r--r--cpu/mpc8260/kgdb.S4
-rw-r--r--cpu/mpc8260/traps.c16
-rw-r--r--cpu/mpc8260/u-boot.lds124
-rw-r--r--cpu/mpc83xx/Makefile2
-rw-r--r--cpu/mpc83xx/config.mk5
-rw-r--r--cpu/mpc83xx/cpu.c118
-rw-r--r--cpu/mpc83xx/cpu_init.c50
-rw-r--r--cpu/mpc83xx/ecc.c390
-rw-r--r--cpu/mpc83xx/interrupts.c4
-rw-r--r--cpu/mpc83xx/pci.c36
-rw-r--r--cpu/mpc83xx/spd_sdram.c13
-rw-r--r--cpu/mpc83xx/traps.c14
-rw-r--r--cpu/mpc83xx/u-boot.lds122
-rw-r--r--cpu/mpc85xx/Makefile2
-rw-r--r--cpu/mpc85xx/cpu.c24
-rw-r--r--cpu/mpc85xx/cpu_init.c100
-rw-r--r--cpu/mpc85xx/ether_fcc.c8
-rw-r--r--cpu/mpc85xx/interrupts.c37
-rw-r--r--cpu/mpc85xx/pci.c2
-rw-r--r--cpu/mpc85xx/qe_io.c85
-rw-r--r--cpu/mpc85xx/spd_sdram.c67
-rw-r--r--cpu/mpc85xx/start.S486
-rw-r--r--cpu/mpc85xx/traps.c113
-rw-r--r--cpu/mpc86xx/Makefile3
-rw-r--r--cpu/mpc86xx/cpu_init.c4
-rw-r--r--cpu/mpc86xx/interrupts.c55
-rw-r--r--cpu/mpc86xx/pci.c146
-rw-r--r--cpu/mpc86xx/pcie_indirect.c199
-rw-r--r--cpu/mpc86xx/start.S85
-rw-r--r--cpu/mpc86xx/traps.c20
-rw-r--r--cpu/mpc8xx/bedbug_860.c2
-rw-r--r--cpu/mpc8xx/fec.c20
-rw-r--r--cpu/mpc8xx/kgdb.S4
-rw-r--r--cpu/mpc8xx/scc.c4
-rw-r--r--cpu/mpc8xx/serial.c4
-rw-r--r--cpu/mpc8xx/traps.c16
-rw-r--r--cpu/nios/cpu.c2
-rw-r--r--cpu/nios/interrupts.c4
-rw-r--r--cpu/nios2/interrupts.c4
-rw-r--r--cpu/ppc4xx/4xx_enet.c10
-rw-r--r--cpu/ppc4xx/Makefile4
-rw-r--r--cpu/ppc4xx/bedbug_405.c2
-rw-r--r--cpu/ppc4xx/dcr.S4
-rw-r--r--cpu/ppc4xx/interrupts.c4
-rw-r--r--cpu/ppc4xx/kgdb.S4
-rw-r--r--cpu/ppc4xx/ndfc.c2
-rw-r--r--cpu/ppc4xx/serial.c4
-rw-r--r--[-rwxr-xr-x]cpu/ppc4xx/traps.c14
-rw-r--r--cpu/ppc4xx/usb.c50
-rw-r--r--cpu/ppc4xx/usbdev.c2
-rw-r--r--cpu/pxa/Makefile2
-rw-r--r--cpu/pxa/usb.c79
124 files changed, 8470 insertions, 3083 deletions
diff --git a/cpu/74xx_7xx/kgdb.S b/cpu/74xx_7xx/kgdb.S
index e838513..4f23122 100644
--- a/cpu/74xx_7xx/kgdb.S
+++ b/cpu/74xx_7xx/kgdb.S
@@ -31,7 +31,7 @@
#include <asm/cache.h>
#include <asm/mmu.h>
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
/*
* cache flushing routines for kgdb
@@ -74,4 +74,4 @@ kgdb_flush_cache_range:
SYNC
blr
-#endif /* CFG_CMD_KGDB */
+#endif
diff --git a/cpu/74xx_7xx/traps.c b/cpu/74xx_7xx/traps.c
index 50c5eeb..b066227 100644
--- a/cpu/74xx_7xx/traps.c
+++ b/cpu/74xx_7xx/traps.c
@@ -40,7 +40,7 @@
DECLARE_GLOBAL_DATA_PTR;
#endif
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
int (*debugger_exception_handler)(struct pt_regs *) = 0;
#endif
@@ -133,7 +133,7 @@ MachineCheckException(struct pt_regs *regs)
return;
}
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -166,7 +166,7 @@ MachineCheckException(struct pt_regs *regs)
void
AlignmentException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -181,7 +181,7 @@ ProgramCheckException(struct pt_regs *regs)
unsigned char *p = regs ? (unsigned char *)(regs->nip) : NULL;
int i, j;
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -204,7 +204,7 @@ ProgramCheckException(struct pt_regs *regs)
void
SoftEmuException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -217,7 +217,7 @@ SoftEmuException(struct pt_regs *regs)
void
UnknownException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
diff --git a/cpu/arm920t/at91rm9200/Makefile b/cpu/arm920t/at91rm9200/Makefile
index 8d4e478..eaabad2 100644
--- a/cpu/arm920t/at91rm9200/Makefile
+++ b/cpu/arm920t/at91rm9200/Makefile
@@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(SOC).a
COBJS = bcm5221.o dm9161.o ether.o i2c.o interrupts.o \
- lxt972.o serial.o usb_ohci.o
+ lxt972.o serial.o usb.o
SOBJS = lowlevel_init.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
diff --git a/cpu/arm920t/at91rm9200/bcm5221.c b/cpu/arm920t/at91rm9200/bcm5221.c
index 6db1435..b52c615 100644
--- a/cpu/arm920t/at91rm9200/bcm5221.c
+++ b/cpu/arm920t/at91rm9200/bcm5221.c
@@ -32,7 +32,7 @@
#ifdef CONFIG_DRIVER_ETHER
-#if (CONFIG_COMMANDS & CFG_CMD_NET)
+#if defined(CONFIG_CMD_NET)
/*
* Name:
@@ -227,6 +227,6 @@ unsigned char bcm5221_AutoNegotiate (AT91PS_EMAC p_mac, int *status)
return FALSE;
}
-#endif /* CONFIG_COMMANDS & CFG_CMD_NET */
+#endif
#endif /* CONFIG_DRIVER_ETHER */
diff --git a/cpu/arm920t/at91rm9200/dm9161.c b/cpu/arm920t/at91rm9200/dm9161.c
index 4b13c23..968f653 100644
--- a/cpu/arm920t/at91rm9200/dm9161.c
+++ b/cpu/arm920t/at91rm9200/dm9161.c
@@ -27,7 +27,7 @@
#ifdef CONFIG_DRIVER_ETHER
-#if (CONFIG_COMMANDS & CFG_CMD_NET)
+#if defined(CONFIG_CMD_NET)
/*
* Name:
@@ -220,6 +220,6 @@ UCHAR dm9161_AutoNegotiate (AT91PS_EMAC p_mac, int *status)
return FALSE;
}
-#endif /* CONFIG_COMMANDS & CFG_CMD_NET */
+#endif
#endif /* CONFIG_DRIVER_ETHER */
diff --git a/cpu/arm920t/at91rm9200/ether.c b/cpu/arm920t/at91rm9200/ether.c
index 67008d0..c8f56aa 100644
--- a/cpu/arm920t/at91rm9200/ether.c
+++ b/cpu/arm920t/at91rm9200/ether.c
@@ -50,7 +50,7 @@ typedef struct {
#ifdef CONFIG_DRIVER_ETHER
-#if (CONFIG_COMMANDS & CFG_CMD_NET)
+#if defined(CONFIG_CMD_NET)
/* alignment as per Errata #11 (64 bytes) is insufficient! */
rbf_t rbfdt[RBF_FRAMEMAX] __attribute((aligned(512)));
@@ -265,7 +265,7 @@ void eth_halt (void)
{
};
-#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
int at91rm9200_miiphy_read(char *devname, unsigned char addr,
unsigned char reg, unsigned short * value)
{
@@ -284,16 +284,16 @@ int at91rm9200_miiphy_write(char *devname, unsigned char addr,
return 0;
}
-#endif /* defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) */
+#endif
int at91rm9200_miiphy_initialize(bd_t *bis)
{
-#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
miiphy_register("at91rm9200phy", at91rm9200_miiphy_read, at91rm9200_miiphy_write);
#endif
return 0;
}
-#endif /* CONFIG_COMMANDS & CFG_CMD_NET */
+#endif
#endif /* CONFIG_DRIVER_ETHER */
diff --git a/cpu/arm920t/at91rm9200/lxt972.c b/cpu/arm920t/at91rm9200/lxt972.c
index f12c59c..4edcc9a 100644
--- a/cpu/arm920t/at91rm9200/lxt972.c
+++ b/cpu/arm920t/at91rm9200/lxt972.c
@@ -33,7 +33,7 @@
#ifdef CONFIG_DRIVER_ETHER
-#if (CONFIG_COMMANDS & CFG_CMD_NET)
+#if defined(CONFIG_CMD_NET)
/*
* Name:
@@ -186,6 +186,6 @@ UCHAR lxt972_AutoNegotiate (AT91PS_EMAC p_mac, int *status)
return (lxt972_GetLinkSpeed (p_mac));
}
-#endif /* CONFIG_COMMANDS & CFG_CMD_NET */
+#endif
#endif /* CONFIG_DRIVER_ETHER */
diff --git a/cpu/arm920t/at91rm9200/usb.c b/cpu/arm920t/at91rm9200/usb.c
new file mode 100644
index 0000000..366262e
--- /dev/null
+++ b/cpu/arm920t/at91rm9200/usb.c
@@ -0,0 +1,53 @@
+/*
+ * (C) Copyright 2006
+ * DENX Software Engineering <mk@denx.de>
+ *
+ * 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 <common.h>
+
+#if defined(CONFIG_USB_OHCI_NEW) && defined(CFG_USB_OHCI_CPU_INIT)
+# ifdef CONFIG_AT91RM9200
+
+#include <asm/arch/hardware.h>
+
+int usb_cpu_init()
+{
+ /* Enable USB host clock. */
+ *AT91C_PMC_SCER = AT91C_PMC_UHP; /* 48MHz clock enabled for UHP */
+ *AT91C_PMC_PCER = 1 << AT91C_ID_UHP; /* Peripheral Clock Enable Register */
+ return 0;
+}
+
+int usb_cpu_stop()
+{
+ /* Initialization failed */
+ *AT91C_PMC_PCDR = 1 << AT91C_ID_UHP; /* Peripheral Clock Disable Register */
+ *AT91C_PMC_SCDR = AT91C_PMC_UHP; /* 48MHz clock disabled for UHP */
+ return 0;
+}
+
+int usb_cpu_init_fail()
+{
+ usb_cpu_stop();
+}
+
+# endif /* CONFIG_AT91RM9200 */
+#endif /* defined(CONFIG_USB_OHCI) && defined(CFG_USB_OHCI_CPU_INIT) */
diff --git a/cpu/arm920t/at91rm9200/usb_ohci.c b/cpu/arm920t/at91rm9200/usb_ohci.c
deleted file mode 100644
index 5b2c56c..0000000
--- a/cpu/arm920t/at91rm9200/usb_ohci.c
+++ /dev/null
@@ -1,1635 +0,0 @@
-/*
- * URB OHCI HCD (Host Controller Driver) for USB on the AT91RM9200.
- *
- * (C) Copyright 2003
- * Gary Jennejohn, DENX Software Engineering <gj@denx.de>
- *
- * 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
- *
- * Modified for the MP2USB by (C) Copyright 2005 Eric Benard
- * ebenard@eukrea.com - based on s3c24x0's driver
- *
- * 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 - you MUST define LITTLEENDIAN in the configuration file for the
- * board or this driver will NOT work!
- * 2 - this driver is intended for use with USB Mass Storage Devices
- * (BBB) ONLY. There is NO support for Interrupt or Isochronous pipes!
- * 3 - when running on a PQFP208 AT91RM9200, define CONFIG_AT91C_PQFP_UHPBUG
- * to activate workaround for bug #41 or this driver will NOT work!
- */
-
-#include <common.h>
-/* #include <pci.h> no PCI on the S3C24X0 */
-
-#ifdef CONFIG_USB_OHCI
-
-#include <asm/arch/hardware.h>
-
-#include <malloc.h>
-#include <usb.h>
-#include "usb_ohci.h"
-
-#define OHCI_USE_NPS /* force NoPowerSwitching mode */
-#undef OHCI_VERBOSE_DEBUG /* not always helpful */
-
-/* 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; })
-
-#undef DEBUG
-#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)
-#undef SHOW_INFO
-#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)
-
-/* 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;
-
-/*-------------------------------------------------------------------------*/
-
-/* 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 *)m32_swap(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);
-#ifdef CONFIG_AT91C_PQFP_UHPBUG
- ndp = (ndp == 2) ? 1:0;
-#endif
- 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;
- }
-
- /* 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 m16_swap (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 = m32_swap (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 = m32_swap (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 *ed)
-{
- ed->hwINFO |= m32_swap (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 (m32_swap (*((__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 *)m32_swap (*((__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 (m32_swap (*((__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 *)m32_swap (*((__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 = m32_swap (OHCI_ED_SKIP); /* skip ed */
- /* dummy td; end of td list for ed */
- td = td_alloc (usb_dev);
- ed->hwTailP = m32_swap (td);
- ed->hwHeadP = ed->hwTailP;
- ed->state = ED_UNLINK;
- ed->type = usb_pipetype (pipe);
- ohci_dev.ed_cnt++;
- }
-
- ed->hwINFO = m32_swap (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 *)(m32_swap (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 = m32_swap (info);
- td->hwCBP = m32_swap (data);
- if (data)
- td->hwBE = m32_swap (data + len - 1);
- 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;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* 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 = m32_swap (td->hwINFO);
- tdBE = m32_swap (td->hwBE);
- tdCBP = m32_swap (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 = m32_swap (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 (m32_swap (td_list->hwINFO))) {
- lurb_priv = &urb_priv;
- dbg(" USB-error/status: %x : %p",
- TD_CC_GET (m32_swap (td_list->hwINFO)), td_list);
- if (td_list->ed->hwHeadP & m32_swap (0x1)) {
- if (lurb_priv && ((td_list->index + 1) < lurb_priv->length)) {
- td_list->ed->hwHeadP =
- (lurb_priv->td[lurb_priv->length - 1]->hwNextTD & m32_swap (0xfffffff0)) |
- (td_list->ed->hwHeadP & m32_swap (0x2));
- lurb_priv->td_cnt += lurb_priv->length - td_list->index - 1;
- } else
- td_list->ed->hwHeadP &= m32_swap (0xfffffff2);
- }
- }
-
- td_list->next_dl_td = td_rev;
- td_rev = td_list;
- td_list_hc = m32_swap (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 = m32_swap (td_list->hwINFO);
-
- ed = td_list->ed;
-
- dl_transfer_length(td_list);
-
- /* error code of transfer */
- cc = TD_CC_GET (tdINFO);
- if (cc != 0) {
- dbg("ConditionCode %#x", cc);
- stat = cc_to_error[cc];
- }
-
- if (ed->state != ED_NEW) {
- edHeadP = m32_swap (ed->hwHeadP) & 0xfffffff0;
- edTailP = m32_swap (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);
-#ifdef CONFIG_AT91C_PQFP_UHPBUG
- ndp = (ndp == 2) ? 1:0;
-#endif
-
- 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));
-#else
- wait_ms(1);
-#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;
-#ifdef CONFIG_AT91C_PQFP_UHPBUG
- data_buf [2] = (data_buf [2] == 2) ? 1:0;
-#endif
- 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);
-#else
- wait_ms(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)*/);
-#else
- wait_ms(1);
-#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));
-#else
- wait_ms(1);
-#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;
- }
-
- wait_ms(10);
- /* ohci_dump_status(&gohci); */
-
- /* 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;
- }
- if (stat >= 0 && stat != 0xff) {
- /* 0xff is returned for an SF-interrupt */
- break;
- }
- if (--timeout) {
- wait_ms(1);
- } else {
- err("CTL:TIMEOUT ");
- stat = USB_ST_CRC_ERR;
- break;
- }
- }
- /* 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;
- }
- }
-
- dev->status = stat;
- dev->act_len = transfer_len;
-
-#ifdef DEBUG
- pkt_print(dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", usb_pipein(pipe));
-#else
- wait_ms(1);
-#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));
-#else
- wait_ms(1);
-#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 */
-
- dbg("%s\n", __FUNCTION__);
-
- 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 ;\n",
- ohci->slot_name,
- readl(&ohci->regs->control));
-
- /* Reset USB (needed by some controllers) */
- writel (0, &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) && !(m32_swap (ohci->hcca->done_head) & 0x01)) {
- ints = OHCI_INTR_WDH;
- } else {
- ints = readl (&regs->intrstatus);
- }
-
- /* dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); */
-
- if (ints & OHCI_INTR_RHSC) {
- got_rhsc = 1;
- }
-
- 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);
-#else
- wait_ms(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) {
- 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);
- }
-
- 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 = m16_swap (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)
-{
- /*
- * Enable USB host clock.
- */
- *AT91C_PMC_SCER = AT91C_PMC_UHP; /* 48MHz clock enabled for UHP */
- *AT91C_PMC_PCER = 1 << AT91C_ID_UHP; /* Peripheral Clock Enable Register */
-
- 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 *)AT91_USB_HOST_BASE;
-
- gohci.flags = 0;
- gohci.slot_name = "at91rm9200";
-
- if (hc_reset (&gohci) < 0) {
- hc_release_ohci (&gohci);
- /* Initialization failed */
- *AT91C_PMC_PCER = AT91C_ID_UHP;
- *AT91C_PMC_SCDR = 1 << AT91C_PMC_UHP; /* 48MHz clock disabled for UHP */
- return -1;
- }
-
- /* FIXME this is a second HC reset; why?? */
-/* writel (gohci.hc_control = OHCI_USB_RESET, &gohci.regs->control);
- wait_ms (10);*/
-
- if (hc_start (&gohci) < 0) {
- err ("can't start usb-%s", gohci.slot_name);
- hc_release_ohci (&gohci);
- /* Initialization failed */
- *AT91C_PMC_PCER = AT91C_ID_UHP;
- *AT91C_PMC_SCDR = 1 << AT91C_PMC_UHP; /* 48MHz clock disabled for UHP */
- return -1;
- }
-
-#ifdef DEBUG
- ohci_dump (&gohci, 1);
-#else
- wait_ms(1);
-#endif
- ohci_inited = 1;
- 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);
- /* may not want to do this */
- *AT91C_PMC_PCER = 1 << AT91C_ID_UHP;
- *AT91C_PMC_SCDR = 1 << AT91C_PMC_UHP; /* 48MHz clock disabled for UHP */
- return 0;
-}
-
-#endif /* CONFIG_USB_OHCI */
diff --git a/cpu/arm920t/at91rm9200/usb_ohci.h b/cpu/arm920t/at91rm9200/usb_ohci.h
deleted file mode 100644
index ecb4e93..0000000
--- a/cpu/arm920t/at91rm9200/usb_ohci.h
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * 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 */
- __u16 frame_no; /* current frame number */
- __u16 pad1; /* set to 0 on each frame_no change */
- __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/arm920t/s3c24x0/Makefile b/cpu/arm920t/s3c24x0/Makefile
index 3a7c4b3..0ff36c5 100644
--- a/cpu/arm920t/s3c24x0/Makefile
+++ b/cpu/arm920t/s3c24x0/Makefile
@@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(SOC).a
COBJS = i2c.o interrupts.o serial.o speed.o \
- usb_ohci.o
+ usb.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
diff --git a/cpu/arm920t/s3c24x0/usb.c b/cpu/arm920t/s3c24x0/usb.c
new file mode 100644
index 0000000..ef5d5bf
--- /dev/null
+++ b/cpu/arm920t/s3c24x0/usb.c
@@ -0,0 +1,72 @@
+/*
+ * (C) Copyright 2006
+ * DENX Software Engineering <mk@denx.de>
+ *
+ * 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 <common.h>
+
+#if defined(CONFIG_USB_OHCI_NEW) && defined(CFG_USB_OHCI_CPU_INIT)
+# if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
+
+#if defined(CONFIG_S3C2400)
+# include <s3c2400.h>
+#elif defined(CONFIG_S3C2410)
+# include <s3c2410.h>
+#endif
+
+int usb_cpu_init (void)
+{
+
+ S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+ /*
+ * Set the 48 MHz UPLL clocking. Values are taken from
+ * "PLL value selection guide", 6-23, s3c2400_UM.pdf.
+ */
+ clk_power->UPLLCON = ((40 << 12) + (1 << 4) + 2);
+ gpio->MISCCR |= 0x8; /* 1 = use pads related USB for USB host */
+
+ /*
+ * Enable USB host clock.
+ */
+ clk_power->CLKCON |= (1 << 4);
+
+ return 0;
+}
+
+int usb_cpu_stop (void)
+{
+ S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
+ /* may not want to do this */
+ clk_power->CLKCON &= ~(1 << 4);
+ return 0;
+}
+
+int usb_cpu_init_fail (void)
+{
+ S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
+ clk_power->CLKCON &= ~(1 << 4);
+ return 0;
+}
+
+# endif /* defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) */
+#endif /* defined(CONFIG_USB_OHCI) && defined(CFG_USB_OHCI_CPU_INIT) */
diff --git a/cpu/arm926ejs/davinci/Makefile b/cpu/arm926ejs/davinci/Makefile
new file mode 100644
index 0000000..0f77f40
--- /dev/null
+++ b/cpu/arm926ejs/davinci/Makefile
@@ -0,0 +1,49 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
+#
+# 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 = $(obj)lib$(SOC).a
+
+COBJS = timer.o ether.o lxt972.o dp83848.o i2c.o nand.o
+SOBJS = lowlevel_init.o reset.o
+
+SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS))
+START := $(addprefix $(obj),$(START))
+
+all: $(obj).depend $(LIB)
+
+$(LIB): $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/cpu/arm926ejs/davinci/dp83848.c b/cpu/arm926ejs/davinci/dp83848.c
new file mode 100644
index 0000000..5719845
--- /dev/null
+++ b/cpu/arm926ejs/davinci/dp83848.c
@@ -0,0 +1,156 @@
+/*
+ * National Semiconductor DP83848 PHY Driver for TI DaVinci
+ * (TMS320DM644x) based boards.
+ *
+ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
+ *
+ * --------------------------------------------------------
+ *
+ * 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 <common.h>
+#include <net.h>
+#include <dp83848.h>
+#include <asm/arch/emac_defs.h>
+
+#ifdef CONFIG_DRIVER_TI_EMAC
+
+#ifdef CONFIG_CMD_NET
+
+int dp83848_is_phy_connected(int phy_addr)
+{
+ u_int16_t id1, id2;
+
+ if (!dm644x_eth_phy_read(phy_addr, DP83848_PHYID1_REG, &id1))
+ return(0);
+ if (!dm644x_eth_phy_read(phy_addr, DP83848_PHYID2_REG, &id2))
+ return(0);
+
+ if ((id1 == DP83848_PHYID1_OUI) && (id2 == DP83848_PHYID2_OUI))
+ return(1);
+
+ return(0);
+}
+
+int dp83848_get_link_speed(int phy_addr)
+{
+ u_int16_t tmp;
+ volatile emac_regs* emac = (emac_regs *)EMAC_BASE_ADDR;
+
+ if (!dm644x_eth_phy_read(phy_addr, DP83848_STAT_REG, &tmp))
+ return(0);
+
+ if (!(tmp & DP83848_LINK_STATUS)) /* link up? */
+ return(0);
+
+ if (!dm644x_eth_phy_read(phy_addr, DP83848_PHY_STAT_REG, &tmp))
+ return(0);
+
+ /* Speed doesn't matter, there is no setting for it in EMAC... */
+ if (tmp & DP83848_SPEED) {
+ if (tmp & DP83848_DUPLEX) {
+ /* set DM644x EMAC for Full Duplex */
+ emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
+ } else {
+ /*set DM644x EMAC for Half Duplex */
+ emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE;
+ }
+
+ return(1);
+ } else {
+ if (tmp & DP83848_DUPLEX) {
+ /* set DM644x EMAC for Full Duplex */
+ emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
+ } else {
+ /*set DM644x EMAC for Half Duplex */
+ emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE;
+ }
+
+ return(1);
+ }
+
+ return(0);
+}
+
+
+int dp83848_init_phy(int phy_addr)
+{
+ int ret = 1;
+
+ if (!dp83848_get_link_speed(phy_addr)) {
+ /* Try another time */
+ udelay(100000);
+ ret = dp83848_get_link_speed(phy_addr);
+ }
+
+ /* Disable PHY Interrupts */
+ dm644x_eth_phy_write(phy_addr, DP83848_PHY_INTR_CTRL_REG, 0);
+
+ return(ret);
+}
+
+
+int dp83848_auto_negotiate(int phy_addr)
+{
+ u_int16_t tmp;
+
+
+ if (!dm644x_eth_phy_read(phy_addr, DP83848_CTL_REG, &tmp))
+ return(0);
+
+ /* Restart Auto_negotiation */
+ tmp &= ~DP83848_AUTONEG; /* remove autonegotiation enable */
+ tmp |= DP83848_ISOLATE; /* Electrically isolate PHY */
+ dm644x_eth_phy_write(phy_addr, DP83848_CTL_REG, tmp);
+
+ /* Set the Auto_negotiation Advertisement Register
+ * MII advertising for Next page, 100BaseTxFD and HD,
+ * 10BaseTFD and HD, IEEE 802.3
+ */
+ tmp = DP83848_NP | DP83848_TX_FDX | DP83848_TX_HDX |
+ DP83848_10_FDX | DP83848_10_HDX | DP83848_AN_IEEE_802_3;
+ dm644x_eth_phy_write(phy_addr, DP83848_ANA_REG, tmp);
+
+
+ /* Read Control Register */
+ if (!dm644x_eth_phy_read(phy_addr, DP83848_CTL_REG, &tmp))
+ return(0);
+
+ tmp |= DP83848_SPEED_SELECT | DP83848_AUTONEG | DP83848_DUPLEX_MODE;
+ dm644x_eth_phy_write(phy_addr, DP83848_CTL_REG, tmp);
+
+ /* Restart Auto_negotiation */
+ tmp |= DP83848_RESTART_AUTONEG;
+ dm644x_eth_phy_write(phy_addr, DP83848_CTL_REG, tmp);
+
+ /*check AutoNegotiate complete */
+ udelay(10000);
+ if (!dm644x_eth_phy_read(phy_addr, DP83848_STAT_REG, &tmp))
+ return(0);
+
+ if (!(tmp & DP83848_AUTONEG_COMP))
+ return(0);
+
+ return (dp83848_get_link_speed(phy_addr));
+}
+
+#endif /* CONFIG_CMD_NET */
+
+#endif /* CONFIG_DRIVER_ETHER */
diff --git a/cpu/arm926ejs/davinci/ether.c b/cpu/arm926ejs/davinci/ether.c
new file mode 100644
index 0000000..766bc7d
--- /dev/null
+++ b/cpu/arm926ejs/davinci/ether.c
@@ -0,0 +1,650 @@
+/*
+ * Ethernet driver for TI TMS320DM644x (DaVinci) chips.
+ *
+ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
+ *
+ * Parts shamelessly stolen from TI's dm644x_emac.c. Original copyright
+ * follows:
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * dm644x_emac.c
+ *
+ * TI DaVinci (DM644X) EMAC peripheral driver source for DV-EVM
+ *
+ * Copyright (C) 2005 Texas Instruments.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+
+ * Modifications:
+ * ver. 1.0: Sep 2005, Anant Gole - Created EMAC version for uBoot.
+ * ver 1.1: Nov 2005, Anant Gole - Extended the RX logic for multiple descriptors
+ *
+ */
+#include <common.h>
+#include <command.h>
+#include <net.h>
+#include <miiphy.h>
+#include <asm/arch/emac_defs.h>
+
+#ifdef CONFIG_DRIVER_TI_EMAC
+
+#ifdef CONFIG_CMD_NET
+
+unsigned int emac_dbg = 0;
+#define debug_emac(fmt,args...) if (emac_dbg) printf(fmt,##args)
+
+/* Internal static functions */
+static int dm644x_eth_hw_init (void);
+static int dm644x_eth_open (void);
+static int dm644x_eth_close (void);
+static int dm644x_eth_send_packet (volatile void *packet, int length);
+static int dm644x_eth_rcv_packet (void);
+static void dm644x_eth_mdio_enable(void);
+
+static int gen_init_phy(int phy_addr);
+static int gen_is_phy_connected(int phy_addr);
+static int gen_get_link_speed(int phy_addr);
+static int gen_auto_negotiate(int phy_addr);
+
+/* Wrappers exported to the U-Boot proper */
+int eth_hw_init(void)
+{
+ return(dm644x_eth_hw_init());
+}
+
+int eth_init(bd_t * bd)
+{
+ return(dm644x_eth_open());
+}
+
+void eth_halt(void)
+{
+ dm644x_eth_close();
+}
+
+int eth_send(volatile void *packet, int length)
+{
+ return(dm644x_eth_send_packet(packet, length));
+}
+
+int eth_rx(void)
+{
+ return(dm644x_eth_rcv_packet());
+}
+
+void eth_mdio_enable(void)
+{
+ dm644x_eth_mdio_enable();
+}
+/* End of wrappers */
+
+
+static u_int8_t dm644x_eth_mac_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+/*
+ * This function must be called before emac_open() if you want to override
+ * the default mac address.
+ */
+void dm644x_eth_set_mac_addr(const u_int8_t *addr)
+{
+ int i;
+
+ for (i = 0; i < sizeof (dm644x_eth_mac_addr); i++) {
+ dm644x_eth_mac_addr[i] = addr[i];
+ }
+}
+
+/* EMAC Addresses */
+static volatile emac_regs *adap_emac = (emac_regs *)EMAC_BASE_ADDR;
+static volatile ewrap_regs *adap_ewrap = (ewrap_regs *)EMAC_WRAPPER_BASE_ADDR;
+static volatile mdio_regs *adap_mdio = (mdio_regs *)EMAC_MDIO_BASE_ADDR;
+
+/* EMAC descriptors */
+static volatile emac_desc *emac_rx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_RX_DESC_BASE);
+static volatile emac_desc *emac_tx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_TX_DESC_BASE);
+static volatile emac_desc *emac_rx_active_head = 0;
+static volatile emac_desc *emac_rx_active_tail = 0;
+static int emac_rx_queue_active = 0;
+
+/* Receive packet buffers */
+static unsigned char emac_rx_buffers[EMAC_MAX_RX_BUFFERS * (EMAC_MAX_ETHERNET_PKT_SIZE + EMAC_PKT_ALIGN)];
+
+/* PHY address for a discovered PHY (0xff - not found) */
+static volatile u_int8_t active_phy_addr = 0xff;
+
+phy_t phy;
+
+static void dm644x_eth_mdio_enable(void)
+{
+ u_int32_t clkdiv;
+
+ clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1;
+
+ adap_mdio->CONTROL = (clkdiv & 0xff) |
+ MDIO_CONTROL_ENABLE |
+ MDIO_CONTROL_FAULT |
+ MDIO_CONTROL_FAULT_ENABLE;
+
+ while (adap_mdio->CONTROL & MDIO_CONTROL_IDLE) {;}
+}
+
+/*
+ * Tries to find an active connected PHY. Returns 1 if address if found.
+ * If no active PHY (or more than one PHY) found returns 0.
+ * Sets active_phy_addr variable.
+ */
+static int dm644x_eth_phy_detect(void)
+{
+ u_int32_t phy_act_state;
+ int i;
+
+ active_phy_addr = 0xff;
+
+ if ((phy_act_state = adap_mdio->ALIVE) == 0)
+ return(0); /* No active PHYs */
+
+ debug_emac("dm644x_eth_phy_detect(), ALIVE = 0x%08x\n", phy_act_state);
+
+ for (i = 0; i < 32; i++) {
+ if (phy_act_state & (1 << i)) {
+ if (phy_act_state & ~(1 << i))
+ return(0); /* More than one PHY */
+ else {
+ active_phy_addr = i;
+ return(1);
+ }
+ }
+ }
+
+ return(0); /* Just to make GCC happy */
+}
+
+
+/* Read a PHY register via MDIO inteface. Returns 1 on success, 0 otherwise */
+int dm644x_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data)
+{
+ int tmp;
+
+ while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;}
+
+ adap_mdio->USERACCESS0 = MDIO_USERACCESS0_GO |
+ MDIO_USERACCESS0_WRITE_READ |
+ ((reg_num & 0x1f) << 21) |
+ ((phy_addr & 0x1f) << 16);
+
+ /* Wait for command to complete */
+ while ((tmp = adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO) {;}
+
+ if (tmp & MDIO_USERACCESS0_ACK) {
+ *data = tmp & 0xffff;
+ return(1);
+ }
+
+ *data = -1;
+ return(0);
+}
+
+/* Write to a PHY register via MDIO inteface. Blocks until operation is complete. */
+int dm644x_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data)
+{
+
+ while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;}
+
+ adap_mdio->USERACCESS0 = MDIO_USERACCESS0_GO |
+ MDIO_USERACCESS0_WRITE_WRITE |
+ ((reg_num & 0x1f) << 21) |
+ ((phy_addr & 0x1f) << 16) |
+ (data & 0xffff);
+
+ /* Wait for command to complete */
+ while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;}
+
+ return(1);
+}
+
+/* PHY functions for a generic PHY */
+static int gen_init_phy(int phy_addr)
+{
+ int ret = 1;
+
+ if (gen_get_link_speed(phy_addr)) {
+ /* Try another time */
+ ret = gen_get_link_speed(phy_addr);
+ }
+
+ return(ret);
+}
+
+static int gen_is_phy_connected(int phy_addr)
+{
+ u_int16_t dummy;
+
+ return(dm644x_eth_phy_read(phy_addr, PHY_PHYIDR1, &dummy));
+}
+
+static int gen_get_link_speed(int phy_addr)
+{
+ u_int16_t tmp;
+
+ if (dm644x_eth_phy_read(phy_addr, MII_STATUS_REG, &tmp) && (tmp & 0x04))
+ return(1);
+
+ return(0);
+}
+
+static int gen_auto_negotiate(int phy_addr)
+{
+ u_int16_t tmp;
+
+ if (!dm644x_eth_phy_read(phy_addr, PHY_BMCR, &tmp))
+ return(0);
+
+ /* Restart Auto_negotiation */
+ tmp |= PHY_BMCR_AUTON;
+ dm644x_eth_phy_write(phy_addr, PHY_BMCR, tmp);
+
+ /*check AutoNegotiate complete */
+ udelay (10000);
+ if (!dm644x_eth_phy_read(phy_addr, PHY_BMSR, &tmp))
+ return(0);
+
+ if (!(tmp & PHY_BMSR_AUTN_COMP))
+ return(0);
+
+ return(gen_get_link_speed(phy_addr));
+}
+/* End of generic PHY functions */
+
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+static int dm644x_mii_phy_read(char *devname, unsigned char addr, unsigned char reg, unsigned short *value)
+{
+ return(dm644x_eth_phy_read(addr, reg, value) ? 0 : 1);
+}
+
+static int dm644x_mii_phy_write(char *devname, unsigned char addr, unsigned char reg, unsigned short value)
+{
+ return(dm644x_eth_phy_write(addr, reg, value) ? 0 : 1);
+}
+
+int dm644x_eth_miiphy_initialize(bd_t *bis)
+{
+ miiphy_register(phy.name, dm644x_mii_phy_read, dm644x_mii_phy_write);
+
+ return(1);
+}
+#endif
+
+/*
+ * This function initializes the emac hardware. It does NOT initialize
+ * EMAC modules power or pin multiplexors, that is done by board_init()
+ * much earlier in bootup process. Returns 1 on success, 0 otherwise.
+ */
+static int dm644x_eth_hw_init(void)
+{
+ u_int32_t phy_id;
+ u_int16_t tmp;
+ int i;
+
+ dm644x_eth_mdio_enable();
+
+ for (i = 0; i < 256; i++) {
+ if (adap_mdio->ALIVE)
+ break;
+ udelay(10);
+ }
+
+ if (i >= 256) {
+ printf("No ETH PHY detected!!!\n");
+ return(0);
+ }
+
+ /* Find if a PHY is connected and get it's address */
+ if (!dm644x_eth_phy_detect())
+ return(0);
+
+ /* Get PHY ID and initialize phy_ops for a detected PHY */
+ if (!dm644x_eth_phy_read(active_phy_addr, PHY_PHYIDR1, &tmp)) {
+ active_phy_addr = 0xff;
+ return(0);
+ }
+
+ phy_id = (tmp << 16) & 0xffff0000;
+
+ if (!dm644x_eth_phy_read(active_phy_addr, PHY_PHYIDR2, &tmp)) {
+ active_phy_addr = 0xff;
+ return(0);
+ }
+
+ phy_id |= tmp & 0x0000ffff;
+
+ switch (phy_id) {
+ case PHY_LXT972:
+ sprintf(phy.name, "LXT972 @ 0x%02x", active_phy_addr);
+ phy.init = lxt972_init_phy;
+ phy.is_phy_connected = lxt972_is_phy_connected;
+ phy.get_link_speed = lxt972_get_link_speed;
+ phy.auto_negotiate = lxt972_auto_negotiate;
+ break;
+ case PHY_DP83848:
+ sprintf(phy.name, "DP83848 @ 0x%02x", active_phy_addr);
+ phy.init = dp83848_init_phy;
+ phy.is_phy_connected = dp83848_is_phy_connected;
+ phy.get_link_speed = dp83848_get_link_speed;
+ phy.auto_negotiate = dp83848_auto_negotiate;
+ break;
+ default:
+ sprintf(phy.name, "GENERIC @ 0x%02x", active_phy_addr);
+ phy.init = gen_init_phy;
+ phy.is_phy_connected = gen_is_phy_connected;
+ phy.get_link_speed = gen_get_link_speed;
+ phy.auto_negotiate = gen_auto_negotiate;
+ }
+
+ return(1);
+}
+
+
+/* Eth device open */
+static int dm644x_eth_open(void)
+{
+ dv_reg_p addr;
+ u_int32_t clkdiv, cnt;
+ volatile emac_desc *rx_desc;
+
+ debug_emac("+ emac_open\n");
+
+ /* Reset EMAC module and disable interrupts in wrapper */
+ adap_emac->SOFTRESET = 1;
+ while (adap_emac->SOFTRESET != 0) {;}
+ adap_ewrap->EWCTL = 0;
+ for (cnt = 0; cnt < 5; cnt++) {
+ clkdiv = adap_ewrap->EWCTL;
+ }
+
+ rx_desc = emac_rx_desc;
+
+ adap_emac->TXCONTROL = 0x01;
+ adap_emac->RXCONTROL = 0x01;
+
+ /* Set MAC Addresses & Init multicast Hash to 0 (disable any multicast receive) */
+ /* Using channel 0 only - other channels are disabled */
+ adap_emac->MACINDEX = 0;
+ adap_emac->MACADDRHI =
+ (dm644x_eth_mac_addr[3] << 24) |
+ (dm644x_eth_mac_addr[2] << 16) |
+ (dm644x_eth_mac_addr[1] << 8) |
+ (dm644x_eth_mac_addr[0]);
+ adap_emac->MACADDRLO =
+ (dm644x_eth_mac_addr[5] << 8) |
+ (dm644x_eth_mac_addr[4]);
+
+ adap_emac->MACHASH1 = 0;
+ adap_emac->MACHASH2 = 0;
+
+ /* Set source MAC address - REQUIRED */
+ adap_emac->MACSRCADDRHI =
+ (dm644x_eth_mac_addr[3] << 24) |
+ (dm644x_eth_mac_addr[2] << 16) |
+ (dm644x_eth_mac_addr[1] << 8) |
+ (dm644x_eth_mac_addr[0]);
+ adap_emac->MACSRCADDRLO =
+ (dm644x_eth_mac_addr[4] << 8) |
+ (dm644x_eth_mac_addr[5]);
+
+ /* Set DMA 8 TX / 8 RX Head pointers to 0 */
+ addr = &adap_emac->TX0HDP;
+ for(cnt = 0; cnt < 16; cnt++)
+ *addr++ = 0;
+
+ addr = &adap_emac->RX0HDP;
+ for(cnt = 0; cnt < 16; cnt++)
+ *addr++ = 0;
+
+ /* Clear Statistics (do this before setting MacControl register) */
+ addr = &adap_emac->RXGOODFRAMES;
+ for(cnt = 0; cnt < EMAC_NUM_STATS; cnt++)
+ *addr++ = 0;
+
+ /* No multicast addressing */
+ adap_emac->MACHASH1 = 0;
+ adap_emac->MACHASH2 = 0;
+
+ /* Create RX queue and set receive process in place */
+ emac_rx_active_head = emac_rx_desc;
+ for (cnt = 0; cnt < EMAC_MAX_RX_BUFFERS; cnt++) {
+ rx_desc->next = (u_int32_t)(rx_desc + 1);
+ rx_desc->buffer = &emac_rx_buffers[cnt * (EMAC_MAX_ETHERNET_PKT_SIZE + EMAC_PKT_ALIGN)];
+ rx_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE;
+ rx_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT;
+ rx_desc++;
+ }
+
+ /* Set the last descriptor's "next" parameter to 0 to end the RX desc list */
+ rx_desc--;
+ rx_desc->next = 0;
+ emac_rx_active_tail = rx_desc;
+ emac_rx_queue_active = 1;
+
+ /* Enable TX/RX */
+ adap_emac->RXMAXLEN = EMAC_MAX_ETHERNET_PKT_SIZE;
+ adap_emac->RXBUFFEROFFSET = 0;
+
+ /* No fancy configs - Use this for promiscous for debug - EMAC_RXMBPENABLE_RXCAFEN_ENABLE */
+ adap_emac->RXMBPENABLE = EMAC_RXMBPENABLE_RXBROADEN;
+
+ /* Enable ch 0 only */
+ adap_emac->RXUNICASTSET = 0x01;
+
+ /* Enable MII interface and Full duplex mode */
+ adap_emac->MACCONTROL = (EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE);
+
+ /* Init MDIO & get link state */
+ clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1;
+ adap_mdio->CONTROL = ((clkdiv & 0xff) | MDIO_CONTROL_ENABLE | MDIO_CONTROL_FAULT);
+
+ if (!phy.get_link_speed(active_phy_addr))
+ return(0);
+
+ /* Start receive process */
+ adap_emac->RX0HDP = (u_int32_t)emac_rx_desc;
+
+ debug_emac("- emac_open\n");
+
+ return(1);
+}
+
+/* EMAC Channel Teardown */
+static void dm644x_eth_ch_teardown(int ch)
+{
+ dv_reg dly = 0xff;
+ dv_reg cnt;
+
+ debug_emac("+ emac_ch_teardown\n");
+
+ if (ch == EMAC_CH_TX) {
+ /* Init TX channel teardown */
+ adap_emac->TXTEARDOWN = 1;
+ for(cnt = 0; cnt != 0xfffffffc; cnt = adap_emac->TX0CP) {
+ /* Wait here for Tx teardown completion interrupt to occur
+ * Note: A task delay can be called here to pend rather than
+ * occupying CPU cycles - anyway it has been found that teardown
+ * takes very few cpu cycles and does not affect functionality */
+ dly--;
+ udelay(1);
+ if (dly == 0)
+ break;
+ }
+ adap_emac->TX0CP = cnt;
+ adap_emac->TX0HDP = 0;
+ } else {
+ /* Init RX channel teardown */
+ adap_emac->RXTEARDOWN = 1;
+ for(cnt = 0; cnt != 0xfffffffc; cnt = adap_emac->RX0CP) {
+ /* Wait here for Rx teardown completion interrupt to occur
+ * Note: A task delay can be called here to pend rather than
+ * occupying CPU cycles - anyway it has been found that teardown
+ * takes very few cpu cycles and does not affect functionality */
+ dly--;
+ udelay(1);
+ if (dly == 0)
+ break;
+ }
+ adap_emac->RX0CP = cnt;
+ adap_emac->RX0HDP = 0;
+ }
+
+ debug_emac("- emac_ch_teardown\n");
+}
+
+/* Eth device close */
+static int dm644x_eth_close(void)
+{
+ debug_emac("+ emac_close\n");
+
+ dm644x_eth_ch_teardown(EMAC_CH_TX); /* TX Channel teardown */
+ dm644x_eth_ch_teardown(EMAC_CH_RX); /* RX Channel teardown */
+
+ /* Reset EMAC module and disable interrupts in wrapper */
+ adap_emac->SOFTRESET = 1;
+ adap_ewrap->EWCTL = 0;
+
+ debug_emac("- emac_close\n");
+ return(1);
+}
+
+static int tx_send_loop = 0;
+
+/*
+ * This function sends a single packet on the network and returns
+ * positive number (number of bytes transmitted) or negative for error
+ */
+static int dm644x_eth_send_packet(volatile void *packet, int length)
+{
+ int ret_status = -1;
+ tx_send_loop = 0;
+
+ /* Return error if no link */
+ if (!phy.get_link_speed(active_phy_addr))
+ {
+ printf("WARN: emac_send_packet: No link\n");
+ return (ret_status);
+ }
+
+ /* Check packet size and if < EMAC_MIN_ETHERNET_PKT_SIZE, pad it up */
+ if (length < EMAC_MIN_ETHERNET_PKT_SIZE)
+ {
+ length = EMAC_MIN_ETHERNET_PKT_SIZE;
+ }
+
+ /* Populate the TX descriptor */
+ emac_tx_desc->next = 0;
+ emac_tx_desc->buffer = (u_int8_t *)packet;
+ emac_tx_desc->buff_off_len = (length & 0xffff);
+ emac_tx_desc->pkt_flag_len = ((length & 0xffff) |
+ EMAC_CPPI_SOP_BIT |
+ EMAC_CPPI_OWNERSHIP_BIT |
+ EMAC_CPPI_EOP_BIT);
+ /* Send the packet */
+ adap_emac->TX0HDP = (unsigned int)emac_tx_desc;
+
+ /* Wait for packet to complete or link down */
+ while (1) {
+ if (!phy.get_link_speed(active_phy_addr)) {
+ dm644x_eth_ch_teardown(EMAC_CH_TX);
+ return (ret_status);
+ }
+ if (adap_emac->TXINTSTATRAW & 0x01) {
+ ret_status = length;
+ break;
+ }
+ tx_send_loop++;
+ }
+
+ return(ret_status);
+}
+
+/*
+ * This function handles receipt of a packet from the network
+ */
+static int dm644x_eth_rcv_packet(void)
+{
+ volatile emac_desc *rx_curr_desc;
+ volatile emac_desc *curr_desc;
+ volatile emac_desc *tail_desc;
+ int status, ret = -1;
+
+ rx_curr_desc = emac_rx_active_head;
+ status = rx_curr_desc->pkt_flag_len;
+ if ((rx_curr_desc) && ((status & EMAC_CPPI_OWNERSHIP_BIT) == 0)) {
+ if (status & EMAC_CPPI_RX_ERROR_FRAME) {
+ /* Error in packet - discard it and requeue desc */
+ printf("WARN: emac_rcv_pkt: Error in packet\n");
+ } else {
+ NetReceive(rx_curr_desc->buffer, (rx_curr_desc->buff_off_len & 0xffff));
+ ret = rx_curr_desc->buff_off_len & 0xffff;
+ }
+
+ /* Ack received packet descriptor */
+ adap_emac->RX0CP = (unsigned int)rx_curr_desc;
+ curr_desc = rx_curr_desc;
+ emac_rx_active_head = (volatile emac_desc *)rx_curr_desc->next;
+
+ if (status & EMAC_CPPI_EOQ_BIT) {
+ if (emac_rx_active_head) {
+ adap_emac->RX0HDP = (unsigned int)emac_rx_active_head;
+ } else {
+ emac_rx_queue_active = 0;
+ printf("INFO:emac_rcv_packet: RX Queue not active\n");
+ }
+ }
+
+ /* Recycle RX descriptor */
+ rx_curr_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE;
+ rx_curr_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT;
+ rx_curr_desc->next = 0;
+
+ if (emac_rx_active_head == 0) {
+ printf("INFO: emac_rcv_pkt: active queue head = 0\n");
+ emac_rx_active_head = curr_desc;
+ emac_rx_active_tail = curr_desc;
+ if (emac_rx_queue_active != 0) {
+ adap_emac->RX0HDP = (unsigned int)emac_rx_active_head;
+ printf("INFO: emac_rcv_pkt: active queue head = 0, HDP fired\n");
+ emac_rx_queue_active = 1;
+ }
+ } else {
+ tail_desc = emac_rx_active_tail;
+ emac_rx_active_tail = curr_desc;
+ tail_desc->next = (unsigned int)curr_desc;
+ status = tail_desc->pkt_flag_len;
+ if (status & EMAC_CPPI_EOQ_BIT) {
+ adap_emac->RX0HDP = (unsigned int)curr_desc;
+ status &= ~EMAC_CPPI_EOQ_BIT;
+ tail_desc->pkt_flag_len = status;
+ }
+ }
+ return(ret);
+ }
+ return(0);
+}
+
+#endif /* CONFIG_CMD_NET */
+
+#endif /* CONFIG_DRIVER_TI_EMAC */
diff --git a/cpu/arm926ejs/davinci/i2c.c b/cpu/arm926ejs/davinci/i2c.c
new file mode 100644
index 0000000..af9dc03
--- /dev/null
+++ b/cpu/arm926ejs/davinci/i2c.c
@@ -0,0 +1,351 @@
+/*
+ * TI DaVinci (TMS320DM644x) I2C driver.
+ *
+ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
+ *
+ * --------------------------------------------------------
+ *
+ * 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 <common.h>
+
+#ifdef CONFIG_DRIVER_DAVINCI_I2C
+
+#include <i2c.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/i2c_defs.h>
+
+#define CHECK_NACK() \
+ do {\
+ if (tmp & (I2C_TIMEOUT | I2C_STAT_NACK)) {\
+ REG(I2C_CON) = 0;\
+ return(1);\
+ }\
+ } while (0)
+
+
+static int wait_for_bus(void)
+{
+ int stat, timeout;
+
+ REG(I2C_STAT) = 0xffff;
+
+ for (timeout = 0; timeout < 10; timeout++) {
+ if (!((stat = REG(I2C_STAT)) & I2C_STAT_BB)) {
+ REG(I2C_STAT) = 0xffff;
+ return(0);
+ }
+
+ REG(I2C_STAT) = stat;
+ udelay(50000);
+ }
+
+ REG(I2C_STAT) = 0xffff;
+ return(1);
+}
+
+
+static int poll_i2c_irq(int mask)
+{
+ int stat, timeout;
+
+ for (timeout = 0; timeout < 10; timeout++) {
+ udelay(1000);
+ stat = REG(I2C_STAT);
+ if (stat & mask) {
+ return(stat);
+ }
+ }
+
+ REG(I2C_STAT) = 0xffff;
+ return(stat | I2C_TIMEOUT);
+}
+
+
+void flush_rx(void)
+{
+ int dummy;
+
+ while (1) {
+ if (!(REG(I2C_STAT) & I2C_STAT_RRDY))
+ break;
+
+ dummy = REG(I2C_DRR);
+ REG(I2C_STAT) = I2C_STAT_RRDY;
+ udelay(1000);
+ }
+}
+
+
+void i2c_init(int speed, int slaveadd)
+{
+ u_int32_t div, psc;
+
+ if (REG(I2C_CON) & I2C_CON_EN) {
+ REG(I2C_CON) = 0;
+ udelay (50000);
+ }
+
+ psc = 2;
+ div = (CFG_HZ_CLOCK / ((psc + 1) * speed)) - 10; /* SCLL + SCLH */
+ REG(I2C_PSC) = psc; /* 27MHz / (2 + 1) = 9MHz */
+ REG(I2C_SCLL) = (div * 50) / 100; /* 50% Duty */
+ REG(I2C_SCLH) = div - REG(I2C_SCLL);
+
+ REG(I2C_OA) = slaveadd;
+ REG(I2C_CNT) = 0;
+
+ /* Interrupts must be enabled or I2C module won't work */
+ REG(I2C_IE) = I2C_IE_SCD_IE | I2C_IE_XRDY_IE |
+ I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | I2C_IE_NACK_IE;
+
+ /* Now enable I2C controller (get it out of reset) */
+ REG(I2C_CON) = I2C_CON_EN;
+
+ udelay(1000);
+}
+
+
+int i2c_probe(u_int8_t chip)
+{
+ int rc = 1;
+
+ if (chip == REG(I2C_OA)) {
+ return(rc);
+ }
+
+ REG(I2C_CON) = 0;
+ if (wait_for_bus()) {return(1);}
+
+ /* try to read one byte from current (or only) address */
+ REG(I2C_CNT) = 1;
+ REG(I2C_SA) = chip;
+ REG(I2C_CON) = (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP);
+ udelay (50000);
+
+ if (!(REG(I2C_STAT) & I2C_STAT_NACK)) {
+ rc = 0;
+ flush_rx();
+ REG(I2C_STAT) = 0xffff;
+ } else {
+ REG(I2C_STAT) = 0xffff;
+ REG(I2C_CON) |= I2C_CON_STP;
+ udelay(20000);
+ if (wait_for_bus()) {return(1);}
+ }
+
+ flush_rx();
+ REG(I2C_STAT) = 0xffff;
+ REG(I2C_CNT) = 0;
+ return(rc);
+}
+
+
+int i2c_read(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len)
+{
+ u_int32_t tmp;
+ int i;
+
+ if ((alen < 0) || (alen > 2)) {
+ printf("%s(): bogus address length %x\n", __FUNCTION__, alen);
+ return(1);
+ }
+
+ if (wait_for_bus()) {return(1);}
+
+ if (alen != 0) {
+ /* Start address phase */
+ tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX;
+ REG(I2C_CNT) = alen;
+ REG(I2C_SA) = chip;
+ REG(I2C_CON) = tmp;
+
+ tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
+
+ CHECK_NACK();
+
+ switch (alen) {
+ case 2:
+ /* Send address MSByte */
+ if (tmp & I2C_STAT_XRDY) {
+ REG(I2C_DXR) = (addr >> 8) & 0xff;
+ } else {
+ REG(I2C_CON) = 0;
+ return(1);
+ }
+
+ tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
+
+ CHECK_NACK();
+ /* No break, fall through */
+ case 1:
+ /* Send address LSByte */
+ if (tmp & I2C_STAT_XRDY) {
+ REG(I2C_DXR) = addr & 0xff;
+ } else {
+ REG(I2C_CON) = 0;
+ return(1);
+ }
+
+ tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK | I2C_STAT_ARDY);
+
+ CHECK_NACK();
+
+ if (!(tmp & I2C_STAT_ARDY)) {
+ REG(I2C_CON) = 0;
+ return(1);
+ }
+ }
+ }
+
+ /* Address phase is over, now read 'len' bytes and stop */
+ tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP;
+ REG(I2C_CNT) = len & 0xffff;
+ REG(I2C_SA) = chip;
+ REG(I2C_CON) = tmp;
+
+ for (i = 0; i < len; i++) {
+ tmp = poll_i2c_irq(I2C_STAT_RRDY | I2C_STAT_NACK | I2C_STAT_ROVR);
+
+ CHECK_NACK();
+
+ if (tmp & I2C_STAT_RRDY) {
+ buf[i] = REG(I2C_DRR);
+ } else {
+ REG(I2C_CON) = 0;
+ return(1);
+ }
+ }
+
+ tmp = poll_i2c_irq(I2C_STAT_SCD | I2C_STAT_NACK);
+
+ CHECK_NACK();
+
+ if (!(tmp & I2C_STAT_SCD)) {
+ REG(I2C_CON) = 0;
+ return(1);
+ }
+
+ flush_rx();
+ REG(I2C_STAT) = 0xffff;
+ REG(I2C_CNT) = 0;
+ REG(I2C_CON) = 0;
+
+ return(0);
+}
+
+
+int i2c_write(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len)
+{
+ u_int32_t tmp;
+ int i;
+
+ if ((alen < 0) || (alen > 2)) {
+ printf("%s(): bogus address length %x\n", __FUNCTION__, alen);
+ return(1);
+ }
+ if (len < 0) {
+ printf("%s(): bogus length %x\n", __FUNCTION__, len);
+ return(1);
+ }
+
+ if (wait_for_bus()) {return(1);}
+
+ /* Start address phase */
+ tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | I2C_CON_STP;
+ REG(I2C_CNT) = (alen == 0) ? len & 0xffff : (len & 0xffff) + alen;
+ REG(I2C_SA) = chip;
+ REG(I2C_CON) = tmp;
+
+ switch (alen) {
+ case 2:
+ /* Send address MSByte */
+ tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
+
+ CHECK_NACK();
+
+ if (tmp & I2C_STAT_XRDY) {
+ REG(I2C_DXR) = (addr >> 8) & 0xff;
+ } else {
+ REG(I2C_CON) = 0;
+ return(1);
+ }
+ /* No break, fall through */
+ case 1:
+ /* Send address LSByte */
+ tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
+
+ CHECK_NACK();
+
+ if (tmp & I2C_STAT_XRDY) {
+ REG(I2C_DXR) = addr & 0xff;
+ } else {
+ REG(I2C_CON) = 0;
+ return(1);
+ }
+ }
+
+ for (i = 0; i < len; i++) {
+ tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
+
+ CHECK_NACK();
+
+ if (tmp & I2C_STAT_XRDY) {
+ REG(I2C_DXR) = buf[i];
+ } else {
+ return(1);
+ }
+ }
+
+ tmp = poll_i2c_irq(I2C_STAT_SCD | I2C_STAT_NACK);
+
+ CHECK_NACK();
+
+ if (!(tmp & I2C_STAT_SCD)) {
+ REG(I2C_CON) = 0;
+ return(1);
+ }
+
+ flush_rx();
+ REG(I2C_STAT) = 0xffff;
+ REG(I2C_CNT) = 0;
+ REG(I2C_CON) = 0;
+
+ return(0);
+}
+
+
+u_int8_t i2c_reg_read(u_int8_t chip, u_int8_t reg)
+{
+ u_int8_t tmp;
+
+ i2c_read(chip, reg, 1, &tmp, 1);
+ return(tmp);
+}
+
+
+void i2c_reg_write(u_int8_t chip, u_int8_t reg, u_int8_t val)
+{
+ u_int8_t tmp;
+
+ i2c_write(chip, reg, 1, &tmp, 1);
+}
+
+#endif /* CONFIG_DRIVER_DAVINCI_I2C */
diff --git a/cpu/arm926ejs/davinci/lowlevel_init.S b/cpu/arm926ejs/davinci/lowlevel_init.S
new file mode 100644
index 0000000..a87c112
--- /dev/null
+++ b/cpu/arm926ejs/davinci/lowlevel_init.S
@@ -0,0 +1,707 @@
+/*
+ * Low-level board setup code for TI DaVinci SoC based boards.
+ *
+ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
+ *
+ * Partially based on TI sources, original copyrights follow:
+ */
+
+/*
+ * Board specific setup info
+ *
+ * (C) Copyright 2003
+ * Texas Instruments, <www.ti.com>
+ * Kshitij Gupta <Kshitij@ti.com>
+ *
+ * Modified for OMAP 1610 H2 board by Nishant Kamat, Jan 2004
+ *
+ * Modified for OMAP 5912 OSK board by Rishi Bhattacharya, Apr 2004
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * Modified for DV-EVM board by Rishi Bhattacharya, Apr 2005
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * Modified for DV-EVM board by Swaminathan S, Nov 2005
+ * 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 <config.h>
+
+.globl lowlevel_init
+lowlevel_init:
+
+ /*-------------------------------------------------------*
+ * Mask all IRQs by setting all bits in the EINT default *
+ *-------------------------------------------------------*/
+ mov r1, $0
+ ldr r0, =EINT_ENABLE0
+ str r1, [r0]
+ ldr r0, =EINT_ENABLE1
+ str r1, [r0]
+
+ /*------------------------------------------------------*
+ * Put the GEM in reset *
+ *------------------------------------------------------*/
+
+ /* Put the GEM in reset */
+ ldr r8, PSC_GEM_FLAG_CLEAR
+ ldr r6, MDCTL_GEM
+ ldr r7, [r6]
+ and r7, r7, r8
+ str r7, [r6]
+
+ /* Enable the Power Domain Transition Command */
+ ldr r6, PTCMD
+ ldr r7, [r6]
+ orr r7, r7, $0x02
+ str r7, [r6]
+
+ /* Check for Transition Complete(PTSTAT) */
+checkStatClkStopGem:
+ ldr r6, PTSTAT
+ ldr r7, [r6]
+ ands r7, r7, $0x02
+ bne checkStatClkStopGem
+
+ /* Check for GEM Reset Completion */
+checkGemStatClkStop:
+ ldr r6, MDSTAT_GEM
+ ldr r7, [r6]
+ ands r7, r7, $0x100
+ bne checkGemStatClkStop
+
+ /* Do this for enabling a WDT initiated reset this is a workaround
+ for a chip bug. Not required under normal situations */
+ ldr r6, P1394
+ mov r10, $0
+ str r10, [r6]
+
+ /*------------------------------------------------------*
+ * Enable L1 & L2 Memories in Fast mode *
+ *------------------------------------------------------*/
+ ldr r6, DFT_ENABLE
+ mov r10, $0x01
+ str r10, [r6]
+
+ ldr r6, MMARG_BRF0
+ ldr r10, MMARG_BRF0_VAL
+ str r10, [r6]
+
+ ldr r6, DFT_ENABLE
+ mov r10, $0
+ str r10, [r6]
+
+ /*------------------------------------------------------*
+ * DDR2 PLL Initialization *
+ *------------------------------------------------------*/
+
+ /* Select the Clock Mode Depending on the Value written in the Boot Table by the run script */
+ mov r10, $0
+ ldr r6, PLL2_CTL
+ ldr r7, PLL_CLKSRC_MASK
+ ldr r8, [r6]
+ and r8, r8, r7
+ mov r9, r10, lsl $8
+ orr r8, r8, r9
+ str r8, [r6]
+
+ /* Select the PLLEN source */
+ ldr r7, PLL_ENSRC_MASK
+ and r8, r8, r7
+ str r8, [r6]
+
+ /* Bypass the PLL */
+ ldr r7, PLL_BYPASS_MASK
+ and r8, r8, r7
+ str r8, [r6]
+
+ /* Wait for few cycles to allow PLLEN Mux switch properly to bypass Clock */
+ mov r10, $0x20
+WaitPPL2Loop:
+ subs r10, r10, $1
+ bne WaitPPL2Loop
+
+ /* Reset the PLL */
+ ldr r7, PLL_RESET_MASK
+ and r8, r8, r7
+ str r8, [r6]
+
+ /* Power up the PLL */
+ ldr r7, PLL_PWRUP_MASK
+ and r8, r8, r7
+ str r8, [r6]
+
+ /* Enable the PLL from Disable Mode */
+ ldr r7, PLL_DISABLE_ENABLE_MASK
+ and r8, r8, r7
+ str r8, [r6]
+
+ /* Program the PLL Multiplier */
+ ldr r6, PLL2_PLLM
+ mov r2, $0x17 /* 162 MHz */
+ str r2, [r6]
+
+ /* Program the PLL2 Divisor Value */
+ ldr r6, PLL2_DIV2
+ mov r3, $0x01
+ str r3, [r6]
+
+ /* Program the PLL2 Divisor Value */
+ ldr r6, PLL2_DIV1
+ mov r4, $0x0b /* 54 MHz */
+ str r4, [r6]
+
+ /* PLL2 DIV2 MMR */
+ ldr r8, PLL2_DIV_MASK
+ ldr r6, PLL2_DIV2
+ ldr r9, [r6]
+ and r8, r8, r9
+ mov r9, $0x01
+ mov r9, r9, lsl $15
+ orr r8, r8, r9
+ str r8, [r6]
+
+ /* Program the GOSET bit to take new divider values */
+ ldr r6, PLL2_PLLCMD
+ ldr r7, [r6]
+ orr r7, r7, $0x01
+ str r7, [r6]
+
+ /* Wait for Done */
+ ldr r6, PLL2_PLLSTAT
+doneLoop_0:
+ ldr r7, [r6]
+ ands r7, r7, $0x01
+ bne doneLoop_0
+
+ /* PLL2 DIV1 MMR */
+ ldr r8, PLL2_DIV_MASK
+ ldr r6, PLL2_DIV1
+ ldr r9, [r6]
+ and r8, r8, r9
+ mov r9, $0x01
+ mov r9, r9, lsl $15
+ orr r8, r8, r9
+ str r8, [r6]
+
+ /* Program the GOSET bit to take new divider values */
+ ldr r6, PLL2_PLLCMD
+ ldr r7, [r6]
+ orr r7, r7, $0x01
+ str r7, [r6]
+
+ /* Wait for Done */
+ ldr r6, PLL2_PLLSTAT
+doneLoop:
+ ldr r7, [r6]
+ ands r7, r7, $0x01
+ bne doneLoop
+
+ /* Wait for PLL to Reset Properly */
+ mov r10, $0x218
+ResetPPL2Loop:
+ subs r10, r10, $1
+ bne ResetPPL2Loop
+
+ /* Bring PLL out of Reset */
+ ldr r6, PLL2_CTL
+ ldr r8, [r6]
+ orr r8, r8, $0x08
+ str r8, [r6]
+
+ /* Wait for PLL to Lock */
+ ldr r10, PLL_LOCK_COUNT
+PLL2Lock:
+ subs r10, r10, $1
+ bne PLL2Lock
+
+ /* Enable the PLL */
+ ldr r6, PLL2_CTL
+ ldr r8, [r6]
+ orr r8, r8, $0x01
+ str r8, [r6]
+
+ /*------------------------------------------------------*
+ * Issue Soft Reset to DDR Module *
+ *------------------------------------------------------*/
+
+ /* Shut down the DDR2 LPSC Module */
+ ldr r8, PSC_FLAG_CLEAR
+ ldr r6, MDCTL_DDR2
+ ldr r7, [r6]
+ and r7, r7, r8
+ orr r7, r7, $0x03
+ str r7, [r6]
+
+ /* Enable the Power Domain Transition Command */
+ ldr r6, PTCMD
+ ldr r7, [r6]
+ orr r7, r7, $0x01
+ str r7, [r6]
+
+ /* Check for Transition Complete(PTSTAT) */
+checkStatClkStop:
+ ldr r6, PTSTAT
+ ldr r7, [r6]
+ ands r7, r7, $0x01
+ bne checkStatClkStop
+
+ /* Check for DDR2 Controller Enable Completion */
+checkDDRStatClkStop:
+ ldr r6, MDSTAT_DDR2
+ ldr r7, [r6]
+ and r7, r7, $0x1f
+ cmp r7, $0x03
+ bne checkDDRStatClkStop
+
+ /*------------------------------------------------------*
+ * Program DDR2 MMRs for 162MHz Setting *
+ *------------------------------------------------------*/
+
+ /* Program PHY Control Register */
+ ldr r6, DDRCTL
+ ldr r7, DDRCTL_VAL
+ str r7, [r6]
+
+ /* Program SDRAM Bank Config Register */
+ ldr r6, SDCFG
+ ldr r7, SDCFG_VAL
+ str r7, [r6]
+
+ /* Program SDRAM TIM-0 Config Register */
+ ldr r6, SDTIM0
+ ldr r7, SDTIM0_VAL_162MHz
+ str r7, [r6]
+
+ /* Program SDRAM TIM-1 Config Register */
+ ldr r6, SDTIM1
+ ldr r7, SDTIM1_VAL_162MHz
+ str r7, [r6]
+
+ /* Program the SDRAM Bank Config Control Register */
+ ldr r10, MASK_VAL
+ ldr r8, SDCFG
+ ldr r9, SDCFG_VAL
+ and r9, r9, r10
+ str r9, [r8]
+
+ /* Program SDRAM SDREF Config Register */
+ ldr r6, SDREF
+ ldr r7, SDREF_VAL
+ str r7, [r6]
+
+ /*------------------------------------------------------*
+ * Issue Soft Reset to DDR Module *
+ *------------------------------------------------------*/
+
+ /* Issue a Dummy DDR2 read/write */
+ ldr r8, DDR2_START_ADDR
+ ldr r7, DUMMY_VAL
+ str r7, [r8]
+ ldr r7, [r8]
+
+ /* Shut down the DDR2 LPSC Module */
+ ldr r8, PSC_FLAG_CLEAR
+ ldr r6, MDCTL_DDR2
+ ldr r7, [r6]
+ and r7, r7, r8
+ orr r7, r7, $0x01
+ str r7, [r6]
+
+ /* Enable the Power Domain Transition Command */
+ ldr r6, PTCMD
+ ldr r7, [r6]
+ orr r7, r7, $0x01
+ str r7, [r6]
+
+ /* Check for Transition Complete(PTSTAT) */
+checkStatClkStop2:
+ ldr r6, PTSTAT
+ ldr r7, [r6]
+ ands r7, r7, $0x01
+ bne checkStatClkStop2
+
+ /* Check for DDR2 Controller Enable Completion */
+checkDDRStatClkStop2:
+ ldr r6, MDSTAT_DDR2
+ ldr r7, [r6]
+ and r7, r7, $0x1f
+ cmp r7, $0x01
+ bne checkDDRStatClkStop2
+
+ /*------------------------------------------------------*
+ * Turn DDR2 Controller Clocks On *
+ *------------------------------------------------------*/
+
+ /* Enable the DDR2 LPSC Module */
+ ldr r6, MDCTL_DDR2
+ ldr r7, [r6]
+ orr r7, r7, $0x03
+ str r7, [r6]
+
+ /* Enable the Power Domain Transition Command */
+ ldr r6, PTCMD
+ ldr r7, [r6]
+ orr r7, r7, $0x01
+ str r7, [r6]
+
+ /* Check for Transition Complete(PTSTAT) */
+checkStatClkEn2:
+ ldr r6, PTSTAT
+ ldr r7, [r6]
+ ands r7, r7, $0x01
+ bne checkStatClkEn2
+
+ /* Check for DDR2 Controller Enable Completion */
+checkDDRStatClkEn2:
+ ldr r6, MDSTAT_DDR2
+ ldr r7, [r6]
+ and r7, r7, $0x1f
+ cmp r7, $0x03
+ bne checkDDRStatClkEn2
+
+ /* DDR Writes and Reads */
+ ldr r6, CFGTEST
+ mov r3, $0x01
+ str r3, [r6]
+
+ /*------------------------------------------------------*
+ * System PLL Initialization *
+ *------------------------------------------------------*/
+
+ /* Select the Clock Mode Depending on the Value written in the Boot Table by the run script */
+ mov r2, $0
+ ldr r6, PLL1_CTL
+ ldr r7, PLL_CLKSRC_MASK
+ ldr r8, [r6]
+ and r8, r8, r7
+ mov r9, r2, lsl $8
+ orr r8, r8, r9
+ str r8, [r6]
+
+ /* Select the PLLEN source */
+ ldr r7, PLL_ENSRC_MASK
+ and r8, r8, r7
+ str r8, [r6]
+
+ /* Bypass the PLL */
+ ldr r7, PLL_BYPASS_MASK
+ and r8, r8, r7
+ str r8, [r6]
+
+ /* Wait for few cycles to allow PLLEN Mux switch properly to bypass Clock */
+ mov r10, $0x20
+
+WaitLoop:
+ subs r10, r10, $1
+ bne WaitLoop
+
+ /* Reset the PLL */
+ ldr r7, PLL_RESET_MASK
+ and r8, r8, r7
+ str r8, [r6]
+
+ /* Disable the PLL */
+ orr r8, r8, $0x10
+ str r8, [r6]
+
+ /* Power up the PLL */
+ ldr r7, PLL_PWRUP_MASK
+ and r8, r8, r7
+ str r8, [r6]
+
+ /* Enable the PLL from Disable Mode */
+ ldr r7, PLL_DISABLE_ENABLE_MASK
+ and r8, r8, r7
+ str r8, [r6]
+
+ /* Program the PLL Multiplier */
+ ldr r6, PLL1_PLLM
+ mov r3, $0x15 /* For 594MHz */
+ str r3, [r6]
+
+ /* Wait for PLL to Reset Properly */
+ mov r10, $0xff
+
+ResetLoop:
+ subs r10, r10, $1
+ bne ResetLoop
+
+ /* Bring PLL out of Reset */
+ ldr r6, PLL1_CTL
+ orr r8, r8, $0x08
+ str r8, [r6]
+
+ /* Wait for PLL to Lock */
+ ldr r10, PLL_LOCK_COUNT
+
+PLL1Lock:
+ subs r10, r10, $1
+ bne PLL1Lock
+
+ /* Enable the PLL */
+ orr r8, r8, $0x01
+ str r8, [r6]
+
+ nop
+ nop
+ nop
+ nop
+
+ /*------------------------------------------------------*
+ * AEMIF configuration for NOR Flash (double check) *
+ *------------------------------------------------------*/
+ ldr r0, _PINMUX0
+ ldr r1, _DEV_SETTING
+ str r1, [r0]
+
+ ldr r0, WAITCFG
+ ldr r1, WAITCFG_VAL
+ ldr r2, [r0]
+ orr r2, r2, r1
+ str r2, [r0]
+
+ ldr r0, ACFG3
+ ldr r1, ACFG3_VAL
+ ldr r2, [r0]
+ and r1, r2, r1
+ str r1, [r0]
+
+ ldr r0, ACFG4
+ ldr r1, ACFG4_VAL
+ ldr r2, [r0]
+ and r1, r2, r1
+ str r1, [r0]
+
+ ldr r0, ACFG5
+ ldr r1, ACFG5_VAL
+ ldr r2, [r0]
+ and r1, r2, r1
+ str r1, [r0]
+
+ /*--------------------------------------*
+ * VTP manual Calibration *
+ *--------------------------------------*/
+ ldr r0, VTPIOCR
+ ldr r1, VTP_MMR0
+ str r1, [r0]
+
+ ldr r0, VTPIOCR
+ ldr r1, VTP_MMR1
+ str r1, [r0]
+
+ /* Wait for 33 VTP CLK cycles. VRP operates at 27 MHz */
+ ldr r10, VTP_LOCK_COUNT
+VTPLock:
+ subs r10, r10, $1
+ bne VTPLock
+
+ ldr r6, DFT_ENABLE
+ mov r10, $0x01
+ str r10, [r6]
+
+ ldr r6, DDRVTPR
+ ldr r7, [r6]
+ and r7, r7, $0x1f
+ and r8, r7, $0x3e0
+ orr r8, r7, r8
+ ldr r7, VTP_RECAL
+ orr r8, r7, r8
+ ldr r7, VTP_EN
+ orr r8, r7, r8
+ str r8, [r0]
+
+
+ /* Wait for 33 VTP CLK cycles. VRP operates at 27 MHz */
+ ldr r10, VTP_LOCK_COUNT
+VTP1Lock:
+ subs r10, r10, $1
+ bne VTP1Lock
+
+ ldr r1, [r0]
+ ldr r2, VTP_MASK
+ and r2, r1, r2
+ str r2, [r0]
+
+ ldr r6, DFT_ENABLE
+ mov r10, $0
+ str r10, [r6]
+
+ /*
+ * Call board-specific lowlevel init.
+ * That MUST be present and THAT returns
+ * back to arch calling code with "mov pc, lr."
+ */
+ b dv_board_init
+
+.ltorg
+
+_PINMUX0:
+ .word 0x01c40000 /* Device Configuration Registers */
+_PINMUX1:
+ .word 0x01c40004 /* Device Configuration Registers */
+
+_DEV_SETTING:
+ .word 0x00000c1f
+
+WAITCFG:
+ .word 0x01e00004
+WAITCFG_VAL:
+ .word 0
+ACFG3:
+ .word 0x01e00014
+ACFG3_VAL:
+ .word 0x3ffffffd
+ACFG4:
+ .word 0x01e00018
+ACFG4_VAL:
+ .word 0x3ffffffd
+ACFG5:
+ .word 0x01e0001c
+ACFG5_VAL:
+ .word 0x3ffffffd
+
+MDCTL_DDR2:
+ .word 0x01c41a34
+MDSTAT_DDR2:
+ .word 0x01c41834
+
+PTCMD:
+ .word 0x01c41120
+PTSTAT:
+ .word 0x01c41128
+
+EINT_ENABLE0:
+ .word 0x01c48018
+EINT_ENABLE1:
+ .word 0x01c4801c
+
+PSC_FLAG_CLEAR:
+ .word 0xffffffe0
+PSC_GEM_FLAG_CLEAR:
+ .word 0xfffffeff
+
+/* DDR2 MMR & CONFIGURATION VALUES, 162 MHZ clock */
+DDRCTL:
+ .word 0x200000e4
+DDRCTL_VAL:
+ .word 0x50006405
+SDREF:
+ .word 0x2000000c
+SDREF_VAL:
+ .word 0x000005c3
+SDCFG:
+ .word 0x20000008
+SDCFG_VAL:
+#ifdef DDR_4BANKS
+ .word 0x00178622
+#elif defined DDR_8BANKS
+ .word 0x00178632
+#else
+#error "Unknown DDR configuration!!!"
+#endif
+SDTIM0:
+ .word 0x20000010
+SDTIM0_VAL_162MHz:
+ .word 0x28923211
+SDTIM1:
+ .word 0x20000014
+SDTIM1_VAL_162MHz:
+ .word 0x0016c722
+VTPIOCR:
+ .word 0x200000f0 /* VTP IO Control register */
+DDRVTPR:
+ .word 0x01c42030 /* DDR VPTR MMR */
+VTP_MMR0:
+ .word 0x201f
+VTP_MMR1:
+ .word 0xa01f
+DFT_ENABLE:
+ .word 0x01c4004c
+VTP_LOCK_COUNT:
+ .word 0x5b0
+VTP_MASK:
+ .word 0xffffdfff
+VTP_RECAL:
+ .word 0x40000
+VTP_EN:
+ .word 0x02000
+CFGTEST:
+ .word 0x80010000
+MASK_VAL:
+ .word 0x00000fff
+
+/* GEM Power Up & LPSC Control Register */
+MDCTL_GEM:
+ .word 0x01c41a9c
+MDSTAT_GEM:
+ .word 0x01c4189c
+
+/* For WDT reset chip bug */
+P1394:
+ .word 0x01c41a20
+
+PLL_CLKSRC_MASK:
+ .word 0xfffffeff /* Mask the Clock Mode bit */
+PLL_ENSRC_MASK:
+ .word 0xffffffdf /* Select the PLLEN source */
+PLL_BYPASS_MASK:
+ .word 0xfffffffe /* Put the PLL in BYPASS */
+PLL_RESET_MASK:
+ .word 0xfffffff7 /* Put the PLL in Reset Mode */
+PLL_PWRUP_MASK:
+ .word 0xfffffffd /* PLL Power up Mask Bit */
+PLL_DISABLE_ENABLE_MASK:
+ .word 0xffffffef /* Enable the PLL from Disable */
+PLL_LOCK_COUNT:
+ .word 0x2000
+
+/* PLL1-SYSTEM PLL MMRs */
+PLL1_CTL:
+ .word 0x01c40900
+PLL1_PLLM:
+ .word 0x01c40910
+
+/* PLL2-SYSTEM PLL MMRs */
+PLL2_CTL:
+ .word 0x01c40d00
+PLL2_PLLM:
+ .word 0x01c40d10
+PLL2_DIV1:
+ .word 0x01c40d18
+PLL2_DIV2:
+ .word 0x01c40d1c
+PLL2_PLLCMD:
+ .word 0x01c40d38
+PLL2_PLLSTAT:
+ .word 0x01c40d3c
+PLL2_DIV_MASK:
+ .word 0xffff7fff
+
+MMARG_BRF0:
+ .word 0x01c42010 /* BRF margin mode 0 (R/W)*/
+MMARG_BRF0_VAL:
+ .word 0x00444400
+
+DDR2_START_ADDR:
+ .word 0x80000000
+DUMMY_VAL:
+ .word 0xa55aa55a
diff --git a/cpu/arm926ejs/davinci/lxt972.c b/cpu/arm926ejs/davinci/lxt972.c
new file mode 100644
index 0000000..6eeb6e5
--- /dev/null
+++ b/cpu/arm926ejs/davinci/lxt972.c
@@ -0,0 +1,142 @@
+/*
+ * Intel LXT971/LXT972 PHY Driver for TI DaVinci
+ * (TMS320DM644x) based boards.
+ *
+ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
+ *
+ * --------------------------------------------------------
+ *
+ * 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 <common.h>
+#include <net.h>
+#include <lxt971a.h>
+#include <asm/arch/emac_defs.h>
+
+#ifdef CONFIG_DRIVER_TI_EMAC
+
+#ifdef CONFIG_CMD_NET
+
+int lxt972_is_phy_connected(int phy_addr)
+{
+ u_int16_t id1, id2;
+
+ if (!dm644x_eth_phy_read(phy_addr, PHY_COMMON_ID1, &id1))
+ return(0);
+ if (!dm644x_eth_phy_read(phy_addr, PHY_COMMON_ID2, &id2))
+ return(0);
+
+ if ((id1 == (0x0013)) && ((id2 & 0xfff0) == 0x78e0))
+ return(1);
+
+ return(0);
+}
+
+int lxt972_get_link_speed(int phy_addr)
+{
+ u_int16_t stat1, tmp;
+ volatile emac_regs* emac = (emac_regs *)EMAC_BASE_ADDR;
+
+ if (!dm644x_eth_phy_read(phy_addr, PHY_LXT971_STAT2, &stat1))
+ return(0);
+
+ if (!(stat1 & PHY_LXT971_STAT2_LINK)) /* link up? */
+ return(0);
+
+ if (!dm644x_eth_phy_read(phy_addr, PHY_LXT971_DIG_CFG, &tmp))
+ return(0);
+
+ tmp |= PHY_LXT971_DIG_CFG_MII_DRIVE;
+
+ dm644x_eth_phy_write(phy_addr, PHY_LXT971_DIG_CFG, tmp);
+ /* Read back */
+ if (!dm644x_eth_phy_read(phy_addr, PHY_LXT971_DIG_CFG, &tmp))
+ return(0);
+
+
+ /* Speed doesn't matter, there is no setting for it in EMAC... */
+ if (stat1 & PHY_LXT971_STAT2_100BTX) {
+ if (stat1 & PHY_LXT971_STAT2_DUPLEX_MODE) {
+ /* set DM644x EMAC for Full Duplex */
+ emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
+ } else {
+ /*set DM644x EMAC for Half Duplex */
+ emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE;
+ }
+
+ return(1);
+ } else {
+ if (stat1 & PHY_LXT971_STAT2_DUPLEX_MODE) {
+ /* set DM644x EMAC for Full Duplex */
+ emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
+ } else {
+ /*set DM644x EMAC for Half Duplex */
+ emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE;
+ }
+
+ return(1);
+ }
+
+ return(0);
+}
+
+
+int lxt972_init_phy(int phy_addr)
+{
+ int ret = 1;
+
+ if (!lxt972_get_link_speed(phy_addr)) {
+ /* Try another time */
+ ret = lxt972_get_link_speed(phy_addr);
+ }
+
+ /* Disable PHY Interrupts */
+ dm644x_eth_phy_write(phy_addr, PHY_LXT971_INT_ENABLE, 0);
+
+ return(ret);
+}
+
+
+int lxt972_auto_negotiate(int phy_addr)
+{
+ u_int16_t tmp;
+
+
+ if (!dm644x_eth_phy_read(phy_addr, PHY_COMMON_CTRL, &tmp))
+ return(0);
+
+ /* Restart Auto_negotiation */
+ tmp |= PHY_COMMON_CTRL_RES_AUTO;
+ dm644x_eth_phy_write(phy_addr, PHY_COMMON_CTRL, tmp);
+
+ /*check AutoNegotiate complete */
+ udelay (10000);
+ if (!dm644x_eth_phy_read(phy_addr, PHY_COMMON_STAT, &tmp))
+ return(0);
+
+ if (!(tmp & PHY_COMMON_STAT_AN_COMP))
+ return(0);
+
+ return (lxt972_get_link_speed(phy_addr));
+}
+
+#endif /* CONFIG_CMD_NET */
+
+#endif /* CONFIG_DRIVER_ETHER */
diff --git a/cpu/arm926ejs/davinci/nand.c b/cpu/arm926ejs/davinci/nand.c
new file mode 100644
index 0000000..127be9f
--- /dev/null
+++ b/cpu/arm926ejs/davinci/nand.c
@@ -0,0 +1,389 @@
+/*
+ * NAND driver for TI DaVinci based boards.
+ *
+ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
+ *
+ * Based on Linux DaVinci NAND driver by TI. Original copyright follows:
+ */
+
+/*
+ *
+ * linux/drivers/mtd/nand/nand_davinci.c
+ *
+ * NAND Flash Driver
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ *
+ * Overview:
+ * This is a device driver for the NAND flash device found on the
+ * DaVinci board which utilizes the Samsung k9k2g08 part.
+ *
+ Modifications:
+ ver. 1.0: Feb 2005, Vinod/Sudhakar
+ -
+ *
+ */
+
+#include <common.h>
+
+#ifdef CFG_USE_NAND
+#if !defined(CFG_NAND_LEGACY)
+
+#include <nand.h>
+#include <asm/arch/nand_defs.h>
+#include <asm/arch/emif_defs.h>
+
+extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
+
+static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd)
+{
+ struct nand_chip *this = mtd->priv;
+ u_int32_t IO_ADDR_W = (u_int32_t)this->IO_ADDR_W;
+
+ IO_ADDR_W &= ~(MASK_ALE|MASK_CLE);
+
+ switch (cmd) {
+ case NAND_CTL_SETCLE:
+ IO_ADDR_W |= MASK_CLE;
+ break;
+ case NAND_CTL_SETALE:
+ IO_ADDR_W |= MASK_ALE;
+ break;
+ }
+
+ this->IO_ADDR_W = (void *)IO_ADDR_W;
+}
+
+/* Set WP on deselect, write enable on select */
+static void nand_davinci_select_chip(struct mtd_info *mtd, int chip)
+{
+#define GPIO_SET_DATA01 0x01c67018
+#define GPIO_CLR_DATA01 0x01c6701c
+#define GPIO_NAND_WP (1 << 4)
+#ifdef SONATA_BOARD_GPIOWP
+ if (chip < 0) {
+ REG(GPIO_CLR_DATA01) |= GPIO_NAND_WP;
+ } else {
+ REG(GPIO_SET_DATA01) |= GPIO_NAND_WP;
+ }
+#endif
+}
+
+#ifdef CFG_NAND_HW_ECC
+#ifdef CFG_NAND_LARGEPAGE
+static struct nand_oobinfo davinci_nand_oobinfo = {
+ .useecc = MTD_NANDECC_AUTOPLACE,
+ .eccbytes = 12,
+ .eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58},
+ .oobfree = { {2, 6}, {12, 12}, {28, 12}, {44, 12}, {60, 4} }
+};
+#elif defined(CFG_NAND_SMALLPAGE)
+static struct nand_oobinfo davinci_nand_oobinfo = {
+ .useecc = MTD_NANDECC_AUTOPLACE,
+ .eccbytes = 3,
+ .eccpos = {0, 1, 2},
+ .oobfree = { {6, 2}, {8, 8} }
+};
+#else
+#error "Either CFG_NAND_LARGEPAGE or CFG_NAND_SMALLPAGE must be defined!"
+#endif
+
+static void nand_davinci_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+ emifregs emif_addr;
+ int dummy;
+
+ emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE;
+
+ dummy = emif_addr->NANDF1ECC;
+ dummy = emif_addr->NANDF2ECC;
+ dummy = emif_addr->NANDF3ECC;
+ dummy = emif_addr->NANDF4ECC;
+
+ emif_addr->NANDFCR |= (1 << 8);
+}
+
+static u_int32_t nand_davinci_readecc(struct mtd_info *mtd, u_int32_t region)
+{
+ u_int32_t ecc = 0;
+ emifregs emif_base_addr;
+
+ emif_base_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE;
+
+ if (region == 1)
+ ecc = emif_base_addr->NANDF1ECC;
+ else if (region == 2)
+ ecc = emif_base_addr->NANDF2ECC;
+ else if (region == 3)
+ ecc = emif_base_addr->NANDF3ECC;
+ else if (region == 4)
+ ecc = emif_base_addr->NANDF4ECC;
+
+ return(ecc);
+}
+
+static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
+{
+ u_int32_t tmp;
+ int region, n;
+ struct nand_chip *this = mtd->priv;
+
+ n = (this->eccmode == NAND_ECC_HW12_2048) ? 4 : 1;
+
+ region = 1;
+ while (n--) {
+ tmp = nand_davinci_readecc(mtd, region);
+ *ecc_code++ = tmp;
+ *ecc_code++ = tmp >> 16;
+ *ecc_code++ = ((tmp >> 8) & 0x0f) | ((tmp >> 20) & 0xf0);
+ region++;
+ }
+ return(0);
+}
+
+static void nand_davinci_gen_true_ecc(u_int8_t *ecc_buf)
+{
+ u_int32_t tmp = ecc_buf[0] | (ecc_buf[1] << 16) | ((ecc_buf[2] & 0xf0) << 20) | ((ecc_buf[2] & 0x0f) << 8);
+
+ ecc_buf[0] = ~(P64o(tmp) | P64e(tmp) | P32o(tmp) | P32e(tmp) | P16o(tmp) | P16e(tmp) | P8o(tmp) | P8e(tmp));
+ ecc_buf[1] = ~(P1024o(tmp) | P1024e(tmp) | P512o(tmp) | P512e(tmp) | P256o(tmp) | P256e(tmp) | P128o(tmp) | P128e(tmp));
+ ecc_buf[2] = ~( P4o(tmp) | P4e(tmp) | P2o(tmp) | P2e(tmp) | P1o(tmp) | P1e(tmp) | P2048o(tmp) | P2048e(tmp));
+}
+
+static int nand_davinci_compare_ecc(u_int8_t *ecc_nand, u_int8_t *ecc_calc, u_int8_t *page_data)
+{
+ u_int32_t i;
+ u_int8_t tmp0_bit[8], tmp1_bit[8], tmp2_bit[8];
+ u_int8_t comp0_bit[8], comp1_bit[8], comp2_bit[8];
+ u_int8_t ecc_bit[24];
+ u_int8_t ecc_sum = 0;
+ u_int8_t find_bit = 0;
+ u_int32_t find_byte = 0;
+ int is_ecc_ff;
+
+ is_ecc_ff = ((*ecc_nand == 0xff) && (*(ecc_nand + 1) == 0xff) && (*(ecc_nand + 2) == 0xff));
+
+ nand_davinci_gen_true_ecc(ecc_nand);
+ nand_davinci_gen_true_ecc(ecc_calc);
+
+ for (i = 0; i <= 2; i++) {
+ *(ecc_nand + i) = ~(*(ecc_nand + i));
+ *(ecc_calc + i) = ~(*(ecc_calc + i));
+ }
+
+ for (i = 0; i < 8; i++) {
+ tmp0_bit[i] = *ecc_nand % 2;
+ *ecc_nand = *ecc_nand / 2;
+ }
+
+ for (i = 0; i < 8; i++) {
+ tmp1_bit[i] = *(ecc_nand + 1) % 2;
+ *(ecc_nand + 1) = *(ecc_nand + 1) / 2;
+ }
+
+ for (i = 0; i < 8; i++) {
+ tmp2_bit[i] = *(ecc_nand + 2) % 2;
+ *(ecc_nand + 2) = *(ecc_nand + 2) / 2;
+ }
+
+ for (i = 0; i < 8; i++) {
+ comp0_bit[i] = *ecc_calc % 2;
+ *ecc_calc = *ecc_calc / 2;
+ }
+
+ for (i = 0; i < 8; i++) {
+ comp1_bit[i] = *(ecc_calc + 1) % 2;
+ *(ecc_calc + 1) = *(ecc_calc + 1) / 2;
+ }
+
+ for (i = 0; i < 8; i++) {
+ comp2_bit[i] = *(ecc_calc + 2) % 2;
+ *(ecc_calc + 2) = *(ecc_calc + 2) / 2;
+ }
+
+ for (i = 0; i< 6; i++)
+ ecc_bit[i] = tmp2_bit[i + 2] ^ comp2_bit[i + 2];
+
+ for (i = 0; i < 8; i++)
+ ecc_bit[i + 6] = tmp0_bit[i] ^ comp0_bit[i];
+
+ for (i = 0; i < 8; i++)
+ ecc_bit[i + 14] = tmp1_bit[i] ^ comp1_bit[i];
+
+ ecc_bit[22] = tmp2_bit[0] ^ comp2_bit[0];
+ ecc_bit[23] = tmp2_bit[1] ^ comp2_bit[1];
+
+ for (i = 0; i < 24; i++)
+ ecc_sum += ecc_bit[i];
+
+ switch (ecc_sum) {
+ case 0:
+ /* Not reached because this function is not called if
+ ECC values are equal */
+ return 0;
+ case 1:
+ /* Uncorrectable error */
+ DEBUG (MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR 1\n");
+ return(-1);
+ case 12:
+ /* Correctable error */
+ find_byte = (ecc_bit[23] << 8) +
+ (ecc_bit[21] << 7) +
+ (ecc_bit[19] << 6) +
+ (ecc_bit[17] << 5) +
+ (ecc_bit[15] << 4) +
+ (ecc_bit[13] << 3) +
+ (ecc_bit[11] << 2) +
+ (ecc_bit[9] << 1) +
+ ecc_bit[7];
+
+ find_bit = (ecc_bit[5] << 2) + (ecc_bit[3] << 1) + ecc_bit[1];
+
+ DEBUG (MTD_DEBUG_LEVEL0, "Correcting single bit ECC error at offset: %d, bit: %d\n", find_byte, find_bit);
+
+ page_data[find_byte] ^= (1 << find_bit);
+
+ return(0);
+ default:
+ if (is_ecc_ff) {
+ if (ecc_calc[0] == 0 && ecc_calc[1] == 0 && ecc_calc[2] == 0)
+ return(0);
+ }
+ DEBUG (MTD_DEBUG_LEVEL0, "UNCORRECTED_ERROR default\n");
+ return(-1);
+ }
+}
+
+static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
+{
+ struct nand_chip *this;
+ int block_count = 0, i, rc;
+
+ this = mtd->priv;
+ block_count = (this->eccmode == NAND_ECC_HW12_2048) ? 4 : 1;
+ for (i = 0; i < block_count; i++) {
+ if (memcmp(read_ecc, calc_ecc, 3) != 0) {
+ rc = nand_davinci_compare_ecc(read_ecc, calc_ecc, dat);
+ if (rc < 0) {
+ return(rc);
+ }
+ }
+ read_ecc += 3;
+ calc_ecc += 3;
+ dat += 512;
+ }
+ return(0);
+}
+#endif
+
+static int nand_davinci_dev_ready(struct mtd_info *mtd)
+{
+ emifregs emif_addr;
+
+ emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE;
+
+ return(emif_addr->NANDFSR & 0x1);
+}
+
+static int nand_davinci_waitfunc(struct mtd_info *mtd, struct nand_chip *this, int state)
+{
+ while(!nand_davinci_dev_ready(mtd)) {;}
+ *NAND_CE0CLE = NAND_STATUS;
+ return(*NAND_CE0DATA);
+}
+
+static void nand_flash_init(void)
+{
+ u_int32_t acfg1 = 0x3ffffffc;
+ u_int32_t acfg2 = 0x3ffffffc;
+ u_int32_t acfg3 = 0x3ffffffc;
+ u_int32_t acfg4 = 0x3ffffffc;
+ emifregs emif_regs;
+
+ /*------------------------------------------------------------------*
+ * NAND FLASH CHIP TIMEOUT @ 459 MHz *
+ * *
+ * AEMIF.CLK freq = PLL1/6 = 459/6 = 76.5 MHz *
+ * AEMIF.CLK period = 1/76.5 MHz = 13.1 ns *
+ * *
+ *------------------------------------------------------------------*/
+ acfg1 = 0
+ | (0 << 31 ) /* selectStrobe */
+ | (0 << 30 ) /* extWait */
+ | (1 << 26 ) /* writeSetup 10 ns */
+ | (3 << 20 ) /* writeStrobe 40 ns */
+ | (1 << 17 ) /* writeHold 10 ns */
+ | (1 << 13 ) /* readSetup 10 ns */
+ | (5 << 7 ) /* readStrobe 60 ns */
+ | (1 << 4 ) /* readHold 10 ns */
+ | (3 << 2 ) /* turnAround ?? ns */
+ | (0 << 0 ) /* asyncSize 8-bit bus */
+ ;
+
+ emif_regs = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE;
+
+ emif_regs->AWCCR |= 0x10000000;
+ emif_regs->AB1CR = acfg1; /* 0x08244128 */;
+ emif_regs->AB2CR = acfg2;
+ emif_regs->AB3CR = acfg3;
+ emif_regs->AB4CR = acfg4;
+ emif_regs->NANDFCR = 0x00000101;
+}
+
+int board_nand_init(struct nand_chip *nand)
+{
+ nand->IO_ADDR_R = (void __iomem *)NAND_CE0DATA;
+ nand->IO_ADDR_W = (void __iomem *)NAND_CE0DATA;
+ nand->chip_delay = 0;
+ nand->select_chip = nand_davinci_select_chip;
+#ifdef CFG_NAND_USE_FLASH_BBT
+ nand->options = NAND_USE_FLASH_BBT;
+#endif
+#ifdef CFG_NAND_HW_ECC
+#ifdef CFG_NAND_LARGEPAGE
+ nand->eccmode = NAND_ECC_HW12_2048;
+#elif defined(CFG_NAND_SMALLPAGE)
+ nand->eccmode = NAND_ECC_HW3_512;
+#else
+#error "Either CFG_NAND_LARGEPAGE or CFG_NAND_SMALLPAGE must be defined!"
+#endif
+ nand->autooob = &davinci_nand_oobinfo;
+ nand->calculate_ecc = nand_davinci_calculate_ecc;
+ nand->correct_data = nand_davinci_correct_data;
+ nand->enable_hwecc = nand_davinci_enable_hwecc;
+#else
+ nand->eccmode = NAND_ECC_SOFT;
+#endif
+
+ /* Set address of hardware control function */
+ nand->hwcontrol = nand_davinci_hwcontrol;
+
+ nand->dev_ready = nand_davinci_dev_ready;
+ nand->waitfunc = nand_davinci_waitfunc;
+
+ nand_flash_init();
+
+ return(0);
+}
+
+#else
+#error "U-Boot legacy NAND support not available for DaVinci chips"
+#endif
+#endif /* CFG_USE_NAND */
diff --git a/cpu/arm926ejs/davinci/reset.S b/cpu/arm926ejs/davinci/reset.S
new file mode 100644
index 0000000..a687d44
--- /dev/null
+++ b/cpu/arm926ejs/davinci/reset.S
@@ -0,0 +1,77 @@
+/*
+ * Processor reset using WDT for TI TMS320DM644x SoC.
+ *
+ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
+ *
+ * -----------------------------------------------------
+ *
+ * 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
+ */
+
+.globl reset_cpu
+reset_cpu:
+ ldr r0, WDT_TGCR
+ mov r1, $0x08
+ str r1, [r0]
+ ldr r1, [r0]
+ orr r1, r1, $0x03
+ str r1, [r0]
+ mov r1, $0
+ ldr r0, WDT_TIM12
+ str r1, [r0]
+ ldr r0, WDT_TIM34
+ str r1, [r0]
+ ldr r0, WDT_PRD12
+ str r1, [r0]
+ ldr r0, WDT_PRD34
+ str r1, [r0]
+ ldr r0, WDT_TCR
+ ldr r1, [r0]
+ orr r1, r1, $0x40
+ str r1, [r0]
+ ldr r0, WDT_WDTCR
+ ldr r1, [r0]
+ orr r1, r1, $0x4000
+ str r1, [r0]
+ ldr r1, WDTCR_VAL1
+ str r1, [r0]
+ ldr r1, WDTCR_VAL2
+ str r1, [r0]
+ nop
+ nop
+ nop
+ nop
+reset_cpu_loop:
+ b reset_cpu_loop
+
+WDT_TGCR:
+ .word 0x01c21c24
+WDT_TIM12:
+ .word 0x01c21c10
+WDT_TIM34:
+ .word 0x01c21c14
+WDT_PRD12:
+ .word 0x01c21c18
+WDT_PRD34:
+ .word 0x01c21c1c
+WDT_TCR:
+ .word 0x01c21c20
+WDT_WDTCR:
+ .word 0x01c21c28
+WDTCR_VAL1:
+ .word 0xa5c64000
+WDTCR_VAL2:
+ .word 0xda7e4000
diff --git a/cpu/arm926ejs/davinci/timer.c b/cpu/arm926ejs/davinci/timer.c
new file mode 100644
index 0000000..c6b1dda
--- /dev/null
+++ b/cpu/arm926ejs/davinci/timer.c
@@ -0,0 +1,165 @@
+/*
+ * (C) Copyright 2003
+ * Texas Instruments <www.ti.com>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * (C) Copyright 2002-2004
+ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+ *
+ * (C) Copyright 2004
+ * Philippe Robin, ARM Ltd. <philippe.robin@arm.com>
+ *
+ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
+ *
+ * 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 <common.h>
+#include <arm926ejs.h>
+
+typedef volatile struct {
+ u_int32_t pid12;
+ u_int32_t emumgt_clksped;
+ u_int32_t gpint_en;
+ u_int32_t gpdir_dat;
+ u_int32_t tim12;
+ u_int32_t tim34;
+ u_int32_t prd12;
+ u_int32_t prd34;
+ u_int32_t tcr;
+ u_int32_t tgcr;
+ u_int32_t wdtcr;
+ u_int32_t tlgc;
+ u_int32_t tlmr;
+} davinci_timer;
+
+davinci_timer *timer = (davinci_timer *)CFG_TIMERBASE;
+
+#define TIMER_LOAD_VAL (CFG_HZ_CLOCK / CFG_HZ)
+#define READ_TIMER timer->tim34
+
+static ulong timestamp;
+static ulong lastinc;
+
+int timer_init(void)
+{
+ /* We are using timer34 in unchained 32-bit mode, full speed */
+ timer->tcr = 0x0;
+ timer->tgcr = 0x0;
+ timer->tgcr = 0x06;
+ timer->tim34 = 0x0;
+ timer->prd34 = TIMER_LOAD_VAL;
+ lastinc = 0;
+ timer->tcr = 0x80 << 16;
+ timestamp = 0;
+
+ return(0);
+}
+
+void reset_timer(void)
+{
+ reset_timer_masked();
+}
+
+ulong get_timer(ulong base)
+{
+ return(get_timer_masked() - base);
+}
+
+void set_timer(ulong t)
+{
+ timestamp = t;
+}
+
+void udelay(unsigned long usec)
+{
+ udelay_masked(usec);
+}
+
+void reset_timer_masked(void)
+{
+ lastinc = READ_TIMER;
+ timestamp = 0;
+}
+
+ulong get_timer_raw(void)
+{
+ ulong now = READ_TIMER;
+
+ if (now >= lastinc) {
+ /* normal mode */
+ timestamp += now - lastinc;
+ } else {
+ /* overflow ... */
+ timestamp += now + TIMER_LOAD_VAL - lastinc;
+ }
+ lastinc = now;
+ return timestamp;
+}
+
+ulong get_timer_masked(void)
+{
+ return(get_timer_raw() / TIMER_LOAD_VAL);
+}
+
+void udelay_masked(unsigned long usec)
+{
+ ulong tmo;
+ ulong endtime;
+ signed long diff;
+
+ tmo = CFG_HZ_CLOCK / 1000;
+ tmo *= usec;
+ tmo /= 1000;
+
+ endtime = get_timer_raw() + tmo;
+
+ do {
+ ulong now = get_timer_raw();
+ diff = endtime - now;
+ } while (diff >= 0);
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On ARM it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+ return(get_timer(0));
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+ulong get_tbclk(void)
+{
+ ulong tbclk;
+
+ tbclk = CFG_HZ;
+ return(tbclk);
+}
diff --git a/cpu/at32ap/atmel_mci.c b/cpu/at32ap/atmel_mci.c
index 9f62c0f..cf48be1 100644
--- a/cpu/at32ap/atmel_mci.c
+++ b/cpu/at32ap/atmel_mci.c
@@ -56,6 +56,7 @@
#define MMC_DEFAULT_RCA 1
static unsigned int mmc_rca;
+static int mmc_card_is_sd;
static block_dev_desc_t mmc_blkdev;
block_dev_desc_t *mmc_get_dev(int dev)
@@ -82,7 +83,9 @@ static void mci_set_mode(unsigned long hz, unsigned long blklen)
blklen &= 0xfffc;
mmci_writel(MR, (MMCI_BF(CLKDIV, clkdiv)
- | MMCI_BF(BLKLEN, blklen)));
+ | MMCI_BF(BLKLEN, blklen)
+ | MMCI_BIT(RDPROOF)
+ | MMCI_BIT(WRPROOF)));
}
#define RESP_NO_CRC 1
@@ -225,7 +228,7 @@ mmc_bread(int dev, unsigned long start, lbaint_t blkcnt,
*buffer++ = data;
wordcount++;
}
- } while(wordcount < (512 / 4));
+ } while(wordcount < (mmc_blkdev.blksz / 4));
pr_debug("mmc: read %u words, waiting for BLKE\n", wordcount);
@@ -243,7 +246,7 @@ out:
fail:
mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, R1 | NCR);
- printf("mmc: bread failed, card status = ", card_status);
+ printf("mmc: bread failed, card status = %08x\n", card_status);
goto out;
}
@@ -371,6 +374,7 @@ static int sd_init_card(struct mmc_cid *cid, int verbose)
mmc_rca = resp[0] >> 16;
if (verbose)
printf("SD Card detected (RCA %u)\n", mmc_rca);
+ mmc_card_is_sd = 1;
return 0;
}
@@ -405,10 +409,64 @@ static int mmc_init_card(struct mmc_cid *cid, int verbose)
return ret;
}
+static void mci_set_data_timeout(struct mmc_csd *csd)
+{
+ static const unsigned int dtomul_to_shift[] = {
+ 0, 4, 7, 8, 10, 12, 16, 20,
+ };
+ static const unsigned int taac_exp[] = {
+ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
+ };
+ static const unsigned int taac_mant[] = {
+ 0, 10, 12, 13, 15, 60, 25, 30,
+ 35, 40, 45, 50, 55, 60, 70, 80,
+ };
+ unsigned int timeout_ns, timeout_clks;
+ unsigned int e, m;
+ unsigned int dtocyc, dtomul;
+ unsigned int shift;
+ u32 dtor;
+
+ e = csd->taac & 0x07;
+ m = (csd->taac >> 3) & 0x0f;
+
+ timeout_ns = (taac_exp[e] * taac_mant[m] + 9) / 10;
+ timeout_clks = csd->nsac * 100;
+
+ timeout_clks += (((timeout_ns + 9) / 10)
+ * ((CFG_MMC_CLK_PP + 99999) / 100000) + 9999) / 10000;
+ if (!mmc_card_is_sd)
+ timeout_clks *= 10;
+ else
+ timeout_clks *= 100;
+
+ dtocyc = timeout_clks;
+ dtomul = 0;
+ while (dtocyc > 15 && dtomul < 8) {
+ dtomul++;
+ shift = dtomul_to_shift[dtomul];
+ dtocyc = (timeout_clks + (1 << shift) - 1) >> shift;
+ }
+
+ if (dtomul >= 8) {
+ dtomul = 7;
+ dtocyc = 15;
+ puts("Warning: Using maximum data timeout\n");
+ }
+
+ dtor = (MMCI_BF(DTOMUL, dtomul)
+ | MMCI_BF(DTOCYC, dtocyc));
+ mmci_writel(DTOR, dtor);
+
+ printf("mmc: Using %u cycles data timeout (DTOR=0x%x)\n",
+ dtocyc << shift, dtor);
+}
+
int mmc_init(int verbose)
{
struct mmc_cid cid;
struct mmc_csd csd;
+ unsigned int max_blksz;
int ret;
/* Initialize controller */
@@ -418,6 +476,8 @@ int mmc_init(int verbose)
mmci_writel(IDR, ~0UL);
mci_set_mode(CFG_MMC_CLK_OD, MMC_DEFAULT_BLKLEN);
+ mmc_card_is_sd = 0;
+
ret = sd_init_card(&cid, verbose);
if (ret) {
mmc_rca = MMC_DEFAULT_RCA;
@@ -433,6 +493,8 @@ int mmc_init(int verbose)
if (verbose)
mmc_dump_csd(&csd);
+ mci_set_data_timeout(&csd);
+
/* Initialize the blockdev structure */
mmc_blkdev.if_type = IF_TYPE_MMC;
mmc_blkdev.part_type = PART_TYPE_DOS;
@@ -444,7 +506,17 @@ int mmc_init(int verbose)
sizeof(mmc_blkdev.product));
sprintf((char *)mmc_blkdev.revision, "%x %x",
cid.prv >> 4, cid.prv & 0x0f);
- mmc_blkdev.blksz = 1 << csd.read_bl_len;
+
+ /*
+ * If we can't use 512 byte blocks, refuse to deal with the
+ * card. Tons of code elsewhere seems to depend on this.
+ */
+ max_blksz = 1 << csd.read_bl_len;
+ if (max_blksz < 512 || (max_blksz > 512 && !csd.read_bl_partial)) {
+ printf("Card does not support 512 byte reads, aborting.\n");
+ return -ENODEV;
+ }
+ mmc_blkdev.blksz = 512;
mmc_blkdev.lba = (csd.c_size + 1) * (1 << (csd.c_size_mult + 2));
mci_set_mode(CFG_MMC_CLK_PP, mmc_blkdev.blksz);
diff --git a/cpu/at32ap/atmel_mci.h b/cpu/at32ap/atmel_mci.h
index 0ffbc4f..5b4f5c9 100644
--- a/cpu/at32ap/atmel_mci.h
+++ b/cpu/at32ap/atmel_mci.h
@@ -57,6 +57,10 @@
#define MMCI_CLKDIV_SIZE 8
#define MMCI_PWSDIV_OFFSET 8
#define MMCI_PWSDIV_SIZE 3
+#define MMCI_RDPROOF_OFFSET 11
+#define MMCI_RDPROOF_SIZE 1
+#define MMCI_WRPROOF_OFFSET 12
+#define MMCI_WRPROOF_SIZE 1
#define MMCI_PDCPADV_OFFSET 14
#define MMCI_PDCPADV_SIZE 1
#define MMCI_PDCMODE_OFFSET 15
diff --git a/cpu/at32ap/interrupts.c b/cpu/at32ap/interrupts.c
index c9e0499..bef1f30 100644
--- a/cpu/at32ap/interrupts.c
+++ b/cpu/at32ap/interrupts.c
@@ -20,8 +20,8 @@
* MA 02111-1307 USA
*/
#include <common.h>
+#include <div64.h>
-#include <asm/div64.h>
#include <asm/errno.h>
#include <asm/io.h>
#include <asm/processor.h>
diff --git a/cpu/i386/serial.c b/cpu/i386/serial.c
index e7299a7..baf35e5 100644
--- a/cpu/i386/serial.c
+++ b/cpu/i386/serial.c
@@ -394,7 +394,7 @@ int serial_buffered_tstc(void)
#endif /* CONFIG_SERIAL_SOFTWARE_FIFO */
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
/*
AS HARNOIS : according to CONFIG_KGDB_SER_INDEX kgdb uses serial port
number 0 or number 1
@@ -500,4 +500,4 @@ void kgdb_interruptible(int yes)
return;
}
#endif /* (CONFIG_KGDB_SER_INDEX & 2) */
-#endif /* CFG_CMD_KGDB */
+#endif
diff --git a/cpu/ixp/cpu.c b/cpu/ixp/cpu.c
index 7f9f334..2c7d5a0 100644
--- a/cpu/ixp/cpu.c
+++ b/cpu/ixp/cpu.c
@@ -85,7 +85,7 @@ int cpu_init (void)
FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ;
#endif
-#if (CONFIG_COMMANDS & CFG_CMD_PCI) || defined (CONFIG_PCI)
+#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)
pci_init();
#endif
return 0;
diff --git a/cpu/ixp/npe/npe.c b/cpu/ixp/npe/npe.c
index ab7ca8b..7e4af44 100644
--- a/cpu/ixp/npe/npe.c
+++ b/cpu/ixp/npe/npe.c
@@ -682,7 +682,7 @@ int npe_initialize(bd_t * bis)
eth_register(dev);
-#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
miiphy_register(dev->name, npe_miiphy_read, npe_miiphy_write);
#endif
diff --git a/cpu/mcf52x2/fec.c b/cpu/mcf52x2/fec.c
index b6540b5..ef9c798 100644
--- a/cpu/mcf52x2/fec.c
+++ b/cpu/mcf52x2/fec.c
@@ -53,7 +53,7 @@
#undef ET_DEBUG
#undef MII_DEBUG
-#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(FEC_ENET)
+#if defined(CONFIG_CMD_NET) && defined(FEC_ENET)
#ifdef CFG_DISCOVER_PHY
#include <miiphy.h>
@@ -363,7 +363,7 @@ void eth_halt (void)
}
-#if defined(CFG_DISCOVER_PHY) || (CONFIG_COMMANDS & CFG_CMD_MII)
+#if defined(CFG_DISCOVER_PHY) || defined(CONFIG_CMD_MII)
static int phyaddr = -1; /* didn't find a PHY yet */
static uint phytype;
@@ -419,7 +419,7 @@ static uint mii_send (uint mii_cmd)
#endif
return (mii_reply & 0xffff); /* data read from phy */
}
-#endif /* CFG_DISCOVER_PHY || (CONFIG_COMMANDS & CFG_CMD_MII) */
+#endif
#if defined(CFG_DISCOVER_PHY)
static void mii_discover_phy (void)
@@ -485,7 +485,7 @@ static void mii_discover_phy (void)
}
#endif /* CFG_DISCOVER_PHY */
-#if (CONFIG_COMMANDS & CFG_CMD_MII) && !defined(CONFIG_BITBANGMII)
+#if defined(CONFIG_CMD_MII) && !defined(CONFIG_BITBANGMII)
static int mii_init_done = 0;
@@ -591,13 +591,13 @@ int mcf52x2_miiphy_write (char *devname, unsigned char addr,
return 0;
}
-#endif /* (CONFIG_COMMANDS & CFG_CMD_MII) && !defined(CONFIG_BITBANGMII) */
-#endif /* CFG_CMD_NET, FEC_ENET */
+#endif
+#endif
int mcf52x2_miiphy_initialize(bd_t *bis)
{
-#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(FEC_ENET)
-#if (CONFIG_COMMANDS & CFG_CMD_MII) && !defined(CONFIG_BITBANGMII)
+#if defined(CONFIG_CMD_NET) && defined(FEC_ENET)
+#if defined(CONFIG_CMD_MII) && !defined(CONFIG_BITBANGMII)
miiphy_register("mcf52x2phy", mcf52x2_miiphy_read, mcf52x2_miiphy_write);
#endif
#endif
diff --git a/cpu/microblaze/cache.c b/cpu/microblaze/cache.c
index 4f36a84..6ce0b55 100755..100644
--- a/cpu/microblaze/cache.c
+++ b/cpu/microblaze/cache.c
@@ -25,7 +25,7 @@
#include <common.h>
#include <asm/asm.h>
-#if (CONFIG_COMMANDS & CFG_CMD_CACHE)
+#if defined(CONFIG_CMD_CACHE)
int dcache_status (void)
{
diff --git a/cpu/microblaze/interrupts.c b/cpu/microblaze/interrupts.c
index b61153f..3f04b29 100755..100644
--- a/cpu/microblaze/interrupts.c
+++ b/cpu/microblaze/interrupts.c
@@ -190,7 +190,7 @@ void interrupt_handler (void)
}
#endif
-#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
+#if defined(CONFIG_CMD_IRQ)
#ifdef CFG_INTC_0
int do_irqinfo (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
@@ -217,4 +217,4 @@ int do_irqinfo (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
puts ("Undefined interrupt controller\n");
}
#endif
-#endif /* CONFIG_COMMANDS & CFG_CMD_IRQ */
+#endif
diff --git a/cpu/microblaze/irq.S b/cpu/microblaze/irq.S
index e1fc190..e1fc190 100755..100644
--- a/cpu/microblaze/irq.S
+++ b/cpu/microblaze/irq.S
diff --git a/cpu/mips/au1x00_eth.c b/cpu/mips/au1x00_eth.c
index 078e832..b69741a 100644
--- a/cpu/mips/au1x00_eth.c
+++ b/cpu/mips/au1x00_eth.c
@@ -63,7 +63,7 @@
#include <asm/io.h>
#include <asm/au1x00.h>
-#if (CONFIG_COMMANDS & CFG_CMD_MII)
+#if defined(CONFIG_CMD_MII)
#include <miiphy.h>
#endif
@@ -241,7 +241,7 @@ int au1x00_enet_initialize(bd_t *bis){
eth_register(dev);
-#if (CONFIG_COMMANDS & CFG_CMD_MII)
+#if defined(CONFIG_CMD_MII)
miiphy_register(dev->name,
au1x00_miiphy_read, au1x00_miiphy_write);
#endif
@@ -249,7 +249,7 @@ int au1x00_enet_initialize(bd_t *bis){
return 1;
}
-#if (CONFIG_COMMANDS & CFG_CMD_MII)
+#if defined(CONFIG_CMD_MII)
int au1x00_miiphy_read(char *devname, unsigned char addr,
unsigned char reg, unsigned short * value)
{
@@ -306,6 +306,6 @@ int au1x00_miiphy_write(char *devname, unsigned char addr,
*mii_control_reg = mii_control;
return 0;
}
-#endif /* CONFIG_COMMANDS & CFG_CMD_MII */
+#endif
#endif /* CONFIG_AU1X00 */
diff --git a/cpu/mpc512x/Makefile b/cpu/mpc512x/Makefile
new file mode 100644
index 0000000..2be35b2
--- /dev/null
+++ b/cpu/mpc512x/Makefile
@@ -0,0 +1,46 @@
+#
+# (C) Copyright 2007 DENX Software Engineering
+#
+# 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 = $(obj)lib$(CPU).a
+
+START = start.o
+COBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o serial.o fec.o i2c.o
+
+SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
+START := $(addprefix $(obj),$(START))
+
+all: $(obj).depend $(START) $(LIB)
+
+$(LIB): $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/cpu/mpc512x/config.mk b/cpu/mpc512x/config.mk
new file mode 100644
index 0000000..8a07c5a
--- /dev/null
+++ b/cpu/mpc512x/config.mk
@@ -0,0 +1,25 @@
+#
+# (C) Copyright 2007 DENX Software Engineering
+#
+# 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_MPC512X -DCONFIG_E300 \
+ -ffixed-r2 -ffixed-r29 -msoft-float -mcpu=603e
diff --git a/cpu/mpc512x/cpu.c b/cpu/mpc512x/cpu.c
new file mode 100644
index 0000000..accae6e
--- /dev/null
+++ b/cpu/mpc512x/cpu.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2004-2006 Freescale Semiconductor, Inc.
+ * (C) Copyright 2007 DENX Software Engineering
+ *
+ * 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
+ */
+
+/*
+ * CPU specific code for the MPC512x family.
+ *
+ * Derived from the MPC83xx code.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <mpc512x.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int checkcpu (void)
+{
+ volatile immap_t *immr = (immap_t *) CFG_IMMR;
+ ulong clock = gd->cpu_clk;
+ u32 pvr = get_pvr ();
+ u32 spridr = immr->sysconf.spridr;
+ char buf[32];
+
+ puts ("CPU: ");
+
+ switch (spridr & 0xffff0000) {
+ case SPR_5121E:
+ puts ("MPC5121e ");
+ break;
+ default:
+ printf ("Unknown part ID %08x ", spridr & 0xffff0000);
+ }
+ printf ("rev. %d.%d, Core ", SVR_MJREV (spridr), SVR_MNREV (spridr));
+
+ switch (pvr & 0xffff0000) {
+ case PVR_E300C4:
+ puts ("e300c4 ");
+ break;
+ default:
+ puts ("unknown ");
+ }
+ printf ("at %s MHz, CSB at %3d MHz\n", strmhz(buf, clock),
+ gd->csb_clk / 1000000);
+ return 0;
+}
+
+
+int
+do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+ ulong msr;
+ volatile immap_t *immap = (immap_t *) CFG_IMMR;
+
+ /* 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 - "RSTE" is the magic word that let us go
+ */
+ immap->reset.rpr = 0x52535445;
+
+ /* Verify Reset Control Reg is enabled */
+ while (!((immap->reset.rcer) & RCER_CRE))
+ ;
+
+ printf ("Resetting the board.\n");
+ udelay(200);
+
+ /* Perform reset */
+ immap->reset.rcr = RCR_SWHR;
+
+ /* Unreached... */
+ return 1;
+}
+
+
+/*
+ * Get timebase clock frequency (like cpu_clk in Hz)
+ */
+unsigned long get_tbclk (void)
+{
+ ulong tbclk;
+
+ tbclk = (gd->bus_clk + 3L) / 4L;
+
+ return tbclk;
+}
+
+
+#if defined(CONFIG_WATCHDOG)
+void watchdog_reset (void)
+{
+ int re_enable = disable_interrupts ();
+
+ /* Reset watchdog */
+ volatile immap_t *immr = (immap_t *) CFG_IMMR;
+ immr->wdt.swsrr = 0x556c;
+ immr->wdt.swsrr = 0xaa39;
+
+ if (re_enable)
+ enable_interrupts ();
+}
+#endif
diff --git a/cpu/mpc512x/cpu_init.c b/cpu/mpc512x/cpu_init.c
new file mode 100644
index 0000000..d6949f6
--- /dev/null
+++ b/cpu/mpc512x/cpu_init.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2004-2006 Freescale Semiconductor, Inc.
+ * (C) Copyright 2007 DENX Software Engineering
+ *
+ * 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
+ *
+ * Derived from the MPC83xx code.
+ *
+ */
+
+#include <common.h>
+#include <mpc512x.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Set up the memory map, initialize registers,
+ */
+void cpu_init_f (volatile immap_t * im)
+{
+ u32 ips_div;
+
+ /* 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));
+
+ /* system performance tweaking */
+
+#ifdef CFG_ACR_PIPE_DEP
+ /* Arbiter pipeline depth */
+ im->arbiter.acr = (im->arbiter.acr & ~ACR_PIPE_DEP) |
+ (CFG_ACR_PIPE_DEP << ACR_PIPE_DEP_SHIFT);
+#endif
+
+#ifdef CFG_ACR_RPTCNT
+ /* Arbiter repeat count */
+ im->arbiter.acr = ((im->arbiter.acr & ~(ACR_RPTCNT)) |
+ (CFG_ACR_RPTCNT << ACR_RPTCNT_SHIFT));
+#endif
+
+ /* RSR - Reset Status Register - clear all status */
+ gd->reset_status = im->reset.rsr;
+ im->reset.rsr = ~(RSR_RES);
+
+ /*
+ * RMR - Reset Mode Register - enable checkstop reset
+ */
+ im->reset.rmr = (RMR_CSRE & (1 << RMR_CSRE_SHIFT));
+
+ /* Set IPS-CSB divider: IPS = 1/2 CSB */
+ ips_div = im->clk.scfr[0];
+ ips_div &= ~(SCFR1_IPS_DIV_MASK);
+ ips_div |= SCFR1_IPS_DIV << SCFR1_IPS_DIV_SHIFT;
+ im->clk.scfr[0] = ips_div;
+
+ /*
+ * Enable Time Base/Decrementer
+ *
+ * NOTICE: TB needs to be enabled as early as possible in order to
+ * have udelay() working; if not enabled, usually leads to a hang, like
+ * during FLASH chip identification etc.
+ */
+ im->sysconf.spcr |= SPCR_TBEN;
+}
+
+int cpu_init_r (void)
+{
+ return 0;
+}
diff --git a/cpu/mpc512x/fec.c b/cpu/mpc512x/fec.c
new file mode 100644
index 0000000..3c142a9
--- /dev/null
+++ b/cpu/mpc512x/fec.c
@@ -0,0 +1,801 @@
+/*
+ * (C) Copyright 2003-2007
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Derived from the MPC8xx FEC driver.
+ * Adapted for MPC512x by Grzegorz Bernacki <gjb@semihalf.com>
+ */
+
+#include <common.h>
+#include <mpc512x.h>
+#include <malloc.h>
+#include <net.h>
+#include <miiphy.h>
+#include "fec.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define DEBUG 0
+
+#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
+ defined(CONFIG_MPC512x_FEC)
+
+#if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
+#error "CONFIG_MII has to be defined!"
+#endif
+
+#if (DEBUG & 0x40)
+static uint32 local_crc32(char *string, unsigned int crc_value, int len);
+#endif
+
+int fec512x_miiphy_read(char *devname, uint8 phyAddr, uint8 regAddr, uint16 * retVal);
+int fec512x_miiphy_write(char *devname, uint8 phyAddr, uint8 regAddr, uint16 data);
+int mpc512x_fec_init_phy(struct eth_device *dev, bd_t * bis);
+
+/********************************************************************/
+#if (DEBUG & 0x2)
+static void mpc512x_fec_phydump (char *devname)
+{
+ uint16 phyStatus, i;
+ uint8 phyAddr = CONFIG_PHY_ADDR;
+ uint8 reg_mask[] = {
+ /* regs to print: 0...8, 21,27,31 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1,
+ };
+
+ for (i = 0; i < 32; i++) {
+ if (reg_mask[i]) {
+ miiphy_read (devname, phyAddr, i, &phyStatus);
+ printf ("Mii reg %d: 0x%04x\n", i, phyStatus);
+ }
+ }
+}
+#endif
+
+/********************************************************************/
+static int mpc512x_fec_bd_init (mpc512x_fec_priv *fec)
+{
+ int ix;
+
+ /*
+ * Receive BDs init
+ */
+ for (ix = 0; ix < FEC_RBD_NUM; ix++) {
+ fec->bdBase->rbd[ix].dataPointer = (uint32)&fec->bdBase->recv_frames[ix];
+ fec->bdBase->rbd[ix].status = FEC_RBD_EMPTY;
+ fec->bdBase->rbd[ix].dataLength = 0;
+ }
+
+ /*
+ * have the last RBD to close the ring
+ */
+ fec->bdBase->rbd[ix - 1].status |= FEC_RBD_WRAP;
+ fec->rbdIndex = 0;
+
+ /*
+ * Trasmit BDs init
+ */
+ for (ix = 0; ix < FEC_TBD_NUM; ix++) {
+ fec->bdBase->tbd[ix].status = 0;
+ }
+
+ /*
+ * Have the last TBD to close the ring
+ */
+ fec->bdBase->tbd[ix - 1].status |= FEC_TBD_WRAP;
+
+ /*
+ * Initialize some indices
+ */
+ fec->tbdIndex = 0;
+ fec->usedTbdIndex = 0;
+ fec->cleanTbdNum = FEC_TBD_NUM;
+
+ return 0;
+}
+
+/********************************************************************/
+static void mpc512x_fec_rbd_clean (mpc512x_fec_priv *fec, volatile FEC_RBD * pRbd)
+{
+ /*
+ * Reset buffer descriptor as empty
+ */
+ if ((fec->rbdIndex) == (FEC_RBD_NUM - 1))
+ pRbd->status = (FEC_RBD_WRAP | FEC_RBD_EMPTY);
+ else
+ pRbd->status = FEC_RBD_EMPTY;
+
+ pRbd->dataLength = 0;
+
+ /*
+ * Increment BD count
+ */
+ fec->rbdIndex = (fec->rbdIndex + 1) % FEC_RBD_NUM;
+
+ /*
+ * Now, we have an empty RxBD, notify FEC
+ */
+ fec->eth->r_des_active = 0x01000000; /* Descriptor polling active */
+}
+
+/********************************************************************/
+static void mpc512x_fec_tbd_scrub (mpc512x_fec_priv *fec)
+{
+ volatile FEC_TBD *pUsedTbd;
+
+#if (DEBUG & 0x1)
+ printf ("tbd_scrub: fec->cleanTbdNum = %d, fec->usedTbdIndex = %d\n",
+ fec->cleanTbdNum, fec->usedTbdIndex);
+#endif
+
+ /*
+ * process all the consumed TBDs
+ */
+ while (fec->cleanTbdNum < FEC_TBD_NUM) {
+ pUsedTbd = &fec->bdBase->tbd[fec->usedTbdIndex];
+ if (pUsedTbd->status & FEC_TBD_READY) {
+#if (DEBUG & 0x20)
+ printf ("Cannot clean TBD %d, in use\n", fec->usedTbdIndex);
+#endif
+ return;
+ }
+
+ /*
+ * clean this buffer descriptor
+ */
+ if (fec->usedTbdIndex == (FEC_TBD_NUM - 1))
+ pUsedTbd->status = FEC_TBD_WRAP;
+ else
+ pUsedTbd->status = 0;
+
+ /*
+ * update some indeces for a correct handling of the TBD ring
+ */
+ fec->cleanTbdNum++;
+ fec->usedTbdIndex = (fec->usedTbdIndex + 1) % FEC_TBD_NUM;
+ }
+}
+
+/********************************************************************/
+static void mpc512x_fec_set_hwaddr (mpc512x_fec_priv *fec, char *mac)
+{
+ uint8 currByte; /* byte for which to compute the CRC */
+ int byte; /* loop - counter */
+ int bit; /* loop - counter */
+ uint32 crc = 0xffffffff; /* initial value */
+
+ /*
+ * The algorithm used is the following:
+ * we loop on each of the six bytes of the provided address,
+ * and we compute the CRC by left-shifting the previous
+ * value by one position, so that each bit in the current
+ * byte of the address may contribute the calculation. If
+ * the latter and the MSB in the CRC are different, then
+ * the CRC value so computed is also ex-ored with the
+ * "polynomium generator". The current byte of the address
+ * is also shifted right by one bit at each iteration.
+ * This is because the CRC generatore in hardware is implemented
+ * as a shift-register with as many ex-ores as the radixes
+ * in the polynomium. This suggests that we represent the
+ * polynomiumm itself as a 32-bit constant.
+ */
+ for (byte = 0; byte < 6; byte++) {
+ currByte = mac[byte];
+ for (bit = 0; bit < 8; bit++) {
+ if ((currByte & 0x01) ^ (crc & 0x01)) {
+ crc >>= 1;
+ crc = crc ^ 0xedb88320;
+ } else {
+ crc >>= 1;
+ }
+ currByte >>= 1;
+ }
+ }
+
+ crc = crc >> 26;
+
+ /*
+ * Set individual hash table register
+ */
+ if (crc >= 32) {
+ fec->eth->iaddr1 = (1 << (crc - 32));
+ fec->eth->iaddr2 = 0;
+ } else {
+ fec->eth->iaddr1 = 0;
+ fec->eth->iaddr2 = (1 << crc);
+ }
+
+ /*
+ * Set physical address
+ */
+ fec->eth->paddr1 = (mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3];
+ fec->eth->paddr2 = (mac[4] << 24) + (mac[5] << 16) + 0x8808;
+}
+
+/********************************************************************/
+static int mpc512x_fec_init (struct eth_device *dev, bd_t * bis)
+{
+ mpc512x_fec_priv *fec = (mpc512x_fec_priv *)dev->priv;
+
+#if (DEBUG & 0x1)
+ printf ("mpc512x_fec_init... Begin\n");
+#endif
+
+ /* Set interrupt mask register */
+ fec->eth->imask = 0x00000000;
+
+ /* Clear FEC-Lite interrupt event register(IEVENT) */
+ fec->eth->ievent = 0xffffffff;
+
+ /* Set transmit fifo watermark register(X_WMRK), default = 64 */
+ fec->eth->x_wmrk = 0x0;
+
+ /* Set Opcode/Pause Duration Register */
+ fec->eth->op_pause = 0x00010020;
+
+ /* Frame length=1518; MII mode */
+ fec->eth->r_cntrl = 0x05ee000c;
+
+ /* Half-duplex, heartbeat disabled */
+ fec->eth->x_cntrl = 0x00000000;
+
+ /* Enable MIB counters */
+ fec->eth->mib_control = 0x0;
+
+ /* Setup recv fifo start and buff size */
+ fec->eth->r_fstart = 0x500;
+ fec->eth->r_buff_size = 0x5e0;
+
+ /* Setup BD base addresses */
+ fec->eth->r_des_start = (uint32)fec->bdBase->rbd;
+ fec->eth->x_des_start = (uint32)fec->bdBase->tbd;
+
+ /* DMA Control */
+ fec->eth->dma_control = 0xc0000000;
+
+ /* Enable FEC */
+ fec->eth->ecntrl |= 0x00000006;
+
+ /* Initilize addresses and status words of BDs */
+ mpc512x_fec_bd_init (fec);
+
+ /* Descriptor polling active */
+ fec->eth->r_des_active = 0x01000000;
+
+#if (DEBUG & 0x1)
+ printf("mpc512x_fec_init... Done \n");
+#endif
+ return 1;
+}
+
+/********************************************************************/
+int mpc512x_fec_init_phy (struct eth_device *dev, bd_t * bis)
+{
+ mpc512x_fec_priv *fec = (mpc512x_fec_priv *)dev->priv;
+ const uint8 phyAddr = CONFIG_PHY_ADDR; /* Only one PHY */
+ int timeout = 1;
+ uint16 phyStatus;
+
+#if (DEBUG & 0x1)
+ printf ("mpc512x_fec_init_phy... Begin\n");
+#endif
+
+ /*
+ * Clear FEC-Lite interrupt event register(IEVENT)
+ */
+ fec->eth->ievent = 0xffffffff;
+
+ /*
+ * Set interrupt mask register
+ */
+ fec->eth->imask = 0x00000000;
+
+ if (fec->xcv_type != SEVENWIRE) {
+ /*
+ * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
+ * and do not drop the Preamble.
+ */
+ fec->eth->mii_speed = (((gd->ipb_clk / 1000000) / 5) + 1) << 1;
+
+ /*
+ * Reset PHY, then delay 300ns
+ */
+ miiphy_write (dev->name, phyAddr, 0x0, 0x8000);
+ udelay (1000);
+
+ if (fec->xcv_type == MII10) {
+ /*
+ * Force 10Base-T, FDX operation
+ */
+#if (DEBUG & 0x2)
+ printf ("Forcing 10 Mbps ethernet link... ");
+#endif
+ miiphy_read (dev->name, phyAddr, 0x1, &phyStatus);
+
+ miiphy_write (dev->name, phyAddr, 0x0, 0x0180);
+
+ timeout = 20;
+ do { /* wait for link status to go down */
+ udelay (10000);
+ if ((timeout--) == 0) {
+#if (DEBUG & 0x2)
+ printf ("hmmm, should not have waited...");
+#endif
+ break;
+ }
+ miiphy_read (dev->name, phyAddr, 0x1, &phyStatus);
+#if (DEBUG & 0x2)
+ printf ("=");
+#endif
+ } while ((phyStatus & 0x0004)); /* !link up */
+
+ timeout = 1000;
+ do { /* wait for link status to come back up */
+ udelay (10000);
+ if ((timeout--) == 0) {
+ printf ("failed. Link is down.\n");
+ break;
+ }
+ miiphy_read (dev->name, phyAddr, 0x1, &phyStatus);
+#if (DEBUG & 0x2)
+ printf ("+");
+#endif
+ } while (!(phyStatus & 0x0004)); /* !link up */
+
+#if (DEBUG & 0x2)
+ printf ("done.\n");
+#endif
+ } else { /* MII100 */
+ /*
+ * Set the auto-negotiation advertisement register bits
+ */
+ miiphy_write (dev->name, phyAddr, 0x4, 0x01e1);
+
+ /*
+ * Set MDIO bit 0.12 = 1(&& bit 0.9=1?) to enable auto-negotiation
+ */
+ miiphy_write (dev->name, phyAddr, 0x0, 0x1200);
+
+ /*
+ * Wait for AN completion
+ */
+ timeout = 50000;
+ do {
+ udelay (1000);
+
+ if ((timeout--) == 0) {
+#if (DEBUG & 0x2)
+ printf ("PHY auto neg 0 failed...\n");
+#endif
+ return -1;
+ }
+
+ if (miiphy_read (dev->name, phyAddr, 0x1, &phyStatus) != 0) {
+#if (DEBUG & 0x2)
+ printf ("PHY auto neg 1 failed 0x%04x...\n", phyStatus);
+#endif
+ return -1;
+ }
+ } while (!(phyStatus & 0x0004));
+
+#if (DEBUG & 0x2)
+ printf ("PHY auto neg complete! \n");
+#endif
+ }
+ }
+
+#if (DEBUG & 0x2)
+ if (fec->xcv_type != SEVENWIRE)
+ mpc512x_fec_phydump (dev->name);
+#endif
+
+#if (DEBUG & 0x1)
+ printf ("mpc512x_fec_init_phy... Done \n");
+#endif
+ return 1;
+}
+
+/********************************************************************/
+static void mpc512x_fec_halt (struct eth_device *dev)
+{
+ mpc512x_fec_priv *fec = (mpc512x_fec_priv *)dev->priv;
+ int counter = 0xffff;
+
+#if (DEBUG & 0x2)
+ if (fec->xcv_type != SEVENWIRE)
+ mpc512x_fec_phydump (dev->name);
+#endif
+
+ /*
+ * mask FEC chip interrupts
+ */
+ fec->eth->imask = 0;
+
+ /*
+ * issue graceful stop command to the FEC transmitter if necessary
+ */
+ fec->eth->x_cntrl |= 0x00000001;
+
+ /*
+ * wait for graceful stop to register
+ */
+ while ((counter--) && (!(fec->eth->ievent & 0x10000000))) ;
+
+ /*
+ * Disable the Ethernet Controller
+ */
+ fec->eth->ecntrl &= 0xfffffffd;
+
+ /*
+ * Issue a reset command to the FEC chip
+ */
+ fec->eth->ecntrl |= 0x1;
+
+ /*
+ * wait at least 16 clock cycles
+ */
+ udelay (10);
+#if (DEBUG & 0x3)
+ printf ("Ethernet task stopped\n");
+#endif
+}
+
+/********************************************************************/
+
+static int mpc512x_fec_send (struct eth_device *dev, volatile void *eth_data,
+ int data_length)
+{
+ /*
+ * This routine transmits one frame. This routine only accepts
+ * 6-byte Ethernet addresses.
+ */
+ mpc512x_fec_priv *fec = (mpc512x_fec_priv *)dev->priv;
+ volatile FEC_TBD *pTbd;
+
+#if (DEBUG & 0x20)
+ printf("tbd status: 0x%04x\n", fec->tbdBase[fec->tbdIndex].status);
+#endif
+
+ /*
+ * Clear Tx BD ring at first
+ */
+ mpc512x_fec_tbd_scrub (fec);
+
+ /*
+ * Check for valid length of data.
+ */
+ if ((data_length > 1500) || (data_length <= 0)) {
+ return -1;
+ }
+
+ /*
+ * Check the number of vacant TxBDs.
+ */
+ if (fec->cleanTbdNum < 1) {
+#if (DEBUG & 0x20)
+ printf ("No available TxBDs ...\n");
+#endif
+ return -1;
+ }
+
+ /*
+ * Get the first TxBD to send the mac header
+ */
+ pTbd = &fec->bdBase->tbd[fec->tbdIndex];
+ pTbd->dataLength = data_length;
+ pTbd->dataPointer = (uint32)eth_data;
+ pTbd->status |= FEC_TBD_LAST | FEC_TBD_TC | FEC_TBD_READY;
+ fec->tbdIndex = (fec->tbdIndex + 1) % FEC_TBD_NUM;
+
+ /* Activate transmit Buffer Descriptor polling */
+ fec->eth->x_des_active = 0x01000000; /* Descriptor polling active */
+
+#if (DEBUG & 0x8)
+ printf ( "+" );
+#endif
+
+ fec->cleanTbdNum -= 1;
+
+ /*
+ * wait until frame is sent .
+ */
+ while (pTbd->status & FEC_TBD_READY) {
+ udelay (10);
+#if (DEBUG & 0x8)
+ printf ("TDB status = %04x\n", pTbd->status);
+#endif
+ }
+
+ return 0;
+}
+
+
+/********************************************************************/
+static int mpc512x_fec_recv (struct eth_device *dev)
+{
+ /*
+ * This command pulls one frame from the card
+ */
+ mpc512x_fec_priv *fec = (mpc512x_fec_priv *)dev->priv;
+ volatile FEC_RBD *pRbd = &fec->bdBase->rbd[fec->rbdIndex];
+ unsigned long ievent;
+ int frame_length, len = 0;
+ uchar buff[FEC_MAX_PKT_SIZE];
+
+#if (DEBUG & 0x1)
+ printf ("mpc512x_fec_recv %d Start...\n", fec->rbdIndex);
+#endif
+#if (DEBUG & 0x8)
+ printf( "-" );
+#endif
+
+ /*
+ * Check if any critical events have happened
+ */
+ ievent = fec->eth->ievent;
+ fec->eth->ievent = ievent;
+ if (ievent & 0x20060000) {
+ /* BABT, Rx/Tx FIFO errors */
+ mpc512x_fec_halt (dev);
+ mpc512x_fec_init (dev, NULL);
+ return 0;
+ }
+ if (ievent & 0x80000000) {
+ /* Heartbeat error */
+ fec->eth->x_cntrl |= 0x00000001;
+ }
+ if (ievent & 0x10000000) {
+ /* Graceful stop complete */
+ if (fec->eth->x_cntrl & 0x00000001) {
+ mpc512x_fec_halt (dev);
+ fec->eth->x_cntrl &= ~0x00000001;
+ mpc512x_fec_init (dev, NULL);
+ }
+ }
+
+ if (!(pRbd->status & FEC_RBD_EMPTY)) {
+ if ((pRbd->status & FEC_RBD_LAST) &&
+ !(pRbd->status & FEC_RBD_ERR) &&
+ ((pRbd->dataLength - 4) > 14)) {
+
+ /*
+ * Get buffer size
+ */
+ frame_length = pRbd->dataLength - 4;
+
+#if (DEBUG & 0x20)
+ {
+ int i;
+ printf ("recv data hdr:");
+ for (i = 0; i < 14; i++)
+ printf ("%x ", *((uint8*)pRbd->dataPointer + i));
+ printf("\n");
+ }
+#endif
+
+ /*
+ * Fill the buffer and pass it to upper layers
+ */
+ memcpy (buff, (void*)pRbd->dataPointer, frame_length);
+ NetReceive ((uchar*)buff, frame_length);
+ len = frame_length;
+ }
+
+ /*
+ * Reset buffer descriptor as empty
+ */
+ mpc512x_fec_rbd_clean (fec, pRbd);
+ }
+
+ /* Try to fill Buffer Descriptors */
+ fec->eth->r_des_active = 0x01000000; /* Descriptor polling active */
+ return len;
+}
+
+/********************************************************************/
+int mpc512x_fec_initialize (bd_t * bis)
+{
+
+ immap_t *im = (immap_t*) CFG_IMMR;
+ mpc512x_fec_priv *fec;
+ struct eth_device *dev;
+ int i;
+ char *tmp, *end, env_enetaddr[6];
+ uint32 *reg;
+ void * bd;
+
+ fec = (mpc512x_fec_priv *) malloc (sizeof(*fec));
+ dev = (struct eth_device *) malloc (sizeof(*dev));
+ memset (dev, 0, sizeof *dev);
+
+ fec->eth = (ethernet_regs *) MPC512X_FEC;
+
+# ifndef CONFIG_FEC_10MBIT
+ fec->xcv_type = MII100;
+# else
+ fec->xcv_type = MII10;
+# endif
+ dev->priv = (void *)fec;
+ dev->iobase = MPC512X_FEC;
+ dev->init = mpc512x_fec_init;
+ dev->halt = mpc512x_fec_halt;
+ dev->send = mpc512x_fec_send;
+ dev->recv = mpc512x_fec_recv;
+
+ sprintf (dev->name, "FEC ETHERNET");
+ eth_register (dev);
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+ miiphy_register (dev->name,
+ fec512x_miiphy_read, fec512x_miiphy_write);
+#endif
+
+ /*
+ * Initialize I\O pins
+ */
+ reg = (uint32 *) &(im->io_ctrl.regs[PSC0_0_IDX]);
+
+ for (i = 0; i < 15; i++)
+ reg[i] = IOCTRL_MUX_FEC | 0x00000001;
+
+ im->io_ctrl.regs[SPDIF_TXCLOCK_IDX] = IOCTRL_MUX_FEC | 0x00000001;
+ im->io_ctrl.regs[SPDIF_TX_IDX] = IOCTRL_MUX_FEC | 0x00000001;
+ im->io_ctrl.regs[SPDIF_RX_IDX] = IOCTRL_MUX_FEC | 0x00000001;
+
+ /* Clean up space FEC's MIB and FIFO RAM ...*/
+ memset ((void *) MPC512X_FEC + 0x200, 0x00, 0x400);
+
+ /*
+ * Malloc space for BDs (must be quad word-aligned)
+ * this pointer is lost, so cannot be freed
+ */
+ bd = malloc (sizeof(mpc512x_buff_descs) + 0x1f);
+ fec->bdBase = (mpc512x_buff_descs*)((uint32)bd & 0xfffffff0);
+ memset ((void *) bd, 0x00, sizeof(mpc512x_buff_descs) + 0x1f);
+
+ /*
+ * Set interrupt mask register
+ */
+ fec->eth->imask = 0x00000000;
+
+ /*
+ * Clear FEC-Lite interrupt event register(IEVENT)
+ */
+ fec->eth->ievent = 0xffffffff;
+
+ /*
+ * Try to set the mac address now. The fec mac address is
+ * a garbage after reset. When not using fec for booting
+ * the Linux fec driver will try to work with this garbage.
+ */
+ tmp = getenv ("ethaddr");
+ if (tmp) {
+ for (i=0; i<6; i++) {
+ env_enetaddr[i] = tmp ? simple_strtoul (tmp, &end, 16) : 0;
+ if (tmp)
+ tmp = (*end) ? end+1 : end;
+ }
+ mpc512x_fec_set_hwaddr (fec, env_enetaddr);
+ fec->eth->gaddr1 = 0x00000000;
+ fec->eth->gaddr2 = 0x00000000;
+ }
+
+ mpc512x_fec_init_phy (dev, bis);
+
+ return 1;
+}
+
+/* MII-interface related functions */
+/********************************************************************/
+int fec512x_miiphy_read (char *devname, uint8 phyAddr, uint8 regAddr, uint16 * retVal)
+{
+ ethernet_regs *eth = (ethernet_regs *) MPC512X_FEC;
+ uint32 reg; /* convenient holder for the PHY register */
+ uint32 phy; /* convenient holder for the PHY */
+ int timeout = 0xffff;
+
+ /*
+ * reading from any PHY's register is done by properly
+ * programming the FEC's MII data register.
+ */
+ reg = regAddr << FEC_MII_DATA_RA_SHIFT;
+ phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
+
+ eth->mii_data = (FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA | phy | reg);
+
+ /*
+ * wait for the related interrupt
+ */
+ while ((timeout--) && (!(eth->ievent & 0x00800000))) ;
+
+ if (timeout == 0) {
+#if (DEBUG & 0x2)
+ printf ("Read MDIO failed...\n");
+#endif
+ return -1;
+ }
+
+ /*
+ * clear mii interrupt bit
+ */
+ eth->ievent = 0x00800000;
+
+ /*
+ * it's now safe to read the PHY's register
+ */
+ *retVal = (uint16) eth->mii_data;
+
+ return 0;
+}
+
+/********************************************************************/
+int fec512x_miiphy_write (char *devname, uint8 phyAddr, uint8 regAddr, uint16 data)
+{
+ ethernet_regs *eth = (ethernet_regs *) MPC512X_FEC;
+ uint32 reg; /* convenient holder for the PHY register */
+ uint32 phy; /* convenient holder for the PHY */
+ int timeout = 0xffff;
+
+ reg = regAddr << FEC_MII_DATA_RA_SHIFT;
+ phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
+
+ eth->mii_data = (FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR |
+ FEC_MII_DATA_TA | phy | reg | data);
+
+ /*
+ * wait for the MII interrupt
+ */
+ while ((timeout--) && (!(eth->ievent & 0x00800000))) ;
+
+ if (timeout == 0) {
+#if (DEBUG & 0x2)
+ printf ("Write MDIO failed...\n");
+#endif
+ return -1;
+ }
+
+ /*
+ * clear MII interrupt bit
+ */
+ eth->ievent = 0x00800000;
+
+ return 0;
+}
+
+#if (DEBUG & 0x40)
+static uint32 local_crc32 (char *string, unsigned int crc_value, int len)
+{
+ int i;
+ char c;
+ unsigned int crc, count;
+
+ /*
+ * crc32 algorithm
+ */
+ /*
+ * crc = 0xffffffff; * The initialized value should be 0xffffffff
+ */
+ crc = crc_value;
+
+ for (i = len; --i >= 0;) {
+ c = *string++;
+ for (count = 0; count < 8; count++) {
+ if ((c & 0x01) ^ (crc & 0x01)) {
+ crc >>= 1;
+ crc = crc ^ 0xedb88320;
+ } else {
+ crc >>= 1;
+ }
+ c >>= 1;
+ }
+ }
+
+ /*
+ * In big endian system, do byte swaping for crc value
+ */
+ /**/ return crc;
+}
+#endif /* DEBUG */
+
+#endif /* CONFIG_MPC512x_FEC */
diff --git a/cpu/mpc512x/fec.h b/cpu/mpc512x/fec.h
new file mode 100644
index 0000000..d2d877a
--- /dev/null
+++ b/cpu/mpc512x/fec.h
@@ -0,0 +1,224 @@
+/*
+ * (C) Copyright 2003 - 2007
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Derived from the MPC8xx driver's header file.
+ */
+
+#ifndef __MPC512X_FEC_H
+#define __MPC512X_FEC_H
+
+#include <common.h>
+#include <mpc512x.h>
+
+typedef unsigned long uint32;
+typedef unsigned short uint16;
+typedef unsigned char uint8;
+
+typedef struct ethernet_register_set {
+
+/* [10:2]addr = 00 */
+
+/* Control and status Registers (offset 000-1FF) */
+
+ volatile uint32 fec_id; /* MBAR_ETH + 0x000 */
+ volatile uint32 ievent; /* MBAR_ETH + 0x004 */
+ volatile uint32 imask; /* MBAR_ETH + 0x008 */
+
+ volatile uint32 RES0[1]; /* MBAR_ETH + 0x00C */
+ volatile uint32 r_des_active; /* MBAR_ETH + 0x010 */
+ volatile uint32 x_des_active; /* MBAR_ETH + 0x014 */
+
+ volatile uint32 RES1[3]; /* MBAR_ETH + 0x018-020 */
+ volatile uint32 ecntrl; /* MBAR_ETH + 0x024 */
+
+ volatile uint32 RES2[6]; /* MBAR_ETH + 0x028-03C */
+ volatile uint32 mii_data; /* MBAR_ETH + 0x040 */
+ volatile uint32 mii_speed; /* MBAR_ETH + 0x044 */
+
+ volatile uint32 RES3[7]; /* MBAR_ETH + 0x048-060 */
+ volatile uint32 mib_control; /* MBAR_ETH + 0x064 */
+
+ volatile uint32 RES4[7]; /* MBAR_ETH + 0x068-80 */
+ volatile uint32 r_cntrl; /* MBAR_ETH + 0x084 */
+ volatile uint32 r_hash; /* MBAR_ETH + 0x088 */
+
+ volatile uint32 RES5[14]; /* MBAR_ETH + 0x08c-0C0 */
+ volatile uint32 x_cntrl; /* MBAR_ETH + 0x0C4 */
+
+ volatile uint32 RES6[7]; /* MBAR_ETH + 0x0C8-0E0 */
+ volatile uint32 paddr1; /* MBAR_ETH + 0x0E4 */
+ volatile uint32 paddr2; /* MBAR_ETH + 0x0E8 */
+ volatile uint32 op_pause; /* MBAR_ETH + 0x0EC */
+
+ volatile uint32 RES7[10]; /* MBAR_ETH + 0x0F0-114 */
+ volatile uint32 iaddr1; /* MBAR_ETH + 0x118 */
+ volatile uint32 iaddr2; /* MBAR_ETH + 0x11C */
+ volatile uint32 gaddr1; /* MBAR_ETH + 0x120 */
+ volatile uint32 gaddr2; /* MBAR_ETH + 0x124 */
+
+ volatile uint32 RES8[6]; /* MBAR_ETH + 0x128-13C */
+ volatile uint32 fifo_id; /* MBAR_ETH + 0x140 */
+ volatile uint32 x_wmrk; /* MBAR_ETH + 0x144 */
+ volatile uint32 RES9[1]; /* MBAR_ETH + 0x148 */
+ volatile uint32 r_bound; /* MBAR_ETH + 0x14C */
+ volatile uint32 r_fstart; /* MBAR_ETH + 0x150 */
+
+ volatile uint32 RES10[11]; /* MBAR_ETH + 0x154-17C */
+ volatile uint32 r_des_start; /* MBAR_ETH + 0x180 */
+ volatile uint32 x_des_start; /* MBAR_ETH + 0x184 */
+ volatile uint32 r_buff_size; /* MBAR_ETH + 0x188 */
+ volatile uint32 RES11[26]; /* MBAR_ETH + 0x18C-1F0 */
+ volatile uint32 dma_control; /* MBAR_ETH + 0x1F4 */
+ volatile uint32 RES12[2]; /* MBAR_ETH + 0x1F8-1FC */
+
+/* MIB COUNTERS (Offset 200-2FF) */
+
+ volatile uint32 rmon_t_drop; /* MBAR_ETH + 0x200 */
+ volatile uint32 rmon_t_packets; /* MBAR_ETH + 0x204 */
+ volatile uint32 rmon_t_bc_pkt; /* MBAR_ETH + 0x208 */
+ volatile uint32 rmon_t_mc_pkt; /* MBAR_ETH + 0x20C */
+ volatile uint32 rmon_t_crc_align; /* MBAR_ETH + 0x210 */
+ volatile uint32 rmon_t_undersize; /* MBAR_ETH + 0x214 */
+ volatile uint32 rmon_t_oversize; /* MBAR_ETH + 0x218 */
+ volatile uint32 rmon_t_frag; /* MBAR_ETH + 0x21C */
+ volatile uint32 rmon_t_jab; /* MBAR_ETH + 0x220 */
+ volatile uint32 rmon_t_col; /* MBAR_ETH + 0x224 */
+ volatile uint32 rmon_t_p64; /* MBAR_ETH + 0x228 */
+ volatile uint32 rmon_t_p65to127; /* MBAR_ETH + 0x22C */
+ volatile uint32 rmon_t_p128to255; /* MBAR_ETH + 0x230 */
+ volatile uint32 rmon_t_p256to511; /* MBAR_ETH + 0x234 */
+ volatile uint32 rmon_t_p512to1023; /* MBAR_ETH + 0x238 */
+ volatile uint32 rmon_t_p1024to2047; /* MBAR_ETH + 0x23C */
+ volatile uint32 rmon_t_p_gte2048; /* MBAR_ETH + 0x240 */
+ volatile uint32 rmon_t_octets; /* MBAR_ETH + 0x244 */
+ volatile uint32 ieee_t_drop; /* MBAR_ETH + 0x248 */
+ volatile uint32 ieee_t_frame_ok; /* MBAR_ETH + 0x24C */
+ volatile uint32 ieee_t_1col; /* MBAR_ETH + 0x250 */
+ volatile uint32 ieee_t_mcol; /* MBAR_ETH + 0x254 */
+ volatile uint32 ieee_t_def; /* MBAR_ETH + 0x258 */
+ volatile uint32 ieee_t_lcol; /* MBAR_ETH + 0x25C */
+ volatile uint32 ieee_t_excol; /* MBAR_ETH + 0x260 */
+ volatile uint32 ieee_t_macerr; /* MBAR_ETH + 0x264 */
+ volatile uint32 ieee_t_cserr; /* MBAR_ETH + 0x268 */
+ volatile uint32 ieee_t_sqe; /* MBAR_ETH + 0x26C */
+ volatile uint32 t_fdxfc; /* MBAR_ETH + 0x270 */
+ volatile uint32 ieee_t_octets_ok; /* MBAR_ETH + 0x274 */
+
+ volatile uint32 RES13[2]; /* MBAR_ETH + 0x278-27C */
+ volatile uint32 rmon_r_drop; /* MBAR_ETH + 0x280 */
+ volatile uint32 rmon_r_packets; /* MBAR_ETH + 0x284 */
+ volatile uint32 rmon_r_bc_pkt; /* MBAR_ETH + 0x288 */
+ volatile uint32 rmon_r_mc_pkt; /* MBAR_ETH + 0x28C */
+ volatile uint32 rmon_r_crc_align; /* MBAR_ETH + 0x290 */
+ volatile uint32 rmon_r_undersize; /* MBAR_ETH + 0x294 */
+ volatile uint32 rmon_r_oversize; /* MBAR_ETH + 0x298 */
+ volatile uint32 rmon_r_frag; /* MBAR_ETH + 0x29C */
+ volatile uint32 rmon_r_jab; /* MBAR_ETH + 0x2A0 */
+
+ volatile uint32 rmon_r_resvd_0; /* MBAR_ETH + 0x2A4 */
+
+ volatile uint32 rmon_r_p64; /* MBAR_ETH + 0x2A8 */
+ volatile uint32 rmon_r_p65to127; /* MBAR_ETH + 0x2AC */
+ volatile uint32 rmon_r_p128to255; /* MBAR_ETH + 0x2B0 */
+ volatile uint32 rmon_r_p256to511; /* MBAR_ETH + 0x2B4 */
+ volatile uint32 rmon_r_p512to1023; /* MBAR_ETH + 0x2B8 */
+ volatile uint32 rmon_r_p1024to2047; /* MBAR_ETH + 0x2BC */
+ volatile uint32 rmon_r_p_gte2048; /* MBAR_ETH + 0x2C0 */
+ volatile uint32 rmon_r_octets; /* MBAR_ETH + 0x2C4 */
+ volatile uint32 ieee_r_drop; /* MBAR_ETH + 0x2C8 */
+ volatile uint32 ieee_r_frame_ok; /* MBAR_ETH + 0x2CC */
+ volatile uint32 ieee_r_crc; /* MBAR_ETH + 0x2D0 */
+ volatile uint32 ieee_r_align; /* MBAR_ETH + 0x2D4 */
+ volatile uint32 r_macerr; /* MBAR_ETH + 0x2D8 */
+ volatile uint32 r_fdxfc; /* MBAR_ETH + 0x2DC */
+ volatile uint32 ieee_r_octets_ok; /* MBAR_ETH + 0x2E0 */
+
+ volatile uint32 RES14[6]; /* MBAR_ETH + 0x2E4-2FC */
+
+ volatile uint32 RES15[64]; /* MBAR_ETH + 0x300-3FF */
+} ethernet_regs;
+
+/* Receive & Transmit Buffer Descriptor definitions */
+typedef struct BufferDescriptor {
+ uint16 status;
+ uint16 dataLength;
+ uint32 dataPointer;
+} FEC_RBD;
+
+typedef struct {
+ uint16 status;
+ uint16 dataLength;
+ uint32 dataPointer;
+} FEC_TBD;
+
+/* private structure */
+typedef enum {
+ SEVENWIRE, /* 7-wire */
+ MII10, /* MII 10Mbps */
+ MII100 /* MII 100Mbps */
+} xceiver_type;
+
+/* BD Numer definitions */
+#define FEC_TBD_NUM 48 /* The user can adjust this value */
+#define FEC_RBD_NUM 32 /* The user can adjust this value */
+
+/* packet size limit */
+#define FEC_MAX_PKT_SIZE 1536
+
+typedef struct {
+ uint8 frame[FEC_MAX_PKT_SIZE];
+} mpc512x_frame;
+
+typedef struct {
+ FEC_RBD rbd[FEC_RBD_NUM]; /* RBD ring */
+ FEC_TBD tbd[FEC_TBD_NUM]; /* TBD ring */
+ mpc512x_frame recv_frames[FEC_RBD_NUM]; /* receive buff */
+} mpc512x_buff_descs;
+
+typedef struct {
+ ethernet_regs *eth;
+ xceiver_type xcv_type; /* transceiver type */
+ mpc512x_buff_descs *bdBase; /* BD rings and recv buffer */
+ uint16 rbdIndex; /* next receive BD to read */
+ uint16 tbdIndex; /* next transmit BD to send */
+ uint16 usedTbdIndex; /* next transmit BD to clean */
+ uint16 cleanTbdNum; /* the number of available transmit BDs */
+} mpc512x_fec_priv;
+
+/* RBD bits definitions */
+#define FEC_RBD_EMPTY 0x8000 /* Buffer is empty */
+#define FEC_RBD_WRAP 0x2000 /* Last BD in ring */
+#define FEC_RBD_LAST 0x0800 /* Buffer is last in frame(useless) */
+#define FEC_RBD_MISS 0x0100 /* Miss bit for prom mode */
+#define FEC_RBD_BC 0x0080 /* The received frame is broadcast frame */
+#define FEC_RBD_MC 0x0040 /* The received frame is multicast frame */
+#define FEC_RBD_LG 0x0020 /* Frame length violation */
+#define FEC_RBD_NO 0x0010 /* Nonoctet align frame */
+#define FEC_RBD_SH 0x0008 /* Short frame */
+#define FEC_RBD_CR 0x0004 /* CRC error */
+#define FEC_RBD_OV 0x0002 /* Receive FIFO overrun */
+#define FEC_RBD_TR 0x0001 /* Frame is truncated */
+#define FEC_RBD_ERR (FEC_RBD_LG | FEC_RBD_NO | FEC_RBD_CR | \
+ FEC_RBD_OV | FEC_RBD_TR)
+
+/* TBD bits definitions */
+#define FEC_TBD_READY 0x8000 /* Buffer is ready */
+#define FEC_TBD_WRAP 0x2000 /* Last BD in ring */
+#define FEC_TBD_LAST 0x0800 /* Buffer is last in frame */
+#define FEC_TBD_TC 0x0400 /* Transmit the CRC */
+#define FEC_TBD_ABC 0x0200 /* Append bad CRC */
+
+/* MII-related definitios */
+#define FEC_MII_DATA_ST 0x40000000 /* Start of frame delimiter */
+#define FEC_MII_DATA_OP_RD 0x20000000 /* Perform a read operation */
+#define FEC_MII_DATA_OP_WR 0x10000000 /* Perform a write operation */
+#define FEC_MII_DATA_PA_MSK 0x0f800000 /* PHY Address field mask */
+#define FEC_MII_DATA_RA_MSK 0x007c0000 /* PHY Register field mask */
+#define FEC_MII_DATA_TA 0x00020000 /* Turnaround */
+#define FEC_MII_DATA_DATAMSK 0x0000ffff /* PHY data field */
+
+#define FEC_MII_DATA_RA_SHIFT 18 /* MII Register address bits */
+#define FEC_MII_DATA_PA_SHIFT 23 /* MII PHY address bits */
+
+#endif /* __MPC512X_FEC_H */
diff --git a/cpu/mpc512x/i2c.c b/cpu/mpc512x/i2c.c
new file mode 100644
index 0000000..00e28d6
--- /dev/null
+++ b/cpu/mpc512x/i2c.c
@@ -0,0 +1,431 @@
+/*
+ * (C) Copyright 2003 - 2007
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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
+ *
+ * Based on the MPC5xxx code.
+ */
+
+#include <common.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_HARD_I2C
+
+#include <mpc512x.h>
+#include <i2c.h>
+
+#define immr ((immap_t *)CFG_IMMR)
+
+/* by default set I2C bus 0 active */
+static unsigned int bus_num = 0;
+
+#define I2C_TIMEOUT 100
+#define I2C_RETRIES 3
+
+struct mpc512x_i2c_tap {
+ int scl2tap;
+ int tap2tap;
+};
+
+static int mpc_reg_in(volatile u32 *reg);
+static void mpc_reg_out(volatile u32 *reg, int val, int mask);
+static int wait_for_bb(void);
+static int wait_for_pin(int *status);
+static int do_address(uchar chip, char rdwr_flag);
+static int send_bytes(uchar chip, char *buf, int len);
+static int receive_bytes(uchar chip, char *buf, int len);
+static int mpc_get_fdr(int);
+
+static int mpc_reg_in (volatile u32 *reg)
+{
+ int ret = *reg >> 24;
+ __asm__ __volatile__ ("eieio");
+ return ret;
+}
+
+static void mpc_reg_out (volatile u32 *reg, int val, int mask)
+{
+ int tmp;
+
+ if (!mask) {
+ *reg = val << 24;
+ } else {
+ tmp = mpc_reg_in (reg);
+ *reg = ((tmp & ~mask) | (val & mask)) << 24;
+ }
+ __asm__ __volatile__ ("eieio");
+
+ return;
+}
+
+static int wait_for_bb (void)
+{
+ i2c512x_dev_t *regs = &immr->i2c.dev[bus_num];
+ int timeout = I2C_TIMEOUT;
+ int status;
+
+ status = mpc_reg_in (&regs->msr);
+
+ while (timeout-- && (status & I2C_BB)) {
+ volatile int temp;
+ mpc_reg_out (&regs->mcr, I2C_STA, I2C_STA);
+ temp = mpc_reg_in (&regs->mdr);
+ mpc_reg_out (&regs->mcr, 0, I2C_STA);
+ mpc_reg_out (&regs->mcr, 0, 0);
+ mpc_reg_out (&regs->mcr, I2C_EN, 0);
+
+ udelay (1000);
+ status = mpc_reg_in (&regs->msr);
+ }
+
+ return (status & I2C_BB);
+}
+
+static int wait_for_pin (int *status)
+{
+ i2c512x_dev_t *regs = &immr->i2c.dev[bus_num];
+ int timeout = I2C_TIMEOUT;
+
+ *status = mpc_reg_in (&regs->msr);
+
+ while (timeout-- && !(*status & I2C_IF)) {
+ udelay (1000);
+ *status = mpc_reg_in (&regs->msr);
+ }
+
+ if (!(*status & I2C_IF)) {
+ return -1;
+ }
+
+ mpc_reg_out (&regs->msr, 0, I2C_IF);
+
+ return 0;
+}
+
+static int do_address (uchar chip, char rdwr_flag)
+{
+ i2c512x_dev_t *regs = &immr->i2c.dev[bus_num];
+ int status;
+
+ chip <<= 1;
+
+ if (rdwr_flag) {
+ chip |= 1;
+ }
+
+ mpc_reg_out (&regs->mcr, I2C_TX, I2C_TX);
+ mpc_reg_out (&regs->mdr, chip, 0);
+
+ if (wait_for_pin (&status)) {
+ return -2;
+ }
+
+ if (status & I2C_RXAK) {
+ return -3;
+ }
+
+ return 0;
+}
+
+static int send_bytes (uchar chip, char *buf, int len)
+{
+ i2c512x_dev_t *regs = &immr->i2c.dev[bus_num];
+ int wrcount;
+ int status;
+
+ for (wrcount = 0; wrcount < len; ++wrcount) {
+
+ mpc_reg_out (&regs->mdr, buf[wrcount], 0);
+
+ if (wait_for_pin (&status)) {
+ break;
+ }
+
+ if (status & I2C_RXAK) {
+ break;
+ }
+
+ }
+
+ return !(wrcount == len);
+}
+
+static int receive_bytes (uchar chip, char *buf, int len)
+{
+ i2c512x_dev_t *regs = &immr->i2c.dev[bus_num];
+ int dummy = 1;
+ int rdcount = 0;
+ int status;
+ int i;
+
+ mpc_reg_out (&regs->mcr, 0, I2C_TX);
+
+ for (i = 0; i < len; ++i) {
+ buf[rdcount] = mpc_reg_in (&regs->mdr);
+
+ if (dummy) {
+ dummy = 0;
+ } else {
+ rdcount++;
+ }
+
+ if (wait_for_pin (&status)) {
+ return -4;
+ }
+ }
+
+ mpc_reg_out (&regs->mcr, I2C_TXAK, I2C_TXAK);
+ buf[rdcount++] = mpc_reg_in (&regs->mdr);
+
+ if (wait_for_pin (&status)) {
+ return -5;
+ }
+
+ mpc_reg_out (&regs->mcr, 0, I2C_TXAK);
+
+ return 0;
+}
+
+/**************** I2C API ****************/
+
+void i2c_init (int speed, int saddr)
+{
+ int i;
+ for(i = 0; i < I2C_BUS_CNT; i++){
+ i2c512x_dev_t *regs = &immr->i2c.dev[i];
+ mpc_reg_out (&regs->mcr, 0, 0);
+
+ /* Set clock */
+ mpc_reg_out (&regs->mfdr, mpc_get_fdr (speed), 0);
+ mpc_reg_out (&regs->madr, saddr << 1, 0);
+
+ /* Enable module */
+ mpc_reg_out (&regs->mcr, I2C_EN, I2C_INIT_MASK);
+ mpc_reg_out (&regs->msr, 0, I2C_IF);
+ }
+
+ /* Disable interrupts */
+ immr->i2c.icr = 0;
+ /* Turn off filters */
+ immr->i2c.mifr = 0;
+ return;
+}
+
+static int mpc_get_fdr (int speed)
+{
+ static int fdr = -1;
+
+ if (fdr == -1) {
+ ulong best_speed = 0;
+ ulong divider;
+ ulong ipb, scl;
+ ulong bestmatch = 0xffffffffUL;
+ int best_i = 0, best_j = 0, i, j;
+ int SCL_Tap[] = { 9, 10, 12, 15, 5, 6, 7, 8};
+ struct mpc512x_i2c_tap scltap[] = {
+ {4, 1},
+ {4, 2},
+ {6, 4},
+ {6, 8},
+ {14, 16},
+ {30, 32},
+ {62, 64},
+ {126, 128}
+ };
+
+ ipb = gd->ipb_clk;
+ for (i = 7; i >= 0; i--) {
+ for (j = 7; j >= 0; j--) {
+ scl = 2 * (scltap[j].scl2tap +
+ (SCL_Tap[i] - 1) * scltap[j].tap2tap
+ + 2);
+ if (ipb <= speed*scl) {
+ if ((speed*scl - ipb) < bestmatch) {
+ bestmatch = speed*scl - ipb;
+ best_i = i;
+ best_j = j;
+ best_speed = ipb/scl;
+ }
+ }
+ }
+ }
+ divider = (best_i & 3) | ((best_i & 4) << 3) | (best_j << 2);
+ if (gd->flags & GD_FLG_RELOC) {
+ fdr = divider;
+ } else {
+ debug("%ld kHz, \n", best_speed / 1000);
+ return divider;
+ }
+ }
+
+ return fdr;
+}
+
+int i2c_probe (uchar chip)
+{
+ i2c512x_dev_t *regs = &immr->i2c.dev[bus_num];
+ int i;
+
+ for (i = 0; i < I2C_RETRIES; i++) {
+ mpc_reg_out (&regs->mcr, I2C_STA, I2C_STA);
+
+ if (! do_address (chip, 0)) {
+ mpc_reg_out (&regs->mcr, 0, I2C_STA);
+ udelay (500);
+ break;
+ }
+
+ mpc_reg_out (&regs->mcr, 0, I2C_STA);
+ udelay (500);
+ }
+
+ return (i == I2C_RETRIES);
+}
+
+int i2c_read (uchar chip, uint addr, int alen, uchar *buf, int len)
+{
+ char xaddr[4];
+ i2c512x_dev_t *regs = &immr->i2c.dev[bus_num];
+ int ret = -1;
+
+ xaddr[0] = (addr >> 24) & 0xFF;
+ xaddr[1] = (addr >> 16) & 0xFF;
+ xaddr[2] = (addr >> 8) & 0xFF;
+ xaddr[3] = addr & 0xFF;
+
+ if (wait_for_bb ()) {
+ printf ("i2c_read: bus is busy\n");
+ goto Done;
+ }
+
+ mpc_reg_out (&regs->mcr, I2C_STA, I2C_STA);
+ if (do_address (chip, 0)) {
+ printf ("i2c_read: failed to address chip\n");
+ goto Done;
+ }
+
+ if (send_bytes (chip, &xaddr[4-alen], alen)) {
+ printf ("i2c_read: send_bytes failed\n");
+ goto Done;
+ }
+
+ mpc_reg_out (&regs->mcr, I2C_RSTA, I2C_RSTA);
+ if (do_address (chip, 1)) {
+ printf ("i2c_read: failed to address chip\n");
+ goto Done;
+ }
+
+ if (receive_bytes (chip, (char *)buf, len)) {
+ printf ("i2c_read: receive_bytes failed\n");
+ goto Done;
+ }
+
+ ret = 0;
+Done:
+ mpc_reg_out (&regs->mcr, 0, I2C_STA);
+ return ret;
+}
+
+int i2c_write (uchar chip, uint addr, int alen, uchar *buf, int len)
+{
+ char xaddr[4];
+ i2c512x_dev_t *regs = &immr->i2c.dev[bus_num];
+ int ret = -1;
+
+ xaddr[0] = (addr >> 24) & 0xFF;
+ xaddr[1] = (addr >> 16) & 0xFF;
+ xaddr[2] = (addr >> 8) & 0xFF;
+ xaddr[3] = addr & 0xFF;
+
+ if (wait_for_bb ()) {
+ printf ("i2c_write: bus is busy\n");
+ goto Done;
+ }
+
+ mpc_reg_out (&regs->mcr, I2C_STA, I2C_STA);
+ if (do_address (chip, 0)) {
+ printf ("i2c_write: failed to address chip\n");
+ goto Done;
+ }
+
+ if (send_bytes (chip, &xaddr[4-alen], alen)) {
+ printf ("i2c_write: send_bytes failed\n");
+ goto Done;
+ }
+
+ if (send_bytes (chip, (char *)buf, len)) {
+ printf ("i2c_write: send_bytes failed\n");
+ goto Done;
+ }
+
+ ret = 0;
+Done:
+ mpc_reg_out (&regs->mcr, 0, I2C_STA);
+ return ret;
+}
+
+uchar i2c_reg_read (uchar chip, uchar reg)
+{
+ uchar buf;
+
+ i2c_read (chip, reg, 1, &buf, 1);
+
+ return buf;
+}
+
+void i2c_reg_write (uchar chip, uchar reg, uchar val)
+{
+ i2c_write (chip, reg, 1, &val, 1);
+
+ return;
+}
+
+
+int i2c_set_bus_num (unsigned int bus)
+{
+ if (bus >= I2C_BUS_CNT) {
+ return -1;
+ }
+ bus_num = bus;
+
+ return 0;
+}
+
+unsigned int i2c_get_bus_num (void)
+{
+ return bus_num;
+}
+
+/* TODO */
+unsigned int i2c_get_bus_speed (void)
+{
+ return -1;
+}
+
+int i2c_set_bus_speed (unsigned int speed)
+{
+ if (speed != CFG_I2C_SPEED)
+ return -1;
+
+ return 0;
+}
+
+#endif /* CONFIG_HARD_I2C */
diff --git a/cpu/mpc512x/interrupts.c b/cpu/mpc512x/interrupts.c
new file mode 100644
index 0000000..8cc241c
--- /dev/null
+++ b/cpu/mpc512x/interrupts.c
@@ -0,0 +1,61 @@
+/*
+ * (C) Copyright 2000-2007
+ * 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
+ *
+ * Derived from the MPC83xx code.
+ */
+
+#include <common.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct irq_action {
+ interrupt_handler_t *handler;
+ void *arg;
+ ulong count;
+};
+
+int interrupt_init_cpu (unsigned *decrementer_count)
+{
+ *decrementer_count = get_tbclk () / CFG_HZ;
+
+ return 0;
+}
+
+/*
+ * 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;
+}
diff --git a/cpu/mpc512x/serial.c b/cpu/mpc512x/serial.c
new file mode 100644
index 0000000..200ff2c
--- /dev/null
+++ b/cpu/mpc512x/serial.c
@@ -0,0 +1,197 @@
+/*
+ * (C) Copyright 2000 - 2007
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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
+ *
+ * Based ont the MPC5200 PSC driver.
+ * Adapted for MPC512x by Jan Wrobel <wrr@semihalf.com>
+ */
+
+/*
+ * Minimal serial functions needed to use one of the PSC ports
+ * as serial console interface.
+ */
+
+#include <common.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_PSC_CONSOLE)
+
+static void fifo_init (volatile psc512x_t *psc)
+{
+ volatile immap_t *im = (immap_t *) CFG_IMMR;
+
+ /* reset Rx & Tx fifo slice */
+ psc->rfcmd = PSC_FIFO_RESET_SLICE;
+ psc->tfcmd = PSC_FIFO_RESET_SLICE;
+
+ /* disable Tx & Rx FIFO interrupts */
+ psc->rfintmask = 0;
+ psc->tfintmask = 0;
+
+ psc->tfsize = CONSOLE_FIFO_TX_SIZE | (CONSOLE_FIFO_TX_ADDR << 16);
+ psc->rfsize = CONSOLE_FIFO_RX_SIZE | (CONSOLE_FIFO_RX_ADDR << 16);
+
+ /* enable Tx & Rx FIFO slice */
+ psc->rfcmd = PSC_FIFO_ENABLE_SLICE;
+ psc->tfcmd = PSC_FIFO_ENABLE_SLICE;
+
+ im->fifoc.fifoc_cmd = FIFOC_DISABLE_CLOCK_GATE;
+ __asm__ volatile ("sync");
+}
+
+int serial_init(void)
+{
+ volatile immap_t *im = (immap_t *) CFG_IMMR;
+ volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
+ unsigned long baseclk;
+ int div;
+
+ fifo_init (psc);
+
+ /* set MR register to point to MR1 */
+ psc->command = PSC_SEL_MODE_REG_1;
+
+ /* disable Tx/Rx */
+ psc->command = PSC_TX_DISABLE | PSC_RX_DISABLE;
+
+ /* choose the prescaler by 16 for the Tx/Rx clock generation */
+ psc->psc_clock_select = 0xdd00;
+
+ /* switch to UART mode */
+ psc->sicr = 0;
+
+ /* mode register points to mr1 */
+ /* configure parity, bit length and so on in mode register 1*/
+ psc->mode = PSC_MODE_8_BITS | PSC_MODE_PARNONE;
+ /* now, mode register points to mr2 */
+ psc->mode = PSC_MODE_1_STOPBIT;
+
+ /* calculate dividor for setting PSC CTUR and CTLR registers */
+ baseclk = (gd->ipb_clk + 8) / 16;
+ div = (baseclk + (gd->baudrate / 2)) / gd->baudrate;
+
+ psc->ctur = (div >> 8) & 0xff;
+ /* set baudrate */
+ psc->ctlr = div & 0xff;
+
+ /* disable all interrupts */
+ psc->psc_imr = 0;
+
+ /* reset and enable Rx/Tx */
+ psc->command = PSC_RST_RX;
+ psc->command = PSC_RST_TX;
+ psc->command = PSC_RX_ENABLE | PSC_TX_ENABLE;
+
+ return 0;
+}
+
+void serial_putc (const char c)
+{
+ volatile immap_t *im = (immap_t *)CFG_IMMR;
+ volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
+
+ if (c == '\n')
+ serial_putc ('\r');
+
+ /* Wait for last character to go. */
+ while (!(psc->psc_status & PSC_SR_TXEMP))
+ ;
+
+ psc->tfdata_8 = c;
+}
+
+void serial_putc_raw (const char c)
+{
+ volatile immap_t *im = (immap_t *) CFG_IMMR;
+ volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
+
+ /* Wait for last character to go. */
+ while (!(psc->psc_status & PSC_SR_TXEMP))
+ ;
+
+ psc->tfdata_8 = c;
+}
+
+
+void serial_puts (const char *s)
+{
+ while (*s) {
+ serial_putc (*s++);
+ }
+}
+
+int serial_getc (void)
+{
+ volatile immap_t *im = (immap_t *) CFG_IMMR;
+ volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
+
+ /* Wait for a character to arrive. */
+ while (psc->rfstat & PSC_FIFO_EMPTY)
+ ;
+
+ return psc->rfdata_8;
+}
+
+int serial_tstc (void)
+{
+ volatile immap_t *im = (immap_t *) CFG_IMMR;
+ volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
+
+ return !(psc->rfstat & PSC_FIFO_EMPTY);
+}
+
+void serial_setbrg (void)
+{
+ volatile immap_t *im = (immap_t *) CFG_IMMR;
+ volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
+ unsigned long baseclk, div;
+
+ baseclk = (gd->csb_clk + 8) / 16;
+ div = (baseclk + (gd->baudrate / 2)) / gd->baudrate;
+
+ psc->ctur = (div >> 8) & 0xFF;
+ psc->ctlr = div & 0xff; /* set baudrate */
+}
+
+void serial_setrts(int s)
+{
+ volatile immap_t *im = (immap_t *) CFG_IMMR;
+ volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
+
+ if (s) {
+ /* Assert RTS (become LOW) */
+ psc->op1 = 0x1;
+ }
+ else {
+ /* Negate RTS (become HIGH) */
+ psc->op0 = 0x1;
+ }
+}
+
+int serial_getcts(void)
+{
+ volatile immap_t *im = (immap_t *) CFG_IMMR;
+ volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
+
+ return (psc->ip & 0x1) ? 0 : 1;
+}
+#endif /* CONFIG_PSC_CONSOLE */
diff --git a/cpu/mpc512x/speed.c b/cpu/mpc512x/speed.c
new file mode 100644
index 0000000..a609827
--- /dev/null
+++ b/cpu/mpc512x/speed.c
@@ -0,0 +1,135 @@
+/*
+ * (C) Copyright 2000-2007
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright (C) 2004-2006 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
+ *
+ * Based on the MPC83xx code.
+ */
+
+#include <common.h>
+#include <mpc512x.h>
+#include <command.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int spmf_mult[] = {
+ 68, 1, 12, 16,
+ 20, 24, 28, 32,
+ 36, 40, 44, 48,
+ 52, 56, 60, 64
+};
+
+static int cpmf_mult[][2] = {
+ {0, 1}, {0, 1}, /* 0 and 1 are not valid */
+ {1, 1}, {3, 2},
+ {2, 1}, {5, 2},
+ {3, 1}, {7, 2},
+ {0, 1}, {0, 1}, /* and all above 7 are not valid too */
+ {0, 1}, {0, 1},
+ {0, 1}, {0, 1},
+ {0, 1}, {0, 1}
+};
+
+static int sys_dividors[][2] = {
+ {2, 1}, {5, 2}, {3, 1}, {7, 2}, {4, 1},
+ {9, 2}, {5, 1}, {7, 1}, {6, 1}, {8, 1},
+ {9, 1}, {11, 1}, {10, 1}, {12, 1}, {13, 1},
+ {15, 1}, {14, 1}, {16, 1}, {17, 1}, {19, 1},
+ {18, 1}, {20, 1}, {21, 1}, {23, 1}, {22, 1},
+ {24, 1}, {25, 1}, {27, 1}, {26, 1}, {28, 1},
+ {29, 1}, {31, 1}, {30, 1}, {32, 1}, {33, 1}
+};
+
+int get_clocks (void)
+{
+ volatile immap_t *im = (immap_t *) CFG_IMMR;
+ u8 spmf;
+ u8 cpmf;
+ u8 sys_div;
+ u8 ips_div;
+ u32 ref_clk = CFG_MPC512X_CLKIN;
+ u32 spll;
+ u32 sys_clk;
+ u32 core_clk;
+ u32 csb_clk;
+ u32 ips_clk;
+
+ if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32) im)
+ return -1;
+
+ spmf = (im->clk.spmr & SPMR_SPMF) >> SPMR_SPMF_SHIFT;
+ spll = ref_clk * spmf_mult[spmf];
+
+ sys_div = (im->clk.scfr[1] & SCFR2_SYS_DIV) >> SCFR2_SYS_DIV_SHIFT;
+ sys_clk = (spll * sys_dividors[sys_div][1]) / sys_dividors[sys_div][0];
+
+ csb_clk = sys_clk / 2;
+
+ cpmf = (im->clk.spmr & SPMR_CPMF) >> SPMR_CPMF_SHIFT;
+ core_clk = (csb_clk * cpmf_mult[cpmf][0]) / cpmf_mult[cpmf][1];
+
+ ips_div = (im->clk.scfr[0] & SCFR1_IPS_DIV_MASK) >> SCFR1_IPS_DIV_SHIFT;
+ if (ips_div != 0) {
+ ips_clk = csb_clk / ips_div;
+ } else {
+ /* in case we cannot get a sane IPS divisor, fail gracefully */
+ ips_clk = 0;
+ }
+
+ gd->ipb_clk = ips_clk;
+ gd->csb_clk = csb_clk;
+ gd->cpu_clk = core_clk;
+ gd->bus_clk = csb_clk;
+ return 0;
+
+}
+
+/********************************************
+ * get_bus_freq
+ * return system bus freq in Hz
+ *********************************************/
+ulong get_bus_freq (ulong dummy)
+{
+ return gd->csb_clk;
+}
+
+int do_clocks (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+ printf ("Clock configuration:\n");
+ printf (" CPU: %4d MHz\n", gd->cpu_clk / 1000000);
+ printf (" Coherent System Bus: %4d MHz\n", gd->csb_clk / 1000000);
+ printf (" IPS Bus: %4d MHz\n", gd->ipb_clk / 1000000);
+ printf (" DDR: %4d MHz\n", 2 * gd->csb_clk / 1000000);
+ return 0;
+}
+
+U_BOOT_CMD(clocks, 1, 0, do_clocks,
+ "clocks - print clock configuration\n",
+ " clocks\n"
+);
+
+int prt_mpc512x_clks (void)
+{
+ do_clocks (NULL, 0, 0, NULL);
+ return (0);
+}
diff --git a/cpu/mpc512x/start.S b/cpu/mpc512x/start.S
new file mode 100644
index 0000000..244c69b
--- /dev/null
+++ b/cpu/mpc512x/start.S
@@ -0,0 +1,780 @@
+/*
+ * 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, 2007 Wolfgang Denk <wd@denx.de>
+ * Copyright Freescale Semiconductor, Inc. 2004, 2006. All rights reserved.
+ *
+ * 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
+ *
+ * Based on the MPC83xx code.
+ */
+
+/*
+ * U-Boot - Startup Code for MPC512x based Embedded Boards
+ */
+
+#include <config.h>
+#include <mpc512x.h>
+#include <version.h>
+
+#define CONFIG_521X 1 /* needed for Linux kernel header files*/
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#ifndef CONFIG_IDENT_STRING
+#define CONFIG_IDENT_STRING "MPC512X"
+#endif
+
+/*
+ * Floating Point enable, Machine Check and Recoverable Interr.
+ */
+#undef MSR_KERNEL
+#ifdef DEBUG
+#define MSR_KERNEL (MSR_FP|MSR_RI)
+#else
+#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
+#endif
+
+/* Macros for manipulating CSx_START/STOP */
+#define START_REG(start) ((start) >> 16)
+#define STOP_REG(start, size) (((start) + (size) - 1) >> 16)
+
+/*
+ * 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
+
+/*
+ * Magic number and version string
+ */
+ .long 0x27051956 /* U-Boot Magic Number */
+ .globl version_string
+version_string:
+ .ascii U_BOOT_VERSION
+ .ascii " (", __DATE__, " - ", __TIME__, ")"
+ .ascii " ", CONFIG_IDENT_STRING, "\0"
+
+/*
+ * Vector Table
+ */
+ .text
+ . = EXC_OFF_SYS_RESET
+
+ .globl _start
+ /* Start from here after reset/power on */
+_start:
+ li r21, BOOTFLAG_COLD /* Normal Power-On: Boot from FLASH */
+ b boot_cold
+
+ .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. */
+ STD_EXCEPTION(0x500, ExtInterrupt, UnknownException)
+
+/* Alignment exception. */
+ . = 0x600
+Alignment:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ 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(SRR0, SRR1)
+ 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
+
+/* Floating Point Unit unavailable exception */
+ STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+/* Decrementer */
+ STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+
+/* Critical interrupt */
+ STD_EXCEPTION(0xa00, Critical, UnknownException)
+
+/* System Call */
+ STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+
+/* Trace interrupt */
+ STD_EXCEPTION(0xd00, Trace, UnknownException)
+
+/* Performance Monitor interrupt */
+ STD_EXCEPTION(0xf00, PerfMon, UnknownException)
+
+/* Intruction Translation Miss */
+ STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
+
+/* Data Load Translation Miss */
+ STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
+
+/* Data Store Translation Miss */
+ STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
+
+/* Instruction Address Breakpoint */
+ STD_EXCEPTION(0x1300, InstructionAddrBreakpoint, DebugException)
+
+/* System Management interrupt */
+ STD_EXCEPTION(0x1400, SystemMgmtInterrupt, UnknownException)
+
+ .globl _end_of_vectors
+_end_of_vectors:
+
+ . = 0x3000
+boot_cold:
+ /* Save msr contents */
+ mfmsr r5
+
+ /* Set IMMR area to our preferred location */
+ lis r4, CONFIG_DEFAULT_IMMR@h
+ lis r3, CFG_IMMR@h
+ ori r3, r3, CFG_IMMR@l
+ stw r3, IMMRBAR(r4)
+ mtspr MBAR, r3 /* IMMRBAR is mirrored into the MBAR SPR (311) */
+
+ /* Initialise the machine */
+ bl cpu_early_init
+
+ /*
+ * Set up Local Access Windows:
+ *
+ * 1) Boot/CS0 (boot FLASH)
+ * 2) On-chip SRAM (initial stack purposes)
+ */
+
+ /* Boot CS/CS0 window range */
+ lis r3, CFG_IMMR@h
+ ori r3, r3, CFG_IMMR@l
+
+ lis r4, START_REG(CFG_FLASH_BASE)
+ ori r4, r4, STOP_REG(CFG_FLASH_BASE, CFG_FLASH_SIZE)
+ stw r4, LPCS0AW(r3)
+
+ /*
+ * The SRAM window has a fixed size (256K), so only the start address
+ * is necessary
+ */
+ lis r4, START_REG(CFG_SRAM_BASE) & 0xff00
+ stw r4, SRAMBAR(r3)
+
+ /*
+ * According to MPC5121e RM, configuring local access windows should
+ * be followed by a dummy read of the config register that was
+ * modified last and an isync
+ */
+ lwz r4, SRAMBAR(r3)
+ isync
+
+ /*
+ * Set configuration of the Boot/CS0, the SRAM window does not have a
+ * config register so no params can be set for it
+ */
+ lis r3, (CFG_IMMR + LPC_OFFSET)@h
+ ori r3, r3, (CFG_IMMR + LPC_OFFSET)@l
+
+ lis r4, CFG_CS0_CFG@h
+ ori r4, r4, CFG_CS0_CFG@l
+ stw r4, CS0_CONFIG(r3)
+
+ /* Master enable all CS's */
+ lis r4, CS_CTRL_ME@h
+ ori r4, r4, CS_CTRL_ME@l
+ stw r4, CS_CTRL(r3)
+
+ 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:
+ 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 */
+
+ /* 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_IMMR@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
+
+ /* NOTREACHED - board_init_f() does not return */
+
+/*
+ * 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 machine, it expects original MSR contents to be in r5.
+ */
+cpu_early_init:
+ /* 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 */
+#ifdef DEBUG
+ rlwimi r3, r5, 0, 21, 22 /* debugger might set SE, BE bits */
+#endif
+ mtmsr r3
+ SYNC
+ mtspr SRR1, r3 /* Mirror current MSR state in SRR1 */
+
+ lis r3, CFG_IMMR@h
+
+#if defined(CONFIG_WATCHDOG)
+ /* Initialise the watchdog and reset it */
+ /*--------------------------------------*/
+ lis r4, CFG_WATCHDOG_VALUE
+ ori r4, r4, (SWCRR_SWEN | SWCRR_SWRI | SWCRR_SWPR)
+ stw r4, SWCRR(r3)
+
+ /* reset */
+ li r4, 0x556C
+ sth r4, SWSRR@l(r3)
+ li r4, 0x0
+ ori r4, r4, 0xAA39
+ sth r4, SWSRR@l(r3)
+#else
+ /* Disable the watchdog */
+ /*----------------------*/
+ lwz r4, SWCRR(r3)
+ /*
+ * Check to see if it's enabled for disabling: once disabled by s/w
+ * it's not possible to re-enable it
+ */
+ andi. r4, r4, 0x4
+ beq 1f
+ xor r4, r4, r4
+ stw r4, SWCRR(r3)
+1:
+#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
+ sync
+ 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, (31 - HID0_ICE_SHIFT + 1), 31, 31
+ blr
+
+ .globl dcache_enable
+dcache_enable:
+ mfspr r3, HID0
+ li r5, HID0_DCFI|HID0_DLOCK
+ andc r3, r3, r5
+ mtspr HID0, r3 /* no invalidate, unlock */
+ ori r3, r3, HID0_DCE
+ ori r5, r3, HID0_DCFI
+ mtspr HID0, r5 /* enable + invalidate */
+ mtspr HID0, r3 /* enable */
+ sync
+ blr
+
+ .globl dcache_disable
+dcache_disable:
+ mfspr r3, HID0
+ lis r4, 0
+ ori r4, r4, HID0_DCE|HID0_DLOCK
+ andc r3, r3, r4
+ ori r4, r3, HID0_DCI
+ 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, (31 - HID0_DCE_SHIFT + 1), 31, 31
+ blr
+
+ .globl get_pvr
+get_pvr:
+ mfspr r3, PVR
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: ppcDcbf */
+/* Description: Data Cache block flush */
+/* Input: r3 = effective address */
+/* Output: none. */
+/*------------------------------------------------------------------------------- */
+ .globl ppcDcbf
+ppcDcbf:
+ dcbf r0,r3
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: ppcDcbi */
+/* Description: Data Cache block Invalidate */
+/* Input: r3 = effective address */
+/* Output: none. */
+/*------------------------------------------------------------------------------- */
+ .globl ppcDcbi
+ppcDcbi:
+ dcbi r0,r3
+ blr
+
+/*--------------------------------------------------------------------------
+ * Function: ppcDcbz
+ * Description: Data Cache block zero.
+ * Input: r3 = effective address
+ * Output: none.
+ *-------------------------------------------------------------------------- */
+
+ .globl ppcDcbz
+ppcDcbz:
+ dcbz r0,r3
+ blr
+
+ .globl ppcDWstore
+ppcDWstore:
+ lfd 1, 0(r4)
+ stfd 1, 0(r3)
+ blr
+
+ .globl ppcDWload
+ppcDWload:
+ lfd 1, 0(r3)
+ stfd 1, 0(r4)
+ 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: cmpwi r6,0
+ add r5,r3,r5
+ beq 7f /* Always flush prefetch queue in any case */
+ subi r0,r6,1
+ andc r3,r3,r0
+ 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 */
+ 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)
+ lwz r4,GOT(_end)
+
+ 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 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_Trace - _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
diff --git a/cpu/mpc512x/traps.c b/cpu/mpc512x/traps.c
new file mode 100644
index 0000000..8455c92
--- /dev/null
+++ b/cpu/mpc512x/traps.c
@@ -0,0 +1,205 @@
+/*
+ * (C) Copyright 2000 - 2007
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * 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
+ *
+ * Derived from the MPC83xx code.
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware
+ * exceptions
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+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)
+{
+ 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 at pc %lx signal %d", regs->nip,signr);
+}
+
+
+void
+MachineCheckException (struct pt_regs *regs)
+{
+ unsigned long fixup;
+
+ if ((fixup = search_exception_table (regs->nip)) != 0) {
+ regs->nip = fixup;
+ return;
+ }
+
+#ifdef CONFIG_CMD_KGDB
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ puts ("Machine check.\nCaused by (from msr): ");
+ printf ("regs %p ",regs);
+ switch (regs->msr & 0x00FF0000) {
+ case (0x80000000 >> 10):
+ puts ("Instruction cache parity signal\n");
+ break;
+ case (0x80000000 >> 11):
+ puts ("Data cache parity signal\n");
+ break;
+ case (0x80000000 >> 12):
+ puts ("Machine check signal\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]);
+
+ panic ("machine check");
+}
+
+void
+AlignmentException (struct pt_regs *regs)
+{
+#ifdef CONFIG_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)
+{
+#ifdef CONFIG_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)
+{
+#ifdef CONFIG_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)
+{
+#ifdef CONFIG_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);
+}
+
+#ifdef CONFIG_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);
+#ifdef CONFIG_CMD_BEDBUG
+ do_bedbug_breakpoint (regs);
+#endif
+}
diff --git a/cpu/mpc5xx/config.mk b/cpu/mpc5xx/config.mk
index 5b26a76..e95b8a1 100644
--- a/cpu/mpc5xx/config.mk
+++ b/cpu/mpc5xx/config.mk
@@ -28,6 +28,9 @@
#
-PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi
+PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi -mrelocatable
PLATFORM_CPPFLAGS += -DCONFIG_5xx -ffixed-r2 -ffixed-r29 -mpowerpc -msoft-float
+
+# Use default linker script. Board port can override in board/*/config.mk
+LDSCRIPT := $(SRCTREE)/cpu/mpc5xx/u-boot.lds
diff --git a/cpu/mpc5xx/interrupts.c b/cpu/mpc5xx/interrupts.c
index 7f6e136..a4f47c7 100644
--- a/cpu/mpc5xx/interrupts.c
+++ b/cpu/mpc5xx/interrupts.c
@@ -178,7 +178,7 @@ void timer_interrupt_cpu (struct pt_regs *regs)
return;
}
-#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
+#if defined(CONFIG_CMD_IRQ)
/*******************************************************************************
*
* irqinfo - print information about IRQs
@@ -204,4 +204,4 @@ int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
}
-#endif /* CONFIG_COMMANDS & CFG_CMD_IRQ */
+#endif
diff --git a/cpu/mpc5xx/traps.c b/cpu/mpc5xx/traps.c
index 14fd59e..d22b89a 100644
--- a/cpu/mpc5xx/traps.c
+++ b/cpu/mpc5xx/traps.c
@@ -36,11 +36,11 @@
#include <command.h>
#include <asm/processor.h>
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
int (*debugger_exception_handler)(struct pt_regs *) = 0;
#endif
-#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+#if defined(CONFIG_CMD_BEDBUG)
extern void do_bedbug_breakpoint(struct pt_regs *);
#endif
@@ -131,7 +131,7 @@ void MachineCheckException(struct pt_regs *regs)
return;
}
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -165,7 +165,7 @@ void MachineCheckException(struct pt_regs *regs)
*/
void AlignmentException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -179,7 +179,7 @@ void AlignmentException(struct pt_regs *regs)
*/
void ProgramCheckException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -193,7 +193,7 @@ void ProgramCheckException(struct pt_regs *regs)
*/
void SoftEmuException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -208,7 +208,7 @@ void SoftEmuException(struct pt_regs *regs)
*/
void UnknownException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -224,7 +224,7 @@ void DebugException(struct pt_regs *regs)
{
printf("Debugger trap at @ %lx\n", regs->nip );
show_regs(regs);
-#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+#if defined(CONFIG_CMD_BEDBUG)
do_bedbug_breakpoint( regs );
#endif
}
diff --git a/cpu/mpc5xx/u-boot.lds b/cpu/mpc5xx/u-boot.lds
new file mode 100644
index 0000000..10001b1
--- /dev/null
+++ b/cpu/mpc5xx/u-boot.lds
@@ -0,0 +1,139 @@
+/*
+ * (C) Copyright 2001 Wolfgang Denk, DENX Software Engineering, wd@denx.de
+ * (C) Copyright 2003 Martin Winistoerfer, martinwinistoerfer@gmx.ch
+ *
+ * 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
+ */
+
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ /* WARNING - the following is hand-optimized to fit within */
+ /* the sector layout of our flash chips! XXX FIXME XXX */
+
+ cpu/mpc5xx/start.o (.text)
+
+ *(.text)
+ *(.got1)
+ }
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(.rodata)
+ *(.rodata1)
+ *(.rodata.str1.4)
+ *(.eh_frame)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+ __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+
+ _end = . ;
+ PROVIDE (end = .);
+/* . = env_start;
+ .ppcenv :
+ {
+ common/environment.o (.ppcenv)
+ }
+*/
+}
diff --git a/cpu/mpc5xxx/Makefile b/cpu/mpc5xxx/Makefile
index 235adb7..312b0bf 100644
--- a/cpu/mpc5xxx/Makefile
+++ b/cpu/mpc5xxx/Makefile
@@ -28,7 +28,7 @@ LIB = $(obj)lib$(CPU).a
START = start.o
SOBJS = io.o firmware_sc_task_bestcomm.impl.o firmware_sc_task.impl.o
COBJS = i2c.o traps.o cpu.o cpu_init.o fec.o ide.o interrupts.o \
- loadtask.o pci_mpc5200.o serial.o speed.o usb_ohci.o
+ loadtask.o pci_mpc5200.o serial.o speed.o usb_ohci.o usb.o
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
diff --git a/cpu/mpc5xxx/config.mk b/cpu/mpc5xxx/config.mk
index ecd94e9..0e861c4 100644
--- a/cpu/mpc5xxx/config.mk
+++ b/cpu/mpc5xxx/config.mk
@@ -21,7 +21,10 @@
# MA 02111-1307 USA
#
-PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi
+PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi -mrelocatable
PLATFORM_CPPFLAGS += -DCONFIG_MPC5xxx -ffixed-r2 -ffixed-r29 \
-mstring -mcpu=603e -mmultiple
+
+# Use default linker script. Board port can override in board/*/config.mk
+LDSCRIPT := $(SRCTREE)/cpu/mpc5xxx/u-boot.lds
diff --git a/cpu/mpc5xxx/cpu_init.c b/cpu/mpc5xxx/cpu_init.c
index d744030..bc6201e 100644
--- a/cpu/mpc5xxx/cpu_init.c
+++ b/cpu/mpc5xxx/cpu_init.c
@@ -198,7 +198,7 @@ int cpu_init_r (void)
/* route critical ints to normal ints */
*(vu_long *)MPC5XXX_ICTL_EXT |= 0x00000001;
-#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_MPC5xxx_FEC)
+#if defined(CONFIG_CMD_NET) && defined(CONFIG_MPC5xxx_FEC)
/* load FEC microcode */
loadtask(0, 2);
#endif
diff --git a/cpu/mpc5xxx/fec.c b/cpu/mpc5xxx/fec.c
index 3d99d5c..1d3da77 100644
--- a/cpu/mpc5xxx/fec.c
+++ b/cpu/mpc5xxx/fec.c
@@ -18,10 +18,10 @@ DECLARE_GLOBAL_DATA_PTR;
/* #define DEBUG 0x28 */
-#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
+#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
defined(CONFIG_MPC5xxx_FEC)
-#if !(defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII))
+#if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
#error "CONFIG_MII has to be defined!"
#endif
@@ -890,7 +890,7 @@ int mpc5xxx_fec_initialize(bd_t * bis)
fec->tbdBase = (FEC_TBD *)FEC_BD_BASE;
fec->rbdBase = (FEC_RBD *)(FEC_BD_BASE + FEC_TBD_NUM * sizeof(FEC_TBD));
#if defined(CONFIG_CANMB) || \
- defined(CONFIG_CM1_QP1) || \
+ defined(CONFIG_CM5200) || \
defined(CONFIG_HMI1001) || \
defined(CONFIG_ICECUBE) || \
defined(CONFIG_INKA4X0) || \
@@ -924,7 +924,7 @@ int mpc5xxx_fec_initialize(bd_t * bis)
sprintf(dev->name, "FEC ETHERNET");
eth_register(dev);
-#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
miiphy_register (dev->name,
fec5xxx_miiphy_read, fec5xxx_miiphy_write);
#endif
diff --git a/cpu/mpc5xxx/ide.c b/cpu/mpc5xxx/ide.c
index 29b99f6..087ddac 100644
--- a/cpu/mpc5xxx/ide.c
+++ b/cpu/mpc5xxx/ide.c
@@ -24,7 +24,7 @@
*/
#include <common.h>
-#ifdef CFG_CMD_IDE
+#if defined(CONFIG_CMD_IDE)
#include <mpc5xxx.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -85,4 +85,4 @@ int ide_preinit (void)
return (0);
}
-#endif /* CFG_CMD_IDE */
+#endif
diff --git a/cpu/mpc5xxx/interrupts.c b/cpu/mpc5xxx/interrupts.c
index beeb222..8816dd1 100644
--- a/cpu/mpc5xxx/interrupts.c
+++ b/cpu/mpc5xxx/interrupts.c
@@ -310,7 +310,7 @@ void irq_free_handler(int irq)
/****************************************************************************/
-#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
+#if defined(CONFIG_CMD_IRQ)
void do_irqinfo(cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char *argv[])
{
int irq, re_enable;
diff --git a/cpu/mpc5xxx/traps.c b/cpu/mpc5xxx/traps.c
index 2ee782b..daa1ec6 100644
--- a/cpu/mpc5xxx/traps.c
+++ b/cpu/mpc5xxx/traps.c
@@ -37,7 +37,7 @@
#include <command.h>
#include <asm/processor.h>
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
int (*debugger_exception_handler)(struct pt_regs *) = 0;
#endif
@@ -123,7 +123,7 @@ MachineCheckException(struct pt_regs *regs)
return;
}
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -158,7 +158,7 @@ MachineCheckException(struct pt_regs *regs)
void
AlignmentException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -170,7 +170,7 @@ AlignmentException(struct pt_regs *regs)
void
ProgramCheckException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -182,7 +182,7 @@ ProgramCheckException(struct pt_regs *regs)
void
SoftEmuException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -195,7 +195,7 @@ SoftEmuException(struct pt_regs *regs)
void
UnknownException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -204,7 +204,7 @@ UnknownException(struct pt_regs *regs)
_exception(0, regs);
}
-#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+#if defined(CONFIG_CMD_BEDBUG)
extern void do_bedbug_breakpoint(struct pt_regs *);
#endif
@@ -214,7 +214,7 @@ DebugException(struct pt_regs *regs)
printf("Debugger trap at @ %lx\n", regs->nip );
show_regs(regs);
-#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+#if defined(CONFIG_CMD_BEDBUG)
do_bedbug_breakpoint( regs );
#endif
}
diff --git a/cpu/mpc5xxx/u-boot-customlayout.lds b/cpu/mpc5xxx/u-boot-customlayout.lds
new file mode 100644
index 0000000..1107943
--- /dev/null
+++ b/cpu/mpc5xxx/u-boot-customlayout.lds
@@ -0,0 +1,135 @@
+/*
+ * (C) Copyright 2003-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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
+ */
+
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ /* WARNING - the following is hand-optimized to fit within */
+ /* the sector layout of our flash chips! XXX FIXME XXX */
+
+ cpu/mpc5xxx/start.o (.text)
+ cpu/mpc5xxx/traps.o (.text)
+ lib_generic/crc32.o (.text)
+ lib_ppc/cache.o (.text)
+ lib_ppc/time.o (.text)
+
+ . = DEFINED(env_offset) ? env_offset : .;
+ common/environment.o (.ppcenv)
+
+ *(.text)
+ *(.got1)
+ . = ALIGN(16);
+ *(.rodata)
+ *(.rodata1)
+ *(.rodata.str1.4)
+ *(.eh_frame)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x0FFF) & 0xFFFFF000;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+ __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(4096);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(4096);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ _end = . ;
+ PROVIDE (end = .);
+}
diff --git a/cpu/mpc5xxx/u-boot.lds b/cpu/mpc5xxx/u-boot.lds
new file mode 100644
index 0000000..a28a3af
--- /dev/null
+++ b/cpu/mpc5xxx/u-boot.lds
@@ -0,0 +1,124 @@
+/*
+ * (C) Copyright 2003-2007
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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
+ */
+
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ cpu/mpc5xxx/start.o (.text)
+ *(.text)
+ *(.got1)
+ . = ALIGN(16);
+ *(.rodata)
+ *(.rodata1)
+ *(.rodata.str1.4)
+ *(.eh_frame)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x0FFF) & 0xFFFFF000;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+ __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(4096);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(4096);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ _end = . ;
+ PROVIDE (end = .);
+}
diff --git a/cpu/mpc5xxx/usb.c b/cpu/mpc5xxx/usb.c
new file mode 100644
index 0000000..ce709fc
--- /dev/null
+++ b/cpu/mpc5xxx/usb.c
@@ -0,0 +1,54 @@
+/*
+ * (C) Copyright 2007
+ * Markus Klotzbuecher, DENX Software Engineering <mk@denx.de>
+ *
+ * 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 <common.h>
+
+#if defined(CONFIG_USB_OHCI_NEW) && defined(CFG_USB_OHCI_CPU_INIT)
+
+#include <mpc5xxx.h>
+
+int usb_cpu_init()
+{
+ /* Set the USB Clock */
+ *(vu_long *)MPC5XXX_CDM_48_FDC = CONFIG_USB_CLOCK;
+
+ /* remove all USB bits first before ORing in ours */
+ *(vu_long *)MPC5XXX_GPS_PORT_CONFIG &= ~0x00807000;
+
+ /* Activate USB port */
+ *(vu_long *)MPC5XXX_GPS_PORT_CONFIG |= CONFIG_USB_CONFIG;
+
+ return 0;
+}
+
+int usb_cpu_stop()
+{
+ return 0;
+}
+
+int usb_cpu_init_fail()
+{
+ return 0;
+}
+
+#endif /* defined(CONFIG_USB_OHCI) && defined(CFG_USB_OHCI_CPU_INIT) */
diff --git a/cpu/mpc8220/config.mk b/cpu/mpc8220/config.mk
index 6fec5df..c41cafe 100644
--- a/cpu/mpc8220/config.mk
+++ b/cpu/mpc8220/config.mk
@@ -21,7 +21,10 @@
# MA 02111-1307 USA
#
-PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi
+PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi -mrelocatable
PLATFORM_CPPFLAGS += -DCONFIG_MPC8220 -ffixed-r2 -ffixed-r29 \
-mstring -mcpu=603e -mmultiple
+
+# Use default linker script. Board port can override in board/*/config.mk
+LDSCRIPT := $(SRCTREE)/cpu/mpc8220/u-boot.lds
diff --git a/cpu/mpc8220/cpu_init.c b/cpu/mpc8220/cpu_init.c
index 3cf5f66..0daac5b 100644
--- a/cpu/mpc8220/cpu_init.c
+++ b/cpu/mpc8220/cpu_init.c
@@ -128,7 +128,7 @@ int cpu_init_r (void)
/* route critical ints to normal ints */
*(vu_long *) 0xf0000710 |= 0x00000001;
-#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_MPC8220_FEC)
+#if defined(CONFIG_CMD_NET) && defined(CONFIG_MPC8220_FEC)
/* load FEC microcode */
loadtask (0, 2);
#endif
diff --git a/cpu/mpc8220/fec.c b/cpu/mpc8220/fec.c
index 1201e79..992e0ff 100644
--- a/cpu/mpc8220/fec.c
+++ b/cpu/mpc8220/fec.c
@@ -15,10 +15,10 @@
#include "fec.h"
#undef DEBUG
-#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
+#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
defined(CONFIG_MPC8220_FEC)
-#if !(defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII))
+#if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
#error "CONFIG_MII has to be defined!"
#endif
@@ -847,7 +847,7 @@ int mpc8220_fec_initialize (bd_t * bis)
sprintf (dev->name, "FEC ETHERNET");
eth_register (dev);
-#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
miiphy_register (dev->name,
fec8220_miiphy_read, fec8220_miiphy_write);
#endif
diff --git a/cpu/mpc8220/traps.c b/cpu/mpc8220/traps.c
index cdee2be..89cca1d 100644
--- a/cpu/mpc8220/traps.c
+++ b/cpu/mpc8220/traps.c
@@ -37,7 +37,7 @@
#include <command.h>
#include <asm/processor.h>
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
int (*debugger_exception_handler) (struct pt_regs *) = 0;
#endif
@@ -118,7 +118,7 @@ void MachineCheckException (struct pt_regs *regs)
regs->nip = fixup;
return;
}
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler
&& (*debugger_exception_handler) (regs))
return;
@@ -152,7 +152,7 @@ void MachineCheckException (struct pt_regs *regs)
void AlignmentException (struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler
&& (*debugger_exception_handler) (regs))
return;
@@ -164,7 +164,7 @@ void AlignmentException (struct pt_regs *regs)
void ProgramCheckException (struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler
&& (*debugger_exception_handler) (regs))
return;
@@ -176,7 +176,7 @@ void ProgramCheckException (struct pt_regs *regs)
void SoftEmuException (struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler
&& (*debugger_exception_handler) (regs))
return;
@@ -189,7 +189,7 @@ void SoftEmuException (struct pt_regs *regs)
void UnknownException (struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler
&& (*debugger_exception_handler) (regs))
return;
@@ -199,7 +199,7 @@ void UnknownException (struct pt_regs *regs)
_exception (0, regs);
}
-#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+#if defined(CONFIG_CMD_BEDBUG)
extern void do_bedbug_breakpoint (struct pt_regs *);
#endif
@@ -208,7 +208,7 @@ void DebugException (struct pt_regs *regs)
printf ("Debugger trap at @ %lx\n", regs->nip);
show_regs (regs);
-#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+#if defined(CONFIG_CMD_BEDBUG)
do_bedbug_breakpoint (regs);
#endif
}
diff --git a/cpu/mpc8220/u-boot.lds b/cpu/mpc8220/u-boot.lds
new file mode 100644
index 0000000..a199a64
--- /dev/null
+++ b/cpu/mpc8220/u-boot.lds
@@ -0,0 +1,124 @@
+/*
+ * (C) Copyright 2003-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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
+ */
+
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ cpu/mpc8220/start.o (.text)
+ *(.text)
+ *(.got1)
+ . = ALIGN(16);
+ *(.rodata)
+ *(.rodata1)
+ *(.rodata.str1.4)
+ *(.eh_frame)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x0FFF) & 0xFFFFF000;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+ __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(4096);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(4096);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ _end = . ;
+ PROVIDE (end = .);
+}
diff --git a/cpu/mpc824x/config.mk b/cpu/mpc824x/config.mk
index dac61d8..17fdb21 100644
--- a/cpu/mpc824x/config.mk
+++ b/cpu/mpc824x/config.mk
@@ -21,6 +21,9 @@
# MA 02111-1307 USA
#
-PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi -fno-strict-aliasing
+PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi -fno-strict-aliasing -mrelocatable
PLATFORM_CPPFLAGS += -DCONFIG_MPC824X -ffixed-r2 -ffixed-r29 -mstring -mcpu=603e -msoft-float
+
+# Use default linker script. Board port can override in board/*/config.mk
+LDSCRIPT := $(SRCTREE)/cpu/mpc824x/u-boot.lds
diff --git a/cpu/mpc824x/traps.c b/cpu/mpc824x/traps.c
index 071d003..0a72430 100644
--- a/cpu/mpc824x/traps.c
+++ b/cpu/mpc824x/traps.c
@@ -175,7 +175,7 @@ UnknownException(struct pt_regs *regs)
_exception(0, regs);
}
-#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+#if defined(CONFIG_CMD_BEDBUG)
extern void do_bedbug_breakpoint(struct pt_regs *);
#endif
@@ -185,7 +185,7 @@ DebugException(struct pt_regs *regs)
printf("Debugger trap at @ %lx\n", regs->nip );
show_regs(regs);
-#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+#if defined(CONFIG_CMD_BEDBUG)
do_bedbug_breakpoint( regs );
#endif
}
diff --git a/cpu/mpc824x/u-boot.lds b/cpu/mpc824x/u-boot.lds
new file mode 100644
index 0000000..8cbef4a
--- /dev/null
+++ b/cpu/mpc824x/u-boot.lds
@@ -0,0 +1,124 @@
+/*
+ * (C) Copyright 2001-2007
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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
+ */
+
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ cpu/mpc824x/start.o (.text)
+ *(.text)
+ *(.got1)
+ . = ALIGN(16);
+ *(.rodata)
+ *(.rodata1)
+ *(.rodata.str1.4)
+ *(.eh_frame)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x0FFF) & 0xFFFFF000;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+ __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(4096);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(4096);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ _end = . ;
+ PROVIDE (end = .);
+}
diff --git a/cpu/mpc8260/bedbug_603e.c b/cpu/mpc8260/bedbug_603e.c
index be09cfb..f1be485 100644
--- a/cpu/mpc8260/bedbug_603e.c
+++ b/cpu/mpc8260/bedbug_603e.c
@@ -10,7 +10,8 @@
#include <bedbug/regs.h>
#include <bedbug/ppc.h>
-#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG) && (defined(CONFIG_MPC824X) || defined(CONFIG_MPC8260))
+#if defined(CONFIG_CMD_BEDBUG) \
+ && (defined(CONFIG_MPC824X) || defined(CONFIG_MPC8260))
#define MAX_BREAK_POINTS 1
diff --git a/cpu/mpc8260/config.mk b/cpu/mpc8260/config.mk
index dd7a71f..d401e4c 100644
--- a/cpu/mpc8260/config.mk
+++ b/cpu/mpc8260/config.mk
@@ -21,7 +21,10 @@
# MA 02111-1307 USA
#
-PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi
+PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi -mrelocatable
PLATFORM_CPPFLAGS += -DCONFIG_8260 -DCONFIG_CPM2 -ffixed-r2 -ffixed-r29 \
-mstring -mcpu=603e -mmultiple
+
+# Use default linker script. Board port can override in board/*/config.mk
+LDSCRIPT := $(SRCTREE)/cpu/mpc8260/u-boot.lds
diff --git a/cpu/mpc8260/cpu_init.c b/cpu/mpc8260/cpu_init.c
index 380d7af..36fc1eb 100644
--- a/cpu/mpc8260/cpu_init.c
+++ b/cpu/mpc8260/cpu_init.c
@@ -182,7 +182,7 @@ void cpu_init_f (volatile immap_t * immr)
#endif
/* now restrict to preliminary range */
- /* the PS came from the HRCW, don´t change it */
+ /* the PS came from the HRCW, don´t change it */
memctl->memc_br0 = SET_VAL_MASK(memctl->memc_br0 , CFG_BR0_PRELIM, BRx_PS_MSK);
memctl->memc_or0 = CFG_OR0_PRELIM;
diff --git a/cpu/mpc8260/ether_fcc.c b/cpu/mpc8260/ether_fcc.c
index 584c40f..37bf445 100644
--- a/cpu/mpc8260/ether_fcc.c
+++ b/cpu/mpc8260/ether_fcc.c
@@ -47,13 +47,13 @@
#include <config.h>
#include <net.h>
-#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
#include <miiphy.h>
#endif
DECLARE_GLOBAL_DATA_PTR;
-#if defined(CONFIG_ETHER_ON_FCC) && (CONFIG_COMMANDS & CFG_CMD_NET) && \
+#if defined(CONFIG_ETHER_ON_FCC) && defined(CONFIG_CMD_NET) && \
defined(CONFIG_NET_MULTI)
static struct ether_fcc_info_s
@@ -393,7 +393,7 @@ int fec_initialize(bd_t *bis)
eth_register(dev);
-#if (defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)) \
+#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) \
&& defined(CONFIG_BITBANGMII)
miiphy_register(dev->name,
bb_miiphy_read, bb_miiphy_write);
@@ -1187,4 +1187,4 @@ eth_loopback_test (void)
#endif /* CONFIG_ETHER_LOOPBACK_TEST */
-#endif /* CONFIG_ETHER_ON_FCC && CFG_CMD_NET && CONFIG_NET_MULTI */
+#endif
diff --git a/cpu/mpc8260/ether_scc.c b/cpu/mpc8260/ether_scc.c
index a733b45..e56839d 100644
--- a/cpu/mpc8260/ether_scc.c
+++ b/cpu/mpc8260/ether_scc.c
@@ -36,7 +36,7 @@
#include <command.h>
#include <config.h>
-#if defined(CONFIG_ETHER_ON_SCC) && (CONFIG_COMMANDS & CFG_CMD_NET)
+#if defined(CONFIG_ETHER_ON_SCC) && defined(CONFIG_CMD_NET)
#if (CONFIG_ETHER_INDEX == 1)
# define PROFF_ENET PROFF_SCC1
@@ -353,4 +353,4 @@ void restart(void)
}
#endif
-#endif /* CONFIG_ETHER_ON_SCC && CFG_CMD_NET */
+#endif
diff --git a/cpu/mpc8260/interrupts.c b/cpu/mpc8260/interrupts.c
index 56e9a72..bf0d4d0 100644
--- a/cpu/mpc8260/interrupts.c
+++ b/cpu/mpc8260/interrupts.c
@@ -246,7 +246,7 @@ void timer_interrupt_cpu (struct pt_regs *regs)
/****************************************************************************/
-#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
+#if defined(CONFIG_CMD_IRQ)
/* ripped this out of ppc4xx/interrupts.c */
@@ -276,4 +276,4 @@ do_irqinfo (cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char *argv[])
enable_interrupts ();
}
-#endif /* CONFIG_COMMANDS & CFG_CMD_IRQ */
+#endif
diff --git a/cpu/mpc8260/kgdb.S b/cpu/mpc8260/kgdb.S
index 2a25024..dae87bb 100644
--- a/cpu/mpc8260/kgdb.S
+++ b/cpu/mpc8260/kgdb.S
@@ -34,7 +34,7 @@
#include <asm/cache.h>
#include <asm/mmu.h>
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
/*
* cache flushing routines for kgdb
@@ -69,4 +69,4 @@ kgdb_flush_cache_range:
SYNC
blr
-#endif /* CFG_CMD_KGDB */
+#endif
diff --git a/cpu/mpc8260/traps.c b/cpu/mpc8260/traps.c
index 0c39e43..b5d416c 100644
--- a/cpu/mpc8260/traps.c
+++ b/cpu/mpc8260/traps.c
@@ -37,7 +37,7 @@
#include <asm/processor.h>
#include <asm/m8260_pci.h>
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
int (*debugger_exception_handler)(struct pt_regs *) = 0;
#endif
@@ -150,7 +150,7 @@ MachineCheckException(struct pt_regs *regs)
return;
}
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -186,7 +186,7 @@ MachineCheckException(struct pt_regs *regs)
void
AlignmentException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -198,7 +198,7 @@ AlignmentException(struct pt_regs *regs)
void
ProgramCheckException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -210,7 +210,7 @@ ProgramCheckException(struct pt_regs *regs)
void
SoftEmuException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -223,7 +223,7 @@ SoftEmuException(struct pt_regs *regs)
void
UnknownException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -232,7 +232,7 @@ UnknownException(struct pt_regs *regs)
_exception(0, regs);
}
-#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+#if defined(CONFIG_CMD_BEDBUG)
extern void do_bedbug_breakpoint(struct pt_regs *);
#endif
@@ -242,7 +242,7 @@ DebugException(struct pt_regs *regs)
printf("Debugger trap at @ %lx\n", regs->nip );
show_regs(regs);
-#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+#if defined(CONFIG_CMD_BEDBUG)
do_bedbug_breakpoint( regs );
#endif
}
diff --git a/cpu/mpc8260/u-boot.lds b/cpu/mpc8260/u-boot.lds
new file mode 100644
index 0000000..b8abc17
--- /dev/null
+++ b/cpu/mpc8260/u-boot.lds
@@ -0,0 +1,124 @@
+/*
+ * (C) Copyright 2001-2007
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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
+ */
+
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ cpu/mpc8260/start.o (.text)
+ *(.text)
+ *(.got1)
+ . = ALIGN(16);
+ *(.rodata)
+ *(.rodata1)
+ *(.rodata.str1.4)
+ *(.eh_frame)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x0FFF) & 0xFFFFF000;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+ __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(4096);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(4096);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ _end = . ;
+ PROVIDE (end = .);
+}
diff --git a/cpu/mpc83xx/Makefile b/cpu/mpc83xx/Makefile
index bb96f77..2329970 100644
--- a/cpu/mpc83xx/Makefile
+++ b/cpu/mpc83xx/Makefile
@@ -29,7 +29,7 @@ LIB = $(obj)lib$(CPU).a
START = start.o
COBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o \
- spd_sdram.o qe_io.o pci.o
+ spd_sdram.o ecc.o qe_io.o pci.o
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
diff --git a/cpu/mpc83xx/config.mk b/cpu/mpc83xx/config.mk
index 8b4ff92..2ec395d 100644
--- a/cpu/mpc83xx/config.mk
+++ b/cpu/mpc83xx/config.mk
@@ -20,7 +20,10 @@
# MA 02111-1307 USA
#
-PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi
+PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi -mrelocatable
PLATFORM_CPPFLAGS += -DCONFIG_MPC83XX -DCONFIG_E300 \
-ffixed-r2 -ffixed-r29 -msoft-float
+
+# Use default linker script. Board port can override in board/*/config.mk
+LDSCRIPT := $(SRCTREE)/cpu/mpc83xx/u-boot.lds
diff --git a/cpu/mpc83xx/cpu.c b/cpu/mpc83xx/cpu.c
index 841fe82..adf8083 100644
--- a/cpu/mpc83xx/cpu.c
+++ b/cpu/mpc83xx/cpu.c
@@ -33,8 +33,7 @@
#include <asm/processor.h>
#if defined(CONFIG_OF_FLAT_TREE)
#include <ft_build.h>
-#endif
-#if defined(CONFIG_OF_LIBFDT)
+#elif defined(CONFIG_OF_LIBFDT)
#include <libfdt.h>
#include <libfdt_env.h>
#endif
@@ -113,12 +112,14 @@ int checkcpu(void)
case SPR_8360E_REV11:
case SPR_8360E_REV12:
case SPR_8360E_REV20:
+ case SPR_8360E_REV21:
puts("MPC8360E, ");
break;
case SPR_8360_REV10:
case SPR_8360_REV11:
case SPR_8360_REV12:
case SPR_8360_REV20:
+ case SPR_8360_REV21:
puts("MPC8360, ");
break;
case SPR_8323E_REV10:
@@ -150,7 +151,8 @@ int checkcpu(void)
puts("MPC8313E, ");
break;
default:
- puts("Rev: Unknown revision number.\nWarning: Unsupported cpu revision!\n");
+ printf("Rev: Unknown revision number:%08x\n"
+ "Warning: Unsupported cpu revision!\n",spridr);
return 0;
}
@@ -329,154 +331,167 @@ void watchdog_reset (void)
/*
* "Setter" functions used to add/modify FDT entries.
*/
-static int fdt_set_eth0(void *fdt, int nodeoffset, const char *name, bd_t *bd)
+static int fdt_set_eth0(void *blob, int nodeoffset, const char *name, bd_t *bd)
{
/*
* Fix it up if it exists, don't create it if it doesn't exist.
*/
- if (fdt_get_property(fdt, nodeoffset, name, 0)) {
- return fdt_setprop(fdt, nodeoffset, name, bd->bi_enetaddr, 6);
+ if (fdt_get_property(blob, nodeoffset, name, 0)) {
+ return fdt_setprop(blob, nodeoffset, name, bd->bi_enetaddr, 6);
}
- return -FDT_ERR_NOTFOUND;
+ return 0;
}
#ifdef CONFIG_HAS_ETH1
/* second onboard ethernet port */
-static int fdt_set_eth1(void *fdt, int nodeoffset, const char *name, bd_t *bd)
+static int fdt_set_eth1(void *blob, int nodeoffset, const char *name, bd_t *bd)
{
/*
* Fix it up if it exists, don't create it if it doesn't exist.
*/
- if (fdt_get_property(fdt, nodeoffset, name, 0)) {
- return fdt_setprop(fdt, nodeoffset, name, bd->bi_enet1addr, 6);
+ if (fdt_get_property(blob, nodeoffset, name, 0)) {
+ return fdt_setprop(blob, nodeoffset, name, bd->bi_enet1addr, 6);
}
- return -FDT_ERR_NOTFOUND;
+ return 0;
}
#endif
#ifdef CONFIG_HAS_ETH2
/* third onboard ethernet port */
-static int fdt_set_eth2(void *fdt, int nodeoffset, const char *name, bd_t *bd)
+static int fdt_set_eth2(void *blob, int nodeoffset, const char *name, bd_t *bd)
{
/*
* Fix it up if it exists, don't create it if it doesn't exist.
*/
- if (fdt_get_property(fdt, nodeoffset, name, 0)) {
- return fdt_setprop(fdt, nodeoffset, name, bd->bi_enet2addr, 6);
+ if (fdt_get_property(blob, nodeoffset, name, 0)) {
+ return fdt_setprop(blob, nodeoffset, name, bd->bi_enet2addr, 6);
}
- return -FDT_ERR_NOTFOUND;
+ return 0;
}
#endif
#ifdef CONFIG_HAS_ETH3
/* fourth onboard ethernet port */
-static int fdt_set_eth3(void *fdt, int nodeoffset, const char *name, bd_t *bd)
+static int fdt_set_eth3(void *blob, int nodeoffset, const char *name, bd_t *bd)
{
/*
* Fix it up if it exists, don't create it if it doesn't exist.
*/
- if (fdt_get_property(fdt, nodeoffset, name, 0)) {
- return fdt_setprop(fdt, nodeoffset, name, bd->bi_enet3addr, 6);
+ if (fdt_get_property(blob, nodeoffset, name, 0)) {
+ return fdt_setprop(blob, nodeoffset, name, bd->bi_enet3addr, 6);
}
- return -FDT_ERR_NOTFOUND;
+ return 0;
}
#endif
-static int fdt_set_busfreq(void *fdt, int nodeoffset, const char *name, bd_t *bd)
+static int fdt_set_busfreq(void *blob, int nodeoffset, const char *name, bd_t *bd)
{
u32 tmp;
/*
* Create or update the property.
*/
tmp = cpu_to_be32(bd->bi_busfreq);
- return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+ return fdt_setprop(blob, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+static int fdt_set_tbfreq(void *blob, int nodeoffset, const char *name, bd_t *bd)
+{
+ u32 tmp;
+ /*
+ * Create or update the property.
+ */
+ tmp = cpu_to_be32(OF_TBCLK);
+ return fdt_setprop(blob, nodeoffset, name, &tmp, sizeof(tmp));
}
+
/*
- * Fixups to the fdt. If "create" is TRUE, the node is created
- * unconditionally. If "create" is FALSE, the node is updated
- * only if it already exists.
+ * Fixups to the fdt.
*/
static const struct {
char *node;
char *prop;
- int (*set_fn)(void *fdt, int nodeoffset, const char *name, bd_t *bd);
+ int (*set_fn)(void *blob, int nodeoffset, const char *name, bd_t *bd);
} fixup_props[] = {
{ "/cpus/" OF_CPU,
- "bus-frequency",
- fdt_set_busfreq
+ "timebase-frequency",
+ fdt_set_tbfreq
},
- { "/cpus/" OF_SOC,
+ { "/cpus/" OF_CPU,
"bus-frequency",
fdt_set_busfreq
},
- { "/" OF_SOC "/serial@4500/",
+ { "/cpus/" OF_CPU,
+ "clock-frequency",
+ fdt_set_busfreq
+ },
+ { "/" OF_SOC "/serial@4500",
"clock-frequency",
fdt_set_busfreq
},
- { "/" OF_SOC "/serial@4600/",
+ { "/" OF_SOC "/serial@4600",
"clock-frequency",
fdt_set_busfreq
},
#ifdef CONFIG_TSEC1
- { "/" OF_SOC "/ethernet@24000,
+ { "/" OF_SOC "/ethernet@24000",
"mac-address",
fdt_set_eth0
},
- { "/" OF_SOC "/ethernet@24000,
+ { "/" OF_SOC "/ethernet@24000",
"local-mac-address",
fdt_set_eth0
},
#endif
#ifdef CONFIG_TSEC2
- { "/" OF_SOC "/ethernet@25000,
+ { "/" OF_SOC "/ethernet@25000",
"mac-address",
fdt_set_eth1
},
- { "/" OF_SOC "/ethernet@25000,
+ { "/" OF_SOC "/ethernet@25000",
"local-mac-address",
fdt_set_eth1
},
#endif
#ifdef CONFIG_UEC_ETH1
#if CFG_UEC1_UCC_NUM == 0 /* UCC1 */
- { "/" OF_QE "/ucc@2000/mac-address",
+ { "/" OF_QE "/ucc@2000",
"mac-address",
fdt_set_eth0
},
- { "/" OF_QE "/ucc@2000/mac-address",
+ { "/" OF_QE "/ucc@2000",
"local-mac-address",
fdt_set_eth0
},
#elif CFG_UEC1_UCC_NUM == 2 /* UCC3 */
- { "/" OF_QE "/ucc@2200/mac-address",
+ { "/" OF_QE "/ucc@2200",
"mac-address",
fdt_set_eth0
},
- { "/" OF_QE "/ucc@2200/mac-address",
+ { "/" OF_QE "/ucc@2200",
"local-mac-address",
fdt_set_eth0
},
#endif
-#endif
+#endif /* CONFIG_UEC_ETH1 */
#ifdef CONFIG_UEC_ETH2
#if CFG_UEC2_UCC_NUM == 1 /* UCC2 */
- { "/" OF_QE "/ucc@3000/mac-address",
+ { "/" OF_QE "/ucc@3000",
"mac-address",
fdt_set_eth1
},
- { "/" OF_QE "/ucc@3000/mac-address",
+ { "/" OF_QE "/ucc@3000",
"local-mac-address",
fdt_set_eth1
},
#elif CFG_UEC1_UCC_NUM == 3 /* UCC4 */
- { "/" OF_QE "/ucc@3200/mac-address",
+ { "/" OF_QE "/ucc@3200",
"mac-address",
fdt_set_eth1
},
- { "/" OF_QE "/ucc@3200/mac-address",
+ { "/" OF_QE "/ucc@3200",
"local-mac-address",
fdt_set_eth1
},
#endif
-#endif
+#endif /* CONFIG_UEC_ETH2 */
};
void
@@ -487,20 +502,23 @@ ft_cpu_setup(void *blob, bd_t *bd)
int j;
for (j = 0; j < (sizeof(fixup_props) / sizeof(fixup_props[0])); j++) {
- nodeoffset = fdt_path_offset(fdt, fixup_props[j].node);
+ nodeoffset = fdt_find_node_by_path(blob, fixup_props[j].node);
if (nodeoffset >= 0) {
- err = (*fixup_props[j].set_fn)(blob, nodeoffset, fixup_props[j].prop, bd);
+ err = fixup_props[j].set_fn(blob, nodeoffset,
+ fixup_props[j].prop, bd);
if (err < 0)
- printf("set_fn/libfdt: %s %s returned %s\n",
+ debug("Problem setting %s = %s: %s\n",
fixup_props[j].node,
fixup_props[j].prop,
fdt_strerror(err));
+ } else {
+ debug("Couldn't find %s: %s\n",
+ fixup_props[j].node,
+ fdt_strerror(nodeoffset));
}
}
}
-#endif
-
-#if defined(CONFIG_OF_FLAT_TREE)
+#elif defined(CONFIG_OF_FLAT_TREE)
void
ft_cpu_setup(void *blob, bd_t *bd)
{
diff --git a/cpu/mpc83xx/cpu_init.c b/cpu/mpc83xx/cpu_init.c
index 3ac9161..7224979 100644
--- a/cpu/mpc83xx/cpu_init.c
+++ b/cpu/mpc83xx/cpu_init.c
@@ -83,20 +83,30 @@ void cpu_init_f (volatile immap_t * im)
im->sysconf.spcr = (im->sysconf.spcr & ~SPCR_TSEC2EP) | (CFG_SPCR_TSEC2EP << SPCR_TSEC2EP_SHIFT);
#endif
-#ifdef CONFIG_MPC834X
#ifdef CFG_SCCR_TSEC1CM
/* TSEC1 clock mode */
im->clk.sccr = (im->clk.sccr & ~SCCR_TSEC1CM) | (CFG_SCCR_TSEC1CM << SCCR_TSEC1CM_SHIFT);
#endif
+
#ifdef CFG_SCCR_TSEC2CM
/* TSEC2 & I2C1 clock mode */
im->clk.sccr = (im->clk.sccr & ~SCCR_TSEC2CM) | (CFG_SCCR_TSEC2CM << SCCR_TSEC2CM_SHIFT);
#endif
+
+#ifdef CFG_SCCR_TSEC1ON
+ /* TSEC1 clock switch */
+ im->clk.sccr = (im->clk.sccr & ~SCCR_TSEC1ON) | (CFG_SCCR_TSEC1ON << SCCR_TSEC1ON_SHIFT);
+#endif
+
+#ifdef CFG_SCCR_TSEC2ON
+ /* TSEC2 clock switch */
+ im->clk.sccr = (im->clk.sccr & ~SCCR_TSEC2ON) | (CFG_SCCR_TSEC2ON << SCCR_TSEC2ON_SHIFT);
+#endif
+
#ifdef CFG_SCCR_USBMPHCM
/* USB MPH clock mode */
im->clk.sccr = (im->clk.sccr & ~SCCR_USBMPHCM) | (CFG_SCCR_USBMPHCM << SCCR_USBMPHCM_SHIFT);
#endif
-#endif /* CONFIG_MPC834X */
#ifdef CFG_SCCR_PCICM
/* PCI & DMA clock mode */
@@ -247,3 +257,39 @@ int cpu_init_r (void)
#endif
return 0;
}
+
+/*
+ * Figure out the cause of the reset
+ */
+int prt_83xx_rsr(void)
+{
+ static struct {
+ ulong mask;
+ char *desc;
+ } bits[] = {
+ {
+ RSR_SWSR, "Software Soft"}, {
+ RSR_SWHR, "Software Hard"}, {
+ RSR_JSRS, "JTAG Soft"}, {
+ RSR_CSHR, "Check Stop"}, {
+ RSR_SWRS, "Software Watchdog"}, {
+ RSR_BMRS, "Bus Monitor"}, {
+ RSR_SRS, "External/Internal Soft"}, {
+ RSR_HRS, "External/Internal Hard"}
+ };
+ static int n = sizeof bits / sizeof bits[0];
+ ulong rsr = gd->reset_status;
+ int i;
+ char *sep;
+
+ puts("Reset Status:");
+
+ sep = " ";
+ for (i = 0; i < n; i++)
+ if (rsr & bits[i].mask) {
+ printf("%s%s", sep, bits[i].desc);
+ sep = ", ";
+ }
+ puts("\n\n");
+ return 0;
+}
diff --git a/cpu/mpc83xx/ecc.c b/cpu/mpc83xx/ecc.c
new file mode 100644
index 0000000..6f13094
--- /dev/null
+++ b/cpu/mpc83xx/ecc.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2007 Freescale Semiconductor, Inc.
+ *
+ * Dave Liu <daveliu@freescale.com>
+ * based on the contribution of Marian Balakowicz <m8@semihalf.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.
+ */
+
+#include <common.h>
+#include <mpc83xx.h>
+#include <command.h>
+
+#if defined(CONFIG_DDR_ECC) && defined(CONFIG_DDR_ECC_CMD)
+void ecc_print_status(void)
+{
+ volatile immap_t *immap = (immap_t *) CFG_IMMR;
+ volatile ddr83xx_t *ddr = &immap->ddr;
+
+ printf("\nECC mode: %s\n\n",
+ (ddr->sdram_cfg & SDRAM_CFG_ECC_EN) ? "ON" : "OFF");
+
+ /* Interrupts */
+ printf("Memory Error Interrupt Enable:\n");
+ printf(" Multiple-Bit Error Interrupt Enable: %d\n",
+ (ddr->err_int_en & ECC_ERR_INT_EN_MBEE) ? 1 : 0);
+ printf(" Single-Bit Error Interrupt Enable: %d\n",
+ (ddr->err_int_en & ECC_ERR_INT_EN_SBEE) ? 1 : 0);
+ printf(" Memory Select Error Interrupt Enable: %d\n\n",
+ (ddr->err_int_en & ECC_ERR_INT_EN_MSEE) ? 1 : 0);
+
+ /* Error disable */
+ printf("Memory Error Disable:\n");
+ printf(" Multiple-Bit Error Disable: %d\n",
+ (ddr->err_disable & ECC_ERROR_DISABLE_MBED) ? 1 : 0);
+ printf(" Sinle-Bit Error Disable: %d\n",
+ (ddr->err_disable & ECC_ERROR_DISABLE_SBED) ? 1 : 0);
+ printf(" Memory Select Error Disable: %d\n\n",
+ (ddr->err_disable & ECC_ERROR_DISABLE_MSED) ? 1 : 0);
+
+ /* Error injection */
+ printf("Memory Data Path Error Injection Mask High/Low: %08lx %08lx\n",
+ ddr->data_err_inject_hi, ddr->data_err_inject_lo);
+
+ printf("Memory Data Path Error Injection Mask ECC:\n");
+ printf(" ECC Mirror Byte: %d\n",
+ (ddr->ecc_err_inject & ECC_ERR_INJECT_EMB) ? 1 : 0);
+ printf(" ECC Injection Enable: %d\n",
+ (ddr->ecc_err_inject & ECC_ERR_INJECT_EIEN) ? 1 : 0);
+ printf(" ECC Error Injection Mask: 0x%02x\n\n",
+ ddr->ecc_err_inject & ECC_ERR_INJECT_EEIM);
+
+ /* SBE counter/threshold */
+ printf("Memory Single-Bit Error Management (0..255):\n");
+ printf(" Single-Bit Error Threshold: %d\n",
+ (ddr->err_sbe & ECC_ERROR_MAN_SBET) >> ECC_ERROR_MAN_SBET_SHIFT);
+ printf(" Single-Bit Error Counter: %d\n\n",
+ (ddr->err_sbe & ECC_ERROR_MAN_SBEC) >> ECC_ERROR_MAN_SBEC_SHIFT);
+
+ /* Error detect */
+ printf("Memory Error Detect:\n");
+ printf(" Multiple Memory Errors: %d\n",
+ (ddr->err_detect & ECC_ERROR_DETECT_MME) ? 1 : 0);
+ printf(" Multiple-Bit Error: %d\n",
+ (ddr->err_detect & ECC_ERROR_DETECT_MBE) ? 1 : 0);
+ printf(" Single-Bit Error: %d\n",
+ (ddr->err_detect & ECC_ERROR_DETECT_SBE) ? 1 : 0);
+ printf(" Memory Select Error: %d\n\n",
+ (ddr->err_detect & ECC_ERROR_DETECT_MSE) ? 1 : 0);
+
+ /* Capture data */
+ printf("Memory Error Address Capture: 0x%08lx\n", ddr->capture_address);
+ printf("Memory Data Path Read Capture High/Low: %08lx %08lx\n",
+ ddr->capture_data_hi, ddr->capture_data_lo);
+ printf("Memory Data Path Read Capture ECC: 0x%02x\n\n",
+ ddr->capture_ecc & CAPTURE_ECC_ECE);
+
+ printf("Memory Error Attributes Capture:\n");
+ printf(" Data Beat Number: %d\n",
+ (ddr->capture_attributes & ECC_CAPT_ATTR_BNUM) >>
+ ECC_CAPT_ATTR_BNUM_SHIFT);
+ printf(" Transaction Size: %d\n",
+ (ddr->capture_attributes & ECC_CAPT_ATTR_TSIZ) >>
+ ECC_CAPT_ATTR_TSIZ_SHIFT);
+ printf(" Transaction Source: %d\n",
+ (ddr->capture_attributes & ECC_CAPT_ATTR_TSRC) >>
+ ECC_CAPT_ATTR_TSRC_SHIFT);
+ printf(" Transaction Type: %d\n",
+ (ddr->capture_attributes & ECC_CAPT_ATTR_TTYP) >>
+ ECC_CAPT_ATTR_TTYP_SHIFT);
+ printf(" Error Information Valid: %d\n\n",
+ ddr->capture_attributes & ECC_CAPT_ATTR_VLD);
+}
+
+int do_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+ volatile immap_t *immap = (immap_t *) CFG_IMMR;
+ volatile ddr83xx_t *ddr = &immap->ddr;
+ volatile u32 val;
+ u64 *addr;
+ u32 count;
+ register u64 *i;
+ u32 ret[2];
+ u32 pattern[2];
+ u32 writeback[2];
+
+ /* The pattern is written into memory to generate error */
+ pattern[0] = 0xfedcba98UL;
+ pattern[1] = 0x76543210UL;
+
+ /* After injecting error, re-initialize the memory with the value */
+ writeback[0] = 0x01234567UL;
+ writeback[1] = 0x89abcdefUL;
+
+ if (argc > 4) {
+ printf("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+ }
+
+ if (argc == 2) {
+ if (strcmp(argv[1], "status") == 0) {
+ ecc_print_status();
+ return 0;
+ } else if (strcmp(argv[1], "captureclear") == 0) {
+ ddr->capture_address = 0;
+ ddr->capture_data_hi = 0;
+ ddr->capture_data_lo = 0;
+ ddr->capture_ecc = 0;
+ ddr->capture_attributes = 0;
+ return 0;
+ }
+ }
+ if (argc == 3) {
+ if (strcmp(argv[1], "sbecnt") == 0) {
+ val = simple_strtoul(argv[2], NULL, 10);
+ if (val > 255) {
+ printf("Incorrect Counter value, "
+ "should be 0..255\n");
+ return 1;
+ }
+
+ val = (val << ECC_ERROR_MAN_SBEC_SHIFT);
+ val |= (ddr->err_sbe & ECC_ERROR_MAN_SBET);
+
+ ddr->err_sbe = val;
+ return 0;
+ } else if (strcmp(argv[1], "sbethr") == 0) {
+ val = simple_strtoul(argv[2], NULL, 10);
+ if (val > 255) {
+ printf("Incorrect Counter value, "
+ "should be 0..255\n");
+ return 1;
+ }
+
+ val = (val << ECC_ERROR_MAN_SBET_SHIFT);
+ val |= (ddr->err_sbe & ECC_ERROR_MAN_SBEC);
+
+ ddr->err_sbe = val;
+ return 0;
+ } else if (strcmp(argv[1], "errdisable") == 0) {
+ val = ddr->err_disable;
+
+ if (strcmp(argv[2], "+sbe") == 0) {
+ val |= ECC_ERROR_DISABLE_SBED;
+ } else if (strcmp(argv[2], "+mbe") == 0) {
+ val |= ECC_ERROR_DISABLE_MBED;
+ } else if (strcmp(argv[2], "+mse") == 0) {
+ val |= ECC_ERROR_DISABLE_MSED;
+ } else if (strcmp(argv[2], "+all") == 0) {
+ val |= (ECC_ERROR_DISABLE_SBED |
+ ECC_ERROR_DISABLE_MBED |
+ ECC_ERROR_DISABLE_MSED);
+ } else if (strcmp(argv[2], "-sbe") == 0) {
+ val &= ~ECC_ERROR_DISABLE_SBED;
+ } else if (strcmp(argv[2], "-mbe") == 0) {
+ val &= ~ECC_ERROR_DISABLE_MBED;
+ } else if (strcmp(argv[2], "-mse") == 0) {
+ val &= ~ECC_ERROR_DISABLE_MSED;
+ } else if (strcmp(argv[2], "-all") == 0) {
+ val &= ~(ECC_ERROR_DISABLE_SBED |
+ ECC_ERROR_DISABLE_MBED |
+ ECC_ERROR_DISABLE_MSED);
+ } else {
+ printf("Incorrect err_disable field\n");
+ return 1;
+ }
+
+ ddr->err_disable = val;
+ __asm__ __volatile__("sync");
+ __asm__ __volatile__("isync");
+ return 0;
+ } else if (strcmp(argv[1], "errdetectclr") == 0) {
+ val = ddr->err_detect;
+
+ if (strcmp(argv[2], "mme") == 0) {
+ val |= ECC_ERROR_DETECT_MME;
+ } else if (strcmp(argv[2], "sbe") == 0) {
+ val |= ECC_ERROR_DETECT_SBE;
+ } else if (strcmp(argv[2], "mbe") == 0) {
+ val |= ECC_ERROR_DETECT_MBE;
+ } else if (strcmp(argv[2], "mse") == 0) {
+ val |= ECC_ERROR_DETECT_MSE;
+ } else if (strcmp(argv[2], "all") == 0) {
+ val |= (ECC_ERROR_DETECT_MME |
+ ECC_ERROR_DETECT_MBE |
+ ECC_ERROR_DETECT_SBE |
+ ECC_ERROR_DETECT_MSE);
+ } else {
+ printf("Incorrect err_detect field\n");
+ return 1;
+ }
+
+ ddr->err_detect = val;
+ return 0;
+ } else if (strcmp(argv[1], "injectdatahi") == 0) {
+ val = simple_strtoul(argv[2], NULL, 16);
+
+ ddr->data_err_inject_hi = val;
+ return 0;
+ } else if (strcmp(argv[1], "injectdatalo") == 0) {
+ val = simple_strtoul(argv[2], NULL, 16);
+
+ ddr->data_err_inject_lo = val;
+ return 0;
+ } else if (strcmp(argv[1], "injectecc") == 0) {
+ val = simple_strtoul(argv[2], NULL, 16);
+ if (val > 0xff) {
+ printf("Incorrect ECC inject mask, "
+ "should be 0x00..0xff\n");
+ return 1;
+ }
+ val |= (ddr->ecc_err_inject & ~ECC_ERR_INJECT_EEIM);
+
+ ddr->ecc_err_inject = val;
+ return 0;
+ } else if (strcmp(argv[1], "inject") == 0) {
+ val = ddr->ecc_err_inject;
+
+ if (strcmp(argv[2], "en") == 0)
+ val |= ECC_ERR_INJECT_EIEN;
+ else if (strcmp(argv[2], "dis") == 0)
+ val &= ~ECC_ERR_INJECT_EIEN;
+ else
+ printf("Incorrect command\n");
+
+ ddr->ecc_err_inject = val;
+ __asm__ __volatile__("sync");
+ __asm__ __volatile__("isync");
+ return 0;
+ } else if (strcmp(argv[1], "mirror") == 0) {
+ val = ddr->ecc_err_inject;
+
+ if (strcmp(argv[2], "en") == 0)
+ val |= ECC_ERR_INJECT_EMB;
+ else if (strcmp(argv[2], "dis") == 0)
+ val &= ~ECC_ERR_INJECT_EMB;
+ else
+ printf("Incorrect command\n");
+
+ ddr->ecc_err_inject = val;
+ return 0;
+ }
+ }
+ if (argc == 4) {
+ if (strcmp(argv[1], "testdw") == 0) {
+ addr = (u64 *) simple_strtoul(argv[2], NULL, 16);
+ count = simple_strtoul(argv[3], NULL, 16);
+
+ if ((u32) addr % 8) {
+ printf("Address not alligned on "
+ "double word boundary\n");
+ return 1;
+ }
+ disable_interrupts();
+
+ for (i = addr; i < addr + count; i++) {
+
+ /* enable injects */
+ ddr->ecc_err_inject |= ECC_ERR_INJECT_EIEN;
+ __asm__ __volatile__("sync");
+ __asm__ __volatile__("isync");
+
+ /* write memory location injecting errors */
+ ppcDWstore((u32 *) i, pattern);
+ __asm__ __volatile__("sync");
+
+ /* disable injects */
+ ddr->ecc_err_inject &= ~ECC_ERR_INJECT_EIEN;
+ __asm__ __volatile__("sync");
+ __asm__ __volatile__("isync");
+
+ /* read data, this generates ECC error */
+ ppcDWload((u32 *) i, ret);
+ __asm__ __volatile__("sync");
+
+ /* re-initialize memory, double word write the location again,
+ * generates new ECC code this time */
+ ppcDWstore((u32 *) i, writeback);
+ __asm__ __volatile__("sync");
+ }
+ enable_interrupts();
+ return 0;
+ }
+ if (strcmp(argv[1], "testword") == 0) {
+ addr = (u64 *) simple_strtoul(argv[2], NULL, 16);
+ count = simple_strtoul(argv[3], NULL, 16);
+
+ if ((u32) addr % 8) {
+ printf("Address not alligned on "
+ "double word boundary\n");
+ return 1;
+ }
+ disable_interrupts();
+
+ for (i = addr; i < addr + count; i++) {
+
+ /* enable injects */
+ ddr->ecc_err_inject |= ECC_ERR_INJECT_EIEN;
+ __asm__ __volatile__("sync");
+ __asm__ __volatile__("isync");
+
+ /* write memory location injecting errors */
+ *(u32 *) i = 0xfedcba98UL;
+ __asm__ __volatile__("sync");
+
+ /* sub double word write,
+ * bus will read-modify-write,
+ * generates ECC error */
+ *((u32 *) i + 1) = 0x76543210UL;
+ __asm__ __volatile__("sync");
+
+ /* disable injects */
+ ddr->ecc_err_inject &= ~ECC_ERR_INJECT_EIEN;
+ __asm__ __volatile__("sync");
+ __asm__ __volatile__("isync");
+
+ /* re-initialize memory,
+ * double word write the location again,
+ * generates new ECC code this time */
+ ppcDWstore((u32 *) i, writeback);
+ __asm__ __volatile__("sync");
+ }
+ enable_interrupts();
+ return 0;
+ }
+ }
+ printf("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+}
+
+U_BOOT_CMD(ecc, 4, 0, do_ecc,
+ "ecc - support for DDR ECC features\n",
+ "status - print out status info\n"
+ "ecc captureclear - clear capture regs data\n"
+ "ecc sbecnt <val> - set Single-Bit Error counter\n"
+ "ecc sbethr <val> - set Single-Bit Threshold\n"
+ "ecc errdisable <flag> - clear/set disable Memory Error Disable, flag:\n"
+ " [-|+]sbe - Single-Bit Error\n"
+ " [-|+]mbe - Multiple-Bit Error\n"
+ " [-|+]mse - Memory Select Error\n"
+ " [-|+]all - all errors\n"
+ "ecc errdetectclr <flag> - clear Memory Error Detect, flag:\n"
+ " mme - Multiple Memory Errors\n"
+ " sbe - Single-Bit Error\n"
+ " mbe - Multiple-Bit Error\n"
+ " mse - Memory Select Error\n"
+ " all - all errors\n"
+ "ecc injectdatahi <hi> - set Memory Data Path Error Injection Mask High\n"
+ "ecc injectdatalo <lo> - set Memory Data Path Error Injection Mask Low\n"
+ "ecc injectecc <ecc> - set ECC Error Injection Mask\n"
+ "ecc inject <en|dis> - enable/disable error injection\n"
+ "ecc mirror <en|dis> - enable/disable mirror byte\n"
+ "ecc testdw <addr> <cnt> - test mem region with double word access:\n"
+ " - enables injects\n"
+ " - writes pattern injecting errors with double word access\n"
+ " - disables injects\n"
+ " - reads pattern back with double word access, generates error\n"
+ " - re-inits memory\n"
+ "ecc testword <addr> <cnt> - test mem region with word access:\n"
+ " - enables injects\n"
+ " - writes pattern injecting errors with word access\n"
+ " - writes pattern with word access, generates error\n"
+ " - disables injects\n" " - re-inits memory");
+#endif
diff --git a/cpu/mpc83xx/interrupts.c b/cpu/mpc83xx/interrupts.c
index bb1fe1a..98ed21c 100644
--- a/cpu/mpc83xx/interrupts.c
+++ b/cpu/mpc83xx/interrupts.c
@@ -81,7 +81,7 @@ void timer_interrupt_cpu (struct pt_regs *regs)
}
-#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
+#if defined(CONFIG_CMD_IRQ)
/* ripped this out of ppc4xx/interrupts.c */
@@ -94,4 +94,4 @@ do_irqinfo(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
}
-#endif /* CONFIG_COMMANDS & CFG_CMD_IRQ */
+#endif
diff --git a/cpu/mpc83xx/pci.c b/cpu/mpc83xx/pci.c
index 785d612..2298218 100644
--- a/cpu/mpc83xx/pci.c
+++ b/cpu/mpc83xx/pci.c
@@ -25,7 +25,14 @@
#include <common.h>
#include <pci.h>
+
+#if defined(CONFIG_OF_LIBFDT)
+#include <libfdt.h>
+#include <libfdt_env.h>
+#elif defined(CONFIG_OF_FLAT_TREE)
#include <ft_build.h>
+#endif
+
#include <asm/mpc8349_pci.h>
#ifdef CONFIG_83XX_GENERIC_PCI
@@ -163,7 +170,34 @@ void mpc83xx_pci_init(int num_buses, struct pci_region **reg, int warmboot)
pci_init_bus(i, reg[i]);
}
-#ifdef CONFIG_OF_FLAT_TREE
+#if defined(CONFIG_OF_LIBFDT)
+void ft_pci_setup(void *blob, bd_t *bd)
+{
+ int nodeoffset;
+ int err;
+ int tmp[2];
+
+ if (pci_num_buses < 1)
+ return;
+
+ nodeoffset = fdt_find_node_by_path(blob, "/" OF_SOC "/pci@8500");
+ if (nodeoffset >= 0) {
+ tmp[0] = cpu_to_be32(pci_hose[0].first_busno);
+ tmp[1] = cpu_to_be32(pci_hose[0].last_busno);
+ err = fdt_setprop(blob, nodeoffset, "bus-range", tmp, sizeof(tmp));
+ }
+
+ if (pci_num_buses < 2)
+ return;
+
+ nodeoffset = fdt_find_node_by_path(blob, "/" OF_SOC "/pci@8600");
+ if (nodeoffset >= 0) {
+ tmp[0] = cpu_to_be32(pci_hose[0].first_busno);
+ tmp[1] = cpu_to_be32(pci_hose[0].last_busno);
+ err = fdt_setprop(blob, nodeoffset, "bus-range", tmp, sizeof(tmp));
+ }
+}
+#elif CONFIG_OF_FLAT_TREE
void ft_pci_setup(void *blob, bd_t *bd)
{
u32 *p;
diff --git a/cpu/mpc83xx/spd_sdram.c b/cpu/mpc83xx/spd_sdram.c
index 647813f..54f0c83 100644
--- a/cpu/mpc83xx/spd_sdram.c
+++ b/cpu/mpc83xx/spd_sdram.c
@@ -574,7 +574,10 @@ long int spd_sdram()
/* Check DIMM data bus width */
if (spd.dataw_lsb == 0x20) {
- burstlen = 0x03; /* 32 bit data bus, burst len is 8 */
+ if (spd.mem_type == SPD_MEMTYPE_DDR)
+ burstlen = 0x03; /* 32 bit data bus, burst len is 8 */
+ else
+ burstlen = 0x02; /* 32 bit data bus, burst len is 4 */
printf("\n DDR DIMM: data bus width is 32 bit");
} else {
burstlen = 0x02; /* Others act as 64 bit bus, burst len is 4 */
@@ -730,8 +733,12 @@ long int spd_sdram()
sdram_cfg |= 0x10000000;
/* The DIMM is 32bit width */
- if (spd.dataw_lsb == 0x20)
- sdram_cfg |= 0x000C0000;
+ if (spd.dataw_lsb == 0x20) {
+ if (spd.mem_type == SPD_MEMTYPE_DDR)
+ sdram_cfg |= 0x000C0000;
+ if (spd.mem_type == SPD_MEMTYPE_DDR2)
+ sdram_cfg |= 0x00080000;
+ }
ddrc_ecc_enable = 0;
diff --git a/cpu/mpc83xx/traps.c b/cpu/mpc83xx/traps.c
index 152fa73..dfd6c03 100644
--- a/cpu/mpc83xx/traps.c
+++ b/cpu/mpc83xx/traps.c
@@ -140,7 +140,7 @@ MachineCheckException(struct pt_regs *regs)
return;
}
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -176,7 +176,7 @@ MachineCheckException(struct pt_regs *regs)
void
AlignmentException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -188,7 +188,7 @@ AlignmentException(struct pt_regs *regs)
void
ProgramCheckException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -200,7 +200,7 @@ ProgramCheckException(struct pt_regs *regs)
void
SoftEmuException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -213,7 +213,7 @@ SoftEmuException(struct pt_regs *regs)
void
UnknownException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -222,7 +222,7 @@ UnknownException(struct pt_regs *regs)
_exception(0, regs);
}
-#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+#if defined(CONFIG_CMD_BEDBUG)
extern void do_bedbug_breakpoint(struct pt_regs *);
#endif
@@ -231,7 +231,7 @@ DebugException(struct pt_regs *regs)
{
printf("Debugger trap at @ %lx\n", regs->nip );
show_regs(regs);
-#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+#if defined(CONFIG_CMD_BEDBUG)
do_bedbug_breakpoint( regs );
#endif
}
diff --git a/cpu/mpc83xx/u-boot.lds b/cpu/mpc83xx/u-boot.lds
new file mode 100644
index 0000000..ca663bc
--- /dev/null
+++ b/cpu/mpc83xx/u-boot.lds
@@ -0,0 +1,122 @@
+/*
+ * (C) Copyright 2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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
+ */
+
+OUTPUT_ARCH(powerpc)
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ cpu/mpc83xx/start.o (.text)
+ *(.text)
+ *(.got1)
+ . = ALIGN(16);
+ *(.rodata)
+ *(.rodata1)
+ *(.rodata.str1.4)
+ *(.eh_frame)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x0FFF) & 0xFFFFF000;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+ __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(4096);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(4096);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ _end = . ;
+ PROVIDE (end = .);
+}
+ENTRY(_start)
diff --git a/cpu/mpc85xx/Makefile b/cpu/mpc85xx/Makefile
index ff67dcd..32091fa 100644
--- a/cpu/mpc85xx/Makefile
+++ b/cpu/mpc85xx/Makefile
@@ -30,7 +30,7 @@ LIB = $(obj)lib$(CPU).a
START = start.o resetvec.o
COBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o \
- pci.o serial_scc.o commproc.o ether_fcc.o spd_sdram.o
+ pci.o serial_scc.o commproc.o ether_fcc.o spd_sdram.o qe_io.o
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
diff --git a/cpu/mpc85xx/cpu.c b/cpu/mpc85xx/cpu.c
index 1d791c9..08e0468 100644
--- a/cpu/mpc85xx/cpu.c
+++ b/cpu/mpc85xx/cpu.c
@@ -280,7 +280,7 @@ ft_cpu_setup(void *blob, bd_t *bd)
if (p != NULL)
*p = cpu_to_be32(clock);
-#if defined(CONFIG_TSEC1)
+#if defined(CONFIG_HAS_ETH0)
p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/mac-address", &len);
if (p)
memcpy(p, bd->bi_enetaddr, 6);
@@ -308,6 +308,17 @@ ft_cpu_setup(void *blob, bd_t *bd)
p = ft_get_prop(blob, "/" OF_SOC "/ethernet@26000/local-mac-address", &len);
if (p)
memcpy(p, bd->bi_enet2addr, 6);
+
+#ifdef CONFIG_UEC_ETH
+ p = ft_get_prop(blob, "/" OF_QE "/ucc@2000/mac-address", &len);
+ if (p)
+ memcpy(p, bd->bi_enet2addr, 6);
+
+ p = ft_get_prop(blob, "/" OF_QE "/ucc@2000/local-mac-address", &len);
+ if (p)
+ memcpy(p, bd->bi_enet2addr, 6);
+
+#endif
#endif
#if defined(CONFIG_HAS_ETH3)
@@ -318,6 +329,17 @@ ft_cpu_setup(void *blob, bd_t *bd)
p = ft_get_prop(blob, "/" OF_SOC "/ethernet@27000/local-mac-address", &len);
if (p)
memcpy(p, bd->bi_enet3addr, 6);
+
+#ifdef CONFIG_UEC_ETH
+ p = ft_get_prop(blob, "/" OF_QE "/ucc@3000/mac-address", &len);
+ if (p)
+ memcpy(p, bd->bi_enet3addr, 6);
+
+ p = ft_get_prop(blob, "/" OF_QE "/ucc@3000/local-mac-address", &len);
+ if (p)
+ memcpy(p, bd->bi_enet3addr, 6);
+
+#endif
#endif
}
diff --git a/cpu/mpc85xx/cpu_init.c b/cpu/mpc85xx/cpu_init.c
index 9517146..7b99610 100644
--- a/cpu/mpc85xx/cpu_init.c
+++ b/cpu/mpc85xx/cpu_init.c
@@ -1,4 +1,6 @@
/*
+ * Copyright 2007 Freescale Semiconductor.
+ *
* (C) Copyright 2003 Motorola Inc.
* Modified by Xianghua Xiao, X.Xiao@motorola.com
*
@@ -32,6 +34,29 @@
DECLARE_GLOBAL_DATA_PTR;
+#ifdef CONFIG_QE
+extern qe_iop_conf_t qe_iop_conf_tab[];
+extern void qe_config_iopin(u8 port, u8 pin, int dir,
+ int open_drain, int assign);
+extern void qe_init(uint qe_base);
+extern void qe_reset(void);
+
+static void config_qe_ioports(void)
+{
+ u8 port, pin;
+ int dir, open_drain, assign;
+ int i;
+
+ for (i = 0; qe_iop_conf_tab[i].assign != QE_IOP_TAB_END; i++) {
+ port = qe_iop_conf_tab[i].port;
+ pin = qe_iop_conf_tab[i].pin;
+ dir = qe_iop_conf_tab[i].dir;
+ open_drain = qe_iop_conf_tab[i].open_drain;
+ assign = qe_iop_conf_tab[i].assign;
+ qe_config_iopin(port, pin, dir, open_drain, assign);
+ }
+}
+#endif
#ifdef CONFIG_CPM2
static void config_8560_ioports (volatile immap_t * immr)
@@ -133,15 +158,18 @@ void cpu_init_f (void)
#endif
/* now restrict to preliminary range */
+ /* if cs1 is already set via debugger, leave cs0/cs1 alone */
+ if (! memctl->br1 & 1) {
#if defined(CFG_BR0_PRELIM) && defined(CFG_OR0_PRELIM)
- memctl->br0 = CFG_BR0_PRELIM;
- memctl->or0 = CFG_OR0_PRELIM;
+ memctl->br0 = CFG_BR0_PRELIM;
+ memctl->or0 = CFG_OR0_PRELIM;
#endif
#if defined(CFG_BR1_PRELIM) && defined(CFG_OR1_PRELIM)
- memctl->or1 = CFG_OR1_PRELIM;
- memctl->br1 = CFG_BR1_PRELIM;
+ memctl->or1 = CFG_OR1_PRELIM;
+ memctl->br1 = CFG_BR1_PRELIM;
#endif
+ }
#if defined(CFG_BR2_PRELIM) && defined(CFG_OR2_PRELIM)
memctl->or2 = CFG_OR2_PRELIM;
@@ -176,6 +204,11 @@ void cpu_init_f (void)
#if defined(CONFIG_CPM2)
m8560_cpm_reset();
#endif
+#ifdef CONFIG_QE
+ /* Config QE ioports */
+ config_qe_ioports();
+#endif
+
}
@@ -185,16 +218,25 @@ void cpu_init_f (void)
* 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)
{
+#if defined(CONFIG_CLEAR_LAW0) || defined(CONFIG_L2_CACHE)
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+#endif
+#ifdef CONFIG_CLEAR_LAW0
+ volatile ccsr_local_ecm_t *ecm = &immap->im_local_ecm;
+
+ /* clear alternate boot location LAW (used for sdram, or ddr bank) */
+ ecm->lawar0 = 0;
+#endif
+
#if defined(CONFIG_L2_CACHE)
- volatile immap_t *immap = (immap_t *)CFG_IMMR;
volatile ccsr_l2cache_t *l2cache = &immap->im_l2cache;
volatile uint cache_ctl;
uint svr, ver;
+ uint l2srbar;
svr = get_svr();
ver = SVR_VER(svr);
@@ -204,33 +246,55 @@ int cpu_init_r(void)
switch (cache_ctl & 0x30000000) {
case 0x20000000:
- if (ver == SVR_8548 || ver == SVR_8548_E) {
+ if (ver == SVR_8548 || ver == SVR_8548_E ||
+ ver == SVR_8544) {
printf ("L2 cache 512KB:");
+ /* set L2E=1, L2I=1, & L2SRAM=0 */
+ cache_ctl = 0xc0000000;
} else {
printf ("L2 cache 256KB:");
+ /* set L2E=1, L2I=1, & L2BLKSZ=2 (256 Kbyte) */
+ cache_ctl = 0xc8000000;
}
break;
- case 0x00000000:
case 0x10000000:
+ printf ("L2 cache 256KB:");
+ if (ver == SVR_8544 || ver == SVR_8544_E) {
+ cache_ctl = 0xc0000000; /* set L2E=1, L2I=1, & L2SRAM=0 */
+ }
+ break;
case 0x30000000:
+ case 0x00000000:
default:
printf ("L2 cache unknown size (0x%08x)\n", cache_ctl);
return -1;
}
- asm("msync;isync");
- l2cache->l2ctl = 0x68000000; /* invalidate */
- cache_ctl = l2cache->l2ctl;
- asm("msync;isync");
-
- l2cache->l2ctl = 0xa8000000; /* enable 256KB L2 cache */
- cache_ctl = l2cache->l2ctl;
- asm("msync;isync");
-
- printf(" enabled\n");
+ if (l2cache->l2ctl & 0x80000000) {
+ printf(" already enabled.");
+ l2srbar = l2cache->l2srbar0;
+#ifdef CFG_INIT_L2_ADDR
+ if (l2cache->l2ctl & 0x00010000 && l2srbar >= CFG_FLASH_BASE) {
+ l2srbar = CFG_INIT_L2_ADDR;
+ l2cache->l2srbar0 = l2srbar;
+ printf(" Moving to 0x%08x", CFG_INIT_L2_ADDR);
+ }
+#endif /* CFG_INIT_L2_ADDR */
+ puts("\n");
+ } else {
+ asm("msync;isync");
+ l2cache->l2ctl = cache_ctl; /* invalidate & enable */
+ asm("msync;isync");
+ printf(" enabled\n");
+ }
#else
printf("L2 cache: disabled\n");
#endif
+#ifdef CONFIG_QE
+ uint qe_base = CFG_IMMR + 0x00080000; /* QE immr base */
+ qe_init(qe_base);
+ qe_reset();
+#endif
return 0;
}
diff --git a/cpu/mpc85xx/ether_fcc.c b/cpu/mpc85xx/ether_fcc.c
index d15d242..5b23a80 100644
--- a/cpu/mpc85xx/ether_fcc.c
+++ b/cpu/mpc85xx/ether_fcc.c
@@ -48,13 +48,13 @@
#include <config.h>
#include <net.h>
-#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
#include <miiphy.h>
#endif
#if defined(CONFIG_CPM2)
-#if defined(CONFIG_ETHER_ON_FCC) && (CONFIG_COMMANDS & CFG_CMD_NET) && \
+#if defined(CONFIG_ETHER_ON_FCC) && defined(CONFIG_CMD_NET) && \
defined(CONFIG_NET_MULTI)
static struct ether_fcc_info_s
@@ -458,7 +458,7 @@ int fec_initialize(bd_t *bis)
eth_register(dev);
-#if (defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)) \
+#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) \
&& defined(CONFIG_BITBANGMII)
miiphy_register(dev->name,
bb_miiphy_read, bb_miiphy_write);
@@ -468,6 +468,6 @@ int fec_initialize(bd_t *bis)
return 1;
}
-#endif /* CONFIG_ETHER_ON_FCC && CFG_CMD_NET && CONFIG_NET_MULTI */
+#endif
#endif /* CONFIG_CPM2 */
diff --git a/cpu/mpc85xx/interrupts.c b/cpu/mpc85xx/interrupts.c
index 832781b..bf737d6 100644
--- a/cpu/mpc85xx/interrupts.c
+++ b/cpu/mpc85xx/interrupts.c
@@ -89,6 +89,39 @@ int interrupt_init (void)
mtspr(SPRN_TCR, TCR_PIE);
set_dec (decrementer_count);
set_msr (get_msr () | MSR_EE);
+
+#ifdef CONFIG_INTERRUPTS
+ volatile ccsr_pic_t *pic = &immr->im_pic;
+
+ pic->iivpr1 = 0x810002; /* 50220 enable ecm interrupts */
+ debug("iivpr1@%x = %x\n",&pic->iivpr1, pic->iivpr1);
+
+ pic->iivpr2 = 0x810002; /* 50240 enable ddr interrupts */
+ debug("iivpr2@%x = %x\n",&pic->iivpr2, pic->iivpr2);
+
+ pic->iivpr3 = 0x810003; /* 50260 enable lbc interrupts */
+ debug("iivpr3@%x = %x\n",&pic->iivpr3, pic->iivpr3);
+
+#ifdef CONFIG_PCI1
+ pic->iivpr8 = 0x810008; /* enable pci1 interrupts */
+ debug("iivpr8@%x = %x\n",&pic->iivpr8, pic->iivpr8);
+#endif
+#if defined(CONFIG_PCI2) || defined(CONFIG_PCIE2)
+ pic->iivpr9 = 0x810009; /* enable pci1 interrupts */
+ debug("iivpr9@%x = %x\n",&pic->iivpr9, pic->iivpr9);
+#endif
+#ifdef CONFIG_PCIE1
+ pic->iivpr10 = 0x81000a; /* enable pcie1 interrupts */
+ debug("iivpr10@%x = %x\n",&pic->iivpr10, pic->iivpr10);
+#endif
+#ifdef CONFIG_PCIE3
+ pic->iivpr11 = 0x81000b; /* enable pcie3 interrupts */
+ debug("iivpr11@%x = %x\n",&pic->iivpr11, pic->iivpr11);
+#endif
+
+ pic->ctpr=0; /* 40080 clear current task priority register */
+#endif
+
return (0);
}
@@ -144,7 +177,7 @@ void set_timer (ulong t)
timestamp = t;
}
-#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
+#if defined(CONFIG_CMD_IRQ)
/*******************************************************************************
*
@@ -159,4 +192,4 @@ do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
return 0;
}
-#endif /* CONFIG_COMMANDS & CFG_CMD_IRQ */
+#endif
diff --git a/cpu/mpc85xx/pci.c b/cpu/mpc85xx/pci.c
index 3c1a323..db09e45 100644
--- a/cpu/mpc85xx/pci.c
+++ b/cpu/mpc85xx/pci.c
@@ -142,7 +142,7 @@ pci_mpc85xx_init(struct pci_controller *board_hose)
u8 header_type;
pci_hose_read_config_byte(hose,
- PCI_BDF(0,17,0),
+ PCI_BDF(0,BRIDGE_ID,0),
PCI_HEADER_TYPE,
&header_type);
}
diff --git a/cpu/mpc85xx/qe_io.c b/cpu/mpc85xx/qe_io.c
new file mode 100644
index 0000000..8878bc5
--- /dev/null
+++ b/cpu/mpc85xx/qe_io.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2006 Freescale Semiconductor, Inc.
+ *
+ * Dave Liu <daveliu@freescale.com>
+ * based on source code of Shlomi Gridish
+ *
+ * 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 "common.h"
+#include "asm/errno.h"
+#include "asm/io.h"
+#include "asm/immap_85xx.h"
+
+#if defined(CONFIG_QE)
+#define NUM_OF_PINS 32
+void qe_config_iopin(u8 port, u8 pin, int dir, int open_drain, int assign)
+{
+ u32 pin_2bit_mask;
+ u32 pin_2bit_dir;
+ u32 pin_2bit_assign;
+ u32 pin_1bit_mask;
+ u32 tmp_val;
+ volatile immap_t *im = (volatile immap_t *)CFG_IMMR;
+ volatile par_io_t *par_io = (volatile par_io_t *)
+ &(im->im_gur.qe_par_io);
+
+ /* Caculate pin location and 2bit mask and dir */
+ pin_2bit_mask = (u32)(0x3 << (NUM_OF_PINS-(pin%(NUM_OF_PINS/2)+1)*2));
+ pin_2bit_dir = (u32)(dir << (NUM_OF_PINS-(pin%(NUM_OF_PINS/2)+1)*2));
+
+ /* Setup the direction */
+ tmp_val = (pin > (NUM_OF_PINS/2) - 1) ? \
+ in_be32(&par_io[port].cpdir2) :
+ in_be32(&par_io[port].cpdir1);
+
+ if (pin > (NUM_OF_PINS/2) -1) {
+ out_be32(&par_io[port].cpdir2, ~pin_2bit_mask & tmp_val);
+ out_be32(&par_io[port].cpdir2, pin_2bit_dir | tmp_val);
+ } else {
+ out_be32(&par_io[port].cpdir1, ~pin_2bit_mask & tmp_val);
+ out_be32(&par_io[port].cpdir1, pin_2bit_dir | tmp_val);
+ }
+
+ /* Calculate pin location for 1bit mask */
+ pin_1bit_mask = (u32)(1 << (NUM_OF_PINS - (pin+1)));
+
+ /* Setup the open drain */
+ tmp_val = in_be32(&par_io[port].cpodr);
+ if (open_drain)
+ out_be32(&par_io[port].cpodr, pin_1bit_mask | tmp_val);
+ else
+ out_be32(&par_io[port].cpodr, ~pin_1bit_mask & tmp_val);
+
+ /* Setup the assignment */
+ tmp_val = (pin > (NUM_OF_PINS/2) - 1) ?
+ in_be32(&par_io[port].cppar2):
+ in_be32(&par_io[port].cppar1);
+ pin_2bit_assign = (u32)(assign
+ << (NUM_OF_PINS - (pin%(NUM_OF_PINS/2)+1)*2));
+
+ /* Clear and set 2 bits mask */
+ if (pin > (NUM_OF_PINS/2) - 1) {
+ out_be32(&par_io[port].cppar2, ~pin_2bit_mask & tmp_val);
+ out_be32(&par_io[port].cppar2, pin_2bit_assign | tmp_val);
+ } else {
+ out_be32(&par_io[port].cppar1, ~pin_2bit_mask & tmp_val);
+ out_be32(&par_io[port].cppar1, pin_2bit_assign | tmp_val);
+ }
+}
+
+#endif /* CONFIG_QE */
diff --git a/cpu/mpc85xx/spd_sdram.c b/cpu/mpc85xx/spd_sdram.c
index 3777f49..5dc223a 100644
--- a/cpu/mpc85xx/spd_sdram.c
+++ b/cpu/mpc85xx/spd_sdram.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2004 Freescale Semiconductor.
+ * Copyright 2004, 2007 Freescale Semiconductor.
* (C) Copyright 2003 Motorola Inc.
* Xianghua Xiao (X.Xiao@motorola.com)
*
@@ -173,11 +173,10 @@ spd_sdram(void)
{
volatile immap_t *immap = (immap_t *)CFG_IMMR;
volatile ccsr_ddr_t *ddr = &immap->im_ddr;
- volatile ccsr_gur_t *gur = &immap->im_gur;
spd_eeprom_t spd;
unsigned int n_ranks;
unsigned int rank_density;
- unsigned int odt_rd_cfg, odt_wr_cfg;
+ unsigned int odt_rd_cfg, odt_wr_cfg, ba_bits;
unsigned int odt_cfg, mode_odt_enable;
unsigned int refresh_clk;
#ifdef MPC85xx_DDR_SDRAM_CLK_CNTL
@@ -189,7 +188,7 @@ spd_sdram(void)
unsigned int max_data_rate, effective_data_rate;
unsigned int busfreq;
unsigned sdram_cfg;
- unsigned int memsize;
+ unsigned int memsize = 0;
unsigned char caslat, caslat_ctrl;
unsigned int trfc, trfc_clk, trfc_low, trfc_high;
unsigned int trcd_clk;
@@ -204,6 +203,46 @@ spd_sdram(void)
unsigned int mode_caslat;
unsigned char sdram_type;
unsigned char d_init;
+ unsigned int bnds;
+
+ /*
+ * Skip configuration if already configured.
+ * memsize is determined from last configured chip select.
+ */
+ if (ddr->cs0_config & 0x80000000) {
+ debug(" cs0 already configured, bnds=%x\n",ddr->cs0_bnds);
+ bnds = 0xfff & ddr->cs0_bnds;
+ if (bnds < 0xff) { /* do not add if at top of 4G */
+ memsize = (bnds + 1) << 4;
+ }
+ }
+ if (ddr->cs1_config & 0x80000000) {
+ debug(" cs1 already configured, bnds=%x\n",ddr->cs1_bnds);
+ bnds = 0xfff & ddr->cs1_bnds;
+ if (bnds < 0xff) { /* do not add if at top of 4G */
+ memsize = (bnds + 1) << 4; /* assume ordered bnds */
+ }
+ }
+ if (ddr->cs2_config & 0x80000000) {
+ debug(" cs2 already configured, bnds=%x\n",ddr->cs2_bnds);
+ bnds = 0xfff & ddr->cs2_bnds;
+ if (bnds < 0xff) { /* do not add if at top of 4G */
+ memsize = (bnds + 1) << 4;
+ }
+ }
+ if (ddr->cs3_config & 0x80000000) {
+ debug(" cs3 already configured, bnds=%x\n",ddr->cs3_bnds);
+ bnds = 0xfff & ddr->cs3_bnds;
+ if (bnds < 0xff) { /* do not add if at top of 4G */
+ memsize = (bnds + 1) << 4;
+ }
+ }
+
+ if (memsize) {
+ printf(" Reusing current %dMB configuration\n",memsize);
+ memsize = setup_laws_and_tlbs(memsize);
+ return memsize << 20;
+ }
/*
* Read SPD information.
@@ -262,6 +301,7 @@ spd_sdram(void)
return 0;
}
+#ifdef CONFIG_MPC8548
/*
* Adjust DDR II IO voltage biasing.
* Only 8548 rev 1 needs the fix
@@ -269,9 +309,11 @@ spd_sdram(void)
if ((SVR_VER(get_svr()) == SVR_8548_E) &&
(SVR_MJREV(get_svr()) == 1) &&
(spd.mem_type == SPD_MEMTYPE_DDR2)) {
+ volatile ccsr_gur_t *gur = &immap->im_gur;
gur->ddrioovcr = (0x80000000 /* Enable */
| 0x10000000);/* VSEL to 1.8V */
}
+#endif
/*
* Determine the size of each Rank in bytes.
@@ -299,9 +341,14 @@ spd_sdram(void)
#endif
}
+ ba_bits = 0;
+ if (spd.nbanks == 0x8)
+ ba_bits = 1;
+
ddr->cs0_config = ( 1 << 31
| (odt_rd_cfg << 20)
| (odt_wr_cfg << 16)
+ | (ba_bits << 14)
| (spd.nrow_addr - 12) << 8
| (spd.ncol_addr - 8) );
debug("\n");
@@ -645,13 +692,10 @@ spd_sdram(void)
*/
cpo = 0;
if (spd.mem_type == SPD_MEMTYPE_DDR2) {
- if (effective_data_rate == 266 || effective_data_rate == 333) {
+ if (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;
+ cpo = 0x9; /* READ_LAT + 7/4 */
}
}
@@ -858,7 +902,12 @@ spd_sdram(void)
if (spd.mem_type == SPD_MEMTYPE_DDR)
clk_adjust = 0x6;
else
+#ifdef CONFIG_MPC8568
+ /* Empirally setting clk_adjust */
+ clk_adjust = 0x6;
+#else
clk_adjust = 0x7;
+#endif
ddr->sdram_clk_cntl = (0
| 0x80000000
diff --git a/cpu/mpc85xx/start.S b/cpu/mpc85xx/start.S
index 77c155c..2c98c2a 100644
--- a/cpu/mpc85xx/start.S
+++ b/cpu/mpc85xx/start.S
@@ -1,7 +1,6 @@
/*
- * Copyright 2004 Freescale Semiconductor.
+ * Copyright 2004, 2007 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.
@@ -46,7 +45,7 @@
#endif
#undef MSR_KERNEL
-#define MSR_KERNEL ( MSR_ME ) /* Machine Check */
+#define MSR_KERNEL ( MSR_ME ) /* Machine Check */
/*
* Set up GOT: Global Offset Table
@@ -80,110 +79,37 @@
*
*/
- .section .bootpg,"ax"
- .globl _start_e500
+ .section .bootpg,"ax"
+ .globl _start_e500
_start_e500:
- mfspr r0, PVR
- lis r1, PVR_85xx_REV1@h
- ori r1, r1, PVR_85xx_REV1@l
- cmpw r0, r1
- bne 1f
- /* Semi-bogus errata fixup for Rev 1 */
- li r0,0x2000
- mtspr 977,r0
+/* clear registers/arrays not reset by hardware */
- /*
- * Before invalidating MMU L1/L2, read TLB1 Entry 0 and then
- * write it back immediately to fixup a Rev 1 bug (Errata CPU4)
- * for this initial TLB1 entry 0, otherwise the TLB1 entry 0
- * will be invalidated (incorrectly).
- */
- lis r2,0x1000
- mtspr MAS0,r2
- tlbre
- tlbwe
- isync
-
-1:
- /*
- * Clear and set up some registers.
- * Note: Some registers need strict synchronization by
- * sync/mbar/msync/isync when being "mtspr".
- * BookE: isync before PID,tlbivax,tlbwe
- * BookE: isync after MSR,PID; msync_isync after tlbivax & tlbwe
- * E500: msync,isync before L1CSR0
- * E500: isync after BBEAR,BBTAR,BUCSR,DBCR0,DBCR1,HID0,HID1,
- * L1CSR0, L1CSR1, MAS[0,1,2,3,4,6],MMUCSR0, PID[0,1,2],
- * SPEFCSR
- */
-
- /* invalidate d-cache */
- mfspr r0,L1CSR0
- ori r0,r0,0x0002
- msync
- isync
- mtspr L1CSR0,r0
- isync
-
- /* disable d-cache */
- li r0,0x0
- mtspr L1CSR0,r0
-
- /* invalidate i-cache */
- mfspr r0,L1CSR1
- ori r0,r0,0x0002
- mtspr L1CSR1,r0
- isync
-
- /* disable i-cache */
- li r0,0x0
- mtspr L1CSR1,r0
- isync
-
- /* clear registers */
- li r0,0
- mtspr SRR0,r0
- mtspr SRR1,r0
- mtspr CSRR0,r0
- mtspr CSRR1,r0
- mtspr MCSRR0,r0
- mtspr MCSRR1,r0
-
- mtspr ESR,r0
- mtspr MCSR,r0
- mtspr DEAR,r0
-
- /* not needed and conflicts with some debuggers */
- /* mtspr DBCR0,r0 */
- mtspr DBCR1,r0
- mtspr DBCR2,r0
- /* not needed and conflicts with some debuggers */
- /* mtspr IAC1,r0 */
- /* mtspr IAC2,r0 */
- mtspr DAC1,r0
- mtspr DAC2,r0
+ /* L1 */
+ li r0,2
+ mtspr L1CSR0,r0 /* invalidate d-cache */
+ mtspr L1CSR1,r0 /* invalidate i-cache */
mfspr r1,DBSR
mtspr DBSR,r1 /* Clear all valid bits */
- mtspr PID0,r0
- mtspr PID1,r0
- mtspr PID2,r0
- mtspr TCR,r0
+ /*
+ * Enable L1 Caches early
+ *
+ */
- mtspr BUCSR,r0 /* disable branch prediction */
- mtspr MAS4,r0
- mtspr MAS6,r0
-#if defined(CONFIG_ENABLE_36BIT_PHYS)
- mtspr MAS7,r0
-#endif
+ lis r2,L1CSR0_CPE@H /* enable parity */
+ ori r2,r2,L1CSR0_DCE
+ mtspr L1CSR0,r2 /* enable L1 Dcache */
isync
+ mtspr L1CSR1,r2 /* enable L1 Icache */
+ isync
+ msync
/* Setup interrupt vectors */
lis r1,TEXT_BASE@h
- mtspr IVPR, r1
+ mtspr IVPR,r1
li r1,0x0100
mtspr IVOR0,r1 /* 0: Critical input */
@@ -217,26 +143,6 @@ _start_e500:
li r1,0x0f00
mtspr IVOR15,r1 /* 15: Debug */
- /*
- * Invalidate MMU L1/L2
- *
- * Note: There is a fixup earlier for Errata CPU4 on
- * Rev 1 parts that must precede this MMU invalidation.
- */
- li r2, 0x001e
- mtspr MMUCSR0, r2
- isync
-
- /*
- * Invalidate all TLB0 entries.
- */
- li r3,4
- li r4,0
- tlbivax r4,r3
- /*
- * To avoid REV1 Errata CPU6 issues, make sure
- * the instruction following tlbivax is not a store.
- */
/*
* After reset, CCSRBAR is located at CFG_CCSRBAR_DEFAULT, i.e.
@@ -254,14 +160,14 @@ _start_e500:
lwzu r4,0(r5) /* how many TLB1 entries we actually use */
mtctr r4
-0: lwzu r0,4(r5)
- lwzu r1,4(r5)
- lwzu r2,4(r5)
- lwzu r3,4(r5)
- mtspr MAS0,r0
- mtspr MAS1,r1
- mtspr MAS2,r2
- mtspr MAS3,r3
+0: lwzu r6,4(r5)
+ lwzu r7,4(r5)
+ lwzu r8,4(r5)
+ lwzu r9,4(r5)
+ mtspr MAS0,r6
+ mtspr MAS1,r7
+ mtspr MAS2,r8
+ mtspr MAS3,r9
isync
msync
tlbwe
@@ -271,22 +177,22 @@ _start_e500:
1:
#if (CFG_CCSRBAR_DEFAULT != CFG_CCSRBAR)
/* Special sequence needed to update CCSRBAR itself */
- lis r4, CFG_CCSRBAR_DEFAULT@h
- ori r4, r4, CFG_CCSRBAR_DEFAULT@l
+ lis r4,CFG_CCSRBAR_DEFAULT@h
+ ori r4,r4,CFG_CCSRBAR_DEFAULT@l
- lis r5, CFG_CCSRBAR@h
- ori r5, r5, CFG_CCSRBAR@l
+ lis r5,CFG_CCSRBAR@h
+ ori r5,r5,CFG_CCSRBAR@l
srwi r6,r5,12
- stw r6, 0(r4)
+ stw r6,0(r4)
isync
- lis r5, 0xffff
+ lis r5,0xffff
ori r5,r5,0xf000
- lwz r5, 0(r5)
+ lwz r5,0(r5)
isync
- lis r3, CFG_CCSRBAR@h
- lwz r5, CFG_CCSRBAR@l(r3)
+ lis r3,CFG_CCSRBAR@h
+ lwz r5,CFG_CCSRBAR@l(r3)
isync
#endif
@@ -300,8 +206,8 @@ _start_e500:
lwzu r5,0(r6) /* how many windows we actually use */
mtctr r5
- li r2,0x0c28 /* the first pair is reserved for boot-over-rio-or-pci */
- li r1,0x0c30
+ li r2,0x0c28 /* the first pair is reserved for */
+ li r1,0x0c30 /* boot-over-rio-or-pci */
0: lwzu r4,4(r6)
lwzu r3,4(r6)
@@ -311,31 +217,6 @@ _start_e500:
addi r1,r1,0x0020
bdnz 0b
- /* Jump out the last 4K page and continue to 'normal' start */
-1: bl 3f
- b _start
-
-3: li r0,0
- mtspr SRR1,r0 /* Keep things disabled for now */
- mflr r1
- mtspr SRR0,r1
- rfi
-
-/*
- * r3 - 1st arg to board_init(): IMMP pointer
- * r4 - 2nd arg to board_init(): boot flag
- */
- .text
- .long 0x27051956 /* U-BOOT Magic Number */
- .globl version_string
-version_string:
- .ascii U_BOOT_VERSION
- .ascii " (", __DATE__, " - ", __TIME__, ")"
- .ascii CONFIG_IDENT_STRING, "\0"
-
- . = EXC_OFF_SYS_RESET
- .globl _start
-_start:
/* Clear and set up some registers. */
li r0,0x0000
lis r1,0xffff
@@ -354,17 +235,14 @@ _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 */
+ ori r0,r0,(HID0_TBEN|HID0_ENMAS7)@l /* Enable Timebase & MAS7 */
+#else
+ ori r0,r0,HID0_TBEN@l /* enable Timebase */
#endif
mtspr HID0,r0
-#if defined(CONFIG_ADDR_STREAMING)
- li r0,0x3000
-#else
- li r0,0x1000
-#endif
+ li r0,(HID1_ASTME|HID1_ABE)@l /* Addr streaming & broadcast */
mtspr HID1,r0
/* Enable Branch Prediction */
@@ -383,37 +261,53 @@ _start:
#endif
/* L1 DCache is used for initial RAM */
- mfspr r2, L1CSR0
- ori r2, r2, 0x0003
- oris r2, r2, 0x0001
- mtspr L1CSR0, r2 /* enable/invalidate L1 Dcache */
- isync
/* Allocate Initial RAM in data cache.
*/
- lis r3, CFG_INIT_RAM_ADDR@h
- ori r3, r3, CFG_INIT_RAM_ADDR@l
- li r2, 512 /* 512*32=16K */
+ lis r3,CFG_INIT_RAM_ADDR@h
+ ori r3,r3,CFG_INIT_RAM_ADDR@l
+ li r2,512 /* 512*32=16K */
mtctr r2
- li r0, 0
+ li r0,0
1:
- dcbz r0, r3
- dcbtls 0,r0, r3
- addi r3, r3, 32
+ dcbz r0,r3
+ dcbtls 0,r0,r3
+ addi r3,r3,32
bdnz 1b
-#ifndef CFG_RAMBOOT
+ /* Jump out the last 4K page and continue to 'normal' start */
+#ifdef CFG_RAMBOOT
+ bl 3f
+ b _start_cont
+#else
/* Calculate absolute address in FLASH and jump there */
/*--------------------------------------------------------------*/
- lis r3, CFG_MONITOR_BASE@h
- ori r3, r3, CFG_MONITOR_BASE@l
- addi r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
+ lis r3,CFG_MONITOR_BASE@h
+ ori r3,r3,CFG_MONITOR_BASE@l
+ addi r3,r3,_start_cont - _start + _START_OFFSET
mtlr r3
- blr
+#endif
-in_flash:
-#endif /* CFG_RAMBOOT */
+3: li r0,0
+ mtspr SRR1,r0 /* Keep things disabled for now */
+ mflr r1
+ mtspr SRR0,r1
+ rfi
+ isync
+ .text
+ .globl _start
+_start:
+ .long 0x27051956 /* U-BOOT Magic Number */
+ .globl version_string
+version_string:
+ .ascii U_BOOT_VERSION
+ .ascii " (", __DATE__, " - ", __TIME__, ")"
+ .ascii CONFIG_IDENT_STRING, "\0"
+
+ .align 4
+ .globl _start_cont
+_start_cont:
/* Setup the stack in initial RAM,could be L2-as-SRAM or L1 dcache*/
lis r1,CFG_INIT_RAM_ADDR@h
ori r1,r1,CFG_INIT_SP_OFFSET@l
@@ -424,26 +318,24 @@ in_flash:
stwu r1,-8(r1) /* Save back chain and move SP */
lis r0,RESET_VECTOR@h /* Address of reset vector */
- ori r0,r0, RESET_VECTOR@l
+ 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) */
GET_GOT
bl cpu_init_f
- bl icache_enable
bl board_init_f
isync
-/* --FIXME-- machine check with MCSRRn and rfmci */
-
+ . = EXC_OFF_SYS_RESET
.globl _start_of_vectors
_start_of_vectors:
-#if 0
+
/* Critical input. */
- CRIT_EXCEPTION(0x0100, CritcalInput, CritcalInputException)
-#endif
-/* Machine check --FIXME-- Should be MACH_EXCEPTION */
- CRIT_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
+ CRIT_EXCEPTION(0x0100, CriticalInput, CritcalInputException)
+
+/* Machine check */
+ MCK_EXCEPTION(0x200, MachineCheck, MachineCheckException)
/* Data Storage exception. */
STD_EXCEPTION(0x0300, DataStorage, UnknownException)
@@ -452,7 +344,7 @@ _start_of_vectors:
STD_EXCEPTION(0x0400, InstStorage, UnknownException)
/* External Interrupt exception. */
- STD_EXCEPTION(0x0500, ExtInterrupt, UnknownException)
+ STD_EXCEPTION(0x0500, ExtInterrupt, ExtIntException)
/* Alignment exception. */
. = 0x0600
@@ -469,8 +361,8 @@ Alignment:
mtlr r6
blrl
.L_Alignment:
- .long AlignmentException - _start + EXC_OFF_SYS_RESET
- .long int_return - _start + EXC_OFF_SYS_RESET
+ .long AlignmentException - _start + _START_OFFSET
+ .long int_return - _start + _START_OFFSET
/* Program check exception */
. = 0x0700
@@ -483,8 +375,8 @@ ProgramCheck:
mtlr r6
blrl
.L_ProgramCheck:
- .long ProgramCheckException - _start + EXC_OFF_SYS_RESET
- .long int_return - _start + EXC_OFF_SYS_RESET
+ .long ProgramCheckException - _start + _START_OFFSET
+ .long int_return - _start + _START_OFFSET
/* No FPU on MPC85xx. This exception is not supposed to happen.
*/
@@ -496,23 +388,23 @@ ProgramCheck:
* r3-... arguments
*/
SystemCall:
- addis r11,r0,0 /* get functions table addr */
- ori r11,r11,0 /* Note: this code is patched in trap_init */
- addis r12,r0,0 /* get number of functions */
+ addis r11,r0,0 /* get functions table addr */
+ ori r11,r11,0 /* Note: this code is patched in trap_init */
+ addis r12,r0,0 /* get number of functions */
ori r12,r12,0
- cmplw 0, r0, r12
+ cmplw 0,r0,r12
bge 1f
- rlwinm r0,r0,2,0,31 /* fn_addr = fn_tbl[r0] */
+ rlwinm r0,r0,2,0,31 /* fn_addr = fn_tbl[r0] */
add r11,r11,r0
lwz r11,0(r11)
- li r20,0xd00-4 /* Get stack pointer */
+ li r20,0xd00-4 /* Get stack pointer */
lwz r12,0(r20)
- subi r12,r12,12 /* Adjust stack pointer */
+ subi r12,r12,12 /* Adjust stack pointer */
li r0,0xc00+_end_back-SystemCall
- cmplw 0, r0, r12 /* Check stack overflow */
+ cmplw 0,r0,r12 /* Check stack overflow */
bgt 1f
stw r12,0(r20)
@@ -570,7 +462,7 @@ _end_back:
_end_of_vectors:
- . = 0x2100
+ . = . + (0x100 - ( . & 0xff )) /* align for debug */
/*
* This code finishes saving the registers to the exception frame
@@ -655,26 +547,58 @@ crit_return:
REST_GPR(31, r1)
lwz r2,_NIP(r1) /* Restore environment */
lwz r0,_MSR(r1)
- mtspr 990,r2 /* SRR2 */
- mtspr 991,r0 /* SRR3 */
+ mtspr SPRN_CSRR0,r2
+ mtspr SPRN_CSRR1,r0
lwz r0,GPR0(r1)
lwz r2,GPR2(r1)
lwz r1,GPR1(r1)
SYNC
rfci
+mck_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 SPRN_MCSRR0,r2
+ mtspr SPRN_MCSRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfmci
+
/* Cache functions.
*/
invalidate_icache:
mfspr r0,L1CSR1
- ori r0,r0,0x0002
+ ori r0,r0,L1CSR1_ICFI
+ msync
+ isync
mtspr L1CSR1,r0
isync
- blr /* entire I cache */
+ blr /* entire I cache */
invalidate_dcache:
mfspr r0,L1CSR0
- ori r0,r0,0x0002
+ ori r0,r0,L1CSR0_DCFI
msync
isync
mtspr L1CSR0,r0
@@ -697,9 +621,9 @@ icache_enable:
.globl icache_disable
icache_disable:
mfspr r0,L1CSR1
- lis r1,0xfffffffe@h
- ori r1,r1,0xfffffffe@l
- and r0,r0,r1
+ lis r3,0
+ ori r3,r3,L1CSR1_ICE
+ andc r0,r0,r3
mtspr L1CSR1,r0
isync
blr
@@ -707,7 +631,7 @@ icache_disable:
.globl icache_status
icache_status:
mfspr r3,L1CSR1
- andi. r3,r3,1
+ andi. r3,r3,L1CSR1_ICE
blr
.globl dcache_enable
@@ -727,12 +651,10 @@ dcache_enable:
.globl dcache_disable
dcache_disable:
- mfspr r0,L1CSR0
- lis r1,0xfffffffe@h
- ori r1,r1,0xfffffffe@l
- and r0,r0,r1
- msync
- isync
+ mfspr r3,L1CSR0
+ lis r4,0
+ ori r4,r4,L1CSR0_DCE
+ andc r3,r3,r4
mtspr L1CSR0,r0
isync
blr
@@ -740,27 +662,27 @@ dcache_disable:
.globl dcache_status
dcache_status:
mfspr r3,L1CSR0
- andi. r3,r3,1
+ andi. r3,r3,L1CSR0_DCE
blr
.globl get_pir
get_pir:
- mfspr r3, PIR
+ mfspr r3,PIR
blr
.globl get_pvr
get_pvr:
- mfspr r3, PVR
+ mfspr r3,PVR
blr
.globl get_svr
get_svr:
- mfspr r3, SVR
+ mfspr r3,SVR
blr
.globl wr_tcr
wr_tcr:
- mtspr TCR, r3
+ mtspr TCR,r3
blr
/*------------------------------------------------------------------------------- */
@@ -913,16 +835,16 @@ ppcSync:
*/
.globl relocate_code
relocate_code:
- mr r1, r3 /* Set new stack pointer */
- mr r9, r4 /* Save copy of Init Data pointer */
- mr r10, r5 /* Save copy of Destination Address */
+ mr r1,r3 /* Set new stack pointer */
+ mr r9,r4 /* Save copy of Init 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
+ 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 */
+ li r6,CFG_CACHELINE_SIZE /* Cache Line Size */
/*
* Fix GOT pointer:
@@ -931,12 +853,12 @@ relocate_code:
*
* Offset:
*/
- sub r15, r10, r4
+ sub r15,r10,r4
/* First our own GOT */
- add r14, r14, r15
+ add r14,r14,r15
/* the the one used by the C code */
- add r30, r30, r15
+ add r30,r30,r15
/*
* Now relocate code
@@ -997,10 +919,10 @@ relocate_code:
* initialization, now running from RAM.
*/
- addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+ addi r0,r10,in_ram - _start + _START_OFFSET
mtlr r0
blr /* NEVER RETURNS! */
-
+ .globl in_ram
in_ram:
/*
@@ -1044,19 +966,19 @@ clear_bss:
lwz r3,GOT(__bss_start)
lwz r4,GOT(_end)
- cmplw 0, r3, r4
+ cmplw 0,r3,r4
beq 6f
- li r0, 0
+ li r0,0
5:
- stw r0, 0(r3)
- addi r3, r3, 4
- cmplw 0, r3, r4
+ stw r0,0(r3)
+ addi r3,r3,4
+ cmplw 0,r3,r4
bne 5b
6:
- mr r3, r9 /* Init Data pointer */
- mr r4, r10 /* Destination Address */
+ mr r3,r9 /* Init Data pointer */
+ mr r4,r10 /* Destination Address */
bl board_init_r
/*
@@ -1067,52 +989,54 @@ clear_bss:
*/
.globl trap_init
trap_init:
- lwz r7, GOT(_start)
- lwz r8, GOT(_end_of_vectors)
+ lwz r7,GOT(_start_of_vectors)
+ lwz r8,GOT(_end_of_vectors)
- li r9, 0x100 /* reset vector always at 0x100 */
+ li r9,0x100 /* reset vector always at 0x100 */
- cmplw 0, r7, r8
+ 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
+ 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 r7,.L_CriticalInput - _start + _START_OFFSET
bl trap_reloc
- li r7, .L_DataStorage - _start + EXC_OFF_SYS_RESET
+ li r7,.L_MachineCheck - _start + _START_OFFSET
bl trap_reloc
- li r7, .L_InstStorage - _start + EXC_OFF_SYS_RESET
+ li r7,.L_DataStorage - _start + _START_OFFSET
bl trap_reloc
- li r7, .L_ExtInterrupt - _start + EXC_OFF_SYS_RESET
+ li r7,.L_InstStorage - _start + _START_OFFSET
bl trap_reloc
- li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+ li r7,.L_ExtInterrupt - _start + _START_OFFSET
bl trap_reloc
- li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+ li r7,.L_Alignment - _start + _START_OFFSET
bl trap_reloc
- li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+ li r7,.L_ProgramCheck - _start + _START_OFFSET
bl trap_reloc
- li r7, .L_Decrementer - _start + EXC_OFF_SYS_RESET
+ li r7,.L_FPUnavailable - _start + _START_OFFSET
bl trap_reloc
- li r7, .L_IntervalTimer - _start + EXC_OFF_SYS_RESET
- li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+ li r7,.L_Decrementer - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_IntervalTimer - _start + _START_OFFSET
+ li r8,_end_of_vectors - _start + _START_OFFSET
2:
bl trap_reloc
- addi r7, r7, 0x100 /* next exception vector */
- cmplw 0, r7, r8
+ addi r7,r7,0x100 /* next exception vector */
+ cmplw 0,r7,r8
blt 2b
lis r7,0x0
- mtspr IVPR, r7
+ mtspr IVPR,r7
mtlr r4 /* restore link register */
blr
@@ -1121,13 +1045,13 @@ trap_init:
* 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,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)
+ lwz r0,4(r7) /* int_return ... */
+ add r0,r0,r3 /* ... += dest_addr */
+ stw r0,4(r7)
blr
@@ -1135,13 +1059,13 @@ trap_reloc:
.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
+ lis r3,(CFG_INIT_RAM_ADDR & ~31)@h
+ ori r3,r3,(CFG_INIT_RAM_ADDR & ~31)@l
+ li r4,512
+ mtctr r4
+1: icbi r0,r3
+ dcbi r0,r3
+ addi r3,r3,32
bdnz 1b
sync /* Wait for all icbi to complete on bus */
isync
diff --git a/cpu/mpc85xx/traps.c b/cpu/mpc85xx/traps.c
index 904f052..efc80c7 100644
--- a/cpu/mpc85xx/traps.c
+++ b/cpu/mpc85xx/traps.c
@@ -1,6 +1,7 @@
/*
* linux/arch/ppc/kernel/traps.c
*
+ * Copyright 2007 Freescale Semiconductor.
* Copyright (C) 2003 Motorola
* Modified by Xianghua Xiao(x.xiao@motorola.com)
*
@@ -41,7 +42,7 @@
DECLARE_GLOBAL_DATA_PTR;
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
int (*debugger_exception_handler)(struct pt_regs *) = 0;
#endif
@@ -74,7 +75,7 @@ static __inline__ unsigned long get_esr(void)
#define ESR_DIZ 0x00400000
#define ESR_U0F 0x00008000
-#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+#if defined(CONFIG_CMD_BEDBUG)
extern void do_bedbug_breakpoint(struct pt_regs *);
#endif
@@ -145,10 +146,13 @@ CritcalInputException(struct pt_regs *regs)
panic("Critical Input Exception");
}
+int machinecheck_count = 0;
+int machinecheck_error = 0;
void
MachineCheckException(struct pt_regs *regs)
{
unsigned long fixup;
+ unsigned int mcsr, mcsrr0, mcsrr1, mcar;
/* Probing PCI using config cycles cause this exception
* when a device is not present. Catch it and return to
@@ -159,40 +163,68 @@ MachineCheckException(struct pt_regs *regs)
return;
}
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+ mcsrr0 = mfspr(SPRN_MCSRR0);
+ mcsrr1 = mfspr(SPRN_MCSRR1);
+ mcsr = mfspr(SPRN_MCSR);
+ mcar = mfspr(SPRN_MCAR);
+
+ machinecheck_count++;
+ machinecheck_error=1;
+
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
printf("Machine check in kernel mode.\n");
- printf("Caused by (from msr): ");
- printf("regs %p ",regs);
- switch( regs->msr & 0x000F0000) {
- case (0x80000000>>12):
- printf("Machine check signal - probably due to mm fault\n"
- "with mmu off\n");
- break;
- case (0x80000000>>13):
- printf("Transfer error ack signal\n");
- break;
- case (0x80000000>>14):
- printf("Data parity signal\n");
- break;
- case (0x80000000>>15):
- printf("Address parity signal\n");
- break;
- default:
- printf("Unknown values in msr\n");
- }
+ printf("Caused by (from mcsr): ");
+ printf("mcsr = 0x%08x\n", mcsr);
+ if (mcsr & 0x80000000)
+ printf("Machine check input pin\n");
+ if (mcsr & 0x40000000)
+ printf("Instruction cache parity error\n");
+ if (mcsr & 0x20000000)
+ printf("Data cache push parity error\n");
+ if (mcsr & 0x10000000)
+ printf("Data cache parity error\n");
+ if (mcsr & 0x00000080)
+ printf("Bus instruction address error\n");
+ if (mcsr & 0x00000040)
+ printf("Bus Read address error\n");
+ if (mcsr & 0x00000020)
+ printf("Bus Write address error\n");
+ if (mcsr & 0x00000010)
+ printf("Bus Instruction data bus error\n");
+ if (mcsr & 0x00000008)
+ printf("Bus Read data bus error\n");
+ if (mcsr & 0x00000004)
+ printf("Bus Write bus error\n");
+ if (mcsr & 0x00000002)
+ printf("Bus Instruction parity error\n");
+ if (mcsr & 0x00000001)
+ printf("Bus Read parity error\n");
+
show_regs(regs);
+ printf("MCSR=0x%08x \tMCSRR0=0x%08x \nMCSRR1=0x%08x \tMCAR=0x%08x\n",
+ mcsr, mcsrr0, mcsrr1, mcar);
print_backtrace((unsigned long *)regs->gpr[1]);
- panic("machine check");
+ if (machinecheck_count > 10) {
+ panic("machine check count too high\n");
+ }
+
+ if (machinecheck_count > 1) {
+ regs->nip += 4; /* skip offending instruction */
+ printf("Skipping current instr, Returning to 0x%08x\n",
+ regs->nip);
+ } else {
+ printf("Returning back to 0x%08x\n",regs->nip);
+ }
}
void
AlignmentException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -207,7 +239,7 @@ ProgramCheckException(struct pt_regs *regs)
{
long esr_val;
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -244,7 +276,7 @@ PITException(struct pt_regs *regs)
void
UnknownException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -253,13 +285,40 @@ UnknownException(struct pt_regs *regs)
regs->nip, regs->msr, regs->trap);
_exception(0, regs);
}
+void
+ExtIntException(struct pt_regs *regs)
+{
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+ volatile ccsr_pic_t *pic = &immap->im_pic;
+ uint vect;
+
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ printf("External Interrupt Exception at PC: %lx, SR: %lx, vector=%lx",
+ regs->nip, regs->msr, regs->trap);
+ vect = pic->iack0;
+ printf(" irq IACK0@%05x=%d\n",&pic->iack0,vect);
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ machinecheck_count++;
+#ifdef EXTINT_NOSKIP
+ printf("Returning back to 0x%08x\n",regs->nip);
+#else
+ regs->nip += 4; /* skip offending instruction */
+ printf("Skipping current instr, Returning to 0x%08x\n",regs->nip);
+#endif
+
+}
void
DebugException(struct pt_regs *regs)
{
printf("Debugger trap at @ %lx\n", regs->nip );
show_regs(regs);
-#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+#if defined(CONFIG_CMD_BEDBUG)
do_bedbug_breakpoint( regs );
#endif
}
diff --git a/cpu/mpc86xx/Makefile b/cpu/mpc86xx/Makefile
index fffcfd2..6d9300e 100644
--- a/cpu/mpc86xx/Makefile
+++ b/cpu/mpc86xx/Makefile
@@ -1,4 +1,5 @@
#
+# Copyright 2007 Freescale Semiconductor, Inc.
# (C) Copyright 2002,2003 Motorola Inc.
# Xianghua Xiao,X.Xiao@motorola.com
#
@@ -30,7 +31,7 @@ LIB = $(obj)lib$(CPU).a
START = start.o #resetvec.o
SOBJS = cache.o
COBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o \
- pci.o pcie_indirect.o spd_sdram.o
+ spd_sdram.o
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
diff --git a/cpu/mpc86xx/cpu_init.c b/cpu/mpc86xx/cpu_init.c
index 4673d05..c8e4666 100644
--- a/cpu/mpc86xx/cpu_init.c
+++ b/cpu/mpc86xx/cpu_init.c
@@ -104,8 +104,8 @@ void cpu_init_f(void)
/* enable the timebase bit in HID0 */
set_hid0(get_hid0() | 0x4000000);
- /* enable SYNCBE | ABE bits in HID1 */
- set_hid1(get_hid1() | 0x00000C00);
+ /* enable EMCP, SYNCBE | ABE bits in HID1 */
+ set_hid1(get_hid1() | 0x80000C00);
}
/*
diff --git a/cpu/mpc86xx/interrupts.c b/cpu/mpc86xx/interrupts.c
index 49820bb..d9f634f 100644
--- a/cpu/mpc86xx/interrupts.c
+++ b/cpu/mpc86xx/interrupts.c
@@ -8,7 +8,7 @@
* (C) Copyright 2003 Motorola Inc. (MPC85xx port)
* Xianghua Xiao (X.Xiao@motorola.com)
*
- * (C) Copyright 2004 Freescale Semiconductor. (MPC86xx Port)
+ * (C) Copyright 2004, 2007 Freescale Semiconductor. (MPC86xx Port)
* Jeff Brown
* Srikanth Srinivasan (srikanth.srinivasan@freescale.com)
*
@@ -71,7 +71,7 @@ static __inline__ void set_dec(unsigned long val)
}
/* interrupt is not supported yet */
-int interrupt_init_cpu(unsigned *decrementer_count)
+int interrupt_init_cpu(unsigned long *decrementer_count)
{
return 0;
}
@@ -80,25 +80,10 @@ int interrupt_init(void)
{
int ret;
- /*
- * The IRQ0 on Rev 2 is pulled high (low in Rev 1.x) to
- * implement PEX10 errata. As INT is active high, it
- * will cause core to take 0x500 interrupt.
- *
- * Due to the PIC's default pass through mode, as soon
- * as interrupts are enabled (MSR[EE] = 1), an interrupt
- * will be taken and u-boot will hang. This is due to a
- * hardware change (per an errata fix) on new revisions
- * of the board with Rev 2.x parts.
- *
- * Setting the PIC to mixed mode prevents the hang.
- */
- if ((get_svr() & 0xf0) == 0x20) {
- volatile immap_t *immr = (immap_t *)CFG_IMMR;
- immr->im_pic.gcr = MPC86xx_PICGCR_RST;
- while (immr->im_pic.gcr & MPC86xx_PICGCR_RST);
- immr->im_pic.gcr = MPC86xx_PICGCR_MODE;
- }
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ immr->im_pic.gcr = MPC86xx_PICGCR_RST;
+ while (immr->im_pic.gcr & MPC86xx_PICGCR_RST);
+ immr->im_pic.gcr = MPC86xx_PICGCR_MODE;
/* call cpu specific function from $(CPU)/interrupts.c */
ret = interrupt_init_cpu(&decrementer_count);
@@ -107,7 +92,7 @@ int interrupt_init(void)
return ret;
decrementer_count = get_tbclk() / CFG_HZ;
- debug("interrupt init: tbclk() = %d MHz, decrementer_count = %d\n",
+ debug("interrupt init: tbclk() = %d MHz, decrementer_count = %ld\n",
(get_tbclk() / 1000000),
decrementer_count);
@@ -119,6 +104,30 @@ int interrupt_init(void)
get_msr(),
get_dec());
+#ifdef CONFIG_INTERRUPTS
+ volatile ccsr_pic_t *pic = &immr->im_pic;
+
+ pic->iivpr1 = 0x810001; /* 50220 enable mcm interrupts */
+ debug("iivpr1@%x = %x\n", &pic->iivpr1, pic->iivpr1);
+
+ pic->iivpr2 = 0x810002; /* 50240 enable ddr interrupts */
+ debug("iivpr2@%x = %x\n", &pic->iivpr2, pic->iivpr2);
+
+ pic->iivpr3 = 0x810003; /* 50260 enable lbc interrupts */
+ debug("iivpr3@%x = %x\n", &pic->iivpr3, pic->iivpr3);
+
+#if defined(CONFIG_PCI1) || defined(CONFIG_PCIE1)
+ pic->iivpr8 = 0x810008; /* enable pcie1 interrupts */
+ debug("iivpr8@%x = %x\n", &pic->iivpr8, pic->iivpr8);
+#endif
+#if defined(CONFIG_PCI2) || defined(CONFIG_PCIE2)
+ pic->iivpr9 = 0x810009; /* enable pcie2 interrupts */
+ debug("iivpr9@%x = %x\n", &pic->iivpr9, pic->iivpr9);
+#endif
+
+ pic->ctpr = 0; /* 40080 clear current task priority register */
+#endif
+
return 0;
}
@@ -158,8 +167,6 @@ void timer_interrupt(struct pt_regs *regs)
timestamp++;
- ppcDcbf(&timestamp);
-
/* Restore Decrementer Count */
set_dec(decrementer_count);
diff --git a/cpu/mpc86xx/pci.c b/cpu/mpc86xx/pci.c
deleted file mode 100644
index b86548d..0000000
--- a/cpu/mpc86xx/pci.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (C) Freescale Semiconductor,Inc.
- * 2005, 2006. All rights reserved.
- *
- * Ed Swarthout (ed.swarthout@freescale.com)
- * Jason Jin (Jason.jin@freescale.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
- */
-
-/*
- * PCIE Configuration space access support for PCIE Bridge
- */
-#include <common.h>
-#include <pci.h>
-
-#if defined(CONFIG_PCI)
-void
-pci_mpc86xx_init(struct pci_controller *hose)
-{
- volatile immap_t *immap = (immap_t *) CFG_CCSRBAR;
- volatile ccsr_pex_t *pcie1 = &immap->im_pex1;
- u16 temp16;
- u32 temp32;
-
- volatile ccsr_gur_t *gur = &immap->im_gur;
- uint host1_agent = (gur->porbmsr & MPC86xx_PORBMSR_HA) >> 17;
- uint pcie1_host = (host1_agent == 2) || (host1_agent == 3);
- uint pcie1_agent = (host1_agent == 0) || (host1_agent == 1);
- uint devdisr = gur->devdisr;
- uint io_sel = (gur->pordevsr & MPC86xx_PORDEVSR_IO_SEL) >> 16;
-
- if ((io_sel == 2 || io_sel == 3 || io_sel == 5 || io_sel == 6 ||
- io_sel == 7 || io_sel == 0xf)
- && !(devdisr & MPC86xx_DEVDISR_PCIEX1)) {
- printf("PCI-EXPRESS 1: Configured as %s \n",
- pcie1_agent ? "Agent" : "Host");
- if (pcie1_agent)
- return; /*Don't scan bus when configured as agent */
- printf(" Scanning PCIE bus");
- debug("0x%08x=0x%08x ",
- &pcie1->pme_msg_det,
- pcie1->pme_msg_det);
- if (pcie1->pme_msg_det) {
- pcie1->pme_msg_det = 0xffffffff;
- debug(" with errors. Clearing. Now 0x%08x",
- pcie1->pme_msg_det);
- }
- debug("\n");
- } else {
- printf("PCI-EXPRESS 1 disabled!\n");
- return;
- }
-
- /*
- * Set first_bus=0 only skipped B0:D0:F0 which is
- * a reserved device in M1575, but make it easy for
- * most of the scan process.
- */
- hose->first_busno = 0x00;
- hose->last_busno = 0xfe;
-
- pcie_setup_indirect(hose, (CFG_IMMR + 0x8000), (CFG_IMMR + 0x8004));
-
- pci_hose_read_config_word(hose,
- PCI_BDF(0, 0, 0), PCI_COMMAND, &temp16);
- temp16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER |
- PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
- pci_hose_write_config_word(hose,
- PCI_BDF(0, 0, 0), PCI_COMMAND, temp16);
-
- pci_hose_write_config_word(hose, PCI_BDF(0, 0, 0), PCI_STATUS, 0xffff);
- pci_hose_write_config_byte(hose,
- PCI_BDF(0, 0, 0), PCI_LATENCY_TIMER, 0x80);
-
- pci_hose_read_config_dword(hose, PCI_BDF(0, 0, 0), PCI_PRIMARY_BUS,
- &temp32);
- temp32 = (temp32 & 0xff000000) | (0xff) | (0x0 << 8) | (0xfe << 16);
- pci_hose_write_config_dword(hose, PCI_BDF(0, 0, 0), PCI_PRIMARY_BUS,
- temp32);
-
- pcie1->powar1 = 0;
- pcie1->powar2 = 0;
- pcie1->piwar1 = 0;
- pcie1->piwar1 = 0;
-
- pcie1->powbar1 = (CFG_PCI1_MEM_BASE >> 12) & 0x000fffff;
- pcie1->powar1 = 0x8004401c; /* 512M MEM space */
- pcie1->potar1 = (CFG_PCI1_MEM_BASE >> 12) & 0x000fffff;
- pcie1->potear1 = 0x00000000;
-
- pcie1->powbar2 = (CFG_PCI1_IO_BASE >> 12) & 0x000fffff;
- pcie1->powar2 = 0x80088017; /* 16M IO space */
- pcie1->potar2 = 0x00000000;
- pcie1->potear2 = 0x00000000;
-
- pcie1->pitar1 = 0x00000000;
- pcie1->piwbar1 = 0x00000000;
- /* Enable, Prefetch, Local Mem, * Snoop R/W, 2G */
- pcie1->piwar1 = 0xa0f5501e;
-
- pci_set_region(hose->regions + 0,
- CFG_PCI_MEMORY_BUS,
- CFG_PCI_MEMORY_PHYS,
- CFG_PCI_MEMORY_SIZE,
- PCI_REGION_MEM | PCI_REGION_MEMORY);
-
- pci_set_region(hose->regions + 1,
- CFG_PCI1_MEM_BASE,
- CFG_PCI1_MEM_PHYS,
- CFG_PCI1_MEM_SIZE,
- PCI_REGION_MEM);
-
- pci_set_region(hose->regions + 2,
- CFG_PCI1_IO_BASE,
- CFG_PCI1_IO_PHYS,
- CFG_PCI1_IO_SIZE,
- PCI_REGION_IO);
-
- hose->region_count = 3;
-
- pci_register_hose(hose);
-
- hose->last_busno = pci_hose_scan(hose);
- debug("pcie_mpc86xx_init: last_busno %x\n", hose->last_busno);
- debug("pcie_mpc86xx init: current_busno %x\n ", hose->current_busno);
-
- printf("....PCIE1 scan & enumeration done\n");
-}
-#endif /* CONFIG_PCI */
diff --git a/cpu/mpc86xx/pcie_indirect.c b/cpu/mpc86xx/pcie_indirect.c
deleted file mode 100644
index b00ad76..0000000
--- a/cpu/mpc86xx/pcie_indirect.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Support for indirect PCI bridges.
- *
- * Copyright (c) Freescale Semiconductor, Inc.
- * 2006. All rights reserved.
- *
- * Jason Jin <Jason.jin@freescale.com>
- *
- * 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.
- *
- * partly derived from
- * arch/powerpc/platforms/86xx/mpc86xx_pcie.c
- */
-
-#include <common.h>
-
-#ifdef CONFIG_PCI
-
-#include <asm/processor.h>
-#include <asm/io.h>
-#include <pci.h>
-
-#define PCI_CFG_OUT out_be32
-#define PEX_FIX out_be32(hose->cfg_addr+0x4, 0x0400ffff)
-
-static int
-indirect_read_config_pcie(struct pci_controller *hose,
- pci_dev_t dev,
- int offset,
- int len,
- u32 *val)
-{
- int bus = PCI_BUS(dev);
-
- volatile unsigned char *cfg_data;
- u32 temp;
-
- PEX_FIX;
- if (bus == 0xff) {
- PCI_CFG_OUT(hose->cfg_addr,
- dev | (offset & 0xfc) | 0x80000001);
- } else {
- PCI_CFG_OUT(hose->cfg_addr,
- dev | (offset & 0xfc) | 0x80000000);
- }
- /*
- * Note: the caller has already checked that offset is
- * suitably aligned and that len is 1, 2 or 4.
- */
- /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
- cfg_data = hose->cfg_data;
- PEX_FIX;
- temp = in_le32((u32 *) cfg_data);
- switch (len) {
- case 1:
- *val = (temp >> (((offset & 3)) * 8)) & 0xff;
- break;
- case 2:
- *val = (temp >> (((offset & 3)) * 8)) & 0xffff;
- break;
- default:
- *val = temp;
- break;
- }
-
- return 0;
-}
-
-static int
-indirect_write_config_pcie(struct pci_controller *hose,
- pci_dev_t dev,
- int offset,
- int len,
- u32 val)
-{
- int bus = PCI_BUS(dev);
- volatile unsigned char *cfg_data;
- u32 temp;
-
- PEX_FIX;
- if (bus == 0xff) {
- PCI_CFG_OUT(hose->cfg_addr,
- dev | (offset & 0xfc) | 0x80000001);
- } else {
- PCI_CFG_OUT(hose->cfg_addr,
- dev | (offset & 0xfc) | 0x80000000);
- }
-
- /*
- * Note: the caller has already checked that offset is
- * suitably aligned and that len is 1, 2 or 4.
- */
- /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
- cfg_data = hose->cfg_data;
- switch (len) {
- case 1:
- PEX_FIX;
- temp = in_le32((u32 *) cfg_data);
- temp = (temp & ~(0xff << ((offset & 3) * 8))) |
- (val << ((offset & 3) * 8));
- PEX_FIX;
- out_le32((u32 *) cfg_data, temp);
- break;
- case 2:
- PEX_FIX;
- temp = in_le32((u32 *) cfg_data);
- temp = (temp & ~(0xffff << ((offset & 3) * 8)));
- temp |= (val << ((offset & 3) * 8));
- PEX_FIX;
- out_le32((u32 *) cfg_data, temp);
- break;
- default:
- PEX_FIX;
- out_le32((u32 *) cfg_data, val);
- break;
- }
- PEX_FIX;
- return 0;
-}
-
-static int
-indirect_read_config_byte_pcie(struct pci_controller *hose,
- pci_dev_t dev,
- int offset,
- u8 *val)
-{
- u32 val32;
- indirect_read_config_pcie(hose, dev, offset, 1, &val32);
- *val = (u8) val32;
- return 0;
-}
-
-static int
-indirect_read_config_word_pcie(struct pci_controller *hose,
- pci_dev_t dev,
- int offset,
- u16 *val)
-{
- u32 val32;
- indirect_read_config_pcie(hose, dev, offset, 2, &val32);
- *val = (u16) val32;
- return 0;
-}
-
-static int
-indirect_read_config_dword_pcie(struct pci_controller *hose,
- pci_dev_t dev,
- int offset,
- u32 *val)
-{
- return indirect_read_config_pcie(hose, dev, offset, 4, val);
-}
-
-static int
-indirect_write_config_byte_pcie(struct pci_controller *hose,
- pci_dev_t dev,
- int offset,
- u8 val)
-{
- return indirect_write_config_pcie(hose, dev, offset, 1, (u32) val);
-}
-
-static int
-indirect_write_config_word_pcie(struct pci_controller *hose,
- pci_dev_t dev,
- int offset,
- unsigned short val)
-{
- return indirect_write_config_pcie(hose, dev, offset, 2, (u32) val);
-}
-
-static int
-indirect_write_config_dword_pcie(struct pci_controller *hose,
- pci_dev_t dev,
- int offset,
- u32 val)
-{
- return indirect_write_config_pcie(hose, dev, offset, 4, val);
-}
-
-void
-pcie_setup_indirect(struct pci_controller *hose, u32 cfg_addr, u32 cfg_data)
-{
- pci_set_ops(hose,
- indirect_read_config_byte_pcie,
- indirect_read_config_word_pcie,
- indirect_read_config_dword_pcie,
- indirect_write_config_byte_pcie,
- indirect_write_config_word_pcie,
- indirect_write_config_dword_pcie);
-
- hose->cfg_addr = (unsigned int *)cfg_addr;
- hose->cfg_data = (unsigned char *)cfg_data;
-}
-
-#endif /* CONFIG_PCI */
diff --git a/cpu/mpc86xx/start.S b/cpu/mpc86xx/start.S
index 412745b..c83310a 100644
--- a/cpu/mpc86xx/start.S
+++ b/cpu/mpc86xx/start.S
@@ -1,5 +1,5 @@
/*
- * Copyright 2004 Freescale Semiconductor.
+ * Copyright 2004, 2007 Freescale Semiconductor.
* Srikanth Srinivasan <srikanth.srinivaan@freescale.com>
*
* See file CREDITS for list of people who contributed to this
@@ -44,11 +44,9 @@
#define CONFIG_IDENT_STRING ""
#endif
-/* We don't want the MMU yet.
-*/
-#undef MSR_KERNEL
-/* Machine Check and Recoverable Interr. */
-#define MSR_KERNEL ( MSR_ME | MSR_RI )
+/*
+ * Need MSR_DR | MSR_IR enabled to access I/O (printf) in exceptions
+ */
/*
* Set up GOT: Global Offset Table
@@ -195,17 +193,21 @@ boot_warm:
bl secondary_cpu_setup
#endif
+1:
+#ifdef CFG_RAMBOOT
/* disable everything */
-1: li r0, 0
+ li r0, 0
mtspr HID0, r0
sync
mtmsr 0
+#endif
+
bl invalidate_bats
sync
#ifdef CFG_L2
/* init the L2 cache */
- addis r3, r0, L2_INIT@h
+ lis r3, L2_INIT@h
ori r3, r3, L2_INIT@l
mtspr l2cr, r3
/* invalidate the L2 cache */
@@ -241,69 +243,9 @@ in_flash:
bl setup_ccsrbar
#endif
-
- /* -- MPC8641 Rev 1.0 MCM Errata fixups -- */
-
- /* skip fixups if not Rev 1.0 */
- mfspr r4, SVR
- rlwinm r4,r4,0,24,31
- cmpwi r4,0x10
- bne 1f
-
- lis r3,MCM_ABCR@ha
- lwz r4,MCM_ABCR@l(r3) /* ABCR -> r4 */
-
- /* set ABCR[A_STRM_CNT] = 0 */
- rlwinm r4,r4,0,0,29
-
- /* set ABCR[ARB_POLICY] to 0x1 (round-robin) */
- addi r0,r0,1
- rlwimi r4,r0,12,18,19
-
- stw r4,MCM_ABCR@l(r3) /* r4 -> ABCR */
- sync
-
- /* Set DBCR[ERD_DIS] */
- lis r3,MCM_DBCR@ha
- lwz r4,MCM_DBCR@l(r3)
- oris r4, r4, 0x4000
- stw r4,MCM_DBCR@l(r3)
- sync
-1:
/* setup the law entries */
bl law_entry
sync
-
-
-#if (EMULATOR_RUN == 1)
- /* On the emulator we want to adjust these ASAP */
- /* otherwise things are sloooow */
- /* Setup OR0 (LALE FIX)*/
- lis r3, CFG_CCSRBAR@h
- ori r3, r3, 0x5004
- li r4, 0x0FF3
- stw r4, 0(r3)
- sync
-
- /* Setup LCRR */
- lis r3, CFG_CCSRBAR@h
- ori r3, r3, 0x50D4
- lis r4, 0x8000
- ori r4, r4, 0x0002
- stw r4, 0(r3)
- sync
-#endif
-#if 1
- /* make sure timer enabled in guts register too */
- lis r3, CFG_CCSRBAR@h
- oris r3,r3, 0xE
- ori r3,r3,0x0070
- lwz r4, 0(r3)
- lis r5,0xFFFC
- ori r5,r5,0x5FFF
- and r4,r4,r5
- stw r4,0(r3)
-#endif
/*
* Cache must be enabled here for stack-in-cache trick.
* This means we need to enable the BATS.
@@ -346,8 +288,6 @@ in_flash:
#ifdef RUN_DIAG
- /* Sri: Code to run the diagnostic automatically */
-
/* Load PX_AUX register address in r4 */
lis r4, 0xf810
ori r4, r4, 0x6
@@ -392,6 +332,7 @@ diag_done:
.globl invalidate_bats
invalidate_bats:
+ li r0, 0
/* invalidate BATs */
mtspr IBAT0U, r0
mtspr IBAT1U, r0
@@ -1040,6 +981,7 @@ trap_init:
mfmsr r7
li r8,MSR_IP
andc r7,r7,r8
+ ori r7,r7,MSR_ME /* Enable Machine Check */
mtmsr r7
mtlr r4 /* restore link register */
@@ -1224,8 +1166,9 @@ secondary_cpu_setup:
sync
isync
- /*SYNCBE|ABE in HID1*/
+ /* MCP|SYNCBE|ABE in HID1 */
mfspr r4, HID1
+ oris r4, r4, 0x8000
ori r4, r4, 0x0C00
mtspr HID1, r4
sync
diff --git a/cpu/mpc86xx/traps.c b/cpu/mpc86xx/traps.c
index 8ea14e5..c84bfbf 100644
--- a/cpu/mpc86xx/traps.c
+++ b/cpu/mpc86xx/traps.c
@@ -34,7 +34,7 @@
#include <command.h>
#include <asm/processor.h>
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
int (*debugger_exception_handler)(struct pt_regs *) = 0;
#endif
@@ -122,7 +122,7 @@ MachineCheckException(struct pt_regs *regs)
return;
}
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler) (regs))
return;
#endif
@@ -130,8 +130,11 @@ MachineCheckException(struct pt_regs *regs)
printf("Machine check in kernel mode.\n");
printf("Caused by (from msr): ");
printf("regs %p ", regs);
- switch (regs->msr & 0x000F0000) {
- case (0x80000000 >> 12):
+ switch ( regs->msr & 0x001F0000) {
+ case (0x80000000>>11):
+ printf("MSS error. MSSSR0: %08x\n", mfspr(SPRN_MSSSR0));
+ break;
+ case (0x80000000>>12):
printf("Machine check signal - probably due to mm fault\n"
"with mmu off\n");
break;
@@ -155,7 +158,7 @@ MachineCheckException(struct pt_regs *regs)
void
AlignmentException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler) (regs))
return;
#endif
@@ -170,7 +173,7 @@ ProgramCheckException(struct pt_regs *regs)
unsigned char *p = regs ? (unsigned char *)(regs->nip) : NULL;
int i, j;
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler) (regs))
return;
#endif
@@ -193,7 +196,7 @@ ProgramCheckException(struct pt_regs *regs)
void
SoftEmuException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler) (regs))
return;
#endif
@@ -205,10 +208,11 @@ SoftEmuException(struct pt_regs *regs)
void
UnknownException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler) (regs))
return;
#endif
+ printf("UnknownException regs@%x\n", regs);
printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
regs->nip, regs->msr, regs->trap);
_exception(0, regs);
diff --git a/cpu/mpc8xx/bedbug_860.c b/cpu/mpc8xx/bedbug_860.c
index e91a100..5d52366 100644
--- a/cpu/mpc8xx/bedbug_860.c
+++ b/cpu/mpc8xx/bedbug_860.c
@@ -10,7 +10,7 @@
#include <bedbug/ppc.h>
#include <bedbug/type.h>
-#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG) && defined(CONFIG_8xx)
+#if defined(CONFIG_CMD_BEDBUG) && defined(CONFIG_8xx)
#define MAX_BREAK_POINTS 2
diff --git a/cpu/mpc8xx/fec.c b/cpu/mpc8xx/fec.c
index 6d2755e..08a3715 100644
--- a/cpu/mpc8xx/fec.c
+++ b/cpu/mpc8xx/fec.c
@@ -31,7 +31,7 @@ DECLARE_GLOBAL_DATA_PTR;
#undef ET_DEBUG
-#if (CONFIG_COMMANDS & CFG_CMD_NET) && \
+#if defined(CONFIG_CMD_NET) && \
(defined(FEC_ENET) || defined(CONFIG_ETHER_ON_FEC1) || defined(CONFIG_ETHER_ON_FEC2))
/* compatibility test, if only FEC_ENET defined assume ETHER on FEC1 */
@@ -49,7 +49,7 @@ DECLARE_GLOBAL_DATA_PTR;
#if defined(WANT_MII)
#include <miiphy.h>
-#if !(defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII))
+#if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
#error "CONFIG_MII has to be defined!"
#endif
@@ -182,7 +182,7 @@ int fec_initialize(bd_t *bis)
eth_register(dev);
-#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
miiphy_register(dev->name,
fec8xx_miiphy_read, fec8xx_miiphy_write);
#endif
@@ -268,7 +268,7 @@ static int fec_recv (struct eth_device *dev)
length -= 4;
-#if (CONFIG_COMMANDS & CFG_CMD_CDP)
+#if defined(CONFIG_CMD_CDP)
if ((rx[0] & 1) != 0
&& memcmp ((uchar *) rx, NetBcastAddr, 6) != 0
&& memcmp ((uchar *) rx, NetCDPAddr, 6) != 0)
@@ -608,7 +608,7 @@ static int fec_init (struct eth_device *dev, bd_t * bd)
fecp->fec_addr_high = (ea[4] << 8) | (ea[5]);
#undef ea
-#if (CONFIG_COMMANDS & CFG_CMD_CDP)
+#if defined(CONFIG_CMD_CDP)
/*
* Turn on multicast address hash table
*/
@@ -787,7 +787,7 @@ static void fec_halt(struct eth_device* dev)
efis->initialized = 0;
}
-#if defined(CFG_DISCOVER_PHY) || defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+#if defined(CFG_DISCOVER_PHY) || defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
/* Make MII read/write commands for the FEC.
*/
@@ -852,7 +852,7 @@ mii_send(uint mii_cmd)
#endif
return (mii_reply & 0xffff); /* data read from phy */
}
-#endif /* CFG_DISCOVER_PHY || (CONFIG_COMMANDS & CFG_CMD_MII) */
+#endif
#if defined(CFG_DISCOVER_PHY)
static int mii_discover_phy(struct eth_device *dev)
@@ -926,7 +926,7 @@ static int mii_discover_phy(struct eth_device *dev)
}
#endif /* CFG_DISCOVER_PHY */
-#if (defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)) && !defined(CONFIG_BITBANGMII)
+#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && !defined(CONFIG_BITBANGMII)
/****************************************************************************
* mii_init -- Initialize the MII for MII command without ethernet
@@ -1020,6 +1020,6 @@ int fec8xx_miiphy_write(char *devname, unsigned char addr,
#endif
return 0;
}
-#endif /* (CONFIG_COMMANDS & CFG_CMD_MII) && !defined(CONFIG_BITBANGMII)*/
+#endif
-#endif /* CFG_CMD_NET, FEC_ENET */
+#endif
diff --git a/cpu/mpc8xx/kgdb.S b/cpu/mpc8xx/kgdb.S
index 11c3c69..812baa3 100644
--- a/cpu/mpc8xx/kgdb.S
+++ b/cpu/mpc8xx/kgdb.S
@@ -34,7 +34,7 @@
#include <asm/cache.h>
#include <asm/mmu.h>
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
/*
* cache flushing routines for kgdb
@@ -71,4 +71,4 @@ kgdb_flush_cache_range:
SYNC
blr
-#endif /* CFG_CMD_KGDB */
+#endif
diff --git a/cpu/mpc8xx/scc.c b/cpu/mpc8xx/scc.c
index 6b9110f..744dcdd 100644
--- a/cpu/mpc8xx/scc.c
+++ b/cpu/mpc8xx/scc.c
@@ -38,7 +38,7 @@
#include <net.h>
#include <command.h>
-#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(SCC_ENET)
+#if defined(CONFIG_CMD_NET) && defined(SCC_ENET)
/* Ethernet Transmit and Receive Buffers */
#define DBUF_LENGTH 1520
@@ -567,4 +567,4 @@ void restart (void)
(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
}
#endif
-#endif /* CFG_CMD_NET, SCC_ENET */
+#endif
diff --git a/cpu/mpc8xx/serial.c b/cpu/mpc8xx/serial.c
index ffc898c..68804cc 100644
--- a/cpu/mpc8xx/serial.c
+++ b/cpu/mpc8xx/serial.c
@@ -666,7 +666,7 @@ void enable_putc(void)
}
#endif
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
void
kgdb_serial_init(void)
@@ -723,6 +723,6 @@ kgdb_interruptible (int yes)
{
return;
}
-#endif /* CFG_CMD_KGDB */
+#endif
#endif /* CONFIG_8xx_CONS_NONE */
diff --git a/cpu/mpc8xx/traps.c b/cpu/mpc8xx/traps.c
index 67b75cc..e1ec889 100644
--- a/cpu/mpc8xx/traps.c
+++ b/cpu/mpc8xx/traps.c
@@ -36,11 +36,11 @@
#include <command.h>
#include <asm/processor.h>
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
int (*debugger_exception_handler)(struct pt_regs *) = 0;
#endif
-#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+#if defined(CONFIG_CMD_BEDBUG)
extern void do_bedbug_breakpoint(struct pt_regs *);
#endif
@@ -126,7 +126,7 @@ MachineCheckException(struct pt_regs *regs)
return;
}
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -159,7 +159,7 @@ MachineCheckException(struct pt_regs *regs)
void
AlignmentException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -171,7 +171,7 @@ AlignmentException(struct pt_regs *regs)
void
ProgramCheckException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -183,7 +183,7 @@ ProgramCheckException(struct pt_regs *regs)
void
SoftEmuException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -196,7 +196,7 @@ SoftEmuException(struct pt_regs *regs)
void
UnknownException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -210,7 +210,7 @@ DebugException(struct pt_regs *regs)
{
printf("Debugger trap at @ %lx\n", regs->nip );
show_regs(regs);
-#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+#if defined(CONFIG_CMD_BEDBUG)
do_bedbug_breakpoint( regs );
#endif
}
diff --git a/cpu/nios/cpu.c b/cpu/nios/cpu.c
index d2bb2c0..5519e82 100644
--- a/cpu/nios/cpu.c
+++ b/cpu/nios/cpu.c
@@ -34,7 +34,7 @@ int checkcpu (void)
/* Get cpu version info */
val = rdctl (CTL_CPU_ID);
- printf ("CPU: ");
+ puts ("CPU: ");
printf ("%s", (val & 0x00008000) ? "Nios-16 " : "Nios-32 ");
rev_major = (val>>12) & 0x07;
rev_minor = (val>>4) & 0x0ff;
diff --git a/cpu/nios/interrupts.c b/cpu/nios/interrupts.c
index 48fc81e..75e491d 100644
--- a/cpu/nios/interrupts.c
+++ b/cpu/nios/interrupts.c
@@ -173,7 +173,7 @@ void irq_install_handler (int vec, interrupt_handler_t *handler, void *arg)
}
/*************************************************************************/
-#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
+#if defined(CONFIG_CMD_IRQ)
int do_irqinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
int vec;
@@ -193,4 +193,4 @@ int do_irqinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
return (0);
}
-#endif /* CONFIG_COMMANDS & CFG_CMD_IRQ */
+#endif
diff --git a/cpu/nios2/interrupts.c b/cpu/nios2/interrupts.c
index 4685161..aeb5b65 100644
--- a/cpu/nios2/interrupts.c
+++ b/cpu/nios2/interrupts.c
@@ -204,7 +204,7 @@ int interrupt_init (void)
/*************************************************************************/
-#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
+#if defined(CONFIG_CMD_IRQ)
int do_irqinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
int i;
@@ -228,4 +228,4 @@ int do_irqinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
return (0);
}
-#endif /* CONFIG_COMMANDS & CFG_CMD_IRQ */
+#endif
diff --git a/cpu/ppc4xx/4xx_enet.c b/cpu/ppc4xx/4xx_enet.c
index b90363f..cc8e734 100644
--- a/cpu/ppc4xx/4xx_enet.c
+++ b/cpu/ppc4xx/4xx_enet.c
@@ -94,9 +94,9 @@
* network support enabled.
* Remark: CONFIG_405 describes Xilinx PPC405 FPGA without EMAC controller!
*/
-#if (CONFIG_COMMANDS & CFG_CMD_NET) && !defined(CONFIG_405) && !defined(CONFIG_IOP480)
+#if defined(CONFIG_CMD_NET) && !defined(CONFIG_405) && !defined(CONFIG_IOP480)
-#if !(defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII))
+#if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
#error "CONFIG_MII has to be defined!"
#endif
@@ -1685,7 +1685,7 @@ int ppc_4xx_eth_initialize (bd_t * bis)
#endif
#if defined(CONFIG_NET_MULTI)
-#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
miiphy_register (dev->name,
emac4xx_miiphy_read, emac4xx_miiphy_write);
#endif
@@ -1726,7 +1726,7 @@ int eth_rx(void)
int emac4xx_miiphy_initialize (bd_t * bis)
{
-#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
miiphy_register ("ppc_4xx_eth0",
emac4xx_miiphy_read, emac4xx_miiphy_write);
#endif
@@ -1735,4 +1735,4 @@ int emac4xx_miiphy_initialize (bd_t * bis)
}
#endif /* !defined(CONFIG_NET_MULTI) */
-#endif /* #if (CONFIG_COMMANDS & CFG_CMD_NET) */
+#endif
diff --git a/cpu/ppc4xx/Makefile b/cpu/ppc4xx/Makefile
index 4068b53..af9da5b 100644
--- a/cpu/ppc4xx/Makefile
+++ b/cpu/ppc4xx/Makefile
@@ -27,12 +27,12 @@ LIB = $(obj)lib$(CPU).a
START = start.o resetvec.o kgdb.o
SOBJS = dcr.o
-COBJS = 405gp_pci.o 4xx_enet.o \
+COBJS = 405gp_pci.o 440spe_pcie.o 4xx_enet.o \
bedbug_405.o commproc.o \
cpu.o cpu_init.o gpio.o i2c.o interrupts.o \
miiphy.o ndfc.o sdram.o serial.o \
40x_spd_sdram.o 44x_spd_ddr.o 44x_spd_ddr2.o speed.o \
- tlb.o traps.o usb_ohci.o usbdev.o \
+ tlb.o traps.o usb_ohci.o usb.o usbdev.o \
440spe_pcie.o
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
diff --git a/cpu/ppc4xx/bedbug_405.c b/cpu/ppc4xx/bedbug_405.c
index a3c2119..5ef5607 100644
--- a/cpu/ppc4xx/bedbug_405.c
+++ b/cpu/ppc4xx/bedbug_405.c
@@ -10,7 +10,7 @@
#include <bedbug/regs.h>
#include <bedbug/ppc.h>
-#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG) && defined(CONFIG_4xx)
+#if defined(CONFIG_CMD_BEDBUG) && defined(CONFIG_4xx)
#define MAX_BREAK_POINTS 4
diff --git a/cpu/ppc4xx/dcr.S b/cpu/ppc4xx/dcr.S
index 7102364..93465a3 100644
--- a/cpu/ppc4xx/dcr.S
+++ b/cpu/ppc4xx/dcr.S
@@ -22,7 +22,7 @@
*/
#include <config.h>
-#if defined(CONFIG_4xx) && defined(CFG_CMD_SETGETDCR)
+#if defined(CONFIG_4xx) && defined(CONFIG_CMD_SETGETDCR)
#include <ppc4xx.h>
@@ -195,4 +195,4 @@ set_dcr:
blr /* Return to calling function */
.Lfe4: .size set_dcr,.Lfe4-set_dcr
/* end set_dcr() */
-#endif /* CONFIG_4xx & CFG_CMD_SETGETDCR */
+#endif
diff --git a/cpu/ppc4xx/interrupts.c b/cpu/ppc4xx/interrupts.c
index c5a9f02..ca565cc 100644
--- a/cpu/ppc4xx/interrupts.c
+++ b/cpu/ppc4xx/interrupts.c
@@ -628,7 +628,7 @@ void timer_interrupt_cpu (struct pt_regs *regs)
/****************************************************************************/
-#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
+#if defined(CONFIG_CMD_IRQ)
/*******************************************************************************
*
@@ -698,4 +698,4 @@ do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
return 0;
}
-#endif /* CONFIG_COMMANDS & CFG_CMD_IRQ */
+#endif
diff --git a/cpu/ppc4xx/kgdb.S b/cpu/ppc4xx/kgdb.S
index be28340..8c4bbf2 100644
--- a/cpu/ppc4xx/kgdb.S
+++ b/cpu/ppc4xx/kgdb.S
@@ -34,7 +34,7 @@
#include <asm/cache.h>
#include <asm/mmu.h>
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
/*
* cache flushing routines for kgdb
*/
@@ -75,4 +75,4 @@ kgdb_flush_cache_range:
SYNC
blr
-#endif /* CFG_CMD_KGDB */
+#endif
diff --git a/cpu/ppc4xx/ndfc.c b/cpu/ppc4xx/ndfc.c
index f63fc79..3984577 100644
--- a/cpu/ppc4xx/ndfc.c
+++ b/cpu/ppc4xx/ndfc.c
@@ -31,7 +31,7 @@
#include <common.h>
-#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY) && \
+#if defined(CONFIG_CMD_NAND) && !defined(CFG_NAND_LEGACY) && \
(defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
defined(CONFIG_405EZ))
diff --git a/cpu/ppc4xx/serial.c b/cpu/ppc4xx/serial.c
index 376ca1e..60712b1 100644
--- a/cpu/ppc4xx/serial.c
+++ b/cpu/ppc4xx/serial.c
@@ -848,7 +848,7 @@ int serial_buffered_tstc (void)
#endif /* CONFIG_SERIAL_SOFTWARE_FIFO */
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
/*
AS HARNOIS : according to CONFIG_KGDB_SER_INDEX kgdb uses serial port
number 0 or number 1
@@ -954,7 +954,7 @@ void kgdb_interruptible (int yes)
return;
}
#endif /* (CONFIG_KGDB_SER_INDEX & 2) */
-#endif /* CFG_CMD_KGDB */
+#endif
#if defined(CONFIG_SERIAL_MULTI)
diff --git a/cpu/ppc4xx/traps.c b/cpu/ppc4xx/traps.c
index de5fde9..f5365cb 100755..100644
--- a/cpu/ppc4xx/traps.c
+++ b/cpu/ppc4xx/traps.c
@@ -38,7 +38,7 @@
DECLARE_GLOBAL_DATA_PTR;
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
int (*debugger_exception_handler)(struct pt_regs *) = 0;
#endif
@@ -78,7 +78,7 @@ static __inline__ unsigned long get_esr(void)
#define ESR_DIZ 0x00400000
#define ESR_U0F 0x00008000
-#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+#if defined(CONFIG_CMD_BEDBUG)
extern void do_bedbug_breakpoint(struct pt_regs *);
#endif
@@ -165,7 +165,7 @@ MachineCheckException(struct pt_regs *regs)
return;
}
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -312,7 +312,7 @@ MachineCheckException(struct pt_regs *regs)
void
AlignmentException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -327,7 +327,7 @@ ProgramCheckException(struct pt_regs *regs)
{
long esr_val;
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -364,7 +364,7 @@ DecrementerPITException(struct pt_regs *regs)
void
UnknownException(struct pt_regs *regs)
{
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -379,7 +379,7 @@ DebugException(struct pt_regs *regs)
{
printf("Debugger trap at @ %lx\n", regs->nip );
show_regs(regs);
-#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+#if defined(CONFIG_CMD_BEDBUG)
do_bedbug_breakpoint( regs );
#endif
}
diff --git a/cpu/ppc4xx/usb.c b/cpu/ppc4xx/usb.c
new file mode 100644
index 0000000..272ed8c
--- /dev/null
+++ b/cpu/ppc4xx/usb.c
@@ -0,0 +1,50 @@
+/*
+ * (C) Copyright 2007
+ * Markus Klotzbuecher, DENX Software Engineering <mk@denx.de>
+ *
+ * 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 <common.h>
+
+#if defined(CONFIG_USB_OHCI_NEW) && defined(CFG_USB_OHCI_CPU_INIT)
+
+#include "usbdev.h"
+
+int usb_cpu_init(void)
+{
+
+#if defined(CONFIG_440EP) || defined(CONFIG_440EPX)
+ usb_dev_init();
+#endif
+
+ return 0;
+}
+
+int usb_cpu_stop(void)
+{
+ return 0;
+}
+
+int usb_cpu_init_fail(void)
+{
+ return 0;
+}
+
+#endif /* defined(CONFIG_USB_OHCI) && defined(CFG_USB_OHCI_CPU_INIT) */
diff --git a/cpu/ppc4xx/usbdev.c b/cpu/ppc4xx/usbdev.c
index 6140d2a..5924a6c 100644
--- a/cpu/ppc4xx/usbdev.c
+++ b/cpu/ppc4xx/usbdev.c
@@ -3,7 +3,7 @@
#include <common.h>
#include <asm/processor.h>
-#if (defined(CONFIG_440EP) || defined(CONFIG_440EPX)) && (CONFIG_COMMANDS & CFG_CMD_USB)
+#if (defined(CONFIG_440EP) || defined(CONFIG_440EPX)) && defined(CONFIG_CMD_USB)
#include <usb.h>
#include "usbdev.h"
diff --git a/cpu/pxa/Makefile b/cpu/pxa/Makefile
index cded7ff..8b4367e 100644
--- a/cpu/pxa/Makefile
+++ b/cpu/pxa/Makefile
@@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(CPU).a
START = start.o
-COBJS = serial.o interrupts.o cpu.o i2c.o pxafb.o mmc.o
+COBJS = serial.o interrupts.o cpu.o i2c.o pxafb.o mmc.o usb.o
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
diff --git a/cpu/pxa/usb.c b/cpu/pxa/usb.c
new file mode 100644
index 0000000..65f457f
--- /dev/null
+++ b/cpu/pxa/usb.c
@@ -0,0 +1,79 @@
+/*
+ * (C) Copyright 2006
+ * Markus Klotzbuecher, DENX Software Engineering <mk@denx.de>
+ *
+ * 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 <common.h>
+
+#if defined(CONFIG_USB_OHCI_NEW) && defined(CFG_USB_OHCI_CPU_INIT)
+# if defined(CONFIG_CPU_MONAHANS) || defined(CONFIG_PXA27X)
+
+#include <asm/arch/pxa-regs.h>
+
+int usb_cpu_init()
+{
+#if defined(CONFIG_CPU_MONAHANS)
+ /* Enable USB host clock. */
+ CKENA |= (CKENA_2_USBHOST | CKENA_20_UDC);
+ udelay(100);
+#endif
+#if defined(CONFIG_PXA27X)
+ /* Enable USB host clock. */
+ CKEN |= CKEN10_USBHOST;
+#endif
+
+#if defined(CONFIG_CPU_MONAHANS)
+ /* Configure Port 2 for Host (USB Client Registers) */
+ UP2OCR = 0x3000c;
+#endif
+
+ UHCHR |= UHCHR_FHR;
+ wait_ms(11);
+ UHCHR &= ~UHCHR_FHR;
+
+ UHCHR |= UHCHR_FSBIR;
+ while (UHCHR & UHCHR_FSBIR)
+ udelay(1);
+
+#if defined(CONFIG_CPU_MONAHANS)
+ UHCHR &= ~UHCHR_SSEP0;
+#endif
+#if defined(CONFIG_PXA27X)
+ UHCHR &= ~UHCHR_SSEP2;
+#endif
+ UHCHR &= ~UHCHR_SSEP1;
+ UHCHR &= ~UHCHR_SSE;
+
+ return 0;
+}
+
+int usb_cpu_stop()
+{
+ return 0;
+}
+
+int usb_cpu_init_fail()
+{
+ return 0;
+}
+
+# endif /* defined(CONFIG_CPU_MONAHANS) || defined(CONFIG_PXA27X) */
+#endif /* defined(CONFIG_USB_OHCI) && defined(CFG_USB_OHCI_CPU_INIT) */