summaryrefslogtreecommitdiff
path: root/arch/ppc/cpu/mpc85xx
diff options
context:
space:
mode:
authorMinkyu Kang <mk7.kang@samsung.com>2010-04-19 10:26:18 +0900
committerMinkyu Kang <mk7.kang@samsung.com>2010-04-19 10:26:18 +0900
commit83653121d7382fccfe329cb732f77f116341ef1d (patch)
tree0b1ce6764252af15dfb2614372de98a44a7ec61f /arch/ppc/cpu/mpc85xx
parent0f1f21a345e02a68ec16f7ab9e7dc687f9276089 (diff)
parent07739bcef5da07cc4a4edef8b91014ccc332eda3 (diff)
downloadu-boot-imx-83653121d7382fccfe329cb732f77f116341ef1d.zip
u-boot-imx-83653121d7382fccfe329cb732f77f116341ef1d.tar.gz
u-boot-imx-83653121d7382fccfe329cb732f77f116341ef1d.tar.bz2
Merge branch 'master' of git://git.denx.de/u-boot-arm
Conflicts: cpu/arm1176/cpu.c cpu/arm1176/start.S cpu/arm_cortexa8/s5pc1xx/Makefile cpu/arm_cortexa8/s5pc1xx/clock.c drivers/serial/serial_s5p.c include/asm-arm/arch-s5pc1xx/clk.h include/asm-arm/arch-s5pc1xx/gpio.h include/asm-arm/arch-s5pc1xx/uart.h Signed-off-by: Minkyu Kang <mk7.kang@samsung.com>
Diffstat (limited to 'arch/ppc/cpu/mpc85xx')
-rw-r--r--arch/ppc/cpu/mpc85xx/Makefile95
-rw-r--r--arch/ppc/cpu/mpc85xx/commproc.c205
-rw-r--r--arch/ppc/cpu/mpc85xx/config.mk35
-rw-r--r--arch/ppc/cpu/mpc85xx/cpu.c330
-rw-r--r--arch/ppc/cpu/mpc85xx/cpu_init.c405
-rw-r--r--arch/ppc/cpu/mpc85xx/cpu_init_early.c112
-rw-r--r--arch/ppc/cpu/mpc85xx/cpu_init_nand.c63
-rw-r--r--arch/ppc/cpu/mpc85xx/ddr-gen1.c89
-rw-r--r--arch/ppc/cpu/mpc85xx/ddr-gen2.c74
-rw-r--r--arch/ppc/cpu/mpc85xx/ddr-gen3.c116
-rw-r--r--arch/ppc/cpu/mpc85xx/ether_fcc.c469
-rw-r--r--arch/ppc/cpu/mpc85xx/fdt.c417
-rw-r--r--arch/ppc/cpu/mpc85xx/fixed_ivor.S79
-rw-r--r--arch/ppc/cpu/mpc85xx/interrupts.c110
-rw-r--r--arch/ppc/cpu/mpc85xx/mp.c355
-rw-r--r--arch/ppc/cpu/mpc85xx/mp.h21
-rw-r--r--arch/ppc/cpu/mpc85xx/mpc8536_serdes.c180
-rw-r--r--arch/ppc/cpu/mpc85xx/pci.c230
-rw-r--r--arch/ppc/cpu/mpc85xx/qe_io.c85
-rw-r--r--arch/ppc/cpu/mpc85xx/release.S311
-rw-r--r--arch/ppc/cpu/mpc85xx/resetvec.S2
-rw-r--r--arch/ppc/cpu/mpc85xx/serial_scc.c268
-rw-r--r--arch/ppc/cpu/mpc85xx/speed.c283
-rw-r--r--arch/ppc/cpu/mpc85xx/start.S1195
-rw-r--r--arch/ppc/cpu/mpc85xx/tlb.c277
-rw-r--r--arch/ppc/cpu/mpc85xx/traps.c325
-rw-r--r--arch/ppc/cpu/mpc85xx/u-boot-nand.lds137
-rw-r--r--arch/ppc/cpu/mpc85xx/u-boot-nand_spl.lds67
-rw-r--r--arch/ppc/cpu/mpc85xx/u-boot.lds157
29 files changed, 6492 insertions, 0 deletions
diff --git a/arch/ppc/cpu/mpc85xx/Makefile b/arch/ppc/cpu/mpc85xx/Makefile
new file mode 100644
index 0000000..f064fee
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/Makefile
@@ -0,0 +1,95 @@
+#
+# (C) Copyright 2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# (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 = $(obj)lib$(CPU).a
+
+START = start.o resetvec.o
+SOBJS-$(CONFIG_MP) += release.o
+SOBJS = $(SOBJS-y)
+
+COBJS-$(CONFIG_CPM2) += commproc.o
+
+# supports ddr1
+COBJS-$(CONFIG_MPC8540) += ddr-gen1.o
+COBJS-$(CONFIG_MPC8560) += ddr-gen1.o
+COBJS-$(CONFIG_MPC8541) += ddr-gen1.o
+COBJS-$(CONFIG_MPC8555) += ddr-gen1.o
+
+# supports ddr1/2
+COBJS-$(CONFIG_MPC8548) += ddr-gen2.o
+COBJS-$(CONFIG_MPC8568) += ddr-gen2.o
+COBJS-$(CONFIG_MPC8544) += ddr-gen2.o
+
+# supports ddr1/2/3
+COBJS-$(CONFIG_MPC8572) += ddr-gen3.o
+COBJS-$(CONFIG_MPC8536) += ddr-gen3.o
+COBJS-$(CONFIG_MPC8569) += ddr-gen3.o
+COBJS-$(CONFIG_P1011) += ddr-gen3.o
+COBJS-$(CONFIG_P1012) += ddr-gen3.o
+COBJS-$(CONFIG_P1013) += ddr-gen3.o
+COBJS-$(CONFIG_P1020) += ddr-gen3.o
+COBJS-$(CONFIG_P1021) += ddr-gen3.o
+COBJS-$(CONFIG_P1022) += ddr-gen3.o
+COBJS-$(CONFIG_P2010) += ddr-gen3.o
+COBJS-$(CONFIG_P2020) += ddr-gen3.o
+COBJS-$(CONFIG_PPC_P4080) += ddr-gen3.o
+
+COBJS-$(CONFIG_CPM2) += ether_fcc.o
+COBJS-$(CONFIG_OF_LIBFDT) += fdt.o
+COBJS-$(CONFIG_MP) += mp.o
+COBJS-$(CONFIG_MPC8536) += mpc8536_serdes.o
+COBJS-$(CONFIG_PCI) += pci.o
+COBJS-$(CONFIG_QE) += qe_io.o
+COBJS-$(CONFIG_CPM2) += serial_scc.o
+
+COBJS = $(COBJS-y)
+COBJS += cpu.o
+COBJS += cpu_init.o
+COBJS += cpu_init_early.o
+COBJS += interrupts.o
+COBJS += speed.o
+COBJS += tlb.o
+COBJS += traps.o
+
+SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
+START := $(addprefix $(obj),$(START))
+
+all: $(obj).depend $(START) $(LIB)
+
+$(LIB): $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/ppc/cpu/mpc85xx/commproc.c b/arch/ppc/cpu/mpc85xx/commproc.c
new file mode 100644
index 0000000..594aace
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/commproc.c
@@ -0,0 +1,205 @@
+/*
+ * 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>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * 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)
+{
+ volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+ volatile ulong count;
+
+ gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_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
+ */
+ cpm->im_cpm_cp.cpcr = CPM_CR_RST;
+ count = 0;
+ do { /* Spin until command processed */
+ __asm__ __volatile__ ("eieio");
+ } while ((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)
+{
+ volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+ 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 *)&(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)
+{
+ volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+ volatile uint *bp;
+
+ /* This is good enough to get SMCs running.....
+ */
+ if (brg < 4) {
+ bp = (uint *)&(cpm->im_cpm_brg1.brgc1);
+ }
+ else {
+ bp = (uint *)&(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)
+{
+ volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+ volatile uint *bp;
+
+ /* This is good enough to get SMCs running.....
+ */
+ if (brg < 4) {
+ bp = (uint *)&(cpm->im_cpm_brg1.brgc1);
+ }
+ else {
+ bp = (uint *)&(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 ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+ volatile uint *bp;
+
+ if (brg < 4) {
+ bp = (uint *)&(cpm->im_cpm_brg1.brgc1);
+ }
+ else {
+ bp = (uint *)&(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 *)(CONFIG_SYS_IMMR + CPM_POST_WORD_ADDR);
+
+ *save_addr = a;
+}
+
+ulong post_word_load (void)
+{
+ volatile ulong *save_addr =
+ (volatile ulong *)(CONFIG_SYS_IMMR + CPM_POST_WORD_ADDR);
+
+ return *save_addr;
+}
+
+#endif /* CONFIG_POST */
diff --git a/arch/ppc/cpu/mpc85xx/config.mk b/arch/ppc/cpu/mpc85xx/config.mk
new file mode 100644
index 0000000..ffb813d
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/config.mk
@@ -0,0 +1,35 @@
+#
+# (C) Copyright 2002,2003 Motorola Inc.
+# Xianghua Xiao, X.Xiao@motorola.com
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+PLATFORM_RELFLAGS += -fPIC -meabi
+
+PLATFORM_CPPFLAGS += -ffixed-r2 -Wa,-me500 -msoft-float -mno-string
+
+# -mspe=yes is needed to have -mno-spe accepted by a buggy GCC;
+# see "[PATCH,rs6000] make -mno-spe work as expected" on
+# http://gcc.gnu.org/ml/gcc-patches/2008-04/msg00311.html
+PLATFORM_CPPFLAGS +=$(call cc-option,-mspe=yes)
+PLATFORM_CPPFLAGS +=$(call cc-option,-mno-spe)
+
+# Use default linker script. Board port can override in board/*/config.mk
+LDSCRIPT := $(SRCTREE)/arch/ppc/cpu/mpc85xx/u-boot.lds
diff --git a/arch/ppc/cpu/mpc85xx/cpu.c b/arch/ppc/cpu/mpc85xx/cpu.c
new file mode 100644
index 0000000..0cc6e03
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/cpu.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright 2004,2007-2009 Freescale Semiconductor, Inc.
+ * (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 <config.h>
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <fsl_esdhc.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int checkcpu (void)
+{
+ sys_info_t sysinfo;
+ uint pvr, svr;
+ uint fam;
+ uint ver;
+ uint major, minor;
+ struct cpu_type *cpu;
+ char buf1[32], buf2[32];
+#ifdef CONFIG_DDR_CLK_FREQ
+ volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+#ifdef CONFIG_FSL_CORENET
+ u32 ddr_sync = ((gur->rcwsr[5]) & FSL_CORENET_RCWSR5_DDR_SYNC)
+ >> FSL_CORENET_RCWSR5_DDR_SYNC_SHIFT;
+#else
+ u32 ddr_ratio = ((gur->porpllsr) & MPC85xx_PORPLLSR_DDR_RATIO)
+ >> MPC85xx_PORPLLSR_DDR_RATIO_SHIFT;
+#endif
+#else
+#ifdef CONFIG_FSL_CORENET
+ u32 ddr_sync = 0;
+#else
+ u32 ddr_ratio = 0;
+#endif
+#endif /* CONFIG_DDR_CLK_FREQ */
+ int i;
+
+ svr = get_svr();
+ major = SVR_MAJ(svr);
+#ifdef CONFIG_MPC8536
+ major &= 0x7; /* the msb of this nibble is a mfg code */
+#endif
+ minor = SVR_MIN(svr);
+
+ if (cpu_numcores() > 1) {
+#ifndef CONFIG_MP
+ puts("Unicore software on multiprocessor system!!\n"
+ "To enable mutlticore build define CONFIG_MP\n");
+#endif
+ volatile ccsr_pic_t *pic = (void *)(CONFIG_SYS_MPC85xx_PIC_ADDR);
+ printf("CPU%d: ", pic->whoami);
+ } else {
+ puts("CPU: ");
+ }
+
+ cpu = gd->cpu;
+
+ puts(cpu->name);
+ if (IS_E_PROCESSOR(svr))
+ puts("E");
+
+ printf(", Version: %d.%d, (0x%08x)\n", major, minor, svr);
+
+ pvr = get_pvr();
+ fam = PVR_FAM(pvr);
+ ver = PVR_VER(pvr);
+ major = PVR_MAJ(pvr);
+ minor = PVR_MIN(pvr);
+
+ printf("Core: ");
+ switch (fam) {
+ case PVR_FAM(PVR_85xx):
+ puts("E500");
+ break;
+ default:
+ puts("Unknown");
+ break;
+ }
+
+ if (PVR_MEM(pvr) == 0x03)
+ puts("MC");
+
+ printf(", Version: %d.%d, (0x%08x)\n", major, minor, pvr);
+
+ get_sys_info(&sysinfo);
+
+ puts("Clock Configuration:");
+ for (i = 0; i < cpu_numcores(); i++) {
+ if (!(i & 3))
+ printf ("\n ");
+ printf("CPU%d:%-4s MHz, ",
+ i,strmhz(buf1, sysinfo.freqProcessor[i]));
+ }
+ printf("\n CCB:%-4s MHz,\n", strmhz(buf1, sysinfo.freqSystemBus));
+
+#ifdef CONFIG_FSL_CORENET
+ if (ddr_sync == 1) {
+ printf(" DDR:%-4s MHz (%s MT/s data rate) "
+ "(Synchronous), ",
+ strmhz(buf1, sysinfo.freqDDRBus/2),
+ strmhz(buf2, sysinfo.freqDDRBus));
+ } else {
+ printf(" DDR:%-4s MHz (%s MT/s data rate) "
+ "(Asynchronous), ",
+ strmhz(buf1, sysinfo.freqDDRBus/2),
+ strmhz(buf2, sysinfo.freqDDRBus));
+ }
+#else
+ switch (ddr_ratio) {
+ case 0x0:
+ printf(" DDR:%-4s MHz (%s MT/s data rate), ",
+ strmhz(buf1, sysinfo.freqDDRBus/2),
+ strmhz(buf2, sysinfo.freqDDRBus));
+ break;
+ case 0x7:
+ printf(" DDR:%-4s MHz (%s MT/s data rate) "
+ "(Synchronous), ",
+ strmhz(buf1, sysinfo.freqDDRBus/2),
+ strmhz(buf2, sysinfo.freqDDRBus));
+ break;
+ default:
+ printf(" DDR:%-4s MHz (%s MT/s data rate) "
+ "(Asynchronous), ",
+ strmhz(buf1, sysinfo.freqDDRBus/2),
+ strmhz(buf2, sysinfo.freqDDRBus));
+ break;
+ }
+#endif
+
+ if (sysinfo.freqLocalBus > LCRR_CLKDIV) {
+ printf("LBC:%-4s MHz\n", strmhz(buf1, sysinfo.freqLocalBus));
+ } else {
+ printf("LBC: unknown (LCRR[CLKDIV] = 0x%02lx)\n",
+ sysinfo.freqLocalBus);
+ }
+
+#ifdef CONFIG_CPM2
+ printf("CPM: %s MHz\n", strmhz(buf1, sysinfo.freqSystemBus));
+#endif
+
+#ifdef CONFIG_QE
+ printf(" QE:%-4s MHz\n", strmhz(buf1, sysinfo.freqQE));
+#endif
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+ for (i = 0; i < CONFIG_SYS_NUM_FMAN; i++) {
+ printf(" FMAN%d: %s MHz\n", i,
+ strmhz(buf1, sysinfo.freqFMan[i]));
+ }
+#endif
+
+#ifdef CONFIG_SYS_DPAA_PME
+ printf(" PME: %s MHz\n", strmhz(buf1, sysinfo.freqPME));
+#endif
+
+ puts("L1: D-cache 32 kB enabled\n I-cache 32 kB enabled\n");
+
+ return 0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+int do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+/* Everything after the first generation of PQ3 parts has RSTCR */
+#if defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \
+ defined(CONFIG_MPC8555) || defined(CONFIG_MPC8560)
+ unsigned long val, msr;
+
+ /*
+ * Initiate hard reset in debug control register DBCR0
+ * Make sure MSR[DE] = 1. This only resets the core.
+ */
+ msr = mfmsr ();
+ msr |= MSR_DE;
+ mtmsr (msr);
+
+ val = mfspr(DBCR0);
+ val |= 0x70000000;
+ mtspr(DBCR0,val);
+#else
+ volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ out_be32(&gur->rstcr, 0x2); /* HRESET_REQ */
+ udelay(100);
+#endif
+
+ return 1;
+}
+
+
+/*
+ * Get timebase clock frequency
+ */
+unsigned long get_tbclk (void)
+{
+#ifdef CONFIG_FSL_CORENET
+ return (gd->bus_clk + 8) / 16;
+#else
+ return (gd->bus_clk + 4UL)/8UL;
+#endif
+}
+
+
+#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(SPRN_TSR);
+ val |= TSR_WIS;
+ mtspr(SPRN_TSR, val);
+}
+#endif /* CONFIG_WATCHDOG */
+
+/*
+ * Configures a UPM. The function requires the respective MxMR to be set
+ * before calling this function. "size" is the number or entries, not a sizeof.
+ */
+void upmconfig (uint upm, uint * table, uint size)
+{
+ int i, mdr, mad, old_mad = 0;
+ volatile u32 *mxmr;
+ volatile ccsr_lbc_t *lbc = (void *)(CONFIG_SYS_MPC85xx_LBC_ADDR);
+ volatile u32 *brp,*orp;
+ volatile u8* dummy = NULL;
+ int upmmask;
+
+ switch (upm) {
+ case UPMA:
+ mxmr = &lbc->mamr;
+ upmmask = BR_MS_UPMA;
+ break;
+ case UPMB:
+ mxmr = &lbc->mbmr;
+ upmmask = BR_MS_UPMB;
+ break;
+ case UPMC:
+ mxmr = &lbc->mcmr;
+ upmmask = BR_MS_UPMC;
+ break;
+ default:
+ printf("%s: Bad UPM index %d to configure\n", __FUNCTION__, upm);
+ hang();
+ }
+
+ /* Find the address for the dummy write transaction */
+ for (brp = &lbc->br0, orp = &lbc->or0, i = 0; i < 8;
+ i++, brp += 2, orp += 2) {
+
+ /* Look for a valid BR with selected UPM */
+ if ((in_be32(brp) & (BR_V | BR_MSEL)) == (BR_V | upmmask)) {
+ dummy = (volatile u8*)(in_be32(brp) & BR_BA);
+ break;
+ }
+ }
+
+ if (i == 8) {
+ printf("Error: %s() could not find matching BR\n", __FUNCTION__);
+ hang();
+ }
+
+ for (i = 0; i < size; i++) {
+ /* 1 */
+ out_be32(mxmr, (in_be32(mxmr) & 0x4fffffc0) | MxMR_OP_WARR | i);
+ /* 2 */
+ out_be32(&lbc->mdr, table[i]);
+ /* 3 */
+ mdr = in_be32(&lbc->mdr);
+ /* 4 */
+ *(volatile u8 *)dummy = 0;
+ /* 5 */
+ do {
+ mad = in_be32(mxmr) & MxMR_MAD_MSK;
+ } while (mad <= old_mad && !(!mad && i == (size-1)));
+ old_mad = mad;
+ }
+ out_be32(mxmr, (in_be32(mxmr) & 0x4fffffc0) | MxMR_OP_NORM);
+}
+
+/*
+ * Initializes on-chip MMC controllers.
+ * to override, implement board_mmc_init()
+ */
+int cpu_mmc_init(bd_t *bis)
+{
+#ifdef CONFIG_FSL_ESDHC
+ return fsl_esdhc_mmc_init(bis);
+#else
+ return 0;
+#endif
+}
diff --git a/arch/ppc/cpu/mpc85xx/cpu_init.c b/arch/ppc/cpu/mpc85xx/cpu_init.c
new file mode 100644
index 0000000..e0126d3
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/cpu_init.c
@@ -0,0 +1,405 @@
+/*
+ * Copyright 2007-2009 Freescale Semiconductor, Inc.
+ *
+ * (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>
+#include <asm/mmu.h>
+#include <asm/fsl_law.h>
+#include "mp.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_MPC8536
+extern void fsl_serdes_init(void);
+#endif
+
+#ifdef CONFIG_QE
+extern qe_iop_conf_t qe_iop_conf_tab[];
+extern void qe_config_iopin(u8 port, u8 pin, int dir,
+ int open_drain, int assign);
+extern void qe_init(uint qe_base);
+extern void qe_reset(void);
+
+static void config_qe_ioports(void)
+{
+ u8 port, pin;
+ int dir, open_drain, assign;
+ int i;
+
+ for (i = 0; qe_iop_conf_tab[i].assign != QE_IOP_TAB_END; i++) {
+ port = qe_iop_conf_tab[i].port;
+ pin = qe_iop_conf_tab[i].pin;
+ dir = qe_iop_conf_tab[i].dir;
+ open_drain = qe_iop_conf_tab[i].open_drain;
+ assign = qe_iop_conf_tab[i].assign;
+ qe_config_iopin(port, pin, dir, open_drain, assign);
+ }
+}
+#endif
+
+#ifdef CONFIG_CPM2
+void config_8560_ioports (volatile ccsr_cpm_t * cpm)
+{
+ 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 (cpm, 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
+ */
+
+#ifdef CONFIG_FSL_CORENET
+static void corenet_tb_init(void)
+{
+ volatile ccsr_rcpm_t *rcpm =
+ (void *)(CONFIG_SYS_FSL_CORENET_RCPM_ADDR);
+ volatile ccsr_pic_t *pic =
+ (void *)(CONFIG_SYS_MPC85xx_PIC_ADDR);
+ u32 whoami = in_be32(&pic->whoami);
+
+ /* Enable the timebase register for this core */
+ out_be32(&rcpm->ctbenrl, (1 << whoami));
+}
+#endif
+
+void cpu_init_f (void)
+{
+ volatile ccsr_lbc_t *memctl = (void *)(CONFIG_SYS_MPC85xx_LBC_ADDR);
+ extern void m8560_cpm_reset (void);
+#ifdef CONFIG_MPC8548
+ ccsr_local_ecm_t *ecm = (void *)(CONFIG_SYS_MPC85xx_ECM_ADDR);
+ uint svr = get_svr();
+
+ /*
+ * CPU2 errata workaround: A core hang possible while executing
+ * a msync instruction and a snoopable transaction from an I/O
+ * master tagged to make quick forward progress is present.
+ * Fixed in silicon rev 2.1.
+ */
+ if ((SVR_MAJ(svr) == 1) || ((SVR_MAJ(svr) == 2 && SVR_MIN(svr) == 0x0)))
+ out_be32(&ecm->eebpcr, in_be32(&ecm->eebpcr) | (1 << 16));
+#endif
+
+ disable_tlb(14);
+ disable_tlb(15);
+
+#ifdef CONFIG_CPM2
+ config_8560_ioports((ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR);
+#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(CONFIG_SYS_OR0_REMAP)
+ memctl->or0 = CONFIG_SYS_OR0_REMAP;
+#endif
+#if defined(CONFIG_SYS_OR1_REMAP)
+ memctl->or1 = CONFIG_SYS_OR1_REMAP;
+#endif
+
+ /* now restrict to preliminary range */
+ /* if cs1 is already set via debugger, leave cs0/cs1 alone */
+ if (! memctl->br1 & 1) {
+#if defined(CONFIG_SYS_BR0_PRELIM) && defined(CONFIG_SYS_OR0_PRELIM)
+ memctl->br0 = CONFIG_SYS_BR0_PRELIM;
+ memctl->or0 = CONFIG_SYS_OR0_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR1_PRELIM) && defined(CONFIG_SYS_OR1_PRELIM)
+ memctl->or1 = CONFIG_SYS_OR1_PRELIM;
+ memctl->br1 = CONFIG_SYS_BR1_PRELIM;
+#endif
+ }
+
+#if defined(CONFIG_SYS_BR2_PRELIM) && defined(CONFIG_SYS_OR2_PRELIM)
+ memctl->or2 = CONFIG_SYS_OR2_PRELIM;
+ memctl->br2 = CONFIG_SYS_BR2_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR3_PRELIM) && defined(CONFIG_SYS_OR3_PRELIM)
+ memctl->or3 = CONFIG_SYS_OR3_PRELIM;
+ memctl->br3 = CONFIG_SYS_BR3_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR4_PRELIM) && defined(CONFIG_SYS_OR4_PRELIM)
+ memctl->or4 = CONFIG_SYS_OR4_PRELIM;
+ memctl->br4 = CONFIG_SYS_BR4_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR5_PRELIM) && defined(CONFIG_SYS_OR5_PRELIM)
+ memctl->or5 = CONFIG_SYS_OR5_PRELIM;
+ memctl->br5 = CONFIG_SYS_BR5_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR6_PRELIM) && defined(CONFIG_SYS_OR6_PRELIM)
+ memctl->or6 = CONFIG_SYS_OR6_PRELIM;
+ memctl->br6 = CONFIG_SYS_BR6_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR7_PRELIM) && defined(CONFIG_SYS_OR7_PRELIM)
+ memctl->or7 = CONFIG_SYS_OR7_PRELIM;
+ memctl->br7 = CONFIG_SYS_BR7_PRELIM;
+#endif
+
+#if defined(CONFIG_CPM2)
+ m8560_cpm_reset();
+#endif
+#ifdef CONFIG_QE
+ /* Config QE ioports */
+ config_qe_ioports();
+#endif
+#if defined(CONFIG_MPC8536)
+ fsl_serdes_init();
+#endif
+#if defined(CONFIG_FSL_DMA)
+ dma_init();
+#endif
+#ifdef CONFIG_FSL_CORENET
+ corenet_tb_init();
+#endif
+ init_used_tlb_cams();
+}
+
+
+/*
+ * Initialize L2 as cache.
+ *
+ * The newer 8548, etc, parts have twice as much cache, but
+ * use the same bit-encoding as the older 8555, etc, parts.
+ *
+ */
+
+int cpu_init_r(void)
+{
+ puts ("L2: ");
+
+#if defined(CONFIG_L2_CACHE)
+ volatile ccsr_l2cache_t *l2cache = (void *)CONFIG_SYS_MPC85xx_L2_ADDR;
+ volatile uint cache_ctl;
+ uint svr, ver;
+ uint l2srbar;
+ u32 l2siz_field;
+
+ svr = get_svr();
+ ver = SVR_SOC_VER(svr);
+
+ asm("msync;isync");
+ cache_ctl = l2cache->l2ctl;
+
+#if defined(CONFIG_SYS_RAMBOOT) && defined(CONFIG_SYS_INIT_L2_ADDR)
+ if (cache_ctl & MPC85xx_L2CTL_L2E) {
+ /* Clear L2 SRAM memory-mapped base address */
+ out_be32(&l2cache->l2srbar0, 0x0);
+ out_be32(&l2cache->l2srbar1, 0x0);
+
+ /* set MBECCDIS=0, SBECCDIS=0 */
+ clrbits_be32(&l2cache->l2errdis,
+ (MPC85xx_L2ERRDIS_MBECC |
+ MPC85xx_L2ERRDIS_SBECC));
+
+ /* set L2E=0, L2SRAM=0 */
+ clrbits_be32(&l2cache->l2ctl,
+ (MPC85xx_L2CTL_L2E |
+ MPC85xx_L2CTL_L2SRAM_ENTIRE));
+ }
+#endif
+
+ l2siz_field = (cache_ctl >> 28) & 0x3;
+
+ switch (l2siz_field) {
+ case 0x0:
+ printf(" unknown size (0x%08x)\n", cache_ctl);
+ return -1;
+ break;
+ case 0x1:
+ if (ver == SVR_8540 || ver == SVR_8560 ||
+ ver == SVR_8541 || ver == SVR_8541_E ||
+ ver == SVR_8555 || ver == SVR_8555_E) {
+ puts("128 KB ");
+ /* set L2E=1, L2I=1, & L2BLKSZ=1 (128 Kbyte) */
+ cache_ctl = 0xc4000000;
+ } else {
+ puts("256 KB ");
+ cache_ctl = 0xc0000000; /* set L2E=1, L2I=1, & L2SRAM=0 */
+ }
+ break;
+ case 0x2:
+ if (ver == SVR_8540 || ver == SVR_8560 ||
+ ver == SVR_8541 || ver == SVR_8541_E ||
+ ver == SVR_8555 || ver == SVR_8555_E) {
+ puts("256 KB ");
+ /* set L2E=1, L2I=1, & L2BLKSZ=2 (256 Kbyte) */
+ cache_ctl = 0xc8000000;
+ } else {
+ puts ("512 KB ");
+ /* set L2E=1, L2I=1, & L2SRAM=0 */
+ cache_ctl = 0xc0000000;
+ }
+ break;
+ case 0x3:
+ puts("1024 KB ");
+ /* set L2E=1, L2I=1, & L2SRAM=0 */
+ cache_ctl = 0xc0000000;
+ break;
+ }
+
+ if (l2cache->l2ctl & MPC85xx_L2CTL_L2E) {
+ puts("already enabled");
+ l2srbar = l2cache->l2srbar0;
+#ifdef CONFIG_SYS_INIT_L2_ADDR
+ if (l2cache->l2ctl & MPC85xx_L2CTL_L2SRAM_ENTIRE
+ && l2srbar >= CONFIG_SYS_FLASH_BASE) {
+ l2srbar = CONFIG_SYS_INIT_L2_ADDR;
+ l2cache->l2srbar0 = l2srbar;
+ printf("moving to 0x%08x", CONFIG_SYS_INIT_L2_ADDR);
+ }
+#endif /* CONFIG_SYS_INIT_L2_ADDR */
+ puts("\n");
+ } else {
+ asm("msync;isync");
+ l2cache->l2ctl = cache_ctl; /* invalidate & enable */
+ asm("msync;isync");
+ puts("enabled\n");
+ }
+#elif defined(CONFIG_BACKSIDE_L2_CACHE)
+ u32 l2cfg0 = mfspr(SPRN_L2CFG0);
+
+ /* invalidate the L2 cache */
+ mtspr(SPRN_L2CSR0, (L2CSR0_L2FI|L2CSR0_L2LFC));
+ while (mfspr(SPRN_L2CSR0) & (L2CSR0_L2FI|L2CSR0_L2LFC))
+ ;
+
+#ifdef CONFIG_SYS_CACHE_STASHING
+ /* set stash id to (coreID) * 2 + 32 + L2 (1) */
+ mtspr(SPRN_L2CSR1, (32 + 1));
+#endif
+
+ /* enable the cache */
+ mtspr(SPRN_L2CSR0, CONFIG_SYS_INIT_L2CSR0);
+
+ if (CONFIG_SYS_INIT_L2CSR0 & L2CSR0_L2E) {
+ while (!(mfspr(SPRN_L2CSR0) & L2CSR0_L2E))
+ ;
+ printf("%d KB enabled\n", (l2cfg0 & 0x3fff) * 64);
+ }
+#else
+ puts("disabled\n");
+#endif
+#ifdef CONFIG_QE
+ uint qe_base = CONFIG_SYS_IMMR + 0x00080000; /* QE immr base */
+ qe_init(qe_base);
+ qe_reset();
+#endif
+
+#if defined(CONFIG_MP)
+ setup_mp();
+#endif
+ return 0;
+}
+
+extern void setup_ivors(void);
+
+void arch_preboot_os(void)
+{
+ u32 msr;
+
+ /*
+ * We are changing interrupt offsets and are about to boot the OS so
+ * we need to make sure we disable all async interrupts. EE is already
+ * disabled by the time we get called.
+ */
+ msr = mfmsr();
+ msr &= ~(MSR_ME|MSR_CE|MSR_DE);
+ mtmsr(msr);
+
+ setup_ivors();
+}
diff --git a/arch/ppc/cpu/mpc85xx/cpu_init_early.c b/arch/ppc/cpu/mpc85xx/cpu_init_early.c
new file mode 100644
index 0000000..32aa94b
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/cpu_init_early.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc
+ *
+ * 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 <asm/mmu.h>
+#include <asm/fsl_law.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR_PHYS)
+#ifdef CONFIG_FSL_CORENET
+static void setup_ccsrbar(void)
+{
+ u32 temp;
+ volatile u32 *ccsr_virt = (volatile u32 *)(CONFIG_SYS_CCSRBAR + 0x1000);
+ volatile ccsr_local_t *ccm;
+
+ /*
+ * We can't call set_law() because we haven't moved
+ * CCSR yet.
+ */
+ ccm = (void *)ccsr_virt;
+
+ out_be32(&ccm->law[0].lawbarh,
+ (u64)CONFIG_SYS_CCSRBAR_PHYS >> 32);
+ out_be32(&ccm->law[0].lawbarl, (u32)CONFIG_SYS_CCSRBAR_PHYS);
+ out_be32(&ccm->law[0].lawar,
+ LAW_EN | (0x1e << 20) | LAW_SIZE_4K);
+
+ in_be32((u32 *)(ccsr_virt + 0));
+ in_be32((u32 *)(ccsr_virt + 1));
+ isync();
+
+ ccm = (void *)CONFIG_SYS_CCSRBAR;
+ /* Now use the temporary LAW to move CCSR */
+ out_be32(&ccm->ccsrbarh, (u64)CONFIG_SYS_CCSRBAR_PHYS >> 32);
+ out_be32(&ccm->ccsrbarl, (u32)CONFIG_SYS_CCSRBAR_PHYS);
+ out_be32(&ccm->ccsrar, CCSRAR_C);
+ temp = in_be32(&ccm->ccsrar);
+ disable_law(0);
+}
+#else
+static void setup_ccsrbar(void)
+{
+ u32 temp;
+ volatile u32 *ccsr_virt = (volatile u32 *)(CONFIG_SYS_CCSRBAR + 0x1000);
+
+ temp = in_be32(ccsr_virt);
+ out_be32(ccsr_virt, CONFIG_SYS_CCSRBAR_PHYS >> 12);
+ temp = in_be32((volatile u32 *)CONFIG_SYS_CCSRBAR);
+}
+#endif
+#endif
+
+/* We run cpu_init_early_f in AS = 1 */
+void cpu_init_early_f(void)
+{
+ u32 mas0, mas1, mas2, mas3, mas7;
+ int i;
+
+ /* Pointer is writable since we allocated a register for it */
+ gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
+
+ /*
+ * Clear initial global data
+ * we don't use memset so we can share this code with NAND_SPL
+ */
+ for (i = 0; i < sizeof(gd_t); i++)
+ ((char *)gd)[i] = 0;
+
+ mas0 = MAS0_TLBSEL(0) | MAS0_ESEL(0);
+ mas1 = MAS1_VALID | MAS1_TID(0) | MAS1_TS | MAS1_TSIZE(BOOKE_PAGESZ_4K);
+ mas2 = FSL_BOOKE_MAS2(CONFIG_SYS_CCSRBAR, MAS2_I|MAS2_G);
+ mas3 = FSL_BOOKE_MAS3(CONFIG_SYS_CCSRBAR_PHYS, 0, MAS3_SW|MAS3_SR);
+ mas7 = FSL_BOOKE_MAS7(CONFIG_SYS_CCSRBAR_PHYS);
+
+ write_tlb(mas0, mas1, mas2, mas3, mas7);
+
+ /* set up CCSR if we want it moved */
+#if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR_PHYS)
+ mas0 = MAS0_TLBSEL(0) | MAS0_ESEL(1);
+ /* mas1 is the same as above */
+ mas2 = FSL_BOOKE_MAS2(CONFIG_SYS_CCSRBAR + 0x1000, MAS2_I|MAS2_G);
+ mas3 = FSL_BOOKE_MAS3(CONFIG_SYS_CCSRBAR_DEFAULT, 0, MAS3_SW|MAS3_SR);
+ mas7 = FSL_BOOKE_MAS7(CONFIG_SYS_CCSRBAR_DEFAULT);
+
+ write_tlb(mas0, mas1, mas2, mas3, mas7);
+
+ setup_ccsrbar();
+#endif
+
+ init_laws();
+ invalidate_tlb(0);
+ init_tlbs();
+}
diff --git a/arch/ppc/cpu/mpc85xx/cpu_init_nand.c b/arch/ppc/cpu/mpc85xx/cpu_init_nand.c
new file mode 100644
index 0000000..184cca4
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/cpu_init_nand.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+void cpu_init_f(void)
+{
+ ccsr_lbc_t *lbc = (void *)(CONFIG_SYS_MPC85xx_LBC_ADDR);
+
+ /*
+ * LCRR - Clock Ratio Register - set up local bus timing
+ * when needed
+ */
+ out_be32(&lbc->lcrr, LCRR_DBYP | LCRR_CLKDIV_8);
+
+#if defined(CONFIG_NAND_BR_PRELIM) && defined(CONFIG_NAND_OR_PRELIM)
+ out_be32(&lbc->br0, CONFIG_NAND_BR_PRELIM);
+ out_be32(&lbc->or0, CONFIG_NAND_OR_PRELIM);
+#else
+#error CONFIG_NAND_BR_PRELIM, CONFIG_NAND_OR_PRELIM must be defined
+#endif
+
+#if defined(CONFIG_SYS_RAMBOOT) && defined(CONFIG_SYS_INIT_L2_ADDR)
+ ccsr_l2cache_t *l2cache = (void *)CONFIG_SYS_MPC85xx_L2_ADDR;
+ char *l2srbar;
+ int i;
+
+ out_be32(&l2cache->l2srbar0, CONFIG_SYS_INIT_L2_ADDR);
+
+ /* set MBECCDIS=1, SBECCDIS=1 */
+ out_be32(&l2cache->l2errdis,
+ (MPC85xx_L2ERRDIS_MBECC | MPC85xx_L2ERRDIS_SBECC));
+
+ /* set L2E=1 & L2SRAM=001 */
+ out_be32(&l2cache->l2ctl,
+ (MPC85xx_L2CTL_L2E | MPC85xx_L2CTL_L2SRAM_ENTIRE));
+
+ /* Initialize L2 SRAM to zero */
+ l2srbar = (char *)CONFIG_SYS_INIT_L2_ADDR;
+ for (i = 0; i < CONFIG_SYS_L2_SIZE; i++)
+ l2srbar[i] = 0;
+#endif
+}
diff --git a/arch/ppc/cpu/mpc85xx/ddr-gen1.c b/arch/ppc/cpu/mpc85xx/ddr-gen1.c
new file mode 100644
index 0000000..54437dd
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/ddr-gen1.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/fsl_ddr_sdram.h>
+
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
+#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
+#endif
+
+void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
+ unsigned int ctrl_num)
+{
+ unsigned int i;
+ volatile ccsr_ddr_t *ddr = (void *)CONFIG_SYS_MPC85xx_DDR_ADDR;
+
+ if (ctrl_num != 0) {
+ printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
+ return;
+ }
+
+ for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+ if (i == 0) {
+ out_be32(&ddr->cs0_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs0_config, regs->cs[i].config);
+
+ } else if (i == 1) {
+ out_be32(&ddr->cs1_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs1_config, regs->cs[i].config);
+
+ } else if (i == 2) {
+ out_be32(&ddr->cs2_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs2_config, regs->cs[i].config);
+
+ } else if (i == 3) {
+ out_be32(&ddr->cs3_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs3_config, regs->cs[i].config);
+ }
+ }
+
+ out_be32(&ddr->timing_cfg_1, regs->timing_cfg_1);
+ out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2);
+ out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode);
+ out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval);
+#if defined(CONFIG_MPC8555) || defined(CONFIG_MPC8541)
+ out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl);
+#endif
+
+ /*
+ * 200 painful micro-seconds must elapse between
+ * the DDR clock setup and the DDR config enable.
+ */
+ udelay(200);
+ asm volatile("sync;isync");
+
+ out_be32(&ddr->sdram_cfg, regs->ddr_sdram_cfg);
+
+ asm("sync;isync;msync");
+ udelay(500);
+}
+
+#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
+/*
+ * Initialize all of memory for ECC, then enable errors.
+ */
+
+void
+ddr_enable_ecc(unsigned int dram_size)
+{
+ volatile ccsr_ddr_t *ddr= (void *)(CONFIG_SYS_MPC85xx_DDR_ADDR);
+
+ dma_meminit(CONFIG_MEM_INIT_VALUE, dram_size);
+
+ /*
+ * Enable errors for ECC.
+ */
+ debug("DMA DDR: err_disable = 0x%08x\n", ddr->err_disable);
+ ddr->err_disable = 0x00000000;
+ asm("sync;isync;msync");
+ debug("DMA DDR: err_disable = 0x%08x\n", ddr->err_disable);
+}
+
+#endif /* CONFIG_DDR_ECC && ! CONFIG_ECC_INIT_VIA_DDRCONTROLLER */
diff --git a/arch/ppc/cpu/mpc85xx/ddr-gen2.c b/arch/ppc/cpu/mpc85xx/ddr-gen2.c
new file mode 100644
index 0000000..655f99c
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/ddr-gen2.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/fsl_ddr_sdram.h>
+
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
+#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
+#endif
+
+void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
+ unsigned int ctrl_num)
+{
+ unsigned int i;
+ volatile ccsr_ddr_t *ddr = (void *)CONFIG_SYS_MPC85xx_DDR_ADDR;
+
+ if (ctrl_num) {
+ printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
+ return;
+ }
+
+ for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+ if (i == 0) {
+ out_be32(&ddr->cs0_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs0_config, regs->cs[i].config);
+
+ } else if (i == 1) {
+ out_be32(&ddr->cs1_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs1_config, regs->cs[i].config);
+
+ } else if (i == 2) {
+ out_be32(&ddr->cs2_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs2_config, regs->cs[i].config);
+
+ } else if (i == 3) {
+ out_be32(&ddr->cs3_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs3_config, regs->cs[i].config);
+ }
+ }
+
+ out_be32(&ddr->timing_cfg_3, regs->timing_cfg_3);
+ out_be32(&ddr->timing_cfg_0, regs->timing_cfg_0);
+ out_be32(&ddr->timing_cfg_1, regs->timing_cfg_1);
+ out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2);
+ out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
+ out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode);
+ out_be32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2);
+ out_be32(&ddr->sdram_md_cntl, regs->ddr_sdram_md_cntl);
+ out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval);
+ out_be32(&ddr->sdram_data_init, regs->ddr_data_init);
+ out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl);
+ out_be32(&ddr->init_addr, regs->ddr_init_addr);
+ out_be32(&ddr->init_ext_addr, regs->ddr_init_ext_addr);
+
+ /*
+ * 200 painful micro-seconds must elapse between
+ * the DDR clock setup and the DDR config enable.
+ */
+ udelay(200);
+ asm volatile("sync;isync");
+
+ out_be32(&ddr->sdram_cfg, regs->ddr_sdram_cfg);
+
+ /* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done. */
+ while (in_be32(&ddr->sdram_cfg_2) & 0x10) {
+ udelay(10000); /* throttle polling rate */
+ }
+}
diff --git a/arch/ppc/cpu/mpc85xx/ddr-gen3.c b/arch/ppc/cpu/mpc85xx/ddr-gen3.c
new file mode 100644
index 0000000..0691ca4
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/ddr-gen3.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/fsl_ddr_sdram.h>
+
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
+#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
+#endif
+
+void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
+ unsigned int ctrl_num)
+{
+ unsigned int i;
+ volatile ccsr_ddr_t *ddr;
+ u32 temp_sdram_cfg;
+
+ switch (ctrl_num) {
+ case 0:
+ ddr = (void *)CONFIG_SYS_MPC85xx_DDR_ADDR;
+ break;
+ case 1:
+ ddr = (void *)CONFIG_SYS_MPC85xx_DDR2_ADDR;
+ break;
+ default:
+ printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
+ return;
+ }
+
+ for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+ if (i == 0) {
+ out_be32(&ddr->cs0_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs0_config, regs->cs[i].config);
+ out_be32(&ddr->cs0_config_2, regs->cs[i].config_2);
+
+ } else if (i == 1) {
+ out_be32(&ddr->cs1_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs1_config, regs->cs[i].config);
+ out_be32(&ddr->cs1_config_2, regs->cs[i].config_2);
+
+ } else if (i == 2) {
+ out_be32(&ddr->cs2_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs2_config, regs->cs[i].config);
+ out_be32(&ddr->cs2_config_2, regs->cs[i].config_2);
+
+ } else if (i == 3) {
+ out_be32(&ddr->cs3_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs3_config, regs->cs[i].config);
+ out_be32(&ddr->cs3_config_2, regs->cs[i].config_2);
+ }
+ }
+
+ out_be32(&ddr->timing_cfg_3, regs->timing_cfg_3);
+ out_be32(&ddr->timing_cfg_0, regs->timing_cfg_0);
+ out_be32(&ddr->timing_cfg_1, regs->timing_cfg_1);
+ out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2);
+ out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
+ out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode);
+ out_be32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2);
+ out_be32(&ddr->sdram_md_cntl, regs->ddr_sdram_md_cntl);
+ out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval);
+ out_be32(&ddr->sdram_data_init, regs->ddr_data_init);
+ out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl);
+ out_be32(&ddr->init_addr, regs->ddr_init_addr);
+ out_be32(&ddr->init_ext_addr, regs->ddr_init_ext_addr);
+
+ out_be32(&ddr->timing_cfg_4, regs->timing_cfg_4);
+ out_be32(&ddr->timing_cfg_5, regs->timing_cfg_5);
+ out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl);
+ out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl);
+ out_be32(&ddr->ddr_sr_cntr, regs->ddr_sr_cntr);
+ out_be32(&ddr->ddr_sdram_rcw_1, regs->ddr_sdram_rcw_1);
+ out_be32(&ddr->ddr_sdram_rcw_2, regs->ddr_sdram_rcw_2);
+
+ /* Set, but do not enable the memory */
+ temp_sdram_cfg = regs->ddr_sdram_cfg;
+ temp_sdram_cfg &= ~(SDRAM_CFG_MEM_EN);
+ out_be32(&ddr->sdram_cfg, temp_sdram_cfg);
+ /*
+ * For 8572 DDR1 erratum - DDR controller may enter illegal state
+ * when operatiing in 32-bit bus mode with 4-beat bursts,
+ * This erratum does not affect DDR3 mode, only for DDR2 mode.
+ */
+#ifdef CONFIG_MPC8572
+ if ((((in_be32(&ddr->sdram_cfg) >> 24) & 0x7) == SDRAM_TYPE_DDR2)
+ && in_be32(&ddr->sdram_cfg) & 0x80000) {
+ /* set DEBUG_1[31] */
+ u32 temp = in_be32(&ddr->debug_1);
+ out_be32(&ddr->debug_1, temp | 1);
+ }
+#endif
+
+ /*
+ * 500 painful micro-seconds must elapse between
+ * the DDR clock setup and the DDR config enable.
+ * DDR2 need 200 us, and DDR3 need 500 us from spec,
+ * we choose the max, that is 500 us for all of case.
+ */
+ udelay(500);
+ asm volatile("sync;isync");
+
+ /* Let the controller go */
+ temp_sdram_cfg = in_be32(&ddr->sdram_cfg);
+ out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN);
+
+ /* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done. */
+ while (in_be32(&ddr->sdram_cfg_2) & 0x10) {
+ udelay(10000); /* throttle polling rate */
+ }
+}
diff --git a/arch/ppc/cpu/mpc85xx/ether_fcc.c b/arch/ppc/cpu/mpc85xx/ether_fcc.c
new file mode 100644
index 0000000..5f1414d
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/ether_fcc.c
@@ -0,0 +1,469 @@
+/*
+ * MPC8560 FCC Fast Ethernet
+ * Copyright (c) 2003 Motorola,Inc.
+ * Xianghua Xiao, (X.Xiao@motorola.com)
+ *
+ * Copyright (c) 2000 MontaVista Software, Inc. Dan Malek (dmalek@jlc.net)
+ *
+ * (C) Copyright 2000 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * MPC8560 FCC Fast Ethernet
+ * Basic ET HW initialization and packet RX/TX routines
+ *
+ * This code will not perform the IO port configuration. This should be
+ * done in the iop_conf_t structure specific for the board.
+ *
+ * TODO:
+ * add a PHY driver to do the negotiation
+ * reflect negotiation results in FPSMR
+ * look for ways to configure the board specific stuff elsewhere, eg.
+ * config_xxx.h or the board directory
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/cpm_85xx.h>
+#include <command.h>
+#include <config.h>
+#include <net.h>
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+#include <miiphy.h>
+#endif
+
+#if defined(CONFIG_ETHER_ON_FCC) && defined(CONFIG_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,
+ CONFIG_SYS_CMXFCR_MASK1,
+ CONFIG_SYS_CMXFCR_VALUE1
+},
+#endif
+
+#ifdef CONFIG_ETHER_ON_FCC2
+{
+ 1,
+ PROFF_FCC2,
+ CPM_CR_FCC2_SBLOCK,
+ CPM_CR_FCC2_PAGE,
+ CONFIG_SYS_CMXFCR_MASK2,
+ CONFIG_SYS_CMXFCR_VALUE2
+},
+#endif
+
+#ifdef CONFIG_ETHER_ON_FCC3
+{
+ 2,
+ PROFF_FCC3,
+ CPM_CR_FCC3_SBLOCK,
+ CPM_CR_FCC3_PAGE,
+ CONFIG_SYS_CMXFCR_MASK3,
+ CONFIG_SYS_CMXFCR_VALUE3
+},
+#endif
+};
+
+/*---------------------------------------------------------------------*/
+
+/* Maximum input DMA size. Must be a should(?) be a multiple of 4. */
+#define PKT_MAXDMA_SIZE 1520
+
+/* The FCC stores dest/src/type, data, and checksum for receive packets. */
+#define PKT_MAXBUF_SIZE 1518
+#define PKT_MINBUF_SIZE 64
+
+/* Maximum input buffer size. Must be a multiple of 32. */
+#define PKT_MAXBLR_SIZE 1536
+
+#define TOUT_LOOP 1000000
+
+#define TX_BUF_CNT 2
+
+static uint rxIdx; /* index of the current RX buffer */
+static uint txIdx; /* index of the current TX buffer */
+
+/*
+ * FCC Ethernet Tx and Rx buffer descriptors.
+ * Provide for Double Buffering
+ * Note: PKTBUFSRX is defined in net.h
+ */
+
+typedef volatile struct rtxbd {
+ cbd_t rxbd[PKTBUFSRX];
+ cbd_t txbd[TX_BUF_CNT];
+} RTXBD;
+
+/* Good news: the FCC supports external BDs! */
+#ifdef __GNUC__
+static RTXBD rtx __attribute__ ((aligned(8)));
+#else
+#error "rtx must be 64-bit aligned"
+#endif
+
+#undef ET_DEBUG
+
+static int fec_send(struct eth_device* dev, volatile void *packet, int length)
+{
+ int i = 0;
+ int result = 0;
+
+ if (length <= 0) {
+ printf("fec: bad packet size: %d\n", length);
+ goto out;
+ }
+
+ for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
+ if (i >= TOUT_LOOP) {
+ printf("fec: tx buffer not ready\n");
+ goto out;
+ }
+ }
+
+ rtx.txbd[txIdx].cbd_bufaddr = (uint)packet;
+ rtx.txbd[txIdx].cbd_datlen = length;
+ rtx.txbd[txIdx].cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_LAST | \
+ BD_ENET_TX_TC | BD_ENET_TX_PAD);
+
+ for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
+ if (i >= TOUT_LOOP) {
+ printf("fec: tx error\n");
+ goto out;
+ }
+ }
+
+#ifdef ET_DEBUG
+ printf("cycles: 0x%x txIdx=0x%04x status: 0x%04x\n", i, txIdx,rtx.txbd[txIdx].cbd_sc);
+ printf("packets at 0x%08x, length_in_bytes=0x%x\n",(uint)packet,length);
+ for(i=0;i<(length/16 + 1);i++) {
+ printf("%08x %08x %08x %08x\n",*((uint *)rtx.txbd[txIdx].cbd_bufaddr+i*4),\
+ *((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 1),*((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 2), \
+ *((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 3));
+ }
+#endif
+
+ /* return only status bits */
+ result = rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_STATS;
+ txIdx = (txIdx + 1) % TX_BUF_CNT;
+
+out:
+ return result;
+}
+
+static int fec_recv(struct eth_device* dev)
+{
+ int length;
+
+ for (;;)
+ {
+ if (rtx.rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
+ length = -1;
+ break; /* nothing received - leave for() loop */
+ }
+ length = rtx.rxbd[rxIdx].cbd_datlen;
+
+ if (rtx.rxbd[rxIdx].cbd_sc & 0x003f) {
+ printf("fec: rx error %04x\n", rtx.rxbd[rxIdx].cbd_sc);
+ }
+ else {
+ /* Pass the packet up to the protocol layers. */
+ NetReceive(NetRxPackets[rxIdx], length - 4);
+ }
+
+
+ /* Give the buffer back to the FCC. */
+ rtx.rxbd[rxIdx].cbd_datlen = 0;
+
+ /* wrap around buffer index when necessary */
+ if ((rxIdx + 1) >= PKTBUFSRX) {
+ rtx.rxbd[PKTBUFSRX - 1].cbd_sc = (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
+ rxIdx = 0;
+ }
+ else {
+ rtx.rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
+ rxIdx++;
+ }
+ }
+ return length;
+}
+
+
+static int fec_init(struct eth_device* dev, bd_t *bis)
+{
+ struct ether_fcc_info_s * info = dev->priv;
+ int i;
+ volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+ volatile ccsr_cpm_cp_t *cp = &(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 */
+ cpm->im_cpm_mux.cmxuar = 0; /* ATM */
+ cpm->im_cpm_mux.cmxfcr = (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) {
+ cpm->im_cpm_fcc1.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
+ } else if (info->ether_index == 1) {
+ cpm->im_cpm_fcc2.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
+ } else if (info->ether_index == 2) {
+ 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) {
+ cpm->im_cpm_fcc1.fpsmr = CONFIG_SYS_FCC_PSMR | FCC_PSMR_ENCRC;
+ } else if (info->ether_index == 1){
+ cpm->im_cpm_fcc2.fpsmr = CONFIG_SYS_FCC_PSMR | FCC_PSMR_ENCRC;
+ } else if (info->ether_index == 2){
+ cpm->im_cpm_fcc3.fpsmr = CONFIG_SYS_FCC_PSMR | FCC_PSMR_ENCRC;
+ }
+
+ /* 28.9 - (6): FDSR: Ethernet Syn */
+ if(info->ether_index == 0) {
+ cpm->im_cpm_fcc1.fdsr = 0xD555;
+ } else if (info->ether_index == 1) {
+ cpm->im_cpm_fcc2.fdsr = 0xD555;
+ } else if (info->ether_index == 2) {
+ 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 *)&(cpm->im_dprambase[info->proff_enet]);
+
+ /* clear whole structure to make sure all reserved fields are zero */
+ memset((void*)pram_ptr, 0, sizeof(fcc_enet_t));
+
+ /*
+ * common Parameter RAM area
+ *
+ * Allocate space in the reserved FCC area of DPRAM for the
+ * internal buffers. No one uses this space (yet), so we
+ * can do this. Later, we will add resource management for
+ * this area.
+ * CPM_FCC_SPECIAL_BASE: 0xB000 for MPC8540, MPC8560
+ * 0x9000 for MPC8541, MPC8555
+ */
+ mem_addr = CPM_FCC_SPECIAL_BASE + ((info->ether_index) * 64);
+ pram_ptr->fen_genfcc.fcc_riptr = mem_addr;
+ pram_ptr->fen_genfcc.fcc_tiptr = mem_addr+32;
+ /*
+ * Set maximum bytes per receive buffer.
+ * It must be a multiple of 32.
+ */
+ pram_ptr->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE; /* 1536 */
+ /* localbus SDRAM should be preferred */
+ pram_ptr->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB |
+ CONFIG_SYS_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 |
+ CONFIG_SYS_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) {
+ cpm->im_cpm_fcc1.fcce = ~0x0;
+ cpm->im_cpm_fcc1.fccm = 0;
+ } else if (info->ether_index == 1) {
+ cpm->im_cpm_fcc2.fcce = ~0x0;
+ cpm->im_cpm_fcc2.fccm = 0;
+ } else if (info->ether_index == 2) {
+ cpm->im_cpm_fcc3.fcce = ~0x0;
+ 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) {
+ cpm->im_cpm_fcc1.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
+ } else if (info->ether_index == 1) {
+ cpm->im_cpm_fcc2.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
+ } else if (info->ether_index == 2) {
+ cpm->im_cpm_fcc3.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
+ }
+
+ return 1;
+}
+
+static void fec_halt(struct eth_device* dev)
+{
+ struct ether_fcc_info_s * info = dev->priv;
+ volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+
+ /* write GFMR: disable tx/rx */
+ if(info->ether_index == 0) {
+ cpm->im_cpm_fcc1.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
+ } else if(info->ether_index == 1) {
+ cpm->im_cpm_fcc2.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
+ } else if(info->ether_index == 2) {
+ cpm->im_cpm_fcc3.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
+ }
+}
+
+int fec_initialize(bd_t *bis)
+{
+ struct eth_device* dev;
+ int i;
+
+ for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++)
+ {
+ dev = (struct eth_device*) malloc(sizeof *dev);
+ memset(dev, 0, sizeof *dev);
+
+ sprintf(dev->name, "FCC%d ETHERNET",
+ ether_fcc_info[i].ether_index + 1);
+ dev->priv = &ether_fcc_info[i];
+ dev->init = fec_init;
+ dev->halt = fec_halt;
+ dev->send = fec_send;
+ dev->recv = fec_recv;
+
+ eth_register(dev);
+
+#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) \
+ && defined(CONFIG_BITBANGMII)
+ miiphy_register(dev->name,
+ bb_miiphy_read, bb_miiphy_write);
+#endif
+ }
+
+ return 1;
+}
+
+#endif
diff --git a/arch/ppc/cpu/mpc85xx/fdt.c b/arch/ppc/cpu/mpc85xx/fdt.c
new file mode 100644
index 0000000..1d11ab4
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/fdt.c
@@ -0,0 +1,417 @@
+/*
+ * Copyright 2007-2009 Freescale Semiconductor, Inc.
+ *
+ * (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 <libfdt.h>
+#include <fdt_support.h>
+#include <asm/processor.h>
+#include <linux/ctype.h>
+#ifdef CONFIG_FSL_ESDHC
+#include <fsl_esdhc.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+extern void ft_qe_setup(void *blob);
+extern void ft_fixup_num_cores(void *blob);
+
+#ifdef CONFIG_MP
+#include "mp.h"
+
+void ft_fixup_cpu(void *blob, u64 memory_limit)
+{
+ int off;
+ ulong spin_tbl_addr = get_spin_phys_addr();
+ u32 bootpg = determine_mp_bootpg();
+ u32 id = get_my_id();
+
+ off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
+ while (off != -FDT_ERR_NOTFOUND) {
+ u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0);
+
+ if (reg) {
+ if (*reg == id) {
+ fdt_setprop_string(blob, off, "status", "okay");
+ } else {
+ u64 val = *reg * SIZE_BOOT_ENTRY + spin_tbl_addr;
+ val = cpu_to_fdt32(val);
+ fdt_setprop_string(blob, off, "status",
+ "disabled");
+ fdt_setprop_string(blob, off, "enable-method",
+ "spin-table");
+ fdt_setprop(blob, off, "cpu-release-addr",
+ &val, sizeof(val));
+ }
+ } else {
+ printf ("cpu NULL\n");
+ }
+ off = fdt_node_offset_by_prop_value(blob, off,
+ "device_type", "cpu", 4);
+ }
+
+ /* Reserve the boot page so OSes dont use it */
+ if ((u64)bootpg < memory_limit) {
+ off = fdt_add_mem_rsv(blob, bootpg, (u64)4096);
+ if (off < 0)
+ printf("%s: %s\n", __FUNCTION__, fdt_strerror(off));
+ }
+}
+#endif
+
+#define ft_fixup_l3cache(x, y)
+
+#if defined(CONFIG_L2_CACHE)
+/* return size in kilobytes */
+static inline u32 l2cache_size(void)
+{
+ volatile ccsr_l2cache_t *l2cache = (void *)CONFIG_SYS_MPC85xx_L2_ADDR;
+ volatile u32 l2siz_field = (l2cache->l2ctl >> 28) & 0x3;
+ u32 ver = SVR_SOC_VER(get_svr());
+
+ switch (l2siz_field) {
+ case 0x0:
+ break;
+ case 0x1:
+ if (ver == SVR_8540 || ver == SVR_8560 ||
+ ver == SVR_8541 || ver == SVR_8541_E ||
+ ver == SVR_8555 || ver == SVR_8555_E)
+ return 128;
+ else
+ return 256;
+ break;
+ case 0x2:
+ if (ver == SVR_8540 || ver == SVR_8560 ||
+ ver == SVR_8541 || ver == SVR_8541_E ||
+ ver == SVR_8555 || ver == SVR_8555_E)
+ return 256;
+ else
+ return 512;
+ break;
+ case 0x3:
+ return 1024;
+ break;
+ }
+
+ return 0;
+}
+
+static inline void ft_fixup_l2cache(void *blob)
+{
+ int len, off;
+ u32 *ph;
+ struct cpu_type *cpu = identify_cpu(SVR_SOC_VER(get_svr()));
+ char compat_buf[38];
+
+ const u32 line_size = 32;
+ const u32 num_ways = 8;
+ const u32 size = l2cache_size() * 1024;
+ const u32 num_sets = size / (line_size * num_ways);
+
+ off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
+ if (off < 0) {
+ debug("no cpu node fount\n");
+ return;
+ }
+
+ ph = (u32 *)fdt_getprop(blob, off, "next-level-cache", 0);
+
+ if (ph == NULL) {
+ debug("no next-level-cache property\n");
+ return ;
+ }
+
+ off = fdt_node_offset_by_phandle(blob, *ph);
+ if (off < 0) {
+ printf("%s: %s\n", __func__, fdt_strerror(off));
+ return ;
+ }
+
+ if (cpu) {
+ if (isdigit(cpu->name[0]))
+ len = sprintf(compat_buf,
+ "fsl,mpc%s-l2-cache-controller", cpu->name);
+ else
+ len = sprintf(compat_buf,
+ "fsl,%c%s-l2-cache-controller",
+ tolower(cpu->name[0]), cpu->name + 1);
+
+ sprintf(&compat_buf[len + 1], "cache");
+ }
+ fdt_setprop(blob, off, "cache-unified", NULL, 0);
+ fdt_setprop_cell(blob, off, "cache-block-size", line_size);
+ fdt_setprop_cell(blob, off, "cache-size", size);
+ fdt_setprop_cell(blob, off, "cache-sets", num_sets);
+ fdt_setprop_cell(blob, off, "cache-level", 2);
+ fdt_setprop(blob, off, "compatible", compat_buf, sizeof(compat_buf));
+
+ /* we dont bother w/L3 since no platform of this type has one */
+}
+#elif defined(CONFIG_BACKSIDE_L2_CACHE)
+static inline void ft_fixup_l2cache(void *blob)
+{
+ int off, l2_off, l3_off = -1;
+ u32 *ph;
+ u32 l2cfg0 = mfspr(SPRN_L2CFG0);
+ u32 size, line_size, num_ways, num_sets;
+
+ size = (l2cfg0 & 0x3fff) * 64 * 1024;
+ num_ways = ((l2cfg0 >> 14) & 0x1f) + 1;
+ line_size = (((l2cfg0 >> 23) & 0x3) + 1) * 32;
+ num_sets = size / (line_size * num_ways);
+
+ off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
+
+ while (off != -FDT_ERR_NOTFOUND) {
+ ph = (u32 *)fdt_getprop(blob, off, "next-level-cache", 0);
+
+ if (ph == NULL) {
+ debug("no next-level-cache property\n");
+ goto next;
+ }
+
+ l2_off = fdt_node_offset_by_phandle(blob, *ph);
+ if (l2_off < 0) {
+ printf("%s: %s\n", __func__, fdt_strerror(off));
+ goto next;
+ }
+
+#ifdef CONFIG_SYS_CACHE_STASHING
+ {
+ u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0);
+ if (reg)
+ fdt_setprop_cell(blob, l2_off, "cache-stash-id",
+ (*reg * 2) + 32 + 1);
+ }
+#endif
+
+ fdt_setprop(blob, l2_off, "cache-unified", NULL, 0);
+ fdt_setprop_cell(blob, l2_off, "cache-block-size", line_size);
+ fdt_setprop_cell(blob, l2_off, "cache-size", size);
+ fdt_setprop_cell(blob, l2_off, "cache-sets", num_sets);
+ fdt_setprop_cell(blob, l2_off, "cache-level", 2);
+ fdt_setprop(blob, l2_off, "compatible", "cache", 6);
+
+ if (l3_off < 0) {
+ ph = (u32 *)fdt_getprop(blob, l2_off, "next-level-cache", 0);
+
+ if (ph == NULL) {
+ debug("no next-level-cache property\n");
+ goto next;
+ }
+ l3_off = *ph;
+ }
+next:
+ off = fdt_node_offset_by_prop_value(blob, off,
+ "device_type", "cpu", 4);
+ }
+ if (l3_off > 0) {
+ l3_off = fdt_node_offset_by_phandle(blob, l3_off);
+ if (l3_off < 0) {
+ printf("%s: %s\n", __func__, fdt_strerror(off));
+ return ;
+ }
+ ft_fixup_l3cache(blob, l3_off);
+ }
+}
+#else
+#define ft_fixup_l2cache(x)
+#endif
+
+static inline void ft_fixup_cache(void *blob)
+{
+ int off;
+
+ off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
+
+ while (off != -FDT_ERR_NOTFOUND) {
+ u32 l1cfg0 = mfspr(SPRN_L1CFG0);
+ u32 l1cfg1 = mfspr(SPRN_L1CFG1);
+ u32 isize, iline_size, inum_sets, inum_ways;
+ u32 dsize, dline_size, dnum_sets, dnum_ways;
+
+ /* d-side config */
+ dsize = (l1cfg0 & 0x7ff) * 1024;
+ dnum_ways = ((l1cfg0 >> 11) & 0xff) + 1;
+ dline_size = (((l1cfg0 >> 23) & 0x3) + 1) * 32;
+ dnum_sets = dsize / (dline_size * dnum_ways);
+
+ fdt_setprop_cell(blob, off, "d-cache-block-size", dline_size);
+ fdt_setprop_cell(blob, off, "d-cache-size", dsize);
+ fdt_setprop_cell(blob, off, "d-cache-sets", dnum_sets);
+
+#ifdef CONFIG_SYS_CACHE_STASHING
+ {
+ u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0);
+ if (reg)
+ fdt_setprop_cell(blob, off, "cache-stash-id",
+ (*reg * 2) + 32 + 0);
+ }
+#endif
+
+ /* i-side config */
+ isize = (l1cfg1 & 0x7ff) * 1024;
+ inum_ways = ((l1cfg1 >> 11) & 0xff) + 1;
+ iline_size = (((l1cfg1 >> 23) & 0x3) + 1) * 32;
+ inum_sets = isize / (iline_size * inum_ways);
+
+ fdt_setprop_cell(blob, off, "i-cache-block-size", iline_size);
+ fdt_setprop_cell(blob, off, "i-cache-size", isize);
+ fdt_setprop_cell(blob, off, "i-cache-sets", inum_sets);
+
+ off = fdt_node_offset_by_prop_value(blob, off,
+ "device_type", "cpu", 4);
+ }
+
+ ft_fixup_l2cache(blob);
+}
+
+
+void fdt_add_enet_stashing(void *fdt)
+{
+ do_fixup_by_compat(fdt, "gianfar", "bd-stash", NULL, 0, 1);
+
+ do_fixup_by_compat_u32(fdt, "gianfar", "rx-stash-len", 96, 1);
+
+ do_fixup_by_compat_u32(fdt, "gianfar", "rx-stash-idx", 0, 1);
+}
+
+#if defined(CONFIG_SYS_DPAA_FMAN) || defined(CONFIG_SYS_DPAA_PME)
+static void ft_fixup_clks(void *blob, const char *alias, unsigned long freq)
+{
+ const char *path = fdt_get_alias(blob, alias);
+
+ int off = fdt_path_offset(blob, path);
+
+ if (off >= 0) {
+ off = fdt_setprop_cell(blob, off, "clock-frequency", freq);
+ if (off > 0)
+ printf("WARNING enable to set clock-frequency "
+ "for %s: %s\n", alias, fdt_strerror(off));
+ }
+}
+
+static void ft_fixup_dpaa_clks(void *blob)
+{
+ sys_info_t sysinfo;
+
+ get_sys_info(&sysinfo);
+ ft_fixup_clks(blob, "fman0", sysinfo.freqFMan[0]);
+
+#if (CONFIG_SYS_NUM_FMAN == 2)
+ ft_fixup_clks(blob, "fman1", sysinfo.freqFMan[1]);
+#endif
+
+#ifdef CONFIG_SYS_DPAA_PME
+ ft_fixup_clks(blob, "pme", sysinfo.freqPME);
+#endif
+}
+#else
+#define ft_fixup_dpaa_clks(x)
+#endif
+
+#ifdef CONFIG_QE
+static void ft_fixup_qe_snum(void *blob)
+{
+ unsigned int svr;
+
+ svr = mfspr(SPRN_SVR);
+ if (SVR_SOC_VER(svr) == SVR_8569_E) {
+ if(IS_SVR_REV(svr, 1, 0))
+ do_fixup_by_compat_u32(blob, "fsl,qe",
+ "fsl,qe-num-snums", 46, 1);
+ else
+ do_fixup_by_compat_u32(blob, "fsl,qe",
+ "fsl,qe-num-snums", 76, 1);
+ }
+}
+#endif
+
+void ft_cpu_setup(void *blob, bd_t *bd)
+{
+ int off;
+ int val;
+ sys_info_t sysinfo;
+
+ /* delete crypto node if not on an E-processor */
+ if (!IS_E_PROCESSOR(get_svr()))
+ fdt_fixup_crypto_node(blob, 0);
+
+ fdt_fixup_ethernet(blob);
+
+ fdt_add_enet_stashing(blob);
+
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+ "timebase-frequency", get_tbclk(), 1);
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+ "bus-frequency", bd->bi_busfreq, 1);
+ get_sys_info(&sysinfo);
+ off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
+ while (off != -FDT_ERR_NOTFOUND) {
+ u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0);
+ val = cpu_to_fdt32(sysinfo.freqProcessor[*reg]);
+ fdt_setprop(blob, off, "clock-frequency", &val, 4);
+ off = fdt_node_offset_by_prop_value(blob, off, "device_type",
+ "cpu", 4);
+ }
+ do_fixup_by_prop_u32(blob, "device_type", "soc", 4,
+ "bus-frequency", bd->bi_busfreq, 1);
+
+ do_fixup_by_compat_u32(blob, "fsl,pq3-localbus",
+ "bus-frequency", gd->lbc_clk, 1);
+ do_fixup_by_compat_u32(blob, "fsl,elbc",
+ "bus-frequency", gd->lbc_clk, 1);
+#ifdef CONFIG_QE
+ ft_qe_setup(blob);
+ ft_fixup_qe_snum(blob);
+#endif
+
+#ifdef CONFIG_SYS_NS16550
+ do_fixup_by_compat_u32(blob, "ns16550",
+ "clock-frequency", CONFIG_SYS_NS16550_CLK, 1);
+#endif
+
+#ifdef CONFIG_CPM2
+ do_fixup_by_compat_u32(blob, "fsl,cpm2-scc-uart",
+ "current-speed", bd->bi_baudrate, 1);
+
+ do_fixup_by_compat_u32(blob, "fsl,cpm2-brg",
+ "clock-frequency", bd->bi_brgfreq, 1);
+#endif
+
+ fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
+
+#ifdef CONFIG_MP
+ ft_fixup_cpu(blob, (u64)bd->bi_memstart + (u64)bd->bi_memsize);
+#endif
+ ft_fixup_num_cores(blob);
+
+ ft_fixup_cache(blob);
+
+#if defined(CONFIG_FSL_ESDHC)
+ fdt_fixup_esdhc(blob, bd);
+#endif
+
+ ft_fixup_dpaa_clks(blob);
+}
diff --git a/arch/ppc/cpu/mpc85xx/fixed_ivor.S b/arch/ppc/cpu/mpc85xx/fixed_ivor.S
new file mode 100644
index 0000000..320cae3
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/fixed_ivor.S
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * Kumar Gala <kumar.gala@freescale.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* This file is intended to be included by other asm code since
+ * we will want to execute this on both the primary core when
+ * it does a bootm and the secondary core's that get released
+ * out of the spin table */
+
+#define SET_IVOR(vector_number, vector_offset) \
+ li r3,vector_offset@l; \
+ mtspr SPRN_IVOR##vector_number,r3;
+
+#define SET_GIVOR(vector_number, vector_offset) \
+ li r3,vector_offset@l; \
+ mtspr SPRN_GIVOR##vector_number,r3;
+
+ SET_IVOR(0, 0x020) /* Critical Input */
+ SET_IVOR(1, 0x000) /* Machine Check */
+ SET_IVOR(2, 0x060) /* Data Storage */
+ SET_IVOR(3, 0x080) /* Instruction Storage */
+ SET_IVOR(4, 0x0a0) /* External Input */
+ SET_IVOR(5, 0x0c0) /* Alignment */
+ SET_IVOR(6, 0x0e0) /* Program */
+ SET_IVOR(7, 0x100) /* FP Unavailable */
+ SET_IVOR(8, 0x120) /* System Call */
+ SET_IVOR(9, 0x140) /* Auxiliary Processor Unavailable */
+ SET_IVOR(10, 0x160) /* Decrementer */
+ SET_IVOR(11, 0x180) /* Fixed Interval Timer */
+ SET_IVOR(12, 0x1a0) /* Watchdog Timer */
+ SET_IVOR(13, 0x1c0) /* Data TLB Error */
+ SET_IVOR(14, 0x1e0) /* Instruction TLB Error */
+ SET_IVOR(15, 0x040) /* Debug */
+
+/* e500v1 & e500v2 only */
+#ifndef CONFIG_E500MC
+ SET_IVOR(32, 0x200) /* SPE Unavailable */
+ SET_IVOR(33, 0x220) /* Embedded FP Data */
+ SET_IVOR(34, 0x240) /* Embedded FP Round */
+#endif
+
+ SET_IVOR(35, 0x260) /* Performance monitor */
+
+/* e500mc only */
+#ifdef CONFIG_E500MC
+ SET_IVOR(36, 0x280) /* Processor doorbell */
+ SET_IVOR(37, 0x2a0) /* Processor doorbell critical */
+ SET_IVOR(38, 0x2c0) /* Guest Processor doorbell */
+ SET_IVOR(39, 0x2e0) /* Guest Processor critical & machine check */
+ SET_IVOR(40, 0x300) /* Hypervisor system call */
+ SET_IVOR(41, 0x320) /* Hypervisor Priviledge */
+
+ SET_GIVOR(2, 0x060) /* Guest Data Storage */
+ SET_GIVOR(3, 0x080) /* Guest Instruction Storage */
+ SET_GIVOR(4, 0x0a0) /* Guest External Input */
+ SET_GIVOR(8, 0x120) /* Guest System Call */
+ SET_GIVOR(13, 0x1c0) /* Guest Data TLB Error */
+ SET_GIVOR(14, 0x1e0) /* Guest Instruction TLB Error */
+#endif
diff --git a/arch/ppc/cpu/mpc85xx/interrupts.c b/arch/ppc/cpu/mpc85xx/interrupts.c
new file mode 100644
index 0000000..409367d
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/interrupts.c
@@ -0,0 +1,110 @@
+/*
+ * (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 <asm/io.h>
+
+int interrupt_init_cpu(unsigned int *decrementer_count)
+{
+ ccsr_pic_t __iomem *pic = (void *)CONFIG_SYS_MPC85xx_PIC_ADDR;
+
+ out_be32(&pic->gcr, MPC85xx_PICGCR_RST);
+ while (in_be32(&pic->gcr) & MPC85xx_PICGCR_RST)
+ ;
+ out_be32(&pic->gcr, MPC85xx_PICGCR_M);
+ in_be32(&pic->gcr);
+
+ *decrementer_count = get_tbclk() / CONFIG_SYS_HZ;
+
+ /* PIE is same as DIE, dec interrupt enable */
+ mtspr(SPRN_TCR, TCR_PIE);
+
+#ifdef CONFIG_INTERRUPTS
+ pic->iivpr1 = 0x810001; /* 50220 enable ecm interrupts */
+ debug("iivpr1@%x = %x\n", (uint)&pic->iivpr1, pic->iivpr1);
+
+ pic->iivpr2 = 0x810002; /* 50240 enable ddr interrupts */
+ debug("iivpr2@%x = %x\n", (uint)&pic->iivpr2, pic->iivpr2);
+
+ pic->iivpr3 = 0x810003; /* 50260 enable lbc interrupts */
+ debug("iivpr3@%x = %x\n", (uint)&pic->iivpr3, pic->iivpr3);
+
+#ifdef CONFIG_PCI1
+ pic->iivpr8 = 0x810008; /* enable pci1 interrupts */
+ debug("iivpr8@%x = %x\n", (uint)&pic->iivpr8, pic->iivpr8);
+#endif
+#if defined(CONFIG_PCI2) || defined(CONFIG_PCIE2)
+ pic->iivpr9 = 0x810009; /* enable pci1 interrupts */
+ debug("iivpr9@%x = %x\n", (uint)&pic->iivpr9, pic->iivpr9);
+#endif
+#ifdef CONFIG_PCIE1
+ pic->iivpr10 = 0x81000a; /* enable pcie1 interrupts */
+ debug("iivpr10@%x = %x\n", (uint)&pic->iivpr10, pic->iivpr10);
+#endif
+#ifdef CONFIG_PCIE3
+ pic->iivpr11 = 0x81000b; /* enable pcie3 interrupts */
+ debug("iivpr11@%x = %x\n", (uint)&pic->iivpr11, pic->iivpr11);
+#endif
+
+ pic->ctpr=0; /* 40080 clear current task priority register */
+#endif
+
+ 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;
+}
+
+void timer_interrupt_cpu(struct pt_regs *regs)
+{
+ /* PIS is same as DIS, dec interrupt status */
+ mtspr(SPRN_TSR, TSR_PIS);
+}
+
+#if defined(CONFIG_CMD_IRQ)
+/* irqinfo - print information about PCI devices,not implemented. */
+int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ return 0;
+}
+#endif
diff --git a/arch/ppc/cpu/mpc85xx/mp.c b/arch/ppc/cpu/mpc85xx/mp.c
new file mode 100644
index 0000000..826bf32
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/mp.c
@@ -0,0 +1,355 @@
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <ioports.h>
+#include <lmb.h>
+#include <asm/io.h>
+#include <asm/mmu.h>
+#include <asm/fsl_law.h>
+#include "mp.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+u32 get_my_id()
+{
+ return mfspr(SPRN_PIR);
+}
+
+int cpu_reset(int nr)
+{
+ volatile ccsr_pic_t *pic = (void *)(CONFIG_SYS_MPC85xx_PIC_ADDR);
+ out_be32(&pic->pir, 1 << nr);
+ /* the dummy read works around an errata on early 85xx MP PICs */
+ (void)in_be32(&pic->pir);
+ out_be32(&pic->pir, 0x0);
+
+ return 0;
+}
+
+int cpu_status(int nr)
+{
+ u32 *table, id = get_my_id();
+
+ if (nr == id) {
+ table = (u32 *)get_spin_virt_addr();
+ printf("table base @ 0x%p\n", table);
+ } else {
+ table = (u32 *)get_spin_virt_addr() + nr * NUM_BOOT_ENTRY;
+ printf("Running on cpu %d\n", id);
+ printf("\n");
+ printf("table @ 0x%p\n", table);
+ printf(" addr - 0x%08x\n", table[BOOT_ENTRY_ADDR_LOWER]);
+ printf(" pir - 0x%08x\n", table[BOOT_ENTRY_PIR]);
+ printf(" r3 - 0x%08x\n", table[BOOT_ENTRY_R3_LOWER]);
+ printf(" r6 - 0x%08x\n", table[BOOT_ENTRY_R6_LOWER]);
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_FSL_CORENET
+int cpu_disable(int nr)
+{
+ volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+
+ setbits_be32(&gur->coredisrl, 1 << nr);
+
+ return 0;
+}
+#else
+int cpu_disable(int nr)
+{
+ volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+
+ switch (nr) {
+ case 0:
+ setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_CPU0);
+ break;
+ case 1:
+ setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_CPU1);
+ break;
+ default:
+ printf("Invalid cpu number for disable %d\n", nr);
+ return 1;
+ }
+
+ return 0;
+}
+#endif
+
+static u8 boot_entry_map[4] = {
+ 0,
+ BOOT_ENTRY_PIR,
+ BOOT_ENTRY_R3_LOWER,
+ BOOT_ENTRY_R6_LOWER,
+};
+
+int cpu_release(int nr, int argc, char *argv[])
+{
+ u32 i, val, *table = (u32 *)get_spin_virt_addr() + nr * NUM_BOOT_ENTRY;
+ u64 boot_addr;
+
+ if (nr == get_my_id()) {
+ printf("Invalid to release the boot core.\n\n");
+ return 1;
+ }
+
+ if (argc != 4) {
+ printf("Invalid number of arguments to release.\n\n");
+ return 1;
+ }
+
+ boot_addr = simple_strtoull(argv[0], NULL, 16);
+
+ /* handle pir, r3, r6 */
+ for (i = 1; i < 4; i++) {
+ if (argv[i][0] != '-') {
+ u8 entry = boot_entry_map[i];
+ val = simple_strtoul(argv[i], NULL, 16);
+ table[entry] = val;
+ }
+ }
+
+ table[BOOT_ENTRY_ADDR_UPPER] = (u32)(boot_addr >> 32);
+
+ /* ensure all table updates complete before final address write */
+ eieio();
+
+ table[BOOT_ENTRY_ADDR_LOWER] = (u32)(boot_addr & 0xffffffff);
+
+ return 0;
+}
+
+u32 determine_mp_bootpg(void)
+{
+ /* if we have 4G or more of memory, put the boot page at 4Gb-4k */
+ if ((u64)gd->ram_size > 0xfffff000)
+ return (0xfffff000);
+
+ return (gd->ram_size - 4096);
+}
+
+ulong get_spin_phys_addr(void)
+{
+ extern ulong __secondary_start_page;
+ extern ulong __spin_table;
+
+ return (determine_mp_bootpg() +
+ (ulong)&__spin_table - (ulong)&__secondary_start_page);
+}
+
+ulong get_spin_virt_addr(void)
+{
+ extern ulong __secondary_start_page;
+ extern ulong __spin_table;
+
+ return (CONFIG_BPTR_VIRT_ADDR +
+ (ulong)&__spin_table - (ulong)&__secondary_start_page);
+}
+
+#ifdef CONFIG_FSL_CORENET
+static void plat_mp_up(unsigned long bootpg)
+{
+ u32 up, cpu_up_mask, whoami;
+ u32 *table = (u32 *)get_spin_virt_addr();
+ volatile ccsr_gur_t *gur;
+ volatile ccsr_local_t *ccm;
+ volatile ccsr_rcpm_t *rcpm;
+ volatile ccsr_pic_t *pic;
+ int timeout = 10;
+ u32 nr_cpus;
+ struct law_entry e;
+
+ gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ ccm = (void *)(CONFIG_SYS_FSL_CORENET_CCM_ADDR);
+ rcpm = (void *)(CONFIG_SYS_FSL_CORENET_RCPM_ADDR);
+ pic = (void *)(CONFIG_SYS_MPC85xx_PIC_ADDR);
+
+ nr_cpus = ((in_be32(&pic->frr) >> 8) & 0xff) + 1;
+
+ whoami = in_be32(&pic->whoami);
+ cpu_up_mask = 1 << whoami;
+ out_be32(&ccm->bstrl, bootpg);
+
+ e = find_law(bootpg);
+ out_be32(&ccm->bstrar, LAW_EN | e.trgt_id << 20 | LAW_SIZE_4K);
+
+ /* readback to sync write */
+ in_be32(&ccm->bstrar);
+
+ /* disable time base at the platform */
+ out_be32(&rcpm->ctbenrl, cpu_up_mask);
+
+ /* release the hounds */
+ up = ((1 << nr_cpus) - 1);
+ out_be32(&gur->brrl, up);
+
+ /* wait for everyone */
+ while (timeout) {
+ int i;
+ for (i = 0; i < nr_cpus; i++) {
+ if (table[i * NUM_BOOT_ENTRY + BOOT_ENTRY_ADDR_LOWER])
+ cpu_up_mask |= (1 << i);
+ };
+
+ if ((cpu_up_mask & up) == up)
+ break;
+
+ udelay(100);
+ timeout--;
+ }
+
+ if (timeout == 0)
+ printf("CPU up timeout. CPU up mask is %x should be %x\n",
+ cpu_up_mask, up);
+
+ /* enable time base at the platform */
+ out_be32(&rcpm->ctbenrl, 0);
+ mtspr(SPRN_TBWU, 0);
+ mtspr(SPRN_TBWL, 0);
+ out_be32(&rcpm->ctbenrl, (1 << nr_cpus) - 1);
+
+#ifdef CONFIG_MPC8xxx_DISABLE_BPTR
+ /*
+ * Disabling Boot Page Translation allows the memory region 0xfffff000
+ * to 0xffffffff to be used normally. Leaving Boot Page Translation
+ * enabled remaps 0xfffff000 to SDRAM which makes that memory region
+ * unusable for normal operation but it does allow OSes to easily
+ * reset a processor core to put it back into U-Boot's spinloop.
+ */
+ clrbits_be32(&ecm->bptr, 0x80000000);
+#endif
+}
+#else
+static void plat_mp_up(unsigned long bootpg)
+{
+ u32 up, cpu_up_mask, whoami;
+ u32 *table = (u32 *)get_spin_virt_addr();
+ volatile u32 bpcr;
+ volatile ccsr_local_ecm_t *ecm = (void *)(CONFIG_SYS_MPC85xx_ECM_ADDR);
+ volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ volatile ccsr_pic_t *pic = (void *)(CONFIG_SYS_MPC85xx_PIC_ADDR);
+ u32 devdisr;
+ int timeout = 10;
+
+ whoami = in_be32(&pic->whoami);
+ out_be32(&ecm->bptr, 0x80000000 | (bootpg >> 12));
+
+ /* disable time base at the platform */
+ devdisr = in_be32(&gur->devdisr);
+ if (whoami)
+ devdisr |= MPC85xx_DEVDISR_TB0;
+ else
+ devdisr |= MPC85xx_DEVDISR_TB1;
+ out_be32(&gur->devdisr, devdisr);
+
+ /* release the hounds */
+ up = ((1 << cpu_numcores()) - 1);
+ bpcr = in_be32(&ecm->eebpcr);
+ bpcr |= (up << 24);
+ out_be32(&ecm->eebpcr, bpcr);
+ asm("sync; isync; msync");
+
+ cpu_up_mask = 1 << whoami;
+ /* wait for everyone */
+ while (timeout) {
+ int i;
+ for (i = 0; i < cpu_numcores(); i++) {
+ if (table[i * NUM_BOOT_ENTRY + BOOT_ENTRY_ADDR_LOWER])
+ cpu_up_mask |= (1 << i);
+ };
+
+ if ((cpu_up_mask & up) == up)
+ break;
+
+ udelay(100);
+ timeout--;
+ }
+
+ if (timeout == 0)
+ printf("CPU up timeout. CPU up mask is %x should be %x\n",
+ cpu_up_mask, up);
+
+ /* enable time base at the platform */
+ if (whoami)
+ devdisr |= MPC85xx_DEVDISR_TB1;
+ else
+ devdisr |= MPC85xx_DEVDISR_TB0;
+ out_be32(&gur->devdisr, devdisr);
+ mtspr(SPRN_TBWU, 0);
+ mtspr(SPRN_TBWL, 0);
+
+ devdisr &= ~(MPC85xx_DEVDISR_TB0 | MPC85xx_DEVDISR_TB1);
+ out_be32(&gur->devdisr, devdisr);
+
+#ifdef CONFIG_MPC8xxx_DISABLE_BPTR
+ /*
+ * Disabling Boot Page Translation allows the memory region 0xfffff000
+ * to 0xffffffff to be used normally. Leaving Boot Page Translation
+ * enabled remaps 0xfffff000 to SDRAM which makes that memory region
+ * unusable for normal operation but it does allow OSes to easily
+ * reset a processor core to put it back into U-Boot's spinloop.
+ */
+ clrbits_be32(&ecm->bptr, 0x80000000);
+#endif
+}
+#endif
+
+void cpu_mp_lmb_reserve(struct lmb *lmb)
+{
+ u32 bootpg = determine_mp_bootpg();
+
+ lmb_reserve(lmb, bootpg, 4096);
+}
+
+void setup_mp(void)
+{
+ extern ulong __secondary_start_page;
+ extern ulong __bootpg_addr;
+ ulong fixup = (ulong)&__secondary_start_page;
+ u32 bootpg = determine_mp_bootpg();
+
+ /* Store the bootpg's SDRAM address for use by secondary CPU cores */
+ __bootpg_addr = bootpg;
+
+ /* look for the tlb covering the reset page, there better be one */
+ int i = find_tlb_idx((void *)CONFIG_BPTR_VIRT_ADDR, 1);
+
+ /* we found a match */
+ if (i != -1) {
+ /* map reset page to bootpg so we can copy code there */
+ disable_tlb(i);
+
+ set_tlb(1, CONFIG_BPTR_VIRT_ADDR, bootpg, /* tlb, epn, rpn */
+ MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G, /* perms, wimge */
+ 0, i, BOOKE_PAGESZ_4K, 1); /* ts, esel, tsize, iprot */
+
+ memcpy((void *)CONFIG_BPTR_VIRT_ADDR, (void *)fixup, 4096);
+
+ plat_mp_up(bootpg);
+ } else {
+ puts("WARNING: No reset page TLB. "
+ "Skipping secondary core setup\n");
+ }
+}
diff --git a/arch/ppc/cpu/mpc85xx/mp.h b/arch/ppc/cpu/mpc85xx/mp.h
new file mode 100644
index 0000000..3422cc1
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/mp.h
@@ -0,0 +1,21 @@
+#ifndef __MPC85XX_MP_H_
+#define __MPC85XX_MP_H_
+
+#include <asm/mp.h>
+
+ulong get_spin_phys_addr(void);
+ulong get_spin_virt_addr(void);
+u32 get_my_id(void);
+
+#define BOOT_ENTRY_ADDR_UPPER 0
+#define BOOT_ENTRY_ADDR_LOWER 1
+#define BOOT_ENTRY_R3_UPPER 2
+#define BOOT_ENTRY_R3_LOWER 3
+#define BOOT_ENTRY_RESV 4
+#define BOOT_ENTRY_PIR 5
+#define BOOT_ENTRY_R6_UPPER 6
+#define BOOT_ENTRY_R6_LOWER 7
+#define NUM_BOOT_ENTRY 8
+#define SIZE_BOOT_ENTRY (NUM_BOOT_ENTRY * sizeof(u32))
+
+#endif
diff --git a/arch/ppc/cpu/mpc85xx/mpc8536_serdes.c b/arch/ppc/cpu/mpc85xx/mpc8536_serdes.c
new file mode 100644
index 0000000..cb6a6f0
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/mpc8536_serdes.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2008 Freescale Semicondutor, Inc.
+ * Dave Liu <daveliu@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/immap_85xx.h>
+
+/* PORDEVSR register */
+#define GUTS_PORDEVSR_OFFS 0xc
+#define GUTS_PORDEVSR_SERDES2_IO_SEL 0x38000000
+#define GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT 27
+
+/* SerDes CR0 register */
+#define FSL_SRDSCR0_OFFS 0x0
+#define FSL_SRDSCR0_TXEQA_MASK 0x00007000
+#define FSL_SRDSCR0_TXEQA_SGMII 0x00004000
+#define FSL_SRDSCR0_TXEQA_SATA 0x00001000
+#define FSL_SRDSCR0_TXEQE_MASK 0x00000700
+#define FSL_SRDSCR0_TXEQE_SGMII 0x00000400
+#define FSL_SRDSCR0_TXEQE_SATA 0x00000100
+
+/* SerDes CR1 register */
+#define FSL_SRDSCR1_OFFS 0x4
+#define FSL_SRDSCR1_LANEA_MASK 0x80200000
+#define FSL_SRDSCR1_LANEA_OFF 0x80200000
+#define FSL_SRDSCR1_LANEE_MASK 0x08020000
+#define FSL_SRDSCR1_LANEE_OFF 0x08020000
+
+/* SerDes CR2 register */
+#define FSL_SRDSCR2_OFFS 0x8
+#define FSL_SRDSCR2_EICA_MASK 0x00001f00
+#define FSL_SRDSCR2_EICA_SGMII 0x00000400
+#define FSL_SRDSCR2_EICA_SATA 0x00001400
+#define FSL_SRDSCR2_EICE_MASK 0x0000001f
+#define FSL_SRDSCR2_EICE_SGMII 0x00000004
+#define FSL_SRDSCR2_EICE_SATA 0x00000014
+
+/* SerDes CR3 register */
+#define FSL_SRDSCR3_OFFS 0xc
+#define FSL_SRDSCR3_LANEA_MASK 0x3f000700
+#define FSL_SRDSCR3_LANEA_SGMII 0x00000000
+#define FSL_SRDSCR3_LANEA_SATA 0x15000500
+#define FSL_SRDSCR3_LANEE_MASK 0x003f0007
+#define FSL_SRDSCR3_LANEE_SGMII 0x00000000
+#define FSL_SRDSCR3_LANEE_SATA 0x00150005
+
+void fsl_serdes_init(void)
+{
+ void *guts = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ void *sd = (void *)CONFIG_SYS_MPC85xx_SERDES2_ADDR;
+ u32 pordevsr = in_be32(guts + GUTS_PORDEVSR_OFFS);
+ u32 srds2_io_sel;
+ u32 tmp;
+
+ /* parse the SRDS2_IO_SEL of PORDEVSR */
+ srds2_io_sel = (pordevsr & GUTS_PORDEVSR_SERDES2_IO_SEL)
+ >> GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT;
+
+ switch (srds2_io_sel) {
+ case 1: /* Lane A - SATA1, Lane E - SATA2 */
+ /* CR 0 */
+ tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
+ tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
+ tmp |= FSL_SRDSCR0_TXEQA_SATA;
+ tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
+ tmp |= FSL_SRDSCR0_TXEQE_SATA;
+ out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
+ /* CR 1 */
+ tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
+ tmp &= ~FSL_SRDSCR1_LANEA_MASK;
+ tmp &= ~FSL_SRDSCR1_LANEE_MASK;
+ out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
+ /* CR 2 */
+ tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
+ tmp &= ~FSL_SRDSCR2_EICA_MASK;
+ tmp |= FSL_SRDSCR2_EICA_SATA;
+ tmp &= ~FSL_SRDSCR2_EICE_MASK;
+ tmp |= FSL_SRDSCR2_EICE_SATA;
+ out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
+ /* CR 3 */
+ tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
+ tmp &= ~FSL_SRDSCR3_LANEA_MASK;
+ tmp |= FSL_SRDSCR3_LANEA_SATA;
+ tmp &= ~FSL_SRDSCR3_LANEE_MASK;
+ tmp |= FSL_SRDSCR3_LANEE_SATA;
+ out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
+ break;
+ case 3: /* Lane A - SATA1, Lane E - disabled */
+ /* CR 0 */
+ tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
+ tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
+ tmp |= FSL_SRDSCR0_TXEQA_SATA;
+ out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
+ /* CR 1 */
+ tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
+ tmp &= ~FSL_SRDSCR1_LANEE_MASK;
+ tmp |= FSL_SRDSCR1_LANEE_OFF;
+ out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
+ /* CR 2 */
+ tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
+ tmp &= ~FSL_SRDSCR2_EICA_MASK;
+ tmp |= FSL_SRDSCR2_EICA_SATA;
+ out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
+ /* CR 3 */
+ tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
+ tmp &= ~FSL_SRDSCR3_LANEA_MASK;
+ tmp |= FSL_SRDSCR3_LANEA_SATA;
+ out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
+ break;
+ case 4: /* Lane A - eTSEC1 SGMII, Lane E - eTSEC3 SGMII */
+ /* CR 0 */
+ tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
+ tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
+ tmp |= FSL_SRDSCR0_TXEQA_SGMII;
+ tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
+ tmp |= FSL_SRDSCR0_TXEQE_SGMII;
+ out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
+ /* CR 1 */
+ tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
+ tmp &= ~FSL_SRDSCR1_LANEA_MASK;
+ tmp &= ~FSL_SRDSCR1_LANEE_MASK;
+ out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
+ /* CR 2 */
+ tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
+ tmp &= ~FSL_SRDSCR2_EICA_MASK;
+ tmp |= FSL_SRDSCR2_EICA_SGMII;
+ tmp &= ~FSL_SRDSCR2_EICE_MASK;
+ tmp |= FSL_SRDSCR2_EICE_SGMII;
+ out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
+ /* CR 3 */
+ tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
+ tmp &= ~FSL_SRDSCR3_LANEA_MASK;
+ tmp |= FSL_SRDSCR3_LANEA_SGMII;
+ tmp &= ~FSL_SRDSCR3_LANEE_MASK;
+ tmp |= FSL_SRDSCR3_LANEE_SGMII;
+ out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
+ break;
+ case 6: /* Lane A - eTSEC1 SGMII, Lane E - disabled */
+ /* CR 0 */
+ tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
+ tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
+ tmp |= FSL_SRDSCR0_TXEQA_SGMII;
+ out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
+ /* CR 1 */
+ tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
+ tmp &= ~FSL_SRDSCR1_LANEE_MASK;
+ tmp |= FSL_SRDSCR1_LANEE_OFF;
+ out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
+ /* CR 2 */
+ tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
+ tmp &= ~FSL_SRDSCR2_EICA_MASK;
+ tmp |= FSL_SRDSCR2_EICA_SGMII;
+ out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
+ /* CR 3 */
+ tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
+ tmp &= ~FSL_SRDSCR3_LANEA_MASK;
+ tmp |= FSL_SRDSCR3_LANEA_SGMII;
+ out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
+ break;
+ case 7: /* Lane A - disabled, Lane E - disabled */
+ /* CR 1 */
+ tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
+ tmp &= ~FSL_SRDSCR1_LANEA_MASK;
+ tmp |= FSL_SRDSCR1_LANEA_OFF;
+ tmp &= ~FSL_SRDSCR1_LANEE_MASK;
+ tmp |= FSL_SRDSCR1_LANEE_OFF;
+ out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
+ break;
+ default:
+ break;
+ }
+}
diff --git a/arch/ppc/cpu/mpc85xx/pci.c b/arch/ppc/cpu/mpc85xx/pci.c
new file mode 100644
index 0000000..75d2716
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/pci.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2004 Freescale Semiconductor.
+ * Copyright (C) 2003 Motorola Inc.
+ * Xianghua Xiao (x.xiao@motorola.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * PCI Configuration space access support for MPC85xx PCI Bridge
+ */
+#include <common.h>
+#include <asm/cpm_85xx.h>
+#include <pci.h>
+
+#if !defined(CONFIG_FSL_PCI_INIT)
+
+#ifndef CONFIG_SYS_PCI1_MEM_BUS
+#define CONFIG_SYS_PCI1_MEM_BUS CONFIG_SYS_PCI1_MEM_BASE
+#endif
+
+#ifndef CONFIG_SYS_PCI1_IO_BUS
+#define CONFIG_SYS_PCI1_IO_BUS CONFIG_SYS_PCI1_IO_BASE
+#endif
+
+#ifndef CONFIG_SYS_PCI2_MEM_BUS
+#define CONFIG_SYS_PCI2_MEM_BUS CONFIG_SYS_PCI2_MEM_BASE
+#endif
+
+#ifndef CONFIG_SYS_PCI2_IO_BUS
+#define CONFIG_SYS_PCI2_IO_BUS CONFIG_SYS_PCI2_IO_BASE
+#endif
+
+static struct pci_controller *pci_hose;
+
+void
+pci_mpc85xx_init(struct pci_controller *board_hose)
+{
+ u16 reg16;
+ u32 dev;
+
+ volatile ccsr_pcix_t *pcix = (void *)(CONFIG_SYS_MPC85xx_PCIX_ADDR);
+#ifdef CONFIG_MPC85XX_PCI2
+ volatile ccsr_pcix_t *pcix2 = (void *)(CONFIG_SYS_MPC85xx_PCIX2_ADDR);
+#endif
+ volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ struct pci_controller * hose;
+
+ pci_hose = board_hose;
+
+ hose = &pci_hose[0];
+
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+
+ pci_setup_indirect(hose,
+ (CONFIG_SYS_IMMR+0x8000),
+ (CONFIG_SYS_IMMR+0x8004));
+
+ /*
+ * Hose scan.
+ */
+ dev = PCI_BDF(hose->first_busno, 0, 0);
+ pci_hose_read_config_word (hose, dev, PCI_COMMAND, &reg16);
+ reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ pci_hose_write_config_word(hose, dev, PCI_COMMAND, reg16);
+
+ /*
+ * Clear non-reserved bits in status register.
+ */
+ pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff);
+
+ if (!(gur->pordevsr & MPC85xx_PORDEVSR_PCI1)) {
+ /* PCI-X init */
+ if (CONFIG_SYS_CLK_FREQ < 66000000)
+ printf("PCI-X will only work at 66 MHz\n");
+
+ reg16 = PCI_X_CMD_MAX_SPLIT | PCI_X_CMD_MAX_READ
+ | PCI_X_CMD_ERO | PCI_X_CMD_DPERR_E;
+ pci_hose_write_config_word(hose, dev, PCIX_COMMAND, reg16);
+ }
+
+ pcix->potar1 = (CONFIG_SYS_PCI1_MEM_BUS >> 12) & 0x000fffff;
+ pcix->potear1 = 0x00000000;
+ pcix->powbar1 = (CONFIG_SYS_PCI1_MEM_PHYS >> 12) & 0x000fffff;
+ pcix->powbear1 = 0x00000000;
+ pcix->powar1 = (POWAR_EN | POWAR_MEM_READ |
+ POWAR_MEM_WRITE | (__ilog2(CONFIG_SYS_PCI1_MEM_SIZE) - 1));
+
+ pcix->potar2 = (CONFIG_SYS_PCI1_IO_BUS >> 12) & 0x000fffff;
+ pcix->potear2 = 0x00000000;
+ pcix->powbar2 = (CONFIG_SYS_PCI1_IO_PHYS >> 12) & 0x000fffff;
+ pcix->powbear2 = 0x00000000;
+ pcix->powar2 = (POWAR_EN | POWAR_IO_READ |
+ POWAR_IO_WRITE | (__ilog2(CONFIG_SYS_PCI1_IO_SIZE) - 1));
+
+ pcix->pitar1 = 0x00000000;
+ pcix->piwbar1 = 0x00000000;
+ pcix->piwar1 = (PIWAR_EN | PIWAR_PF | PIWAR_LOCAL |
+ PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP | PIWAR_MEM_2G);
+
+ pcix->powar3 = 0;
+ pcix->powar4 = 0;
+ pcix->piwar2 = 0;
+ pcix->piwar3 = 0;
+
+ pci_set_region(hose->regions + 0,
+ CONFIG_SYS_PCI1_MEM_BUS,
+ CONFIG_SYS_PCI1_MEM_PHYS,
+ CONFIG_SYS_PCI1_MEM_SIZE,
+ PCI_REGION_MEM);
+
+ pci_set_region(hose->regions + 1,
+ CONFIG_SYS_PCI1_IO_BUS,
+ CONFIG_SYS_PCI1_IO_PHYS,
+ CONFIG_SYS_PCI1_IO_SIZE,
+ PCI_REGION_IO);
+
+ hose->region_count = 2;
+
+ pci_register_hose(hose);
+
+#if defined(CONFIG_MPC8555CDS) || defined(CONFIG_MPC8541CDS)
+ /*
+ * This is a SW workaround for an apparent HW problem
+ * in the PCI controller on the MPC85555/41 CDS boards.
+ * The first config cycle must be to a valid, known
+ * device on the PCI bus in order to trick the PCI
+ * controller state machine into a known valid state.
+ * Without this, the first config cycle has the chance
+ * of hanging the controller permanently, just leaving
+ * it in a semi-working state, or leaving it working.
+ *
+ * Pick on the Tundra, Device 17, to get it right.
+ */
+ {
+ u8 header_type;
+
+ pci_hose_read_config_byte(hose,
+ PCI_BDF(0,BRIDGE_ID,0),
+ PCI_HEADER_TYPE,
+ &header_type);
+ }
+#endif
+
+ hose->last_busno = pci_hose_scan(hose);
+
+#ifdef CONFIG_MPC85XX_PCI2
+ hose = &pci_hose[1];
+
+ hose->first_busno = pci_hose[0].last_busno + 1;
+ hose->last_busno = 0xff;
+
+ pci_setup_indirect(hose,
+ (CONFIG_SYS_IMMR+0x9000),
+ (CONFIG_SYS_IMMR+0x9004));
+
+ dev = PCI_BDF(hose->first_busno, 0, 0);
+ pci_hose_read_config_word (hose, dev, PCI_COMMAND, &reg16);
+ reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ pci_hose_write_config_word(hose, dev, PCI_COMMAND, reg16);
+
+ /*
+ * Clear non-reserved bits in status register.
+ */
+ pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff);
+
+ pcix2->potar1 = (CONFIG_SYS_PCI2_MEM_BUS >> 12) & 0x000fffff;
+ pcix2->potear1 = 0x00000000;
+ pcix2->powbar1 = (CONFIG_SYS_PCI2_MEM_PHYS >> 12) & 0x000fffff;
+ pcix2->powbear1 = 0x00000000;
+ pcix2->powar1 = (POWAR_EN | POWAR_MEM_READ |
+ POWAR_MEM_WRITE | (__ilog2(CONFIG_SYS_PCI2_MEM_SIZE) - 1));
+
+ pcix2->potar2 = (CONFIG_SYS_PCI2_IO_BUS >> 12) & 0x000fffff;
+ pcix2->potear2 = 0x00000000;
+ pcix2->powbar2 = (CONFIG_SYS_PCI2_IO_PHYS >> 12) & 0x000fffff;
+ pcix2->powbear2 = 0x00000000;
+ pcix2->powar2 = (POWAR_EN | POWAR_IO_READ |
+ POWAR_IO_WRITE | (__ilog2(CONFIG_SYS_PCI2_IO_SIZE) - 1));
+
+ pcix2->pitar1 = 0x00000000;
+ pcix2->piwbar1 = 0x00000000;
+ pcix2->piwar1 = (PIWAR_EN | PIWAR_PF | PIWAR_LOCAL |
+ PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP | PIWAR_MEM_2G);
+
+ pcix2->powar3 = 0;
+ pcix2->powar4 = 0;
+ pcix2->piwar2 = 0;
+ pcix2->piwar3 = 0;
+
+ pci_set_region(hose->regions + 0,
+ CONFIG_SYS_PCI2_MEM_BUS,
+ CONFIG_SYS_PCI2_MEM_PHYS,
+ CONFIG_SYS_PCI2_MEM_SIZE,
+ PCI_REGION_MEM);
+
+ pci_set_region(hose->regions + 1,
+ CONFIG_SYS_PCI2_IO_BUS,
+ CONFIG_SYS_PCI2_IO_PHYS,
+ CONFIG_SYS_PCI2_IO_SIZE,
+ PCI_REGION_IO);
+
+ hose->region_count = 2;
+
+ /*
+ * Hose scan.
+ */
+ pci_register_hose(hose);
+
+ hose->last_busno = pci_hose_scan(hose);
+#endif
+}
+#endif /* !CONFIG_FSL_PCI_INIT */
diff --git a/arch/ppc/cpu/mpc85xx/qe_io.c b/arch/ppc/cpu/mpc85xx/qe_io.c
new file mode 100644
index 0000000..72a29b7
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/qe_io.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2006 Freescale Semiconductor, Inc.
+ *
+ * Dave Liu <daveliu@freescale.com>
+ * based on source code of Shlomi Gridish
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "common.h"
+#include "asm/errno.h"
+#include "asm/io.h"
+#include "asm/immap_85xx.h"
+
+#if defined(CONFIG_QE)
+#define NUM_OF_PINS 32
+void qe_config_iopin(u8 port, u8 pin, int dir, int open_drain, int assign)
+{
+ u32 pin_2bit_mask;
+ u32 pin_2bit_dir;
+ u32 pin_2bit_assign;
+ u32 pin_1bit_mask;
+ u32 tmp_val;
+ volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ volatile par_io_t *par_io = (volatile par_io_t *)
+ &(gur->qe_par_io);
+
+ /* Caculate pin location and 2bit mask and dir */
+ pin_2bit_mask = (u32)(0x3 << (NUM_OF_PINS-(pin%(NUM_OF_PINS/2)+1)*2));
+ pin_2bit_dir = (u32)(dir << (NUM_OF_PINS-(pin%(NUM_OF_PINS/2)+1)*2));
+
+ /* Setup the direction */
+ tmp_val = (pin > (NUM_OF_PINS/2) - 1) ? \
+ in_be32(&par_io[port].cpdir2) :
+ in_be32(&par_io[port].cpdir1);
+
+ if (pin > (NUM_OF_PINS/2) -1) {
+ out_be32(&par_io[port].cpdir2, ~pin_2bit_mask & tmp_val);
+ out_be32(&par_io[port].cpdir2, pin_2bit_dir | tmp_val);
+ } else {
+ out_be32(&par_io[port].cpdir1, ~pin_2bit_mask & tmp_val);
+ out_be32(&par_io[port].cpdir1, pin_2bit_dir | tmp_val);
+ }
+
+ /* Calculate pin location for 1bit mask */
+ pin_1bit_mask = (u32)(1 << (NUM_OF_PINS - (pin+1)));
+
+ /* Setup the open drain */
+ tmp_val = in_be32(&par_io[port].cpodr);
+ if (open_drain)
+ out_be32(&par_io[port].cpodr, pin_1bit_mask | tmp_val);
+ else
+ out_be32(&par_io[port].cpodr, ~pin_1bit_mask & tmp_val);
+
+ /* Setup the assignment */
+ tmp_val = (pin > (NUM_OF_PINS/2) - 1) ?
+ in_be32(&par_io[port].cppar2):
+ in_be32(&par_io[port].cppar1);
+ pin_2bit_assign = (u32)(assign
+ << (NUM_OF_PINS - (pin%(NUM_OF_PINS/2)+1)*2));
+
+ /* Clear and set 2 bits mask */
+ if (pin > (NUM_OF_PINS/2) - 1) {
+ out_be32(&par_io[port].cppar2, ~pin_2bit_mask & tmp_val);
+ out_be32(&par_io[port].cppar2, pin_2bit_assign | tmp_val);
+ } else {
+ out_be32(&par_io[port].cppar1, ~pin_2bit_mask & tmp_val);
+ out_be32(&par_io[port].cppar1, pin_2bit_assign | tmp_val);
+ }
+}
+
+#endif /* CONFIG_QE */
diff --git a/arch/ppc/cpu/mpc85xx/release.S b/arch/ppc/cpu/mpc85xx/release.S
new file mode 100644
index 0000000..0b5b9da
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/release.S
@@ -0,0 +1,311 @@
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc.
+ * Kumar Gala <kumar.gala@freescale.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#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>
+
+/* To boot secondary cpus, we need a place for them to start up.
+ * Normally, they start at 0xfffffffc, but that's usually the
+ * firmware, and we don't want to have to run the firmware again.
+ * Instead, the primary cpu will set the BPTR to point here to
+ * this page. We then set up the core, and head to
+ * start_secondary. Note that this means that the code below
+ * must never exceed 1023 instructions (the branch at the end
+ * would then be the 1024th).
+ */
+ .globl __secondary_start_page
+ .align 12
+__secondary_start_page:
+/* First do some preliminary setup */
+ lis r3, HID0_EMCP@h /* enable machine check */
+#ifndef CONFIG_E500MC
+ ori r3,r3,HID0_TBEN@l /* enable Timebase */
+#endif
+#ifdef CONFIG_PHYS_64BIT
+ ori r3,r3,HID0_ENMAS7@l /* enable MAS7 updates */
+#endif
+ mtspr SPRN_HID0,r3
+
+#ifndef CONFIG_E500MC
+ li r3,(HID1_ASTME|HID1_ABE)@l /* Addr streaming & broadcast */
+ mfspr r0,PVR
+ andi. r0,r0,0xff
+ cmpwi r0,0x50@l /* if we are rev 5.0 or greater set MBDD */
+ blt 1f
+ /* Set MBDD bit also */
+ ori r3, r3, HID1_MBDD@l
+1:
+ mtspr SPRN_HID1,r3
+#endif
+
+ /* Enable branch prediction */
+ lis r3,BUCSR_ENABLE@h
+ ori r3,r3,BUCSR_ENABLE@l
+ mtspr SPRN_BUCSR,r3
+
+ /* Ensure TB is 0 */
+ li r3,0
+ mttbl r3
+ mttbu r3
+
+ /* Enable/invalidate the I-Cache */
+ lis r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@h
+ ori r2,r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@l
+ mtspr SPRN_L1CSR1,r2
+1:
+ mfspr r3,SPRN_L1CSR1
+ and. r1,r3,r2
+ bne 1b
+
+ lis r3,(L1CSR1_CPE|L1CSR1_ICE)@h
+ ori r3,r3,(L1CSR1_CPE|L1CSR1_ICE)@l
+ mtspr SPRN_L1CSR1,r3
+ isync
+2:
+ mfspr r3,SPRN_L1CSR1
+ andi. r1,r3,L1CSR1_ICE@l
+ beq 2b
+
+ /* Enable/invalidate the D-Cache */
+ lis r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@h
+ ori r2,r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@l
+ mtspr SPRN_L1CSR0,r2
+1:
+ mfspr r3,SPRN_L1CSR0
+ and. r1,r3,r2
+ bne 1b
+
+ lis r3,(L1CSR0_CPE|L1CSR0_DCE)@h
+ ori r3,r3,(L1CSR0_CPE|L1CSR0_DCE)@l
+ mtspr SPRN_L1CSR0,r3
+ isync
+2:
+ mfspr r3,SPRN_L1CSR0
+ andi. r1,r3,L1CSR0_DCE@l
+ beq 2b
+
+#define toreset(x) (x - __secondary_start_page + 0xfffff000)
+
+ /* get our PIR to figure out our table entry */
+ lis r3,toreset(__spin_table)@h
+ ori r3,r3,toreset(__spin_table)@l
+
+ /* r10 has the base address for the entry */
+ mfspr r0,SPRN_PIR
+#ifdef CONFIG_E500MC
+ rlwinm r4,r0,27,27,31
+#else
+ mr r4,r0
+#endif
+ slwi r8,r4,5
+ add r10,r3,r8
+
+#if defined(CONFIG_E500MC) && defined(CONFIG_SYS_CACHE_STASHING)
+ /* set stash id to (coreID) * 2 + 32 + L1 CT (0) */
+ slwi r8,r4,1
+ addi r8,r8,32
+ mtspr L1CSR2,r8
+#endif
+
+#ifdef CONFIG_BACKSIDE_L2_CACHE
+ /* Enable/invalidate the L2 cache */
+ msync
+ lis r2,(L2CSR0_L2FI|L2CSR0_L2LFC)@h
+ ori r2,r2,(L2CSR0_L2FI|L2CSR0_L2LFC)@l
+ mtspr SPRN_L2CSR0,r2
+1:
+ mfspr r3,SPRN_L2CSR0
+ and. r1,r3,r2
+ bne 1b
+
+#ifdef CONFIG_SYS_CACHE_STASHING
+ /* set stash id to (coreID) * 2 + 32 + L2 (1) */
+ addi r3,r8,1
+ mtspr SPRN_L2CSR1,r3
+#endif
+
+ lis r3,CONFIG_SYS_INIT_L2CSR0@h
+ ori r3,r3,CONFIG_SYS_INIT_L2CSR0@l
+ mtspr SPRN_L2CSR0,r3
+ isync
+2:
+ mfspr r3,SPRN_L2CSR0
+ andis. r1,r3,L2CSR0_L2E@h
+ beq 2b
+#endif
+
+#define EPAPR_MAGIC (0x45504150)
+#define ENTRY_ADDR_UPPER 0
+#define ENTRY_ADDR_LOWER 4
+#define ENTRY_R3_UPPER 8
+#define ENTRY_R3_LOWER 12
+#define ENTRY_RESV 16
+#define ENTRY_PIR 20
+#define ENTRY_R6_UPPER 24
+#define ENTRY_R6_LOWER 28
+#define ENTRY_SIZE 32
+
+ /* setup the entry */
+ li r3,0
+ li r8,1
+ stw r0,ENTRY_PIR(r10)
+ stw r3,ENTRY_ADDR_UPPER(r10)
+ stw r8,ENTRY_ADDR_LOWER(r10)
+ stw r3,ENTRY_R3_UPPER(r10)
+ stw r4,ENTRY_R3_LOWER(r10)
+ stw r3,ENTRY_R6_UPPER(r10)
+ stw r3,ENTRY_R6_LOWER(r10)
+
+ /* load r13 with the address of the 'bootpg' in SDRAM */
+ lis r13,toreset(__bootpg_addr)@h
+ ori r13,r13,toreset(__bootpg_addr)@l
+ lwz r13,0(r13)
+
+ /* setup mapping for AS = 1, and jump there */
+ lis r11,(MAS0_TLBSEL(1)|MAS0_ESEL(1))@h
+ mtspr SPRN_MAS0,r11
+ lis r11,(MAS1_VALID|MAS1_IPROT)@h
+ ori r11,r11,(MAS1_TS|MAS1_TSIZE(BOOKE_PAGESZ_4K))@l
+ mtspr SPRN_MAS1,r11
+ oris r11,r13,(MAS2_I|MAS2_G)@h
+ ori r11,r13,(MAS2_I|MAS2_G)@l
+ mtspr SPRN_MAS2,r11
+ oris r11,r13,(MAS3_SX|MAS3_SW|MAS3_SR)@h
+ ori r11,r13,(MAS3_SX|MAS3_SW|MAS3_SR)@l
+ mtspr SPRN_MAS3,r11
+ tlbwe
+
+ bl 1f
+1: mflr r11
+ /*
+ * OR in 0xfff to create a mask of the bootpg SDRAM address. We use
+ * this mask to fixup the cpu spin table and the address that we want
+ * to jump to, eg change them from 0xfffffxxx to 0x7ffffxxx if the
+ * bootpg is at 0x7ffff000 in SDRAM.
+ */
+ ori r13,r13,0xfff
+ and r11, r11, r13
+ and r10, r10, r13
+
+ addi r11,r11,(2f-1b)
+ mfmsr r13
+ ori r12,r13,MSR_IS|MSR_DS@l
+
+ mtspr SPRN_SRR0,r11
+ mtspr SPRN_SRR1,r12
+ rfi
+
+ /* spin waiting for addr */
+2:
+ lwz r4,ENTRY_ADDR_LOWER(r10)
+ andi. r11,r4,1
+ bne 2b
+ isync
+
+ /* setup IVORs to match fixed offsets */
+#include "fixed_ivor.S"
+
+ /* get the upper bits of the addr */
+ lwz r11,ENTRY_ADDR_UPPER(r10)
+
+ /* setup branch addr */
+ mtspr SPRN_SRR0,r4
+
+ /* mark the entry as released */
+ li r8,3
+ stw r8,ENTRY_ADDR_LOWER(r10)
+
+ /* mask by ~64M to setup our tlb we will jump to */
+ rlwinm r12,r4,0,0,5
+
+ /* setup r3, r4, r5, r6, r7, r8, r9 */
+ lwz r3,ENTRY_R3_LOWER(r10)
+ li r4,0
+ li r5,0
+ lwz r6,ENTRY_R6_LOWER(r10)
+ lis r7,(64*1024*1024)@h
+ li r8,0
+ li r9,0
+
+ /* load up the pir */
+ lwz r0,ENTRY_PIR(r10)
+ mtspr SPRN_PIR,r0
+ mfspr r0,SPRN_PIR
+ stw r0,ENTRY_PIR(r10)
+
+ mtspr IVPR,r12
+/*
+ * Coming here, we know the cpu has one TLB mapping in TLB1[0]
+ * which maps 0xfffff000-0xffffffff one-to-one. We set up a
+ * second mapping that maps addr 1:1 for 64M, and then we jump to
+ * addr
+ */
+ lis r10,(MAS0_TLBSEL(1)|MAS0_ESEL(0))@h
+ mtspr SPRN_MAS0,r10
+ lis r10,(MAS1_VALID|MAS1_IPROT)@h
+ ori r10,r10,(MAS1_TSIZE(BOOKE_PAGESZ_64M))@l
+ mtspr SPRN_MAS1,r10
+ /* WIMGE = 0b00000 for now */
+ mtspr SPRN_MAS2,r12
+ ori r12,r12,(MAS3_SX|MAS3_SW|MAS3_SR)
+ mtspr SPRN_MAS3,r12
+#ifdef CONFIG_ENABLE_36BIT_PHYS
+ mtspr SPRN_MAS7,r11
+#endif
+ tlbwe
+
+/* Now we have another mapping for this page, so we jump to that
+ * mapping
+ */
+ mtspr SPRN_SRR1,r13
+ rfi
+
+ /*
+ * Allocate some space for the SDRAM address of the bootpg.
+ * This variable has to be in the boot page so that it can
+ * be accessed by secondary cores when they come out of reset.
+ */
+ .globl __bootpg_addr
+__bootpg_addr:
+ .long 0
+
+ .align L1_CACHE_SHIFT
+ .globl __spin_table
+__spin_table:
+ .space CONFIG_MAX_CPUS*ENTRY_SIZE
+
+ /* Fill in the empty space. The actual reset vector is
+ * the last word of the page */
+__secondary_start_code_end:
+ .space 4092 - (__secondary_start_code_end - __secondary_start_page)
+__secondary_reset_vector:
+ b __secondary_start_page
diff --git a/arch/ppc/cpu/mpc85xx/resetvec.S b/arch/ppc/cpu/mpc85xx/resetvec.S
new file mode 100644
index 0000000..29555d4
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/resetvec.S
@@ -0,0 +1,2 @@
+ .section .resetvec,"ax"
+ b _start_e500
diff --git a/arch/ppc/cpu/mpc85xx/serial_scc.c b/arch/ppc/cpu/mpc85xx/serial_scc.c
new file mode 100644
index 0000000..2dab212
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/serial_scc.c
@@ -0,0 +1,268 @@
+/*
+ * (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>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#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 ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+ volatile ccsr_cpm_scc_t *sp;
+ volatile scc_uart_t *up;
+ volatile cbd_t *tbdf, *rbdf;
+ volatile ccsr_cpm_cp_t *cp = &(cpm->im_cpm_cp);
+ uint dpaddr;
+
+ /* initialize pointers to SCC */
+
+ sp = (ccsr_cpm_scc_t *) &(cpm->im_cpm_scc[SCC_INDEX]);
+ up = (scc_uart_t *)&(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).
+ */
+ cpm->im_cpm_mux.cmxscr = \
+ (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 *)&(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)
+{
+#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 ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+
+ if (c == '\n')
+ serial_putc ('\r');
+
+ up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]);
+ tbdf = (cbd_t *)&(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 ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+ unsigned char c;
+
+ up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]);
+ rbdf = (cbd_t *)&(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 ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+
+ up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]);
+ rbdf = (cbd_t *)&(cpm->im_dprambase[up->scc_genscc.scc_rbase]);
+
+ return ((rbdf->cbd_sc & BD_SC_EMPTY) == 0);
+}
+
+#endif /* CONFIG_CONS_ON_SCC */
diff --git a/arch/ppc/cpu/mpc85xx/speed.c b/arch/ppc/cpu/mpc85xx/speed.c
new file mode 100644
index 0000000..268edbc
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/speed.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright 2004, 2007-2009 Freescale Semiconductor, Inc.
+ *
+ * (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>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* --------------------------------------------------------------- */
+
+void get_sys_info (sys_info_t * sysInfo)
+{
+ volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+#ifdef CONFIG_FSL_CORENET
+ volatile ccsr_clk_t *clk = (void *)(CONFIG_SYS_FSL_CORENET_CLK_ADDR);
+
+ const u8 core_cplx_PLL[16] = {
+ [ 0] = 0, /* CC1 PPL / 1 */
+ [ 1] = 0, /* CC1 PPL / 2 */
+ [ 2] = 0, /* CC1 PPL / 4 */
+ [ 4] = 1, /* CC2 PPL / 1 */
+ [ 5] = 1, /* CC2 PPL / 2 */
+ [ 6] = 1, /* CC2 PPL / 4 */
+ [ 8] = 2, /* CC3 PPL / 1 */
+ [ 9] = 2, /* CC3 PPL / 2 */
+ [10] = 2, /* CC3 PPL / 4 */
+ [12] = 3, /* CC4 PPL / 1 */
+ [13] = 3, /* CC4 PPL / 2 */
+ [14] = 3, /* CC4 PPL / 4 */
+ };
+
+ const u8 core_cplx_PLL_div[16] = {
+ [ 0] = 1, /* CC1 PPL / 1 */
+ [ 1] = 2, /* CC1 PPL / 2 */
+ [ 2] = 4, /* CC1 PPL / 4 */
+ [ 4] = 1, /* CC2 PPL / 1 */
+ [ 5] = 2, /* CC2 PPL / 2 */
+ [ 6] = 4, /* CC2 PPL / 4 */
+ [ 8] = 1, /* CC3 PPL / 1 */
+ [ 9] = 2, /* CC3 PPL / 2 */
+ [10] = 4, /* CC3 PPL / 4 */
+ [12] = 1, /* CC4 PPL / 1 */
+ [13] = 2, /* CC4 PPL / 2 */
+ [14] = 4, /* CC4 PPL / 4 */
+ };
+ uint lcrr_div, i, freqCC_PLL[4], rcw_tmp;
+ unsigned long sysclk = CONFIG_SYS_CLK_FREQ;
+
+ sysInfo->freqSystemBus = sysclk;
+ sysInfo->freqDDRBus = sysclk;
+ freqCC_PLL[0] = sysclk;
+ freqCC_PLL[1] = sysclk;
+ freqCC_PLL[2] = sysclk;
+ freqCC_PLL[3] = sysclk;
+
+ sysInfo->freqSystemBus *= (in_be32(&gur->rcwsr[0]) >> 25) & 0x1f;
+ sysInfo->freqDDRBus *= ((in_be32(&gur->rcwsr[0]) >> 17) & 0x1f);
+ freqCC_PLL[0] *= (in_be32(&clk->pllc1gsr) >> 1) & 0x3f;
+ freqCC_PLL[1] *= (in_be32(&clk->pllc2gsr) >> 1) & 0x3f;
+ freqCC_PLL[2] *= (in_be32(&clk->pllc3gsr) >> 1) & 0x3f;
+ freqCC_PLL[3] *= (in_be32(&clk->pllc4gsr) >> 1) & 0x3f;
+
+ rcw_tmp = in_be32(&gur->rcwsr[3]);
+ for (i = 0; i < cpu_numcores(); i++) {
+ u32 c_pll_sel = (in_be32(&clk->clkc0csr + i*8) >> 27) & 0xf;
+ u32 cplx_pll = core_cplx_PLL[c_pll_sel];
+
+ sysInfo->freqProcessor[i] =
+ freqCC_PLL[cplx_pll] / core_cplx_PLL_div[c_pll_sel];
+ }
+
+#define PME_CLK_SEL 0x80000000
+#define FM1_CLK_SEL 0x40000000
+#define FM2_CLK_SEL 0x20000000
+ rcw_tmp = in_be32(&gur->rcwsr[7]);
+
+#ifdef CONFIG_SYS_DPAA_PME
+ if (rcw_tmp & PME_CLK_SEL)
+ sysInfo->freqPME = freqCC_PLL[2] / 2;
+ else
+ sysInfo->freqPME = sysInfo->freqSystemBus / 2;
+#endif
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+ if (rcw_tmp & FM1_CLK_SEL)
+ sysInfo->freqFMan[0] = freqCC_PLL[2] / 2;
+ else
+ sysInfo->freqFMan[0] = sysInfo->freqSystemBus / 2;
+#if (CONFIG_SYS_NUM_FMAN) == 2
+ if (rcw_tmp & FM2_CLK_SEL)
+ sysInfo->freqFMan[1] = freqCC_PLL[2] / 2;
+ else
+ sysInfo->freqFMan[1] = sysInfo->freqSystemBus / 2;
+#endif
+#endif
+
+#else
+ uint plat_ratio,e500_ratio,half_freqSystemBus;
+ uint lcrr_div;
+ int i;
+#ifdef CONFIG_QE
+ u32 qe_ratio;
+#endif
+
+ plat_ratio = (gur->porpllsr) & 0x0000003e;
+ plat_ratio >>= 1;
+ sysInfo->freqSystemBus = plat_ratio * CONFIG_SYS_CLK_FREQ;
+
+ /* Divide before multiply to avoid integer
+ * overflow for processor speeds above 2GHz */
+ half_freqSystemBus = sysInfo->freqSystemBus/2;
+ for (i = 0; i < cpu_numcores(); i++) {
+ e500_ratio = ((gur->porpllsr) >> (i * 8 + 16)) & 0x3f;
+ sysInfo->freqProcessor[i] = e500_ratio * half_freqSystemBus;
+ }
+
+ /* Note: freqDDRBus is the MCLK frequency, not the data rate. */
+ sysInfo->freqDDRBus = sysInfo->freqSystemBus;
+
+#ifdef CONFIG_DDR_CLK_FREQ
+ {
+ u32 ddr_ratio = ((gur->porpllsr) & MPC85xx_PORPLLSR_DDR_RATIO)
+ >> MPC85xx_PORPLLSR_DDR_RATIO_SHIFT;
+ if (ddr_ratio != 0x7)
+ sysInfo->freqDDRBus = ddr_ratio * CONFIG_DDR_CLK_FREQ;
+ }
+#endif
+#endif
+
+#ifdef CONFIG_QE
+ qe_ratio = ((gur->porpllsr) & MPC85xx_PORPLLSR_QE_RATIO)
+ >> MPC85xx_PORPLLSR_QE_RATIO_SHIFT;
+ sysInfo->freqQE = qe_ratio * CONFIG_SYS_CLK_FREQ;
+#endif
+
+#if defined(CONFIG_SYS_LBC_LCRR)
+ /* We will program LCRR to this value later */
+ lcrr_div = CONFIG_SYS_LBC_LCRR & LCRR_CLKDIV;
+#else
+ {
+ volatile ccsr_lbc_t *lbc = (void *)(CONFIG_SYS_MPC85xx_LBC_ADDR);
+ lcrr_div = in_be32(&lbc->lcrr) & LCRR_CLKDIV;
+ }
+#endif
+ if (lcrr_div == 2 || lcrr_div == 4 || lcrr_div == 8) {
+#if defined(CONFIG_FSL_CORENET)
+ /* If this is corenet based SoC, bit-representation
+ * for four times the clock divider values.
+ */
+ lcrr_div *= 4;
+#elif !defined(CONFIG_MPC8540) && !defined(CONFIG_MPC8541) && \
+ !defined(CONFIG_MPC8555) && !defined(CONFIG_MPC8560)
+ /*
+ * Yes, the entire PQ38 family use the same
+ * bit-representation for twice the clock divider values.
+ */
+ lcrr_div *= 2;
+#endif
+ sysInfo->freqLocalBus = sysInfo->freqSystemBus / lcrr_div;
+ } else {
+ /* In case anyone cares what the unknown value is */
+ sysInfo->freqLocalBus = lcrr_div;
+ }
+}
+
+
+int get_clocks (void)
+{
+ sys_info_t sys_info;
+#ifdef CONFIG_MPC8544
+ volatile ccsr_gur_t *gur = (void *) CONFIG_SYS_MPC85xx_GUTS_ADDR;
+#endif
+#if defined(CONFIG_CPM2)
+ volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+ uint sccr, dfbrg;
+
+ /* set VCO = 4 * BRG */
+ cpm->im_cpm_intctl.sccr &= 0xfffffffc;
+ sccr = 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[0];
+ gd->bus_clk = sys_info.freqSystemBus;
+ gd->mem_clk = sys_info.freqDDRBus;
+ gd->lbc_clk = sys_info.freqLocalBus;
+
+#ifdef CONFIG_QE
+ gd->qe_clk = sys_info.freqQE;
+ gd->brg_clk = gd->qe_clk / 2;
+#endif
+ /*
+ * The base clock for I2C depends on the actual SOC. Unfortunately,
+ * there is no pattern that can be used to determine the frequency, so
+ * the only choice is to look up the actual SOC number and use the value
+ * for that SOC. This information is taken from application note
+ * AN2919.
+ */
+#if defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \
+ defined(CONFIG_MPC8560) || defined(CONFIG_MPC8555)
+ gd->i2c1_clk = sys_info.freqSystemBus;
+#elif defined(CONFIG_MPC8544)
+ /*
+ * On the 8544, the I2C clock is the same as the SEC clock. This can be
+ * either CCB/2 or CCB/3, depending on the value of cfg_sec_freq. See
+ * 4.4.3.3 of the 8544 RM. Note that this might actually work for all
+ * 85xx, but only the 8544 has cfg_sec_freq, so it's unknown if the
+ * PORDEVSR2_SEC_CFG bit is 0 on all 85xx boards that are not an 8544.
+ */
+ if (gur->pordevsr2 & MPC85xx_PORDEVSR2_SEC_CFG)
+ gd->i2c1_clk = sys_info.freqSystemBus / 3;
+ else
+ gd->i2c1_clk = sys_info.freqSystemBus / 2;
+#else
+ /* Most 85xx SOCs use CCB/2, so this is the default behavior. */
+ gd->i2c1_clk = sys_info.freqSystemBus / 2;
+#endif
+ gd->i2c2_clk = gd->i2c1_clk;
+
+#if defined(CONFIG_FSL_ESDHC)
+#ifdef CONFIG_MPC8569
+ gd->sdhc_clk = gd->bus_clk;
+#else
+ gd->sdhc_clk = gd->bus_clk / 2;
+#endif
+#endif /* defined(CONFIG_FSL_ESDHC) */
+
+#if defined(CONFIG_CPM2)
+ gd->vco_out = 2*sys_info.freqSystemBus;
+ gd->cpm_clk = gd->vco_out / 2;
+ gd->scc_clk = gd->vco_out / 4;
+ gd->brg_clk = gd->vco_out / (1 << (2 * (dfbrg + 1)));
+#endif
+
+ if(gd->cpu_clk != 0) return (0);
+ else return (1);
+}
+
+
+/********************************************
+ * get_bus_freq
+ * return system bus freq in Hz
+ *********************************************/
+ulong get_bus_freq (ulong dummy)
+{
+ return gd->bus_clk;
+}
+
+/********************************************
+ * get_ddr_freq
+ * return ddr bus freq in Hz
+ *********************************************/
+ulong get_ddr_freq (ulong dummy)
+{
+ return gd->mem_clk;
+}
diff --git a/arch/ppc/cpu/mpc85xx/start.S b/arch/ppc/cpu/mpc85xx/start.S
new file mode 100644
index 0000000..b3cb56a
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/start.S
@@ -0,0 +1,1195 @@
+/*
+ * Copyright 2004, 2007-2010 Freescale Semiconductor, Inc.
+ * Copyright (C) 2003 Motorola,Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* U-Boot Startup Code for 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 <timestamp.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 r12 to access the GOT
+ */
+ START_GOT
+ GOT_ENTRY(_GOT2_TABLE_)
+ GOT_ENTRY(_FIXUP_TABLE_)
+
+#ifndef CONFIG_NAND_SPL
+ GOT_ENTRY(_start)
+ GOT_ENTRY(_start_of_vectors)
+ GOT_ENTRY(_end_of_vectors)
+ GOT_ENTRY(transfer_to_handler)
+#endif
+
+ 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:
+
+/* clear registers/arrays not reset by hardware */
+
+ /* L1 */
+ li r0,2
+ mtspr L1CSR0,r0 /* invalidate d-cache */
+ mtspr L1CSR1,r0 /* invalidate i-cache */
+
+ mfspr r1,DBSR
+ mtspr DBSR,r1 /* Clear all valid bits */
+
+ /*
+ * Enable L1 Caches early
+ *
+ */
+
+#if defined(CONFIG_E500MC) && defined(CONFIG_SYS_CACHE_STASHING)
+ /* set stash id to (coreID) * 2 + 32 + L1 CT (0) */
+ li r2,(32 + 0)
+ mtspr L1CSR2,r2
+#endif
+
+ /* Enable/invalidate the I-Cache */
+ lis r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@h
+ ori r2,r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@l
+ mtspr SPRN_L1CSR1,r2
+1:
+ mfspr r3,SPRN_L1CSR1
+ and. r1,r3,r2
+ bne 1b
+
+ lis r3,(L1CSR1_CPE|L1CSR1_ICE)@h
+ ori r3,r3,(L1CSR1_CPE|L1CSR1_ICE)@l
+ mtspr SPRN_L1CSR1,r3
+ isync
+2:
+ mfspr r3,SPRN_L1CSR1
+ andi. r1,r3,L1CSR1_ICE@l
+ beq 2b
+
+ /* Enable/invalidate the D-Cache */
+ lis r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@h
+ ori r2,r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@l
+ mtspr SPRN_L1CSR0,r2
+1:
+ mfspr r3,SPRN_L1CSR0
+ and. r1,r3,r2
+ bne 1b
+
+ lis r3,(L1CSR0_CPE|L1CSR0_DCE)@h
+ ori r3,r3,(L1CSR0_CPE|L1CSR0_DCE)@l
+ mtspr SPRN_L1CSR0,r3
+ isync
+2:
+ mfspr r3,SPRN_L1CSR0
+ andi. r1,r3,L1CSR0_DCE@l
+ beq 2b
+
+ /* Setup interrupt vectors */
+ lis r1,TEXT_BASE@h
+ mtspr IVPR,r1
+
+ li r1,0x0100
+ mtspr IVOR0,r1 /* 0: Critical input */
+ li r1,0x0200
+ mtspr IVOR1,r1 /* 1: Machine check */
+ li r1,0x0300
+ mtspr IVOR2,r1 /* 2: Data storage */
+ li r1,0x0400
+ mtspr IVOR3,r1 /* 3: Instruction storage */
+ li r1,0x0500
+ mtspr IVOR4,r1 /* 4: External interrupt */
+ li r1,0x0600
+ mtspr IVOR5,r1 /* 5: Alignment */
+ li r1,0x0700
+ mtspr IVOR6,r1 /* 6: Program check */
+ li r1,0x0800
+ mtspr IVOR7,r1 /* 7: floating point unavailable */
+ li r1,0x0900
+ mtspr IVOR8,r1 /* 8: System call */
+ /* 9: Auxiliary processor unavailable(unsupported) */
+ li r1,0x0a00
+ mtspr IVOR10,r1 /* 10: Decrementer */
+ li r1,0x0b00
+ mtspr IVOR11,r1 /* 11: Interval timer */
+ li r1,0x0c00
+ mtspr IVOR12,r1 /* 12: Watchdog timer */
+ li r1,0x0d00
+ mtspr IVOR13,r1 /* 13: Data TLB error */
+ li r1,0x0e00
+ mtspr IVOR14,r1 /* 14: Instruction TLB error */
+ li r1,0x0f00
+ mtspr IVOR15,r1 /* 15: Debug */
+
+ /* 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 */
+
+#ifdef CONFIG_SYS_BOOK3E_HV
+ mtspr MAS8,r0 /* make sure MAS8 is clear */
+#endif
+
+ /* Enable Time Base and Select Time Base Clock */
+ lis r0,HID0_EMCP@h /* Enable machine check */
+#if defined(CONFIG_ENABLE_36BIT_PHYS)
+ ori r0,r0,HID0_ENMAS7@l /* Enable MAS7 */
+#endif
+#ifndef CONFIG_E500MC
+ ori r0,r0,HID0_TBEN@l /* Enable Timebase */
+#endif
+ mtspr HID0,r0
+
+#ifndef CONFIG_E500MC
+ li r0,(HID1_ASTME|HID1_ABE)@l /* Addr streaming & broadcast */
+ mfspr r3,PVR
+ andi. r3,r3, 0xff
+ cmpwi r3,0x50@l /* if we are rev 5.0 or greater set MBDD */
+ blt 1f
+ /* Set MBDD bit also */
+ ori r0, r0, HID1_MBDD@l
+1:
+ mtspr HID1,r0
+#endif
+
+ /* Enable Branch Prediction */
+#if defined(CONFIG_BTB)
+ lis r0,BUCSR_ENABLE@h
+ ori r0,r0,BUCSR_ENABLE@l
+ mtspr SPRN_BUCSR,r0
+#endif
+
+#if defined(CONFIG_SYS_INIT_DBCR)
+ lis r1,0xffff
+ ori r1,r1,0xffff
+ mtspr DBSR,r1 /* Clear all status bits */
+ lis r0,CONFIG_SYS_INIT_DBCR@h /* DBCR0[IDM] must be set */
+ ori r0,r0,CONFIG_SYS_INIT_DBCR@l
+ mtspr DBCR0,r0
+#endif
+
+#ifdef CONFIG_MPC8569
+#define CONFIG_SYS_LBC_ADDR (CONFIG_SYS_CCSRBAR_DEFAULT + 0x5000)
+#define CONFIG_SYS_LBCR_ADDR (CONFIG_SYS_LBC_ADDR + 0xd0)
+
+ /* MPC8569 Rev.0 silcon needs to set bit 13 of LBCR to allow elBC to
+ * use address space which is more than 12bits, and it must be done in
+ * the 4K boot page. So we set this bit here.
+ */
+
+ /* create a temp mapping TLB0[0] for LBCR */
+ lis r6,FSL_BOOKE_MAS0(0, 0, 0)@h
+ ori r6,r6,FSL_BOOKE_MAS0(0, 0, 0)@l
+
+ lis r7,FSL_BOOKE_MAS1(1, 0, 0, 0, BOOKE_PAGESZ_4K)@h
+ ori r7,r7,FSL_BOOKE_MAS1(1, 0, 0, 0, BOOKE_PAGESZ_4K)@l
+
+ lis r8,FSL_BOOKE_MAS2(CONFIG_SYS_LBC_ADDR, MAS2_I|MAS2_G)@h
+ ori r8,r8,FSL_BOOKE_MAS2(CONFIG_SYS_LBC_ADDR, MAS2_I|MAS2_G)@l
+
+ lis r9,FSL_BOOKE_MAS3(CONFIG_SYS_LBC_ADDR, 0,
+ (MAS3_SX|MAS3_SW|MAS3_SR))@h
+ ori r9,r9,FSL_BOOKE_MAS3(CONFIG_SYS_LBC_ADDR, 0,
+ (MAS3_SX|MAS3_SW|MAS3_SR))@l
+
+ mtspr MAS0,r6
+ mtspr MAS1,r7
+ mtspr MAS2,r8
+ mtspr MAS3,r9
+ isync
+ msync
+ tlbwe
+
+ /* Set LBCR register */
+ lis r4,CONFIG_SYS_LBCR_ADDR@h
+ ori r4,r4,CONFIG_SYS_LBCR_ADDR@l
+
+ lis r5,CONFIG_SYS_LBC_LBCR@h
+ ori r5,r5,CONFIG_SYS_LBC_LBCR@l
+ stw r5,0(r4)
+ isync
+
+ /* invalidate this temp TLB */
+ lis r4,CONFIG_SYS_LBC_ADDR@h
+ ori r4,r4,CONFIG_SYS_LBC_ADDR@l
+ tlbivax 0,r4
+ isync
+
+#endif /* CONFIG_MPC8569 */
+
+ lis r6,FSL_BOOKE_MAS0(1, 15, 0)@h
+ ori r6,r6,FSL_BOOKE_MAS0(1, 15, 0)@l
+
+#ifndef CONFIG_SYS_RAMBOOT
+ /* create a temp mapping in AS=1 to the 4M boot window */
+ lis r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_4M)@h
+ ori r7,r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_4M)@l
+
+ lis r8,FSL_BOOKE_MAS2(TEXT_BASE & 0xffc00000, (MAS2_I|MAS2_G))@h
+ ori r8,r8,FSL_BOOKE_MAS2(TEXT_BASE & 0xffc00000, (MAS2_I|MAS2_G))@l
+
+ /* The 85xx has the default boot window 0xff800000 - 0xffffffff */
+ lis r9,FSL_BOOKE_MAS3(0xffc00000, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@h
+ ori r9,r9,FSL_BOOKE_MAS3(0xffc00000, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@l
+#else
+ /*
+ * create a temp mapping in AS=1 to the 1M TEXT_BASE space, the main
+ * image has been relocated to TEXT_BASE on the second stage.
+ */
+ lis r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_1M)@h
+ ori r7,r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_1M)@l
+
+ lis r8,FSL_BOOKE_MAS2(TEXT_BASE, (MAS2_I|MAS2_G))@h
+ ori r8,r8,FSL_BOOKE_MAS2(TEXT_BASE, (MAS2_I|MAS2_G))@l
+
+ lis r9,FSL_BOOKE_MAS3(TEXT_BASE, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@h
+ ori r9,r9,FSL_BOOKE_MAS3(TEXT_BASE, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@l
+#endif
+
+ mtspr MAS0,r6
+ mtspr MAS1,r7
+ mtspr MAS2,r8
+ mtspr MAS3,r9
+ isync
+ msync
+ tlbwe
+
+ /* create a temp mapping in AS=1 to the stack */
+ lis r6,FSL_BOOKE_MAS0(1, 14, 0)@h
+ ori r6,r6,FSL_BOOKE_MAS0(1, 14, 0)@l
+
+ lis r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_16K)@h
+ ori r7,r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_16K)@l
+
+ lis r8,FSL_BOOKE_MAS2(CONFIG_SYS_INIT_RAM_ADDR, 0)@h
+ ori r8,r8,FSL_BOOKE_MAS2(CONFIG_SYS_INIT_RAM_ADDR, 0)@l
+
+ lis r9,FSL_BOOKE_MAS3(CONFIG_SYS_INIT_RAM_ADDR, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@h
+ ori r9,r9,FSL_BOOKE_MAS3(CONFIG_SYS_INIT_RAM_ADDR, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@l
+
+ mtspr MAS0,r6
+ mtspr MAS1,r7
+ mtspr MAS2,r8
+ mtspr MAS3,r9
+ isync
+ msync
+ tlbwe
+
+ lis r6,MSR_IS|MSR_DS@h
+ ori r6,r6,MSR_IS|MSR_DS@l
+ lis r7,switch_as@h
+ ori r7,r7,switch_as@l
+
+ mtspr SPRN_SRR0,r7
+ mtspr SPRN_SRR1,r6
+ rfi
+
+switch_as:
+/* L1 DCache is used for initial RAM */
+
+ /* Allocate Initial RAM in data cache.
+ */
+ lis r3,CONFIG_SYS_INIT_RAM_ADDR@h
+ ori r3,r3,CONFIG_SYS_INIT_RAM_ADDR@l
+ mfspr r2, L1CFG0
+ andi. r2, r2, 0x1ff
+ /* cache size * 1024 / (2 * L1 line size) */
+ slwi r2, r2, (10 - 1 - L1_CACHE_SHIFT)
+ mtctr r2
+ li r0,0
+1:
+ dcbz r0,r3
+ dcbtls 0,r0,r3
+ addi r3,r3,CONFIG_SYS_CACHELINE_SIZE
+ bdnz 1b
+
+ /* Jump out the last 4K page and continue to 'normal' start */
+#ifdef CONFIG_SYS_RAMBOOT
+ b _start_cont
+#else
+ /* Calculate absolute address in FLASH and jump there */
+ /*--------------------------------------------------------------*/
+ lis r3,CONFIG_SYS_MONITOR_BASE@h
+ ori r3,r3,CONFIG_SYS_MONITOR_BASE@l
+ addi r3,r3,_start_cont - _start + _START_OFFSET
+ mtlr r3
+ blr
+#endif
+
+ .text
+ .globl _start
+_start:
+ .long 0x27051956 /* U-BOOT Magic Number */
+ .globl version_string
+version_string:
+ .ascii U_BOOT_VERSION
+ .ascii " (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")"
+ .ascii CONFIG_IDENT_STRING, "\0"
+
+ .align 4
+ .globl _start_cont
+_start_cont:
+ /* Setup the stack in initial RAM,could be L2-as-SRAM or L1 dcache*/
+ lis r1,CONFIG_SYS_INIT_RAM_ADDR@h
+ ori r1,r1,CONFIG_SYS_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_early_f
+
+ /* switch back to AS = 0 */
+ lis r3,(MSR_CE|MSR_ME|MSR_DE)@h
+ ori r3,r3,(MSR_CE|MSR_ME|MSR_DE)@l
+ mtmsr r3
+ isync
+
+ bl cpu_init_f
+ bl board_init_f
+ isync
+
+#ifndef CONFIG_NAND_SPL
+ . = EXC_OFF_SYS_RESET
+ .globl _start_of_vectors
+_start_of_vectors:
+
+/* Critical input. */
+ CRIT_EXCEPTION(0x0100, CriticalInput, CritcalInputException)
+
+/* Machine check */
+ MCK_EXCEPTION(0x200, 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, ExtIntException)
+
+/* Alignment exception. */
+ . = 0x0600
+Alignment:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ mfspr r4,DAR
+ stw r4,_DAR(r21)
+ mfspr r5,DSISR
+ stw r5,_DSISR(r21)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
+
+/* Program check exception */
+ . = 0x0700
+ProgramCheck:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+ MSR_KERNEL, COPY_EE)
+
+ /* No FPU on MPC85xx. This exception is not supposed to happen.
+ */
+ STD_EXCEPTION(0x0800, FPUnavailable, UnknownException)
+
+ . = 0x0900
+/*
+ * r0 - SYSCALL number
+ * r3-... arguments
+ */
+SystemCall:
+ addis r11,r0,0 /* get functions table addr */
+ ori r11,r11,0 /* Note: this code is patched in trap_init */
+ addis r12,r0,0 /* get number of functions */
+ ori r12,r12,0
+
+ cmplw 0,r0,r12
+ bge 1f
+
+ rlwinm r0,r0,2,0,31 /* fn_addr = fn_tbl[r0] */
+ add r11,r11,r0
+ lwz r11,0(r11)
+
+ li r20,0xd00-4 /* Get stack pointer */
+ lwz r12,0(r20)
+ subi r12,r12,12 /* Adjust stack pointer */
+ li r0,0xc00+_end_back-SystemCall
+ cmplw 0,r0,r12 /* Check stack overflow */
+ bgt 1f
+ stw r12,0(r20)
+
+ mflr r0
+ stw r0,0(r12)
+ mfspr r0,SRR0
+ stw r0,4(r12)
+ mfspr r0,SRR1
+ stw r0,8(r12)
+
+ li r12,0xc00+_back-SystemCall
+ mtlr r12
+ mtspr SRR0,r11
+
+1: SYNC
+ rfi
+_back:
+
+ mfmsr r11 /* Disable interrupts */
+ li r12,0
+ ori r12,r12,MSR_EE
+ andc r11,r11,r12
+ SYNC /* Some chip revs need this... */
+ mtmsr r11
+ SYNC
+
+ li r12,0xd00-4 /* restore regs */
+ lwz r12,0(r12)
+
+ lwz r11,0(r12)
+ mtlr r11
+ lwz r11,4(r12)
+ mtspr SRR0,r11
+ lwz r11,8(r12)
+ mtspr SRR1,r11
+
+ addi r12,r12,12 /* Adjust stack pointer */
+ li r20,0xd00-4
+ stw r12,0(r20)
+
+ SYNC
+ rfi
+_end_back:
+
+ STD_EXCEPTION(0x0a00, Decrementer, timer_interrupt)
+ STD_EXCEPTION(0x0b00, IntervalTimer, UnknownException)
+ STD_EXCEPTION(0x0c00, WatchdogTimer, UnknownException)
+
+ STD_EXCEPTION(0x0d00, DataTLBError, UnknownException)
+ STD_EXCEPTION(0x0e00, InstructionTLBError, UnknownException)
+
+ CRIT_EXCEPTION(0x0f00, DebugBreakpoint, DebugException )
+
+ .globl _end_of_vectors
+_end_of_vectors:
+
+
+ . = . + (0x100 - ( . & 0xff )) /* align for debug */
+
+/*
+ * 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 SPRN_CSRR0,r2
+ mtspr SPRN_CSRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfci
+
+mck_return:
+ mfmsr r28 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r28,r28,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r28
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SPRN_MCSRR0,r2
+ mtspr SPRN_MCSRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfmci
+
+/* Cache functions.
+*/
+.globl invalidate_icache
+invalidate_icache:
+ mfspr r0,L1CSR1
+ ori r0,r0,L1CSR1_ICFI
+ msync
+ isync
+ mtspr L1CSR1,r0
+ isync
+ blr /* entire I cache */
+
+.globl invalidate_dcache
+invalidate_dcache:
+ mfspr r0,L1CSR0
+ ori r0,r0,L1CSR0_DCFI
+ 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 r3,0
+ ori r3,r3,L1CSR1_ICE
+ andc r0,r0,r3
+ mtspr L1CSR1,r0
+ isync
+ blr
+
+ .globl icache_status
+icache_status:
+ mfspr r3,L1CSR1
+ andi. r3,r3,L1CSR1_ICE
+ 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 r3,L1CSR0
+ lis r4,0
+ ori r4,r4,L1CSR0_DCE
+ andc r3,r3,r4
+ mtspr L1CSR0,r0
+ isync
+ blr
+
+ .globl dcache_status
+dcache_status:
+ mfspr r3,L1CSR0
+ andi. r3,r3,L1CSR0_DCE
+ blr
+
+ .globl get_pir
+get_pir:
+ mfspr r3,PIR
+ blr
+
+ .globl get_pvr
+get_pvr:
+ mfspr r3,PVR
+ blr
+
+ .globl get_svr
+get_svr:
+ mfspr r3,SVR
+ blr
+
+ .globl wr_tcr
+wr_tcr:
+ mtspr TCR,r3
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: in8 */
+/* Description: Input 8 bits */
+/*------------------------------------------------------------------------------- */
+ .globl in8
+in8:
+ lbz r3,0x0000(r3)
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: out8 */
+/* Description: Output 8 bits */
+/*------------------------------------------------------------------------------- */
+ .globl out8
+out8:
+ stb r4,0x0000(r3)
+ sync
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: out16 */
+/* Description: Output 16 bits */
+/*------------------------------------------------------------------------------- */
+ .globl out16
+out16:
+ sth r4,0x0000(r3)
+ sync
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: out16r */
+/* Description: Byte reverse and output 16 bits */
+/*------------------------------------------------------------------------------- */
+ .globl out16r
+out16r:
+ sthbrx r4,r0,r3
+ sync
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: out32 */
+/* Description: Output 32 bits */
+/*------------------------------------------------------------------------------- */
+ .globl out32
+out32:
+ stw r4,0x0000(r3)
+ sync
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: out32r */
+/* Description: Byte reverse and output 32 bits */
+/*------------------------------------------------------------------------------- */
+ .globl out32r
+out32r:
+ stwbrx r4,r0,r3
+ sync
+ 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
+#endif /* !CONFIG_NAND_SPL */
+
+/*------------------------------------------------------------------------------*/
+
+/*
+ * void write_tlb(mas0, mas1, mas2, mas3, mas7)
+ */
+ .globl write_tlb
+write_tlb:
+ mtspr MAS0,r3
+ mtspr MAS1,r4
+ mtspr MAS2,r5
+ mtspr MAS3,r6
+#ifdef CONFIG_ENABLE_36BIT_PHYS
+ mtspr MAS7,r7
+#endif
+ li r3,0
+#ifdef CONFIG_SYS_BOOK3E_HV
+ mtspr MAS8,r3
+#endif
+ isync
+ tlbwe
+ msync
+ isync
+ 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 */
+
+ GET_GOT
+ mr r3,r5 /* Destination Address */
+ lis r4,CONFIG_SYS_MONITOR_BASE@h /* Source Address */
+ ori r4,r4,CONFIG_SYS_MONITOR_BASE@l
+ lwz r5,GOT(__init_end)
+ sub r5,r5,r4
+ li r6,CONFIG_SYS_CACHELINE_SIZE /* Cache Line Size */
+
+ /*
+ * Fix GOT pointer:
+ *
+ * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
+ *
+ * Offset:
+ */
+ sub r15,r10,r4
+
+ /* First our own GOT */
+ add r12,r12,r15
+ /* the the one used by the C code */
+ add r30,r30,r15
+
+ /*
+ * Now relocate code
+ */
+
+ cmplw cr1,r3,r4
+ addi r0,r5,3
+ srwi. r0,r0,2
+ beq cr1,4f /* In place copy is not necessary */
+ beq 7f /* Protect against 0 count */
+ mtctr r0
+ bge cr1,2f
+
+ la r8,-4(r4)
+ la r7,-4(r3)
+1: lwzu r0,4(r8)
+ stwu r0,4(r7)
+ bdnz 1b
+ b 4f
+
+2: slwi r0,r0,2
+ add r8,r4,r0
+ add r7,r3,r0
+3: lwzu r0,-4(r8)
+ stwu r0,-4(r7)
+ bdnz 3b
+
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4: cmpwi r6,0
+ add r5,r3,r5
+ beq 7f /* Always flush prefetch queue in any case */
+ subi r0,r6,1
+ andc r3,r3,r0
+ mr r4,r3
+5: dcbst 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 5b
+ sync /* Wait for all dcbst to complete on bus */
+ mr r4,r3
+6: icbi 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 6b
+7: sync /* Wait for all icbi to complete on bus */
+ isync
+
+ /*
+ * Re-point the IVPR at RAM
+ */
+ mtspr IVPR,r10
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+
+ addi r0,r10,in_ram - _start + _START_OFFSET
+ mtlr r0
+ blr /* NEVER RETURNS! */
+ .globl in_ram
+in_ram:
+
+ /*
+ * Relocation Function, r12 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)
+ cmpwi r0,0
+ beq- 2f
+ add r0,r0,r11
+ stw r0,0(r3)
+2: bdnz 1b
+
+ /*
+ * Now adjust the fixups and the pointers to the fixups
+ * in case we need to move ourselves again.
+ */
+ 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
+
+#ifndef CONFIG_NAND_SPL
+ /*
+ * Copy exception vector code to low memory
+ *
+ * r3: dest_addr
+ * r7: source address, r8: end address, r9: target address
+ */
+ .globl trap_init
+trap_init:
+ mflr r4 /* save link register */
+ GET_GOT
+ lwz r7,GOT(_start_of_vectors)
+ 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 */
+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_CriticalInput - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_MachineCheck - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_DataStorage - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_InstStorage - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_ExtInterrupt - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_Alignment - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_ProgramCheck - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_FPUnavailable - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_Decrementer - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_IntervalTimer - _start + _START_OFFSET
+ li r8,_end_of_vectors - _start + _START_OFFSET
+2:
+ bl trap_reloc
+ addi r7,r7,0x100 /* next exception vector */
+ cmplw 0,r7,r8
+ blt 2b
+
+ lis r7,0x0
+ mtspr IVPR,r7
+
+ mtlr r4 /* restore link register */
+ blr
+
+.globl unlock_ram_in_cache
+unlock_ram_in_cache:
+ /* invalidate the INIT_RAM section */
+ lis r3,(CONFIG_SYS_INIT_RAM_ADDR & ~(CONFIG_SYS_CACHELINE_SIZE-1))@h
+ ori r3,r3,(CONFIG_SYS_INIT_RAM_ADDR & ~(CONFIG_SYS_CACHELINE_SIZE-1))@l
+ mfspr r4,L1CFG0
+ andi. r4,r4,0x1ff
+ slwi r4,r4,(10 - 1 - L1_CACHE_SHIFT)
+ mtctr r4
+1: dcbi r0,r3
+ addi r3,r3,CONFIG_SYS_CACHELINE_SIZE
+ bdnz 1b
+ sync
+
+ /* Invalidate the TLB entries for the cache */
+ lis r3,CONFIG_SYS_INIT_RAM_ADDR@h
+ ori r3,r3,CONFIG_SYS_INIT_RAM_ADDR@l
+ tlbivax 0,r3
+ addi r3,r3,0x1000
+ tlbivax 0,r3
+ addi r3,r3,0x1000
+ tlbivax 0,r3
+ addi r3,r3,0x1000
+ tlbivax 0,r3
+ isync
+ blr
+
+.globl flush_dcache
+flush_dcache:
+ mfspr r3,SPRN_L1CFG0
+
+ rlwinm r5,r3,9,3 /* Extract cache block size */
+ twlgti r5,1 /* Only 32 and 64 byte cache blocks
+ * are currently defined.
+ */
+ li r4,32
+ subfic r6,r5,2 /* r6 = log2(1KiB / cache block size) -
+ * log2(number of ways)
+ */
+ slw r5,r4,r5 /* r5 = cache block size */
+
+ rlwinm r7,r3,0,0xff /* Extract number of KiB in the cache */
+ mulli r7,r7,13 /* An 8-way cache will require 13
+ * loads per set.
+ */
+ slw r7,r7,r6
+
+ /* save off HID0 and set DCFA */
+ mfspr r8,SPRN_HID0
+ ori r9,r8,HID0_DCFA@l
+ mtspr SPRN_HID0,r9
+ isync
+
+ lis r4,0
+ mtctr r7
+
+1: lwz r3,0(r4) /* Load... */
+ add r4,r4,r5
+ bdnz 1b
+
+ msync
+ lis r4,0
+ mtctr r7
+
+1: dcbf 0,r4 /* ...and flush. */
+ add r4,r4,r5
+ bdnz 1b
+
+ /* restore HID0 */
+ mtspr SPRN_HID0,r8
+ isync
+
+ blr
+
+.globl setup_ivors
+setup_ivors:
+
+#include "fixed_ivor.S"
+ blr
+#endif /* !CONFIG_NAND_SPL */
diff --git a/arch/ppc/cpu/mpc85xx/tlb.c b/arch/ppc/cpu/mpc85xx/tlb.c
new file mode 100644
index 0000000..b3037ac
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/tlb.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2008-2009 Freescale Semiconductor, Inc.
+ *
+ * (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 <asm/processor.h>
+#include <asm/mmu.h>
+#ifdef CONFIG_ADDR_MAP
+#include <addr_map.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void invalidate_tlb(u8 tlb)
+{
+ if (tlb == 0)
+ mtspr(MMUCSR0, 0x4);
+ if (tlb == 1)
+ mtspr(MMUCSR0, 0x2);
+}
+
+void init_tlbs(void)
+{
+ int i;
+
+ for (i = 0; i < num_tlb_entries; i++) {
+ write_tlb(tlb_table[i].mas0,
+ tlb_table[i].mas1,
+ tlb_table[i].mas2,
+ tlb_table[i].mas3,
+ tlb_table[i].mas7);
+ }
+
+ return ;
+}
+
+#ifndef CONFIG_NAND_SPL
+static inline void use_tlb_cam(u8 idx)
+{
+ int i = idx / 32;
+ int bit = idx % 32;
+
+ gd->used_tlb_cams[i] |= (1 << bit);
+}
+
+static inline void free_tlb_cam(u8 idx)
+{
+ int i = idx / 32;
+ int bit = idx % 32;
+
+ gd->used_tlb_cams[i] &= ~(1 << bit);
+}
+
+void init_used_tlb_cams(void)
+{
+ int i;
+ unsigned int num_cam = mfspr(SPRN_TLB1CFG) & 0xfff;
+
+ for (i = 0; i < ((CONFIG_SYS_NUM_TLBCAMS+31)/32); i++)
+ gd->used_tlb_cams[i] = 0;
+
+ /* walk all the entries */
+ for (i = 0; i < num_cam; i++) {
+ u32 _mas1;
+
+ mtspr(MAS0, FSL_BOOKE_MAS0(1, i, 0));
+
+ asm volatile("tlbre;isync");
+ _mas1 = mfspr(MAS1);
+
+ /* if the entry isn't valid skip it */
+ if ((_mas1 & MAS1_VALID))
+ use_tlb_cam(i);
+ }
+}
+
+int find_free_tlbcam(void)
+{
+ int i;
+ u32 idx;
+
+ for (i = 0; i < ((CONFIG_SYS_NUM_TLBCAMS+31)/32); i++) {
+ idx = ffz(gd->used_tlb_cams[i]);
+
+ if (idx != 32)
+ break;
+ }
+
+ idx += i * 32;
+
+ if (idx >= CONFIG_SYS_NUM_TLBCAMS)
+ return -1;
+
+ return idx;
+}
+
+void set_tlb(u8 tlb, u32 epn, u64 rpn,
+ u8 perms, u8 wimge,
+ u8 ts, u8 esel, u8 tsize, u8 iprot)
+{
+ u32 _mas0, _mas1, _mas2, _mas3, _mas7;
+
+ if (tlb == 1)
+ use_tlb_cam(esel);
+
+ _mas0 = FSL_BOOKE_MAS0(tlb, esel, 0);
+ _mas1 = FSL_BOOKE_MAS1(1, iprot, 0, ts, tsize);
+ _mas2 = FSL_BOOKE_MAS2(epn, wimge);
+ _mas3 = FSL_BOOKE_MAS3(rpn, 0, perms);
+ _mas7 = FSL_BOOKE_MAS7(rpn);
+
+ write_tlb(_mas0, _mas1, _mas2, _mas3, _mas7);
+
+#ifdef CONFIG_ADDR_MAP
+ if ((tlb == 1) && (gd->flags & GD_FLG_RELOC))
+ addrmap_set_entry(epn, rpn, (1UL << ((tsize * 2) + 10)), esel);
+#endif
+}
+
+void disable_tlb(u8 esel)
+{
+ u32 _mas0, _mas1, _mas2, _mas3, _mas7;
+
+ free_tlb_cam(esel);
+
+ _mas0 = FSL_BOOKE_MAS0(1, esel, 0);
+ _mas1 = 0;
+ _mas2 = 0;
+ _mas3 = 0;
+ _mas7 = 0;
+
+ mtspr(MAS0, _mas0);
+ mtspr(MAS1, _mas1);
+ mtspr(MAS2, _mas2);
+ mtspr(MAS3, _mas3);
+#ifdef CONFIG_ENABLE_36BIT_PHYS
+ mtspr(MAS7, _mas7);
+#endif
+ asm volatile("isync;msync;tlbwe;isync");
+
+#ifdef CONFIG_ADDR_MAP
+ if (gd->flags & GD_FLG_RELOC)
+ addrmap_set_entry(0, 0, 0, esel);
+#endif
+}
+
+static void tlbsx (const volatile unsigned *addr)
+{
+ __asm__ __volatile__ ("tlbsx 0,%0" : : "r" (addr), "m" (*addr));
+}
+
+/* return -1 if we didn't find anything */
+int find_tlb_idx(void *addr, u8 tlbsel)
+{
+ u32 _mas0, _mas1;
+
+ /* zero out Search PID, AS */
+ mtspr(MAS6, 0);
+
+ tlbsx(addr);
+
+ _mas0 = mfspr(MAS0);
+ _mas1 = mfspr(MAS1);
+
+ /* we found something, and its in the TLB we expect */
+ if ((MAS1_VALID & _mas1) &&
+ (MAS0_TLBSEL(tlbsel) == (_mas0 & MAS0_TLBSEL_MSK))) {
+ return ((_mas0 & MAS0_ESEL_MSK) >> 16);
+ }
+
+ return -1;
+}
+
+#ifdef CONFIG_ADDR_MAP
+void init_addr_map(void)
+{
+ int i;
+ unsigned int num_cam = mfspr(SPRN_TLB1CFG) & 0xfff;
+
+ /* walk all the entries */
+ for (i = 0; i < num_cam; i++) {
+ unsigned long epn;
+ u32 tsize, _mas1;
+ phys_addr_t rpn;
+
+ mtspr(MAS0, FSL_BOOKE_MAS0(1, i, 0));
+
+ asm volatile("tlbre;isync");
+ _mas1 = mfspr(MAS1);
+
+ /* if the entry isn't valid skip it */
+ if (!(_mas1 & MAS1_VALID))
+ continue;
+
+ tsize = (_mas1 >> 8) & 0xf;
+ epn = mfspr(MAS2) & MAS2_EPN;
+ rpn = mfspr(MAS3) & MAS3_RPN;
+#ifdef CONFIG_ENABLE_36BIT_PHYS
+ rpn |= ((phys_addr_t)mfspr(MAS7)) << 32;
+#endif
+
+ addrmap_set_entry(epn, rpn, (1UL << ((tsize * 2) + 10)), i);
+ }
+
+ return ;
+}
+#endif
+
+unsigned int setup_ddr_tlbs(unsigned int memsize_in_meg)
+{
+ int i;
+ unsigned int tlb_size;
+ unsigned int ram_tlb_address = (unsigned int)CONFIG_SYS_DDR_SDRAM_BASE;
+ unsigned int max_cam = (mfspr(SPRN_TLB1CFG) >> 16) & 0xf;
+ u64 size, memsize = (u64)memsize_in_meg << 20;
+
+ size = min(memsize, CONFIG_MAX_MEM_MAPPED);
+
+ /* Convert (4^max) kB to (2^max) bytes */
+ max_cam = max_cam * 2 + 10;
+
+ for (i = 0; size && i < 8; i++) {
+ int ram_tlb_index = find_free_tlbcam();
+ u32 camsize = __ilog2_u64(size) & ~1U;
+ u32 align = __ilog2(ram_tlb_address) & ~1U;
+
+ if (ram_tlb_index == -1)
+ break;
+
+ if (align == -2) align = max_cam;
+ if (camsize > align)
+ camsize = align;
+
+ if (camsize > max_cam)
+ camsize = max_cam;
+
+ tlb_size = (camsize - 10) / 2;
+
+ set_tlb(1, ram_tlb_address, ram_tlb_address,
+ MAS3_SX|MAS3_SW|MAS3_SR, 0,
+ 0, ram_tlb_index, tlb_size, 1);
+
+ size -= 1ULL << camsize;
+ memsize -= 1ULL << camsize;
+ ram_tlb_address += 1UL << camsize;
+ }
+
+ if (memsize)
+ print_size(memsize, " left unmapped\n");
+
+ /*
+ * Confirm that the requested amount of memory was mapped.
+ */
+ return memsize_in_meg;
+}
+#endif /* !CONFIG_NAND_SPL */
diff --git a/arch/ppc/cpu/mpc85xx/traps.c b/arch/ppc/cpu/mpc85xx/traps.c
new file mode 100644
index 0000000..10108d8
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/traps.c
@@ -0,0 +1,325 @@
+/*
+ * linux/arch/ppc/kernel/traps.c
+ *
+ * Copyright 2007 Freescale Semiconductor.
+ * 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 <kgdb.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Returns 0 if exception not found and fixup otherwise. */
+extern unsigned long search_exception_table(unsigned long);
+
+/*
+ * End of addressable memory. This may be less than the actual
+ * amount of memory on the system if we're unable to keep all
+ * the memory mapped in.
+ */
+extern ulong get_effective_memsize(void);
+#define END_OF_MEM (gd->bd->bi_memstart + get_effective_memsize())
+
+static __inline__ void set_tsr(unsigned long val)
+{
+ asm volatile("mtspr 0x150, %0" : : "r" (val));
+}
+
+static __inline__ unsigned long get_esr(void)
+{
+ unsigned long val;
+ asm volatile("mfspr %0, 0x03e" : "=r" (val) :);
+ return val;
+}
+
+#define ESR_MCI 0x80000000
+#define ESR_PIL 0x08000000
+#define ESR_PPR 0x04000000
+#define ESR_PTR 0x02000000
+#define ESR_DST 0x00800000
+#define ESR_DIZ 0x00400000
+#define ESR_U0F 0x00008000
+
+#if defined(CONFIG_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");
+}
+
+int machinecheck_count = 0;
+int machinecheck_error = 0;
+void
+MachineCheckException(struct pt_regs *regs)
+{
+ unsigned long fixup;
+ unsigned int mcsr, mcsrr0, mcsrr1, mcar;
+
+ /* Probing PCI using config cycles cause this exception
+ * when a device is not present. Catch it and return to
+ * the PCI exception handler.
+ */
+ if ((fixup = search_exception_table(regs->nip)) != 0) {
+ regs->nip = fixup;
+ return;
+ }
+
+ mcsrr0 = mfspr(SPRN_MCSRR0);
+ mcsrr1 = mfspr(SPRN_MCSRR1);
+ mcsr = mfspr(SPRN_MCSR);
+ mcar = mfspr(SPRN_MCAR);
+
+ machinecheck_count++;
+ machinecheck_error=1;
+
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ printf("Machine check in kernel mode.\n");
+ printf("Caused by (from mcsr): ");
+ printf("mcsr = 0x%08x\n", mcsr);
+ if (mcsr & 0x80000000)
+ printf("Machine check input pin\n");
+ if (mcsr & 0x40000000)
+ printf("Instruction cache parity error\n");
+ if (mcsr & 0x20000000)
+ printf("Data cache push parity error\n");
+ if (mcsr & 0x10000000)
+ printf("Data cache parity error\n");
+ if (mcsr & 0x00000080)
+ printf("Bus instruction address error\n");
+ if (mcsr & 0x00000040)
+ printf("Bus Read address error\n");
+ if (mcsr & 0x00000020)
+ printf("Bus Write address error\n");
+ if (mcsr & 0x00000010)
+ printf("Bus Instruction data bus error\n");
+ if (mcsr & 0x00000008)
+ printf("Bus Read data bus error\n");
+ if (mcsr & 0x00000004)
+ printf("Bus Write bus error\n");
+ if (mcsr & 0x00000002)
+ printf("Bus Instruction parity error\n");
+ if (mcsr & 0x00000001)
+ printf("Bus Read parity error\n");
+
+ show_regs(regs);
+ printf("MCSR=0x%08x \tMCSRR0=0x%08x \nMCSRR1=0x%08x \tMCAR=0x%08x\n",
+ mcsr, mcsrr0, mcsrr1, mcar);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ if (machinecheck_count > 10) {
+ panic("machine check count too high\n");
+ }
+
+ if (machinecheck_count > 1) {
+ regs->nip += 4; /* skip offending instruction */
+ printf("Skipping current instr, Returning to 0x%08lx\n",
+ regs->nip);
+ } else {
+ printf("Returning back to 0x%08lx\n",regs->nip);
+ }
+}
+
+void
+AlignmentException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Alignment Exception");
+}
+
+void
+ProgramCheckException(struct pt_regs *regs)
+{
+ long esr_val;
+
+#if defined(CONFIG_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 defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+ regs->nip, regs->msr, regs->trap);
+ _exception(0, regs);
+}
+
+void
+ExtIntException(struct pt_regs *regs)
+{
+ volatile ccsr_pic_t *pic = (void *)(CONFIG_SYS_MPC85xx_PIC_ADDR);
+
+ uint vect;
+
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ printf("External Interrupt Exception at PC: %lx, SR: %lx, vector=%lx",
+ regs->nip, regs->msr, regs->trap);
+ vect = pic->iack0;
+ printf(" irq IACK0@%05x=%d\n",(int)&pic->iack0,vect);
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+}
+
+void
+DebugException(struct pt_regs *regs)
+{
+ printf("Debugger trap at @ %lx\n", regs->nip );
+ show_regs(regs);
+#if defined(CONFIG_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/arch/ppc/cpu/mpc85xx/u-boot-nand.lds b/arch/ppc/cpu/mpc85xx/u-boot-nand.lds
new file mode 100644
index 0000000..b9240f2
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/u-boot-nand.lds
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+PHDRS
+{
+ text PT_LOAD;
+ bss PT_LOAD;
+}
+
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ *(.text)
+ *(.got1)
+ } :text
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(.eh_frame)
+ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+ } :text
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+ __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+ .bootpg ADDR(.text) - 0x1000 :
+ {
+ arch/ppc/cpu/mpc85xx/start.o (.bootpg)
+ } :text = 0xffff
+
+ . = ADDR(.text) + 0x80000;
+
+ __bss_start = .;
+ .bss (NOLOAD) :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ } :bss
+
+ . = ALIGN(4);
+ _end = . ;
+ PROVIDE (end = .);
+}
diff --git a/arch/ppc/cpu/mpc85xx/u-boot-nand_spl.lds b/arch/ppc/cpu/mpc85xx/u-boot-nand_spl.lds
new file mode 100644
index 0000000..fef3e42
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/u-boot-nand_spl.lds
@@ -0,0 +1,67 @@
+/*
+ * (C) Copyright 2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de
+ *
+ * Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+SECTIONS
+{
+ . = 0xfff00000;
+ .text : {
+ *(.text)
+ }
+ _etext = .;
+
+ .reloc : {
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+ __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+ . = ALIGN(8);
+ .data : {
+ *(.rodata*)
+ *(.data*)
+ *(.sdata*)
+ }
+ _edata = .;
+
+ . = ALIGN(8);
+ __init_begin = .;
+ __init_end = .;
+
+ .resetvec ADDR(.text) + 0xffc : {
+ *(.resetvec)
+ } = 0xffff
+
+ __bss_start = .;
+ .bss : {
+ *(.sbss)
+ *(.bss)
+ }
+ _end = .;
+}
+ASSERT(__init_end <= 0xfff00ffc, "NAND bootstrap too big");
diff --git a/arch/ppc/cpu/mpc85xx/u-boot.lds b/arch/ppc/cpu/mpc85xx/u-boot.lds
new file mode 100644
index 0000000..9698bf4
--- /dev/null
+++ b/arch/ppc/cpu/mpc85xx/u-boot.lds
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2007-2009 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef RESET_VECTOR_ADDRESS
+#define RESET_VECTOR_ADDRESS 0xfffffffc
+#endif
+
+OUTPUT_ARCH(powerpc)
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+PHDRS
+{
+ text PT_LOAD;
+ bss PT_LOAD;
+}
+
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ *(.text)
+ *(.got1)
+ } :text
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(.eh_frame)
+ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+ } :text
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+ __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+ .bootpg RESET_VECTOR_ADDRESS - 0xffc :
+ {
+ arch/ppc/cpu/mpc85xx/start.o (.bootpg)
+ } :text = 0xffff
+
+ .resetvec RESET_VECTOR_ADDRESS :
+ {
+ *(.resetvec)
+ } :text = 0xffff
+
+ . = RESET_VECTOR_ADDRESS + 0x4;
+
+ /*
+ * Make sure that the bss segment isn't linked at 0x0, otherwise its
+ * address won't be updated during relocation fixups. Note that
+ * this is a temporary fix. Code to dynamically the fixup the bss
+ * location will be added in the future. When the bss relocation
+ * fixup code is present this workaround should be removed.
+ */
+#if (RESET_VECTOR_ADDRESS == 0xfffffffc)
+ . |= 0x10;
+#endif
+
+ __bss_start = .;
+ .bss (NOLOAD) :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ } :bss
+
+ . = ALIGN(4);
+ _end = . ;
+ PROVIDE (end = .);
+}