* Patches by Xianghua Xiao, 15 Oct 2003:
- Added Motorola CPU 8540/8560 support (cpu/85xx)
- Added Motorola MPC8540ADS board support (board/mpc8540ads)
- Added Motorola MPC8560ADS board support (board/mpc8560ads)
* Minor code cleanup
diff --git a/cpu/mpc85xx/Makefile b/cpu/mpc85xx/Makefile
new file mode 100644
index 0000000..996915e
--- /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 tsec.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 100644
index 0000000..df11052
--- /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_MPC8560)
+/*
+ * 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_MPC8560 */
diff --git a/cpu/mpc85xx/config.mk b/cpu/mpc85xx/config.mk
new file mode 100644
index 0000000..c12e923
--- /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 += -mrelocatable -ffixed-r14 -meabi
+
+PLATFORM_CPPFLAGS += -DCONFIG_MPC85xx -DCONFIG_E500 -ffixed-r2 -ffixed-r29 -Wa,-me500 -msoft-float
diff --git a/cpu/mpc85xx/cpu.c b/cpu/mpc85xx/cpu.c
new file mode 100644
index 0000000..64f2782
--- /dev/null
+++ b/cpu/mpc85xx/cpu.c
@@ -0,0 +1,151 @@
+/*
+ * (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)
+{
+ uint pir = get_pir();
+ uint pvr = get_pvr();
+
+ printf("Motorola PowerPC ProcessorID=%08x Rev. ",pir);
+ switch(pvr) {
+ default:
+ printf("PVR=%08x", pvr);
+ break;
+ }
+
+ printf("\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
+ */
+ __asm__ __volatile__("lis 3, 0x7000" ::: "r3");
+ mtspr(DBCR0,3);
+ 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 + 3L) / 4L);
+}
+
+
+#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)
+__inline__ void dcbz(const void* addr)
+{
+ __asm__ __volatile__ ("dcbz 0,%0" :: "r" (addr));
+}
+
+__inline__ void dcbf(const void* addr)
+{
+ __asm__ __volatile__ ("dcbf 0,%0" :: "r" (addr));
+}
+
+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 100644
index 0000000..3ffd558
--- /dev/null
+++ b/cpu/mpc85xx/cpu_init.c
@@ -0,0 +1,205 @@
+/*
+ * (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_MPC8560
+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_MPC8560
+ 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_MPC8560)
+ m8560_cpm_reset();
+#endif
+}
+
+/*
+ * We initialize L2 as cache here.
+ */
+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 temp;
+
+ asm("msync;isync");
+ l2cache->l2ctl = 0x68000000; /* invalidate */
+ temp = l2cache->l2ctl;
+ asm("msync;isync");
+ l2cache->l2ctl = 0xa8000000; /* enable 256KB L2 cache */
+ temp = l2cache->l2ctl;
+ asm("msync;isync");
+
+ printf("L2 cache enabled: 256KB\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 100644
index 0000000..f78e5b4
--- /dev/null
+++ b/cpu/mpc85xx/ether_fcc.c
@@ -0,0 +1,461 @@
+/*
+ * 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_MPC8560)
+
+#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
+
+#define 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 );
+
+ 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.
+ */
+ 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 0;
+}
+
+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 = ðer_fcc_info[i];
+ dev->init = fec_init;
+ dev->halt = fec_halt;
+ dev->send = fec_send;
+ dev->recv = fec_recv;
+
+ eth_register(dev);
+ }
+
+ return 1;
+}
+
+#endif /* CONFIG_ETHER_ON_FCC && CFG_CMD_NET && CONFIG_NET_MULTI */
+
+#endif /* CONFIG_MPC8560 */
diff --git a/cpu/mpc85xx/i2c.c b/cpu/mpc85xx/i2c.c
new file mode 100644
index 0000000..ae08d18
--- /dev/null
+++ b/cpu/mpc85xx/i2c.c
@@ -0,0 +1,288 @@
+/*
+ * (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>
+
+#define DEBUG
+
+#if defined(DEBUG)
+#define DEB(x) x
+#else
+#define DEB(x)
+#endif
+
+#ifdef CONFIG_HARD_I2C
+#include <i2c.h>
+
+#define TIMEOUT (CFG_HZ/4)
+
+#define I2C_Addr ((unsigned *)(CFG_CCSRBAR + 0x3000))
+
+#define I2CADR &I2C_Addr[0]
+#define I2CFDR &I2C_Addr[1]
+#define I2CCCR &I2C_Addr[2]
+#define I2CCSR &I2C_Addr[3]
+#define I2CCDR &I2C_Addr[4]
+#define I2CDFSRR &I2C_Addr[5]
+
+#define I2C_READ 1
+#define I2C_WRITE 0
+
+/* taken from linux include/asm-ppc/io.h */
+inline unsigned in_le32(volatile unsigned *addr)
+{
+ unsigned ret;
+
+ __asm__ __volatile__("lwbrx %0,0,%1;\n"
+ "twi 0,%0,0;\n"
+ "isync" : "=r" (ret) :
+ "r" (addr), "m" (*addr));
+ return ret;
+}
+
+inline void out_le32(volatile unsigned *addr, int val)
+{
+ __asm__ __volatile__("stwbrx %1,0,%2; eieio" : "=m" (*addr) :
+ "r" (val), "r" (addr));
+}
+
+#define writel(val, addr) out_le32(addr, val)
+#define readl(addr) in_le32(addr)
+
+void
+i2c_init(int speed, int slaveadd)
+{
+ /* stop I2C controller */
+ writel (0x0, I2CCCR);
+ /* set clock */
+ writel (0x3f, I2CFDR);
+ /* set default filter */
+ writel (0x10,I2CDFSRR);
+ /* write slave address */
+ writel (slaveadd, I2CADR);
+ /* clear status register */
+ writel (0x0, I2CCSR);
+ /* start I2C controller */
+ writel (MPC85xx_I2CCR_MEN, I2CCCR);
+}
+
+static __inline__ int
+i2c_wait4bus (void)
+{
+ ulong timeval = get_timer (0);
+
+ while (readl (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 = readl (I2CCSR);
+
+ if (!(csr & MPC85xx_I2CSR_MIF))
+ continue;
+
+ writel (0x0, I2CCSR);
+
+ if (csr & MPC85xx_I2CSR_MAL)
+ {
+ DEB(printf ("i2c_wait: MAL\n"));
+ return -1;
+ }
+
+ if (!(csr & MPC85xx_I2CSR_MCF))
+ {
+ DEB(printf ("i2c_wait: unfinished\n"));
+ return -1;
+ }
+
+ if (write == I2C_WRITE && (csr & MPC85xx_I2CSR_RXAK))
+ {
+ DEB(printf ("i2c_wait: No RXACK\n"));
+ return -1;
+ }
+
+ return 0;
+ } while (get_timer (timeval) < TIMEOUT);
+
+ DEB(printf ("i2c_wait: timed out\n"));
+ return -1;
+}
+
+static __inline__ int
+i2c_write_addr (u8 dev, u8 dir, int rsta)
+{
+ writel (MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA | MPC85xx_I2CCR_MTX |
+ (rsta?MPC85xx_I2CCR_RSTA:0), I2CCCR);
+
+ writel ((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;
+
+ writel (MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA | MPC85xx_I2CCR_MTX, I2CCCR);
+
+ for (i=0; i < length; i++)
+ {
+ writel (data[i], I2CCDR);
+
+ if (i2c_wait (I2C_WRITE) < 0)
+ break;
+ }
+
+ return i;
+}
+
+static __inline__ int
+__i2c_read (u8 *data, int length)
+{
+ int i;
+
+ writel (MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA |
+ ((length == 1) ? MPC85xx_I2CCR_TXAK : 0), I2CCCR);
+
+ /* dummy read */
+ readl (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)
+ writel (MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA |
+ MPC85xx_I2CCR_TXAK, I2CCCR);
+
+ /* Generate stop on last byte */
+ if (i == length - 1)
+ writel (MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_TXAK, I2CCCR);
+
+ data[i] = readl (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:
+ writel (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:
+ writel (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, (char *)&tmp, 1);
+}
+
+uchar i2c_reg_read (uchar i2c_addr, uchar reg)
+{
+ char buf[1];
+
+ i2c_read (i2c_addr, reg, 1, buf, 1);
+
+ return (buf[0]);
+}
+
+void i2c_reg_write (uchar i2c_addr, uchar reg, uchar val)
+{
+ i2c_write (i2c_addr, reg, 1, &val, 1);
+}
+
+#endif /* CONFIG_HARD_I2C */
diff --git a/cpu/mpc85xx/interrupts.c b/cpu/mpc85xx/interrupts.c
new file mode 100644
index 0000000..745b3b2
--- /dev/null
+++ b/cpu/mpc85xx/interrupts.c
@@ -0,0 +1,138 @@
+/*
+ * (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");
+}
+
+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);
+}
+
+/* interrupt is not supported yet */
+int interrupt_init (void)
+{
+ 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)
+{
+ printf ("*** Timer Interrupt *** ");
+ timestamp++;
+
+#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 100644
index 0000000..5732c29
--- /dev/null
+++ b/cpu/mpc85xx/pci.c
@@ -0,0 +1,107 @@
+/*
+ * 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)
+/*
+ * Initialize PCI Devices, report devices found.
+ */
+#ifndef CONFIG_PCI_PNP
+static struct pci_config_table pci_mpc85xxads_config_table[] = {
+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_IDSEL_NUMBER, PCI_ANY_ID,
+ pci_cfgfunc_config_device, { PCI_ENET0_IOADDR,
+ PCI_ENET0_MEMADDR,
+ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER }},
+ { }
+};
+#endif
+
+struct pci_controller local_hose = {
+#ifndef CONFIG_PCI_PNP
+ config_table: pci_mpc85xxads_config_table,
+#endif
+};
+
+void pci_init_board(void)
+{
+ struct pci_controller* hose = (struct pci_controller *)&local_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_PCI_MEM_BASE,
+ CFG_PCI_MEM_PHYS,
+ (CFG_PCI_MEM_SIZE/2),
+ PCI_REGION_MEM);
+
+ pci_set_region(hose->regions + 1,
+ (CFG_PCI_MEM_BASE+0x08000000),
+ (CFG_PCI_MEM_PHYS+0x08000000),
+ 0x1000000, /* 16M */
+ PCI_REGION_IO);
+
+ hose->region_count = 2;
+
+ pci_setup_indirect(hose,
+ (CFG_IMMR+0x8000),
+ (CFG_IMMR+0x8004));
+
+ pci_register_hose(hose);
+
+ hose->last_busno = pci_hose_scan(hose);
+
+ pci_read_config_word (PCI_BDF(0,0,0), PCI_COMMAND, ®16);
+ 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);
+
+ pcix->potar1 = (CFG_PCI_MEM_BASE >> 12) & 0x000fffff;
+ pcix->potear1 = 0x00000000;
+ pcix->powbar1 = (CFG_PCI_MEM_BASE >> 12) & 0x000fffff;
+ pcix->powbear1 = 0x00000000;
+ pcix->powar1 = 0x8004401a; /* 128M MEM space */
+ pcix->potar2 = ((CFG_PCI_MEM_BASE + 0x08000000) >> 12) & 0x000fffff;
+ pcix->potear2 = 0x00000000;
+ pcix->powbar2 = ((CFG_PCI_MEM_BASE + 0x08000000) >> 12) && 0x000fffff;
+ pcix->powbear2 = 0x00000000;
+ pcix->powar2 = 0x80088017; /* 16M IO space */
+ pcix->pitar1 = 0x00000000;
+ pcix->piwbar1 = 0x00000000;
+ pcix->piwar1 = 0xa0F5501f;
+
+}
+#endif /* CONFIG_PCI */
diff --git a/cpu/mpc85xx/resetvec.S b/cpu/mpc85xx/resetvec.S
new file mode 100644
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 100644
index 0000000..ea82761
--- /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_MPC8560)
+#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_MPC8560 */
diff --git a/cpu/mpc85xx/spd_sdram.c b/cpu/mpc85xx/spd_sdram.c
new file mode 100644
index 0000000..ccd06e9
--- /dev/null
+++ b/cpu/mpc85xx/spd_sdram.c
@@ -0,0 +1,308 @@
+/*
+ * (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>
+
+#ifdef CONFIG_SPD_EEPROM
+
+#undef DEBUG
+
+#if defined(DEBUG)
+#define DEB(x) x
+#else
+#define DEB(x)
+#endif
+
+#define ns2clk(ns) ((ns) / (2000000000 /get_bus_freq(0) + 1))
+
+long int spd_sdram(void) {
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+ volatile ccsr_ddr_t *ddr = &immap->im_ddr;
+ volatile ccsr_local_ecm_t *ecm = &immap->im_local_ecm;
+ spd_eeprom_t spd;
+ unsigned int memsize,tmp,tmp1,tmp2;
+ unsigned char caslat;
+
+ i2c_read (SPD_EEPROM_ADDRESS, 0, 1, (uchar *) & spd, sizeof (spd));
+
+ if ( spd.nrows > 2 ) {
+ printf("DDR:Only two chip selects are supported on ADS.\n");
+ return 0;
+ }
+
+ if ( spd.nrow_addr < 12 || spd.nrow_addr > 14 || spd.ncol_addr < 8 || spd.ncol_addr > 11) {
+ printf("DDR:Row or Col number unsupported.\n");
+ return 0;
+ }
+
+ ddr->cs0_bnds = ((spd.row_dens>>2) - 1);
+ ddr->cs0_config = ( 1<<31 | (spd.nrow_addr-12)<<8 | (spd.ncol_addr-8) );
+ DEB(printf("\n"));
+ DEB(printf("cs0_bnds = 0x%08x\n",ddr->cs0_bnds));
+ DEB(printf("cs0_config = 0x%08x\n",ddr->cs0_config));
+ if ( spd.nrows == 2 ) {
+ ddr->cs1_bnds = ((spd.row_dens<<14) | ((spd.row_dens>>1) - 1));
+ ddr->cs1_config = ( 1<<31 | (spd.nrow_addr-12)<<8 | (spd.ncol_addr-8) );
+ DEB(printf("cs1_bnds = 0x%08x\n",ddr->cs1_bnds));
+ DEB(printf("cs1_config = 0x%08x\n",ddr->cs1_config));
+ }
+
+ memsize = spd.nrows * (4 * spd.row_dens);
+ if( spd.mem_type == 0x07 ) {
+ printf("DDR module detected, total size:%dMB.\n",memsize);
+ } else {
+ printf("No DDR module found!\n");
+ return 0;
+ }
+
+ switch(memsize) {
+ case 16:
+ tmp = 7; /* TLB size */
+ tmp1 = 1; /* TLB entry number */
+ tmp2 = 23; /* Local Access Window size */
+ break;
+ case 32:
+ tmp = 7;
+ tmp1 = 2;
+ tmp2 = 24;
+ break;
+ case 64:
+ tmp = 8;
+ tmp1 = 1;
+ tmp2 = 25;
+ break;
+ case 128:
+ tmp = 8;
+ tmp1 = 2;
+ tmp2 = 26;
+ break;
+ case 256:
+ tmp = 9;
+ tmp1 = 1;
+ tmp2 = 27;
+ break;
+ case 512:
+ tmp = 9;
+ tmp1 = 2;
+ tmp2 = 28;
+ break;
+ case 1024:
+ tmp = 10;
+ tmp1 = 1;
+ tmp2 = 29;
+ break;
+ default:
+ printf("DDR:we only added support 16M,32M,64M,128M,256M,512M and 1G DDR I.\n");
+ return 0;
+ break;
+ }
+
+ /* configure DDR TLB to TLB1 Entry 4,5 */
+ mtspr(MAS0, TLB1_MAS0(1,4,0));
+ mtspr(MAS1, TLB1_MAS1(1,1,0,0,tmp));
+ mtspr(MAS2, TLB1_MAS2(((CFG_DDR_SDRAM_BASE>>12) & 0xfffff),0,0,0,0,0,0,0,0));
+ mtspr(MAS3, TLB1_MAS3(((CFG_DDR_SDRAM_BASE>>12) & 0xfffff),0,0,0,0,0,1,0,1,0,1));
+ asm volatile("isync;msync;tlbwe;isync");
+ DEB(printf("DDR:MAS0=0x%08x\n",TLB1_MAS0(1,4,0)));
+ DEB(printf("DDR:MAS1=0x%08x\n",TLB1_MAS1(1,1,0,0,tmp)));
+ DEB(printf("DDR:MAS2=0x%08x\n",TLB1_MAS2(((CFG_DDR_SDRAM_BASE>>12) \
+ & 0xfffff),0,0,0,0,0,0,0,0)));
+ DEB(printf("DDR:MAS3=0x%08x\n",TLB1_MAS3(((CFG_DDR_SDRAM_BASE>>12) \
+ & 0xfffff),0,0,0,0,0,1,0,1,0,1)));
+
+ if(tmp1 == 2) {
+ mtspr(MAS0, TLB1_MAS0(1,5,0));
+ mtspr(MAS1, TLB1_MAS1(1,1,0,0,tmp));
+ mtspr(MAS2, TLB1_MAS2((((CFG_DDR_SDRAM_BASE+(memsize*1024*1024)/2)>>12) \
+ & 0xfffff),0,0,0,0,0,0,0,0));
+ mtspr(MAS3, TLB1_MAS3((((CFG_DDR_SDRAM_BASE+(memsize*1024*1024)/2)>>12) \
+ & 0xfffff),0,0,0,0,0,1,0,1,0,1));
+ asm volatile("isync;msync;tlbwe;isync");
+ DEB(printf("DDR:MAS0=0x%08x\n",TLB1_MAS0(1,5,0)));
+ DEB(printf("DDR:MAS1=0x%08x\n",TLB1_MAS1(1,1,0,0,tmp)));
+ DEB(printf("DDR:MAS2=0x%08x\n",TLB1_MAS2((((CFG_DDR_SDRAM_BASE \
+ +(memsize*1024*1024)/2)>>12) & 0xfffff),0,0,0,0,0,0,0,0)));
+ DEB(printf("DDR:MAS3=0x%08x\n",TLB1_MAS3((((CFG_DDR_SDRAM_BASE \
+ +(memsize*1024*1024)/2)>>12) & 0xfffff),0,0,0,0,0,1,0,1,0,1)));
+ }
+
+#if defined(CONFIG_RAM_AS_FLASH)
+ ecm->lawbar2 = ((CFG_DDR_SDRAM_BASE>>12) & 0xfffff);
+ ecm->lawar2 = (LAWAR_EN | LAWAR_TRGT_IF_DDR | (LAWAR_SIZE & tmp2));
+ DEB(printf("DDR:LAWBAR2=0x%08x\n",ecm->lawbar2));
+ DEB(printf("DDR:LARAR2=0x%08x\n",ecm->lawar2));
+#else
+ ecm->lawbar1 = ((CFG_DDR_SDRAM_BASE>>12) & 0xfffff);
+ ecm->lawar1 = (LAWAR_EN | LAWAR_TRGT_IF_DDR | (LAWAR_SIZE & tmp2));
+ DEB(printf("DDR:LAWBAR1=0x%08x\n",ecm->lawbar1));
+ DEB(printf("DDR:LARAR1=0x%08x\n",ecm->lawar1));
+#endif
+
+ tmp = 20000/(((spd.clk_cycle & 0xF0) >> 4) * 10 + (spd.clk_cycle & 0x0f));
+ DEB(printf("DDR:Module maximum data rate is: %dMhz\n",tmp));
+
+ /* find the largest CAS */
+ if(spd.cas_lat & 0x40) {
+ caslat = 7;
+ } else if (spd.cas_lat & 0x20) {
+ caslat = 6;
+ } else if (spd.cas_lat & 0x10) {
+ caslat = 5;
+ } else if (spd.cas_lat & 0x08) {
+ caslat = 4;
+ } else if (spd.cas_lat & 0x04) {
+ caslat = 3;
+ } else if (spd.cas_lat & 0x02) {
+ caslat = 2;
+ } else if (spd.cas_lat & 0x01) {
+ caslat = 1;
+ } else {
+ printf("DDR:no valid CAS Latency information.\n");
+ return 0;
+ }
+
+ tmp1 = get_bus_freq(0)/1000000;
+ if(tmp1<230 && tmp1>=90 && tmp>=230) { /* 90~230 range, treated as DDR 200 */
+ if(spd.clk_cycle3 == 0xa0) caslat -= 2;
+ else if(spd.clk_cycle2 == 0xa0) caslat--;
+ } else if(tmp1<280 && tmp1>=230 && tmp>=280) { /* 230-280 range, treated as DDR 266 */
+ if(spd.clk_cycle3 == 0x75) caslat -= 2;
+ else if(spd.clk_cycle2 == 0x75) caslat--;
+ } else if(tmp1<350 && tmp1>=280 && tmp>=350) { /* 280~350 range, treated as DDR 333 */
+ if(spd.clk_cycle3 == 0x60) caslat -= 2;
+ else if(spd.clk_cycle2 == 0x60) caslat--;
+ } else if(tmp1<90 || tmp1 >=350) { /* DDR rate out-of-range */
+ printf("DDR:platform frequency is not fit for DDR rate\n");
+ return 0;
+ }
+
+ /* note: caslat must also be programmed into ddr->sdram_mode register */
+ /* note: WRREC(Twr) and WRTORD(Twtr) are not in SPD,use conservative value here */
+#if 1
+ ddr->timing_cfg_1 = (((ns2clk(spd.trp/4) & 0x07) << 28 ) | \
+ ((ns2clk(spd.tras) & 0x0f ) << 24 ) | \
+ ((ns2clk(spd.trcd/4) & 0x07) << 20 ) | \
+ ((caslat & 0x07)<< 16 ) | \
+ (((ns2clk(spd.sset[6]) - 8) & 0x0f) << 12 ) | \
+ ( 0x300 ) | \
+ ((ns2clk(spd.trrd/4) & 0x07) << 4) | 1);
+#else
+ ddr->timing_cfg_1 = 0x37344321;
+ caslat = 4;
+#endif
+ DEB(printf("DDR:timing_cfg_1=0x%08x\n",ddr->timing_cfg_1));
+
+ /* note: hand-coded value for timing_cfg_2, see Errata DDR1*/
+#if defined(CONFIG_MPC85xx_REV1)
+ ddr->timing_cfg_2 = 0x00000800;
+#endif
+ DEB(printf("DDR:timing_cfg_2=0x%08x\n",ddr->timing_cfg_2));
+
+ /* only DDR I is supported, DDR I and II have different mode-register-set definition */
+ /* burst length is always 4 */
+ switch(caslat) {
+ case 2:
+ ddr->sdram_mode = 0x52; /* 1.5 */
+ break;
+ case 3:
+ ddr->sdram_mode = 0x22; /* 2.0 */
+ break;
+ case 4:
+ ddr->sdram_mode = 0x62; /* 2.5 */
+ break;
+ case 5:
+ ddr->sdram_mode = 0x32; /* 3.0 */
+ break;
+ default:
+ printf("DDR:only CAS Latency 1.5,2.0,2.5,3.0 is supported.\n");
+ return 0;
+ }
+ DEB(printf("DDR:sdram_mode=0x%08x\n",ddr->sdram_mode));
+
+ switch(spd.refresh) {
+ case 0x00:
+ case 0x80:
+ tmp = ns2clk(15625);
+ break;
+ case 0x01:
+ case 0x81:
+ tmp = ns2clk(3900);
+ break;
+ case 0x02:
+ case 0x82:
+ tmp = ns2clk(7800);
+ break;
+ case 0x03:
+ case 0x83:
+ tmp = ns2clk(31300);
+ break;
+ case 0x04:
+ case 0x84:
+ tmp = ns2clk(62500);
+ break;
+ case 0x05:
+ case 0x85:
+ tmp = ns2clk(125000);
+ break;
+ default:
+ tmp = 0x512;
+ break;
+ }
+
+ /* set BSTOPRE to 0x100 for page mode, if auto-charge is used, set BSTOPRE = 0 */
+ ddr->sdram_interval = ((tmp & 0x3fff) << 16) | 0x100;
+ DEB(printf("DDR:sdram_interval=0x%08x\n",ddr->sdram_interval));
+
+ /* is this an ECC DDR chip? */
+#if defined(CONFIG_DDR_ECC)
+ if(spd.config == 0x02) {
+ ddr->err_disable = 0x0000000d;
+ ddr->err_sbe = 0x00ff0000;
+ }
+ DEB(printf("DDR:err_disable=0x%08x\n",ddr->err_disable));
+ DEB(printf("DDR:err_sbe=0x%08x\n",ddr->err_sbe));
+#endif
+ asm("sync;isync;msync");
+
+ udelay(500);
+
+ /* registered or unbuffered? */
+#if defined(CONFIG_DDR_ECC)
+ ddr->sdram_cfg = (spd.config == 0x02)?0x20000000:0x0;
+#endif
+ ddr->sdram_cfg = 0xc2000000|((spd.mod_attr == 0x20) ? 0x0 : \
+ ((spd.mod_attr == 0x26) ? 0x10000000:0x0));
+ asm("sync;isync;msync");
+
+ udelay(500);
+
+ DEB(printf("DDR:sdram_cfg=0x%08x\n",ddr->sdram_cfg));
+
+ return (memsize*1024*1024);
+}
+
+#endif /* CONFIG_SPD_EEPROM */
diff --git a/cpu/mpc85xx/speed.c b/cpu/mpc85xx/speed.c
new file mode 100644
index 0000000..a720cff
--- /dev/null
+++ b/cpu/mpc85xx/speed.c
@@ -0,0 +1,124 @@
+/*
+ * (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>
+
+/* --------------------------------------------------------------- */
+
+#define ONE_BILLION 1000000000
+
+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_MPC8560)
+ 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_MPC8560)
+ 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 100644
index 0000000..468923c
--- /dev/null
+++ b/cpu/mpc85xx/start.S
@@ -0,0 +1,1156 @@
+/*
+ * 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:
+#if defined(CONFIG_MPC85xx_REV1)
+ li r0,0x2000
+ mtspr 977,r0
+#endif
+
+ /* 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
+ isync
+
+ /* 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 */
+ sync
+ 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
+
+ mtspr DBCR0,r0
+ isync
+ mtspr DBCR1,r0
+ isync
+ mtspr DBCR2,r0
+ isync
+ mtspr IAC1,r0
+ mtspr IAC2,r0
+ mtspr DAC1,r0
+ mtspr DAC2,r0
+
+ mfspr r1,DBSR
+ mtspr DBSR,r1 /* Clear all valid bits */
+
+ isync
+ mtspr PID0,r0
+ isync
+ mtspr PID1,r0
+ isync
+ mtspr PID2,r0
+ isync
+
+ mtspr TCR,r0
+
+ mtspr BUCSR,r0 /* disable branch prediction */
+ isync
+
+ mtspr HID0,r0
+ isync
+ mtspr HID1,r0
+ isync
+
+ mtspr MAS4,r0
+ isync
+ mtspr MAS6,r0
+ isync
+
+ /* Setup interrupt vectors */
+ mtspr IVPR, r0
+
+ 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,0x0c00
+ mtspr IVOR8,r1 /* 8: System call */
+ /* 9: Auxiliary processor unavailable(unsupported) */
+ li r1,0x1000
+ mtspr IVOR10,r1 /* 10: Decrementer */
+ li r1,0x1400
+ mtspr IVOR13,r1 /* 13: Data TLB error */
+ li r1,0x1300
+ mtspr IVOR14,r1 /* 14: Instruction TLB error */
+ li r1,0x2000
+ mtspr IVOR15,r1 /* 15: Debug */
+
+ /* invalidate MMU L1/L2 */
+ /* Note: before invalidate MMU L1/L2, we read TLB1 Entry 0 and then
+ * write it back immediately to fixup a bug(Errata CPU4) for this initial
+ * TLB1 entry 0,otherwise the TLB1 entry 0 will be invalidated.
+ */
+#if defined(CONFIG_MPC85xx_REV1)
+ lis r2,0x1000
+ mtspr MAS0,r2
+ tlbre
+ tlbwe
+ isync
+ li r2, 0x001e
+ mtspr MMUCSR0, r2
+ isync
+#endif
+
+ /* 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,0x000f /* max 16 TLB1 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
+
+ /* invalidate all TLB0 entries */
+ li r3,4
+ li r4,0
+ tlbivax r4,r3
+#if defined(CONFIG_MPC85xx_REV1) /* Errata CPU6 */
+ nop
+#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
+#if defined(CONFIG_RAM_AS_FLASH)
+ li r1,0x0006
+#else
+ li r1,0x0007 /*we have 8 LAWs, but reseve one for boot-over-rio-or-pci */
+#endif
+ mtctr r1
+ lwzu r5,0(r6) /* how many windows we actually use */
+
+#if defined(CONFIG_RAM_AS_FLASH)
+ li r2,0x0c48
+ li r1,0x0c50
+#else
+ li r2,0x0c28 /* the first pair is reserved for boot-over-rio-or-pci */
+ li r1,0x0c30
+#endif
+
+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 */
+ li r0,0x4000 /* time base is processor clock */
+ mtspr HID0,r0
+ isync
+
+#if defined(CONFIG_ADDR_STREAMING)
+ li r0,0x2000
+ mtspr HID1,r0
+ isync
+#endif
+
+ /* Enable Branch Prediction */
+#if defined(CONFIG_BTB)
+ li r0,0x201 /* BBFI = 1, BPEN = 1 */
+ mtspr BUCSR,r0
+ isync
+#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
+ isync
+#endif
+
+/* L1 DCache is used for initial RAM */
+ mfspr r2, L1CSR0
+ ori r2, r2, 0x0003
+ oris r2, r2, 0x0001
+ msync
+ isync
+ 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
+ sync
+
+
+/* --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)
+ STD_EXCEPTION(0x0900, Decrementer, timer_interrupt)
+ STD_EXCEPTION(0x0a00, Trap_0a, UnknownException)
+ STD_EXCEPTION(0x0b00, Trap_0b, UnknownException)
+
+ . = 0x0c00
+/*
+ * 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(0xd00, SingleStep, UnknownException)
+
+ STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+ STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+
+ STD_EXCEPTION(0x1000, PIT, PITException)
+
+ STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
+ STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
+
+ STD_EXCEPTION(0x1500, Reserved5, UnknownException)
+ STD_EXCEPTION(0x1600, Reserved6, UnknownException)
+ STD_EXCEPTION(0x1700, Reserved7, UnknownException)
+ STD_EXCEPTION(0x1800, Reserved8, UnknownException)
+ STD_EXCEPTION(0x1900, Reserved9, UnknownException)
+ STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
+ STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
+
+ STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
+ STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
+ STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
+ STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
+
+ CRIT_EXCEPTION(0x2000, 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 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: 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
+
+/*
+ * 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
+ li r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 2b
+
+ li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+ li r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 3b
+
+ li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
+ li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 4b
+
+ 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 100644
index 0000000..fd0b436
--- /dev/null
+++ b/cpu/mpc85xx/traps.c
@@ -0,0 +1,272 @@
+/*
+ * 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);
+
+/* THIS NEEDS CHANGING to use the board info structure.
+ */
+#define END_OF_MEM (CFG_SDRAM_SIZE * 1024 * 1024)
+
+
+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)
+{
+ 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 & 0x0000F000)
+ {
+ case (1<<12) :
+ printf("Machine check signal - probably due to mm fault\n"
+ "with mmu off\n");
+ break;
+ case (1<<13) :
+ printf("Transfer error ack signal\n");
+ break;
+ case (1<<14) :
+ printf("Data parity signal\n");
+ break;
+ case (1<<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;
+}
diff --git a/cpu/mpc85xx/tsec.c b/cpu/mpc85xx/tsec.c
new file mode 100644
index 0000000..4a5731e
--- /dev/null
+++ b/cpu/mpc85xx/tsec.c
@@ -0,0 +1,441 @@
+/*
+ * tsec.c
+ * Motorola Three Speed Ethernet Controller driver
+ *
+ * This software may be used and distributed according to the
+ * terms of the GNU Public License, Version 2, incorporated
+ * herein by reference.
+ *
+ * (C) Copyright 2003, Motorola, Inc.
+ * maintained by Xianghua Xiao (x.xiao@motorola.com)
+ * author Andy Fleming
+ *
+ */
+
+#include <config.h>
+#include <mpc85xx.h>
+#include <common.h>
+#include <malloc.h>
+#include <net.h>
+#include <command.h>
+
+#if defined(CONFIG_TSEC_ENET)
+#include "tsec.h"
+
+#define TX_BUF_CNT 2
+
+#undef TSEC_DEBUG
+#ifdef TSEC_DEBUG
+#define DBGPRINT(x) printf(x)
+#else
+#define DBGPRINT(x)
+#endif
+
+static uint rxIdx; /* index of the current RX buffer */
+static uint txIdx; /* index of the current TX buffer */
+
+typedef volatile struct rtxbd {
+ txbd8_t txbd[TX_BUF_CNT];
+ rxbd8_t rxbd[PKTBUFSRX];
+} RTXBD;
+
+#ifdef __GNUC__
+static RTXBD rtx __attribute__ ((aligned(8)));
+#else
+#error "rtx must be 64-bit aligned"
+#endif
+
+static int tsec_send(struct eth_device* dev, volatile void *packet, int length);
+static int tsec_recv(struct eth_device* dev);
+static int tsec_init(struct eth_device* dev, bd_t * bd);
+static void tsec_halt(struct eth_device* dev);
+static void init_registers(tsec_t *regs);
+static void startup_tsec(tsec_t *regs);
+static void init_phy(tsec_t *regs);
+
+/* Initialize device structure. returns 0 on failure, 1 on
+ * success */
+int tsec_initialize(bd_t *bis)
+{
+ struct eth_device* dev;
+ int i;
+
+ dev = (struct eth_device*) malloc(sizeof *dev);
+
+ if(dev == NULL)
+ return 0;
+
+ memset(dev, 0, sizeof *dev);
+
+ sprintf(dev->name, "MOTOROLA ETHERNET");
+ dev->iobase = 0;
+ dev->priv = 0;
+ dev->init = tsec_init;
+ dev->halt = tsec_halt;
+ dev->send = tsec_send;
+ dev->recv = tsec_recv;
+
+ /* Tell u-boot to get the addr from the env */
+ for(i=0;i<6;i++)
+ dev->enetaddr[i] = 0;
+
+ eth_register(dev);
+
+ return 1;
+}
+
+
+/* Initializes data structures and registers for the controller,
+ * and brings the interface up */
+int tsec_init(struct eth_device* dev, bd_t * bd)
+{
+ tsec_t *regs;
+ uint tempval;
+ char tmpbuf[MAC_ADDR_LEN];
+ int i;
+
+ regs = (tsec_t *)(TSEC_BASE_ADDR);
+
+ /* Make sure the controller is stopped */
+ tsec_halt(dev);
+
+ /* Reset the MAC */
+ regs->maccfg1 |= MACCFG1_SOFT_RESET;
+
+ /* Clear MACCFG1[Soft_Reset] */
+ regs->maccfg1 &= ~(MACCFG1_SOFT_RESET);
+
+ /* Init MACCFG2. Defaults to GMII/MII */
+ regs->maccfg2 = MACCFG2_INIT_SETTINGS;
+
+ /* Init ECNTRL */
+ regs->ecntrl = ECNTRL_INIT_SETTINGS;
+
+ /* Copy the station address into the address registers.
+ * Backwards, because little endian MACS are dumb */
+ for(i=0;i<MAC_ADDR_LEN;i++) {
+ tmpbuf[MAC_ADDR_LEN - 1 - i] = bd->bi_enetaddr[i];
+ }
+ (uint)(regs->macstnaddr1) = *((uint *)(tmpbuf));
+
+ tempval = *((uint *)(tmpbuf +4));
+
+ (uint)(regs->macstnaddr2) = tempval;
+
+ /* Initialize the PHY */
+ init_phy(regs);
+
+ /* reset the indices to zero */
+ rxIdx = 0;
+ txIdx = 0;
+
+ /* Clear out (for the most part) the other registers */
+ init_registers(regs);
+
+ /* Ready the device for tx/rx */
+ startup_tsec(regs);
+
+ return 1;
+
+}
+
+
+/* Reads from the register at offset in the PHY at phyid, */
+/* using the register set defined in regbase. It waits until the */
+/* bits in the miimstat are valid (miimind notvalid bit cleared), */
+/* and then passes those bits on to the variable specified in */
+/* value */
+/* Before it does the read, it needs to clear the command field */
+uint read_phy_reg(tsec_t *regbase, uint phyid, uint offset)
+{
+ uint value;
+
+ /* Put the address of the phy, and the register number into
+ * MIIMADD
+ */
+ regbase->miimadd = (phyid << 8) | offset;
+
+ /* Clear the command register, and wait */
+ regbase->miimcom = 0;
+ asm("msync");
+
+ /* Initiate a read command, and wait */
+ regbase->miimcom = MIIM_READ_COMMAND;
+ asm("msync");
+
+ /* Wait for the the indication that the read is done */
+ while((regbase->miimind & (MIIMIND_NOTVALID | MIIMIND_BUSY)));
+
+ /* Grab the value read from the PHY */
+ value = regbase->miimstat;
+
+ return value;
+}
+
+/* Setup the PHY */
+static void init_phy(tsec_t *regs)
+{
+ uint testval;
+ unsigned int timeout = TSEC_TIMEOUT;
+
+ /* Assign a Physical address to the TBI */
+ regs->tbipa=TBIPA_VALUE;
+
+ /* reset the management interface */
+ regs->miimcfg=MIIMCFG_RESET;
+
+ regs->miimcfg=MIIMCFG_INIT_VALUE;
+
+ /* Wait until the bus is free */
+ while(regs->miimind & MIIMIND_BUSY);
+
+#ifdef CONFIG_PHY_CIS8201
+ /* override PHY config settings */
+ write_phy_reg(regs, 0, MIIM_AUX_CONSTAT, MIIM_AUXCONSTAT_INIT);
+
+ /* Set up interface mode */
+ write_phy_reg(regs, 0, MIIM_EXT_CON1, MIIM_EXTCON1_INIT);
+#endif
+
+ /* Set the PHY to gigabit, full duplex, Auto-negotiate */
+ write_phy_reg(regs, 0, MIIM_CONTROL, MIIM_CONTROL_INIT);
+
+ /* Wait until TBI_STATUS indicates AN is done */
+ DBGPRINT("Waiting for Auto-negotiation to complete\n");
+ testval=read_phy_reg(regs, 0, MIIM_TBI_STATUS);
+
+ while((!(testval & MIIM_TBI_STATUS_AN_DONE))&& timeout--) {
+ testval=read_phy_reg(regs, 0, MIIM_TBI_STATUS);
+ }
+
+ if(testval & MIIM_TBI_STATUS_AN_DONE)
+ DBGPRINT("Auto-negotiation done\n");
+ else
+ DBGPRINT("Auto-negotiation timed-out.\n");
+
+#ifdef CONFIG_PHY_CIS8201
+ /* Find out what duplexity (duplicity?) we have */
+ /* Read it twice to make sure */
+ testval=read_phy_reg(regs, 0, MIIM_AUX_CONSTAT);
+
+ if(testval & MIIM_AUXCONSTAT_DUPLEX) {
+ DBGPRINT("Enet starting in full duplex\n");
+ regs->maccfg2 |= MACCFG2_FULL_DUPLEX;
+ } else {
+ DBGPRINT("Enet starting in half duplex\n");
+ regs->maccfg2 &= ~MACCFG2_FULL_DUPLEX;
+ }
+
+ /* Also, we look to see what speed we are at
+ * if Gigabit, MACCFG2 goes in GMII, otherwise,
+ * MII mode.
+ */
+ if((testval & MIIM_AUXCONSTAT_SPEED) != MIIM_AUXCONSTAT_GBIT) {
+ if((testval & MIIM_AUXCONSTAT_SPEED) == MIIM_AUXCONSTAT_100)
+ DBGPRINT("Enet starting in 100BT\n");
+ else
+ DBGPRINT("Enet starting in 10BT\n");
+
+ /* mark the mode in MACCFG2 */
+ regs->maccfg2 = ((regs->maccfg2&~(MACCFG2_IF)) | MACCFG2_MII);
+ } else {
+ DBGPRINT("Enet starting in 1000BT\n");
+ }
+
+#endif
+
+#ifdef CONFIG_PHY_M88E1011
+ /* Read the PHY to see what speed and duplex we are */
+ testval=read_phy_reg(regs, 0, MIIM_PHY_STATUS);
+
+ timeout = TSEC_TIMEOUT;
+ while((!(testval & MIIM_PHYSTAT_SPDDONE)) && timeout--) {
+ testval = read_phy_reg(regs,0,MIIM_PHY_STATUS);
+ }
+
+ if(!(testval & MIIM_PHYSTAT_SPDDONE))
+ DBGPRINT("Enet: Speed not resolved\n");
+
+ testval=read_phy_reg(regs, 0, MIIM_PHY_STATUS);
+ if(testval & MIIM_PHYSTAT_DUPLEX) {
+ DBGPRINT("Enet starting in Full Duplex\n");
+ regs->maccfg2 |= MACCFG2_FULL_DUPLEX;
+ } else {
+ DBGPRINT("Enet starting in Half Duplex\n");
+ regs->maccfg2 &= ~MACCFG2_FULL_DUPLEX;
+ }
+
+ if(!((testval&MIIM_PHYSTAT_SPEED) == MIIM_PHYSTAT_GBIT)) {
+ if((testval & MIIM_PHYSTAT_SPEED) == MIIM_PHYSTAT_100)
+ DBGPRINT("Enet starting in 100BT\n");
+ else
+ DBGPRINT("Enet starting in 10BT\n");
+
+ regs->maccfg2 = ((regs->maccfg2&~(MACCFG2_IF)) | MACCFG2_MII);
+ } else {
+ DBGPRINT("Enet starting in 1000BT\n");
+ }
+#endif
+
+}
+
+
+static void init_registers(tsec_t *regs)
+{
+ /* Clear IEVENT */
+ regs->ievent = IEVENT_INIT_CLEAR;
+
+ regs->imask = IMASK_INIT_CLEAR;
+
+ regs->hash.iaddr0 = 0;
+ regs->hash.iaddr1 = 0;
+ regs->hash.iaddr2 = 0;
+ regs->hash.iaddr3 = 0;
+ regs->hash.iaddr4 = 0;
+ regs->hash.iaddr5 = 0;
+ regs->hash.iaddr6 = 0;
+ regs->hash.iaddr7 = 0;
+
+ regs->hash.gaddr0 = 0;
+ regs->hash.gaddr1 = 0;
+ regs->hash.gaddr2 = 0;
+ regs->hash.gaddr3 = 0;
+ regs->hash.gaddr4 = 0;
+ regs->hash.gaddr5 = 0;
+ regs->hash.gaddr6 = 0;
+ regs->hash.gaddr7 = 0;
+
+ regs->rctrl = 0x00000000;
+
+ /* Init RMON mib registers */
+ memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t));
+
+ regs->rmon.cam1 = 0xffffffff;
+ regs->rmon.cam2 = 0xffffffff;
+
+ regs->mrblr = MRBLR_INIT_SETTINGS;
+
+ regs->minflr = MINFLR_INIT_SETTINGS;
+
+ regs->attr = ATTR_INIT_SETTINGS;
+ regs->attreli = ATTRELI_INIT_SETTINGS;
+
+}
+
+static void startup_tsec(tsec_t *regs)
+{
+ int i;
+
+ /* Point to the buffer descriptors */
+ regs->tbase = (unsigned int)(&rtx.txbd[txIdx]);
+ regs->rbase = (unsigned int)(&rtx.rxbd[rxIdx]);
+
+ /* Initialize the Rx Buffer descriptors */
+ for (i = 0; i < PKTBUFSRX; i++) {
+ rtx.rxbd[i].status = RXBD_EMPTY;
+ rtx.rxbd[i].length = 0;
+ rtx.rxbd[i].bufPtr = (uint)NetRxPackets[i];
+ }
+ rtx.rxbd[PKTBUFSRX -1].status |= RXBD_WRAP;
+
+ /* Initialize the TX Buffer Descriptors */
+ for(i=0; i<TX_BUF_CNT; i++) {
+ rtx.txbd[i].status = 0;
+ rtx.txbd[i].length = 0;
+ rtx.txbd[i].bufPtr = 0;
+ }
+ rtx.txbd[TX_BUF_CNT -1].status |= TXBD_WRAP;
+
+ /* Enable Transmit and Receive */
+ regs->maccfg1 |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
+
+ /* Tell the DMA it is clear to go */
+ regs->dmactrl |= DMACTRL_INIT_SETTINGS;
+ regs->tstat = TSTAT_CLEAR_THALT;
+ regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
+}
+
+/* This returns the status bits of the device. The return value
+ * is never checked, and this is what the 8260 driver did, so we
+ * do the same. Presumably, this would be zero if there were no
+ * errors */
+static int tsec_send(struct eth_device* dev, volatile void *packet, int length)
+{
+ int i;
+ int result = 0;
+ tsec_t * regs = (tsec_t *)(TSEC_BASE_ADDR);
+
+ /* Find an empty buffer descriptor */
+ for(i=0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
+ if (i >= TOUT_LOOP) {
+ DBGPRINT("tsec: tx buffers full\n");
+ return result;
+ }
+ }
+
+ rtx.txbd[txIdx].bufPtr = (uint)packet;
+ rtx.txbd[txIdx].length = length;
+ rtx.txbd[txIdx].status |= (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT);
+
+ /* Tell the DMA to go */
+ regs->tstat = TSTAT_CLEAR_THALT;
+
+ /* Wait for buffer to be transmitted */
+ for(i=0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
+ if (i >= TOUT_LOOP) {
+ DBGPRINT("tsec: tx error\n");
+ return result;
+ }
+ }
+
+ txIdx = (txIdx + 1) % TX_BUF_CNT;
+ result = rtx.txbd[txIdx].status & TXBD_STATS;
+
+ return result;
+}
+
+static int tsec_recv(struct eth_device* dev)
+{
+ int length;
+ tsec_t *regs = (tsec_t *)(TSEC_BASE_ADDR);
+
+ while(!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) {
+
+ length = rtx.rxbd[rxIdx].length;
+
+ /* Send the packet up if there were no errors */
+ if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) {
+ NetReceive(NetRxPackets[rxIdx], length - 4);
+ }
+
+ rtx.rxbd[rxIdx].length = 0;
+
+ /* Set the wrap bit if this is the last element in the list */
+ rtx.rxbd[rxIdx].status = RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0);
+
+ rxIdx = (rxIdx + 1) % PKTBUFSRX;
+ }
+
+ if(regs->ievent&IEVENT_BSY) {
+ regs->ievent = IEVENT_BSY;
+ regs->rstat = RSTAT_CLEAR_RHALT;
+ }
+
+ return -1;
+
+}
+
+
+static void tsec_halt(struct eth_device* dev)
+{
+ tsec_t *regs = (tsec_t *)(TSEC_BASE_ADDR);
+
+ regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
+ regs->dmactrl |= (DMACTRL_GRS | DMACTRL_GTS);
+
+ while(!(regs->ievent & (IEVENT_GRSC | IEVENT_GTSC)));
+
+ regs->maccfg1 &= ~(MACCFG1_TX_EN | MACCFG1_RX_EN);
+
+}
+#endif /* CONFIG_TSEC_ENET */
diff --git a/cpu/mpc85xx/tsec.h b/cpu/mpc85xx/tsec.h
new file mode 100644
index 0000000..cfcfd39
--- /dev/null
+++ b/cpu/mpc85xx/tsec.h
@@ -0,0 +1,393 @@
+/*
+ * tsec.h
+ *
+ * Driver for the Motorola Triple Speed Ethernet Controller
+ *
+ * This software may be used and distributed according to the
+ * terms of the GNU Public License, Version 2, incorporated
+ * herein by reference.
+ *
+ * (C) Copyright 2003, Motorola, Inc.
+ * maintained by Xianghua Xiao (x.xiao@motorola.com)
+ * author Andy Fleming
+ *
+ */
+
+#ifndef __TSEC_H
+#define __TSEC_H
+
+#include <net.h>
+#include <mpc85xx.h>
+
+#define TSEC_BASE_ADDR (CFG_IMMR + 0x24000)
+#define TSEC_MEM_SIZE 0x01000
+
+#define MAC_ADDR_LEN 6
+
+#define TSEC_TIMEOUT 1000000
+#define TOUT_LOOP 1000000
+
+/* MAC register bits */
+#define MACCFG1_SOFT_RESET 0x80000000
+#define MACCFG1_RESET_RX_MC 0x00080000
+#define MACCFG1_RESET_TX_MC 0x00040000
+#define MACCFG1_RESET_RX_FUN 0x00020000
+#define MACCFG1_RESET_TX_FUN 0x00010000
+#define MACCFG1_LOOPBACK 0x00000100
+#define MACCFG1_RX_FLOW 0x00000020
+#define MACCFG1_TX_FLOW 0x00000010
+#define MACCFG1_SYNCD_RX_EN 0x00000008
+#define MACCFG1_RX_EN 0x00000004
+#define MACCFG1_SYNCD_TX_EN 0x00000002
+#define MACCFG1_TX_EN 0x00000001
+
+#define MACCFG2_INIT_SETTINGS 0x00007205
+#define MACCFG2_FULL_DUPLEX 0x00000001
+#define MACCFG2_IF 0x00000300
+#define MACCFG2_MII 0x00000100
+
+#define ECNTRL_INIT_SETTINGS 0x00001000
+#define ECNTRL_TBI_MODE 0x00000020
+
+#define TBIPA_VALUE 0x1f
+#define MIIMCFG_INIT_VALUE 0x00000003
+#define MIIMCFG_RESET 0x80000000
+
+#define MIIMIND_BUSY 0x00000001
+#define MIIMIND_NOTVALID 0x00000004
+
+#define MIIM_TBICON 0x11
+#define MIIM_TBICON_GMII 0x00000010
+#define MIIM_TBICON_AN 0x00000100
+
+#define MIIM_CONTROL 0x00
+#define MIIM_CONTROL_INIT 0x00001140
+#define MIIM_ANEN 0x00001000
+
+#define MIIM_TBI_STATUS 0x1
+#define MIIM_TBI_STATUS_AN_DONE 0x00000020
+
+#define MIIM_TBI_ANEX 0x6
+#define MIIM_TBI_ANEX_NP 0x00000004
+#define MIIM_TBI_ANEX_PRX 0x00000002
+
+#define MIIM_TBI_ANLPBPA 0x5
+#define MIIM_TBI_ANLPBPA_HALF 0x00000040
+#define MIIM_TBI_ANLPBPA_FULL 0x00000020
+
+#ifdef CONFIG_PHY_CIS8201
+#define MIIM_AUX_CONSTAT 0x1c
+#define MIIM_AUXCONSTAT_INIT 0x0004
+#define MIIM_AUXCONSTAT_DUPLEX 0x0020
+#define MIIM_AUXCONSTAT_SPEED 0x0018
+#define MIIM_AUXCONSTAT_GBIT 0x0010
+#define MIIM_AUXCONSTAT_100 0x0008
+
+#define MIIM_EXT_CON1 0x17
+#define MIIM_EXTCON1_INIT 0x0000
+
+#endif
+
+#ifdef CONFIG_PHY_M88E1011
+#define MIIM_ANAR 0x04
+#define MIIM_ANAR_ADVERTISEMENT 0x01e1
+
+#define MIIM_GBIT_CON 0x09
+#define MIIM_GBIT_CON_ADVERT 0x1e00
+
+#define MIIM_PHY_STATUS 0x11
+#define MIIM_PHYSTAT_SPEED 0xc000
+#define MIIM_PHYSTAT_GBIT 0x8000
+#define MIIM_PHYSTAT_100 0x4000
+#define MIIM_PHYSTAT_DUPLEX 0x2000
+#define MIIM_PHYSTAT_SPDDONE 0x0800
+#define MIIM_PHYSTAT_LINK 0x0400
+#endif
+
+#define MIIM_READ_COMMAND 0x00000001
+
+#define MRBLR_INIT_SETTINGS PKTSIZE_ALIGN
+
+#define MINFLR_INIT_SETTINGS 0x00000040
+
+#define DMACTRL_INIT_SETTINGS 0x000000c3
+#define DMACTRL_GRS 0x00000010
+#define DMACTRL_GTS 0x00000008
+
+#define TSTAT_CLEAR_THALT 0x80000000
+#define RSTAT_CLEAR_RHALT 0x00800000
+
+/* Write value to the PHY at phyid to the register at offset, */
+/* using the register space defined in regbase. Note that */
+/* miimcfg needs to have the clock speed setup correctly. This */
+/* macro will wait until the write is done before it finishes */
+#define write_phy_reg(regbase, phyid, offset, value) do { \
+ int timeout=1000000; \
+ regbase->miimadd = (phyid << 8) | offset; \
+ regbase->miimcon = value; \
+ asm("msync"); \
+ while((regbase->miimind & MIIMIND_BUSY) && timeout--); \
+} while(0)
+
+
+#define IEVENT_INIT_CLEAR 0xffffffff
+#define IEVENT_BABR 0x80000000
+#define IEVENT_RXC 0x40000000
+#define IEVENT_BSY 0x20000000
+#define IEVENT_EBERR 0x10000000
+#define IEVENT_MSRO 0x04000000
+#define IEVENT_GTSC 0x02000000
+#define IEVENT_BABT 0x01000000
+#define IEVENT_TXC 0x00800000
+#define IEVENT_TXE 0x00400000
+#define IEVENT_TXB 0x00200000
+#define IEVENT_TXF 0x00100000
+#define IEVENT_IE 0x00080000
+#define IEVENT_LC 0x00040000
+#define IEVENT_CRL 0x00020000
+#define IEVENT_XFUN 0x00010000
+#define IEVENT_RXB0 0x00008000
+#define IEVENT_GRSC 0x00000100
+#define IEVENT_RXF0 0x00000080
+
+#define IMASK_INIT_CLEAR 0x00000000
+#define IMASK_TXEEN 0x00400000
+#define IMASK_TXBEN 0x00200000
+#define IMASK_TXFEN 0x00100000
+#define IMASK_RXFEN0 0x00000080
+
+
+/* Default Attribute fields */
+#define ATTR_INIT_SETTINGS 0x000000c0
+#define ATTRELI_INIT_SETTINGS 0x00000000
+
+
+/* TxBD status field bits */
+#define TXBD_READY 0x8000
+#define TXBD_PADCRC 0x4000
+#define TXBD_WRAP 0x2000
+#define TXBD_INTERRUPT 0x1000
+#define TXBD_LAST 0x0800
+#define TXBD_CRC 0x0400
+#define TXBD_DEF 0x0200
+#define TXBD_HUGEFRAME 0x0080
+#define TXBD_LATECOLLISION 0x0080
+#define TXBD_RETRYLIMIT 0x0040
+#define TXBD_RETRYCOUNTMASK 0x003c
+#define TXBD_UNDERRUN 0x0002
+#define TXBD_STATS 0x03ff
+
+/* RxBD status field bits */
+#define RXBD_EMPTY 0x8000
+#define RXBD_RO1 0x4000
+#define RXBD_WRAP 0x2000
+#define RXBD_INTERRUPT 0x1000
+#define RXBD_LAST 0x0800
+#define RXBD_FIRST 0x0400
+#define RXBD_MISS 0x0100
+#define RXBD_BROADCAST 0x0080
+#define RXBD_MULTICAST 0x0040
+#define RXBD_LARGE 0x0020
+#define RXBD_NONOCTET 0x0010
+#define RXBD_SHORT 0x0008
+#define RXBD_CRCERR 0x0004
+#define RXBD_OVERRUN 0x0002
+#define RXBD_TRUNCATED 0x0001
+#define RXBD_STATS 0x003f
+
+typedef struct txbd8
+{
+ ushort status; /* Status Fields */
+ ushort length; /* Buffer length */
+ uint bufPtr; /* Buffer Pointer */
+} txbd8_t;
+
+typedef struct rxbd8
+{
+ ushort status; /* Status Fields */
+ ushort length; /* Buffer Length */
+ uint bufPtr; /* Buffer Pointer */
+} rxbd8_t;
+
+typedef struct rmon_mib
+{
+ /* Transmit and Receive Counters */
+ uint tr64; /* Transmit and Receive 64-byte Frame Counter */
+ uint tr127; /* Transmit and Receive 65-127 byte Frame Counter */
+ uint tr255; /* Transmit and Receive 128-255 byte Frame Counter */
+ uint tr511; /* Transmit and Receive 256-511 byte Frame Counter */
+ uint tr1k; /* Transmit and Receive 512-1023 byte Frame Counter */
+ uint trmax; /* Transmit and Receive 1024-1518 byte Frame Counter */
+ uint trmgv; /* Transmit and Receive 1519-1522 byte Good VLAN Frame */
+ /* Receive Counters */
+ uint rbyt; /* Receive Byte Counter */
+ uint rpkt; /* Receive Packet Counter */
+ uint rfcs; /* Receive FCS Error Counter */
+ uint rmca; /* Receive Multicast Packet (Counter) */
+ uint rbca; /* Receive Broadcast Packet */
+ uint rxcf; /* Receive Control Frame Packet */
+ uint rxpf; /* Receive Pause Frame Packet */
+ uint rxuo; /* Receive Unknown OP Code */
+ uint raln; /* Receive Alignment Error */
+ uint rflr; /* Receive Frame Length Error */
+ uint rcde; /* Receive Code Error */
+ uint rcse; /* Receive Carrier Sense Error */
+ uint rund; /* Receive Undersize Packet */
+ uint rovr; /* Receive Oversize Packet */
+ uint rfrg; /* Receive Fragments */
+ uint rjbr; /* Receive Jabber */
+ uint rdrp; /* Receive Drop */
+ /* Transmit Counters */
+ uint tbyt; /* Transmit Byte Counter */
+ uint tpkt; /* Transmit Packet */
+ uint tmca; /* Transmit Multicast Packet */
+ uint tbca; /* Transmit Broadcast Packet */
+ uint txpf; /* Transmit Pause Control Frame */
+ uint tdfr; /* Transmit Deferral Packet */
+ uint tedf; /* Transmit Excessive Deferral Packet */
+ uint tscl; /* Transmit Single Collision Packet */
+ /* (0x2_n700) */
+ uint tmcl; /* Transmit Multiple Collision Packet */
+ uint tlcl; /* Transmit Late Collision Packet */
+ uint txcl; /* Transmit Excessive Collision Packet */
+ uint tncl; /* Transmit Total Collision */
+
+ uint res2;
+
+ uint tdrp; /* Transmit Drop Frame */
+ uint tjbr; /* Transmit Jabber Frame */
+ uint tfcs; /* Transmit FCS Error */
+ uint txcf; /* Transmit Control Frame */
+ uint tovr; /* Transmit Oversize Frame */
+ uint tund; /* Transmit Undersize Frame */
+ uint tfrg; /* Transmit Fragments Frame */
+ /* General Registers */
+ uint car1; /* Carry Register One */
+ uint car2; /* Carry Register Two */
+ uint cam1; /* Carry Register One Mask */
+ uint cam2; /* Carry Register Two Mask */
+} rmon_mib_t;
+
+typedef struct tsec_hash_regs
+{
+ uint iaddr0; /* Individual Address Register 0 */
+ uint iaddr1; /* Individual Address Register 1 */
+ uint iaddr2; /* Individual Address Register 2 */
+ uint iaddr3; /* Individual Address Register 3 */
+ uint iaddr4; /* Individual Address Register 4 */
+ uint iaddr5; /* Individual Address Register 5 */
+ uint iaddr6; /* Individual Address Register 6 */
+ uint iaddr7; /* Individual Address Register 7 */
+ uint res1[24];
+ uint gaddr0; /* Group Address Register 0 */
+ uint gaddr1; /* Group Address Register 1 */
+ uint gaddr2; /* Group Address Register 2 */
+ uint gaddr3; /* Group Address Register 3 */
+ uint gaddr4; /* Group Address Register 4 */
+ uint gaddr5; /* Group Address Register 5 */
+ uint gaddr6; /* Group Address Register 6 */
+ uint gaddr7; /* Group Address Register 7 */
+ uint res2[24];
+} tsec_hash_t;
+
+typedef struct tsec
+{
+ /* General Control and Status Registers (0x2_n000) */
+ uint res000[4];
+
+ uint ievent; /* Interrupt Event */
+ uint imask; /* Interrupt Mask */
+ uint edis; /* Error Disabled */
+ uint res01c;
+ uint ecntrl; /* Ethernet Control */
+ uint minflr; /* Minimum Frame Length */
+ uint ptv; /* Pause Time Value */
+ uint dmactrl; /* DMA Control */
+ uint tbipa; /* TBI PHY Address */
+
+ uint res034[3];
+ uint res040[48];
+
+ /* Transmit Control and Status Registers (0x2_n100) */
+ uint tctrl; /* Transmit Control */
+ uint tstat; /* Transmit Status */
+ uint res108;
+ uint tbdlen; /* Tx BD Data Length */
+ uint res110[5];
+ uint ctbptr; /* Current TxBD Pointer */
+ uint res128[23];
+ uint tbptr; /* TxBD Pointer */
+ uint res188[30];
+ /* (0x2_n200) */
+ uint res200;
+ uint tbase; /* TxBD Base Address */
+ uint res208[42];
+ uint ostbd; /* Out of Sequence TxBD */
+ uint ostbdp; /* Out of Sequence Tx Data Buffer Pointer */
+ uint res2b8[18];
+
+ /* Receive Control and Status Registers (0x2_n300) */
+ uint rctrl; /* Receive Control */
+ uint rstat; /* Receive Status */
+ uint res308;
+ uint rbdlen; /* RxBD Data Length */
+ uint res310[4];
+ uint res320;
+ uint crbptr; /* Current Receive Buffer Pointer */
+ uint res328[6];
+ uint mrblr; /* Maximum Receive Buffer Length */
+ uint res344[16];
+ uint rbptr; /* RxBD Pointer */
+ uint res388[30];
+ /* (0x2_n400) */
+ uint res400;
+ uint rbase; /* RxBD Base Address */
+ uint res408[62];
+
+ /* MAC Registers (0x2_n500) */
+ uint maccfg1; /* MAC Configuration #1 */
+ uint maccfg2; /* MAC Configuration #2 */
+ uint ipgifg; /* Inter Packet Gap/Inter Frame Gap */
+ uint hafdup; /* Half-duplex */
+ uint maxfrm; /* Maximum Frame */
+ uint res514;
+ uint res518;
+
+ uint res51c;
+
+ uint miimcfg; /* MII Management: Configuration */
+ uint miimcom; /* MII Management: Command */
+ uint miimadd; /* MII Management: Address */
+ uint miimcon; /* MII Management: Control */
+ uint miimstat; /* MII Management: Status */
+ uint miimind; /* MII Management: Indicators */
+
+ uint res538;
+
+ uint ifstat; /* Interface Status */
+ uint macstnaddr1; /* Station Address, part 1 */
+ uint macstnaddr2; /* Station Address, part 2 */
+ uint res548[46];
+
+ /* (0x2_n600) */
+ uint res600[32];
+
+ /* RMON MIB Registers (0x2_n680-0x2_n73c) */
+ rmon_mib_t rmon;
+ uint res740[48];
+
+ /* Hash Function Registers (0x2_n800) */
+ tsec_hash_t hash;
+
+ uint res900[128];
+
+ /* Pattern Registers (0x2_nb00) */
+ uint resb00[62];
+ uint attr; /* Default Attribute Register */
+ uint attreli; /* Default Attribute Extract Length and Index */
+
+ /* TSEC Future Expansion Space (0x2_nc00-0x2_nffc) */
+ uint resc00[256];
+} tsec_t;
+
+#endif /* __TSEC_H */