summaryrefslogtreecommitdiffstats
path: root/arch/ppc
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2007-07-05 18:02:15 +0200
committerSascha Hauer <sha@octopus.labnet.pengutronix.de>2007-07-05 18:02:15 +0200
commitab7a1181545e5a0521075f818a8727cbe7961530 (patch)
treebf9e3fd9fb25a6a1cc767ac5d72e15f93185a721 /arch/ppc
parent19ea863d0faba4516e5c0029c50d264c48fd420e (diff)
downloadbarebox-ab7a1181545e5a0521075f818a8727cbe7961530.tar.gz
barebox-ab7a1181545e5a0521075f818a8727cbe7961530.tar.xz
svn_rev_673
Diffstat (limited to 'arch/ppc')
-rw-r--r--arch/ppc/mach-mpc5xxx/Makefile14
-rw-r--r--arch/ppc/mach-mpc5xxx/cpu.c123
-rw-r--r--arch/ppc/mach-mpc5xxx/cpu_init.c201
-rw-r--r--arch/ppc/mach-mpc5xxx/firmware_sc_task.impl.S364
-rw-r--r--arch/ppc/mach-mpc5xxx/firmware_sc_task_bestcomm.impl.S361
-rw-r--r--arch/ppc/mach-mpc5xxx/ide.c88
-rw-r--r--arch/ppc/mach-mpc5xxx/interrupts.c349
-rw-r--r--arch/ppc/mach-mpc5xxx/io.S128
-rw-r--r--arch/ppc/mach-mpc5xxx/loadtask.c77
-rw-r--r--arch/ppc/mach-mpc5xxx/pci_mpc5200.c187
-rw-r--r--arch/ppc/mach-mpc5xxx/reginfo.c59
-rw-r--r--arch/ppc/mach-mpc5xxx/speed.c107
-rw-r--r--arch/ppc/mach-mpc5xxx/start.S797
-rw-r--r--arch/ppc/mach-mpc5xxx/traps.c229
14 files changed, 3084 insertions, 0 deletions
diff --git a/arch/ppc/mach-mpc5xxx/Makefile b/arch/ppc/mach-mpc5xxx/Makefile
new file mode 100644
index 0000000000..e75f1d1e66
--- /dev/null
+++ b/arch/ppc/mach-mpc5xxx/Makefile
@@ -0,0 +1,14 @@
+obj-y += cpu.o
+obj-y += cpu_init.o
+obj-y += loadtask.o
+obj-y += speed.o
+obj-y += traps.o
+extra-y += start.o
+obj-$(CONFIG_MPC5200) += firmware_sc_task_bestcomm.impl.o
+obj-$(CONFIG_INTERRUPTS) += interrupts.o
+obj-$(CONFIG_REGINFO) += reginfo.o
+
+#obj-y += firmware_sc_task.impl.o
+#obj-y += io.o
+#obj-y += ide.o
+#obj-y += pci_mpc5200.o
diff --git a/arch/ppc/mach-mpc5xxx/cpu.c b/arch/ppc/mach-mpc5xxx/cpu.c
new file mode 100644
index 0000000000..1bb340dedb
--- /dev/null
+++ b/arch/ppc/mach-mpc5xxx/cpu.c
@@ -0,0 +1,123 @@
+/*
+ * (C) Copyright 2000-2003
+ * 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
+ */
+
+/*
+ * CPU specific code for the MPC5xxx CPUs
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/arch/mpc5xxx.h>
+#include <asm/processor.h>
+#include <asm/byteorder.h>
+#include <init.h>
+#include <types.h>
+#include <asm/arch/clocks.h>
+
+#if defined(CONFIG_OF_FLAT_TREE)
+#include <ft_build.h>
+#endif
+
+int checkcpu (void)
+{
+ ulong clock = get_cpu_clock();
+ char buf[32];
+#ifndef CONFIG_MGT5100
+ uint svr, pvr;
+#endif
+
+ puts ("CPU: ");
+
+#ifdef CONFIG_MGT5100
+ puts (CPU_ID_STR);
+ printf (" (JTAG ID %08lx)", *(vu_long *)MPC5XXX_CDM_JTAGID);
+#else
+ svr = get_svr();
+ pvr = get_pvr();
+ switch (SVR_VER (svr)) {
+ case SVR_MPC5200:
+ printf ("MPC5200");
+ break;
+ default:
+ printf ("MPC52?? (SVR %08x)", svr);
+ break;
+ }
+
+ printf (" v%d.%d, Core v%d.%d", SVR_MJREV (svr), SVR_MNREV (svr),
+ PVR_MAJ(pvr), PVR_MIN(pvr));
+#endif
+ printf (" at %s MHz\n", strmhz (buf, clock));
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void do_reset (void)
+{
+ ulong msr;
+ /* Interrupts and MMU off */
+ __asm__ __volatile__ ("mfmsr %0":"=r" (msr):);
+
+ msr &= ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR);
+ __asm__ __volatile__ ("mtmsr %0"::"r" (msr));
+
+ /* Charge the watchdog timer */
+ *(vu_long *)(MPC5XXX_GPT0_COUNTER) = 0x0001000f;
+ *(vu_long *)(MPC5XXX_GPT0_ENABLE) = 0x9004; /* wden|ce|timer_ms */
+ while(1);
+}
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef CONFIG_OF_FLAT_TREE
+void
+ft_cpu_setup(void *blob, bd_t *bd)
+{
+ u32 *p;
+ int len;
+
+ /* Core XLB bus frequency */
+ p = ft_get_prop(blob, "/cpus/" OF_CPU "/bus-frequency", &len);
+ if (p != NULL)
+ *p = cpu_to_be32(get_bus_clock());
+
+ /* SOC peripherals use the IPB bus frequency */
+ p = ft_get_prop(blob, "/" OF_SOC "/bus-frequency", &len);
+ if (p != NULL)
+ *p = cpu_to_be32(get_ipb_clock());
+
+ p = ft_get_prop(blob, "/" OF_SOC "/ethernet@3000/mac-address", &len);
+ if (p != NULL)
+ memcpy(p, bd->bi_enetaddr, 6);
+}
+#endif
+
+int cpu_init_board_data(bd_t *bd)
+{
+ bd->bi_intfreq = get_cpu_clock(); /* Internal Freq, in Hz */
+ bd->bi_busfreq = get_bus_clock(); /* Bus Freq, in Hz */
+ bd->bi_mbar_base = CFG_MBAR; /* base of internal registers */
+ bd->bi_ipbfreq = get_ipb_clock();
+ bd->bi_pcifreq = get_pci_clock();
+ return 0;
+}
diff --git a/arch/ppc/mach-mpc5xxx/cpu_init.c b/arch/ppc/mach-mpc5xxx/cpu_init.c
new file mode 100644
index 0000000000..b8c069f3a0
--- /dev/null
+++ b/arch/ppc/mach-mpc5xxx/cpu_init.c
@@ -0,0 +1,201 @@
+/*
+ * (C) Copyright 2000-2003
+ * 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/arch/mpc5xxx.h>
+#include <types.h>
+
+/*
+ * Breath some life into the CPU...
+ *
+ * Set up the memory map,
+ * initialize a bunch of registers.
+ */
+void cpu_init_f (void)
+{
+ unsigned long addecr = (1 << 25); /* Boot_CS */
+#if defined(CFG_RAMBOOT) && defined(CONFIG_MGT5100)
+ addecr |= (1 << 22); /* SDRAM enable */
+#endif
+
+ /*
+ * Memory Controller: configure chip selects and enable them
+ */
+#if defined(CFG_BOOTCS_START) && defined(CFG_BOOTCS_SIZE)
+ *(vu_long *)MPC5XXX_BOOTCS_START = START_REG(CFG_BOOTCS_START);
+ *(vu_long *)MPC5XXX_BOOTCS_STOP = STOP_REG(CFG_BOOTCS_START,
+ CFG_BOOTCS_SIZE);
+#endif
+#if defined(CFG_BOOTCS_CFG)
+ *(vu_long *)MPC5XXX_BOOTCS_CFG = CFG_BOOTCS_CFG;
+#endif
+
+#if defined(CFG_CS0_START) && defined(CFG_CS0_SIZE)
+ *(vu_long *)MPC5XXX_CS0_START = START_REG(CFG_CS0_START);
+ *(vu_long *)MPC5XXX_CS0_STOP = STOP_REG(CFG_CS0_START, CFG_CS0_SIZE);
+ /* CS0 and BOOT_CS cannot be enabled at once. */
+ /* addecr |= (1 << 16); */
+#endif
+#if defined(CFG_CS0_CFG)
+ *(vu_long *)MPC5XXX_CS0_CFG = CFG_CS0_CFG;
+#endif
+
+#if defined(CFG_CS1_START) && defined(CFG_CS1_SIZE)
+ *(vu_long *)MPC5XXX_CS1_START = START_REG(CFG_CS1_START);
+ *(vu_long *)MPC5XXX_CS1_STOP = STOP_REG(CFG_CS1_START, CFG_CS1_SIZE);
+ addecr |= (1 << 17);
+#endif
+#if defined(CFG_CS1_CFG)
+ *(vu_long *)MPC5XXX_CS1_CFG = CFG_CS1_CFG;
+#endif
+
+#if defined(CFG_CS2_START) && defined(CFG_CS2_SIZE)
+ *(vu_long *)MPC5XXX_CS2_START = START_REG(CFG_CS2_START);
+ *(vu_long *)MPC5XXX_CS2_STOP = STOP_REG(CFG_CS2_START, CFG_CS2_SIZE);
+ addecr |= (1 << 18);
+#endif
+#if defined(CFG_CS2_CFG)
+ *(vu_long *)MPC5XXX_CS2_CFG = CFG_CS2_CFG;
+#endif
+
+#if defined(CFG_CS3_START) && defined(CFG_CS3_SIZE)
+ *(vu_long *)MPC5XXX_CS3_START = START_REG(CFG_CS3_START);
+ *(vu_long *)MPC5XXX_CS3_STOP = STOP_REG(CFG_CS3_START, CFG_CS3_SIZE);
+ addecr |= (1 << 19);
+#endif
+#if defined(CFG_CS3_CFG)
+ *(vu_long *)MPC5XXX_CS3_CFG = CFG_CS3_CFG;
+#endif
+
+#if defined(CFG_CS4_START) && defined(CFG_CS4_SIZE)
+ *(vu_long *)MPC5XXX_CS4_START = START_REG(CFG_CS4_START);
+ *(vu_long *)MPC5XXX_CS4_STOP = STOP_REG(CFG_CS4_START, CFG_CS4_SIZE);
+ addecr |= (1 << 20);
+#endif
+#if defined(CFG_CS4_CFG)
+ *(vu_long *)MPC5XXX_CS4_CFG = CFG_CS4_CFG;
+#endif
+
+#if defined(CFG_CS5_START) && defined(CFG_CS5_SIZE)
+ *(vu_long *)MPC5XXX_CS5_START = START_REG(CFG_CS5_START);
+ *(vu_long *)MPC5XXX_CS5_STOP = STOP_REG(CFG_CS5_START, CFG_CS5_SIZE);
+ addecr |= (1 << 21);
+#endif
+#if defined(CFG_CS5_CFG)
+ *(vu_long *)MPC5XXX_CS5_CFG = CFG_CS5_CFG;
+#endif
+
+#if defined(CONFIG_MPC5200)
+ addecr |= 1;
+#if defined(CFG_CS6_START) && defined(CFG_CS6_SIZE)
+ *(vu_long *)MPC5XXX_CS6_START = START_REG(CFG_CS6_START);
+ *(vu_long *)MPC5XXX_CS6_STOP = STOP_REG(CFG_CS6_START, CFG_CS6_SIZE);
+ addecr |= (1 << 26);
+#endif
+#if defined(CFG_CS6_CFG)
+ *(vu_long *)MPC5XXX_CS6_CFG = CFG_CS6_CFG;
+#endif
+
+#if defined(CFG_CS7_START) && defined(CFG_CS7_SIZE)
+ *(vu_long *)MPC5XXX_CS7_START = START_REG(CFG_CS5_START);
+ *(vu_long *)MPC5XXX_CS7_STOP = STOP_REG(CFG_CS7_START, CFG_CS7_SIZE);
+ addecr |= (1 << 27);
+#endif
+#if defined(CFG_CS7_CFG)
+ *(vu_long *)MPC5XXX_CS7_CFG = CFG_CS7_CFG;
+#endif
+
+#if defined(CFG_CS_BURST)
+ *(vu_long *)MPC5XXX_CS_BURST = CFG_CS_BURST;
+#endif
+#if defined(CFG_CS_DEADCYCLE)
+ *(vu_long *)MPC5XXX_CS_DEADCYCLE = CFG_CS_DEADCYCLE;
+#endif
+#endif /* CONFIG_MPC5200 */
+
+ /* Enable chip selects */
+ *(vu_long *)MPC5XXX_ADDECR = addecr;
+ *(vu_long *)MPC5XXX_CS_CTRL = (1 << 24);
+
+ /* Setup pin multiplexing */
+#if defined(CFG_GPS_PORT_CONFIG)
+ *(vu_long *)MPC5XXX_GPS_PORT_CONFIG = CFG_GPS_PORT_CONFIG;
+#endif
+
+#if defined(CONFIG_MPC5200)
+ /* enable timebase */
+ *(vu_long *)(MPC5XXX_XLBARB + 0x40) |= (1 << 13);
+
+ /* Enable snooping for RAM */
+ *(vu_long *)(MPC5XXX_XLBARB + 0x40) |= (1 << 15);
+ *(vu_long *)(MPC5XXX_XLBARB + 0x70) = CFG_SDRAM_BASE | 0x1d;
+
+# if defined(CFG_IPBSPEED_133)
+ /* Motorola reports IPB should better run at 133 MHz. */
+ *(vu_long *)MPC5XXX_ADDECR |= 1;
+ /* pci_clk_sel = 0x02, ipb_clk_sel = 0x00; */
+ addecr = *(vu_long *)MPC5XXX_CDM_CFG;
+ addecr &= ~0x103;
+# if defined(CFG_PCISPEED_66)
+ /* pci_clk_sel = 0x01 -> IPB_CLK/2 */
+ addecr |= 0x01;
+# else
+ /* pci_clk_sel = 0x02 -> XLB_CLK/4 = IPB_CLK/4 */
+ addecr |= 0x02;
+# endif /* CFG_PCISPEED_66 */
+ *(vu_long *)MPC5XXX_CDM_CFG = addecr;
+# endif /* CFG_IPBSPEED_133 */
+ /* Configure the XLB Arbiter */
+ *(vu_long *)MPC5XXX_XLBARB_MPRIEN = 0xff;
+ *(vu_long *)MPC5XXX_XLBARB_MPRIVAL = 0x11111111;
+
+# if defined(CFG_XLB_PIPELINING)
+ /* Enable piplining */
+ *(vu_long *)(MPC5XXX_XLBARB + 0x40) &= ~(1 << 31);
+# endif
+#endif /* CONFIG_MPC5200 */
+}
+
+/*
+ * initialize higher level parts of CPU like time base and timers
+ */
+int cpu_init_r (void)
+{
+ /* mask all interrupts */
+#if defined(CONFIG_MGT5100)
+ *(vu_long *)MPC5XXX_ICTL_PER_MASK = 0xfffffc00;
+#elif defined(CONFIG_MPC5200)
+ *(vu_long *)MPC5XXX_ICTL_PER_MASK = 0xffffff00;
+#endif
+ *(vu_long *)MPC5XXX_ICTL_CRIT |= 0x0001ffff;
+ *(vu_long *)MPC5XXX_ICTL_EXT &= ~0x00000f00;
+ /* route critical ints to normal ints */
+ *(vu_long *)MPC5XXX_ICTL_EXT |= 0x00000001;
+
+#ifdef CONFIG_DRIVER_NET_MPC5200
+ /* load FEC microcode */
+ loadtask(0, 2);
+#endif
+
+ return (0);
+}
diff --git a/arch/ppc/mach-mpc5xxx/firmware_sc_task.impl.S b/arch/ppc/mach-mpc5xxx/firmware_sc_task.impl.S
new file mode 100644
index 0000000000..b668ee5cf8
--- /dev/null
+++ b/arch/ppc/mach-mpc5xxx/firmware_sc_task.impl.S
@@ -0,0 +1,364 @@
+/*
+ * Copyright (C) 2001, Software Center, Motorola China.
+ *
+ * This file contains microcode for the FEC controller of the MGT5100 CPU.
+ */
+
+#include <config.h>
+
+#if defined(CONFIG_MGT5100)
+
+/* sas/sccg, gas target */
+.section smartdmaInitData,"aw",@progbits /* Initialized data for task variables */
+.section smartdmaTaskTable,"aw",@progbits /* Task tables */
+.globl taskTable
+taskTable:
+.globl scEthernetRecv_Entry
+scEthernetRecv_Entry: /* Task 0 */
+.long scEthernetRecv_TDT - taskTable /* Task 0 Descriptor Table */
+.long scEthernetRecv_TDT - taskTable + 0x000000a4
+.long scEthernetRecv_VarTab - taskTable /* Task 0 Variable Table */
+.long scEthernetRecv_FDT - taskTable + 0x03 /* Task 0 Function Descriptor Table & Flags */
+.long 0x00000000
+.long 0x00000000
+.long scEthernetRecv_CSave - taskTable /* Task 0 context save space */
+.long 0xf0000000
+.globl scEthernetXmit_Entry
+scEthernetXmit_Entry: /* Task 1 */
+.long scEthernetXmit_TDT - taskTable /* Task 1 Descriptor Table */
+.long scEthernetXmit_TDT - taskTable + 0x000000d0
+.long scEthernetXmit_VarTab - taskTable /* Task 1 Variable Table */
+.long scEthernetXmit_FDT - taskTable + 0x03 /* Task 1 Function Descriptor Table & Flags */
+.long 0x00000000
+.long 0x00000000
+.long scEthernetXmit_CSave - taskTable /* Task 1 context save space */
+.long 0xf0000000
+
+
+.globl scEthernetRecv_TDT
+scEthernetRecv_TDT: /* Task 0 Descriptor Table */
+.long 0xc4c50000 /* 0000: LCDEXT: idx0 = var9 + var10; idx0 once var0; idx0 += inc0 */
+.long 0x84c5e000 /* 0004: LCD: idx1 = var9 + var11; ; idx1 += inc0 */
+.long 0x10001f08 /* 0008: DRD1A: var7 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x10000380 /* 000C: DRD1A: var0 = *idx0; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x00000f88 /* 0010: DRD1A: var3 = *idx1; FN=0 init=0 WS=0 RS=0 */
+.long 0x81980000 /* 0014: LCD: idx0 = var3; idx0 once var0; idx0 += inc0 */
+.long 0x10000780 /* 0018: DRD1A: var1 = *idx0; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x60000000 /* 001C: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long 0x010c504c /* 0020: DRD2B1: var4 = EU1(); EU1(var1,var12) */
+.long 0x82180349 /* 0024: LCD: idx0 = var4; idx0 != var13; idx0 += inc1 */
+.long 0x81c68004 /* 0028: LCD: idx1 = var3 + var13 + 4; idx1 once var0; idx1 += inc0 */
+.long 0x70000000 /* 002C: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long 0x018c504e /* 0030: DRD2B1: var6 = EU1(); EU1(var1,var14) */
+.long 0x70000000 /* 0034: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long 0x020c504f /* 0038: DRD2B1: var8 = EU1(); EU1(var1,var15) */
+.long 0x00000b88 /* 003C: DRD1A: var2 = *idx1; FN=0 init=0 WS=0 RS=0 */
+.long 0x8000d184 /* 0040: LCDEXT: idx1 = 0xf0003184; ; */
+.long 0xc6990452 /* 0044: LCDEXT: idx2 = var13; idx2 < var17; idx2 += inc2 */
+.long 0x81486010 /* 0048: LCD: idx3 = var2 + var16; ; idx3 += inc2 */
+.long 0x006acf88 /* 004C: DRD1A: *idx3 = *idx1; FN=0 init=3 WS=1 RS=1 */
+.long 0x8000d184 /* 0050: LCDEXT: idx1 = 0xf0003184; ; */
+.long 0x86810492 /* 0054: LCD: idx2 = var13, idx3 = var2; idx2 < var18; idx2 += inc2, idx3 += inc2 */
+.long 0x006acf88 /* 0058: DRD1A: *idx3 = *idx1; FN=0 init=3 WS=1 RS=1 */
+.long 0x8000d184 /* 005C: LCDEXT: idx1 = 0xf0003184; ; */
+.long 0x868184d2 /* 0060: LCD: idx2 = var13, idx3 = var3; idx2 < var19; idx2 += inc2, idx3 += inc2 */
+.long 0x000acf88 /* 0064: DRD1A: *idx3 = *idx1; FN=0 init=0 WS=1 RS=1 */
+.long 0xc318839b /* 0068: LCDEXT: idx1 = var6; idx1 == var14; idx1 += inc3 */
+.long 0x80190000 /* 006C: LCD: idx2 = var0; idx2 once var0; idx2 += inc0 */
+.long 0x04008468 /* 0070: DRD1A: idx1 = var13; FN=0 INT init=0 WS=0 RS=0 */
+.long 0xc4038358 /* 0074: LCDEXT: idx1 = var8, idx2 = var7; idx1 == var13; idx1 += inc3, idx2 += inc0 */
+.long 0x81c50000 /* 0078: LCD: idx3 = var3 + var10; idx3 once var0; idx3 += inc0 */
+.long 0x1000cb18 /* 007C: DRD1A: *idx2 = idx3; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x00000f18 /* 0080: DRD1A: var3 = idx3; FN=0 init=0 WS=0 RS=0 */
+.long 0xc4188364 /* 0084: LCDEXT: idx1 = var8; idx1 > var13; idx1 += inc4 */
+.long 0x83990000 /* 0088: LCD: idx2 = var7; idx2 once var0; idx2 += inc0 */
+.long 0x10000c00 /* 008C: DRD1A: var3 = var0; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x0000c800 /* 0090: DRD1A: *idx2 = var0; FN=0 init=0 WS=0 RS=0 */
+.long 0x81988000 /* 0094: LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */
+.long 0x10000788 /* 0098: DRD1A: var1 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x60000000 /* 009C: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long 0x080c504c /* 00A0: DRD2B1: idx0 = EU1(); EU1(var1,var12) */
+.long 0x000001f8 /* 00A4(:0): NOP */
+
+
+.globl scEthernetXmit_TDT
+scEthernetXmit_TDT: /* Task 1 Descriptor Table */
+.long 0x80014800 /* 0000: LCDEXT: idx0 = 0xf0004800; ; */
+.long 0x85c60004 /* 0004: LCD: idx1 = var11 + var12 + 4; idx1 once var0; idx1 += inc0 */
+.long 0x10002308 /* 0008: DRD1A: var8 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x10000f88 /* 000C: DRD1A: var3 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x00000380 /* 0010: DRD1A: var0 = *idx0; FN=0 init=0 WS=0 RS=0 */
+.long 0x81980000 /* 0014: LCD: idx0 = var3; idx0 once var0; idx0 += inc0 */
+.long 0x10000780 /* 0018: DRD1A: var1 = *idx0; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x60000000 /* 001C: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long 0x024c504d /* 0020: DRD2B1: var9 = EU1(); EU1(var1,var13) */
+.long 0x84980309 /* 0024: LCD: idx0 = var9; idx0 != var12; idx0 += inc1 */
+.long 0xc0004003 /* 0028: LCDEXT: idx1 = 0x00000003; ; */
+.long 0x81c60004 /* 002C: LCD: idx2 = var3 + var12 + 4; idx2 once var0; idx2 += inc0 */
+.long 0x70000000 /* 0030: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long 0x010c504e /* 0034: DRD2B1: var4 = EU1(); EU1(var1,var14) */
+.long 0x70000000 /* 0038: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long 0x014c504f /* 003C: DRD2B1: var5 = EU1(); EU1(var1,var15) */
+.long 0x70000000 /* 0040: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long 0x028c5050 /* 0044: DRD2B1: var10 = EU1(); EU1(var1,var16) */
+.long 0x70000000 /* 0048: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long 0x018c5051 /* 004C: DRD2B1: var6 = EU1(); EU1(var1,var17) */
+.long 0x10000b90 /* 0050: DRD1A: var2 = *idx2; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x60000000 /* 0054: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long 0x01cc50a1 /* 0058: DRD2B1: var7 = EU1(); EU1(var2,idx1) */
+.long 0xc2988312 /* 005C: LCDEXT: idx1 = var5; idx1 > var12; idx1 += inc2 */
+.long 0x83490000 /* 0060: LCD: idx2 = var6 + var18; idx2 once var0; idx2 += inc0 */
+.long 0x00001b10 /* 0064: DRD1A: var6 = idx2; FN=0 init=0 WS=0 RS=0 */
+.long 0x8000d1a4 /* 0068: LCDEXT: idx1 = 0xf00031a4; ; */
+.long 0x8301031c /* 006C: LCD: idx2 = var6, idx3 = var2; idx2 > var12; idx2 += inc3, idx3 += inc4 */
+.long 0x008ac798 /* 0070: DRD1A: *idx1 = *idx3; FN=0 init=4 WS=1 RS=1 */
+.long 0x8000d1a4 /* 0074: LCDEXT: idx1 = 0xf00031a4; ; */
+.long 0xc1430000 /* 0078: LCDEXT: idx2 = var2 + var6; idx2 once var0; idx2 += inc0 */
+.long 0x82998312 /* 007C: LCD: idx3 = var5; idx3 > var12; idx3 += inc2 */
+.long 0x088ac790 /* 0080: DRD1A: *idx1 = *idx2; FN=0 TFD init=4 WS=1 RS=1 */
+.long 0x81988000 /* 0084: LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */
+.long 0x60000100 /* 0088: DRD2A: EU0=0 EU1=1 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long 0x0c4c5c4d /* 008C: DRD2B1: *idx1 = EU1(); EU1(*idx1,var13) */
+.long 0xc21883ad /* 0090: LCDEXT: idx1 = var4; idx1 == var14; idx1 += inc5 */
+.long 0x80190000 /* 0094: LCD: idx2 = var0; idx2 once var0; idx2 += inc0 */
+.long 0x04008460 /* 0098: DRD1A: idx1 = var12; FN=0 INT init=0 WS=0 RS=0 */
+.long 0xc4052305 /* 009C: LCDEXT: idx1 = var8, idx2 = var10; idx2 == var12; idx1 += inc0, idx2 += inc5 */
+.long 0x81c98000 /* 00A0: LCD: idx3 = var3 + var19; idx3 once var0; idx3 += inc0 */
+.long 0x1000c718 /* 00A4: DRD1A: *idx1 = idx3; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x00000f18 /* 00A8: DRD1A: var3 = idx3; FN=0 init=0 WS=0 RS=0 */
+.long 0xc4188000 /* 00AC: LCDEXT: idx1 = var8; idx1 once var0; idx1 += inc0 */
+.long 0x85190312 /* 00B0: LCD: idx2 = var10; idx2 > var12; idx2 += inc2 */
+.long 0x10000c00 /* 00B4: DRD1A: var3 = var0; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x1000c400 /* 00B8: DRD1A: *idx1 = var0; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x00008860 /* 00BC: DRD1A: idx2 = var12; FN=0 init=0 WS=0 RS=0 */
+.long 0x81988000 /* 00C0: LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */
+.long 0x10000788 /* 00C4: DRD1A: var1 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x60000000 /* 00C8: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long 0x080c504d /* 00CC: DRD2B1: idx0 = EU1(); EU1(var1,var13) */
+.long 0x000001f8 /* 00D0(:0): NOP */
+
+.align 8
+
+.globl scEthernetRecv_VarTab
+scEthernetRecv_VarTab: /* Task 0 Variable Table */
+.long 0x00000000 /* var[0] */
+.long 0x00000000 /* var[1] */
+.long 0x00000000 /* var[2] */
+.long 0x00000000 /* var[3] */
+.long 0x00000000 /* var[4] */
+.long 0x00000000 /* var[5] */
+.long 0x00000000 /* var[6] */
+.long 0x00000000 /* var[7] */
+.long 0x00000000 /* var[8] */
+.long 0xf0004800 /* var[9] */
+.long 0x00000008 /* var[10] */
+.long 0x0000000c /* var[11] */
+.long 0x80000000 /* var[12] */
+.long 0x00000000 /* var[13] */
+.long 0x10000000 /* var[14] */
+.long 0x20000000 /* var[15] */
+.long 0x000005e4 /* var[16] */
+.long 0x0000000e /* var[17] */
+.long 0x000005e0 /* var[18] */
+.long 0x00000004 /* var[19] */
+.long 0x00000000 /* var[20] */
+.long 0x00000000 /* var[21] */
+.long 0x00000000 /* var[22] */
+.long 0x00000000 /* var[23] */
+.long 0x00000000 /* inc[0] */
+.long 0x60000000 /* inc[1] */
+.long 0x20000001 /* inc[2] */
+.long 0x80000000 /* inc[3] */
+.long 0x40000000 /* inc[4] */
+.long 0x00000000 /* inc[5] */
+.long 0x00000000 /* inc[6] */
+.long 0x00000000 /* inc[7] */
+
+.align 8
+
+.globl scEthernetXmit_VarTab
+scEthernetXmit_VarTab: /* Task 1 Variable Table */
+.long 0x00000000 /* var[0] */
+.long 0x00000000 /* var[1] */
+.long 0x00000000 /* var[2] */
+.long 0x00000000 /* var[3] */
+.long 0x00000000 /* var[4] */
+.long 0x00000000 /* var[5] */
+.long 0x00000000 /* var[6] */
+.long 0x00000000 /* var[7] */
+.long 0x00000000 /* var[8] */
+.long 0x00000000 /* var[9] */
+.long 0x00000000 /* var[10] */
+.long 0xf0004800 /* var[11] */
+.long 0x00000000 /* var[12] */
+.long 0x80000000 /* var[13] */
+.long 0x10000000 /* var[14] */
+.long 0x08000000 /* var[15] */
+.long 0x20000000 /* var[16] */
+.long 0x0000ffff /* var[17] */
+.long 0xffffffff /* var[18] */
+.long 0x00000008 /* var[19] */
+.long 0x00000000 /* var[20] */
+.long 0x00000000 /* var[21] */
+.long 0x00000000 /* var[22] */
+.long 0x00000000 /* var[23] */
+.long 0x00000000 /* inc[0] */
+.long 0x60000000 /* inc[1] */
+.long 0x40000000 /* inc[2] */
+.long 0x4000ffff /* inc[3] */
+.long 0xe0000001 /* inc[4] */
+.long 0x80000000 /* inc[5] */
+.long 0x00000000 /* inc[6] */
+.long 0x00000000 /* inc[7] */
+
+.align 8
+
+.globl scEthernetRecv_FDT
+scEthernetRecv_FDT: /* Task 0 Function Descriptor Table */
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x05800000 /* and(), EU# 1 */
+.long 0x05400000 /* andn(), EU# 1 */
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+
+.align 8
+
+.globl scEthernetXmit_FDT
+scEthernetXmit_FDT: /* Task 1 Function Descriptor Table */
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x05800000 /* and(), EU# 1 */
+.long 0x05400000 /* andn(), EU# 1 */
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+
+
+.align 8
+.globl scEthernetRecv_CSave
+scEthernetRecv_CSave: /* Task 0 context save space */
+.space 256, 0x0
+
+
+.align 8
+.globl scEthernetXmit_CSave
+scEthernetXmit_CSave: /* Task 1 context save space */
+.space 256, 0x0
+
+#endif /* CONFIG_MGT5100 */
diff --git a/arch/ppc/mach-mpc5xxx/firmware_sc_task_bestcomm.impl.S b/arch/ppc/mach-mpc5xxx/firmware_sc_task_bestcomm.impl.S
new file mode 100644
index 0000000000..42d0e3ce08
--- /dev/null
+++ b/arch/ppc/mach-mpc5xxx/firmware_sc_task_bestcomm.impl.S
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 2001, Software Center, Motorola China.
+ *
+ * This file contains microcode for the FEC controller of the MPC5200 CPU.
+ */
+
+/* sas/sccg, gas target */
+.section smartdmaInitData,"aw",@progbits /* Initialized data for task variables */
+.section smartdmaTaskTable,"aw",@progbits /* Task tables */
+.align 9
+
+.globl taskTable
+taskTable:
+
+.globl scEthernetRecv_Entry
+scEthernetRecv_Entry: /* Task 0 */
+.long scEthernetRecv_TDT - taskTable /* Task 0 Descriptor Table */
+.long scEthernetRecv_TDT - taskTable + 0x000000a4
+.long scEthernetRecv_VarTab - taskTable /* Task 0 Variable Table */
+.long scEthernetRecv_FDT - taskTable + 0x03 /* Task 0 Function Descriptor Table & Flags */
+.long 0x00000000
+.long 0x00000000
+.long scEthernetRecv_CSave - taskTable /* Task 0 context save space */
+.long 0xf0000000
+
+.globl scEthernetXmit_Entry
+scEthernetXmit_Entry: /* Task 1 */
+.long scEthernetXmit_TDT - taskTable /* Task 1 Descriptor Table */
+.long scEthernetXmit_TDT - taskTable + 0x000000d0
+.long scEthernetXmit_VarTab - taskTable /* Task 1 Variable Table */
+.long scEthernetXmit_FDT - taskTable + 0x03 /* Task 1 Function Descriptor Table & Flags */
+.long 0x00000000
+.long 0x00000000
+.long scEthernetXmit_CSave - taskTable /* Task 1 context save space */
+.long 0xf0000000
+
+
+.globl scEthernetRecv_TDT
+scEthernetRecv_TDT: /* Task 0 Descriptor Table */
+.long 0xc4c50000 /* 0000: LCDEXT: idx0 = var9 + var10; idx0 once var0; idx0 += inc0 */
+.long 0x84c5e000 /* 0004: LCD: idx1 = var9 + var11; ; idx1 += inc0 */
+.long 0x10001f08 /* 0008: DRD1A: var7 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x10000380 /* 000C: DRD1A: var0 = *idx0; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x00000f88 /* 0010: DRD1A: var3 = *idx1; FN=0 init=0 WS=0 RS=0 */
+.long 0x81980000 /* 0014: LCD: idx0 = var3; idx0 once var0; idx0 += inc0 */
+.long 0x10000780 /* 0018: DRD1A: var1 = *idx0; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x60000000 /* 001C: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long 0x010cf04c /* 0020: DRD2B1: var4 = EU3(); EU3(var1,var12) */
+.long 0x82180349 /* 0024: LCD: idx0 = var4; idx0 != var13; idx0 += inc1 */
+.long 0x81c68004 /* 0028: LCD: idx1 = var3 + var13 + 4; idx1 once var0; idx1 += inc0 */
+.long 0x70000000 /* 002C: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long 0x018cf04e /* 0030: DRD2B1: var6 = EU3(); EU3(var1,var14) */
+.long 0x70000000 /* 0034: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long 0x020cf04f /* 0038: DRD2B1: var8 = EU3(); EU3(var1,var15) */
+.long 0x00000b88 /* 003C: DRD1A: var2 = *idx1; FN=0 init=0 WS=0 RS=0 */
+.long 0x8000d184 /* 0040: LCDEXT: idx1 = 0xf0003184; ; */
+.long 0xc6990452 /* 0044: LCDEXT: idx2 = var13; idx2 < var17; idx2 += inc2 */
+.long 0x81486010 /* 0048: LCD: idx3 = var2 + var16; ; idx3 += inc2 */
+.long 0x006acf88 /* 004C: DRD1A: *idx3 = *idx1; FN=0 init=3 WS=1 RS=1 */
+.long 0x8000d184 /* 0050: LCDEXT: idx1 = 0xf0003184; ; */
+.long 0x86810492 /* 0054: LCD: idx2 = var13, idx3 = var2; idx2 < var18; idx2 += inc2, idx3 += inc2 */
+.long 0x006acf88 /* 0058: DRD1A: *idx3 = *idx1; FN=0 init=3 WS=1 RS=1 */
+.long 0x8000d184 /* 005C: LCDEXT: idx1 = 0xf0003184; ; */
+.long 0x868184d2 /* 0060: LCD: idx2 = var13, idx3 = var3; idx2 < var19; idx2 += inc2, idx3 += inc2 */
+.long 0x000acf88 /* 0064: DRD1A: *idx3 = *idx1; FN=0 init=0 WS=1 RS=1 */
+.long 0xc318839b /* 0068: LCDEXT: idx1 = var6; idx1 == var14; idx1 += inc3 */
+.long 0x80190000 /* 006C: LCD: idx2 = var0; idx2 once var0; idx2 += inc0 */
+.long 0x04008468 /* 0070: DRD1A: idx1 = var13; FN=0 INT init=0 WS=0 RS=0 */
+.long 0xc4038358 /* 0074: LCDEXT: idx1 = var8, idx2 = var7; idx1 == var13; idx1 += inc3, idx2 += inc0 */
+.long 0x81c50000 /* 0078: LCD: idx3 = var3 + var10; idx3 once var0; idx3 += inc0 */
+.long 0x1000cb18 /* 007C: DRD1A: *idx2 = idx3; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x00000f18 /* 0080: DRD1A: var3 = idx3; FN=0 init=0 WS=0 RS=0 */
+.long 0xc4188364 /* 0084: LCDEXT: idx1 = var8; idx1 > var13; idx1 += inc4 */
+.long 0x83990000 /* 0088: LCD: idx2 = var7; idx2 once var0; idx2 += inc0 */
+.long 0x10000c00 /* 008C: DRD1A: var3 = var0; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x0000c800 /* 0090: DRD1A: *idx2 = var0; FN=0 init=0 WS=0 RS=0 */
+.long 0x81988000 /* 0094: LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */
+.long 0x10000788 /* 0098: DRD1A: var1 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x60000000 /* 009C: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long 0x080cf04c /* 00A0: DRD2B1: idx0 = EU3(); EU3(var1,var12) */
+.long 0x000001f8 /* 00A4(:0): NOP */
+
+
+.globl scEthernetXmit_TDT
+scEthernetXmit_TDT: /* Task 1 Descriptor Table */
+.long 0x80024800 /* 0000: LCDEXT: idx0 = 0xf0008800; ; */
+.long 0x85c60004 /* 0004: LCD: idx1 = var11 + var12 + 4; idx1 once var0; idx1 += inc0 */
+.long 0x10002308 /* 0008: DRD1A: var8 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x10000f88 /* 000C: DRD1A: var3 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x00000380 /* 0010: DRD1A: var0 = *idx0; FN=0 init=0 WS=0 RS=0 */
+.long 0x81980000 /* 0014: LCD: idx0 = var3; idx0 once var0; idx0 += inc0 */
+.long 0x10000780 /* 0018: DRD1A: var1 = *idx0; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x60000000 /* 001C: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long 0x024cf04d /* 0020: DRD2B1: var9 = EU3(); EU3(var1,var13) */
+.long 0x84980309 /* 0024: LCD: idx0 = var9; idx0 != var12; idx0 += inc1 */
+.long 0xc0004003 /* 0028: LCDEXT: idx1 = 0x00000003; ; */
+.long 0x81c60004 /* 002C: LCD: idx2 = var3 + var12 + 4; idx2 once var0; idx2 += inc0 */
+.long 0x70000000 /* 0030: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long 0x010cf04e /* 0034: DRD2B1: var4 = EU3(); EU3(var1,var14) */
+.long 0x70000000 /* 0038: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long 0x014cf04f /* 003C: DRD2B1: var5 = EU3(); EU3(var1,var15) */
+.long 0x70000000 /* 0040: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long 0x028cf050 /* 0044: DRD2B1: var10 = EU3(); EU3(var1,var16) */
+.long 0x70000000 /* 0048: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long 0x018cf051 /* 004C: DRD2B1: var6 = EU3(); EU3(var1,var17) */
+.long 0x10000b90 /* 0050: DRD1A: var2 = *idx2; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x60000000 /* 0054: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long 0x01ccf0a1 /* 0058: DRD2B1: var7 = EU3(); EU3(var2,idx1) */
+.long 0xc2988312 /* 005C: LCDEXT: idx1 = var5; idx1 > var12; idx1 += inc2 */
+.long 0x83490000 /* 0060: LCD: idx2 = var6 + var18; idx2 once var0; idx2 += inc0 */
+.long 0x00001b10 /* 0064: DRD1A: var6 = idx2; FN=0 init=0 WS=0 RS=0 */
+.long 0x8000d1a4 /* 0068: LCDEXT: idx1 = 0xf00031a4; ; */
+.long 0x8301031c /* 006C: LCD: idx2 = var6, idx3 = var2; idx2 > var12; idx2 += inc3, idx3 += inc4 */
+.long 0x008ac798 /* 0070: DRD1A: *idx1 = *idx3; FN=0 init=4 WS=1 RS=1 */
+.long 0x8000d1a4 /* 0074: LCDEXT: idx1 = 0xf00031a4; ; */
+.long 0xc1430000 /* 0078: LCDEXT: idx2 = var2 + var6; idx2 once var0; idx2 += inc0 */
+.long 0x82998312 /* 007C: LCD: idx3 = var5; idx3 > var12; idx3 += inc2 */
+.long 0x088ac790 /* 0080: DRD1A: *idx1 = *idx2; FN=0 TFD init=4 WS=1 RS=1 */
+.long 0x81988000 /* 0084: LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */
+.long 0x60000001 /* 0088: DRD2A: EU0=0 EU1=0 EU2=0 EU3=1 EXT init=0 WS=0 RS=0 */
+.long 0x0c4cfc4d /* 008C: DRD2B1: *idx1 = EU3(); EU3(*idx1,var13) */
+.long 0xc21883ad /* 0090: LCDEXT: idx1 = var4; idx1 == var14; idx1 += inc5 */
+.long 0x80190000 /* 0094: LCD: idx2 = var0; idx2 once var0; idx2 += inc0 */
+.long 0x04008460 /* 0098: DRD1A: idx1 = var12; FN=0 INT init=0 WS=0 RS=0 */
+.long 0xc4052305 /* 009C: LCDEXT: idx1 = var8, idx2 = var10; idx2 == var12; idx1 += inc0, idx2 += inc5 */
+.long 0x81c98000 /* 00A0: LCD: idx3 = var3 + var19; idx3 once var0; idx3 += inc0 */
+.long 0x1000c718 /* 00A4: DRD1A: *idx1 = idx3; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x00000f18 /* 00A8: DRD1A: var3 = idx3; FN=0 init=0 WS=0 RS=0 */
+.long 0xc4188000 /* 00AC: LCDEXT: idx1 = var8; idx1 once var0; idx1 += inc0 */
+.long 0x85190312 /* 00B0: LCD: idx2 = var10; idx2 > var12; idx2 += inc2 */
+.long 0x10000c00 /* 00B4: DRD1A: var3 = var0; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x1000c400 /* 00B8: DRD1A: *idx1 = var0; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x00008860 /* 00BC: DRD1A: idx2 = var12; FN=0 init=0 WS=0 RS=0 */
+.long 0x81988000 /* 00C0: LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */
+.long 0x10000788 /* 00C4: DRD1A: var1 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x60000000 /* 00C8: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long 0x080cf04d /* 00CC: DRD2B1: idx0 = EU3(); EU3(var1,var13) */
+.long 0x000001f8 /* 00D0(:0): NOP */
+
+.align 8
+
+.globl scEthernetRecv_VarTab
+scEthernetRecv_VarTab: /* Task 0 Variable Table */
+.long 0x00000000 /* var[0] */
+.long 0x00000000 /* var[1] */
+.long 0x00000000 /* var[2] */
+.long 0x00000000 /* var[3] */
+.long 0x00000000 /* var[4] */
+.long 0x00000000 /* var[5] */
+.long 0x00000000 /* var[6] */
+.long 0x00000000 /* var[7] */
+.long 0x00000000 /* var[8] */
+.long 0xf0008800 /* var[9] */
+.long 0x00000008 /* var[10] */
+.long 0x0000000c /* var[11] */
+.long 0x80000000 /* var[12] */
+.long 0x00000000 /* var[13] */
+.long 0x10000000 /* var[14] */
+.long 0x20000000 /* var[15] */
+.long 0x000005e4 /* var[16] */
+.long 0x0000000e /* var[17] */
+.long 0x000005e0 /* var[18] */
+.long 0x00000004 /* var[19] */
+.long 0x00000000 /* var[20] */
+.long 0x00000000 /* var[21] */
+.long 0x00000000 /* var[22] */
+.long 0x00000000 /* var[23] */
+.long 0x00000000 /* inc[0] */
+.long 0x60000000 /* inc[1] */
+.long 0x20000001 /* inc[2] */
+.long 0x80000000 /* inc[3] */
+.long 0x40000000 /* inc[4] */
+.long 0x00000000 /* inc[5] */
+.long 0x00000000 /* inc[6] */
+.long 0x00000000 /* inc[7] */
+
+.align 8
+
+.globl scEthernetXmit_VarTab
+scEthernetXmit_VarTab: /* Task 1 Variable Table */
+.long 0x00000000 /* var[0] */
+.long 0x00000000 /* var[1] */
+.long 0x00000000 /* var[2] */
+.long 0x00000000 /* var[3] */
+.long 0x00000000 /* var[4] */
+.long 0x00000000 /* var[5] */
+.long 0x00000000 /* var[6] */
+.long 0x00000000 /* var[7] */
+.long 0x00000000 /* var[8] */
+.long 0x00000000 /* var[9] */
+.long 0x00000000 /* var[10] */
+.long 0xf0008800 /* var[11] */
+.long 0x00000000 /* var[12] */
+.long 0x80000000 /* var[13] */
+.long 0x10000000 /* var[14] */
+.long 0x08000000 /* var[15] */
+.long 0x20000000 /* var[16] */
+.long 0x0000ffff /* var[17] */
+.long 0xffffffff /* var[18] */
+.long 0x00000008 /* var[19] */
+.long 0x00000000 /* var[20] */
+.long 0x00000000 /* var[21] */
+.long 0x00000000 /* var[22] */
+.long 0x00000000 /* var[23] */
+.long 0x00000000 /* inc[0] */
+.long 0x60000000 /* inc[1] */
+.long 0x40000000 /* inc[2] */
+.long 0x4000ffff /* inc[3] */
+.long 0xe0000001 /* inc[4] */
+.long 0x80000000 /* inc[5] */
+.long 0x00000000 /* inc[6] */
+.long 0x00000000 /* inc[7] */
+
+.align 8
+
+.globl scEthernetRecv_FDT
+scEthernetRecv_FDT: /* Task 0 Function Descriptor Table */
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x21800000 /* and(), EU# 3 */
+.long 0x21400000 /* andn(), EU# 3 */
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+
+.align 8
+
+.globl scEthernetXmit_FDT
+scEthernetXmit_FDT: /* Task 1 Function Descriptor Table */
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x21800000 /* and(), EU# 3 */
+.long 0x21400000 /* andn(), EU# 3 */
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+
+
+.globl scEthernetRecv_CSave
+scEthernetRecv_CSave: /* Task 0 context save space */
+.space 128, 0x0
+
+
+.globl scEthernetXmit_CSave
+scEthernetXmit_CSave: /* Task 1 context save space */
+.space 128, 0x0
+
diff --git a/arch/ppc/mach-mpc5xxx/ide.c b/arch/ppc/mach-mpc5xxx/ide.c
new file mode 100644
index 0000000000..29b99f6b15
--- /dev/null
+++ b/arch/ppc/mach-mpc5xxx/ide.c
@@ -0,0 +1,88 @@
+/*
+ * (C) Copyright 2004
+ * Pierre AUBERT, Staubli Faverges, <p.aubert@staubli.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
+ *
+ * Init is derived from Linux code.
+ */
+#include <common.h>
+
+#ifdef CFG_CMD_IDE
+#include <mpc5xxx.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define CALC_TIMING(t) (t + period - 1) / period
+
+#ifdef CONFIG_IDE_RESET
+extern void init_ide_reset (void);
+#endif
+
+int ide_preinit (void)
+{
+ long period, t0, t1, t2_8, t2_16, t4, ta;
+ vu_long reg;
+ struct mpc5xxx_sdma *psdma = (struct mpc5xxx_sdma *) MPC5XXX_SDMA;
+
+ reg = *(vu_long *) MPC5XXX_GPS_PORT_CONFIG;
+#if defined(CONFIG_TOTAL5200)
+ /* ATA cs0/1 on i2c2 clk/io */
+ reg = (reg & ~0x03000000ul) | 0x02000000ul;
+#else
+ /* ATA cs0/1 on Local Plus cs4/5 */
+ reg = (reg & ~0x03000000ul) | 0x01000000ul;
+#endif /* CONFIG_TOTAL5200 */
+ *(vu_long *) MPC5XXX_GPS_PORT_CONFIG = reg;
+
+ /* All sample codes do that... */
+ *(vu_long *) MPC5XXX_ATA_SHARE_COUNT = 0;
+
+ /* Configure and reset host */
+ *(vu_long *) MPC5XXX_ATA_HOST_CONFIG = MPC5xxx_ATA_HOSTCONF_IORDY |
+ MPC5xxx_ATA_HOSTCONF_SMR | MPC5xxx_ATA_HOSTCONF_FR;
+ udelay (10);
+ *(vu_long *) MPC5XXX_ATA_HOST_CONFIG = MPC5xxx_ATA_HOSTCONF_IORDY;
+
+ /* Disable prefetch on Commbus */
+ psdma->PtdCntrl |= 1;
+
+ /* Init timings : we use PIO mode 0 timings */
+ period = 1000000000 / gd->ipb_clk; /* period in ns */
+
+ t0 = CALC_TIMING (600);
+ t2_8 = CALC_TIMING (290);
+ t2_16 = CALC_TIMING (165);
+ reg = (t0 << 24) | (t2_8 << 16) | (t2_16 << 8);
+ *(vu_long *) MPC5XXX_ATA_PIO1 = reg;
+
+ t4 = CALC_TIMING (30);
+ t1 = CALC_TIMING (70);
+ ta = CALC_TIMING (35);
+ reg = (t4 << 24) | (t1 << 16) | (ta << 8);
+
+ *(vu_long *) MPC5XXX_ATA_PIO2 = reg;
+
+#ifdef CONFIG_IDE_RESET
+ init_ide_reset ();
+#endif /* CONFIG_IDE_RESET */
+
+ return (0);
+}
+#endif /* CFG_CMD_IDE */
diff --git a/arch/ppc/mach-mpc5xxx/interrupts.c b/arch/ppc/mach-mpc5xxx/interrupts.c
new file mode 100644
index 0000000000..8665a066b0
--- /dev/null
+++ b/arch/ppc/mach-mpc5xxx/interrupts.c
@@ -0,0 +1,349 @@
+/*
+ * (C) Copyright 2006
+ * Detlev Zundel, DENX Software Engineering, dzu@denx.de
+ *
+ * (C) Copyright -2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2001
+ * Josh Huber <huber@mclx.com>, Mission Critical Linux, 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
+ */
+
+/* this section was ripped out of arch/ppc/syslib/mpc52xx_pic.c in the
+ * Linux 2.6 source with the following copyright.
+ *
+ * Based on (well, mostly copied from) the code from the 2.4 kernel by
+ * Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg.
+ *
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 Montavista Software, Inc
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <command.h>
+#include <asm/arch/sdma.h>
+#include <asm/bitops.h>
+#include <asm/arch/clocks.h>
+
+struct irq_action {
+ interrupt_handler_t *handler;
+ void *arg;
+ ulong count;
+};
+
+static struct irq_action irq_handlers[NR_IRQS];
+
+static struct mpc5xxx_intr *intr;
+static struct mpc5xxx_sdma *sdma;
+
+static void mpc5xxx_ic_disable(unsigned int irq)
+{
+ u32 val;
+
+ if (irq == MPC5XXX_IRQ0) {
+ val = in_be32(&intr->ctrl);
+ val &= ~(1 << 11);
+ out_be32(&intr->ctrl, val);
+ } else if (irq < MPC5XXX_IRQ1) {
+ BUG();
+ } else if (irq <= MPC5XXX_IRQ3) {
+ val = in_be32(&intr->ctrl);
+ val &= ~(1 << (10 - (irq - MPC5XXX_IRQ1)));
+ out_be32(&intr->ctrl, val);
+ } else if (irq < MPC5XXX_SDMA_IRQ_BASE) {
+ val = in_be32(&intr->main_mask);
+ val |= 1 << (16 - (irq - MPC5XXX_MAIN_IRQ_BASE));
+ out_be32(&intr->main_mask, val);
+ } else if (irq < MPC5XXX_PERP_IRQ_BASE) {
+ val = in_be32(&sdma->IntMask);
+ val |= 1 << (irq - MPC5XXX_SDMA_IRQ_BASE);
+ out_be32(&sdma->IntMask, val);
+ } else {
+ val = in_be32(&intr->per_mask);
+ val |= 1 << (31 - (irq - MPC5XXX_PERP_IRQ_BASE));
+ out_be32(&intr->per_mask, val);
+ }
+}
+
+static void mpc5xxx_ic_enable(unsigned int irq)
+{
+ u32 val;
+
+ if (irq == MPC5XXX_IRQ0) {
+ val = in_be32(&intr->ctrl);
+ val |= 1 << 11;
+ out_be32(&intr->ctrl, val);
+ } else if (irq < MPC5XXX_IRQ1) {
+ BUG();
+ } else if (irq <= MPC5XXX_IRQ3) {
+ val = in_be32(&intr->ctrl);
+ val |= 1 << (10 - (irq - MPC5XXX_IRQ1));
+ out_be32(&intr->ctrl, val);
+ } else if (irq < MPC5XXX_SDMA_IRQ_BASE) {
+ val = in_be32(&intr->main_mask);
+ val &= ~(1 << (16 - (irq - MPC5XXX_MAIN_IRQ_BASE)));
+ out_be32(&intr->main_mask, val);
+ } else if (irq < MPC5XXX_PERP_IRQ_BASE) {
+ val = in_be32(&sdma->IntMask);
+ val &= ~(1 << (irq - MPC5XXX_SDMA_IRQ_BASE));
+ out_be32(&sdma->IntMask, val);
+ } else {
+ val = in_be32(&intr->per_mask);
+ val &= ~(1 << (31 - (irq - MPC5XXX_PERP_IRQ_BASE)));
+ out_be32(&intr->per_mask, val);
+ }
+}
+
+static void mpc5xxx_ic_ack(unsigned int irq)
+{
+ u32 val;
+
+ /*
+ * Only some irqs are reset here, others in interrupting hardware.
+ */
+
+ switch (irq) {
+ case MPC5XXX_IRQ0:
+ val = in_be32(&intr->ctrl);
+ val |= 0x08000000;
+ out_be32(&intr->ctrl, val);
+ break;
+ case MPC5XXX_CCS_IRQ:
+ val = in_be32(&intr->enc_status);
+ val |= 0x00000400;
+ out_be32(&intr->enc_status, val);
+ break;
+ case MPC5XXX_IRQ1:
+ val = in_be32(&intr->ctrl);
+ val |= 0x04000000;
+ out_be32(&intr->ctrl, val);
+ break;
+ case MPC5XXX_IRQ2:
+ val = in_be32(&intr->ctrl);
+ val |= 0x02000000;
+ out_be32(&intr->ctrl, val);
+ break;
+ case MPC5XXX_IRQ3:
+ val = in_be32(&intr->ctrl);
+ val |= 0x01000000;
+ out_be32(&intr->ctrl, val);
+ break;
+ default:
+ if (irq >= MPC5XXX_SDMA_IRQ_BASE
+ && irq < (MPC5XXX_SDMA_IRQ_BASE + MPC5XXX_SDMA_IRQ_NUM)) {
+ out_be32(&sdma->IntPend,
+ 1 << (irq - MPC5XXX_SDMA_IRQ_BASE));
+ }
+ break;
+ }
+}
+
+static void mpc5xxx_ic_disable_and_ack(unsigned int irq)
+{
+ mpc5xxx_ic_disable(irq);
+ mpc5xxx_ic_ack(irq);
+}
+
+static void mpc5xxx_ic_end(unsigned int irq)
+{
+ mpc5xxx_ic_enable(irq);
+}
+
+void mpc5xxx_init_irq(void)
+{
+ u32 intr_ctrl;
+
+ /* Remap the necessary zones */
+ intr = (struct mpc5xxx_intr *)(MPC5XXX_ICTL);
+ sdma = (struct mpc5xxx_sdma *)(MPC5XXX_SDMA);
+
+ /* Disable all interrupt sources. */
+ out_be32(&sdma->IntPend, 0xffffffff); /* 1 means clear pending */
+ out_be32(&sdma->IntMask, 0xffffffff); /* 1 means disabled */
+ out_be32(&intr->per_mask, 0x7ffffc00); /* 1 means disabled */
+ out_be32(&intr->main_mask, 0x00010fff); /* 1 means disabled */
+ intr_ctrl = in_be32(&intr->ctrl);
+ intr_ctrl |= 0x0f000000 | /* clear IRQ 0-3 */
+ 0x00ff0000 | /* IRQ 0-3 level sensitive low active */
+ 0x00001000 | /* MEE master external enable */
+ 0x00000000 | /* 0 means disable IRQ 0-3 */
+ 0x00000001; /* CEb route critical normally */
+ out_be32(&intr->ctrl, intr_ctrl);
+
+ /* Zero a bunch of the priority settings. */
+ out_be32(&intr->per_pri1, 0);
+ out_be32(&intr->per_pri2, 0);
+ out_be32(&intr->per_pri3, 0);
+ out_be32(&intr->main_pri1, 0);
+ out_be32(&intr->main_pri2, 0);
+}
+
+int mpc5xxx_get_irq(struct pt_regs *regs)
+{
+ u32 status;
+ int irq = -1;
+
+ status = in_be32(&intr->enc_status);
+
+ if (status & 0x00000400) { /* critical */
+ irq = (status >> 8) & 0x3;
+ if (irq == 2) /* high priority peripheral */
+ goto peripheral;
+ irq += MPC5XXX_CRIT_IRQ_BASE;
+ } else if (status & 0x00200000) { /* main */
+ irq = (status >> 16) & 0x1f;
+ if (irq == 4) /* low priority peripheral */
+ goto peripheral;
+ irq += MPC5XXX_MAIN_IRQ_BASE;
+ } else if (status & 0x20000000) { /* peripheral */
+ peripheral:
+ irq = (status >> 24) & 0x1f;
+ if (irq == 0) { /* bestcomm */
+ status = in_be32(&sdma->IntPend);
+ irq = ffs(status) + MPC5XXX_SDMA_IRQ_BASE - 1;
+ } else
+ irq += MPC5XXX_PERP_IRQ_BASE;
+ }
+
+ return irq;
+}
+
+/****************************************************************************/
+
+int interrupt_init_cpu(ulong * decrementer_count)
+{
+ *decrementer_count = get_timebase_clock() / 1000;
+
+ mpc5xxx_init_irq();
+
+ return 0;
+}
+
+/****************************************************************************/
+
+/*
+ * Handle external interrupts
+ */
+void external_interrupt(struct pt_regs *regs)
+{
+ int irq, unmask = 1;
+
+ irq = mpc5xxx_get_irq(regs);
+
+ mpc5xxx_ic_disable_and_ack(irq);
+
+ enable_interrupts();
+
+ if (irq_handlers[irq].handler != NULL)
+ (*irq_handlers[irq].handler) (irq_handlers[irq].arg);
+ else {
+ printf("\nBogus External Interrupt IRQ %d\n", irq);
+ /*
+ * turn off the bogus interrupt, otherwise it
+ * might repeat forever
+ */
+ unmask = 0;
+ }
+
+ if (unmask)
+ mpc5xxx_ic_end(irq);
+}
+
+void timer_interrupt_cpu(struct pt_regs *regs)
+{
+ /* nothing to do here */
+ return;
+}
+
+/****************************************************************************/
+
+/*
+ * Install and free a interrupt handler.
+ */
+
+void irq_install_handler(int irq, interrupt_handler_t * handler, void *arg)
+{
+ if (irq < 0 || irq >= NR_IRQS) {
+ printf("irq_install_handler: bad irq number %d\n", irq);
+ return;
+ }
+
+ if (irq_handlers[irq].handler != NULL)
+ printf("irq_install_handler: 0x%08lx replacing 0x%08lx\n",
+ (ulong) handler, (ulong) irq_handlers[irq].handler);
+
+ irq_handlers[irq].handler = handler;
+ irq_handlers[irq].arg = arg;
+
+ mpc5xxx_ic_enable(irq);
+}
+
+void irq_free_handler(int irq)
+{
+ if (irq < 0 || irq >= NR_IRQS) {
+ printf("irq_free_handler: bad irq number %d\n", irq);
+ return;
+ }
+
+ mpc5xxx_ic_disable(irq);
+
+ irq_handlers[irq].handler = NULL;
+ irq_handlers[irq].arg = NULL;
+}
+
+/****************************************************************************/
+
+#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
+void do_irqinfo(cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char *argv[])
+{
+ int irq, re_enable;
+ u32 intr_ctrl;
+ char *irq_config[] = { "level sensitive, active high",
+ "edge sensitive, rising active edge",
+ "edge sensitive, falling active edge",
+ "level sensitive, active low"
+ };
+
+ re_enable = disable_interrupts();
+
+ intr_ctrl = in_be32(&intr->ctrl);
+ printf("Interrupt configuration:\n");
+
+ for (irq = 0; irq <= 3; irq++) {
+ printf("IRQ%d: %s\n", irq,
+ irq_config[(intr_ctrl >> (22 - 2 * irq)) & 0x3]);
+ }
+
+ puts("\nInterrupt-Information:\n" "Nr Routine Arg Count\n");
+
+ for (irq = 0; irq < NR_IRQS; irq++)
+ if (irq_handlers[irq].handler != NULL)
+ printf("%02d %08lx %08lx %ld\n", irq,
+ (ulong) irq_handlers[irq].handler,
+ (ulong) irq_handlers[irq].arg,
+ irq_handlers[irq].count);
+
+ if (re_enable)
+ enable_interrupts();
+}
+#endif
diff --git a/arch/ppc/mach-mpc5xxx/io.S b/arch/ppc/mach-mpc5xxx/io.S
new file mode 100644
index 0000000000..2178a26763
--- /dev/null
+++ b/arch/ppc/mach-mpc5xxx/io.S
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ * Copyright (C) 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <aheppel@sysgo.de>
+ * Copyright (C) 2003 Wolfgang Denk <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 <ppc_asm.tmpl>
+
+/* ------------------------------------------------------------------------------- */
+/* Function: in8 */
+/* Description: Input 8 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl in8
+in8:
+ lbz r3,0(r3)
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: in16 */
+/* Description: Input 16 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl in16
+in16:
+ lhz r3,0(r3)
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: in16r */
+/* Description: Input 16 bits and byte reverse */
+/* ------------------------------------------------------------------------------- */
+ .globl in16r
+in16r:
+ lhbrx r3,0,r3
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: in32 */
+/* Description: Input 32 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl in32
+in32:
+ lwz 3,0(3)
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: in32r */
+/* Description: Input 32 bits and byte reverse */
+/* ------------------------------------------------------------------------------- */
+ .globl in32r
+in32r:
+ lwbrx r3,0,r3
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: out8 */
+/* Description: Output 8 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl out8
+out8:
+ stb r4,0(r3)
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: out16 */
+/* Description: Output 16 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl out16
+out16:
+ sth r4,0(r3)
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: out16r */
+/* Description: Byte reverse and output 16 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl out16r
+out16r:
+ sthbrx r4,0,r3
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: out32 */
+/* Description: Output 32 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl out32
+out32:
+ stw r4,0(r3)
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: out32r */
+/* Description: Byte reverse and output 32 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl out32r
+out32r:
+ stwbrx r4,0,r3
+ sync
+ blr
diff --git a/arch/ppc/mach-mpc5xxx/loadtask.c b/arch/ppc/mach-mpc5xxx/loadtask.c
new file mode 100644
index 0000000000..77ba8c89d2
--- /dev/null
+++ b/arch/ppc/mach-mpc5xxx/loadtask.c
@@ -0,0 +1,77 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * This file is based on code
+ * (C) Copyright Motorola, Inc., 2000
+ */
+
+#include <common.h>
+#include <asm/arch/mpc5xxx.h>
+#include <types.h>
+
+/* BestComm/SmartComm microcode */
+extern int taskTable;
+
+void loadtask(int basetask, int tasks)
+{
+ int *sram = (int *)MPC5XXX_SRAM;
+ int *task_org = &taskTable;
+ unsigned int start, offset, end;
+ int i;
+
+#ifdef DEBUG
+ printf("basetask = %d, tasks = %d\n", basetask, tasks);
+ printf("task_org = 0x%08x\n", (unsigned int)task_org);
+#endif
+
+ /* setup TaskBAR register */
+ *(vu_long *)MPC5XXX_SDMA = MPC5XXX_SRAM;
+
+ /* relocate task table entries */
+ offset = (unsigned int)sram;
+ for (i = basetask; i < basetask + tasks; i++) {
+ sram[i * 8 + 0] = task_org[i * 8 + 0] + offset;
+ sram[i * 8 + 1] = task_org[i * 8 + 1] + offset;
+ sram[i * 8 + 2] = task_org[i * 8 + 2] + offset;
+ sram[i * 8 + 3] = task_org[i * 8 + 3] + offset;
+ sram[i * 8 + 4] = task_org[i * 8 + 4];
+ sram[i * 8 + 5] = task_org[i * 8 + 5];
+ sram[i * 8 + 6] = task_org[i * 8 + 6] + offset;
+ sram[i * 8 + 7] = task_org[i * 8 + 7];
+ }
+
+ /* relocate task descriptors */
+ start = (sram[basetask * 8] - (unsigned int)sram);
+ end = (sram[(basetask + tasks - 1) * 8 + 1] - (unsigned int)sram);
+
+#ifdef DEBUG
+ printf ("TDT start = 0x%08x, end = 0x%08x\n", start, end);
+#endif
+
+ start /= 4;
+ end /= 4;
+ for (i = start; i <= end; i++) {
+ sram[i] = task_org[i];
+ }
+
+ /* relocate variables */
+ start = (sram[basetask * 8 + 2] - (unsigned int)sram);
+ end = (sram[(basetask + tasks - 1) * 8 + 2] + 256 - (unsigned int)sram);
+ start /= 4;
+ end /= 4;
+ for (i = start; i < end; i++) {
+ sram[i] = task_org[i];
+ }
+
+ /* relocate function decriptors */
+ start = ((sram[basetask * 8 + 3] & 0xfffffffc) - (unsigned int)sram);
+ end = ((sram[(basetask + tasks - 1) * 8 + 3] & 0xfffffffc) + 256 - (unsigned int)sram);
+ start /= 4;
+ end /= 4;
+ for (i = start; i < end; i++) {
+ sram[i] = task_org[i];
+ }
+
+ asm volatile ("sync");
+}
diff --git a/arch/ppc/mach-mpc5xxx/pci_mpc5200.c b/arch/ppc/mach-mpc5xxx/pci_mpc5200.c
new file mode 100644
index 0000000000..a7de4a2268
--- /dev/null
+++ b/arch/ppc/mach-mpc5xxx/pci_mpc5200.c
@@ -0,0 +1,187 @@
+/*
+ * (C) Copyright 2000-2003
+ * 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>
+
+#if defined(CONFIG_PCI) && defined(CONFIG_MPC5200)
+
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <pci.h>
+#include <mpc5xxx.h>
+
+/* System RAM mapped over PCI */
+#define CONFIG_PCI_MEMORY_BUS CFG_SDRAM_BASE
+#define CONFIG_PCI_MEMORY_PHYS CFG_SDRAM_BASE
+#define CONFIG_PCI_MEMORY_SIZE (1024 * 1024 * 1024)
+
+/* PCIIWCR bit fields */
+#define IWCR_MEM (0 << 3)
+#define IWCR_IO (1 << 3)
+#define IWCR_READ (0 << 1)
+#define IWCR_READLINE (1 << 1)
+#define IWCR_READMULT (2 << 1)
+#define IWCR_EN (1 << 0)
+
+static int mpc5200_read_config_dword(struct pci_controller *hose,
+ pci_dev_t dev, int offset, u32* value)
+{
+ *(volatile u32 *)MPC5XXX_PCI_CAR = (1 << 31) | dev | offset;
+ eieio();
+ udelay(10);
+#if (defined CONFIG_PF5200 || defined CONFIG_CPCI5200)
+ if (dev & 0x00ff0000) {
+ u32 val;
+ val = in_le16((volatile u16 *)(CONFIG_PCI_IO_PHYS+2));
+ udelay(10);
+ val = val << 16;
+ val |= in_le16((volatile u16 *)(CONFIG_PCI_IO_PHYS+0));
+ *value = val;
+ } else {
+ *value = in_le32((volatile u32 *)CONFIG_PCI_IO_PHYS);
+ }
+ udelay(10);
+#else
+ *value = in_le32((volatile u32 *)CONFIG_PCI_IO_PHYS);
+#endif
+ eieio();
+ *(volatile u32 *)MPC5XXX_PCI_CAR = 0;
+ udelay(10);
+ return 0;
+}
+
+static int mpc5200_write_config_dword(struct pci_controller *hose,
+ pci_dev_t dev, int offset, u32 value)
+{
+ *(volatile u32 *)MPC5XXX_PCI_CAR = (1 << 31) | dev | offset;
+ eieio();
+ udelay(10);
+ out_le32((volatile u32 *)CONFIG_PCI_IO_PHYS, value);
+ eieio();
+ *(volatile u32 *)MPC5XXX_PCI_CAR = 0;
+ udelay(10);
+ return 0;
+}
+
+void pci_mpc5xxx_init (struct pci_controller *hose)
+{
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+
+ /* System space */
+ pci_set_region(hose->regions + 0,
+ CONFIG_PCI_MEMORY_BUS,
+ CONFIG_PCI_MEMORY_PHYS,
+ CONFIG_PCI_MEMORY_SIZE,
+ PCI_REGION_MEM | PCI_REGION_MEMORY);
+
+ /* PCI memory space */
+ pci_set_region(hose->regions + 1,
+ CONFIG_PCI_MEM_BUS,
+ CONFIG_PCI_MEM_PHYS,
+ CONFIG_PCI_MEM_SIZE,
+ PCI_REGION_MEM);
+
+ /* PCI IO space */
+ pci_set_region(hose->regions + 2,
+ CONFIG_PCI_IO_BUS,
+ CONFIG_PCI_IO_PHYS,
+ CONFIG_PCI_IO_SIZE,
+ PCI_REGION_IO);
+
+ hose->region_count = 3;
+
+ pci_register_hose(hose);
+
+ /* GPIO Multiplexing - enable PCI */
+ *(vu_long *)MPC5XXX_GPS_PORT_CONFIG &= ~(1 << 15);
+
+ /* Set host bridge as pci master and enable memory decoding */
+ *(vu_long *)MPC5XXX_PCI_CMD |=
+ PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+
+ /* Set maximum latency timer */
+ *(vu_long *)MPC5XXX_PCI_CFG |= (0xf800);
+
+ /* Set cache line size */
+ *(vu_long *)MPC5XXX_PCI_CFG = (*(vu_long *)MPC5XXX_PCI_CFG & ~0xff) |
+ (CONFIG_CACHELINE_SIZE / 4);
+
+ /* Map MBAR to PCI space */
+ *(vu_long *)MPC5XXX_PCI_BAR0 = CFG_MBAR;
+ *(vu_long *)MPC5XXX_PCI_TBATR0 = CFG_MBAR | 1;
+
+ /* Map RAM to PCI space */
+ *(vu_long *)MPC5XXX_PCI_BAR1 = CONFIG_PCI_MEMORY_BUS | (1 << 3);
+ *(vu_long *)MPC5XXX_PCI_TBATR1 = CONFIG_PCI_MEMORY_PHYS | 1;
+
+ /* Park XLB on PCI */
+ *(vu_long *)(MPC5XXX_XLBARB + 0x40) &= ~((7 << 8) | (3 << 5));
+ *(vu_long *)(MPC5XXX_XLBARB + 0x40) |= (3 << 8) | (3 << 5);
+
+ /* Disable interrupts from PCI controller */
+ *(vu_long *)MPC5XXX_PCI_GSCR &= ~(7 << 12);
+ *(vu_long *)MPC5XXX_PCI_ICR &= ~(7 << 24);
+
+ /* Set PCI retry counter to 0 = infinite retry. */
+ /* The default of 255 is too short for slow devices. */
+ *(vu_long *)MPC5XXX_PCI_ICR &= 0xFFFFFF00;
+
+ /* Disable initiator windows */
+ *(vu_long *)MPC5XXX_PCI_IWCR = 0;
+
+ /* Map PCI memory to physical space */
+ *(vu_long *)MPC5XXX_PCI_IW0BTAR = CONFIG_PCI_MEM_PHYS |
+ (((CONFIG_PCI_MEM_SIZE - 1) >> 8) & 0x00ff0000) |
+ (CONFIG_PCI_MEM_BUS >> 16);
+ *(vu_long *)MPC5XXX_PCI_IWCR |= (IWCR_MEM | IWCR_READ | IWCR_EN) << 24;
+
+ /* Map PCI I/O to physical space */
+ *(vu_long *)MPC5XXX_PCI_IW1BTAR = CONFIG_PCI_IO_PHYS |
+ (((CONFIG_PCI_IO_SIZE - 1) >> 8) & 0x00ff0000) |
+ (CONFIG_PCI_IO_BUS >> 16);
+ *(vu_long *)MPC5XXX_PCI_IWCR |= (IWCR_IO | IWCR_READ | IWCR_EN) << 16;
+
+ /* Reset the PCI bus */
+ *(vu_long *)MPC5XXX_PCI_GSCR |= 1;
+ udelay(1000);
+ *(vu_long *)MPC5XXX_PCI_GSCR &= ~1;
+ udelay(1000);
+
+ pci_set_ops(hose,
+ pci_hose_read_config_byte_via_dword,
+ pci_hose_read_config_word_via_dword,
+ mpc5200_read_config_dword,
+ pci_hose_write_config_byte_via_dword,
+ pci_hose_write_config_word_via_dword,
+ mpc5200_write_config_dword);
+
+ udelay(1000);
+
+#ifdef CONFIG_PCI_SCAN_SHOW
+ printf("PCI: Bus Dev VenId DevId Class Int\n");
+#endif
+
+ hose->last_busno = pci_hose_scan(hose);
+}
+#endif /* CONFIG_PCI && CONFIG_MPC5200 */
diff --git a/arch/ppc/mach-mpc5xxx/reginfo.c b/arch/ppc/mach-mpc5xxx/reginfo.c
new file mode 100644
index 0000000000..130e0357d6
--- /dev/null
+++ b/arch/ppc/mach-mpc5xxx/reginfo.c
@@ -0,0 +1,59 @@
+#include <stdio.h>
+#include <config.h>
+#include <asm/arch/mpc5xxx.h>
+
+void reginfo(void)
+{
+ puts ("\nMPC5200 registers\n");
+ printf ("MBAR=%08x\n", CFG_MBAR);
+ puts ("Memory map registers\n");
+ printf ("\tCS0: start %08X\tstop %08X\tconfig %08X\ten %d\n",
+ *(volatile ulong*)MPC5XXX_CS0_START,
+ *(volatile ulong*)MPC5XXX_CS0_STOP,
+ *(volatile ulong*)MPC5XXX_CS0_CFG,
+ (*(volatile ulong*)MPC5XXX_ADDECR & 0x00010000) ? 1 : 0);
+ printf ("\tCS1: start %08X\tstop %08X\tconfig %08X\ten %d\n",
+ *(volatile ulong*)MPC5XXX_CS1_START,
+ *(volatile ulong*)MPC5XXX_CS1_STOP,
+ *(volatile ulong*)MPC5XXX_CS1_CFG,
+ (*(volatile ulong*)MPC5XXX_ADDECR & 0x00020000) ? 1 : 0);
+ printf ("\tCS2: start %08X\tstop %08X\tconfig %08X\ten %d\n",
+ *(volatile ulong*)MPC5XXX_CS2_START,
+ *(volatile ulong*)MPC5XXX_CS2_STOP,
+ *(volatile ulong*)MPC5XXX_CS2_CFG,
+ (*(volatile ulong*)MPC5XXX_ADDECR & 0x00040000) ? 1 : 0);
+ printf ("\tCS3: start %08X\tstop %08X\tconfig %08X\ten %d\n",
+ *(volatile ulong*)MPC5XXX_CS3_START,
+ *(volatile ulong*)MPC5XXX_CS3_STOP,
+ *(volatile ulong*)MPC5XXX_CS3_CFG,
+ (*(volatile ulong*)MPC5XXX_ADDECR & 0x00080000) ? 1 : 0);
+ printf ("\tCS4: start %08X\tstop %08X\tconfig %08X\ten %d\n",
+ *(volatile ulong*)MPC5XXX_CS4_START,
+ *(volatile ulong*)MPC5XXX_CS4_STOP,
+ *(volatile ulong*)MPC5XXX_CS4_CFG,
+ (*(volatile ulong*)MPC5XXX_ADDECR & 0x00100000) ? 1 : 0);
+ printf ("\tCS5: start %08X\tstop %08X\tconfig %08X\ten %d\n",
+ *(volatile ulong*)MPC5XXX_CS5_START,
+ *(volatile ulong*)MPC5XXX_CS5_STOP,
+ *(volatile ulong*)MPC5XXX_CS5_CFG,
+ (*(volatile ulong*)MPC5XXX_ADDECR & 0x00200000) ? 1 : 0);
+ printf ("\tCS6: start %08X\tstop %08X\tconfig %08X\ten %d\n",
+ *(volatile ulong*)MPC5XXX_CS6_START,
+ *(volatile ulong*)MPC5XXX_CS6_STOP,
+ *(volatile ulong*)MPC5XXX_CS6_CFG,
+ (*(volatile ulong*)MPC5XXX_ADDECR & 0x04000000) ? 1 : 0);
+ printf ("\tCS7: start %08X\tstop %08X\tconfig %08X\ten %d\n",
+ *(volatile ulong*)MPC5XXX_CS7_START,
+ *(volatile ulong*)MPC5XXX_CS7_STOP,
+ *(volatile ulong*)MPC5XXX_CS7_CFG,
+ (*(volatile ulong*)MPC5XXX_ADDECR & 0x08000000) ? 1 : 0);
+ printf ("\tBOOTCS: start %08X\tstop %08X\tconfig %08X\ten %d\n",
+ *(volatile ulong*)MPC5XXX_BOOTCS_START,
+ *(volatile ulong*)MPC5XXX_BOOTCS_STOP,
+ *(volatile ulong*)MPC5XXX_BOOTCS_CFG,
+ (*(volatile ulong*)MPC5XXX_ADDECR & 0x02000000) ? 1 : 0);
+ printf ("\tSDRAMCS0: %08X\n",
+ *(volatile ulong*)MPC5XXX_SDRAM_CS0CFG);
+ printf ("\tSDRAMCS1: %08X\n",
+ *(volatile ulong*)MPC5XXX_SDRAM_CS1CFG);
+}
diff --git a/arch/ppc/mach-mpc5xxx/speed.c b/arch/ppc/mach-mpc5xxx/speed.c
new file mode 100644
index 0000000000..7207016831
--- /dev/null
+++ b/arch/ppc/mach-mpc5xxx/speed.c
@@ -0,0 +1,107 @@
+/*
+ * (C) Copyright 2000-2002
+ * 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/arch/mpc5xxx.h>
+#include <init.h>
+#include <asm/processor.h>
+#include <types.h>
+
+/* Bus-to-Core Multipliers */
+
+static int bus2core[] = {
+ 3, 2, 2, 2, 4, 4, 5, 9,
+ 6, 11, 8, 10, 3, 12, 7, 0,
+ 6, 5, 13, 2, 14, 4, 15, 9,
+ 0, 11, 8, 10, 16, 12, 7, 0
+};
+
+unsigned long get_bus_clock(void)
+{
+ unsigned long val, vco;
+
+#if !defined(CFG_MPC5XXX_CLKIN)
+#error clock measuring not implemented yet - define CFG_MPC5XXX_CLKIN
+#endif
+
+ val = *(vu_long *)MPC5XXX_CDM_PORCFG;
+ if (val & (1 << 6))
+ vco = CFG_MPC5XXX_CLKIN * 12;
+ else
+ vco = CFG_MPC5XXX_CLKIN * 16;
+
+ if (val & (1 << 5))
+ return vco / 8;
+ else
+ return vco / 4;
+}
+
+unsigned long get_cpu_clock(void)
+{
+ unsigned long val;
+ val = *(vu_long *)MPC5XXX_CDM_PORCFG;
+ return get_bus_clock() * bus2core[val & 0x1f] / 2;
+}
+
+unsigned long get_ipb_clock(void)
+{
+ unsigned long val;
+
+ val = *(vu_long *)MPC5XXX_CDM_CFG;
+ if (val & (1 << 8))
+ return get_bus_clock() / 2;
+ else
+ return get_bus_clock();
+}
+
+unsigned long get_pci_clock(void)
+{
+ unsigned long val;
+
+ val = *(vu_long *)MPC5XXX_CDM_CFG;
+ switch (val & 3) {
+ case 0:
+ return get_ipb_clock();
+ case 1:
+ return get_ipb_clock() / 2;
+ default:
+ return get_bus_clock() / 4;
+ }
+}
+
+unsigned long get_timebase_clock(void)
+{
+ return (get_bus_clock() + 3L) / 4L;
+}
+
+int prt_mpc5xxx_clks (void)
+{
+ printf(" Bus %ld MHz, IPB %ld MHz, PCI %ld MHz\n",
+ get_bus_clock() / 1000000, get_ipb_clock() / 1000000,
+ get_pci_clock() / 1000000);
+
+ return 0;
+}
+
+late_initcall(prt_mpc5xxx_clks);
+
diff --git a/arch/ppc/mach-mpc5xxx/start.S b/arch/ppc/mach-mpc5xxx/start.S
new file mode 100644
index 0000000000..e9fe76ebbd
--- /dev/null
+++ b/arch/ppc/mach-mpc5xxx/start.S
@@ -0,0 +1,797 @@
+/*
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ * Copyright (C) 2000 - 2003 Wolfgang Denk <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
+ */
+
+/*
+ * U-Boot - Startup Code for MPC5xxx CPUs
+ */
+#include <config.h>
+#include <asm/arch/mpc5xxx.h>
+
+#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
+
+/* We don't want the MMU yet.
+*/
+#undef MSR_KERNEL
+/* Floating Point enable, Machine Check and Recoverable Interr. */
+#ifdef DEBUG
+#define MSR_KERNEL (MSR_FP|MSR_RI)
+#else
+#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
+#endif
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r14 to access the GOT
+ */
+ START_GOT
+ GOT_ENTRY(_GOT2_TABLE_)
+ GOT_ENTRY(_FIXUP_TABLE_)
+
+ GOT_ENTRY(_start)
+ GOT_ENTRY(_start_of_vectors)
+ GOT_ENTRY(_end_of_vectors)
+ GOT_ENTRY(transfer_to_handler)
+
+ GOT_ENTRY(__init_end)
+ GOT_ENTRY(_end)
+ GOT_ENTRY(__bss_start)
+ END_GOT
+
+/*
+ * Exception vectors
+ */
+ .text
+ . = EXC_OFF_SYS_RESET
+ .globl _start
+_start:
+ li r21, BOOTFLAG_COLD /* Normal Power-On */
+ nop
+ b boot_cold
+
+ . = EXC_OFF_SYS_RESET + 0x10
+
+ .globl _start_warm
+_start_warm:
+ li r21, BOOTFLAG_WARM /* Software reboot */
+ b boot_warm
+
+boot_cold:
+boot_warm:
+ mfmsr r5 /* save msr contents */
+
+ /* Move CSBoot and adjust instruction pointer */
+ /*--------------------------------------------------------------*/
+
+#if defined(CFG_LOWBOOT)
+# if defined(CFG_RAMBOOT)
+# error CFG_LOWBOOT is incompatible with CFG_RAMBOOT
+# endif /* CFG_RAMBOOT */
+# if defined(CONFIG_MGT5100)
+# error CFG_LOWBOOT is incompatible with MGT5100
+# endif /* CONFIG_MGT5100 */
+ lis r4, CFG_DEFAULT_MBAR@h
+ lis r3, START_REG(CFG_BOOTCS_START)@h
+ ori r3, r3, START_REG(CFG_BOOTCS_START)@l
+ stw r3, 0x4(r4) /* CS0 start */
+ lis r3, STOP_REG(CFG_BOOTCS_START, CFG_BOOTCS_SIZE)@h
+ ori r3, r3, STOP_REG(CFG_BOOTCS_START, CFG_BOOTCS_SIZE)@l
+ stw r3, 0x8(r4) /* CS0 stop */
+ lis r3, 0x02010000@h
+ ori r3, r3, 0x02010000@l
+ stw r3, 0x54(r4) /* CS0 and Boot enable */
+
+ lis r3, lowboot_reentry@h /* jump from bootlow address space (0x0000xxxx) */
+ ori r3, r3, lowboot_reentry@l /* to the address space the linker used */
+ mtlr r3
+ blr
+
+lowboot_reentry:
+ lis r3, START_REG(CFG_BOOTCS_START)@h
+ ori r3, r3, START_REG(CFG_BOOTCS_START)@l
+ stw r3, 0x4c(r4) /* Boot start */
+ lis r3, STOP_REG(CFG_BOOTCS_START, CFG_BOOTCS_SIZE)@h
+ ori r3, r3, STOP_REG(CFG_BOOTCS_START, CFG_BOOTCS_SIZE)@l
+ stw r3, 0x50(r4) /* Boot stop */
+ lis r3, 0x02000001@h
+ ori r3, r3, 0x02000001@l
+ stw r3, 0x54(r4) /* Boot enable, CS0 disable */
+#endif /* CFG_LOWBOOT */
+
+#if defined(CFG_DEFAULT_MBAR) && !defined(CFG_RAMBOOT)
+ lis r3, CFG_MBAR@h
+ ori r3, r3, CFG_MBAR@l
+#if defined(CONFIG_MPC5200)
+ /* MBAR is mirrored into the MBAR SPR */
+ mtspr MBAR,r3
+ rlwinm r3, r3, 16, 16, 31
+#endif
+#if defined(CONFIG_MGT5100)
+ rlwinm r3, r3, 17, 15, 31
+#endif
+ lis r4, CFG_DEFAULT_MBAR@h
+ stw r3, 0(r4)
+#endif /* CFG_DEFAULT_MBAR */
+
+ /* Initialise the MPC5xxx processor core */
+ /*--------------------------------------------------------------*/
+
+ bl init_5xxx_core
+
+ /* initialize some things that are hard to access from C */
+ /*--------------------------------------------------------------*/
+
+ /* set up stack in on-chip SRAM */
+ lis r3, CFG_INIT_RAM_ADDR@h
+ ori r3, r3, CFG_INIT_RAM_ADDR@l
+ ori r1, r3, CFG_INIT_SP_OFFSET
+ li r0, 0 /* Make room for stack frame header and */
+ stwu r0, -4(r1) /* clear final stack frame so that */
+ stwu r0, -4(r1) /* stack backtraces terminate cleanly */
+
+ /* let the C-code set up the rest */
+ /* */
+ /* Be careful to keep code relocatable ! */
+ /*--------------------------------------------------------------*/
+
+ GET_GOT /* initialize GOT access */
+
+ /* r3: IMMR */
+ bl cpu_init_f /* run low-level CPU init code (in Flash)*/
+
+ mr r3, r21
+ /* r3: BOOTFLAG */
+ bl initdram /* initialize sdram */
+ /* r3: End of RAM */
+
+ b _continue_init
+/*
+ * Vector Table
+ */
+
+ .globl _start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+ STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. */
+ STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. */
+ STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+#ifdef CONFIG_INTERRUPTS
+ STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
+#endif
+
+/* Alignment exception. */
+ . = 0x600
+Alignment:
+ EXCEPTION_PROLOG
+ mfspr r4,DAR
+ stw r4,_DAR(r21)
+ mfspr r5,DSISR
+ stw r5,_DSISR(r21)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r20,MSR_KERNEL
+ rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
+ rlwimi r20,r23,0,25,25 /* copy IP bit from saved MSR */
+ lwz r6,GOT(transfer_to_handler)
+ mtlr r6
+ blrl
+.L_Alignment:
+ .long AlignmentException - _start + EXC_OFF_SYS_RESET
+ .long int_return - _start + EXC_OFF_SYS_RESET
+
+/* Program check exception */
+ . = 0x700
+ProgramCheck:
+ EXCEPTION_PROLOG
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r20,MSR_KERNEL
+ rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
+ rlwimi r20,r23,0,25,25 /* copy IP bit from saved MSR */
+ lwz r6,GOT(transfer_to_handler)
+ mtlr r6
+ blrl
+.L_ProgramCheck:
+ .long ProgramCheckException - _start + EXC_OFF_SYS_RESET
+ .long int_return - _start + EXC_OFF_SYS_RESET
+
+ STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+ /* I guess we could implement decrementer, and may have
+ * to someday for timekeeping.
+ */
+#ifdef CONFIG_INTERRUPTS
+ STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+#else
+ STD_EXCEPTION(0x900, Decrementer, UnknownException)
+#endif
+ STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+ STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+ STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+ STD_EXCEPTION(0xd00, SingleStep, UnknownException)
+
+ STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+ STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+
+ STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
+#ifdef DEBUG
+ . = 0x1300
+ /*
+ * This exception occurs when the program counter matches the
+ * Instruction Address Breakpoint Register (IABR).
+ *
+ * I want the cpu to halt if this occurs so I can hunt around
+ * with the debugger and look at things.
+ *
+ * When DEBUG is defined, both machine check enable (in the MSR)
+ * and checkstop reset enable (in the reset mode register) are
+ * turned off and so a checkstop condition will result in the cpu
+ * halting.
+ *
+ * I force the cpu into a checkstop condition by putting an illegal
+ * instruction here (at least this is the theory).
+ *
+ * well - that didnt work, so just do an infinite loop!
+ */
+1: b 1b
+#else
+ STD_EXCEPTION(0x1300, InstructionBreakpoint, DebugException)
+#endif
+ STD_EXCEPTION(0x1400, SMI, UnknownException)
+
+ STD_EXCEPTION(0x1500, Trap_15, UnknownException)
+ STD_EXCEPTION(0x1600, Trap_16, UnknownException)
+ STD_EXCEPTION(0x1700, Trap_17, UnknownException)
+ STD_EXCEPTION(0x1800, Trap_18, UnknownException)
+ STD_EXCEPTION(0x1900, Trap_19, UnknownException)
+ STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
+ STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
+ STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
+ STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
+ STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
+ STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
+ STD_EXCEPTION(0x2000, Trap_20, UnknownException)
+ STD_EXCEPTION(0x2100, Trap_21, UnknownException)
+ STD_EXCEPTION(0x2200, Trap_22, UnknownException)
+ STD_EXCEPTION(0x2300, Trap_23, UnknownException)
+ STD_EXCEPTION(0x2400, Trap_24, UnknownException)
+ STD_EXCEPTION(0x2500, Trap_25, UnknownException)
+ STD_EXCEPTION(0x2600, Trap_26, UnknownException)
+ STD_EXCEPTION(0x2700, Trap_27, UnknownException)
+ STD_EXCEPTION(0x2800, Trap_28, UnknownException)
+ STD_EXCEPTION(0x2900, Trap_29, UnknownException)
+ STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
+ STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
+ STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
+ STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
+ STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
+ STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
+
+
+ .globl _end_of_vectors
+_end_of_vectors:
+
+ . = 0x3000
+
+_continue_init:
+
+ mr r1, r3 /* Set new stack pointer at end of RAM */
+ subi r1, r1, 0x10
+ mr r9, r3 /* Save copy of end of RAM */
+
+ lis r3, CFG_MONITOR_BASE@h /* Destination Address */
+ ori r3, r3, CFG_MONITOR_BASE@l
+ mr r10, r3 /* Save copy of Destination Address */
+
+ bl calc_source /* Calculate Source Address */
+calc_source:
+ mfspr r4, LR
+ subi r4, r4, (calc_source - _start)
+ subi r4, r4, 0x100
+
+ lis r5, __init_size@h /* Size */
+ ori r5, r5, __init_size@l
+
+ li r6, CONFIG_CACHELINE_SIZE /* Cache Line Size */
+
+ /*
+ * Fix GOT pointer:
+ *
+ * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
+ *
+ * Offset:
+ */
+ sub r15, r10, r4
+
+ /* First our own GOT */
+ add r14, r14, r15
+ /* then the one used by the C code */
+ add r30, r30, r15
+
+ /*
+ * Now relocate code
+ */
+
+ cmplw cr1,r3,r4
+ addi r0,r5,3
+ srwi. r0,r0,2
+ beq cr1,4f /* In place copy is not necessary */
+ beq 7f /* Protect against 0 count */
+ mtctr r0
+ bge cr1,2f
+
+ la r8,-4(r4)
+ la r7,-4(r3)
+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
+ mfspr r7,HID0 /* don't do dcbst if dcache is disabled */
+ rlwinm r7,r7,HID0_DCE_BITPOS+1,31,31
+ cmpwi r7,0
+ beq 9f
+ mr r4,r3
+5: dcbst 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 5b
+ sync /* Wait for all dcbst to complete on bus */
+9: mfspr r7,HID0 /* don't do icbi if icache is disabled */
+ rlwinm r7,r7,HID0_ICE_BITPOS+1,31,31
+ cmpwi r7,0
+ beq 7f
+ mr r4,r3
+6: icbi 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 6b
+7: sync /* Wait for all icbi to complete on bus */
+ isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+
+ addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+ mtlr r0
+ blr
+
+in_ram:
+
+ /*
+ * Relocation Function, r14 point to got2+0x8000
+ *
+ * Adjust got2 pointers, no need to check for 0, this code
+ * already puts a few entries in the table.
+ */
+ li r0,__got2_entries@sectoff@l
+ la r3,GOT(_GOT2_TABLE_)
+ lwz r11,GOT(_GOT2_TABLE_)
+ mtctr r0
+ sub r11,r3,r11
+ addi r3,r3,-4
+1: lwzu r0,4(r3)
+ add r0,r0,r11
+ stw r0,0(r3)
+ bdnz 1b
+
+ /*
+ * Now adjust the fixups and the pointers to the fixups
+ * in case we need to move ourselves again.
+ */
+2: li r0,__fixup_entries@sectoff@l
+ lwz r3,GOT(_FIXUP_TABLE_)
+ cmpwi r0,0
+ mtctr r0
+ addi r3,r3,-4
+ beq 4f
+3: lwzu r4,4(r3)
+ lwzux r0,r4,r11
+ add r0,r0,r11
+ stw r10,0(r3)
+ stw r0,0(r4)
+ bdnz 3b
+4:
+clear_bss:
+ /*
+ * Now clear BSS segment
+ */
+ lwz r3,GOT(__bss_start)
+ 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 /* end of RAM */
+ bl board_init_r
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+ .globl transfer_to_handler
+transfer_to_handler:
+ stw r22,_NIP(r21)
+ lis r22,MSR_POW@h
+ andc r23,r23,r22
+ stw r23,_MSR(r21)
+ SAVE_GPR(7, r21)
+ SAVE_4GPRS(8, r21)
+ SAVE_8GPRS(12, r21)
+ SAVE_8GPRS(24, r21)
+ mflr r23
+ andi. r24,r23,0x3f00 /* get vector offset */
+ stw r24,TRAP(r21)
+ li r22,0
+ stw r22,RESULT(r21)
+ lwz r24,0(r23) /* virtual address of handler */
+ lwz r23,4(r23) /* where to go when done */
+ mtspr SRR0,r24
+ mtspr SRR1,r20
+ mtlr r23
+ SYNC
+ rfi /* jump to handler, enable MMU */
+
+int_return:
+ mfmsr r28 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r28,r28,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r28
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SRR0,r2
+ mtspr SRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfi
+
+/*
+ * This code initialises the MPC5xxx processor core
+ * (conforms to PowerPC 603e spec)
+ * Note: expects original MSR contents to be in r5.
+ */
+
+ .globl init_5xx_core
+init_5xxx_core:
+
+ /* Initialize machine status; enable machine check interrupt */
+ /*--------------------------------------------------------------*/
+
+ li r3, MSR_KERNEL /* Set ME and RI flags */
+ rlwimi r3, r5, 0, 25, 25 /* preserve IP bit set by HRCW */
+#ifdef DEBUG
+ rlwimi r3, r5, 0, 21, 22 /* debugger might set SE & BE bits */
+#endif
+ SYNC /* Some chip revs need this... */
+ mtmsr r3
+ SYNC
+ mtspr SRR1, r3 /* Make SRR1 match MSR */
+
+ /* Initialize the Hardware Implementation-dependent Registers */
+ /* HID0 also contains cache control */
+ /*--------------------------------------------------------------*/
+
+ lis r3, CFG_HID0_INIT@h
+ ori r3, r3, CFG_HID0_INIT@l
+ SYNC
+ mtspr HID0, r3
+
+ lis r3, CFG_HID0_FINAL@h
+ ori r3, r3, CFG_HID0_FINAL@l
+ SYNC
+ mtspr HID0, r3
+
+ /* clear all BAT's */
+ /*--------------------------------------------------------------*/
+
+ li r0, 0
+ mtspr DBAT0U, r0
+ mtspr DBAT0L, r0
+ mtspr DBAT1U, r0
+ mtspr DBAT1L, r0
+ mtspr DBAT2U, r0
+ mtspr DBAT2L, r0
+ mtspr DBAT3U, r0
+ mtspr DBAT3L, r0
+ mtspr DBAT4U, r0
+ mtspr DBAT4L, r0
+ mtspr DBAT5U, r0
+ mtspr DBAT5L, r0
+ mtspr DBAT6U, r0
+ mtspr DBAT6L, r0
+ mtspr DBAT7U, r0
+ mtspr DBAT7L, r0
+ mtspr IBAT0U, r0
+ mtspr IBAT0L, r0
+ mtspr IBAT1U, r0
+ mtspr IBAT1L, r0
+ mtspr IBAT2U, r0
+ mtspr IBAT2L, r0
+ mtspr IBAT3U, r0
+ mtspr IBAT3L, r0
+ mtspr IBAT4U, r0
+ mtspr IBAT4L, r0
+ mtspr IBAT5U, r0
+ mtspr IBAT5L, r0
+ mtspr IBAT6U, r0
+ mtspr IBAT6L, r0
+ mtspr IBAT7U, r0
+ mtspr IBAT7L, r0
+ SYNC
+
+ /* invalidate all tlb's */
+ /* */
+ /* From the 603e User Manual: "The 603e provides the ability to */
+ /* invalidate a TLB entry. The TLB Invalidate Entry (tlbie) */
+ /* instruction invalidates the TLB entry indexed by the EA, and */
+ /* operates on both the instruction and data TLBs simultaneously*/
+ /* invalidating four TLB entries (both sets in each TLB). The */
+ /* index corresponds to bits 15-19 of the EA. To invalidate all */
+ /* entries within both TLBs, 32 tlbie instructions should be */
+ /* issued, incrementing this field by one each time." */
+ /* */
+ /* "Note that the tlbia instruction is not implemented on the */
+ /* 603e." */
+ /* */
+ /* bits 15-19 correspond to addresses 0x00000000 to 0x0001F000 */
+ /* incrementing by 0x1000 each time. The code below is sort of */
+ /* based on code in "flush_tlbs" from arch/ppc/kernel/head.S */
+ /* */
+ /*--------------------------------------------------------------*/
+
+ li r3, 32
+ mtctr r3
+ li r3, 0
+1: tlbie r3
+ addi r3, r3, 0x1000
+ bdnz 1b
+ SYNC
+
+ /* Done! */
+ /*--------------------------------------------------------------*/
+
+ blr
+
+/* Cache functions.
+ *
+ * Note: requires that all cache bits in
+ * HID0 are in the low half word.
+ */
+ .globl icache_enable
+icache_enable:
+ mfspr r3, HID0
+ ori r3, r3, HID0_ICE
+ lis r4, 0
+ ori r4, r4, HID0_ILOCK
+ andc r3, r3, r4
+ ori r4, r3, HID0_ICFI
+ isync
+ mtspr HID0, r4 /* sets enable and invalidate, clears lock */
+ isync
+ mtspr HID0, r3 /* clears invalidate */
+ blr
+
+ .globl icache_disable
+icache_disable:
+ mfspr r3, HID0
+ lis r4, 0
+ ori r4, r4, HID0_ICE|HID0_ILOCK
+ andc r3, r3, r4
+ ori r4, r3, HID0_ICFI
+ isync
+ mtspr HID0, r4 /* sets invalidate, clears enable and lock */
+ isync
+ mtspr HID0, r3 /* clears invalidate */
+ blr
+
+ .globl icache_status
+icache_status:
+ mfspr r3, HID0
+ rlwinm r3, r3, HID0_ICE_BITPOS + 1, 31, 31
+ blr
+
+ .globl dcache_enable
+dcache_enable:
+ mfspr r3, HID0
+ ori r3, r3, HID0_DCE
+ lis r4, 0
+ ori r4, r4, HID0_DLOCK
+ andc r3, r3, r4
+ ori r4, r3, HID0_DCI
+ sync
+ mtspr HID0, r4 /* sets enable and invalidate, clears lock */
+ sync
+ mtspr HID0, r3 /* clears invalidate */
+ blr
+
+ .globl dcache_disable
+dcache_disable:
+ mfspr r3, HID0
+ lis r4, 0
+ ori r4, r4, HID0_DCE|HID0_DLOCK
+ andc r3, r3, r4
+ ori r4, r3, HID0_DCI
+ sync
+ mtspr HID0, r4 /* sets invalidate, clears enable and lock */
+ sync
+ mtspr HID0, r3 /* clears invalidate */
+ blr
+
+ .globl dcache_status
+dcache_status:
+ mfspr r3, HID0
+ rlwinm r3, r3, HID0_DCE_BITPOS + 1, 31, 31
+ blr
+
+ .globl get_svr
+get_svr:
+ mfspr r3, SVR
+ blr
+
+ .globl get_pvr
+get_pvr:
+ mfspr r3, PVR
+ blr
+
+ /*
+ * Copy exception vector code to low memory
+ *
+ * r3: dest_addr
+ * r7: source address, r8: end address, r9: target address
+ */
+ .globl trap_init
+trap_init:
+ lwz r7, GOT(_start)
+ lwz r8, GOT(_end_of_vectors)
+
+ li r9, 0x100 /* reset vector always at 0x100 */
+
+ cmplw 0, r7, r8
+ bgelr /* return if r7>=r8 - just in case */
+
+ mflr r4 /* save link register */
+1:
+ lwz r0, 0(r7)
+ stw r0, 0(r9)
+ addi r7, r7, 4
+ addi r9, r9, 4
+ cmplw 0, r7, r8
+ bne 1b
+
+ /*
+ * relocate `hdlr' and `int_return' entries
+ */
+ li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+ li r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 2b
+
+ li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+ li r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 3b
+
+ li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
+ li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 4b
+
+ mfmsr r3 /* now that the vectors have */
+ lis r7, MSR_IP@h /* relocated into low memory */
+ ori r7, r7, MSR_IP@l /* MSR[IP] can be turned off */
+ andc r3, r3, r7 /* (if it was on) */
+ SYNC /* Some chip revs need this... */
+ mtmsr r3
+ SYNC
+
+ mtlr r4 /* restore link register */
+ blr
+
+ /*
+ * Function: relocate entries for one exception vector
+ */
+trap_reloc:
+ lwz r0, 0(r7) /* hdlr ... */
+ add r0, r0, r3 /* ... += dest_addr */
+ stw r0, 0(r7)
+
+ lwz r0, 4(r7) /* int_return ... */
+ add r0, r0, r3 /* ... += dest_addr */
+ stw r0, 4(r7)
+
+ blr
diff --git a/arch/ppc/mach-mpc5xxx/traps.c b/arch/ppc/mach-mpc5xxx/traps.c
new file mode 100644
index 0000000000..865a742fce
--- /dev/null
+++ b/arch/ppc/mach-mpc5xxx/traps.c
@@ -0,0 +1,229 @@
+/*
+ * linux/arch/ppc/kernel/traps.c
+ *
+ * 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)
+ * fixed Machine Check Reasons by Reinhard Meyer (r.meyer@emk-elektronik.de)
+ *
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/processor.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+int (*debugger_exception_handler)(struct pt_regs *) = 0;
+#endif
+
+/* Returns 0 if exception not found and fixup otherwise. */
+extern unsigned long search_exception_table(unsigned long);
+
+/* THIS NEEDS CHANGING to use the board info structure.
+*/
+#define END_OF_MEM 0x02000000
+
+/*
+ * 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
+MachineCheckException(struct pt_regs *regs)
+{
+ unsigned long fixup;
+
+ /* Probing PCI using config cycles cause this exception
+ * when a device is not present. Catch it and return to
+ * the PCI exception handler.
+ */
+ if ((fixup = search_exception_table(regs->nip)) != 0) {
+ regs->nip = fixup;
+ return;
+ }
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ printf("Machine check in kernel mode.\n");
+ printf("Caused by (from msr): ");
+ printf("regs %p ",regs);
+ /* refer to 603e Manual (MPC603EUM/AD), chapter 4.5.2.1 */
+ switch( regs->msr & 0x000F0000)
+ {
+ case (0x80000000>>12) :
+ printf("Machine check signal - probably due to mm fault\n"
+ "with mmu off\n");
+ break;
+ case (0x80000000>>13) :
+ printf("Transfer error ack signal\n");
+ break;
+ case (0x80000000>>14) :
+ printf("Data parity signal\n");
+ break;
+ case (0x80000000>>15) :
+ printf("Address parity signal\n");
+ break;
+ default:
+ printf("Unknown values in msr\n");
+ }
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("machine check");
+}
+
+void
+AlignmentException(struct pt_regs *regs)
+{
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Alignment Exception");
+}
+
+void
+ProgramCheckException(struct pt_regs *regs)
+{
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Program Check Exception");
+}
+
+void
+SoftEmuException(struct pt_regs *regs)
+{
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Software Emulation Exception");
+}
+
+
+void
+UnknownException(struct pt_regs *regs)
+{
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+ regs->nip, regs->msr, regs->trap);
+ _exception(0, regs);
+}
+
+#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+extern void do_bedbug_breakpoint(struct pt_regs *);
+#endif
+
+void
+DebugException(struct pt_regs *regs)
+{
+
+ printf("Debugger trap at @ %lx\n", regs->nip );
+ show_regs(regs);
+#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+ do_bedbug_breakpoint( regs );
+#endif
+}
+
+/* Probe an address by reading. If not present, return -1, otherwise
+ * return 0.
+ */
+int
+addr_probe(uint *addr)
+{
+ return 0;
+}