summaryrefslogtreecommitdiff
path: root/cpu/mpc85xx
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/mpc85xx')
-rwxr-xr-xcpu/mpc85xx/Makefile45
-rwxr-xr-xcpu/mpc85xx/commproc.c214
-rwxr-xr-xcpu/mpc85xx/config.mk26
-rwxr-xr-xcpu/mpc85xx/cpu.c229
-rwxr-xr-xcpu/mpc85xx/cpu_init.c236
-rwxr-xr-xcpu/mpc85xx/ether_fcc.c473
-rwxr-xr-xcpu/mpc85xx/i2c.c265
-rwxr-xr-xcpu/mpc85xx/interrupts.c162
-rwxr-xr-xcpu/mpc85xx/pci.c122
-rwxr-xr-xcpu/mpc85xx/resetvec.S2
-rwxr-xr-xcpu/mpc85xx/serial_scc.c274
-rwxr-xr-xcpu/mpc85xx/spd_sdram.c1118
-rwxr-xr-xcpu/mpc85xx/speed.c123
-rwxr-xr-xcpu/mpc85xx/start.S1157
-rwxr-xr-xcpu/mpc85xx/traps.c273
15 files changed, 4719 insertions, 0 deletions
diff --git a/cpu/mpc85xx/Makefile b/cpu/mpc85xx/Makefile
new file mode 100755
index 0000000..5298dc1
--- /dev/null
+++ b/cpu/mpc85xx/Makefile
@@ -0,0 +1,45 @@
+#
+# (C) Copyright 2002,2003 Motorola Inc.
+# Xianghua Xiao,X.Xiao@motorola.com
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = lib$(CPU).a
+
+START = start.o resetvec.o
+COBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o \
+ pci.o serial_scc.o commproc.o ether_fcc.o i2c.o spd_sdram.o
+OBJS = $(COBJS)
+
+all: .depend $(START) $(LIB)
+
+$(LIB): $(OBJS)
+ $(AR) crv $@ $(OBJS)
+
+#########################################################################
+
+.depend: Makefile $(START:.o=.S) $(AOBJS:.o=.S) $(COBJS:.o=.c)
+ $(CC) -M $(CFLAGS) $(START:.o=.S) $(AOBJS:.o=.S) $(COBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################
diff --git a/cpu/mpc85xx/commproc.c b/cpu/mpc85xx/commproc.c
new file mode 100755
index 0000000..aa8a5a5
--- /dev/null
+++ b/cpu/mpc85xx/commproc.c
@@ -0,0 +1,214 @@
+/*
+ * Adapted for Motorola MPC8560 chips
+ * Xianghua Xiao <x.xiao@motorola.com>
+ *
+ * This file is based on "arch/ppc/8260_io/commproc.c" - here is it's
+ * copyright notice:
+ *
+ * General Purpose functions for the global management of the
+ * 8220 Communication Processor Module.
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ * Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com)
+ * 2.3.99 Updates
+ * Copyright (c) 2003 Motorola,Inc.
+ *
+ * In addition to the individual control of the communication
+ * channels, there are a few functions that globally affect the
+ * communication processor.
+ *
+ * Buffer descriptors must be allocated from the dual ported memory
+ * space. The allocator for that is here. When the communication
+ * process is reset, we reclaim the memory available. There is
+ * currently no deallocator for this memory.
+ */
+#include <common.h>
+#include <asm/cpm_85xx.h>
+
+#if defined(CONFIG_CPM2)
+/*
+ * because we have stack and init data in dual port ram
+ * we must reduce the size
+ */
+#undef CPM_DATAONLY_SIZE
+#define CPM_DATAONLY_SIZE ((uint)(8 * 1024) - CPM_DATAONLY_BASE)
+
+void
+m8560_cpm_reset(void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ volatile ulong count;
+
+ gd = (gd_t *) (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET);
+
+ /* Reclaim the DP memory for our use.
+ */
+ gd->dp_alloc_base = CPM_DATAONLY_BASE;
+ gd->dp_alloc_top = gd->dp_alloc_base + CPM_DATAONLY_SIZE;
+
+ /*
+ * Reset CPM
+ */
+ immr->im_cpm.im_cpm_cp.cpcr = CPM_CR_RST;
+ count = 0;
+ do { /* Spin until command processed */
+ __asm__ __volatile__ ("eieio");
+ } while ((immr->im_cpm.im_cpm_cp.cpcr & CPM_CR_FLG) && ++count < 1000000);
+}
+
+/* Allocate some memory from the dual ported ram.
+ * To help protocols with object alignment restrictions, we do that
+ * if they ask.
+ */
+uint
+m8560_cpm_dpalloc(uint size, uint align)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ uint retloc;
+ uint align_mask, off;
+ uint savebase;
+
+ align_mask = align - 1;
+ savebase = gd->dp_alloc_base;
+
+ if ((off = (gd->dp_alloc_base & align_mask)) != 0)
+ gd->dp_alloc_base += (align - off);
+
+ if ((off = size & align_mask) != 0)
+ size += align - off;
+
+ if ((gd->dp_alloc_base + size) >= gd->dp_alloc_top) {
+ gd->dp_alloc_base = savebase;
+ panic("m8560_cpm_dpalloc: ran out of dual port ram!");
+ }
+
+ retloc = gd->dp_alloc_base;
+ gd->dp_alloc_base += size;
+
+ memset((void *)&(immr->im_cpm.im_dprambase[retloc]), 0, size);
+
+ return(retloc);
+}
+
+/* We also own one page of host buffer space for the allocation of
+ * UART "fifos" and the like.
+ */
+uint
+m8560_cpm_hostalloc(uint size, uint align)
+{
+ /* the host might not even have RAM yet - just use dual port RAM */
+ return (m8560_cpm_dpalloc(size, align));
+}
+
+/* Set a baud rate generator. This needs lots of work. There are
+ * eight BRGs, which can be connected to the CPM channels or output
+ * as clocks. The BRGs are in two different block of internal
+ * memory mapped space.
+ * The baud rate clock is the system clock divided by something.
+ * It was set up long ago during the initial boot phase and is
+ * is given to us.
+ * Baud rate clocks are zero-based in the driver code (as that maps
+ * to port numbers). Documentation uses 1-based numbering.
+ */
+#define BRG_INT_CLK gd->brg_clk
+#define BRG_UART_CLK ((BRG_INT_CLK + 15) / 16)
+
+/* This function is used by UARTS, or anything else that uses a 16x
+ * oversampled clock.
+ */
+void
+m8560_cpm_setbrg(uint brg, uint rate)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ volatile uint *bp;
+
+ /* This is good enough to get SMCs running.....
+ */
+ if (brg < 4) {
+ bp = (uint *)&(immr->im_cpm.im_cpm_brg1.brgc1);
+ }
+ else {
+ bp = (uint *)&(immr->im_cpm.im_cpm_brg2.brgc5);
+ brg -= 4;
+ }
+ bp += brg;
+ *bp = (((((BRG_UART_CLK+rate-1)/rate)-1)&0xfff)<<1)|CPM_BRG_EN;
+}
+
+/* This function is used to set high speed synchronous baud rate
+ * clocks.
+ */
+void
+m8560_cpm_fastbrg(uint brg, uint rate, int div16)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ volatile uint *bp;
+
+ /* This is good enough to get SMCs running.....
+ */
+ if (brg < 4) {
+ bp = (uint *)&(immr->im_cpm.im_cpm_brg1.brgc1);
+ }
+ else {
+ bp = (uint *)&(immr->im_cpm.im_cpm_brg2.brgc5);
+ brg -= 4;
+ }
+ bp += brg;
+ *bp = (((((BRG_INT_CLK+rate-1)/rate)-1)&0xfff)<<1)|CPM_BRG_EN;
+ if (div16)
+ *bp |= CPM_BRG_DIV16;
+}
+
+/* This function is used to set baud rate generators using an external
+ * clock source and 16x oversampling.
+ */
+
+void
+m8560_cpm_extcbrg(uint brg, uint rate, uint extclk, int pinsel)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ volatile uint *bp;
+
+ if (brg < 4) {
+ bp = (uint *)&(immr->im_cpm.im_cpm_brg1.brgc1);
+ }
+ else {
+ bp = (uint *)&(immr->im_cpm.im_cpm_brg2.brgc5);
+ brg -= 4;
+ }
+ bp += brg;
+ *bp = ((((((extclk/16)+rate-1)/rate)-1)&0xfff)<<1)|CPM_BRG_EN;
+ if (pinsel == 0)
+ *bp |= CPM_BRG_EXTC_CLK3_9;
+ else
+ *bp |= CPM_BRG_EXTC_CLK5_15;
+}
+
+#ifdef CONFIG_POST
+
+void post_word_store (ulong a)
+{
+ volatile ulong *save_addr =
+ (volatile ulong *)(CFG_IMMR + CPM_POST_WORD_ADDR);
+
+ *save_addr = a;
+}
+
+ulong post_word_load (void)
+{
+ volatile ulong *save_addr =
+ (volatile ulong *)(CFG_IMMR + CPM_POST_WORD_ADDR);
+
+ return *save_addr;
+}
+
+#endif /* CONFIG_POST */
+
+#endif /* CONFIG_CPM2 */
diff --git a/cpu/mpc85xx/config.mk b/cpu/mpc85xx/config.mk
new file mode 100755
index 0000000..6121074
--- /dev/null
+++ b/cpu/mpc85xx/config.mk
@@ -0,0 +1,26 @@
+#
+# (C) Copyright 2002,2003 Motorola Inc.
+# Xianghua Xiao, X.Xiao@motorola.com
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi
+
+PLATFORM_CPPFLAGS += -DCONFIG_MPC85xx -DCONFIG_E500 -ffixed-r2 -ffixed-r29 -Wa,-me500 -msoft-float -mno-string
diff --git a/cpu/mpc85xx/cpu.c b/cpu/mpc85xx/cpu.c
new file mode 100755
index 0000000..f7fe22e
--- /dev/null
+++ b/cpu/mpc85xx/cpu.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2004 Freescale Semiconductor.
+ * (C) Copyright 2002, 2003 Motorola Inc.
+ * Xianghua Xiao (X.Xiao@motorola.com)
+ *
+ * (C) Copyright 2000
+ * 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
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <asm/cache.h>
+
+/* ------------------------------------------------------------------------- */
+
+int checkcpu (void)
+{
+ sys_info_t sysinfo;
+ uint lcrr; /* local bus clock ratio register */
+ uint clkdiv; /* clock divider portion of lcrr */
+ uint pvr, svr;
+ uint fam;
+ uint ver;
+ uint major, minor;
+
+ svr = get_svr();
+ ver = SVR_VER(svr);
+ major = SVR_MAJ(svr);
+ minor = SVR_MIN(svr);
+
+ puts("CPU: ");
+ switch (ver) {
+ case SVR_8540:
+ puts("8540");
+ break;
+ case SVR_8541:
+ puts("8541");
+ break;
+ case SVR_8555:
+ puts("8555");
+ break;
+ case SVR_8560:
+ puts("8560");
+ break;
+ case SVR_8548:
+ puts("8548");
+ break;
+ case SVR_8548_E:
+ puts("8548_E");
+ break;
+ default:
+ puts("Unknown");
+ break;
+ }
+ printf(", Version: %d.%d, (0x%08x)\n", major, minor, svr);
+
+ pvr = get_pvr();
+ fam = PVR_FAM(pvr);
+ ver = PVR_VER(pvr);
+ major = PVR_MAJ(pvr);
+ minor = PVR_MIN(pvr);
+
+ printf("Core: ");
+ switch (fam) {
+ case PVR_FAM(PVR_85xx):
+ puts("E500");
+ break;
+ default:
+ puts("Unknown");
+ break;
+ }
+ printf(", Version: %d.%d, (0x%08x)\n", major, minor, pvr);
+
+ get_sys_info(&sysinfo);
+
+ puts("Clock Configuration:\n");
+ printf(" CPU:%4lu MHz, ", sysinfo.freqProcessor / 1000000);
+ printf("CCB:%4lu MHz,\n", sysinfo.freqSystemBus / 1000000);
+ printf(" DDR:%4lu MHz, ", sysinfo.freqSystemBus / 2000000);
+
+#if defined(CFG_LBC_LCRR)
+ lcrr = CFG_LBC_LCRR;
+#else
+ {
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+ volatile ccsr_lbc_t *lbc= &immap->im_lbc;
+
+ lcrr = lbc->lcrr;
+ }
+#endif
+ clkdiv = lcrr & 0x0f;
+ if (clkdiv == 2 || clkdiv == 4 || clkdiv == 8) {
+#ifdef CONFIG_MPC8548
+ /*
+ * Yes, the entire PQ38 family use the same
+ * bit-representation for twice the clock divider values.
+ */
+ clkdiv *= 2;
+#endif
+ printf("LBC:%4lu MHz\n",
+ sysinfo.freqSystemBus / 1000000 / clkdiv);
+ } else {
+ printf("LBC: unknown (lcrr: 0x%08x)\n", lcrr);
+ }
+
+ if (ver == SVR_8560) {
+ printf("CPM: %lu Mhz\n",
+ sysinfo.freqSystemBus / 1000000);
+ }
+
+ puts("L1: D-cache 32 kB enabled\n I-cache 32 kB enabled\n");
+
+ return 0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+int do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+ /*
+ * Initiate hard reset in debug control register DBCR0
+ * Make sure MSR[DE] = 1
+ */
+ unsigned long val;
+
+ val = mfspr(DBCR0);
+ val |= 0x70000000;
+ mtspr(DBCR0,val);
+
+ return 1;
+}
+
+
+/*
+ * Get timebase clock frequency
+ */
+unsigned long get_tbclk (void)
+{
+
+ sys_info_t sys_info;
+
+ get_sys_info(&sys_info);
+ return ((sys_info.freqSystemBus + 7L) / 8L);
+}
+
+
+#if defined(CONFIG_WATCHDOG)
+void
+watchdog_reset(void)
+{
+ int re_enable = disable_interrupts();
+ reset_85xx_watchdog();
+ if (re_enable) enable_interrupts();
+}
+
+void
+reset_85xx_watchdog(void)
+{
+ /*
+ * Clear TSR(WIS) bit by writing 1
+ */
+ unsigned long val;
+ val = mfspr(tsr);
+ val |= 0x40000000;
+ mtspr(tsr, val);
+}
+#endif /* CONFIG_WATCHDOG */
+
+#if defined(CONFIG_DDR_ECC)
+void dma_init(void) {
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+ volatile ccsr_dma_t *dma = &immap->im_dma;
+
+ dma->satr0 = 0x02c40000;
+ dma->datr0 = 0x02c40000;
+ asm("sync; isync; msync");
+ return;
+}
+
+uint dma_check(void) {
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+ volatile ccsr_dma_t *dma = &immap->im_dma;
+ volatile uint status = dma->sr0;
+
+ /* While the channel is busy, spin */
+ while((status & 4) == 4) {
+ status = dma->sr0;
+ }
+
+ if (status != 0) {
+ printf ("DMA Error: status = %x\n", status);
+ }
+ return status;
+}
+
+int dma_xfer(void *dest, uint count, void *src) {
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+ volatile ccsr_dma_t *dma = &immap->im_dma;
+
+ dma->dar0 = (uint) dest;
+ dma->sar0 = (uint) src;
+ dma->bcr0 = count;
+ dma->mr0 = 0xf000004;
+ asm("sync;isync;msync");
+ dma->mr0 = 0xf000005;
+ asm("sync;isync;msync");
+ return dma_check();
+}
+#endif
diff --git a/cpu/mpc85xx/cpu_init.c b/cpu/mpc85xx/cpu_init.c
new file mode 100755
index 0000000..efde9cc
--- /dev/null
+++ b/cpu/mpc85xx/cpu_init.c
@@ -0,0 +1,236 @@
+/*
+ * (C) Copyright 2003 Motorola Inc.
+ * Modified by Xianghua Xiao, X.Xiao@motorola.com
+ *
+ * (C) Copyright 2000
+ * 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
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <asm/processor.h>
+#include <ioports.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_CPM2
+static void config_8560_ioports (volatile immap_t * immr)
+{
+ int portnum;
+
+ for (portnum = 0; portnum < 4; portnum++) {
+ uint pmsk = 0,
+ ppar = 0,
+ psor = 0,
+ pdir = 0,
+ podr = 0,
+ pdat = 0;
+ iop_conf_t *iopc = (iop_conf_t *) & iop_conf_tab[portnum][0];
+ iop_conf_t *eiopc = iopc + 32;
+ uint msk = 1;
+
+ /*
+ * NOTE:
+ * index 0 refers to pin 31,
+ * index 31 refers to pin 0
+ */
+ while (iopc < eiopc) {
+ if (iopc->conf) {
+ pmsk |= msk;
+ if (iopc->ppar)
+ ppar |= msk;
+ if (iopc->psor)
+ psor |= msk;
+ if (iopc->pdir)
+ pdir |= msk;
+ if (iopc->podr)
+ podr |= msk;
+ if (iopc->pdat)
+ pdat |= msk;
+ }
+
+ msk <<= 1;
+ iopc++;
+ }
+
+ if (pmsk != 0) {
+ volatile ioport_t *iop = ioport_addr (immr, portnum);
+ uint tpmsk = ~pmsk;
+
+ /*
+ * the (somewhat confused) paragraph at the
+ * bottom of page 35-5 warns that there might
+ * be "unknown behaviour" when programming
+ * PSORx and PDIRx, if PPARx = 1, so I
+ * decided this meant I had to disable the
+ * dedicated function first, and enable it
+ * last.
+ */
+ iop->ppar &= tpmsk;
+ iop->psor = (iop->psor & tpmsk) | psor;
+ iop->podr = (iop->podr & tpmsk) | podr;
+ iop->pdat = (iop->pdat & tpmsk) | pdat;
+ iop->pdir = (iop->pdir & tpmsk) | pdir;
+ iop->ppar |= ppar;
+ }
+ }
+}
+#endif
+
+/*
+ * Breathe some life into the CPU...
+ *
+ * Set up the memory map
+ * initialize a bunch of registers
+ */
+
+void cpu_init_f (void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+ volatile ccsr_lbc_t *memctl = &immap->im_lbc;
+ extern void m8560_cpm_reset (void);
+
+ /* 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));
+
+
+#ifdef CONFIG_CPM2
+ config_8560_ioports(immap);
+#endif
+
+ /* Map banks 0 and 1 to the FLASH banks 0 and 1 at preliminary
+ * addresses - these have to be modified later when FLASH size
+ * has been determined
+ */
+#if defined(CFG_OR0_REMAP)
+ memctl->or0 = CFG_OR0_REMAP;
+#endif
+#if defined(CFG_OR1_REMAP)
+ memctl->or1 = CFG_OR1_REMAP;
+#endif
+
+ /* now restrict to preliminary range */
+#if defined(CFG_BR0_PRELIM) && defined(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;
+#endif
+
+#if !defined(CONFIG_MPC85xx)
+#if defined(CFG_BR2_PRELIM) && defined(CFG_OR2_PRELIM)
+ memctl->or2 = CFG_OR2_PRELIM;
+ memctl->br2 = CFG_BR2_PRELIM;
+#endif
+#endif
+
+#if defined(CFG_BR3_PRELIM) && defined(CFG_OR3_PRELIM)
+ memctl->or3 = CFG_OR3_PRELIM;
+ memctl->br3 = CFG_BR3_PRELIM;
+#endif
+
+#if defined(CFG_BR4_PRELIM) && defined(CFG_OR4_PRELIM)
+ memctl->or4 = CFG_OR4_PRELIM;
+ memctl->br4 = CFG_BR4_PRELIM;
+#endif
+
+#if defined(CFG_BR5_PRELIM) && defined(CFG_OR5_PRELIM)
+ memctl->or5 = CFG_OR5_PRELIM;
+ memctl->br5 = CFG_BR5_PRELIM;
+#endif
+
+#if defined(CFG_BR6_PRELIM) && defined(CFG_OR6_PRELIM)
+ memctl->or6 = CFG_OR6_PRELIM;
+ memctl->br6 = CFG_BR6_PRELIM;
+#endif
+
+#if defined(CFG_BR7_PRELIM) && defined(CFG_OR7_PRELIM)
+ memctl->or7 = CFG_OR7_PRELIM;
+ memctl->br7 = CFG_BR7_PRELIM;
+#endif
+
+#if defined(CONFIG_CPM2)
+ m8560_cpm_reset();
+#endif
+}
+
+
+/*
+ * Initialize L2 as cache.
+ *
+ * The newer 8548, etc, parts have twice as much cache, but
+ * use the same bit-encoding as the older 8555, etc, parts.
+ *
+ * FIXME: Use PVR_VER(pvr) == 1 test here instead of SVR_VER()?
+ */
+
+int cpu_init_r(void)
+{
+#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;
+
+ svr = get_svr();
+ ver = SVR_VER(svr);
+
+ asm("msync;isync");
+ cache_ctl = l2cache->l2ctl;
+
+ switch (cache_ctl & 0x30000000) {
+ case 0x20000000:
+ if (ver == SVR_8548 || ver == SVR_8548_E) {
+ printf ("L2 cache 512KB:");
+ } else {
+ printf ("L2 cache 256KB:");
+ }
+ break;
+ case 0x00000000:
+ case 0x10000000:
+ case 0x30000000:
+ default:
+ printf ("L2 cache unknown size (0x%08x)\n", cache_ctl);
+ return -1;
+ }
+
+ asm("msync;isync");
+ l2cache->l2ctl = 0x68000000; /* invalidate */
+ cache_ctl = l2cache->l2ctl;
+ asm("msync;isync");
+
+ l2cache->l2ctl = 0xa8000000; /* enable 256KB L2 cache */
+ cache_ctl = l2cache->l2ctl;
+ asm("msync;isync");
+
+ printf(" enabled\n");
+#else
+ printf("L2 cache: disabled\n");
+#endif
+
+ return 0;
+}
diff --git a/cpu/mpc85xx/ether_fcc.c b/cpu/mpc85xx/ether_fcc.c
new file mode 100755
index 0000000..d15d242
--- /dev/null
+++ b/cpu/mpc85xx/ether_fcc.c
@@ -0,0 +1,473 @@
+/*
+ * MPC8560 FCC Fast Ethernet
+ * Copyright (c) 2003 Motorola,Inc.
+ * Xianghua Xiao, (X.Xiao@motorola.com)
+ *
+ * Copyright (c) 2000 MontaVista Software, Inc. Dan Malek (dmalek@jlc.net)
+ *
+ * (C) Copyright 2000 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.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
+ */
+
+/*
+ * MPC8560 FCC Fast Ethernet
+ * Basic ET HW initialization and packet RX/TX routines
+ *
+ * This code will not perform the IO port configuration. This should be
+ * done in the iop_conf_t structure specific for the board.
+ *
+ * TODO:
+ * add a PHY driver to do the negotiation
+ * reflect negotiation results in FPSMR
+ * look for ways to configure the board specific stuff elsewhere, eg.
+ * config_xxx.h or the board directory
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/cpm_85xx.h>
+#include <command.h>
+#include <config.h>
+#include <net.h>
+
+#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+#include <miiphy.h>
+#endif
+
+#if defined(CONFIG_CPM2)
+
+#if defined(CONFIG_ETHER_ON_FCC) && (CONFIG_COMMANDS & CFG_CMD_NET) && \
+ defined(CONFIG_NET_MULTI)
+
+static struct ether_fcc_info_s
+{
+ int ether_index;
+ int proff_enet;
+ ulong cpm_cr_enet_sblock;
+ ulong cpm_cr_enet_page;
+ ulong cmxfcr_mask;
+ ulong cmxfcr_value;
+}
+ ether_fcc_info[] =
+{
+#ifdef CONFIG_ETHER_ON_FCC1
+{
+ 0,
+ PROFF_FCC1,
+ CPM_CR_FCC1_SBLOCK,
+ CPM_CR_FCC1_PAGE,
+ CFG_CMXFCR_MASK1,
+ CFG_CMXFCR_VALUE1
+},
+#endif
+
+#ifdef CONFIG_ETHER_ON_FCC2
+{
+ 1,
+ PROFF_FCC2,
+ CPM_CR_FCC2_SBLOCK,
+ CPM_CR_FCC2_PAGE,
+ CFG_CMXFCR_MASK2,
+ CFG_CMXFCR_VALUE2
+},
+#endif
+
+#ifdef CONFIG_ETHER_ON_FCC3
+{
+ 2,
+ PROFF_FCC3,
+ CPM_CR_FCC3_SBLOCK,
+ CPM_CR_FCC3_PAGE,
+ CFG_CMXFCR_MASK3,
+ CFG_CMXFCR_VALUE3
+},
+#endif
+};
+
+/*---------------------------------------------------------------------*/
+
+/* Maximum input DMA size. Must be a should(?) be a multiple of 4. */
+#define PKT_MAXDMA_SIZE 1520
+
+/* The FCC stores dest/src/type, data, and checksum for receive packets. */
+#define PKT_MAXBUF_SIZE 1518
+#define PKT_MINBUF_SIZE 64
+
+/* Maximum input buffer size. Must be a multiple of 32. */
+#define PKT_MAXBLR_SIZE 1536
+
+#define TOUT_LOOP 1000000
+
+#define TX_BUF_CNT 2
+
+static uint rxIdx; /* index of the current RX buffer */
+static uint txIdx; /* index of the current TX buffer */
+
+/*
+ * FCC Ethernet Tx and Rx buffer descriptors.
+ * Provide for Double Buffering
+ * Note: PKTBUFSRX is defined in net.h
+ */
+
+typedef volatile struct rtxbd {
+ cbd_t rxbd[PKTBUFSRX];
+ cbd_t txbd[TX_BUF_CNT];
+} RTXBD;
+
+/* Good news: the FCC supports external BDs! */
+#ifdef __GNUC__
+static RTXBD rtx __attribute__ ((aligned(8)));
+#else
+#error "rtx must be 64-bit aligned"
+#endif
+
+#undef ET_DEBUG
+
+static int fec_send(struct eth_device* dev, volatile void *packet, int length)
+{
+ int i = 0;
+ int result = 0;
+
+ if (length <= 0) {
+ printf("fec: bad packet size: %d\n", length);
+ goto out;
+ }
+
+ for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
+ if (i >= TOUT_LOOP) {
+ printf("fec: tx buffer not ready\n");
+ goto out;
+ }
+ }
+
+ rtx.txbd[txIdx].cbd_bufaddr = (uint)packet;
+ rtx.txbd[txIdx].cbd_datlen = length;
+ rtx.txbd[txIdx].cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_LAST | \
+ BD_ENET_TX_TC | BD_ENET_TX_PAD);
+
+ for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
+ if (i >= TOUT_LOOP) {
+ printf("fec: tx error\n");
+ goto out;
+ }
+ }
+
+#ifdef ET_DEBUG
+ printf("cycles: 0x%x txIdx=0x%04x status: 0x%04x\n", i, txIdx,rtx.txbd[txIdx].cbd_sc);
+ printf("packets at 0x%08x, length_in_bytes=0x%x\n",(uint)packet,length);
+ for(i=0;i<(length/16 + 1);i++) {
+ printf("%08x %08x %08x %08x\n",*((uint *)rtx.txbd[txIdx].cbd_bufaddr+i*4),\
+ *((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 1),*((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 2), \
+ *((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 3));
+ }
+#endif
+
+ /* return only status bits */
+ result = rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_STATS;
+ txIdx = (txIdx + 1) % TX_BUF_CNT;
+
+out:
+ return result;
+}
+
+static int fec_recv(struct eth_device* dev)
+{
+ int length;
+
+ for (;;)
+ {
+ if (rtx.rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
+ length = -1;
+ break; /* nothing received - leave for() loop */
+ }
+ length = rtx.rxbd[rxIdx].cbd_datlen;
+
+ if (rtx.rxbd[rxIdx].cbd_sc & 0x003f) {
+ printf("fec: rx error %04x\n", rtx.rxbd[rxIdx].cbd_sc);
+ }
+ else {
+ /* Pass the packet up to the protocol layers. */
+ NetReceive(NetRxPackets[rxIdx], length - 4);
+ }
+
+
+ /* Give the buffer back to the FCC. */
+ rtx.rxbd[rxIdx].cbd_datlen = 0;
+
+ /* wrap around buffer index when necessary */
+ if ((rxIdx + 1) >= PKTBUFSRX) {
+ rtx.rxbd[PKTBUFSRX - 1].cbd_sc = (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
+ rxIdx = 0;
+ }
+ else {
+ rtx.rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
+ rxIdx++;
+ }
+ }
+ return length;
+}
+
+
+static int fec_init(struct eth_device* dev, bd_t *bis)
+{
+ struct ether_fcc_info_s * info = dev->priv;
+ int i;
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ volatile ccsr_cpm_cp_t *cp = &(immr->im_cpm.im_cpm_cp);
+ fcc_enet_t *pram_ptr;
+ unsigned long mem_addr;
+
+#if 0
+ mii_discover_phy();
+#endif
+
+ /* 28.9 - (1-2): ioports have been set up already */
+
+ /* 28.9 - (3): connect FCC's tx and rx clocks */
+ immr->im_cpm.im_cpm_mux.cmxuar = 0; /* ATM */
+ immr->im_cpm.im_cpm_mux.cmxfcr = (immr->im_cpm.im_cpm_mux.cmxfcr & ~info->cmxfcr_mask) |
+ info->cmxfcr_value;
+
+ /* 28.9 - (4): GFMR: disable tx/rx, CCITT CRC, set Mode Ethernet */
+ if(info->ether_index == 0) {
+ immr->im_cpm.im_cpm_fcc1.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
+ } else if (info->ether_index == 1) {
+ immr->im_cpm.im_cpm_fcc2.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
+ } else if (info->ether_index == 2) {
+ immr->im_cpm.im_cpm_fcc3.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
+ }
+
+ /* 28.9 - (5): FPSMR: enable full duplex, select CCITT CRC for Ethernet,MII */
+ if(info->ether_index == 0) {
+ immr->im_cpm.im_cpm_fcc1.fpsmr = CFG_FCC_PSMR | FCC_PSMR_ENCRC;
+ } else if (info->ether_index == 1){
+ immr->im_cpm.im_cpm_fcc2.fpsmr = CFG_FCC_PSMR | FCC_PSMR_ENCRC;
+ } else if (info->ether_index == 2){
+ immr->im_cpm.im_cpm_fcc3.fpsmr = CFG_FCC_PSMR | FCC_PSMR_ENCRC;
+ }
+
+ /* 28.9 - (6): FDSR: Ethernet Syn */
+ if(info->ether_index == 0) {
+ immr->im_cpm.im_cpm_fcc1.fdsr = 0xD555;
+ } else if (info->ether_index == 1) {
+ immr->im_cpm.im_cpm_fcc2.fdsr = 0xD555;
+ } else if (info->ether_index == 2) {
+ immr->im_cpm.im_cpm_fcc3.fdsr = 0xD555;
+ }
+
+ /* reset indeces to current rx/tx bd (see eth_send()/eth_rx()) */
+ rxIdx = 0;
+ txIdx = 0;
+
+ /* Setup Receiver Buffer Descriptors */
+ for (i = 0; i < PKTBUFSRX; i++)
+ {
+ rtx.rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
+ rtx.rxbd[i].cbd_datlen = 0;
+ rtx.rxbd[i].cbd_bufaddr = (uint)NetRxPackets[i];
+ }
+ rtx.rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
+
+ /* Setup Ethernet Transmitter Buffer Descriptors */
+ for (i = 0; i < TX_BUF_CNT; i++)
+ {
+ rtx.txbd[i].cbd_sc = 0;
+ rtx.txbd[i].cbd_datlen = 0;
+ rtx.txbd[i].cbd_bufaddr = 0;
+ }
+ rtx.txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
+
+ /* 28.9 - (7): initialize parameter ram */
+ pram_ptr = (fcc_enet_t *)&(immr->im_cpm.im_dprambase[info->proff_enet]);
+
+ /* clear whole structure to make sure all reserved fields are zero */
+ memset((void*)pram_ptr, 0, sizeof(fcc_enet_t));
+
+ /*
+ * common Parameter RAM area
+ *
+ * Allocate space in the reserved FCC area of DPRAM for the
+ * internal buffers. No one uses this space (yet), so we
+ * can do this. Later, we will add resource management for
+ * this area.
+ * CPM_FCC_SPECIAL_BASE: 0xB000 for MPC8540, MPC8560
+ * 0x9000 for MPC8541, MPC8555
+ */
+ mem_addr = CPM_FCC_SPECIAL_BASE + ((info->ether_index) * 64);
+ pram_ptr->fen_genfcc.fcc_riptr = mem_addr;
+ pram_ptr->fen_genfcc.fcc_tiptr = mem_addr+32;
+ /*
+ * Set maximum bytes per receive buffer.
+ * It must be a multiple of 32.
+ */
+ pram_ptr->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE; /* 1536 */
+ /* localbus SDRAM should be preferred */
+ pram_ptr->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB |
+ CFG_CPMFCR_RAMTYPE) << 24;
+ pram_ptr->fen_genfcc.fcc_rbase = (unsigned int)(&rtx.rxbd[rxIdx]);
+ pram_ptr->fen_genfcc.fcc_rbdstat = 0;
+ pram_ptr->fen_genfcc.fcc_rbdlen = 0;
+ pram_ptr->fen_genfcc.fcc_rdptr = 0;
+ /* localbus SDRAM should be preferred */
+ pram_ptr->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB |
+ CFG_CPMFCR_RAMTYPE) << 24;
+ pram_ptr->fen_genfcc.fcc_tbase = (unsigned int)(&rtx.txbd[txIdx]);
+ pram_ptr->fen_genfcc.fcc_tbdstat = 0;
+ pram_ptr->fen_genfcc.fcc_tbdlen = 0;
+ pram_ptr->fen_genfcc.fcc_tdptr = 0;
+
+ /* protocol-specific area */
+ pram_ptr->fen_statbuf = 0x0;
+ pram_ptr->fen_cmask = 0xdebb20e3; /* CRC mask */
+ pram_ptr->fen_cpres = 0xffffffff; /* CRC preset */
+ pram_ptr->fen_crcec = 0;
+ pram_ptr->fen_alec = 0;
+ pram_ptr->fen_disfc = 0;
+ pram_ptr->fen_retlim = 15; /* Retry limit threshold */
+ pram_ptr->fen_retcnt = 0;
+ pram_ptr->fen_pper = 0;
+ pram_ptr->fen_boffcnt = 0;
+ pram_ptr->fen_gaddrh = 0;
+ pram_ptr->fen_gaddrl = 0;
+ pram_ptr->fen_mflr = PKT_MAXBUF_SIZE; /* maximum frame length register */
+ /*
+ * Set Ethernet station address.
+ *
+ * This is supplied in the board information structure, so we
+ * copy that into the controller.
+ * So far we have only been given one Ethernet address. We make
+ * it unique by setting a few bits in the upper byte of the
+ * non-static part of the address.
+ */
+#define ea eth_get_dev()->enetaddr
+ pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
+ pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
+ pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
+#undef ea
+ pram_ptr->fen_ibdcount = 0;
+ pram_ptr->fen_ibdstart = 0;
+ pram_ptr->fen_ibdend = 0;
+ pram_ptr->fen_txlen = 0;
+ pram_ptr->fen_iaddrh = 0; /* disable hash */
+ pram_ptr->fen_iaddrl = 0;
+ pram_ptr->fen_minflr = PKT_MINBUF_SIZE; /* minimum frame length register: 64 */
+ /* pad pointer. use tiptr since we don't need a specific padding char */
+ pram_ptr->fen_padptr = pram_ptr->fen_genfcc.fcc_tiptr;
+ pram_ptr->fen_maxd1 = PKT_MAXDMA_SIZE; /* maximum DMA1 length:1520 */
+ pram_ptr->fen_maxd2 = PKT_MAXDMA_SIZE; /* maximum DMA2 length:1520 */
+
+#if defined(ET_DEBUG)
+ printf("parm_ptr(0xff788500) = %p\n",pram_ptr);
+ printf("pram_ptr->fen_genfcc.fcc_rbase %08x\n",
+ pram_ptr->fen_genfcc.fcc_rbase);
+ printf("pram_ptr->fen_genfcc.fcc_tbase %08x\n",
+ pram_ptr->fen_genfcc.fcc_tbase);
+#endif
+
+ /* 28.9 - (8)(9): clear out events in FCCE */
+ /* 28.9 - (9): FCCM: mask all events */
+ if(info->ether_index == 0) {
+ immr->im_cpm.im_cpm_fcc1.fcce = ~0x0;
+ immr->im_cpm.im_cpm_fcc1.fccm = 0;
+ } else if (info->ether_index == 1) {
+ immr->im_cpm.im_cpm_fcc2.fcce = ~0x0;
+ immr->im_cpm.im_cpm_fcc2.fccm = 0;
+ } else if (info->ether_index == 2) {
+ immr->im_cpm.im_cpm_fcc3.fcce = ~0x0;
+ immr->im_cpm.im_cpm_fcc3.fccm = 0;
+ }
+
+ /* 28.9 - (10-12): we don't use ethernet interrupts */
+
+ /* 28.9 - (13)
+ *
+ * Let's re-initialize the channel now. We have to do it later
+ * than the manual describes because we have just now finished
+ * the BD initialization.
+ */
+ cp->cpcr = mk_cr_cmd(info->cpm_cr_enet_page,
+ info->cpm_cr_enet_sblock,
+ 0x0c,
+ CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ do {
+ __asm__ __volatile__ ("eieio");
+ } while (cp->cpcr & CPM_CR_FLG);
+
+ /* 28.9 - (14): enable tx/rx in gfmr */
+ if(info->ether_index == 0) {
+ immr->im_cpm.im_cpm_fcc1.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
+ } else if (info->ether_index == 1) {
+ immr->im_cpm.im_cpm_fcc2.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
+ } else if (info->ether_index == 2) {
+ immr->im_cpm.im_cpm_fcc3.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
+ }
+
+ return 1;
+}
+
+static void fec_halt(struct eth_device* dev)
+{
+ struct ether_fcc_info_s * info = dev->priv;
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+ /* write GFMR: disable tx/rx */
+ if(info->ether_index == 0) {
+ immr->im_cpm.im_cpm_fcc1.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
+ } else if(info->ether_index == 1) {
+ immr->im_cpm.im_cpm_fcc2.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
+ } else if(info->ether_index == 2) {
+ immr->im_cpm.im_cpm_fcc3.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
+ }
+}
+
+int fec_initialize(bd_t *bis)
+{
+ struct eth_device* dev;
+ int i;
+
+ for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++)
+ {
+ dev = (struct eth_device*) malloc(sizeof *dev);
+ memset(dev, 0, sizeof *dev);
+
+ sprintf(dev->name, "FCC%d ETHERNET",
+ ether_fcc_info[i].ether_index + 1);
+ dev->priv = &ether_fcc_info[i];
+ dev->init = fec_init;
+ dev->halt = fec_halt;
+ dev->send = fec_send;
+ dev->recv = fec_recv;
+
+ eth_register(dev);
+
+#if (defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)) \
+ && defined(CONFIG_BITBANGMII)
+ miiphy_register(dev->name,
+ bb_miiphy_read, bb_miiphy_write);
+#endif
+ }
+
+ return 1;
+}
+
+#endif /* CONFIG_ETHER_ON_FCC && CFG_CMD_NET && CONFIG_NET_MULTI */
+
+#endif /* CONFIG_CPM2 */
diff --git a/cpu/mpc85xx/i2c.c b/cpu/mpc85xx/i2c.c
new file mode 100755
index 0000000..32dcf5d
--- /dev/null
+++ b/cpu/mpc85xx/i2c.c
@@ -0,0 +1,265 @@
+/*
+ * (C) Copyright 2003,Motorola Inc.
+ * Xianghua Xiao <x.xiao@motorola.com>
+ * Adapted for Motorola 85xx chip.
+ *
+ * (C) Copyright 2003
+ * Gleb Natapov <gnatapov@mrv.com>
+ * Some bits are taken from linux driver writen by adrian@humboldt.co.uk
+ *
+ * Hardware I2C driver for MPC107 PCI bridge.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_HARD_I2C
+#include <i2c.h>
+
+#define TIMEOUT (CFG_HZ/4)
+
+#define I2C_Addr ((u8 *)(CFG_CCSRBAR + 0x3000))
+
+#define I2CADR &I2C_Addr[0]
+#define I2CFDR &I2C_Addr[4]
+#define I2CCCR &I2C_Addr[8]
+#define I2CCSR &I2C_Addr[12]
+#define I2CCDR &I2C_Addr[16]
+#define I2CDFSRR &I2C_Addr[20]
+
+#define I2C_READ 1
+#define I2C_WRITE 0
+
+void
+i2c_init(int speed, int slaveadd)
+{
+ /* stop I2C controller */
+ writeb(0x0, I2CCCR);
+
+ /* set clock */
+ writeb(0x3f, I2CFDR);
+
+ /* set default filter */
+ writeb(0x10,I2CDFSRR);
+
+ /* write slave address */
+ writeb(slaveadd, I2CADR);
+
+ /* clear status register */
+ writeb(0x0, I2CCSR);
+
+ /* start I2C controller */
+ writeb(MPC85xx_I2CCR_MEN, I2CCCR);
+}
+
+static __inline__ int
+i2c_wait4bus (void)
+{
+ ulong timeval = get_timer (0);
+
+ while (readb(I2CCSR) & MPC85xx_I2CSR_MBB) {
+ if (get_timer (timeval) > TIMEOUT) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static __inline__ int
+i2c_wait (int write)
+{
+ u32 csr;
+ ulong timeval = get_timer (0);
+
+ do {
+ csr = readb(I2CCSR);
+
+ if (!(csr & MPC85xx_I2CSR_MIF))
+ continue;
+
+ writeb(0x0, I2CCSR);
+
+ if (csr & MPC85xx_I2CSR_MAL) {
+ debug("i2c_wait: MAL\n");
+ return -1;
+ }
+
+ if (!(csr & MPC85xx_I2CSR_MCF)) {
+ debug("i2c_wait: unfinished\n");
+ return -1;
+ }
+
+ if (write == I2C_WRITE && (csr & MPC85xx_I2CSR_RXAK)) {
+ debug("i2c_wait: No RXACK\n");
+ return -1;
+ }
+
+ return 0;
+ } while (get_timer (timeval) < TIMEOUT);
+
+ debug("i2c_wait: timed out\n");
+ return -1;
+}
+
+static __inline__ int
+i2c_write_addr (u8 dev, u8 dir, int rsta)
+{
+ writeb(MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA | MPC85xx_I2CCR_MTX |
+ (rsta?MPC85xx_I2CCR_RSTA:0),
+ I2CCCR);
+
+ writeb((dev << 1) | dir, I2CCDR);
+
+ if (i2c_wait (I2C_WRITE) < 0)
+ return 0;
+
+ return 1;
+}
+
+static __inline__ int
+__i2c_write (u8 *data, int length)
+{
+ int i;
+
+ writeb(MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA | MPC85xx_I2CCR_MTX,
+ I2CCCR);
+
+ for (i=0; i < length; i++) {
+ writeb(data[i], I2CCDR);
+
+ if (i2c_wait (I2C_WRITE) < 0)
+ break;
+ }
+
+ return i;
+}
+
+static __inline__ int
+__i2c_read (u8 *data, int length)
+{
+ int i;
+
+ writeb(MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA |
+ ((length == 1) ? MPC85xx_I2CCR_TXAK : 0),
+ I2CCCR);
+
+ /* dummy read */
+ readb(I2CCDR);
+
+ for (i=0; i < length; i++) {
+ if (i2c_wait (I2C_READ) < 0)
+ break;
+
+ /* Generate ack on last next to last byte */
+ if (i == length - 2)
+ writeb(MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA |
+ MPC85xx_I2CCR_TXAK,
+ I2CCCR);
+
+ /* Generate stop on last byte */
+ if (i == length - 1)
+ writeb(MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_TXAK, I2CCCR);
+
+ data[i] = readb(I2CCDR);
+ }
+
+ return i;
+}
+
+int
+i2c_read (u8 dev, uint addr, int alen, u8 *data, int length)
+{
+ int i = 0;
+ u8 *a = (u8*)&addr;
+
+ if (i2c_wait4bus () < 0)
+ goto exit;
+
+ if (i2c_write_addr (dev, I2C_WRITE, 0) == 0)
+ goto exit;
+
+ if (__i2c_write (&a[4 - alen], alen) != alen)
+ goto exit;
+
+ if (i2c_write_addr (dev, I2C_READ, 1) == 0)
+ goto exit;
+
+ i = __i2c_read (data, length);
+
+ exit:
+ writeb(MPC85xx_I2CCR_MEN, I2CCCR);
+
+ return !(i == length);
+}
+
+int
+i2c_write (u8 dev, uint addr, int alen, u8 *data, int length)
+{
+ int i = 0;
+ u8 *a = (u8*)&addr;
+
+ if (i2c_wait4bus () < 0)
+ goto exit;
+
+ if (i2c_write_addr (dev, I2C_WRITE, 0) == 0)
+ goto exit;
+
+ if (__i2c_write (&a[4 - alen], alen) != alen)
+ goto exit;
+
+ i = __i2c_write (data, length);
+
+ exit:
+ writeb(MPC85xx_I2CCR_MEN, I2CCCR);
+
+ return !(i == length);
+}
+
+int i2c_probe (uchar chip)
+{
+ int tmp;
+
+ /*
+ * Try to read the first location of the chip. The underlying
+ * driver doesn't appear to support sending just the chip address
+ * and looking for an <ACK> back.
+ */
+ udelay(10000);
+ return i2c_read (chip, 0, 1, (uchar *)&tmp, 1);
+}
+
+uchar i2c_reg_read (uchar i2c_addr, uchar reg)
+{
+ uchar buf[1];
+
+ i2c_read (i2c_addr, reg, 1, buf, 1);
+
+ return (buf[0]);
+}
+
+void i2c_reg_write (uchar i2c_addr, uchar reg, uchar val)
+{
+ i2c_write (i2c_addr, reg, 1, &val, 1);
+}
+
+#endif /* CONFIG_HARD_I2C */
diff --git a/cpu/mpc85xx/interrupts.c b/cpu/mpc85xx/interrupts.c
new file mode 100755
index 0000000..832781b
--- /dev/null
+++ b/cpu/mpc85xx/interrupts.c
@@ -0,0 +1,162 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2002 (440 port)
+ * Scott McNutt, Artesyn Communication Producs, smcnutt@artsyncp.com
+ *
+ * (C) Copyright 2003 Motorola Inc. (MPC85xx port)
+ * Xianghua Xiao (X.Xiao@motorola.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <asm/processor.h>
+#include <ppc_asm.tmpl>
+
+unsigned decrementer_count; /* count value for 1e6/HZ microseconds */
+
+static __inline__ unsigned long get_msr(void)
+{
+ unsigned long msr;
+
+ asm volatile("mfmsr %0" : "=r" (msr) :);
+ return msr;
+}
+
+static __inline__ void set_msr(unsigned long msr)
+{
+ asm volatile("mtmsr %0" : : "r" (msr));
+ asm volatile("isync");
+}
+
+static __inline__ unsigned long get_dec (void)
+{
+ unsigned long val;
+
+ asm volatile ("mfdec %0":"=r" (val):);
+
+ return val;
+}
+
+
+static __inline__ void set_dec (unsigned long val)
+{
+ if (val)
+ asm volatile ("mtdec %0"::"r" (val));
+}
+
+void enable_interrupts (void)
+{
+ set_msr (get_msr() | MSR_EE);
+}
+
+/* returns flag if MSR_EE was set before */
+int disable_interrupts (void)
+{
+ ulong msr = get_msr();
+ set_msr (msr & ~MSR_EE);
+ return ((msr & MSR_EE) != 0);
+}
+
+int interrupt_init (void)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+ immr->im_pic.gcr = MPC85xx_PICGCR_RST;
+ while (immr->im_pic.gcr & MPC85xx_PICGCR_RST);
+ immr->im_pic.gcr = MPC85xx_PICGCR_M;
+ decrementer_count = get_tbclk() / CFG_HZ;
+ mtspr(SPRN_TCR, TCR_PIE);
+ set_dec (decrementer_count);
+ set_msr (get_msr () | MSR_EE);
+ return (0);
+}
+
+/*
+ * Install and free a interrupt handler. Not implemented yet.
+ */
+
+void
+irq_install_handler(int vec, interrupt_handler_t *handler, void *arg)
+{
+ return;
+}
+
+void
+irq_free_handler(int vec)
+{
+ return;
+}
+
+/****************************************************************************/
+
+
+volatile ulong timestamp = 0;
+
+/*
+ * timer_interrupt - gets called when the decrementer overflows,
+ * with interrupts disabled.
+ * Trivial implementation - no need to be really accurate.
+ */
+void timer_interrupt(struct pt_regs *regs)
+{
+ timestamp++;
+ set_dec (decrementer_count);
+ mtspr(SPRN_TSR, TSR_PIS);
+#if defined(CONFIG_WATCHDOG)
+ if ((timestamp % 1000) == 0)
+ reset_85xx_watchdog();
+#endif /* CONFIG_WATCHDOG */
+}
+
+void reset_timer (void)
+{
+ timestamp = 0;
+}
+
+ulong get_timer (ulong base)
+{
+ return (timestamp - base);
+}
+
+void set_timer (ulong t)
+{
+ timestamp = t;
+}
+
+#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
+
+/*******************************************************************************
+ *
+ * irqinfo - print information about PCI devices,not implemented.
+ *
+ */
+int
+do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ printf ("\nInterrupt-unsupported:\n");
+
+ return 0;
+}
+
+#endif /* CONFIG_COMMANDS & CFG_CMD_IRQ */
diff --git a/cpu/mpc85xx/pci.c b/cpu/mpc85xx/pci.c
new file mode 100755
index 0000000..a94493e
--- /dev/null
+++ b/cpu/mpc85xx/pci.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2004 Freescale Semiconductor.
+ * Copyright (C) 2003 Motorola Inc.
+ * Xianghua Xiao (x.xiao@motorola.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * PCI Configuration space access support for MPC85xx PCI Bridge
+ */
+#include <common.h>
+#include <asm/cpm_85xx.h>
+#include <pci.h>
+
+
+#if defined(CONFIG_PCI)
+
+void
+pci_mpc85xx_init(struct pci_controller *hose)
+{
+ volatile immap_t *immap = (immap_t *)CFG_CCSRBAR;
+ volatile ccsr_pcix_t *pcix = &immap->im_pcix;
+
+ u16 reg16;
+
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+
+ pci_set_region(hose->regions + 0,
+ CFG_PCI1_MEM_BASE,
+ CFG_PCI1_MEM_PHYS,
+ CFG_PCI1_MEM_SIZE,
+ PCI_REGION_MEM);
+
+ pci_set_region(hose->regions + 1,
+ CFG_PCI1_IO_BASE,
+ CFG_PCI1_IO_PHYS,
+ CFG_PCI1_IO_SIZE,
+ PCI_REGION_IO);
+
+ hose->region_count = 2;
+
+ pci_setup_indirect(hose,
+ (CFG_IMMR+0x8000),
+ (CFG_IMMR+0x8004));
+
+ pcix->potar1 = (CFG_PCI1_MEM_BASE >> 12) & 0x000fffff;
+ pcix->potear1 = 0x00000000;
+ pcix->powbar1 = (CFG_PCI1_MEM_BASE >> 12) & 0x000fffff;
+ pcix->powbear1 = 0x00000000;
+ pcix->powar1 = 0x8004401c; /* 512M MEM space */
+
+ pcix->potar2 = 0x00000000;
+ pcix->potear2 = 0x00000000;
+ pcix->powbar2 = (CFG_PCI1_IO_BASE >> 12) & 0x000fffff;
+ pcix->powbear2 = 0x00000000;
+ pcix->powar2 = 0x80088017; /* 16M IO space */
+
+ pcix->pitar1 = 0x00000000;
+ pcix->piwbar1 = 0x00000000;
+ pcix->piwar1 = 0xa0f5501e; /* Enable, Prefetch, Local Mem,
+ * Snoop R/W, 2G */
+
+ /*
+ * Hose scan.
+ */
+ pci_register_hose(hose);
+
+ pci_read_config_word (PCI_BDF(0,0,0), PCI_COMMAND, &reg16);
+ reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ pci_write_config_word(PCI_BDF(0,0,0), PCI_COMMAND, reg16);
+
+ /*
+ * Clear non-reserved bits in status register.
+ */
+ pci_write_config_word(PCI_BDF(0,0,0), PCI_STATUS, 0xffff);
+ pci_write_config_byte(PCI_BDF(0,0,0), PCI_LATENCY_TIMER,0x80);
+
+#if defined(CONFIG_MPC8555CDS) || defined(CONFIG_MPC8541CDS)
+ /*
+ * This is a SW workaround for an apparent HW problem
+ * in the PCI controller on the MPC85555/41 CDS boards.
+ * The first config cycle must be to a valid, known
+ * device on the PCI bus in order to trick the PCI
+ * controller state machine into a known valid state.
+ * Without this, the first config cycle has the chance
+ * of hanging the controller permanently, just leaving
+ * it in a semi-working state, or leaving it working.
+ *
+ * Pick on the Tundra, Device 17, to get it right.
+ */
+ {
+ u8 header_type;
+
+ pci_hose_read_config_byte(hose,
+ PCI_BDF(0,17,0),
+ PCI_HEADER_TYPE,
+ &header_type);
+ }
+#endif
+
+ hose->last_busno = pci_hose_scan(hose);
+}
+
+#endif /* CONFIG_PCI */
diff --git a/cpu/mpc85xx/resetvec.S b/cpu/mpc85xx/resetvec.S
new file mode 100755
index 0000000..29555d4
--- /dev/null
+++ b/cpu/mpc85xx/resetvec.S
@@ -0,0 +1,2 @@
+ .section .resetvec,"ax"
+ b _start_e500
diff --git a/cpu/mpc85xx/serial_scc.c b/cpu/mpc85xx/serial_scc.c
new file mode 100755
index 0000000..cf060d6
--- /dev/null
+++ b/cpu/mpc85xx/serial_scc.c
@@ -0,0 +1,274 @@
+/*
+ * (C) Copyright 2003 Motorola Inc.
+ * Xianghua Xiao (X.Xiao@motorola.com)
+ * Modified based on 8260 for 8560.
+ *
+ * (C) Copyright 2000
+ * 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
+ *
+ * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00.
+ */
+
+/*
+ * Minimal serial functions needed to use one of the SCC ports
+ * as serial console interface.
+ */
+
+#include <common.h>
+#include <asm/cpm_85xx.h>
+
+#if defined(CONFIG_CPM2)
+#if defined(CONFIG_CONS_ON_SCC)
+
+#if CONFIG_CONS_INDEX == 1 /* Console on SCC1 */
+
+#define SCC_INDEX 0
+#define PROFF_SCC PROFF_SCC1
+#define CMXSCR_MASK (CMXSCR_GR1|CMXSCR_SC1|\
+ CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK)
+#define CMXSCR_VALUE (CMXSCR_RS1CS_BRG1|CMXSCR_TS1CS_BRG1)
+#define CPM_CR_SCC_PAGE CPM_CR_SCC1_PAGE
+#define CPM_CR_SCC_SBLOCK CPM_CR_SCC1_SBLOCK
+
+#elif CONFIG_CONS_INDEX == 2 /* Console on SCC2 */
+
+#define SCC_INDEX 1
+#define PROFF_SCC PROFF_SCC2
+#define CMXSCR_MASK (CMXSCR_GR2|CMXSCR_SC2|\
+ CMXSCR_RS2CS_MSK|CMXSCR_TS2CS_MSK)
+#define CMXSCR_VALUE (CMXSCR_RS2CS_BRG2|CMXSCR_TS2CS_BRG2)
+#define CPM_CR_SCC_PAGE CPM_CR_SCC2_PAGE
+#define CPM_CR_SCC_SBLOCK CPM_CR_SCC2_SBLOCK
+
+#elif CONFIG_CONS_INDEX == 3 /* Console on SCC3 */
+
+#define SCC_INDEX 2
+#define PROFF_SCC PROFF_SCC3
+#define CMXSCR_MASK (CMXSCR_GR3|CMXSCR_SC3|\
+ CMXSCR_RS3CS_MSK|CMXSCR_TS3CS_MSK)
+#define CMXSCR_VALUE (CMXSCR_RS3CS_BRG3|CMXSCR_TS3CS_BRG3)
+#define CPM_CR_SCC_PAGE CPM_CR_SCC3_PAGE
+#define CPM_CR_SCC_SBLOCK CPM_CR_SCC3_SBLOCK
+
+#elif CONFIG_CONS_INDEX == 4 /* Console on SCC4 */
+
+#define SCC_INDEX 3
+#define PROFF_SCC PROFF_SCC4
+#define CMXSCR_MASK (CMXSCR_GR4|CMXSCR_SC4|\
+ CMXSCR_RS4CS_MSK|CMXSCR_TS4CS_MSK)
+#define CMXSCR_VALUE (CMXSCR_RS4CS_BRG4|CMXSCR_TS4CS_BRG4)
+#define CPM_CR_SCC_PAGE CPM_CR_SCC4_PAGE
+#define CPM_CR_SCC_SBLOCK CPM_CR_SCC4_SBLOCK
+
+#else
+
+#error "console not correctly defined"
+
+#endif
+
+int serial_init (void)
+{
+ volatile immap_t *im = (immap_t *)CFG_IMMR;
+ volatile ccsr_cpm_scc_t *sp;
+ volatile scc_uart_t *up;
+ volatile cbd_t *tbdf, *rbdf;
+ volatile ccsr_cpm_cp_t *cp = &(im->im_cpm.im_cpm_cp);
+ uint dpaddr;
+
+ /* initialize pointers to SCC */
+
+ sp = (ccsr_cpm_scc_t *) &(im->im_cpm.im_cpm_scc[SCC_INDEX]);
+ up = (scc_uart_t *)&(im->im_cpm.im_dprambase[PROFF_SCC]);
+
+ /* Disable transmitter/receiver.
+ */
+ sp->gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+ /* put the SCC channel into NMSI (non multiplexd serial interface)
+ * mode and wire the selected SCC Tx and Rx clocks to BRGx (15-15).
+ */
+ im->im_cpm.im_cpm_mux.cmxscr = \
+ (im->im_cpm.im_cpm_mux.cmxscr&~CMXSCR_MASK)|CMXSCR_VALUE;
+
+ /* Set up the baud rate generator.
+ */
+ serial_setbrg ();
+
+ /* Allocate space for two buffer descriptors in the DP ram.
+ * damm: allocating space after the two buffers for rx/tx data
+ */
+
+ dpaddr = m8560_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+ rbdf = (cbd_t *)&(im->im_cpm.im_dprambase[dpaddr]);
+ rbdf->cbd_bufaddr = (uint) (rbdf+2);
+ rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
+ tbdf = rbdf + 1;
+ tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
+ tbdf->cbd_sc = BD_SC_WRAP;
+
+ /* Set up the uart parameters in the parameter ram.
+ */
+ up->scc_genscc.scc_rbase = dpaddr;
+ up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
+ up->scc_genscc.scc_rfcr = CPMFCR_EB;
+ up->scc_genscc.scc_tfcr = CPMFCR_EB;
+ up->scc_genscc.scc_mrblr = 1;
+ up->scc_maxidl = 0;
+ up->scc_brkcr = 1;
+ up->scc_parec = 0;
+ up->scc_frmec = 0;
+ up->scc_nosec = 0;
+ up->scc_brkec = 0;
+ up->scc_uaddr1 = 0;
+ up->scc_uaddr2 = 0;
+ up->scc_toseq = 0;
+ up->scc_char1 = up->scc_char2 = up->scc_char3 = up->scc_char4 = 0x8000;
+ up->scc_char5 = up->scc_char6 = up->scc_char7 = up->scc_char8 = 0x8000;
+ up->scc_rccm = 0xc0ff;
+
+ /* Mask all interrupts and remove anything pending.
+ */
+ sp->sccm = 0;
+ sp->scce = 0xffff;
+
+ /* Set 8 bit FIFO, 16 bit oversampling and UART mode.
+ */
+ sp->gsmrh = SCC_GSMRH_RFW; /* 8 bit FIFO */
+ sp->gsmrl = \
+ SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16 | SCC_GSMRL_MODE_UART;
+
+ /* Set CTS no flow control, 1 stop bit, 8 bit character length,
+ * normal async UART mode, no parity
+ */
+ sp->psmr = SCU_PSMR_CL;
+
+ /* execute the "Init Rx and Tx params" CP command.
+ */
+
+ while (cp->cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ cp->cpcr = mk_cr_cmd(CPM_CR_SCC_PAGE, CPM_CR_SCC_SBLOCK,
+ 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+ while (cp->cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ /* Enable transmitter/receiver.
+ */
+ sp->gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT;
+
+ return (0);
+}
+
+void
+serial_setbrg (void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_CONS_USE_EXTC)
+ m8560_cpm_extcbrg(SCC_INDEX, gd->baudrate,
+ CONFIG_CONS_EXTC_RATE, CONFIG_CONS_EXTC_PINSEL);
+#else
+ m8560_cpm_setbrg(SCC_INDEX, gd->baudrate);
+#endif
+}
+
+void
+serial_putc(const char c)
+{
+ volatile scc_uart_t *up;
+ volatile cbd_t *tbdf;
+ volatile immap_t *im;
+
+ if (c == '\n')
+ serial_putc ('\r');
+
+ im = (immap_t *)CFG_IMMR;
+ up = (scc_uart_t *)&(im->im_cpm.im_dprambase[PROFF_SCC]);
+ tbdf = (cbd_t *)&(im->im_cpm.im_dprambase[up->scc_genscc.scc_tbase]);
+
+ /* Wait for last character to go.
+ */
+ while (tbdf->cbd_sc & BD_SC_READY)
+ ;
+
+ /* Load the character into the transmit buffer.
+ */
+ *(volatile char *)tbdf->cbd_bufaddr = c;
+ tbdf->cbd_datlen = 1;
+ tbdf->cbd_sc |= BD_SC_READY;
+}
+
+void
+serial_puts (const char *s)
+{
+ while (*s) {
+ serial_putc (*s++);
+ }
+}
+
+int
+serial_getc(void)
+{
+ volatile cbd_t *rbdf;
+ volatile scc_uart_t *up;
+ volatile immap_t *im;
+ unsigned char c;
+
+ im = (immap_t *)CFG_IMMR;
+ up = (scc_uart_t *)&(im->im_cpm.im_dprambase[PROFF_SCC]);
+ rbdf = (cbd_t *)&(im->im_cpm.im_dprambase[up->scc_genscc.scc_rbase]);
+
+ /* Wait for character to show up.
+ */
+ while (rbdf->cbd_sc & BD_SC_EMPTY)
+ ;
+
+ /* Grab the char and clear the buffer again.
+ */
+ c = *(volatile unsigned char *)rbdf->cbd_bufaddr;
+ rbdf->cbd_sc |= BD_SC_EMPTY;
+
+ return (c);
+}
+
+int
+serial_tstc()
+{
+ volatile cbd_t *rbdf;
+ volatile scc_uart_t *up;
+ volatile immap_t *im;
+
+ im = (immap_t *)CFG_IMMR;
+ up = (scc_uart_t *)&(im->im_cpm.im_dprambase[PROFF_SCC]);
+ rbdf = (cbd_t *)&(im->im_cpm.im_dprambase[up->scc_genscc.scc_rbase]);
+
+ return ((rbdf->cbd_sc & BD_SC_EMPTY) == 0);
+}
+
+#endif /* CONFIG_CONS_ON_SCC */
+
+#endif /* CONFIG_CPM2 */
diff --git a/cpu/mpc85xx/spd_sdram.c b/cpu/mpc85xx/spd_sdram.c
new file mode 100755
index 0000000..af99282
--- /dev/null
+++ b/cpu/mpc85xx/spd_sdram.c
@@ -0,0 +1,1118 @@
+/*
+ * Copyright 2004 Freescale Semiconductor.
+ * (C) Copyright 2003 Motorola Inc.
+ * Xianghua Xiao (X.Xiao@motorola.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <i2c.h>
+#include <spd.h>
+#include <asm/mmu.h>
+
+
+#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
+extern void dma_init(void);
+extern uint dma_check(void);
+extern int dma_xfer(void *dest, uint count, void *src);
+#endif
+
+#ifdef CONFIG_SPD_EEPROM
+
+#ifndef CFG_READ_SPD
+#define CFG_READ_SPD i2c_read
+#endif
+
+static unsigned int setup_laws_and_tlbs(unsigned int memsize);
+
+
+/*
+ * Convert picoseconds into clock cycles (rounding up if needed).
+ */
+
+int
+picos_to_clk(int picos)
+{
+ int clks;
+
+ clks = picos / (2000000000 / (get_bus_freq(0) / 1000));
+ if (picos % (2000000000 / (get_bus_freq(0) / 1000)) != 0) {
+ clks++;
+ }
+
+ return clks;
+}
+
+
+/*
+ * Calculate the Density of each Physical Rank.
+ * Returned size is in bytes.
+ *
+ * Study these table from Byte 31 of JEDEC SPD Spec.
+ *
+ * DDR I DDR II
+ * Bit Size Size
+ * --- ----- ------
+ * 7 high 512MB 512MB
+ * 6 256MB 256MB
+ * 5 128MB 128MB
+ * 4 64MB 16GB
+ * 3 32MB 8GB
+ * 2 16MB 4GB
+ * 1 2GB 2GB
+ * 0 low 1GB 1GB
+ *
+ * Reorder Table to be linear by stripping the bottom
+ * 2 or 5 bits off and shifting them up to the top.
+ */
+
+unsigned int
+compute_banksize(unsigned int mem_type, unsigned char row_dens)
+{
+ unsigned int bsize;
+
+ if (mem_type == SPD_MEMTYPE_DDR) {
+ /* Bottom 2 bits up to the top. */
+ bsize = ((row_dens >> 2) | ((row_dens & 3) << 6)) << 24;
+ debug("DDR: DDR I rank density = 0x%08x\n", bsize);
+ } else {
+ /* Bottom 5 bits up to the top. */
+ bsize = ((row_dens >> 5) | ((row_dens & 31) << 3)) << 27;
+ debug("DDR: DDR II rank density = 0x%08x\n", bsize);
+ }
+ return bsize;
+}
+
+
+/*
+ * Convert a two-nibble BCD value into a cycle time.
+ * While the spec calls for nano-seconds, picos are returned.
+ *
+ * This implements the tables for bytes 9, 23 and 25 for both
+ * DDR I and II. No allowance for distinguishing the invalid
+ * fields absent for DDR I yet present in DDR II is made.
+ * (That is, cycle times of .25, .33, .66 and .75 ns are
+ * allowed for both DDR II and I.)
+ */
+
+unsigned int
+convert_bcd_tenths_to_cycle_time_ps(unsigned int spd_val)
+{
+ /*
+ * Table look up the lower nibble, allow DDR I & II.
+ */
+ unsigned int tenths_ps[16] = {
+ 0,
+ 100,
+ 200,
+ 300,
+ 400,
+ 500,
+ 600,
+ 700,
+ 800,
+ 900,
+ 250,
+ 330, /* FIXME: Is 333 better/valid? */
+ 660, /* FIXME: Is 667 better/valid? */
+ 750,
+ 0, /* undefined */
+ 0 /* undefined */
+ };
+
+ unsigned int whole_ns = (spd_val & 0xF0) >> 4;
+ unsigned int tenth_ns = spd_val & 0x0F;
+ unsigned int ps = whole_ns * 1000 + tenths_ps[tenth_ns];
+
+ return ps;
+}
+
+
+long int
+spd_sdram(void)
+{
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+ volatile ccsr_ddr_t *ddr = &immap->im_ddr;
+ volatile ccsr_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_cfg, mode_odt_enable;
+ unsigned int dqs_cfg;
+ unsigned char twr_clk, twtr_clk, twr_auto_clk;
+ unsigned int tCKmin_ps, tCKmax_ps;
+ unsigned int max_data_rate, effective_data_rate;
+ unsigned int busfreq;
+ unsigned sdram_cfg;
+ unsigned int memsize;
+ unsigned char caslat, caslat_ctrl;
+ unsigned int trfc, trfc_clk, trfc_low, trfc_high;
+ unsigned int trcd_clk;
+ unsigned int trtp_clk;
+ unsigned char cke_min_clk;
+ unsigned char add_lat;
+ unsigned char wr_lat;
+ unsigned char wr_data_delay;
+ unsigned char four_act;
+ unsigned char cpo;
+ unsigned char burst_len;
+ unsigned int mode_caslat;
+ unsigned char sdram_type;
+ unsigned char d_init;
+
+ /*
+ * Read SPD information.
+ */
+ CFG_READ_SPD(SPD_EEPROM_ADDRESS, 0, 1, (uchar *) &spd, sizeof(spd));
+
+ /*
+ * Check for supported memory module types.
+ */
+ if (spd.mem_type != SPD_MEMTYPE_DDR &&
+ spd.mem_type != SPD_MEMTYPE_DDR2) {
+ printf("Unable to locate DDR I or DDR II module.\n"
+ " Fundamental memory type is 0x%0x\n",
+ spd.mem_type);
+ return 0;
+ }
+
+ /*
+ * These test gloss over DDR I and II differences in interpretation
+ * of bytes 3 and 4, but irrelevantly. Multiple asymmetric banks
+ * are not supported on DDR I; and not encoded on DDR II.
+ *
+ * Also note that the 8548 controller can support:
+ * 12 <= nrow <= 16
+ * and
+ * 8 <= ncol <= 11 (still, for DDR)
+ * 6 <= ncol <= 9 (for FCRAM)
+ */
+ if (spd.nrow_addr < 12 || spd.nrow_addr > 14) {
+ printf("DDR: Unsupported number of Row Addr lines: %d.\n",
+ spd.nrow_addr);
+ return 0;
+ }
+ if (spd.ncol_addr < 8 || spd.ncol_addr > 11) {
+ printf("DDR: Unsupported number of Column Addr lines: %d.\n",
+ spd.ncol_addr);
+ return 0;
+ }
+
+ /*
+ * Determine the number of physical banks controlled by
+ * different Chip Select signals. This is not quite the
+ * same as the number of DIMM modules on the board. Feh.
+ */
+ if (spd.mem_type == SPD_MEMTYPE_DDR) {
+ n_ranks = spd.nrows;
+ } else {
+ n_ranks = (spd.nrows & 0x7) + 1;
+ }
+
+ debug("DDR: number of ranks = %d\n", n_ranks);
+
+ if (n_ranks > 2) {
+ printf("DDR: Only 2 chip selects are supported: %d\n",
+ n_ranks);
+ return 0;
+ }
+
+ /*
+ * Adjust DDR II IO voltage biasing. It just makes it work.
+ */
+ if (spd.mem_type == SPD_MEMTYPE_DDR2) {
+ gur->ddrioovcr = (0
+ | 0x80000000 /* Enable */
+ | 0x10000000 /* VSEL to 1.8V */
+ );
+ }
+
+ /*
+ * Determine the size of each Rank in bytes.
+ */
+ rank_density = compute_banksize(spd.mem_type, spd.row_dens);
+
+
+ /*
+ * Eg: Bounds: 0x0000_0000 to 0x0f000_0000 first 256 Meg
+ */
+ ddr->cs0_bnds = (rank_density >> 24) - 1;
+
+ /*
+ * ODT configuration recommendation from DDR Controller Chapter.
+ */
+ odt_rd_cfg = 0; /* Never assert ODT */
+ odt_wr_cfg = 0; /* Never assert ODT */
+ if (spd.mem_type == SPD_MEMTYPE_DDR2) {
+ odt_wr_cfg = 1; /* Assert ODT on writes to CS0 */
+#if 0
+ /* FIXME: How to determine the number of dimm modules? */
+ if (n_dimm_modules == 2) {
+ odt_rd_cfg = 1; /* Assert ODT on reads to CS0 */
+ }
+#endif
+ }
+
+ ddr->cs0_config = ( 1 << 31
+ | (odt_rd_cfg << 20)
+ | (odt_wr_cfg << 16)
+ | (spd.nrow_addr - 12) << 8
+ | (spd.ncol_addr - 8) );
+ debug("\n");
+ debug("DDR: cs0_bnds = 0x%08x\n", ddr->cs0_bnds);
+ debug("DDR: cs0_config = 0x%08x\n", ddr->cs0_config);
+
+ if (n_ranks == 2) {
+ /*
+ * Eg: Bounds: 0x0f00_0000 to 0x1e0000_0000, second 256 Meg
+ */
+ ddr->cs1_bnds = ( (rank_density >> 8)
+ | ((rank_density >> (24 - 1)) - 1) );
+ ddr->cs1_config = ( 1<<31
+ | (odt_rd_cfg << 20)
+ | (odt_wr_cfg << 16)
+ | (spd.nrow_addr - 12) << 8
+ | (spd.ncol_addr - 8) );
+ debug("DDR: cs1_bnds = 0x%08x\n", ddr->cs1_bnds);
+ debug("DDR: cs1_config = 0x%08x\n", ddr->cs1_config);
+ }
+
+
+ /*
+ * Find the largest CAS by locating the highest 1 bit
+ * in the spd.cas_lat field. Translate it to a DDR
+ * controller field value:
+ *
+ * CAS Lat DDR I DDR II Ctrl
+ * Clocks SPD Bit SPD Bit Value
+ * ------- ------- ------- -----
+ * 1.0 0 0001
+ * 1.5 1 0010
+ * 2.0 2 2 0011
+ * 2.5 3 0100
+ * 3.0 4 3 0101
+ * 3.5 5 0110
+ * 4.0 4 0111
+ * 4.5 1000
+ * 5.0 5 1001
+ */
+ caslat = __ilog2(spd.cas_lat);
+ if ((spd.mem_type == SPD_MEMTYPE_DDR)
+ && (caslat > 5)) {
+ printf("DDR I: Invalid SPD CAS Latency: 0x%x.\n", spd.cas_lat);
+ return 0;
+
+ } else if (spd.mem_type == SPD_MEMTYPE_DDR2
+ && (caslat < 2 || caslat > 5)) {
+ printf("DDR II: Invalid SPD CAS Latency: 0x%x.\n",
+ spd.cas_lat);
+ return 0;
+ }
+ debug("DDR: caslat SPD bit is %d\n", caslat);
+
+ /*
+ * Calculate the Maximum Data Rate based on the Minimum Cycle time.
+ * The SPD clk_cycle field (tCKmin) is measured in tenths of
+ * nanoseconds and represented as BCD.
+ */
+ tCKmin_ps = convert_bcd_tenths_to_cycle_time_ps(spd.clk_cycle);
+ debug("DDR: tCKmin = %d ps\n", tCKmin_ps);
+
+ /*
+ * Double-data rate, scaled 1000 to picoseconds, and back down to MHz.
+ */
+ max_data_rate = 2 * 1000 * 1000 / tCKmin_ps;
+ debug("DDR: Module max data rate = %d Mhz\n", max_data_rate);
+
+
+ /*
+ * Adjust the CAS Latency to allow for bus speeds that
+ * are slower than the DDR module.
+ */
+ busfreq = get_bus_freq(0) / 1000000; /* MHz */
+
+ effective_data_rate = max_data_rate;
+ if (busfreq < 90) {
+ /* DDR rate out-of-range */
+ puts("DDR: platform frequency is not fit for DDR rate\n");
+ return 0;
+
+ } else if (90 <= busfreq && busfreq < 230 && max_data_rate >= 230) {
+ /*
+ * busfreq 90~230 range, treated as DDR 200.
+ */
+ effective_data_rate = 200;
+ if (spd.clk_cycle3 == 0xa0) /* 10 ns */
+ caslat -= 2;
+ else if (spd.clk_cycle2 == 0xa0)
+ caslat--;
+
+ } else if (230 <= busfreq && busfreq < 280 && max_data_rate >= 280) {
+ /*
+ * busfreq 230~280 range, treated as DDR 266.
+ */
+ effective_data_rate = 266;
+ if (spd.clk_cycle3 == 0x75) /* 7.5 ns */
+ caslat -= 2;
+ else if (spd.clk_cycle2 == 0x75)
+ caslat--;
+
+ } else if (280 <= busfreq && busfreq < 350 && max_data_rate >= 350) {
+ /*
+ * busfreq 280~350 range, treated as DDR 333.
+ */
+ effective_data_rate = 333;
+ if (spd.clk_cycle3 == 0x60) /* 6.0 ns */
+ caslat -= 2;
+ else if (spd.clk_cycle2 == 0x60)
+ caslat--;
+
+ } else if (350 <= busfreq && busfreq < 460 && max_data_rate >= 460) {
+ /*
+ * busfreq 350~460 range, treated as DDR 400.
+ */
+ effective_data_rate = 400;
+ if (spd.clk_cycle3 == 0x50) /* 5.0 ns */
+ caslat -= 2;
+ else if (spd.clk_cycle2 == 0x50)
+ caslat--;
+
+ } else if (460 <= busfreq && busfreq < 560 && max_data_rate >= 560) {
+ /*
+ * busfreq 460~560 range, treated as DDR 533.
+ */
+ effective_data_rate = 533;
+ if (spd.clk_cycle3 == 0x3D) /* 3.75 ns */
+ caslat -= 2;
+ else if (spd.clk_cycle2 == 0x3D)
+ caslat--;
+
+ } else if (560 <= busfreq && busfreq < 700 && max_data_rate >= 700) {
+ /*
+ * busfreq 560~700 range, treated as DDR 667.
+ */
+ effective_data_rate = 667;
+ if (spd.clk_cycle3 == 0x30) /* 3.0 ns */
+ caslat -= 2;
+ else if (spd.clk_cycle2 == 0x30)
+ caslat--;
+
+ } else if (700 <= busfreq) {
+ /*
+ * DDR rate out-of-range
+ */
+ printf("DDR: Bus freq %d MHz is not fit for DDR rate %d MHz\n",
+ busfreq, max_data_rate);
+ return 0;
+ }
+
+
+ /*
+ * Convert caslat clocks to DDR controller value.
+ * Force caslat_ctrl to be DDR Controller field-sized.
+ */
+ if (spd.mem_type == SPD_MEMTYPE_DDR) {
+ caslat_ctrl = (caslat + 1) & 0x07;
+ } else {
+ caslat_ctrl = (2 * caslat - 1) & 0x0f;
+ }
+
+ debug("DDR: effective data rate is %d MHz\n", effective_data_rate);
+ debug("DDR: caslat SPD bit is %d, controller field is 0x%x\n",
+ caslat, caslat_ctrl);
+
+ /*
+ * Timing Config 0.
+ * Avoid writing for DDR I. The new PQ38 DDR controller
+ * dreams up non-zero default values to be backwards compatible.
+ */
+ if (spd.mem_type == SPD_MEMTYPE_DDR2) {
+ unsigned char taxpd_clk = 8; /* By the book. */
+ unsigned char tmrd_clk = 2; /* By the book. */
+ unsigned char act_pd_exit = 2; /* Empirical? */
+ unsigned char pre_pd_exit = 6; /* Empirical? */
+
+ ddr->timing_cfg_0 = (0
+ | ((act_pd_exit & 0x7) << 20) /* ACT_PD_EXIT */
+ | ((pre_pd_exit & 0x7) << 16) /* PRE_PD_EXIT */
+ | ((taxpd_clk & 0xf) << 8) /* ODT_PD_EXIT */
+ | ((tmrd_clk & 0xf) << 0) /* MRS_CYC */
+ );
+#if 0
+ ddr->timing_cfg_0 |= 0xaa000000; /* extra cycles */
+#endif
+ debug("DDR: timing_cfg_0 = 0x%08x\n", ddr->timing_cfg_0);
+
+ } else {
+#if 0
+ /*
+ * Force extra cycles with 0xaa bits.
+ * Incidentally supply the dreamt-up backwards compat value!
+ */
+ ddr->timing_cfg_0 = 0x00110105; /* backwards compat value */
+ ddr->timing_cfg_0 |= 0xaa000000; /* extra cycles */
+ debug("DDR: HACK timing_cfg_0 = 0x%08x\n", ddr->timing_cfg_0);
+#endif
+ }
+
+
+ /*
+ * Some Timing Config 1 values now.
+ * Sneak Extended Refresh Recovery in here too.
+ */
+
+ /*
+ * For DDR I, WRREC(Twr) and WRTORD(Twtr) are not in SPD,
+ * use conservative value.
+ * For DDR II, they are bytes 36 and 37, in quarter nanos.
+ */
+
+ if (spd.mem_type == SPD_MEMTYPE_DDR) {
+ twr_clk = 3; /* Clocks */
+ twtr_clk = 1; /* Clocks */
+ } else {
+ twr_clk = picos_to_clk(spd.twr * 250);
+ twtr_clk = picos_to_clk(spd.twtr * 250);
+ }
+
+ /*
+ * Calculate Trfc, in picos.
+ * DDR I: Byte 42 straight up in ns.
+ * DDR II: Byte 40 and 42 swizzled some, in ns.
+ */
+ if (spd.mem_type == SPD_MEMTYPE_DDR) {
+ trfc = spd.trfc * 1000; /* up to ps */
+ } else {
+ unsigned int byte40_table_ps[8] = {
+ 0,
+ 250,
+ 330,
+ 500,
+ 660,
+ 750,
+ 0,
+ 0
+ };
+
+ trfc = (((spd.trctrfc_ext & 0x1) * 256) + spd.trfc) * 1000
+ + byte40_table_ps[(spd.trctrfc_ext >> 1) & 0x7];
+ }
+ trfc_clk = picos_to_clk(trfc);
+
+ /*
+ * Trcd, Byte 29, from quarter nanos to ps and clocks.
+ */
+ trcd_clk = picos_to_clk(spd.trcd * 250) & 0x7;
+
+ /*
+ * Convert trfc_clk to DDR controller fields. DDR I should
+ * fit in the REFREC field (16-19) of TIMING_CFG_1, but the
+ * 8548 controller has an extended REFREC field of three bits.
+ * The controller automatically adds 8 clocks to this value,
+ * so preadjust it down 8 first before splitting it up.
+ */
+ trfc_low = (trfc_clk - 8) & 0xf;
+ trfc_high = ((trfc_clk - 8) >> 4) & 0x3;
+
+ /*
+ * Sneak in some Extended Refresh Recovery.
+ */
+ ddr->ext_refrec = (trfc_high << 16);
+ debug("DDR: ext_refrec = 0x%08x\n", ddr->ext_refrec);
+
+ ddr->timing_cfg_1 =
+ (0
+ | ((picos_to_clk(spd.trp * 250) & 0x07) << 28) /* PRETOACT */
+ | ((picos_to_clk(spd.tras * 1000) & 0x0f ) << 24) /* ACTTOPRE */
+ | (trcd_clk << 20) /* ACTTORW */
+ | (caslat_ctrl << 16) /* CASLAT */
+ | (trfc_low << 12) /* REFEC */
+ | ((twr_clk & 0x07) << 8) /* WRRREC */
+ | ((picos_to_clk(spd.trrd * 250) & 0x07) << 4) /* ACTTOACT */
+ | ((twtr_clk & 0x07) << 0) /* WRTORD */
+ );
+
+ debug("DDR: timing_cfg_1 = 0x%08x\n", ddr->timing_cfg_1);
+
+
+ /*
+ * Timing_Config_2
+ * Was: 0x00000800;
+ */
+
+ /*
+ * Additive Latency
+ * For DDR I, 0.
+ * For DDR II, with ODT enabled, use "a value" less than ACTTORW,
+ * which comes from Trcd, and also note that:
+ * add_lat + caslat must be >= 4
+ */
+ add_lat = 0;
+ if (spd.mem_type == SPD_MEMTYPE_DDR2
+ && (odt_wr_cfg || odt_rd_cfg)
+ && (caslat < 4)) {
+ add_lat = 4 - caslat;
+ if (add_lat > trcd_clk) {
+ add_lat = trcd_clk - 1;
+ }
+ }
+
+ /*
+ * Write Data Delay
+ * Historically 0x2 == 4/8 clock delay.
+ * Empirically, 0x3 == 6/8 clock delay is suggested for DDR I 266.
+ */
+ wr_data_delay = 3;
+
+ /*
+ * Write Latency
+ * Read to Precharge
+ * Minimum CKE Pulse Width.
+ * Four Activate Window
+ */
+ if (spd.mem_type == SPD_MEMTYPE_DDR) {
+ /*
+ * This is a lie. It should really be 1, but if it is
+ * set to 1, bits overlap into the old controller's
+ * otherwise unused ACSM field. If we leave it 0, then
+ * the HW will magically treat it as 1 for DDR 1. Oh Yea.
+ */
+ wr_lat = 0;
+
+ trtp_clk = 2; /* By the book. */
+ cke_min_clk = 1; /* By the book. */
+ four_act = 1; /* By the book. */
+
+ } else {
+ wr_lat = caslat - 1;
+
+ /* Convert SPD value from quarter nanos to picos. */
+ trtp_clk = picos_to_clk(spd.trtp * 250);
+
+ cke_min_clk = 3; /* By the book. */
+ four_act = picos_to_clk(37500); /* By the book. 1k pages? */
+ }
+
+ /*
+ * Empirically set ~MCAS-to-preamble override for DDR 2.
+ * Your milage will vary.
+ */
+ cpo = 0;
+ if (spd.mem_type == SPD_MEMTYPE_DDR2) {
+ if (effective_data_rate == 266 || effective_data_rate == 333) {
+ cpo = 0x7; /* READ_LAT + 5/4 */
+ } else if (effective_data_rate == 400) {
+ cpo = 0x9; /* READ_LAT + 7/4 */
+ } else {
+ /* Pure speculation */
+ cpo = 0xb;
+ }
+ }
+
+ ddr->timing_cfg_2 = (0
+ | ((add_lat & 0x7) << 28) /* ADD_LAT */
+ | ((cpo & 0x1f) << 23) /* CPO */
+ | ((wr_lat & 0x7) << 19) /* WR_LAT */
+ | ((trtp_clk & 0x7) << 13) /* RD_TO_PRE */
+ | ((wr_data_delay & 0x7) << 10) /* WR_DATA_DELAY */
+ | ((cke_min_clk & 0x7) << 6) /* CKE_PLS */
+ | ((four_act & 0x1f) << 0) /* FOUR_ACT */
+ );
+
+ debug("DDR: timing_cfg_2 = 0x%08x\n", ddr->timing_cfg_2);
+
+
+ /*
+ * Determine the Mode Register Set.
+ *
+ * This is nominally part specific, but it appears to be
+ * consistent for all DDR I devices, and for all DDR II devices.
+ *
+ * caslat must be programmed
+ * burst length is always 4
+ * burst type is sequential
+ *
+ * For DDR I:
+ * operating mode is "normal"
+ *
+ * For DDR II:
+ * other stuff
+ */
+
+ mode_caslat = 0;
+
+ /*
+ * Table lookup from DDR I or II Device Operation Specs.
+ */
+ if (spd.mem_type == SPD_MEMTYPE_DDR) {
+ if (1 <= caslat && caslat <= 4) {
+ unsigned char mode_caslat_table[4] = {
+ 0x5, /* 1.5 clocks */
+ 0x2, /* 2.0 clocks */
+ 0x6, /* 2.5 clocks */
+ 0x3 /* 3.0 clocks */
+ };
+ mode_caslat = mode_caslat_table[caslat - 1];
+ } else {
+ puts("DDR I: Only CAS Latencies of 1.5, 2.0, "
+ "2.5 and 3.0 clocks are supported.\n");
+ return 0;
+ }
+
+ } else {
+ if (2 <= caslat && caslat <= 5) {
+ mode_caslat = caslat;
+ } else {
+ puts("DDR II: Only CAS Latencies of 2.0, 3.0, "
+ "4.0 and 5.0 clocks are supported.\n");
+ return 0;
+ }
+ }
+
+ /*
+ * Encoded Burst Lenght of 4.
+ */
+ burst_len = 2; /* Fiat. */
+
+ if (spd.mem_type == SPD_MEMTYPE_DDR) {
+ twr_auto_clk = 0; /* Historical */
+ } else {
+ /*
+ * Determine tCK max in picos. Grab tWR and convert to picos.
+ * Auto-precharge write recovery is:
+ * WR = roundup(tWR_ns/tCKmax_ns).
+ *
+ * Ponder: Is twr_auto_clk different than twr_clk?
+ */
+ tCKmax_ps = convert_bcd_tenths_to_cycle_time_ps(spd.tckmax);
+ twr_auto_clk = (spd.twr * 250 + tCKmax_ps - 1) / tCKmax_ps;
+ }
+
+
+ /*
+ * Mode Reg in bits 16 ~ 31,
+ * Extended Mode Reg 1 in bits 0 ~ 15.
+ */
+ mode_odt_enable = 0x0; /* Default disabled */
+ if (odt_wr_cfg || odt_rd_cfg) {
+ /*
+ * Bits 6 and 2 in Extended MRS(1)
+ * Bit 2 == 0x04 == 75 Ohm, with 2 DIMM modules.
+ * Bit 6 == 0x40 == 150 Ohm, with 1 DIMM module.
+ */
+ mode_odt_enable = 0x40; /* 150 Ohm */
+ }
+
+ ddr->sdram_mode =
+ (0
+ | (add_lat << (16 + 3)) /* Additive Latency in EMRS1 */
+ | (mode_odt_enable << 16) /* ODT Enable in EMRS1 */
+ | (twr_auto_clk << 9) /* Write Recovery Autopre */
+ | (mode_caslat << 4) /* caslat */
+ | (burst_len << 0) /* Burst length */
+ );
+
+ debug("DDR: sdram_mode = 0x%08x\n", ddr->sdram_mode);
+
+
+ /*
+ * Clear EMRS2 and EMRS3.
+ */
+ ddr->sdram_mode_2 = 0;
+ debug("DDR: sdram_mode_2 = 0x%08x\n", ddr->sdram_mode_2);
+
+
+ /*
+ * Determine Refresh Rate. Ignore self refresh bit on DDR I.
+ * Table from SPD Spec, Byte 12, converted to picoseconds and
+ * filled in with "default" normal values.
+ */
+ {
+ unsigned int refresh_clk;
+ unsigned int refresh_time_ns[8] = {
+ 15625000, /* 0 Normal 1.00x */
+ 3900000, /* 1 Reduced .25x */
+ 7800000, /* 2 Extended .50x */
+ 31300000, /* 3 Extended 2.00x */
+ 62500000, /* 4 Extended 4.00x */
+ 125000000, /* 5 Extended 8.00x */
+ 15625000, /* 6 Normal 1.00x filler */
+ 15625000, /* 7 Normal 1.00x filler */
+ };
+
+ refresh_clk = picos_to_clk(refresh_time_ns[spd.refresh & 0x7]);
+
+ /*
+ * Set BSTOPRE to 0x100 for page mode
+ * If auto-charge is used, set BSTOPRE = 0
+ */
+ ddr->sdram_interval =
+ (0
+ | (refresh_clk & 0x3fff) << 16
+ | 0x100
+ );
+ debug("DDR: sdram_interval = 0x%08x\n", ddr->sdram_interval);
+ }
+
+ /*
+ * Is this an ECC DDR chip?
+ * But don't mess with it if the DDR controller will init mem.
+ */
+#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
+ if (spd.config == 0x02) {
+ ddr->err_disable = 0x0000000d;
+ ddr->err_sbe = 0x00ff0000;
+ }
+ debug("DDR: err_disable = 0x%08x\n", ddr->err_disable);
+ debug("DDR: err_sbe = 0x%08x\n", ddr->err_sbe);
+#endif
+
+ asm("sync;isync;msync");
+ udelay(500);
+
+ /*
+ * SDRAM Cfg 2
+ */
+
+ /*
+ * When ODT is enabled, Chap 9 suggests asserting ODT to
+ * internal IOs only during reads.
+ */
+ odt_cfg = 0;
+ if (odt_rd_cfg | odt_wr_cfg) {
+ odt_cfg = 0x2; /* ODT to IOs during reads */
+ }
+
+ /*
+ * Try to use differential DQS with DDR II.
+ */
+ if (spd.mem_type == SPD_MEMTYPE_DDR) {
+ dqs_cfg = 0; /* No Differential DQS for DDR I */
+ } else {
+ dqs_cfg = 0x1; /* Differential DQS for DDR II */
+ }
+
+#if defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
+ /*
+ * Use the DDR controller to auto initialize memory.
+ */
+ d_init = 1;
+ ddr->sdram_data_init = CONFIG_MEM_INIT_VALUE;
+ debug("DDR: ddr_data_init = 0x%08x\n", ddr->sdram_data_init);
+#else
+ /*
+ * Memory will be initialized via DMA, or not at all.
+ */
+ d_init = 0;
+#endif
+
+ ddr->sdram_cfg_2 = (0
+ | (dqs_cfg << 26) /* Differential DQS */
+ | (odt_cfg << 21) /* ODT */
+ | (d_init << 4) /* D_INIT auto init DDR */
+ );
+
+ debug("DDR: sdram_cfg_2 = 0x%08x\n", ddr->sdram_cfg_2);
+
+
+#ifdef MPC85xx_DDR_SDRAM_CLK_CNTL
+ {
+ unsigned char clk_adjust;
+
+ /*
+ * Setup the clock control.
+ * SDRAM_CLK_CNTL[0] = Source synchronous enable == 1
+ * SDRAM_CLK_CNTL[5-7] = Clock Adjust
+ * 0110 3/4 cycle late
+ * 0111 7/8 cycle late
+ */
+ if (spd.mem_type == SPD_MEMTYPE_DDR) {
+ clk_adjust = 0x6;
+ } else {
+ clk_adjust = 0x7;
+ }
+
+ ddr->sdram_clk_cntl = (0
+ | 0x80000000
+ | (clk_adjust << 23)
+ );
+ debug("DDR: sdram_clk_cntl = 0x%08x\n", ddr->sdram_clk_cntl);
+ }
+#endif
+
+ /*
+ * Figure out the settings for the sdram_cfg register.
+ * Build up the entire register in 'sdram_cfg' before writing
+ * since the write into the register will actually enable the
+ * memory controller; all settings must be done before enabling.
+ *
+ * sdram_cfg[0] = 1 (ddr sdram logic enable)
+ * sdram_cfg[1] = 1 (self-refresh-enable)
+ * sdram_cfg[5:7] = (SDRAM type = DDR SDRAM)
+ * 010 DDR 1 SDRAM
+ * 011 DDR 2 SDRAM
+ */
+ sdram_type = (spd.mem_type == SPD_MEMTYPE_DDR) ? 2 : 3;
+ sdram_cfg = (0
+ | (1 << 31) /* Enable */
+ | (1 << 30) /* Self refresh */
+ | (sdram_type << 24) /* SDRAM type */
+ );
+
+ /*
+ * sdram_cfg[3] = RD_EN - registered DIMM enable
+ * A value of 0x26 indicates micron registered DIMMS (micron.com)
+ */
+ if (spd.mem_type == SPD_MEMTYPE_DDR && spd.mod_attr == 0x26) {
+ sdram_cfg |= 0x10000000; /* RD_EN */
+ }
+
+#if defined(CONFIG_DDR_ECC)
+ /*
+ * If the user wanted ECC (enabled via sdram_cfg[2])
+ */
+ if (spd.config == 0x02) {
+ sdram_cfg |= 0x20000000; /* ECC_EN */
+ }
+#endif
+
+ /*
+ * REV1 uses 1T timing.
+ * REV2 may use 1T or 2T as configured by the user.
+ */
+ {
+ uint pvr = get_pvr();
+
+ if (pvr != PVR_85xx_REV1) {
+#if defined(CONFIG_DDR_2T_TIMING)
+ /*
+ * Enable 2T timing by setting sdram_cfg[16].
+ */
+ sdram_cfg |= 0x8000; /* 2T_EN */
+#endif
+ }
+ }
+
+ /*
+ * 200 painful micro-seconds must elapse between
+ * the DDR clock setup and the DDR config enable.
+ */
+ udelay(200);
+
+ /*
+ * Go!
+ */
+ ddr->sdram_cfg = sdram_cfg;
+
+ asm("sync;isync;msync");
+ udelay(500);
+
+ debug("DDR: sdram_cfg = 0x%08x\n", ddr->sdram_cfg);
+
+
+#if defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
+ /*
+ * Poll until memory is initialized.
+ * 512 Meg at 400 might hit this 200 times or so.
+ */
+ while ((ddr->sdram_cfg_2 & (d_init << 4)) != 0) {
+ udelay(1000);
+ }
+#endif
+
+
+ /*
+ * Figure out memory size in Megabytes.
+ */
+ memsize = n_ranks * rank_density / 0x100000;
+
+ /*
+ * Establish Local Access Window and TLB mappings for DDR memory.
+ */
+ memsize = setup_laws_and_tlbs(memsize);
+ if (memsize == 0) {
+ return 0;
+ }
+
+ return memsize * 1024 * 1024;
+}
+
+
+/*
+ * Setup Local Access Window and TLB1 mappings for the requested
+ * amount of memory. Returns the amount of memory actually mapped
+ * (usually the original request size), or 0 on error.
+ */
+
+static unsigned int
+setup_laws_and_tlbs(unsigned int memsize)
+{
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+ volatile ccsr_local_ecm_t *ecm = &immap->im_local_ecm;
+ unsigned int tlb_size;
+ unsigned int law_size;
+ unsigned int ram_tlb_index;
+ unsigned int ram_tlb_address;
+
+ /*
+ * Determine size of each TLB1 entry.
+ */
+ switch (memsize) {
+ case 16:
+ case 32:
+ tlb_size = BOOKE_PAGESZ_16M;
+ break;
+ case 64:
+ case 128:
+ tlb_size = BOOKE_PAGESZ_64M;
+ break;
+ case 256:
+ case 512:
+ case 1024:
+ case 2048:
+ tlb_size = BOOKE_PAGESZ_256M;
+ break;
+ default:
+ puts("DDR: only 16M,32M,64M,128M,256M,512M,1G and 2G are supported.\n");
+
+ /*
+ * The memory was not able to be mapped.
+ */
+ return 0;
+ break;
+ }
+
+ /*
+ * Configure DDR TLB1 entries.
+ * Starting at TLB1 8, use no more than 8 TLB1 entries.
+ */
+ ram_tlb_index = 8;
+ ram_tlb_address = (unsigned int)CFG_DDR_SDRAM_BASE;
+ while (ram_tlb_address < (memsize * 1024 * 1024)
+ && ram_tlb_index < 16) {
+ mtspr(MAS0, TLB1_MAS0(1, ram_tlb_index, 0));
+ mtspr(MAS1, TLB1_MAS1(1, 1, 0, 0, tlb_size));
+ mtspr(MAS2, TLB1_MAS2(E500_TLB_EPN(ram_tlb_address),
+ 0, 0, 0, 0, 0, 0, 0, 0));
+ mtspr(MAS3, TLB1_MAS3(E500_TLB_RPN(ram_tlb_address),
+ 0, 0, 0, 0, 0, 1, 0, 1, 0, 1));
+ asm volatile("isync;msync;tlbwe;isync");
+
+ debug("DDR: MAS0=0x%08x\n", TLB1_MAS0(1, ram_tlb_index, 0));
+ debug("DDR: MAS1=0x%08x\n", TLB1_MAS1(1, 1, 0, 0, tlb_size));
+ debug("DDR: MAS2=0x%08x\n",
+ TLB1_MAS2(E500_TLB_EPN(ram_tlb_address),
+ 0, 0, 0, 0, 0, 0, 0, 0));
+ debug("DDR: MAS3=0x%08x\n",
+ TLB1_MAS3(E500_TLB_RPN(ram_tlb_address),
+ 0, 0, 0, 0, 0, 1, 0, 1, 0, 1));
+
+ ram_tlb_address += (0x1000 << ((tlb_size - 1) * 2));
+ ram_tlb_index++;
+ }
+
+
+ /*
+ * First supported LAW size is 16M, at LAWAR_SIZE_16M == 23. Fnord.
+ */
+ law_size = 19 + __ilog2(memsize);
+
+ /*
+ * Set up LAWBAR for all of DDR.
+ */
+ ecm->lawbar1 = ((CFG_DDR_SDRAM_BASE >> 12) & 0xfffff);
+ ecm->lawar1 = (LAWAR_EN
+ | LAWAR_TRGT_IF_DDR
+ | (LAWAR_SIZE & law_size));
+ debug("DDR: LAWBAR1=0x%08x\n", ecm->lawbar1);
+ debug("DDR: LARAR1=0x%08x\n", ecm->lawar1);
+
+ /*
+ * Confirm that the requested amount of memory was mapped.
+ */
+ return memsize;
+}
+
+#endif /* CONFIG_SPD_EEPROM */
+
+
+#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
+
+/*
+ * Initialize all of memory for ECC, then enable errors.
+ */
+
+void
+ddr_enable_ecc(unsigned int dram_size)
+{
+ uint *p = 0;
+ uint i = 0;
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+ volatile ccsr_ddr_t *ddr= &immap->im_ddr;
+
+ dma_init();
+
+ for (*p = 0; p < (uint *)(8 * 1024); p++) {
+ if (((unsigned int)p & 0x1f) == 0) {
+ ppcDcbz((unsigned long) p);
+ }
+ *p = (unsigned int)CONFIG_MEM_INIT_VALUE;
+ if (((unsigned int)p & 0x1c) == 0x1c) {
+ ppcDcbf((unsigned long) p);
+ }
+ }
+
+ /* 8K */
+ dma_xfer((uint *)0x2000, 0x2000, (uint *)0);
+ /* 16K */
+ dma_xfer((uint *)0x4000, 0x4000, (uint *)0);
+ /* 32K */
+ dma_xfer((uint *)0x8000, 0x8000, (uint *)0);
+ /* 64K */
+ dma_xfer((uint *)0x10000, 0x10000, (uint *)0);
+ /* 128k */
+ dma_xfer((uint *)0x20000, 0x20000, (uint *)0);
+ /* 256k */
+ dma_xfer((uint *)0x40000, 0x40000, (uint *)0);
+ /* 512k */
+ dma_xfer((uint *)0x80000, 0x80000, (uint *)0);
+ /* 1M */
+ dma_xfer((uint *)0x100000, 0x100000, (uint *)0);
+ /* 2M */
+ dma_xfer((uint *)0x200000, 0x200000, (uint *)0);
+ /* 4M */
+ dma_xfer((uint *)0x400000, 0x400000, (uint *)0);
+
+ for (i = 1; i < dram_size / 0x800000; i++) {
+ dma_xfer((uint *)(0x800000*i), 0x800000, (uint *)0);
+ }
+
+ /*
+ * Enable errors for ECC.
+ */
+ debug("DMA DDR: err_disable = 0x%08x\n", ddr->err_disable);
+ ddr->err_disable = 0x00000000;
+ asm("sync;isync;msync");
+ debug("DMA DDR: err_disable = 0x%08x\n", ddr->err_disable);
+}
+
+#endif /* CONFIG_DDR_ECC && ! CONFIG_ECC_INIT_VIA_DDRCONTROLLER */
diff --git a/cpu/mpc85xx/speed.c b/cpu/mpc85xx/speed.c
new file mode 100755
index 0000000..d736742
--- /dev/null
+++ b/cpu/mpc85xx/speed.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2004 Freescale Semiconductor.
+ * (C) Copyright 2003 Motorola Inc.
+ * Xianghua Xiao, (X.Xiao@motorola.com)
+ *
+ * (C) Copyright 2000
+ * 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
+ */
+
+#include <common.h>
+#include <ppc_asm.tmpl>
+#include <asm/processor.h>
+
+/* --------------------------------------------------------------- */
+
+void get_sys_info (sys_info_t * sysInfo)
+{
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+ volatile ccsr_gur_t *gur = &immap->im_gur;
+ uint plat_ratio,e500_ratio;
+
+ plat_ratio = (gur->porpllsr) & 0x0000003e;
+ plat_ratio >>= 1;
+ switch(plat_ratio) {
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0c:
+ case 0x10:
+ sysInfo->freqSystemBus = plat_ratio * CONFIG_SYS_CLK_FREQ;
+ break;
+ default:
+ sysInfo->freqSystemBus = 0;
+ break;
+ }
+
+ e500_ratio = (gur->porpllsr) & 0x003f0000;
+ e500_ratio >>= 16;
+ switch(e500_ratio) {
+ case 0x04:
+ sysInfo->freqProcessor = 2*sysInfo->freqSystemBus;
+ break;
+ case 0x05:
+ sysInfo->freqProcessor = 5*sysInfo->freqSystemBus/2;
+ break;
+ case 0x06:
+ sysInfo->freqProcessor = 3*sysInfo->freqSystemBus;
+ break;
+ case 0x07:
+ sysInfo->freqProcessor = 7*sysInfo->freqSystemBus/2;
+ break;
+ default:
+ sysInfo->freqProcessor = 0;
+ break;
+ }
+}
+
+int get_clocks (void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+ sys_info_t sys_info;
+#if defined(CONFIG_CPM2)
+ volatile immap_t *immap = (immap_t *) CFG_IMMR;
+ uint sccr, dfbrg;
+
+ /* set VCO = 4 * BRG */
+ immap->im_cpm.im_cpm_intctl.sccr &= 0xfffffffc;
+ sccr = immap->im_cpm.im_cpm_intctl.sccr;
+ dfbrg = (sccr & SCCR_DFBRG_MSK) >> SCCR_DFBRG_SHIFT;
+#endif
+ get_sys_info (&sys_info);
+ gd->cpu_clk = sys_info.freqProcessor;
+ gd->bus_clk = sys_info.freqSystemBus;
+#if defined(CONFIG_CPM2)
+ gd->vco_out = 2*sys_info.freqSystemBus;
+ gd->cpm_clk = gd->vco_out / 2;
+ gd->scc_clk = gd->vco_out / 4;
+ gd->brg_clk = gd->vco_out / (1 << (2 * (dfbrg + 1)));
+#endif
+
+ if(gd->cpu_clk != 0) return (0);
+ else return (1);
+}
+
+
+/********************************************
+ * get_bus_freq
+ * return system bus freq in Hz
+ *********************************************/
+ulong get_bus_freq (ulong dummy)
+{
+ ulong val;
+
+ sys_info_t sys_info;
+
+ get_sys_info (&sys_info);
+ val = sys_info.freqSystemBus;
+
+ return val;
+}
diff --git a/cpu/mpc85xx/start.S b/cpu/mpc85xx/start.S
new file mode 100755
index 0000000..7ac6573
--- /dev/null
+++ b/cpu/mpc85xx/start.S
@@ -0,0 +1,1157 @@
+/*
+ * Copyright 2004 Freescale Semiconductor.
+ * Copyright (C) 2003 Motorola,Inc.
+ * Xianghua Xiao<X.Xiao@motorola.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* U-Boot Startup Code for Motorola 85xx PowerPC based Embedded Boards
+ *
+ * The processor starts at 0xfffffffc and the code is first executed in the
+ * last 4K page(0xfffff000-0xffffffff) in flash/rom.
+ *
+ */
+
+#include <config.h>
+#include <mpc85xx.h>
+#include <version.h>
+
+#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#ifndef CONFIG_IDENT_STRING
+#define CONFIG_IDENT_STRING ""
+#endif
+
+#undef MSR_KERNEL
+#define MSR_KERNEL ( MSR_ME ) /* Machine Check */
+
+/*
+ * 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
+
+/*
+ * e500 Startup -- after reset only the last 4KB of the effective
+ * address space is mapped in the MMU L2 TLB1 Entry0. The .bootpg
+ * section is located at THIS LAST page and basically does three
+ * things: clear some registers, set up exception tables and
+ * add more TLB entries for 'larger spaces'(e.g. the boot rom) to
+ * continue the boot procedure.
+
+ * Once the boot rom is mapped by TLB entries we can proceed
+ * with normal startup.
+ *
+ */
+
+ .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
+
+ /*
+ * 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
+
+ mfspr r1,DBSR
+ mtspr DBSR,r1 /* Clear all valid bits */
+
+ mtspr PID0,r0
+ mtspr PID1,r0
+ mtspr PID2,r0
+ mtspr TCR,r0
+
+ mtspr BUCSR,r0 /* disable branch prediction */
+ mtspr MAS4,r0
+ mtspr MAS6,r0
+#if defined(CONFIG_ENABLE_36BIT_PHYS)
+ mtspr MAS7,r0
+#endif
+ isync
+
+ /* Setup interrupt vectors */
+ lis r1,TEXT_BASE@h
+ mtspr IVPR, r1
+
+ li r1,0x0100
+ mtspr IVOR0,r1 /* 0: Critical input */
+ li r1,0x0200
+ mtspr IVOR1,r1 /* 1: Machine check */
+ li r1,0x0300
+ mtspr IVOR2,r1 /* 2: Data storage */
+ li r1,0x0400
+ mtspr IVOR3,r1 /* 3: Instruction storage */
+ li r1,0x0500
+ mtspr IVOR4,r1 /* 4: External interrupt */
+ li r1,0x0600
+ mtspr IVOR5,r1 /* 5: Alignment */
+ li r1,0x0700
+ mtspr IVOR6,r1 /* 6: Program check */
+ li r1,0x0800
+ mtspr IVOR7,r1 /* 7: floating point unavailable */
+ li r1,0x0900
+ mtspr IVOR8,r1 /* 8: System call */
+ /* 9: Auxiliary processor unavailable(unsupported) */
+ li r1,0x0a00
+ mtspr IVOR10,r1 /* 10: Decrementer */
+ li r1,0x0b00
+ mtspr IVOR11,r1 /* 11: Interval timer */
+ li r1,0x0c00
+ mtspr IVOR12,r1 /* 12: Watchdog timer */
+ li r1,0x0d00
+ mtspr IVOR13,r1 /* 13: Data TLB error */
+ li r1,0x0e00
+ mtspr IVOR14,r1 /* 14: Instruction TLB error */
+ 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.
+ * 0xff700000-0xff800000. We need add a TLB1 entry for this 1MB
+ * region before we can access any CCSR registers such as L2
+ * registers, Local Access Registers,etc. We will also re-allocate
+ * CFG_CCSRBAR_DEFAULT to CFG_CCSRBAR immediately after TLB1 setup.
+ *
+ * Please refer to board-specif directory for TLB1 entry configuration.
+ * (e.g. board/<yourboard>/init.S)
+ *
+ */
+ bl tlb1_entry
+ mr r5,r0
+ li r1,0x0020 /* max 16 TLB1 plus some TLB0 entries */
+ mtctr r1
+ lwzu r4,0(r5) /* how many TLB1 entries we actually use */
+
+0: cmpwi r4,0
+ beq 1f
+ 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
+ isync
+ msync
+ tlbwe
+ isync
+ addi r4,r4,-1
+ bdnz 0b
+
+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 r5, CFG_CCSRBAR@h
+ ori r5, r5, CFG_CCSRBAR@l
+ srwi r6,r5,12
+ stw r6, 0(r4)
+ isync
+
+ lis r5, 0xffff
+ ori r5,r5,0xf000
+ lwz r5, 0(r5)
+ isync
+
+ lis r3, CFG_CCSRBAR@h
+ lwz r5, CFG_CCSRBAR@l(r3)
+ isync
+#endif
+
+
+ /* set up local access windows, defined at board/<boardname>/init.S */
+ lis r7,CFG_CCSRBAR@h
+ ori r7,r7,CFG_CCSRBAR@l
+
+ bl law_entry
+ mr r6,r0
+ li r1,0x0007 /* 8 LAWs, but reserve one for boot-over-rio-or-pci */
+ mtctr r1
+ lwzu r5,0(r6) /* how many windows we actually use */
+
+ li r2,0x0c28 /* the first pair is reserved for boot-over-rio-or-pci */
+ li r1,0x0c30
+
+0: cmpwi r5,0
+ beq 1f
+ lwzu r4,4(r6)
+ lwzu r3,4(r6)
+ stwx r4,r7,r2
+ stwx r3,r7,r1
+ addi r5,r5,-1
+ addi r2,r2,0x0020
+ 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
+ mtspr DEC,r0 /* prevent dec exceptions */
+ mttbl r0 /* prevent fit & wdt exceptions */
+ mttbu r0
+ mtspr TSR,r1 /* clear all timer exception status */
+ mtspr TCR,r0 /* disable all */
+ mtspr ESR,r0 /* clear exception syndrome register */
+ mtspr MCSR,r0 /* machine check syndrome register */
+ mtxer r0 /* clear integer exception register */
+ lis r1,0x0002 /* set CE bit (Critical Exceptions) */
+ ori r1,r1,0x1200 /* set ME/DE bit */
+ mtmsr r1 /* change MSR */
+ isync
+
+ /* Enable Time Base and Select Time Base Clock */
+ lis r0,HID0_EMCP@h /* Enable machine check */
+ ori r0,r0,0x4000 /* time base is processor clock */
+#if defined(CONFIG_ENABLE_36BIT_PHYS)
+ ori r0,r0,0x0080 /* enable MAS7 updates */
+#endif
+ mtspr HID0,r0
+
+#if defined(CONFIG_ADDR_STREAMING)
+ li r0,0x3000
+#else
+ li r0,0x1000
+#endif
+ mtspr HID1,r0
+
+ /* Enable Branch Prediction */
+#if defined(CONFIG_BTB)
+ li r0,0x201 /* BBFI = 1, BPEN = 1 */
+ mtspr BUCSR,r0
+#endif
+
+#if defined(CFG_INIT_DBCR)
+ lis r1,0xffff
+ ori r1,r1,0xffff
+ mtspr DBSR,r1 /* Clear all status bits */
+ lis r0,CFG_INIT_DBCR@h /* DBCR0[IDM] must be set */
+ ori r0,r0,CFG_INIT_DBCR@l
+ mtspr DBCR0,r0
+#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 */
+ mtctr r2
+ li r0, 0
+1:
+ dcbz r0, r3
+ dcbtls 0,r0, r3
+ addi r3, r3, 32
+ bdnz 1b
+
+#ifndef CFG_RAMBOOT
+ /* 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
+ mtlr r3
+ blr
+
+in_flash:
+#endif /* CFG_RAMBOOT */
+
+ /* 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
+
+ li r0,0
+ stwu r0,-4(r1)
+ stwu r0,-4(r1) /* Terminate call chain */
+
+ 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
+ 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 */
+
+ .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)
+
+/* Data Storage exception. */
+ STD_EXCEPTION(0x0300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. */
+ STD_EXCEPTION(0x0400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+ STD_EXCEPTION(0x0500, ExtInterrupt, UnknownException)
+
+/* Alignment exception. */
+ . = 0x0600
+Alignment:
+ EXCEPTION_PROLOG
+ mfspr r4,DAR
+ stw r4,_DAR(r21)
+ mfspr r5,DSISR
+ stw r5,_DSISR(r21)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r20,MSR_KERNEL
+ rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
+ 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 */
+ . = 0x0700
+ProgramCheck:
+ EXCEPTION_PROLOG
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r20,MSR_KERNEL
+ rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
+ 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
+
+ /* No FPU on MPC85xx. This exception is not supposed to happen.
+ */
+ STD_EXCEPTION(0x0800, FPUnavailable, UnknownException)
+
+ . = 0x0900
+/*
+ * r0 - SYSCALL number
+ * 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 */
+ ori r12,r12,0
+
+ cmplw 0, r0, r12
+ bge 1f
+
+ 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 */
+ lwz r12,0(r20)
+ subi r12,r12,12 /* Adjust stack pointer */
+ li r0,0xc00+_end_back-SystemCall
+ cmplw 0, r0, r12 /* Check stack overflow */
+ bgt 1f
+ stw r12,0(r20)
+
+ mflr r0
+ stw r0,0(r12)
+ mfspr r0,SRR0
+ stw r0,4(r12)
+ mfspr r0,SRR1
+ stw r0,8(r12)
+
+ li r12,0xc00+_back-SystemCall
+ mtlr r12
+ mtspr SRR0,r11
+
+1: SYNC
+ rfi
+_back:
+
+ mfmsr r11 /* Disable interrupts */
+ li r12,0
+ ori r12,r12,MSR_EE
+ andc r11,r11,r12
+ SYNC /* Some chip revs need this... */
+ mtmsr r11
+ SYNC
+
+ li r12,0xd00-4 /* restore regs */
+ lwz r12,0(r12)
+
+ lwz r11,0(r12)
+ mtlr r11
+ lwz r11,4(r12)
+ mtspr SRR0,r11
+ lwz r11,8(r12)
+ mtspr SRR1,r11
+
+ addi r12,r12,12 /* Adjust stack pointer */
+ li r20,0xd00-4
+ stw r12,0(r20)
+
+ SYNC
+ rfi
+_end_back:
+
+ STD_EXCEPTION(0x0a00, Decrementer, timer_interrupt)
+ STD_EXCEPTION(0x0b00, IntervalTimer, UnknownException)
+ STD_EXCEPTION(0x0c00, WatchdogTimer, UnknownException)
+
+ STD_EXCEPTION(0x0d00, DataTLBError, UnknownException)
+ STD_EXCEPTION(0x0e00, InstructionTLBError, UnknownException)
+
+ CRIT_EXCEPTION(0x0f00, DebugBreakpoint, DebugException )
+
+ .globl _end_of_vectors
+_end_of_vectors:
+
+
+ . = 0x2100
+
+/*
+ * 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)
+ mtspr SPRG2,r22 /* r1 is now kernel sp */
+
+ 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
+
+crit_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 990,r2 /* SRR2 */
+ mtspr 991,r0 /* SRR3 */
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfci
+
+/* Cache functions.
+*/
+invalidate_icache:
+ mfspr r0,L1CSR1
+ ori r0,r0,0x0002
+ mtspr L1CSR1,r0
+ isync
+ blr /* entire I cache */
+
+invalidate_dcache:
+ mfspr r0,L1CSR0
+ ori r0,r0,0x0002
+ msync
+ isync
+ mtspr L1CSR0,r0
+ isync
+ blr
+
+ .globl icache_enable
+icache_enable:
+ mflr r8
+ bl invalidate_icache
+ mtlr r8
+ isync
+ mfspr r4,L1CSR1
+ ori r4,r4,0x0001
+ oris r4,r4,0x0001
+ mtspr L1CSR1,r4
+ isync
+ blr
+
+ .globl icache_disable
+icache_disable:
+ mfspr r0,L1CSR1
+ lis r1,0xfffffffe@h
+ ori r1,r1,0xfffffffe@l
+ and r0,r0,r1
+ mtspr L1CSR1,r0
+ isync
+ blr
+
+ .globl icache_status
+icache_status:
+ mfspr r3,L1CSR1
+ srwi r3, r3, 31 /* >>31 => select bit 0 */
+ blr
+
+ .globl dcache_enable
+dcache_enable:
+ mflr r8
+ bl invalidate_dcache
+ mtlr r8
+ isync
+ mfspr r0,L1CSR0
+ ori r0,r0,0x0001
+ oris r0,r0,0x0001
+ msync
+ isync
+ mtspr L1CSR0,r0
+ isync
+ blr
+
+ .globl dcache_disable
+dcache_disable:
+ mfspr r0,L1CSR0
+ lis r1,0xfffffffe@h
+ ori r1,r1,0xfffffffe@l
+ and r0,r0,r1
+ msync
+ isync
+ mtspr L1CSR0,r0
+ isync
+ blr
+
+ .globl dcache_status
+dcache_status:
+ mfspr r3,L1CSR0
+ srwi r3, r3, 31 /* >>31 => select bit 0 */
+ blr
+
+ .globl get_pir
+get_pir:
+ mfspr r3, PIR
+ blr
+
+ .globl get_pvr
+get_pvr:
+ mfspr r3, PVR
+ blr
+
+ .globl get_svr
+get_svr:
+ mfspr r3, SVR
+ blr
+
+ .globl wr_tcr
+wr_tcr:
+ mtspr TCR, r3
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: in8 */
+/* Description: Input 8 bits */
+/*------------------------------------------------------------------------------- */
+ .globl in8
+in8:
+ lbz r3,0x0000(r3)
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: out8 */
+/* Description: Output 8 bits */
+/*------------------------------------------------------------------------------- */
+ .globl out8
+out8:
+ stb r4,0x0000(r3)
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: out16 */
+/* Description: Output 16 bits */
+/*------------------------------------------------------------------------------- */
+ .globl out16
+out16:
+ sth r4,0x0000(r3)
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: out16r */
+/* Description: Byte reverse and output 16 bits */
+/*------------------------------------------------------------------------------- */
+ .globl out16r
+out16r:
+ sthbrx r4,r0,r3
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: out32 */
+/* Description: Output 32 bits */
+/*------------------------------------------------------------------------------- */
+ .globl out32
+out32:
+ stw r4,0x0000(r3)
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: out32r */
+/* Description: Byte reverse and output 32 bits */
+/*------------------------------------------------------------------------------- */
+ .globl out32r
+out32r:
+ stwbrx r4,r0,r3
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: in16 */
+/* Description: Input 16 bits */
+/*------------------------------------------------------------------------------- */
+ .globl in16
+in16:
+ lhz r3,0x0000(r3)
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: in16r */
+/* Description: Input 16 bits and byte reverse */
+/*------------------------------------------------------------------------------- */
+ .globl in16r
+in16r:
+ lhbrx r3,r0,r3
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: in32 */
+/* Description: Input 32 bits */
+/*------------------------------------------------------------------------------- */
+ .globl in32
+in32:
+ lwz 3,0x0000(3)
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: in32r */
+/* Description: Input 32 bits and byte reverse */
+/*------------------------------------------------------------------------------- */
+ .globl in32r
+in32r:
+ lwbrx r3,r0,r3
+ 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
+
+/*------------------------------------------------------------------------------- */
+/* Function: ppcSync */
+/* Description: Processor Synchronize */
+/* Input: none. */
+/* Output: none. */
+/*------------------------------------------------------------------------------- */
+ .globl ppcSync
+ppcSync:
+ sync
+ 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 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
+ 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
+ /* the 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)
+1: lwzu r0,4(r8)
+ stwu r0,4(r7)
+ bdnz 1b
+ b 4f
+
+2: slwi r0,r0,2
+ 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
+
+ /*
+ * Re-point the IVPR at RAM
+ */
+ mtspr IVPR,r10
+
+/*
+ * 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 /* NEVER RETURNS! */
+
+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 /* Init Data pointer */
+ mr r4, r10 /* Destination Address */
+ bl board_init_r
+
+ /*
+ * Copy exception vector code to low memory
+ *
+ * r3: dest_addr
+ * r7: source address, r8: end address, r9: target address
+ */
+ .globl trap_init
+trap_init:
+ lwz r7, GOT(_start)
+ lwz r8, GOT(_end_of_vectors)
+
+ li r9, 0x100 /* reset vector always at 0x100 */
+
+ cmplw 0, r7, r8
+ bgelr /* return if r7>=r8 - just in case */
+
+ mflr r4 /* save link register */
+1:
+ lwz r0, 0(r7)
+ stw r0, 0(r9)
+ addi r7, r7, 4
+ addi r9, r9, 4
+ cmplw 0, r7, r8
+ bne 1b
+
+ /*
+ * relocate `hdlr' and `int_return' entries
+ */
+ li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+ li r7, .L_DataStorage - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+ li r7, .L_InstStorage - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+ li r7, .L_ExtInterrupt - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+ 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
+ bl trap_reloc
+ li r7, .L_Decrementer - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+ li r7, .L_IntervalTimer - _start + EXC_OFF_SYS_RESET
+ li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+2:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 2b
+
+ lis r7,0x0
+ mtspr IVPR, r7
+
+ mtlr r4 /* restore link register */
+ blr
+
+ /*
+ * Function: relocate entries for one exception vector
+ */
+trap_reloc:
+ lwz r0, 0(r7) /* hdlr ... */
+ add r0, r0, r3 /* ... += dest_addr */
+ stw r0, 0(r7)
+
+ lwz r0, 4(r7) /* int_return ... */
+ add r0, r0, r3 /* ... += dest_addr */
+ stw r0, 4(r7)
+
+ blr
+
+#ifdef CFG_INIT_RAM_LOCK
+.globl unlock_ram_in_cache
+unlock_ram_in_cache:
+ /* invalidate the INIT_RAM section */
+ lis r3, (CFG_INIT_RAM_ADDR & ~31)@h
+ ori r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
+ li r2,512
+ mtctr r2
+1: icbi r0, r3
+ dcbi r0, r3
+ addi r3, r3, 32
+ bdnz 1b
+ sync /* Wait for all icbi to complete on bus */
+ isync
+ blr
+#endif
diff --git a/cpu/mpc85xx/traps.c b/cpu/mpc85xx/traps.c
new file mode 100755
index 0000000..a87eed2
--- /dev/null
+++ b/cpu/mpc85xx/traps.c
@@ -0,0 +1,273 @@
+/*
+ * linux/arch/ppc/kernel/traps.c
+ *
+ * Copyright (C) 2003 Motorola
+ * Modified by Xianghua Xiao(x.xiao@motorola.com)
+ *
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/processor.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+int (*debugger_exception_handler)(struct pt_regs *) = 0;
+#endif
+
+/* Returns 0 if exception not found and fixup otherwise. */
+extern unsigned long search_exception_table(unsigned long);
+
+/*
+ * End of memory as shown by board info and determined by DDR setup.
+ */
+#define END_OF_MEM (gd->bd->bi_memstart + gd->bd->bi_memsize)
+
+
+static __inline__ void set_tsr(unsigned long val)
+{
+ asm volatile("mtspr 0x150, %0" : : "r" (val));
+}
+
+static __inline__ unsigned long get_esr(void)
+{
+ unsigned long val;
+ asm volatile("mfspr %0, 0x03e" : "=r" (val) :);
+ return val;
+}
+
+#define ESR_MCI 0x80000000
+#define ESR_PIL 0x08000000
+#define ESR_PPR 0x04000000
+#define ESR_PTR 0x02000000
+#define ESR_DST 0x00800000
+#define ESR_DIZ 0x00400000
+#define ESR_U0F 0x00008000
+
+#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+extern void do_bedbug_breakpoint(struct pt_regs *);
+#endif
+
+/*
+ * Trap & Exception support
+ */
+
+void
+print_backtrace(unsigned long *sp)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+ int cnt = 0;
+ unsigned long i;
+
+ printf("Call backtrace: ");
+ while (sp) {
+ if ((uint)sp > END_OF_MEM)
+ break;
+
+ i = sp[1];
+ if (cnt++ % 7 == 0)
+ printf("\n");
+ printf("%08lX ", i);
+ if (cnt > 32) break;
+ sp = (unsigned long *)*sp;
+ }
+ printf("\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);
+
+ printf("\n");
+ for (i = 0; i < 32; i++) {
+ if ((i % 8) == 0)
+ {
+ printf("GPR%02d: ", i);
+ }
+
+ printf("%08lX ", regs->gpr[i]);
+ if ((i % 8) == 7)
+ {
+ printf("\n");
+ }
+ }
+}
+
+
+void
+_exception(int signr, struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
+}
+
+void
+CritcalInputException(struct pt_regs *regs)
+{
+ panic("Critical Input Exception");
+}
+
+void
+MachineCheckException(struct pt_regs *regs)
+{
+ unsigned long fixup;
+
+ /* Probing PCI using config cycles cause this exception
+ * when a device is not present. Catch it and return to
+ * the PCI exception handler.
+ */
+ if ((fixup = search_exception_table(regs->nip)) != 0) {
+ regs->nip = fixup;
+ return;
+ }
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ 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");
+ }
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("machine check");
+}
+
+void
+AlignmentException(struct pt_regs *regs)
+{
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Alignment Exception");
+}
+
+void
+ProgramCheckException(struct pt_regs *regs)
+{
+ long esr_val;
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ show_regs(regs);
+
+ esr_val = get_esr();
+ if( esr_val & ESR_PIL )
+ printf( "** Illegal Instruction **\n" );
+ else if( esr_val & ESR_PPR )
+ printf( "** Privileged Instruction **\n" );
+ else if( esr_val & ESR_PTR )
+ printf( "** Trap Instruction **\n" );
+
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Program Check Exception");
+}
+
+void
+PITException(struct pt_regs *regs)
+{
+ /*
+ * Reset PIT interrupt
+ */
+ set_tsr(0x0c000000);
+
+ /*
+ * Call timer_interrupt routine in interrupts.c
+ */
+ timer_interrupt(NULL);
+}
+
+
+void
+UnknownException(struct pt_regs *regs)
+{
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+ regs->nip, regs->msr, regs->trap);
+ _exception(0, regs);
+}
+
+void
+DebugException(struct pt_regs *regs)
+{
+ printf("Debugger trap at @ %lx\n", regs->nip );
+ show_regs(regs);
+#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+ do_bedbug_breakpoint( regs );
+#endif
+}
+
+/* Probe an address by reading. If not present, return -1, otherwise
+ * return 0.
+ */
+int
+addr_probe(uint *addr)
+{
+ return 0;
+}