[PATCH V4 2/4] Minimal support of the MPC85xx architecture
Renaud Barbier
renaud.barbier at ge.com
Tue May 1 05:26:01 EDT 2012
The directories cpu-85xx and mach-mpc85xx contain a minimal CPU support
suitable for the P2020RDB board. This includes startup code for the CPU,
peripherals and clock source initialization as well as header files
and updates to configuration and build files.
Signed-off-by: Renaud Barbier <renaud.barbier at ge.com>
---
arch/ppc/Kconfig | 3 +
arch/ppc/Makefile | 7 +
arch/ppc/cpu-85xx/Makefile | 7 +
arch/ppc/cpu-85xx/cpu.c | 103 ++
arch/ppc/cpu-85xx/cpu_init.c | 130 +++
arch/ppc/cpu-85xx/fixed_ivor.S | 61 ++
arch/ppc/cpu-85xx/release.S | 263 +++++
arch/ppc/cpu-85xx/resetvec.S | 2 +
arch/ppc/cpu-85xx/start.S | 1092 +++++++++++++++++++++
arch/ppc/cpu-85xx/tlb.c | 177 ++++
arch/ppc/cpu-85xx/traps.c | 297 ++++++
arch/ppc/include/asm/config.h | 44 +
arch/ppc/include/asm/config_mpc85xx.h | 37 +
arch/ppc/include/asm/e500.h | 39 +
arch/ppc/include/asm/fsl_ddr_sdram.h | 34 +
arch/ppc/include/asm/fsl_law.h | 91 ++
arch/ppc/include/asm/fsl_lbc.h | 67 ++
arch/ppc/lib/Makefile | 1 +
arch/ppc/lib/board.c | 9 +-
arch/ppc/lib/reloc.S | 47 +
arch/ppc/mach-mpc85xx/Kconfig | 45 +
arch/ppc/mach-mpc85xx/Makefile | 6 +
arch/ppc/mach-mpc85xx/cpuid.c | 73 ++
arch/ppc/mach-mpc85xx/fsl_law.c | 160 +++
arch/ppc/mach-mpc85xx/fsl_lbc.c | 17 +
arch/ppc/mach-mpc85xx/include/mach/clocks.h | 11 +
arch/ppc/mach-mpc85xx/include/mach/early_udelay.h | 40 +
arch/ppc/mach-mpc85xx/include/mach/immap_85xx.h | 132 +++
arch/ppc/mach-mpc85xx/include/mach/mp.h | 15 +
arch/ppc/mach-mpc85xx/include/mach/mpc85xx.h | 17 +
arch/ppc/mach-mpc85xx/mp.c | 155 +++
arch/ppc/mach-mpc85xx/speed.c | 96 ++
arch/ppc/mach-mpc85xx/time.c | 54 +
33 files changed, 3328 insertions(+), 4 deletions(-)
create mode 100644 arch/ppc/cpu-85xx/Makefile
create mode 100644 arch/ppc/cpu-85xx/cpu.c
create mode 100644 arch/ppc/cpu-85xx/cpu_init.c
create mode 100644 arch/ppc/cpu-85xx/fixed_ivor.S
create mode 100644 arch/ppc/cpu-85xx/release.S
create mode 100644 arch/ppc/cpu-85xx/resetvec.S
create mode 100644 arch/ppc/cpu-85xx/start.S
create mode 100644 arch/ppc/cpu-85xx/tlb.c
create mode 100644 arch/ppc/cpu-85xx/traps.c
create mode 100644 arch/ppc/include/asm/config.h
create mode 100644 arch/ppc/include/asm/config_mpc85xx.h
create mode 100644 arch/ppc/include/asm/e500.h
create mode 100644 arch/ppc/include/asm/fsl_ddr_sdram.h
create mode 100644 arch/ppc/include/asm/fsl_law.h
create mode 100644 arch/ppc/include/asm/fsl_lbc.h
create mode 100644 arch/ppc/lib/reloc.S
create mode 100644 arch/ppc/mach-mpc85xx/Kconfig
create mode 100644 arch/ppc/mach-mpc85xx/Makefile
create mode 100644 arch/ppc/mach-mpc85xx/cpuid.c
create mode 100644 arch/ppc/mach-mpc85xx/fsl_law.c
create mode 100644 arch/ppc/mach-mpc85xx/fsl_lbc.c
create mode 100644 arch/ppc/mach-mpc85xx/include/mach/clocks.h
create mode 100644 arch/ppc/mach-mpc85xx/include/mach/early_udelay.h
create mode 100644 arch/ppc/mach-mpc85xx/include/mach/immap_85xx.h
create mode 100644 arch/ppc/mach-mpc85xx/include/mach/mp.h
create mode 100644 arch/ppc/mach-mpc85xx/include/mach/mpc85xx.h
create mode 100644 arch/ppc/mach-mpc85xx/mp.c
create mode 100644 arch/ppc/mach-mpc85xx/speed.c
create mode 100644 arch/ppc/mach-mpc85xx/time.c
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index 164598f..d124065 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -12,9 +12,12 @@ choice
config ARCH_MPC5XXX
bool "Freescale MPC5xxx"
+config ARCH_MPC85XX
+ bool "Freescale MPC85xx"
endchoice
source arch/ppc/mach-mpc5xxx/Kconfig
+source arch/ppc/mach-mpc85xx/Kconfig
source common/Kconfig
source commands/Kconfig
source net/Kconfig
diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile
index 2d9e47f..67eb667 100644
--- a/arch/ppc/Makefile
+++ b/arch/ppc/Makefile
@@ -7,9 +7,16 @@ ifdef CONFIG_RELOCATABLE
CPPFLAGS += -fPIC -mrelocatable
endif
+ifdef CONFIG_MPC85xx
+CPPFLAGS += -Wa,-me500x2 -msoft-float -mno-string
+endif
board-$(CONFIG_MACH_PHYCORE_MPC5200B_TINY) := pcm030
+
machine-$(CONFIG_ARCH_MPC5200) := mpc5xxx
+machine-$(CONFIG_ARCH_MPC85XX) := mpc85xx
+
+cpu-$(CONFIG_ARCH_MPC85XX) := 85xx
TEXT_BASE = $(CONFIG_TEXT_BASE)
diff --git a/arch/ppc/cpu-85xx/Makefile b/arch/ppc/cpu-85xx/Makefile
new file mode 100644
index 0000000..be1ad21
--- /dev/null
+++ b/arch/ppc/cpu-85xx/Makefile
@@ -0,0 +1,7 @@
+obj-y += cpu.o
+obj-y += cpu_init.o
+obj-y += traps.o
+obj-y += tlb.o
+extra-y += start.o
+extra-y += resetvec.o
+obj-$(CONFIG_MP) += release.o
diff --git a/arch/ppc/cpu-85xx/cpu.c b/arch/ppc/cpu-85xx/cpu.c
new file mode 100644
index 0000000..74eba0f
--- /dev/null
+++ b/arch/ppc/cpu-85xx/cpu.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2012 GE Intelligent Platforms, Inc
+ * Copyright 2004,2007-2011 Freescale Semiconductor, Inc.
+ * (C) Copyright 2002, 2003 Motorola Inc.
+ * Xianghua Xiao (X.Xiao at motorola.com)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <common.h>
+#include <command.h>
+#include <asm/processor.h>
+#include <asm/config_mpc85xx.h>
+#include <asm/e500.h>
+#include <asm/common.h>
+#include <asm/config.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <asm/mmu.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <mach/immap_85xx.h>
+#include <mach/clocks.h>
+
+void __noreturn reset_cpu(unsigned long addr)
+{
+ void __iomem *regs = (void __iomem *)MPC85xx_GUTS_ADDR;
+
+ /* Everything after the first generation of PQ3 parts has RSTCR */
+ out_be32(regs + MPC85xx_GUTS_RSTCR_OFFSET, 0x2); /* HRESET_REQ */
+ udelay(100);
+
+ while (1)
+ ;
+}
+
+unsigned long get_timebase_clock(void)
+{
+ struct sys_info sysinfo;
+
+ get_sys_info(&sysinfo);
+
+ return (sysinfo.freqSystemBus + 4UL)/8UL;
+}
+
+/*
+ * Return the memory size based on the configuration registers.
+ */
+phys_size_t get_effective_memsize(void)
+{
+ void __iomem *regs = (void __iomem *)(MPC85xx_DDR_ADDR);
+ phys_size_t sdram_size;
+ uint san , ean;
+ uint reg;
+ int ix;
+
+ sdram_size = 0;
+
+ for (ix = 0; ix < CFG_CHIP_SELECTS_PER_CTRL; ix++) {
+ if (in_be32(regs + DDR_OFF(CS0_CONFIG) + (ix * 8)) &
+ SDRAM_CFG_MEM_EN) {
+ reg = in_be32(regs + DDR_OFF(CS0_BNDS) + (ix * 8));
+ /* start address */
+ san = (reg & 0x0fff00000) >> 16;
+ /* end address */
+ ean = (reg & 0x00000fff);
+ sdram_size = ((ean - san + 1) << 24);
+ }
+ }
+
+ return sdram_size;
+}
+
+long int initdram(int board_type)
+{
+ phys_size_t dram_size = 0;
+
+ dram_size = fixed_sdram();
+
+ dram_size = setup_ddr_tlbs(dram_size / 0x100000);
+ dram_size *= 0x100000;
+
+ return dram_size;
+}
diff --git a/arch/ppc/cpu-85xx/cpu_init.c b/arch/ppc/cpu-85xx/cpu_init.c
new file mode 100644
index 0000000..e127765
--- /dev/null
+++ b/arch/ppc/cpu-85xx/cpu_init.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2012 GE Intelligent Platforms, Inc.
+ *
+ * Copyright 2007-2011 Freescale Semiconductor, Inc.
+ *
+ * (C) Copyright 2003 Motorola Inc.
+ * Modified by Xianghua Xiao, X.Xiao at motorola.com
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd at 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 <init.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/cache.h>
+#include <asm/mmu.h>
+#include <asm/fsl_law.h>
+#include <mach/immap_85xx.h>
+#include <mach/mp.h>
+
+static void setup_ccsrbar(void)
+{
+ u32 temp;
+ u32 mas0, mas1, mas2, mas3, mas7;
+ u32 *ccsr_virt = (u32 *)(CFG_CCSRBAR + 0x1000);
+
+ mas0 = MAS0_TLBSEL(0) | MAS0_ESEL(1);
+ mas1 = MAS1_VALID | MAS1_TID(0) | MAS1_TS | MAS1_TSIZE(BOOKE_PAGESZ_4K);
+ /* mas1 is the same as above */
+ mas2 = FSL_BOOKE_MAS2(CFG_CCSRBAR + 0x1000, MAS2_I|MAS2_G);
+ mas3 = FSL_BOOKE_MAS3(CFG_CCSRBAR_DEFAULT, 0, MAS3_SW|MAS3_SR);
+ mas7 = FSL_BOOKE_MAS7(CFG_CCSRBAR_DEFAULT);
+
+ write_tlb(mas0, mas1, mas2, mas3, mas7);
+
+ temp = in_be32(ccsr_virt);
+ out_be32(ccsr_virt, CFG_CCSRBAR_PHYS >> 12);
+ temp = in_be32((u32 *)CFG_CCSRBAR);
+}
+
+void cpu_init_early_f(void)
+{
+ u32 mas0, mas1, mas2, mas3, mas7;
+
+ mas0 = MAS0_TLBSEL(0) | MAS0_ESEL(0);
+ mas1 = MAS1_VALID | MAS1_TID(0) | MAS1_TS | MAS1_TSIZE(BOOKE_PAGESZ_4K);
+ mas2 = FSL_BOOKE_MAS2(CFG_CCSRBAR, MAS2_I|MAS2_G);
+ mas3 = FSL_BOOKE_MAS3(CFG_CCSRBAR_PHYS, 0, MAS3_SW|MAS3_SR);
+ mas7 = FSL_BOOKE_MAS7(CFG_CCSRBAR_PHYS);
+
+ write_tlb(mas0, mas1, mas2, mas3, mas7);
+
+ /* set up CCSR if we want it moved */
+ if (CFG_CCSRBAR_DEFAULT != CFG_CCSRBAR_PHYS)
+ setup_ccsrbar();
+
+ init_laws();
+ invalidate_tlb(0);
+ init_tlbs();
+}
+
+void cpu_init_f(void)
+{
+ disable_tlb(14);
+ disable_tlb(15);
+
+ init_early_memctl_regs();
+}
+
+int l2_cache_init(void)
+{
+ void __iomem *l2cache = (void __iomem *)MPC85xx_L2_ADDR;
+ uint cache_ctl;
+ uint svr, ver;
+ u32 l2siz_field;
+
+ svr = get_svr();
+ ver = SVR_SOC_VER(svr);
+
+ asm("msync;isync");
+ cache_ctl = in_be32(l2cache + MPC85xx_L2_CTL_OFFSET);
+
+ l2siz_field = (cache_ctl >> 28) & 0x3;
+
+ switch (l2siz_field) {
+ case 0x0:
+ return -1;
+ break;
+ case 0x1:
+ cache_ctl = 0xc0000000; /* set L2E=1, L2I=1, L2SRAM=0 */
+ break;
+ case 0x2:
+ /* set L2E=1, L2I=1, & L2SRAM=0 */
+ cache_ctl = 0xc0000000;
+ break;
+ case 0x3:
+ /* set L2E=1, L2I=1, & L2SRAM=0 */
+ cache_ctl = 0xc0000000;
+ break;
+ }
+
+ if (!(in_be32(l2cache + MPC85xx_L2_CTL_OFFSET) & MPC85xx_L2CTL_L2E)) {
+ asm("msync;isync");
+ /* invalidate & enable */
+ out_be32(l2cache + MPC85xx_L2_CTL_OFFSET, cache_ctl);
+ asm("msync;isync");
+ }
+
+ return 0;
+}
diff --git a/arch/ppc/cpu-85xx/fixed_ivor.S b/arch/ppc/cpu-85xx/fixed_ivor.S
new file mode 100644
index 0000000..a00a435
--- /dev/null
+++ b/arch/ppc/cpu-85xx/fixed_ivor.S
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * Kumar Gala <kumar.gala at freescale.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* This file is intended to be included by other asm code since
+ * we will want to execute this on both the primary core when
+ * it does a bootm and the secondary core's that get released
+ * out of the spin table.
+ */
+
+#define SET_IVOR(vector_number, vector_offset) \
+ li r3,vector_offset at l; \
+ mtspr SPRN_IVOR##vector_number,r3;
+
+#define SET_GIVOR(vector_number, vector_offset) \
+ li r3,vector_offset at l; \
+ mtspr SPRN_GIVOR##vector_number,r3;
+
+ SET_IVOR(0, 0x020) /* Critical Input */
+ SET_IVOR(1, 0x000) /* Machine Check */
+ SET_IVOR(2, 0x060) /* Data Storage */
+ SET_IVOR(3, 0x080) /* Instruction Storage */
+ SET_IVOR(4, 0x0a0) /* External Input */
+ SET_IVOR(5, 0x0c0) /* Alignment */
+ SET_IVOR(6, 0x0e0) /* Program */
+ SET_IVOR(7, 0x100) /* FP Unavailable */
+ SET_IVOR(8, 0x120) /* System Call */
+ SET_IVOR(9, 0x140) /* Auxiliary Processor Unavailable */
+ SET_IVOR(10, 0x160) /* Decrementer */
+ SET_IVOR(11, 0x180) /* Fixed Interval Timer */
+ SET_IVOR(12, 0x1a0) /* Watchdog Timer */
+ SET_IVOR(13, 0x1c0) /* Data TLB Error */
+ SET_IVOR(14, 0x1e0) /* Instruction TLB Error */
+ SET_IVOR(15, 0x040) /* Debug */
+
+ /* e500v1 & e500v2 only */
+ SET_IVOR(32, 0x200) /* SPE Unavailable */
+ SET_IVOR(33, 0x220) /* Embedded FP Data */
+ SET_IVOR(34, 0x240) /* Embedded FP Round */
+
+ SET_IVOR(35, 0x260) /* Performance monitor */
diff --git a/arch/ppc/cpu-85xx/release.S b/arch/ppc/cpu-85xx/release.S
new file mode 100644
index 0000000..afe1421
--- /dev/null
+++ b/arch/ppc/cpu-85xx/release.S
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc.
+ * Kumar Gala <kumar.gala at freescale.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <asm/config_mpc85xx.h>
+#include <mach/mpc85xx.h>
+
+#include <asm/ppc_asm.tmpl>
+#include <asm/ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+/* To boot secondary cpus, we need a place for them to start up.
+ * Normally, they start at 0xfffffffc, but that's usually the
+ * firmware, and we don't want to have to run the firmware again.
+ * Instead, the primary cpu will set the BPTR to point here to
+ * this page. We then set up the core, and head to
+ * start_secondary. Note that this means that the code below
+ * must never exceed 1023 instructions (the branch at the end
+ * would then be the 1024th).
+ */
+ .globl __secondary_start_page
+ .align 12
+__secondary_start_page:
+/* First do some preliminary setup */
+ lis r3, HID0_EMCP at h /* enable machine check */
+
+ ori r3,r3,HID0_TBEN at l /* enable Timebase */
+
+ mtspr SPRN_HID0,r3
+
+ li r3,(HID1_ASTME|HID1_ABE)@l /* Addr streaming & broadcast */
+ mfspr r0,PVR
+ andi. r0,r0,0xff
+ cmpwi r0,0x50 at l /* if we are rev 5.0 or greater set MBDD */
+ blt 1f
+ /* Set MBDD bit also */
+ ori r3, r3, HID1_MBDD at l
+1:
+ mtspr SPRN_HID1,r3
+
+ /* Enable branch prediction */
+ lis r3,BUCSR_ENABLE at h
+ ori r3,r3,BUCSR_ENABLE at l
+ mtspr SPRN_BUCSR,r3
+
+ /* Ensure TB is 0 */
+ li r3,0
+ mttbl r3
+ mttbu r3
+
+ /* Enable/invalidate the I-Cache */
+ lis r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@h
+ ori r2,r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@l
+ mtspr SPRN_L1CSR1,r2
+1:
+ mfspr r3,SPRN_L1CSR1
+ and. r1,r3,r2
+ bne 1b
+
+ lis r3,(L1CSR1_CPE|L1CSR1_ICE)@h
+ ori r3,r3,(L1CSR1_CPE|L1CSR1_ICE)@l
+ mtspr SPRN_L1CSR1,r3
+ isync
+2:
+ mfspr r3,SPRN_L1CSR1
+ andi. r1,r3,L1CSR1_ICE at l
+ beq 2b
+
+ /* Enable/invalidate the D-Cache */
+ lis r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@h
+ ori r2,r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@l
+ mtspr SPRN_L1CSR0,r2
+1:
+ mfspr r3,SPRN_L1CSR0
+ and. r1,r3,r2
+ bne 1b
+
+ lis r3,(L1CSR0_CPE|L1CSR0_DCE)@h
+ ori r3,r3,(L1CSR0_CPE|L1CSR0_DCE)@l
+ mtspr SPRN_L1CSR0,r3
+ isync
+2:
+ mfspr r3,SPRN_L1CSR0
+ andi. r1,r3,L1CSR0_DCE at l
+ beq 2b
+
+#define toreset(x) (x - __secondary_start_page + 0xfffff000)
+
+ /* get our PIR to figure out our table entry */
+ lis r3,toreset(__spin_table)@h
+ ori r3,r3,toreset(__spin_table)@l
+
+ /* r10 has the base address for the entry */
+ mfspr r0,SPRN_PIR
+ mr r4,r0
+ slwi r8,r4,5
+ add r10,r3,r8
+
+#define EPAPR_MAGIC (0x45504150)
+#define ENTRY_ADDR_UPPER 0
+#define ENTRY_ADDR_LOWER 4
+#define ENTRY_R3_UPPER 8
+#define ENTRY_R3_LOWER 12
+#define ENTRY_RESV 16
+#define ENTRY_PIR 20
+#define ENTRY_R6_UPPER 24
+#define ENTRY_R6_LOWER 28
+#define ENTRY_SIZE 32
+
+ /* setup the entry */
+ li r3,0
+ li r8,1
+ stw r0,ENTRY_PIR(r10)
+ stw r3,ENTRY_ADDR_UPPER(r10)
+ stw r8,ENTRY_ADDR_LOWER(r10)
+ stw r3,ENTRY_R3_UPPER(r10)
+ stw r4,ENTRY_R3_LOWER(r10)
+ stw r3,ENTRY_R6_UPPER(r10)
+ stw r3,ENTRY_R6_LOWER(r10)
+
+ /* load r13 with the address of the 'bootpg' in SDRAM */
+ lis r13,toreset(__bootpg_addr)@h
+ ori r13,r13,toreset(__bootpg_addr)@l
+ lwz r13,0(r13)
+
+ /* setup mapping for AS = 1, and jump there */
+ lis r11,(MAS0_TLBSEL(1)|MAS0_ESEL(1))@h
+ mtspr SPRN_MAS0,r11
+ lis r11,(MAS1_VALID|MAS1_IPROT)@h
+ ori r11,r11,(MAS1_TS|MAS1_TSIZE(BOOKE_PAGESZ_4K))@l
+ mtspr SPRN_MAS1,r11
+ oris r11,r13,(MAS2_I|MAS2_G)@h
+ ori r11,r13,(MAS2_I|MAS2_G)@l
+ mtspr SPRN_MAS2,r11
+ oris r11,r13,(MAS3_SX|MAS3_SW|MAS3_SR)@h
+ ori r11,r13,(MAS3_SX|MAS3_SW|MAS3_SR)@l
+ mtspr SPRN_MAS3,r11
+ tlbwe
+
+ bl 1f
+1: mflr r11
+ /*
+ * OR in 0xfff to create a mask of the bootpg SDRAM address. We use
+ * this mask to fixup the cpu spin table and the address that we want
+ * to jump to, eg change them from 0xfffffxxx to 0x7ffffxxx if the
+ * bootpg is at 0x7ffff000 in SDRAM.
+ */
+ ori r13,r13,0xfff
+ and r11, r11, r13
+ and r10, r10, r13
+
+ addi r11,r11,(2f-1b)
+ mfmsr r13
+ ori r12,r13,MSR_IS|MSR_DS at l
+
+ mtspr SPRN_SRR0,r11
+ mtspr SPRN_SRR1,r12
+ rfi
+
+ /* spin waiting for addr */
+2:
+ lwz r4,ENTRY_ADDR_LOWER(r10)
+ andi. r11,r4,1
+ bne 2b
+ isync
+
+ /* setup IVORs to match fixed offsets */
+#include "fixed_ivor.S"
+
+ /* get the upper bits of the addr */
+ lwz r11,ENTRY_ADDR_UPPER(r10)
+
+ /* setup branch addr */
+ mtspr SPRN_SRR0,r4
+
+ /* mark the entry as released */
+ li r8,3
+ stw r8,ENTRY_ADDR_LOWER(r10)
+
+ /* mask by ~64M to setup our tlb we will jump to */
+ rlwinm r12,r4,0,0,5
+
+ /* setup r3, r4, r5, r6, r7, r8, r9 */
+ lwz r3,ENTRY_R3_LOWER(r10)
+ li r4,0
+ li r5,0
+ lwz r6,ENTRY_R6_LOWER(r10)
+ lis r7,(64*1024*1024)@h
+ li r8,0
+ li r9,0
+
+ /* load up the pir */
+ lwz r0,ENTRY_PIR(r10)
+ mtspr SPRN_PIR,r0
+ mfspr r0,SPRN_PIR
+ stw r0,ENTRY_PIR(r10)
+
+ mtspr IVPR,r12
+/*
+ * Coming here, we know the cpu has one TLB mapping in TLB1[0]
+ * which maps 0xfffff000-0xffffffff one-to-one. We set up a
+ * second mapping that maps addr 1:1 for 64M, and then we jump to
+ * addr
+ */
+ lis r10,(MAS0_TLBSEL(1)|MAS0_ESEL(0))@h
+ mtspr SPRN_MAS0,r10
+ lis r10,(MAS1_VALID|MAS1_IPROT)@h
+ ori r10,r10,(MAS1_TSIZE(BOOKE_PAGESZ_64M))@l
+ mtspr SPRN_MAS1,r10
+ /* WIMGE = 0b00000 for now */
+ mtspr SPRN_MAS2,r12
+ ori r12,r12,(MAS3_SX|MAS3_SW|MAS3_SR)
+ mtspr SPRN_MAS3,r12
+ tlbwe
+
+/* Now we have another mapping for this page, so we jump to that
+ * mapping
+ */
+ mtspr SPRN_SRR1,r13
+ rfi
+
+ /*
+ * Allocate some space for the SDRAM address of the bootpg.
+ * This variable has to be in the boot page so that it can
+ * be accessed by secondary cores when they come out of reset.
+ */
+ .globl __bootpg_addr
+__bootpg_addr:
+ .long 0
+
+ .align L1_CACHE_SHIFT
+ .globl __spin_table
+__spin_table:
+ .space MAX_CPUS*ENTRY_SIZE
+
+ /* Fill in the empty space. The actual reset vector is
+ * the last word of the page */
+__secondary_start_code_end:
+ .space 4092 - (__secondary_start_code_end - __secondary_start_page)
+__secondary_reset_vector:
+ b __secondary_start_page
diff --git a/arch/ppc/cpu-85xx/resetvec.S b/arch/ppc/cpu-85xx/resetvec.S
new file mode 100644
index 0000000..29555d4
--- /dev/null
+++ b/arch/ppc/cpu-85xx/resetvec.S
@@ -0,0 +1,2 @@
+ .section .resetvec,"ax"
+ b _start_e500
diff --git a/arch/ppc/cpu-85xx/start.S b/arch/ppc/cpu-85xx/start.S
new file mode 100644
index 0000000..9fde9cd
--- /dev/null
+++ b/arch/ppc/cpu-85xx/start.S
@@ -0,0 +1,1092 @@
+/*
+ * Copyright 2004, 2007-2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2003 Motorola,Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * U-Boot Startup Code for Motorola 85xx PowerPC based Embedded Boards
+ *
+ * The processor starts at 0xfffffffc and the code is first executed in the
+ * last 4K page(0xfffff000-0xffffffff) in flash/rom.
+ */
+
+#include <config.h>
+#include <asm/config.h>
+#include <mach/mpc85xx.h>
+
+#include <asm/processor.h>
+#include <asm/ppc_asm.tmpl>
+#include <asm/ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#undef MSR_KERNEL
+#define MSR_KERNEL ( MSR_ME ) /* Machine Check */
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r12 to access the GOT
+ */
+ START_GOT
+ GOT_ENTRY(_GOT2_TABLE_)
+ GOT_ENTRY(_FIXUP_TABLE_)
+
+ GOT_ENTRY(_start)
+ GOT_ENTRY(_start_of_vectors)
+ GOT_ENTRY(_end_of_vectors)
+ GOT_ENTRY(transfer_to_handler)
+ GOT_ENTRY(__init_end)
+ GOT_ENTRY(_end)
+ GOT_ENTRY(__bss_start)
+ END_GOT
+
+/*
+ * e500 Startup -- after reset only the last 4KB of the effective
+ * address space is mapped in the MMU L2 TLB1 Entry0. The .bootpg
+ * section is located at THIS LAST page and basically does three
+ * things: clear some registers, set up exception tables and
+ * add more TLB entries for 'larger spaces'(e.g. the boot rom) to
+ * continue the boot procedure.
+ * Once the boot rom is mapped by TLB entries we can proceed
+ * with normal startup.
+ */
+
+ .section .bootpg,"ax"
+ .globl _start_e500
+
+_start_e500:
+
+/* clear registers/arrays not reset by hardware */
+
+ /* L1 */
+ li r0,2
+ mtspr L1CSR0,r0 /* invalidate d-cache */
+ mtspr L1CSR1,r0 /* invalidate i-cache */
+
+ mfspr r1,DBSR
+ mtspr DBSR,r1 /* Clear all valid bits */
+
+ /* Enable/invalidate the I-Cache */
+ lis r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@h
+ ori r2,r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@l
+ mtspr SPRN_L1CSR1,r2
+1:
+ mfspr r3,SPRN_L1CSR1
+ and. r1,r3,r2
+ bne 1b
+
+ lis r3,(L1CSR1_CPE|L1CSR1_ICE)@h
+ ori r3,r3,(L1CSR1_CPE|L1CSR1_ICE)@l
+ mtspr SPRN_L1CSR1,r3
+ isync
+2:
+ mfspr r3,SPRN_L1CSR1
+ andi. r1,r3,L1CSR1_ICE at l
+ beq 2b
+
+ /* Enable/invalidate the D-Cache */
+ lis r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@h
+ ori r2,r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@l
+ mtspr SPRN_L1CSR0,r2
+1:
+ mfspr r3,SPRN_L1CSR0
+ and. r1,r3,r2
+ bne 1b
+
+ lis r3,(L1CSR0_CPE|L1CSR0_DCE)@h
+ ori r3,r3,(L1CSR0_CPE|L1CSR0_DCE)@l
+ mtspr SPRN_L1CSR0,r3
+ isync
+2:
+ mfspr r3,SPRN_L1CSR0
+ andi. r1,r3,L1CSR0_DCE at l
+ beq 2b
+
+ /* Setup interrupt vectors */
+ lis r1,TEXT_BASE at h
+ mtspr IVPR,r1
+
+ li r1,0x0100
+ mtspr IVOR0,r1 /* 0: Critical input */
+ li r1,0x0200
+ mtspr IVOR1,r1 /* 1: Machine check */
+ li r1,0x0300
+ mtspr IVOR2,r1 /* 2: Data storage */
+ li r1,0x0400
+ mtspr IVOR3,r1 /* 3: Instruction storage */
+ li r1,0x0500
+ mtspr IVOR4,r1 /* 4: External interrupt */
+ li r1,0x0600
+ mtspr IVOR5,r1 /* 5: Alignment */
+ li r1,0x0700
+ mtspr IVOR6,r1 /* 6: Program check */
+ li r1,0x0800
+ mtspr IVOR7,r1 /* 7: floating point unavailable */
+ li r1,0x0900
+ mtspr IVOR8,r1 /* 8: System call */
+ /* 9: Auxiliary processor unavailable(unsupported) */
+ li r1,0x0a00
+ mtspr IVOR10,r1 /* 10: Decrementer */
+ li r1,0x0b00
+ mtspr IVOR11,r1 /* 11: Interval timer */
+ li r1,0x0c00
+ mtspr IVOR12,r1 /* 12: Watchdog timer */
+ li r1,0x0d00
+ mtspr IVOR13,r1 /* 13: Data TLB error */
+ li r1,0x0e00
+ mtspr IVOR14,r1 /* 14: Instruction TLB error */
+ li r1,0x0f00
+ mtspr IVOR15,r1 /* 15: Debug */
+
+ /* Clear and set up some registers. */
+ li r0,0x0000
+ lis r1,0xffff
+ mtspr DEC,r0 /* prevent dec exceptions */
+ mttbl r0 /* prevent fit & wdt exceptions */
+ mttbu r0
+ mtspr TSR,r1 /* clear all timer exception status */
+ mtspr TCR,r0 /* disable all */
+ mtspr ESR,r0 /* clear exception syndrome register */
+ mtspr MCSR,r0 /* machine check syndrome register */
+ mtxer r0 /* clear integer exception register */
+
+ /* Enable Time Base and Select Time Base Clock */
+ lis r0,HID0_EMCP at h /* Enable machine check */
+ ori r0,r0,HID0_TBEN at l /* Enable Timebase */
+ mtspr HID0,r0
+
+ li r0,(HID1_ASTME|HID1_ABE)@l /* Addr streaming & broadcast */
+ mfspr r3,PVR
+ andi. r3,r3, 0xff
+ cmpwi r3,0x50 at l /* if we are rev 5.0 or greater set MBDD */
+ blt 1f
+ /* Set MBDD bit also */
+ ori r0, r0, HID1_MBDD at l
+1:
+ mtspr HID1,r0
+
+ /* Enable Branch Prediction */
+#if defined(CFG_BTB)
+ lis r0,BUCSR_ENABLE at h
+ ori r0,r0,BUCSR_ENABLE at l
+ mtspr SPRN_BUCSR,r0
+#endif
+
+ lis r6,FSL_BOOKE_MAS0(1, 15, 0)@h
+ ori r6,r6,FSL_BOOKE_MAS0(1, 15, 0)@l
+
+ /* create a temp mapping in AS=1 to the 4M boot window */
+ lis r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_4M)@h
+ ori r7,r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_4M)@l
+
+ lis r8,FSL_BOOKE_MAS2(TEXT_BASE & 0xffc00000, (MAS2_I|MAS2_G))@h
+ ori r8,r8,FSL_BOOKE_MAS2(TEXT_BASE & 0xffc00000, (MAS2_I|MAS2_G))@l
+
+ /* The 85xx has the default boot window 0xff800000 - 0xffffffff */
+ lis r9,FSL_BOOKE_MAS3(0xffc00000, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@h
+ ori r9,r9,FSL_BOOKE_MAS3(0xffc00000, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@l
+
+ mtspr MAS0,r6
+ mtspr MAS1,r7
+ mtspr MAS2,r8
+ mtspr MAS3,r9
+ isync
+ msync
+ tlbwe
+
+ /* create a temp mapping in AS=1 to the stack */
+ lis r6,FSL_BOOKE_MAS0(1, 14, 0)@h
+ ori r6,r6,FSL_BOOKE_MAS0(1, 14, 0)@l
+
+ lis r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_16K)@h
+ ori r7,r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_16K)@l
+
+ lis r8,FSL_BOOKE_MAS2(CFG_INIT_RAM_ADDR, 0)@h
+ ori r8,r8,FSL_BOOKE_MAS2(CFG_INIT_RAM_ADDR, 0)@l
+
+ lis r9,FSL_BOOKE_MAS3(CFG_INIT_RAM_ADDR, 0,
+ (MAS3_SX|MAS3_SW|MAS3_SR))@h
+ ori r9,r9,FSL_BOOKE_MAS3(CFG_INIT_RAM_ADDR, 0,
+ (MAS3_SX|MAS3_SW|MAS3_SR))@l
+
+ mtspr MAS0,r6
+ mtspr MAS1,r7
+ mtspr MAS2,r8
+ mtspr MAS3,r9
+ isync
+ msync
+ tlbwe
+
+ lis r6,MSR_IS|MSR_DS at h
+ ori r6,r6,MSR_IS|MSR_DS at l
+ lis r7,switch_as at h
+ ori r7,r7,switch_as at l
+
+ mtspr SPRN_SRR0,r7
+ mtspr SPRN_SRR1,r6
+ rfi
+
+switch_as:
+/* L1 DCache is used for initial RAM */
+
+ /* Allocate initial RAM in data cache. */
+ lis r3,CFG_INIT_RAM_ADDR at h
+ ori r3,r3,CFG_INIT_RAM_ADDR at l
+ mfspr r2, L1CFG0
+ andi. r2, r2, 0x1ff
+ /* cache size * 1024 / (2 * L1 line size) */
+ slwi r2, r2, (10 - 1 - L1_CACHE_SHIFT)
+ mtctr r2
+ li r0,0
+1:
+ dcbz r0,r3
+ dcbtls 0,r0,r3
+ addi r3,r3,CACHELINE_SIZE
+ bdnz 1b
+
+ /*
+ * Jump out the last 4K page and continue to 'normal' start.
+ * Calculate absolute address in FLASH and jump there.
+ */
+ lis r3,TEXT_BASE at h
+ ori r3,r3,TEXT_BASE at l
+ addi r3,r3,_start_cont - _start + _START_OFFSET
+ mtlr r3
+ blr
+
+ .text
+ .globl _start
+_start:
+ .long 0x62626F78 /* Magic Number */
+
+ .align 4
+ .globl _start_cont
+_start_cont:
+ /* Setup the stack in initial RAM,could be L2-as-SRAM or L1 dcache */
+ lis r1,CFG_INIT_RAM_ADDR at h
+ ori r1,r1,CFG_INIT_SP_OFFSET at l
+
+ li r0,0
+ stwu r0,-4(r1)
+ stwu r0,-4(r1) /* Terminate call chain */
+
+ stwu r1,-8(r1) /* Save back chain and move SP */
+ lis r0,RESET_VECTOR at h /* Address of reset vector */
+ ori r0,r0,RESET_VECTOR at l
+ stwu r1,-8(r1) /* Save back chain and move SP */
+ stw r0,+12(r1) /* Save return addr (underflow vect) */
+
+ GET_GOT
+ bl cpu_init_early_f
+
+ /* switch back to AS = 0 */
+ lis r3,(MSR_CE|MSR_ME|MSR_DE)@h
+ ori r3,r3,(MSR_CE|MSR_ME|MSR_DE)@l
+ mtmsr r3
+ isync
+
+ bl cpu_init_f
+ bl initdram
+ b relocate_code
+ isync
+
+ /* NOTREACHED - board_init_f() does not return */
+
+ . = EXC_OFF_SYS_RESET
+ .globl _start_of_vectors
+_start_of_vectors:
+
+/* Critical input. */
+ CRIT_EXCEPTION(0x0100, CriticalInput, CritcalInputException)
+
+/* Machine check */
+ MCK_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. */
+ STD_EXCEPTION(0x0300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. */
+ STD_EXCEPTION(0x0400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+#ifdef CFG_USE_IRQ
+ STD_EXCEPTION(0x0500, ExtInterrupt, ExtIntException)
+#endif
+
+/* Alignment exception. */
+ . = 0x0600
+Alignment:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ mfspr r4,DAR
+ stw r4,_DAR(r21)
+ mfspr r5,DSISR
+ stw r5,_DSISR(r21)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
+
+/* Program check exception */
+ . = 0x0700
+ProgramCheck:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+ MSR_KERNEL, COPY_EE)
+
+ /* No FPU on MPC85xx. This exception is not supposed to happen.
+ */
+ STD_EXCEPTION(0x0800, FPUnavailable, UnknownException)
+
+ . = 0x0900
+/*
+ * r0 - SYSCALL number
+ * r3-... arguments
+ */
+SystemCall:
+ addis r11,r0,0 /* get functions table addr */
+ ori r11,r11,0 /* Note: this code is patched in trap_init */
+ addis r12,r0,0 /* get number of functions */
+ ori r12,r12,0
+
+ cmplw 0,r0,r12
+ bge 1f
+
+ rlwinm r0,r0,2,0,31 /* fn_addr = fn_tbl[r0] */
+ add r11,r11,r0
+ lwz r11,0(r11)
+
+ li r20,0xd00-4 /* Get stack pointer */
+ lwz r12,0(r20)
+ subi r12,r12,12 /* Adjust stack pointer */
+ li r0,0xc00+_end_back-SystemCall
+ cmplw 0,r0,r12 /* Check stack overflow */
+ bgt 1f
+ stw r12,0(r20)
+
+ mflr r0
+ stw r0,0(r12)
+ mfspr r0,SRR0
+ stw r0,4(r12)
+ mfspr r0,SRR1
+ stw r0,8(r12)
+
+ li r12,0xc00+_back-SystemCall
+ mtlr r12
+ mtspr SRR0,r11
+
+1: SYNC
+ rfi
+_back:
+
+ mfmsr r11 /* Disable interrupts */
+ li r12,0
+ ori r12,r12,MSR_EE
+ andc r11,r11,r12
+ SYNC /* Some chip revs need this... */
+ mtmsr r11
+ SYNC
+
+ li r12,0xd00-4 /* restore regs */
+ lwz r12,0(r12)
+
+ lwz r11,0(r12)
+ mtlr r11
+ lwz r11,4(r12)
+ mtspr SRR0,r11
+ lwz r11,8(r12)
+ mtspr SRR1,r11
+
+ addi r12,r12,12 /* Adjust stack pointer */
+ li r20,0xd00-4
+ stw r12,0(r20)
+
+ SYNC
+ rfi
+_end_back:
+
+ STD_EXCEPTION(0x0a00, Decrementer, UnknownException)
+ STD_EXCEPTION(0x0b00, IntervalTimer, UnknownException)
+ STD_EXCEPTION(0x0c00, WatchdogTimer, UnknownException)
+
+ STD_EXCEPTION(0x0d00, DataTLBError, UnknownException)
+ STD_EXCEPTION(0x0e00, InstructionTLBError, UnknownException)
+
+ CRIT_EXCEPTION(0x0f00, DebugBreakpoint, DebugException )
+
+ .globl _end_of_vectors
+_end_of_vectors:
+
+ . = . + (0x100 - ( . & 0xff )) /* align for debug */
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+ .globl transfer_to_handler
+transfer_to_handler:
+ stw r22,_NIP(r21)
+ lis r22,MSR_POW at h
+ andc r23,r23,r22
+ stw r23,_MSR(r21)
+ SAVE_GPR(7, r21)
+ SAVE_4GPRS(8, r21)
+ SAVE_8GPRS(12, r21)
+ SAVE_8GPRS(24, r21)
+
+ mflr r23
+ andi. r24,r23,0x3f00 /* get vector offset */
+ stw r24,TRAP(r21)
+ li r22,0
+ stw r22,RESULT(r21)
+ mtspr SPRG2,r22 /* r1 is now kernel sp */
+
+ lwz r24,0(r23) /* virtual address of handler */
+ lwz r23,4(r23) /* where to go when done */
+ mtspr SRR0,r24
+ mtspr SRR1,r20
+ mtlr r23
+ SYNC
+ rfi /* jump to handler, enable MMU */
+
+int_return:
+ mfmsr r28 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r28,r28,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r28
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SRR0,r2
+ mtspr SRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfi
+
+crit_return:
+ mfmsr r28 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r28,r28,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r28
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SPRN_CSRR0,r2
+ mtspr SPRN_CSRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfci
+
+mck_return:
+ mfmsr r28 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r28,r28,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r28
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SPRN_MCSRR0,r2
+ mtspr SPRN_MCSRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfmci
+
+/*
+ * Cache functions.
+ */
+.globl invalidate_icache
+invalidate_icache:
+ mfspr r0,L1CSR1
+ ori r0,r0,L1CSR1_ICFI
+ msync
+ isync
+ mtspr L1CSR1,r0
+ isync
+ blr /* entire I cache */
+
+.globl invalidate_dcache
+invalidate_dcache:
+ mfspr r0,L1CSR0
+ ori r0,r0,L1CSR0_DCFI
+ msync
+ isync
+ mtspr L1CSR0,r0
+ isync
+ blr
+
+ .globl icache_enable
+icache_enable:
+ mflr r8
+ bl invalidate_icache
+ mtlr r8
+ isync
+ mfspr r4,L1CSR1
+ ori r4,r4,0x0001
+ oris r4,r4,0x0001
+ mtspr L1CSR1,r4
+ isync
+ blr
+
+ .globl icache_disable
+icache_disable:
+ mfspr r0,L1CSR1
+ lis r3,0
+ ori r3,r3,L1CSR1_ICE
+ andc r0,r0,r3
+ mtspr L1CSR1,r0
+ isync
+ blr
+
+ .globl icache_status
+icache_status:
+ mfspr r3,L1CSR1
+ andi. r3,r3,L1CSR1_ICE
+ blr
+
+ .globl dcache_enable
+dcache_enable:
+ mflr r8
+ bl invalidate_dcache
+ mtlr r8
+ isync
+ mfspr r0,L1CSR0
+ ori r0,r0,0x0001
+ oris r0,r0,0x0001
+ msync
+ isync
+ mtspr L1CSR0,r0
+ isync
+ blr
+
+ .globl dcache_disable
+dcache_disable:
+ mfspr r3,L1CSR0
+ lis r4,0
+ ori r4,r4,L1CSR0_DCE
+ andc r3,r3,r4
+ mtspr L1CSR0,r3
+ isync
+ blr
+
+ .globl dcache_status
+dcache_status:
+ mfspr r3,L1CSR0
+ andi. r3,r3,L1CSR0_DCE
+ blr
+
+ .globl get_pir
+get_pir:
+ mfspr r3,PIR
+ blr
+
+ .globl get_pvr
+get_pvr:
+ mfspr r3,PVR
+ blr
+
+ .globl get_svr
+get_svr:
+ mfspr r3,SVR
+ blr
+
+ .globl wr_tcr
+wr_tcr:
+ mtspr TCR,r3
+ blr
+
+/*---------------------------------------------------------------------------
+ * Function: in8
+ * Description: Input 8 bits
+ *--------------------------------------------------------------------------- */
+ .globl in8
+in8:
+ lbz r3,0x0000(r3)
+ blr
+
+/*---------------------------------------------------------------------------
+ * Function: out8
+ * Description: Output 8 bits
+ *--------------------------------------------------------------------------- */
+ .globl out8
+out8:
+ stb r4,0x0000(r3)
+ sync
+ blr
+
+/*---------------------------------------------------------------------------
+ * Function: out16
+ * Description: Output 16 bits
+ *--------------------------------------------------------------------------- */
+ .globl out16
+out16:
+ sth r4,0x0000(r3)
+ sync
+ blr
+
+/*---------------------------------------------------------------------------
+ * Function: out16r
+ * Description: Byte reverse and output 16 bits
+ *--------------------------------------------------------------------------- */
+ .globl out16r
+out16r:
+ sthbrx r4,r0,r3
+ sync
+ blr
+
+/*---------------------------------------------------------------------------
+ * Function: out32
+ * Description: Output 32 bits
+ *--------------------------------------------------------------------------- */
+ .globl out32
+out32:
+ stw r4,0x0000(r3)
+ sync
+ blr
+
+/*---------------------------------------------------------------------------
+ * Function: out32r
+ * Description: Byte reverse and output 32 bits
+ *--------------------------------------------------------------------------- */
+ .globl out32r
+out32r:
+ stwbrx r4,r0,r3
+ sync
+ blr
+
+/*---------------------------------------------------------------------------
+ * Function: in16
+ * Description: Input 16 bits
+ *--------------------------------------------------------------------------- */
+ .globl in16
+in16:
+ lhz r3,0x0000(r3)
+ blr
+
+/*---------------------------------------------------------------------------
+ * Function: in16r
+ * Description: Input 16 bits and byte reverse
+ *--------------------------------------------------------------------------- */
+ .globl in16r
+in16r:
+ lhbrx r3,r0,r3
+ blr
+
+/*---------------------------------------------------------------------------
+ * Function: in32
+ * Description: Input 32 bits
+ *--------------------------------------------------------------------------- */
+ .globl in32
+in32:
+ lwz 3,0x0000(3)
+ blr
+
+/*---------------------------------------------------------------------------
+ * Function: in32r
+ * Description: Input 32 bits and byte reverse
+ *--------------------------------------------------------------------------- */
+ .globl in32r
+in32r:
+ lwbrx r3,r0,r3
+ blr
+
+/*
+ * void write_tlb(mas0, mas1, mas2, mas3, mas7)
+ */
+ .globl write_tlb
+write_tlb:
+ mtspr MAS0,r3
+ mtspr MAS1,r4
+ mtspr MAS2,r5
+ mtspr MAS3,r6
+ li r3,0
+ isync
+ tlbwe
+ msync
+ isync
+ blr
+
+/*
+ * void relocate_code (end of ram)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+ .globl relocate_code
+relocate_code:
+ mr r9, r3 /* Save end of RAM */
+
+ lis r10, (_end - _start)@h /* Size */
+ ori r10, r10, (_end - _start)@l
+ sub r3, r3, r10
+
+ /* 64KB aligned */
+ lis r10, 0xffff0000 at h
+ ori r10, r10, 0xffff0000 at l
+ and r3, r3, r10
+
+ mr r1, r3 /* Set new stack just below barebox code */
+ mr r10, r3 /* Save copy of Destination Address */
+
+ bl calc_source
+calc_source:
+ mfspr r4, LR /* r4 = address in memory (flash, RAM) */
+ subi r4, r4, (calc_source - _start)
+
+ GET_GOT
+ lis r5, __init_size at h
+ ori r5, r5, __init_size at l
+
+ li r6,CACHELINE_SIZE /* Cache Line Size */
+
+ /*
+ * Fix GOT pointer:
+ *
+ * New GOT-PTR = (old GOT-PTR - TEXT_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
+ mr r4,r3
+5: dcbst 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 5b
+ sync /* Wait for all dcbst to complete on bus */
+ mr r4,r3
+6: icbi 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 6b
+7: sync /* Wait for all icbi to complete on bus */
+ isync
+
+ /*
+ * Re-point the IVPR at RAM
+ */
+ mtspr IVPR,r10
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+
+ addi r0,r10,in_ram - _start + _START_OFFSET
+ mtlr r0
+ blr /* NEVER RETURNS! */
+
+ .globl in_ram
+in_ram:
+
+ /*
+ * Relocation Function, 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 at sectoff@l
+ la r3,GOT(_GOT2_TABLE_)
+ lwz r11,GOT(_GOT2_TABLE_)
+ mtctr r0
+ sub r11,r3,r11
+ addi r3,r3,-4
+1: lwzu r0,4(r3)
+ cmpwi r0,0
+ beq- 2f
+ add r0,r0,r11
+ stw r0,0(r3)
+2: bdnz 1b
+
+ /*
+ * Now adjust the fixups and the pointers to the fixups
+ * in case we need to move ourselves again.
+ */
+ li r0,__fixup_entries at 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
+ cmpwi r0,0
+ add r0,r0,r11
+ stw r4,0(r3)
+ beq- 5f
+ stw r0,0(r4)
+5: 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, r10 /* Destination Address */
+ bl board_init_r
+
+ /*
+ * Copy exception vector code to low memory
+ *
+ * r3: dest_addr
+ * r7: source address, r8: end address, r9: target address
+ */
+ .globl trap_init
+trap_init:
+ mflr r4 /* save link register */
+ GET_GOT
+ lwz r7,GOT(_start_of_vectors)
+ lwz r8,GOT(_end_of_vectors)
+
+ li r9,0x100 /* reset vector always at 0x100 */
+
+ cmplw 0,r7,r8
+ bgelr /* return if r7>=r8 - just in case */
+1:
+ lwz r0,0(r7)
+ stw r0,0(r9)
+ addi r7,r7,4
+ addi r9,r9,4
+ cmplw 0,r7,r8
+ bne 1b
+
+ /*
+ * relocate `hdlr' and `int_return' entries
+ */
+ li r7,.L_CriticalInput - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_MachineCheck - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_DataStorage - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_InstStorage - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_Alignment - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_ProgramCheck - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_FPUnavailable - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_Decrementer - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_IntervalTimer - _start + _START_OFFSET
+ li r8,_end_of_vectors - _start + _START_OFFSET
+2:
+ bl trap_reloc
+ addi r7,r7,0x100 /* next exception vector */
+ cmplw 0,r7,r8
+ blt 2b
+
+ lis r7,0x0
+ mtspr IVPR,r7
+
+ mtlr r4 /* restore link register */
+ blr
+
+
+.globl _text_base
+_text_base:
+ .long TEXT_BASE
+
+.globl unlock_ram_in_cache
+unlock_ram_in_cache:
+ /* invalidate the INIT_RAM section */
+ lis r3,(CFG_INIT_RAM_ADDR & ~(CACHELINE_SIZE-1))@h
+ ori r3,r3,(CFG_INIT_RAM_ADDR & ~(CACHELINE_SIZE-1))@l
+ mfspr r4,L1CFG0
+ andi. r4,r4,0x1ff
+ slwi r4,r4,(10 - 1 - L1_CACHE_SHIFT)
+ mtctr r4
+1: dcbi r0,r3
+ addi r3,r3,CACHELINE_SIZE
+ bdnz 1b
+ sync
+
+ /* Invalidate the TLB entries for the cache */
+ lis r3,CFG_INIT_RAM_ADDR at h
+ ori r3,r3,CFG_INIT_RAM_ADDR at l
+ tlbivax 0,r3
+ addi r3,r3,0x1000
+ tlbivax 0,r3
+ addi r3,r3,0x1000
+ tlbivax 0,r3
+ addi r3,r3,0x1000
+ tlbivax 0,r3
+ isync
+ blr
+
+.globl flush_dcache
+flush_dcache:
+ mfspr r3,SPRN_L1CFG0
+
+ rlwinm r5,r3,9,3 /* Extract cache block size */
+ twlgti r5,1 /* Only 32 and 64 byte cache blocks
+ * are currently defined.
+ */
+ li r4,32
+ subfic r6,r5,2 /* r6 = log2(1KiB / cache block size) -
+ * log2(number of ways)
+ */
+ slw r5,r4,r5 /* r5 = cache block size */
+
+ rlwinm r7,r3,0,0xff /* Extract number of KiB in the cache */
+ mulli r7,r7,13 /* An 8-way cache will require 13
+ * loads per set.
+ */
+ slw r7,r7,r6
+
+ /* save off HID0 and set DCFA */
+ mfspr r8,SPRN_HID0
+ ori r9,r8,HID0_DCFA at l
+ mtspr SPRN_HID0,r9
+ isync
+
+ lis r4,0
+ mtctr r7
+
+1: lwz r3,0(r4) /* Load... */
+ add r4,r4,r5
+ bdnz 1b
+
+ msync
+ lis r4,0
+ mtctr r7
+
+1: dcbf 0,r4 /* ...and flush. */
+ add r4,r4,r5
+ bdnz 1b
+
+ /* restore HID0 */
+ mtspr SPRN_HID0,r8
+ isync
+
+ blr
+
+.globl setup_ivors
+setup_ivors:
+
+#include "fixed_ivor.S"
+ blr
diff --git a/arch/ppc/cpu-85xx/tlb.c b/arch/ppc/cpu-85xx/tlb.c
new file mode 100644
index 0000000..614fea7
--- /dev/null
+++ b/arch/ppc/cpu-85xx/tlb.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2012 GE Intelligent Platforms, Inc.
+ *
+ * Copyright 2008-2009 Freescale Semiconductor, Inc.
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/config.h>
+#include <asm/config_mpc85xx.h>
+#include <asm/mmu.h>
+#include <asm/bitops.h>
+
+void invalidate_tlb(u8 tlb)
+{
+ if (tlb == 0)
+ mtspr(MMUCSR0, 0x4);
+ if (tlb == 1)
+ mtspr(MMUCSR0, 0x2);
+}
+
+void init_tlbs(void)
+{
+ int i;
+
+ for (i = 0; i < num_tlb_entries; i++) {
+ write_tlb(tlb_table[i].mas0,
+ tlb_table[i].mas1,
+ tlb_table[i].mas2,
+ tlb_table[i].mas3,
+ tlb_table[i].mas7);
+ }
+
+ return ;
+}
+
+static int find_free_tlbcam(void)
+{
+ int ix;
+ u32 _mas1;
+ unsigned int num_cam = mfspr(SPRN_TLB1CFG) & 0xfff;
+
+ for (ix = 0; ix < num_cam; ix++) {
+ mtspr(MAS0, FSL_BOOKE_MAS0(1, ix, 0));
+ asm volatile("tlbre;isync");
+ _mas1 = mfspr(MAS1);
+ if (!(_mas1 & MAS1_VALID))
+ return ix;
+ }
+
+ if (ix >= NUM_TLBCAMS)
+ panic("No more free TLBs");
+
+ return ix;
+}
+
+void set_tlb(u8 tlb, u32 epn, u64 rpn,
+ u8 perms, u8 wimge,
+ u8 ts, u8 esel, u8 tsize, u8 iprot)
+{
+ u32 _mas0, _mas1, _mas2, _mas3, _mas7;
+
+ _mas0 = FSL_BOOKE_MAS0(tlb, esel, 0);
+ _mas1 = FSL_BOOKE_MAS1(1, iprot, 0, ts, tsize);
+ _mas2 = FSL_BOOKE_MAS2(epn, wimge);
+ _mas3 = FSL_BOOKE_MAS3(rpn, 0, perms);
+ _mas7 = FSL_BOOKE_MAS7(rpn);
+
+ write_tlb(_mas0, _mas1, _mas2, _mas3, _mas7);
+
+}
+
+void disable_tlb(u8 esel)
+{
+ mtspr(MAS0, FSL_BOOKE_MAS0(1, esel, 0));
+ mtspr(MAS1, 0);
+ mtspr(MAS2, 0);
+ mtspr(MAS3, 0);
+ asm volatile("isync;msync;tlbwe;isync");
+}
+
+static void tlbsx(const unsigned *addr)
+{
+ __asm__ __volatile__ ("tlbsx 0,%0" : : "r" (addr), "m" (*addr));
+}
+
+int find_tlb_idx(void *addr, u8 tlbsel)
+{
+ u32 _mas0, _mas1;
+
+ /* zero out Search PID, AS */
+ mtspr(MAS6, 0);
+ tlbsx(addr);
+
+ _mas0 = mfspr(MAS0);
+ _mas1 = mfspr(MAS1);
+
+ /* we found something, and its in the TLB we expect */
+ if ((MAS1_VALID & _mas1) &&
+ (MAS0_TLBSEL(tlbsel) == (_mas0 & MAS0_TLBSEL_MSK))) {
+ return (_mas0 & MAS0_ESEL_MSK) >> 16;
+ }
+
+ panic("The TLB was not found");
+}
+
+static unsigned int setup_ddr_tlbs_phys(phys_addr_t p_addr,
+ unsigned int memsize_in_meg)
+{
+ int i;
+ unsigned int tlb_size;
+ unsigned int wimge = 0;
+ unsigned int ram_tlb_address = (unsigned int)CFG_SDRAM_BASE;
+ unsigned int max_cam = (mfspr(SPRN_TLB1CFG) >> 16) & 0xf;
+ u64 size, memsize = (u64)memsize_in_meg << 20;
+
+ size = min((u64)memsize, (u64)MAX_MEM_MAPPED);
+
+ /* Convert (4^max) kB to (2^max) bytes */
+ max_cam = (max_cam * 2) + 10;
+
+ for (i = 0; size && (i < 8); i++) {
+ int ram_tlb_index = find_free_tlbcam();
+ u32 camsize = __ilog2_u64(size) & ~1U;
+ u32 align = __ilog2(ram_tlb_address) & ~1U;
+
+ if (align == -2)
+ align = max_cam;
+ if (camsize > align)
+ camsize = align;
+
+ if (camsize > max_cam)
+ camsize = max_cam;
+
+ tlb_size = (camsize - 10) / 2;
+
+ set_tlb(1, ram_tlb_address, p_addr,
+ MAS3_SX|MAS3_SW|MAS3_SR, wimge,
+ 0, ram_tlb_index, tlb_size, 1);
+
+ size -= 1ULL << camsize;
+ memsize -= 1ULL << camsize;
+ ram_tlb_address += 1UL << camsize;
+ p_addr += 1UL << camsize;
+ }
+
+ if (memsize)
+ printf("%lld left unmapped\n", memsize);
+
+ return memsize_in_meg;
+}
+
+unsigned int setup_ddr_tlbs(unsigned int memsize_in_meg)
+{
+ return setup_ddr_tlbs_phys(CFG_SDRAM_BASE, memsize_in_meg);
+}
diff --git a/arch/ppc/cpu-85xx/traps.c b/arch/ppc/cpu-85xx/traps.c
new file mode 100644
index 0000000..a28a2ce
--- /dev/null
+++ b/arch/ppc/cpu-85xx/traps.c
@@ -0,0 +1,297 @@
+/*
+ * linux/arch/powerpc/kernel/traps.c
+ *
+ * Copyright 2007 Freescale Semiconductor.
+ * Copyright (C) 2003 Motorola
+ * Modified by Xianghua Xiao(x.xiao at motorola.com)
+ *
+ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort at cs.nmt.edu)
+ * and Paul Mackerras (paulus at cs.anu.edu.au)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd at 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 <init.h>
+#include <kgdb.h>
+#include <asm/processor.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <mach/immap_85xx.h>
+
+int machinecheck_count;
+int machinecheck_error;
+
+/*
+ * End of addressable memory.
+ */
+#define END_OF_MEM (get_effective_memsize())
+
+static inline void set_tsr(unsigned long val)
+{
+ asm volatile("mtspr 0x150, %0" : : "r" (val));
+}
+
+static inline unsigned long get_esr(void)
+{
+ unsigned long val;
+ asm volatile("mfspr %0, 0x03e" : "=r" (val) : );
+ return val;
+}
+
+#define ESR_MCI 0x80000000
+#define ESR_PIL 0x08000000
+#define ESR_PPR 0x04000000
+#define ESR_PTR 0x02000000
+#define ESR_DST 0x00800000
+#define ESR_DIZ 0x00400000
+#define ESR_U0F 0x00008000
+
+/*
+ * Trap & Exception support
+ */
+void print_backtrace(unsigned long *sp)
+{
+ int cnt = 0;
+ unsigned long i;
+
+ printf("Call backtrace: ");
+ while (sp) {
+ if ((uint)sp > END_OF_MEM)
+ break;
+
+ i = sp[1];
+ if ((cnt++ % 7) == 0)
+ printf("\n");
+ printf("%08lX ", i);
+ if (cnt > 32)
+ break;
+ sp = (unsigned long *)*sp;
+ }
+ printf("\n");
+}
+
+void show_regs(struct pt_regs *regs)
+{
+ int i;
+
+ printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx "
+ "DAR: %08lX\n",
+ regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+ printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x "
+ "IR/DR: %01x%01x\n",
+ regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
+ regs->msr & MSR_FP ? 1 : 0, regs->msr&MSR_ME ? 1 : 0,
+ regs->msr&MSR_IR ? 1 : 0,
+ regs->msr&MSR_DR ? 1 : 0);
+
+ printf("\n");
+ for (i = 0; i < 32; i++) {
+ if ((i % 8) == 0)
+ printf("GPR%02d: ", i);
+
+ printf("%08lX ", regs->gpr[i]);
+ if ((i % 8) == 7)
+ printf("\n");
+ }
+}
+
+void _exception(int signr, struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Exception in kernel pc %lx signal %d", regs->nip, signr);
+}
+
+void CritcalInputException(struct pt_regs *regs)
+{
+ panic("Critical Input Exception");
+}
+
+static int exception_init(void)
+{
+ machinecheck_count = 0;
+ machinecheck_error = 0;
+
+ return 0;
+}
+core_initcall(exception_init);
+
+void MachineCheckException(struct pt_regs *regs)
+{
+ unsigned long fixup;
+ unsigned int mcsr, mcsrr0, mcsrr1, mcar;
+
+ /*
+ * Probing PCI using config cycles cause this exception
+ * when a device is not present. Catch it and return to
+ * the PCI exception handler.
+ */
+ fixup = search_exception_table(regs->nip);
+ if (fixup != 0) {
+ regs->nip = fixup;
+ return;
+ }
+
+ mcsrr0 = mfspr(SPRN_MCSRR0);
+ mcsrr1 = mfspr(SPRN_MCSRR1);
+ mcsr = mfspr(SPRN_MCSR);
+ mcar = mfspr(SPRN_MCAR);
+
+ machinecheck_count++;
+ machinecheck_error = 1;
+
+#if defined(CONFIG_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ printf("Machine check in kernel mode.\n");
+ printf("Caused by (from mcsr): ");
+ printf("mcsr = 0x%08x\n", mcsr);
+ if (mcsr & 0x80000000)
+ printf("Machine check input pin\n");
+ if (mcsr & 0x40000000)
+ printf("Instruction cache parity error\n");
+ if (mcsr & 0x20000000)
+ printf("Data cache push parity error\n");
+ if (mcsr & 0x10000000)
+ printf("Data cache parity error\n");
+ if (mcsr & 0x00000080)
+ printf("Bus instruction address error\n");
+ if (mcsr & 0x00000040)
+ printf("Bus Read address error\n");
+ if (mcsr & 0x00000020)
+ printf("Bus Write address error\n");
+ if (mcsr & 0x00000010)
+ printf("Bus Instruction data bus error\n");
+ if (mcsr & 0x00000008)
+ printf("Bus Read data bus error\n");
+ if (mcsr & 0x00000004)
+ printf("Bus Write bus error\n");
+ if (mcsr & 0x00000002)
+ printf("Bus Instruction parity error\n");
+ if (mcsr & 0x00000001)
+ printf("Bus Read parity error\n");
+
+ show_regs(regs);
+ printf("MCSR=0x%08x\tMCSRR0=0x%08x\nMCSRR1=0x%08x\tMCAR=0x%08x\n",
+ mcsr, mcsrr0, mcsrr1, mcar);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+
+ if (machinecheck_count > 10)
+ panic("machine check count too high\n");
+
+ if (machinecheck_count > 1) {
+ regs->nip += 4; /* skip offending instruction */
+ printf("Skipping current instr, Returning to 0x%08lx\n",
+ regs->nip);
+ } else {
+ printf("Returning back to 0x%08lx\n", regs->nip);
+ }
+}
+
+void AlignmentException(struct pt_regs *regs)
+{
+#if defined(CONFIG_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Alignment Exception");
+}
+
+void ProgramCheckException(struct pt_regs *regs)
+{
+ long esr_val;
+
+#if defined(CONFIG_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ show_regs(regs);
+
+ esr_val = get_esr();
+ if (esr_val & ESR_PIL)
+ printf("** Illegal Instruction **\n");
+ else if (esr_val & ESR_PPR)
+ printf("** Privileged Instruction **\n");
+ else if (esr_val & ESR_PTR)
+ printf("** Trap Instruction **\n");
+
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Program Check Exception");
+}
+
+void PITException(struct pt_regs *regs)
+{
+ /* Reset PIT interrupt */
+ set_tsr(0x0c000000);
+}
+
+void UnknownException(struct pt_regs *regs)
+{
+#if defined(CONFIG_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+ regs->nip, regs->msr, regs->trap);
+ _exception(0, regs);
+}
+
+void ExtIntException(struct pt_regs *regs)
+{
+ void __iomem *pic = (void __iomem *)(MPC8xxx_PIC_ADDR);
+ uint vect;
+
+#if defined(CONFIG_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ printf("External Interrupt Exception at PC: %lx, SR: %lx, vector=%lx",
+ regs->nip, regs->msr, regs->trap);
+ vect = in_be32(pic + MPC85xx_PIC_IACK0_OFFSET);
+ printf(" irq IACK0@%05x=%d\n", (int)(pic + MPC85xx_PIC_IACK0_OFFSET),
+ vect);
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+}
+
+void DebugException(struct pt_regs *regs)
+{
+ printf("Debugger trap at @ %lx\n", regs->nip);
+ show_regs(regs);
+#if defined(CONFIG_BEDBUG)
+ do_bedbug_breakpoint(regs);
+#endif
+}
diff --git a/arch/ppc/include/asm/config.h b/arch/ppc/include/asm/config.h
new file mode 100644
index 0000000..9c4458b
--- /dev/null
+++ b/arch/ppc/include/asm/config.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2012 GE Intelligent Platforms, Inc.
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _ASM_CONFIG_H_
+#define _ASM_CONFIG_H_
+
+#ifdef CONFIG_MPC85xx
+#include <asm/config_mpc85xx.h>
+#endif
+
+#ifndef MAX_MEM_MAPPED
+#if defined(CONFIG_E500)
+#define MAX_MEM_MAPPED ((phys_size_t)(2 << 30))
+#endif
+#endif
+
+/*
+ * Provide a default boot page translation virtual address that lines up with
+ * Freescale's default e500 reset page.
+ */
+#if (defined(CONFIG_E500) && defined(CONFIG_MP))
+#ifndef BPTR_VIRT_ADDR
+#define BPTR_VIRT_ADDR 0xfffff000
+#endif
+#endif
+
+#endif /* _ASM_CONFIG_H_ */
diff --git a/arch/ppc/include/asm/config_mpc85xx.h b/arch/ppc/include/asm/config_mpc85xx.h
new file mode 100644
index 0000000..5da4f2f
--- /dev/null
+++ b/arch/ppc/include/asm/config_mpc85xx.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2012 GE Intelligent Platforms, Inc.
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _ASM_MPC85xx_CONFIG_H_
+#define _ASM_MPC85xx_CONFIG_H_
+
+/* Number of TLB CAM entries we have on FSL Book-E chips */
+#if defined(CONFIG_E500)
+#define NUM_TLBCAMS 16
+#endif
+
+#if defined(CONFIG_P2020)
+#define MAX_CPUS 2
+#define FSL_NUM_LAWS 12
+#define FSL_SEC_COMPAT 2
+#else
+#error Processor type not defined for this platform
+#endif
+
+#endif /* _ASM_MPC85xx_CONFIG_H_ */
diff --git a/arch/ppc/include/asm/e500.h b/arch/ppc/include/asm/e500.h
new file mode 100644
index 0000000..ceb28cd
--- /dev/null
+++ b/arch/ppc/include/asm/e500.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2012 GE Intelligent Platforms, Inc.
+ * Copyright 2003 Motorola,Inc.
+ * Xianghua Xiao(x.xiao at motorola.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __E500_H__
+#define __E500_H__
+
+#ifndef __ASSEMBLY__
+#include <asm/config_mpc85xx.h>
+
+struct sys_info {
+ unsigned long freqProcessor[MAX_CPUS];
+ unsigned long freqSystemBus;
+ unsigned long freqDDRBus;
+ unsigned long freqLocalBus;
+};
+
+#endif /* _ASMLANGUAGE */
+
+#define RESET_VECTOR 0xfffffffc
+
+#endif /* __E500_H__ */
diff --git a/arch/ppc/include/asm/fsl_ddr_sdram.h b/arch/ppc/include/asm/fsl_ddr_sdram.h
new file mode 100644
index 0000000..5de2d72
--- /dev/null
+++ b/arch/ppc/include/asm/fsl_ddr_sdram.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2012 GE Intelligent Platforms, Inc.
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#ifndef FSL_DDR_MEMCTL_H
+#define FSL_DDR_MEMCTL_H
+
+/*
+ * DDR_SDRAM_CFG - DDR SDRAM Control Configuration
+ */
+#define SDRAM_CFG_MEM_EN 0x80000000
+#define SDRAM_CFG_SREN 0x40000000
+#define SDRAM_CFG_ECC_EN 0x20000000
+#define SDRAM_CFG_RD_EN 0x10000000
+#define SDRAM_CFG_SDRAM_TYPE_DDR1 0x02000000
+#define SDRAM_CFG_SDRAM_TYPE_DDR2 0x03000000
+#define SDRAM_CFG_SDRAM_TYPE_MASK 0x07000000
+#define SDRAM_CFG_SDRAM_TYPE_SHIFT 24
+#define SDRAM_CFG_DYN_PWR 0x00200000
+#define SDRAM_CFG_32_BE 0x00080000
+#define SDRAM_CFG_8_BE 0x00040000
+#define SDRAM_CFG_NCAP 0x00020000
+#define SDRAM_CFG_2T_EN 0x00008000
+#define SDRAM_CFG_BI 0x00000001
+
+extern phys_size_t get_effective_memsize(void);
+extern phys_size_t fixed_sdram(void);
+
+#endif
diff --git a/arch/ppc/include/asm/fsl_law.h b/arch/ppc/include/asm/fsl_law.h
new file mode 100644
index 0000000..14f29e5
--- /dev/null
+++ b/arch/ppc/include/asm/fsl_law.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#ifndef _FSL_LAW_H_
+#define _FSL_LAW_H_
+
+#include <asm/io.h>
+
+#define LAW_EN 0x80000000
+
+#define SET_LAW_ENTRY(idx, a, sz, trgt) \
+ { .index = idx, .addr = a, .size = sz, .trgt_id = trgt }
+
+#define SET_LAW(a, sz, trgt) \
+ { .index = -1, .addr = a, .size = sz, .trgt_id = trgt }
+
+enum law_size {
+ LAW_SIZE_4K = 0xb,
+ LAW_SIZE_8K,
+ LAW_SIZE_16K,
+ LAW_SIZE_32K,
+ LAW_SIZE_64K,
+ LAW_SIZE_128K,
+ LAW_SIZE_256K,
+ LAW_SIZE_512K,
+ LAW_SIZE_1M,
+ LAW_SIZE_2M,
+ LAW_SIZE_4M,
+ LAW_SIZE_8M,
+ LAW_SIZE_16M,
+ LAW_SIZE_32M,
+ LAW_SIZE_64M,
+ LAW_SIZE_128M,
+ LAW_SIZE_256M,
+ LAW_SIZE_512M,
+ LAW_SIZE_1G,
+ LAW_SIZE_2G,
+ LAW_SIZE_4G,
+ LAW_SIZE_8G,
+ LAW_SIZE_16G,
+ LAW_SIZE_32G,
+};
+
+#define law_size_bits(sz) (__ilog2_u64(sz) - 1)
+#define lawar_size(x) (1ULL << (((x) & 0x3f) + 1))
+
+enum law_trgt_if {
+ LAW_TRGT_IF_PCI = 0x00,
+ LAW_TRGT_IF_PCI_2 = 0x01,
+ LAW_TRGT_IF_PCIE_1 = 0x02,
+#if !defined(CONFIG_P2020)
+ LAW_TRGT_IF_PCIE_3 = 0x03,
+#endif
+ LAW_TRGT_IF_LBC = 0x04,
+ LAW_TRGT_IF_CCSR = 0x08,
+ LAW_TRGT_IF_DDR_INTRLV = 0x0b,
+ LAW_TRGT_IF_RIO = 0x0c,
+ LAW_TRGT_IF_RIO_2 = 0x0d,
+ LAW_TRGT_IF_DDR = 0x0f,
+ LAW_TRGT_IF_DDR_2 = 0x16, /* 2nd controller */
+};
+#define LAW_TRGT_IF_DDR_1 LAW_TRGT_IF_DDR
+#define LAW_TRGT_IF_PCI_1 LAW_TRGT_IF_PCI
+#define LAW_TRGT_IF_PCIX LAW_TRGT_IF_PCI
+#define LAW_TRGT_IF_PCIE_2 LAW_TRGT_IF_PCI_2
+#define LAW_TRGT_IF_RIO_1 LAW_TRGT_IF_RIO
+
+
+#if defined(CONFIG_P2020)
+#define LAW_TRGT_IF_PCIE_3 LAW_TRGT_IF_PCI
+#endif
+
+struct law_entry {
+ int index;
+ phys_addr_t addr;
+ enum law_size size;
+ enum law_trgt_if trgt_id;
+};
+
+extern int set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id);
+extern void init_laws(void);
+
+/* define in board code */
+extern struct law_entry law_table[];
+extern int num_law_entries;
+#endif
diff --git a/arch/ppc/include/asm/fsl_lbc.h b/arch/ppc/include/asm/fsl_lbc.h
new file mode 100644
index 0000000..8c6b08a
--- /dev/null
+++ b/arch/ppc/include/asm/fsl_lbc.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2012 GE Intelligent Platforms, Inc.
+ * Copyright (C) 2004-2008,2010-2011 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef __ASM_PPC_FSL_LBC_H
+#define __ASM_PPC_FSL_LBC_H
+
+#include <config.h>
+#include <common.h>
+
+/*
+ * BR - Base Registers
+ */
+#define BR_PS 0x00001800
+#define BR_PS_SHIFT 11
+#define BR_PS_8 0x00000800 /* Port Size 8 bit */
+#define BR_PS_16 0x00001000 /* Port Size 16 bit */
+#define BR_PS_32 0x00001800 /* Port Size 32 bit */
+#define BR_V 0x00000001
+#define BR_V_SHIFT 0
+
+/* Convert an address into the right format for the BR registers */
+#define BR_PHYS_ADDR(x) ((x) & 0xffff8000)
+
+/* helpers to convert values into an OR address mask (GPCM mode) */
+#if 0
+#define P2SZ_TO_AM(s) ((~((s) - 1)) & 0xffff8000) /* must be pow of 2 */
+#define MEG_TO_AM(m) P2SZ_TO_AM((m) << 20)
+#endif
+
+/*
+ * CLKDIV is five bits only on 8536, 8572, and 8610, so far, but the fifth bit
+ * should always be zero on older parts that have a four bit CLKDIV.
+ */
+#define LCRR_CLKDIV 0x0000001f
+#define LCRR_CLKDIV_SHIFT 0
+#define LCRR_CLKDIV_4 0x00000002
+#define LCRR_CLKDIV_8 0x00000004
+#define LCRR_CLKDIV_16 0x00000008
+
+#ifndef __ASSEMBLY__
+#include <asm/io.h>
+
+extern void init_early_memctl_regs(void);
+
+/* LBC register offsets. */
+#define FSL_LBC_BRX(x) ((x) * 8) /* bank register offsets. */
+#define FSL_LBC_ORX(x) (4 + ((x) * 8)) /* option register offset. */
+#define FSL_LBC_LCCR 0x0d4 /* Clock ration register. */
+
+#define LBC_BASE_ADDR ((void __iomem *)LBC_ADDR)
+#define get_lbc_br(x) (in_be32((LBC_BASE_ADDR + FSL_LBC_BRX(x))))
+#define get_lbc_or(x) (in_be32((LBC_BASE_ADDR + FSL_LBC_ORX(x))))
+#define set_lbc_br(x, v) (out_be32((LBC_BASE_ADDR + FSL_LBC_BRX(x)), v))
+#define set_lbc_or(x, v) (out_be32((LBC_BASE_ADDR + FSL_LBC_ORX(x)), v))
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_PPC_FSL_LBC_H */
diff --git a/arch/ppc/lib/Makefile b/arch/ppc/lib/Makefile
index 0f5e017..ba2f078 100644
--- a/arch/ppc/lib/Makefile
+++ b/arch/ppc/lib/Makefile
@@ -8,4 +8,5 @@ obj-y += misc.o
obj-$(CONFIG_CMD_BOOTM) += ppclinux.o
obj-$(CONFIG_MODULES) += module.o
obj-y += crtsavres.o
+obj-y += reloc.o
diff --git a/arch/ppc/lib/board.c b/arch/ppc/lib/board.c
index a840c75..f5fea15 100644
--- a/arch/ppc/lib/board.c
+++ b/arch/ppc/lib/board.c
@@ -30,14 +30,11 @@
#include <net.h>
#include <asm-generic/memory_layout.h>
-/************************************************************************
- *
+/*
* This is the next part if the initialization sequence: we are now
* running from RAM and have a "normal" C environment, i. e. global
* data can be written, BSS has been cleared, the stack size in not
* that critical any more, etc.
- *
- ************************************************************************
*/
void board_init_r (ulong end_of_ram)
@@ -46,6 +43,10 @@ void board_init_r (ulong end_of_ram)
asm ("sync ; isync");
+#ifdef CONFIG_MPC85xx
+ _text_base = end_of_ram;
+#endif
+
/*
* FIXME: 128k stack size. Is this enough? should
* it be configurable?
diff --git a/arch/ppc/lib/reloc.S b/arch/ppc/lib/reloc.S
new file mode 100644
index 0000000..92ee189
--- /dev/null
+++ b/arch/ppc/lib/reloc.S
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2009 Wolfgang Denk <wd at 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 <asm/ppc_asm.tmpl>
+
+ .file "reloc.S"
+
+ .text
+ /*
+ * Function: relocate entries for one exception vector
+ */
+ .globl trap_reloc
+ .type trap_reloc, @function
+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)
+
+ lwz r0, 8(r7) /* transfer_to_handler ...*/
+ add r0, r0, r3 /* ... += dest_addr */
+ stw r0, 8(r7)
+
+ blr
+ .size trap_reloc, .-trap_reloc
diff --git a/arch/ppc/mach-mpc85xx/Kconfig b/arch/ppc/mach-mpc85xx/Kconfig
new file mode 100644
index 0000000..4758951
--- /dev/null
+++ b/arch/ppc/mach-mpc85xx/Kconfig
@@ -0,0 +1,45 @@
+if ARCH_MPC85XX
+
+config TEXT_BASE
+ hex
+ default 0xeff80000 if P2020RDB
+
+config BOARDINFO
+ default "P2020_RDB" if P2020RDB
+
+config MPC85xx
+ bool
+ default y if P2020RDB
+
+choice
+ prompt "Select your board"
+
+config P2020RDB
+ bool "P2020RDB"
+ help
+ Say Y here if you are using the Freescale P2020RDB
+
+endchoice
+endif
+
+if P2020RDB
+config P2020
+ bool
+ default y
+
+config BOOKE
+ bool
+ default y
+
+config E500
+ bool
+ default y
+
+config MP
+ bool
+ default y if P2020
+
+config FSL_ELBC
+ bool
+ default y
+endif
diff --git a/arch/ppc/mach-mpc85xx/Makefile b/arch/ppc/mach-mpc85xx/Makefile
new file mode 100644
index 0000000..6900108
--- /dev/null
+++ b/arch/ppc/mach-mpc85xx/Makefile
@@ -0,0 +1,6 @@
+obj-y += cpuid.o
+obj-y += fsl_lbc.o
+obj-y += fsl_law.o
+obj-y += speed.o
+obj-y +=time.o
+obj-$(CONFIG_MP) += mp.o
diff --git a/arch/ppc/mach-mpc85xx/cpuid.c b/arch/ppc/mach-mpc85xx/cpuid.c
new file mode 100644
index 0000000..4fe53a4
--- /dev/null
+++ b/arch/ppc/mach-mpc85xx/cpuid.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * This file is derived from arch/powerpc/cpu/mpc85xx/cpu.c and
+ * arch/powerpc/cpu/mpc86xx/cpu.c. Basically this file contains
+ * cpu specific common code for 85xx/86xx processors.
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <common.h>
+#include <command.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <mach/immap_85xx.h>
+
+struct cpu_type cpu_type_list[] = {
+ CPU_TYPE_ENTRY(P2020, P2020, 2),
+ CPU_TYPE_ENTRY(P2020, P2020_E, 2),
+};
+
+struct cpu_type cpu_type_unknown = CPU_TYPE_ENTRY(Unknown, Unknown, 1);
+
+struct cpu_type *identify_cpu(u32 ver)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(cpu_type_list); i++) {
+ if (cpu_type_list[i].soc_ver == ver)
+ return &cpu_type_list[i];
+ }
+ return &cpu_type_unknown;
+}
+
+int cpu_numcores(void)
+{
+ void __iomem *pic = (void __iomem *)MPC8xxx_PIC_ADDR;
+ struct cpu_type *cpu;
+ uint svr;
+ uint ver;
+ int tmp;
+
+ svr = get_svr();
+ ver = SVR_SOC_VER(svr);
+ cpu = identify_cpu(ver);
+
+ /* better to query feature reporting register than just assume 1 */
+ if (cpu == &cpu_type_unknown) {
+ tmp = in_be32(pic + MPC85xx_PIC_FRR_OFFSET);
+ tmp = (tmp & MPC8xxx_PICFRR_NCPU_MASK) >>
+ MPC8xxx_PICFRR_NCPU_SHIFT;
+ tmp += 1;
+ } else {
+ tmp = cpu->num_cores;
+ }
+
+ return tmp;
+}
diff --git a/arch/ppc/mach-mpc85xx/fsl_law.c b/arch/ppc/mach-mpc85xx/fsl_law.c
new file mode 100644
index 0000000..fecece5
--- /dev/null
+++ b/arch/ppc/mach-mpc85xx/fsl_law.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2012 GE Intelligent Platforms, Inc.
+ *
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd at 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/config.h>
+#include <asm/fsl_law.h>
+#include <asm/io.h>
+
+#define FSL_HW_NUM_LAWS FSL_NUM_LAWS
+
+#define LAW_BASE (CFG_IMMR + 0xc08)
+#define LAWAR_ADDR(x) ((u32 *)LAW_BASE + 8 * (x) + 2)
+#define LAWBAR_ADDR(x) ((u32 *)LAW_BASE + 8 * (x))
+#define LAWBAR_SHIFT 12
+
+static inline phys_addr_t get_law_base_addr(int idx)
+{
+ return (phys_addr_t)in_be32(LAWBAR_ADDR(idx)) << LAWBAR_SHIFT;
+}
+
+static inline void set_law_base_addr(int idx, phys_addr_t addr)
+{
+ out_be32(LAWBAR_ADDR(idx), addr >> LAWBAR_SHIFT);
+}
+
+static void set_law(u8 idx, phys_addr_t addr, enum law_size sz,
+ enum law_trgt_if id)
+{
+ out_be32(LAWAR_ADDR(idx), 0);
+ set_law_base_addr(idx, addr);
+ out_be32(LAWAR_ADDR(idx), LAW_EN | ((u32)id << 20) | (u32)sz);
+
+ /* Read back so that we sync the writes */
+ in_be32(LAWAR_ADDR(idx));
+}
+
+static int is_free_law(int idx)
+{
+ u32 lawar;
+
+ lawar = in_be32(LAWAR_ADDR(idx));
+ if (!(lawar & LAW_EN))
+ return 1;
+
+ return 0;
+}
+
+static void set_next_law(phys_addr_t addr, enum law_size sz,
+ enum law_trgt_if id)
+{
+ u32 idx;
+
+ for (idx = 0; idx < FSL_HW_NUM_LAWS; idx++) {
+ if (is_free_law(idx)) {
+ set_law(idx, addr, sz, id);
+ break;
+ }
+ }
+
+ if (idx >= FSL_HW_NUM_LAWS)
+ panic("No more LAWS available\n");
+}
+
+static void set_last_law(phys_addr_t addr, enum law_size sz,
+ enum law_trgt_if id)
+{
+ u32 idx;
+
+ for (idx = (FSL_HW_NUM_LAWS - 1); idx >= 0; idx--) {
+ if (is_free_law(idx)) {
+ set_law(idx, addr, sz, id);
+ break;
+ }
+ }
+
+ if (idx < 0)
+ panic("No more LAWS available\n");
+}
+
+/* use up to 2 LAWs for DDR, use the last available LAWs */
+int set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id)
+{
+ u64 start_align, law_sz;
+ int law_sz_enc;
+
+ if (start == 0)
+ start_align = 1ull << (LAW_SIZE_32G + 1);
+ else
+ start_align = 1ull << (ffs64(start) - 1);
+
+ law_sz = min(start_align, sz);
+ law_sz_enc = __ilog2_u64(law_sz) - 1;
+
+ set_last_law(start, law_sz_enc, id);
+
+ /* recalculate size based on what was actually covered by the law */
+ law_sz = 1ull << __ilog2_u64(law_sz);
+
+ /* do we still have anything to map */
+ sz = sz - law_sz;
+ if (sz) {
+ start += law_sz;
+
+ start_align = 1ull << (ffs64(start) - 1);
+ law_sz = min(start_align, sz);
+ law_sz_enc = __ilog2_u64(law_sz) - 1;
+
+ set_last_law(start, law_sz_enc, id);
+ } else {
+ return 0;
+ }
+
+ /* do we still have anything to map */
+ sz = sz - law_sz;
+ if (sz)
+ return 1;
+
+ return 0;
+}
+
+void init_laws(void)
+{
+ int i;
+
+ if (FSL_HW_NUM_LAWS > 32)
+ panic("FSL_HW_NUM_LAWS can not be > 32 w/o code changes");
+
+ for (i = 0; i < num_law_entries; i++) {
+ if (law_table[i].index == -1)
+ set_next_law(law_table[i].addr, law_table[i].size,
+ law_table[i].trgt_id);
+ else
+ set_law(law_table[i].index, law_table[i].addr,
+ law_table[i].size, law_table[i].trgt_id);
+ }
+}
diff --git a/arch/ppc/mach-mpc85xx/fsl_lbc.c b/arch/ppc/mach-mpc85xx/fsl_lbc.c
new file mode 100644
index 0000000..78a46e8
--- /dev/null
+++ b/arch/ppc/mach-mpc85xx/fsl_lbc.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/fsl_lbc.h>
+#include <mach/immap_85xx.h>
+
+void init_early_memctl_regs(void)
+{
+ set_lbc_br(0, CFG_BR0_PRELIM);
+ set_lbc_or(0, CFG_OR0_PRELIM);
+}
diff --git a/arch/ppc/mach-mpc85xx/include/mach/clocks.h b/arch/ppc/mach-mpc85xx/include/mach/clocks.h
new file mode 100644
index 0000000..99c63be
--- /dev/null
+++ b/arch/ppc/mach-mpc85xx/include/mach/clocks.h
@@ -0,0 +1,11 @@
+#ifndef __ASM_ARCH_CLOCKS_H
+#define __ASM_ARCH_CLOCKS_H
+
+#include <mach/mpc85xx.h>
+
+#define NSEC_PER_SEC 1000000000L
+
+unsigned long get_bus_freq(ulong dummy);
+unsigned long get_timebase_clock(void);
+void get_sys_info(struct sys_info *sysInfo);
+#endif /* __ASM_ARCH_CLOCKS_H */
diff --git a/arch/ppc/mach-mpc85xx/include/mach/early_udelay.h b/arch/ppc/mach-mpc85xx/include/mach/early_udelay.h
new file mode 100644
index 0000000..dc2d8bc
--- /dev/null
+++ b/arch/ppc/mach-mpc85xx/include/mach/early_udelay.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2012 GE Intelligent Platforms, Inc.
+ *
+ * Copyright (C) 2009 Matthias Kaehlcke <matthias at kaehlcke.net>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+/* early_udelay: delay execution before timers are initialized
+ *
+ * "usecs * 100" gives a time of around 1 second on a 1Ghz CPU.
+ */
+static inline void early_udelay(unsigned long usecs)
+{
+ uint64_t start;
+ uint32_t loops = usecs * 100;
+
+ start = get_ticks();
+
+ while ((get_ticks() - start) < loops)
+ ;
+}
diff --git a/arch/ppc/mach-mpc85xx/include/mach/immap_85xx.h b/arch/ppc/mach-mpc85xx/include/mach/immap_85xx.h
new file mode 100644
index 0000000..b802249
--- /dev/null
+++ b/arch/ppc/mach-mpc85xx/include/mach/immap_85xx.h
@@ -0,0 +1,132 @@
+/*
+ * MPC85xx Internal Memory Map
+ *
+ * Copyright 2007-2011 Freescale Semiconductor, Inc.
+ *
+ * Copyright(c) 2002,2003 Motorola Inc.
+ * Xianghua Xiao (x.xiao at motorola.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __IMMAP_85xx__
+#define __IMMAP_85xx__
+
+#include <asm/types.h>
+#include <asm/fsl_lbc.h>
+#include <asm/config.h>
+
+#define MPC85xx_LOCAL_OFFSET 0x0000
+#define MPC85xx_ECM_OFFSET 0x1000
+#define MPC85xx_DDR_OFFSET 0x2000
+#define MPC85xx_LBC_OFFSET 0x5000
+
+#define MPC85xx_GPIO_OFFSET 0xf000
+#define MPC85xx_L2_OFFSET 0x20000
+
+#define MPC85xx_PIC_OFFSET 0x40000
+#define MPC85xx_GUTS_OFFSET 0xe0000
+
+#define MPC85xx_LOCAL_ADDR (CFG_IMMR + MPC85xx_LOCAL_OFFSET)
+#define MPC85xx_ECM_ADDR (CFG_IMMR + MPC85xx_ECM_OFFSET)
+#define MPC85xx_GUTS_ADDR (CFG_IMMR + MPC85xx_GUTS_OFFSET)
+#define MPC85xx_DDR_ADDR (CFG_IMMR + MPC85xx_DDR_OFFSET)
+#define LBC_ADDR (CFG_IMMR + MPC85xx_LBC_OFFSET)
+#define MPC85xx_GPIO_ADDR (CFG_IMMR + MPC85xx_GPIO_OFFSET)
+#define MPC85xx_L2_ADDR (CFG_IMMR + MPC85xx_L2_OFFSET)
+#define MPC8xxx_PIC_ADDR (CFG_IMMR + MPC85xx_PIC_OFFSET)
+
+/* Local-Access Registers */
+#define MPC85xx_LOCAL_BPTR_OFFSET 0x20 /* Boot Page Translation */
+
+/* ECM Registers */
+#define MPC85xx_ECM_EEBPCR_OFFSET 0x00 /* ECM CCB Port Configuration */
+
+/*
+ * DDR Memory Controller Register Offsets
+ */
+/* Chip Select 0, 1,2, 3 Memory Bounds */
+#define MPC85xx_DDR_CS0_BNDS_OFFSET 0x000
+#define MPC85xx_DDR_CS1_BNDS_OFFSET 0x008
+#define MPC85xx_DDR_CS2_BNDS_OFFSET 0x010
+#define MPC85xx_DDR_CS3_BNDS_OFFSET 0x018
+/* Chip Select 0, 1, 2, 3 Configuration */
+#define MPC85xx_DDR_CS0_CONFIG_OFFSET 0x080
+#define MPC85xx_DDR_CS1_CONFIG_OFFSET 0x084
+#define MPC85xx_DDR_CS2_CONFIG_OFFSET 0x088
+#define MPC85xx_DDR_CS3_CONFIG_OFFSET 0x08c
+/* SDRAM Timing Configuration 0, 1, 2, 3 */
+#define MPC85xx_DDR_TIMING_CFG_3_OFFSET 0x100
+#define MPC85xx_DDR_TIMING_CFG_0_OFFSET 0x104
+#define MPC85xx_DDR_TIMING_CFG_1_OFFSET 0x108
+#define MPC85xx_DDR_TIMING_CFG_2_OFFSET 0x10c
+/* SDRAM Control Configuration */
+#define MPC85xx_DDR_SDRAM_CFG_OFFSET 0x110
+#define MPC85xx_DDR_SDRAM_CFG_2_OFFSET 0x114
+/* SDRAM Mode Configuration */
+#define MPC85xx_DDR_SDRAM_MODE_OFFSET 0x118
+#define MPC85xx_DDR_SDRAM_MODE_2_OFFSET 0x11c
+/* SDRAM Mode Control */
+#define MPC85xx_DDR_SDRAM_MD_CNTL_OFFSET 0x120
+/* SDRAM Interval Configuration */
+#define MPC85xx_DDR_SDRAM_INTERVAL_OFFSET 0x124
+/* SDRAM Data initialization */
+#define MPC85xx_DDR_SDRAM_DATA_INIT_OFFSET 0x128
+/* SDRAM Clock Control */
+#define MPC85xx_DDR_SDRAM_CLK_CNTL_OFFSET 0x130
+/* training init and extended addr */
+#define MPC85xx_DDR_SDRAM_INIT_ADDR_OFFSET 0x148
+#define MPC85xx_DDR_SDRAM_INIT_ADDR_EXT_OFFSET 0x14c
+
+#define DDR_OFF(REGNAME) (MPC85xx_DDR_##REGNAME##_OFFSET)
+
+/*
+ * GPIO Register Offsets
+ */
+#define MPC85xx_GPIO_GPDIR 0x00
+#define MPC85xx_GPIO_GPDAT 0x08
+
+/*
+ * L2 Cache Register Offsets
+ */
+#define MPC85xx_L2_CTL_OFFSET 0x0 /* L2 configuration 0 */
+#define MPC85xx_L2CTL_L2E 0x80000000
+
+/* PIC registers offsets */
+#define MPC85xx_PIC_WHOAMI_OFFSET 0x090
+#define MPC85xx_PIC_FRR_OFFSET 0x1000 /* Feature Reporting */
+/* PIC registers fields values and masks. */
+#define MPC8xxx_PICFRR_NCPU_MASK 0x00001f00
+#define MPC8xxx_PICFRR_NCPU_SHIFT 8
+#define MPC85xx_PICGCR_RST 0x80000000
+#define MPC85xx_PICGCR_M 0x20000000
+
+#define MPC85xx_PIC_IACK0_OFFSET 0x600a0 /* IRQ Acknowledge for
+ Processor 0 */
+
+/* Global Utilities Register Offsets and field values */
+#define MPC85xx_GUTS_PORPLLSR_OFFSET 0x0
+#define MPC85xx_PORPLLSR_DDR_RATIO 0x00003e00
+#define MPC85xx_PORPLLSR_DDR_RATIO_SHIFT 9
+#define MPC85xx_GUTS_DEVDISR_OFFSET 0x70
+#define MPC85xx_DEVDISR_TB0 0x00004000
+#define MPC85xx_DEVDISR_TB1 0x00001000
+#define MPC85xx_GUTS_RSTCR_OFFSET 0xb0
+
+#endif /*__IMMAP_85xx__*/
diff --git a/arch/ppc/mach-mpc85xx/include/mach/mp.h b/arch/ppc/mach-mpc85xx/include/mach/mp.h
new file mode 100644
index 0000000..19b5c87
--- /dev/null
+++ b/arch/ppc/mach-mpc85xx/include/mach/mp.h
@@ -0,0 +1,15 @@
+#ifndef __MPC85XX_MP_H_
+#define __MPC85XX_MP_H_
+
+void setup_mp(void);
+int cpu_numcores(void);
+
+extern ulong __secondary_start_page;
+extern ulong __spin_table;
+extern ulong __bootpg_addr;
+
+#define BOOT_ENTRY_ADDR_LOWER 1
+#define NUM_BOOT_ENTRY 8
+#define SIZE_BOOT_ENTRY (NUM_BOOT_ENTRY * sizeof(u32))
+
+#endif
diff --git a/arch/ppc/mach-mpc85xx/include/mach/mpc85xx.h b/arch/ppc/mach-mpc85xx/include/mach/mpc85xx.h
new file mode 100644
index 0000000..ba27c64
--- /dev/null
+++ b/arch/ppc/mach-mpc85xx/include/mach/mpc85xx.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2004, 2007 Freescale Semiconductor.
+ * Copyright(c) 2003 Motorola Inc.
+ */
+
+#ifndef __MPC85xx_H__
+#define __MPC85xx_H__
+
+/* define for common ppc_asm.tmpl */
+#define EXC_OFF_SYS_RESET 0x100 /* System reset */
+#define _START_OFFSET 0
+
+#if defined(CONFIG_E500)
+#include <asm/e500.h>
+#endif
+
+#endif /* __MPC85xx_H__ */
diff --git a/arch/ppc/mach-mpc85xx/mp.c b/arch/ppc/mach-mpc85xx/mp.c
new file mode 100644
index 0000000..3dfc80a
--- /dev/null
+++ b/arch/ppc/mach-mpc85xx/mp.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <common.h>
+#include <environment.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/mmu.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <mach/immap_85xx.h>
+#include <mach/early_udelay.h>
+#include <mach/mp.h>
+
+/*
+ * Determine if Barebox should keep secondary cores in reset, or let them out
+ * of reset and hold them in a spinloop.
+ *
+ */
+static int hold_cores_in_reset(int verbose)
+{
+ /* Do not hold core in reset. */
+ return 0;
+}
+
+static u32 determine_mp_bootpg(void)
+{
+ /* if we have 4G or more of memory, put the boot page at 4Gb-4k */
+ if ((u64)get_effective_memsize() > 0xfffff000)
+ return 0xfffff000;
+
+ return get_effective_memsize() - 4096;
+}
+
+static ulong get_spin_virt_addr(void)
+{
+ return BPTR_VIRT_ADDR + (ulong)&__spin_table -
+ (ulong)&__secondary_start_page;
+}
+
+static void plat_mp_up(unsigned long bootpg)
+{
+ u32 up, cpu_up_mask, whoami;
+ u32 *table = (u32 *)get_spin_virt_addr();
+ u32 bpcr;
+ void __iomem *local = (void __iomem *)(MPC85xx_LOCAL_ADDR);
+ void __iomem *ecm = (void __iomem *)(MPC85xx_ECM_ADDR);
+ void __iomem *gur = (void __iomem *)(MPC85xx_GUTS_ADDR);
+ void __iomem *pic = (void __iomem *)(MPC8xxx_PIC_ADDR);
+ u32 devdisr;
+ int timeout = 10;
+
+ whoami = in_be32(pic + MPC85xx_PIC_WHOAMI_OFFSET);
+ out_be32(local + MPC85xx_LOCAL_BPTR_OFFSET,
+ 0x80000000 | (bootpg >> 12));
+
+ /* disable time base at the platform */
+ devdisr = in_be32(gur + MPC85xx_GUTS_DEVDISR_OFFSET);
+ if (whoami)
+ devdisr |= MPC85xx_DEVDISR_TB0;
+ else
+ devdisr |= MPC85xx_DEVDISR_TB1;
+ out_be32(gur + MPC85xx_GUTS_DEVDISR_OFFSET, devdisr);
+
+ up = ((1 << cpu_numcores()) - 1);
+ bpcr = in_be32(ecm + MPC85xx_ECM_EEBPCR_OFFSET);
+ bpcr |= (up << 24);
+ out_be32(ecm + MPC85xx_ECM_EEBPCR_OFFSET, bpcr);
+ asm("sync; isync; msync");
+
+ cpu_up_mask = 1 << whoami;
+ /* wait for everyone */
+ while (timeout) {
+ int i;
+ for (i = 0; i < cpu_numcores(); i++) {
+ if (table[i * NUM_BOOT_ENTRY + BOOT_ENTRY_ADDR_LOWER])
+ cpu_up_mask |= (1 << i);
+ };
+
+ if ((cpu_up_mask & up) == up)
+ break;
+
+ early_udelay(100);
+ timeout--;
+ }
+
+ if (timeout == 0)
+ debug("CPU up timeout. CPU up mask is %x should be %x\n",
+ cpu_up_mask, up);
+
+ /* enable time base at the platform */
+ if (whoami)
+ devdisr |= MPC85xx_DEVDISR_TB1;
+ else
+ devdisr |= MPC85xx_DEVDISR_TB0;
+ out_be32(gur + MPC85xx_GUTS_DEVDISR_OFFSET, devdisr);
+ mtspr(SPRN_TBWU, 0);
+ mtspr(SPRN_TBWL, 0);
+
+ devdisr &= ~(MPC85xx_DEVDISR_TB0 | MPC85xx_DEVDISR_TB1);
+ out_be32(gur + MPC85xx_GUTS_DEVDISR_OFFSET, devdisr);
+}
+
+void setup_mp(void)
+{
+ ulong fixup = (ulong)&__secondary_start_page;
+ u32 bootpg = determine_mp_bootpg();
+ int i;
+
+ if (hold_cores_in_reset(0))
+ return;
+
+ /* Store the bootpg's SDRAM address for use by secondary CPU cores */
+ __bootpg_addr = bootpg;
+
+ /* look for the tlb covering the reset page, there better be one */
+ i = find_tlb_idx((void *)BPTR_VIRT_ADDR, 1);
+
+ /* we found a match */
+ if (i != -1) {
+ /* map reset page to bootpg so we can copy code there */
+ disable_tlb(i);
+
+ set_tlb(1, BPTR_VIRT_ADDR, bootpg, /* tlb, epn, rpn */
+ MAS3_SX|MAS3_SW|MAS3_SR,
+ MAS2_I|MAS2_G, /* perms, wimge */
+ 0, i, BOOKE_PAGESZ_4K, 1); /* ts, esel, tsize, iprot */
+
+ memcpy((void *)BPTR_VIRT_ADDR, (void *)fixup, 4096);
+
+ plat_mp_up(bootpg);
+ } else {
+ puts("WARNING: No reset page TLB. "
+ "Skipping secondary core setup\n");
+ }
+}
diff --git a/arch/ppc/mach-mpc85xx/speed.c b/arch/ppc/mach-mpc85xx/speed.c
new file mode 100644
index 0000000..27ce323
--- /dev/null
+++ b/arch/ppc/mach-mpc85xx/speed.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2012 GE Intelligent Platforms, Inc.
+ *
+ * Copyright 2004, 2007-2011 Freescale Semiconductor, Inc.
+ *
+ * (C) Copyright 2003 Motorola Inc.
+ * Xianghua Xiao, (X.Xiao at motorola.com)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <mach/mpc85xx.h>
+#include <mach/immap_85xx.h>
+#include <mach/mp.h>
+
+void get_sys_info(struct sys_info *sysInfo)
+{
+ void __iomem *gur = (void __iomem *)(MPC85xx_GUTS_ADDR);
+ uint plat_ratio, e500_ratio, half_freqSystemBus;
+ uint lcrr_div;
+ int i;
+
+ plat_ratio = in_be32(gur + MPC85xx_GUTS_PORPLLSR_OFFSET) & 0x0000003e;
+ plat_ratio >>= 1;
+ sysInfo->freqSystemBus = plat_ratio * CFG_SYS_CLK_FREQ;
+
+ /*
+ * Divide before multiply to avoid integer
+ * overflow for processor speeds above 2GHz.
+ */
+ half_freqSystemBus = sysInfo->freqSystemBus/2;
+ for (i = 0; i < cpu_numcores(); i++) {
+ e500_ratio = (in_be32(gur + MPC85xx_GUTS_PORPLLSR_OFFSET) >>
+ (i * 8 + 16)) & 0x3f;
+ sysInfo->freqProcessor[i] = e500_ratio * half_freqSystemBus;
+ }
+
+ /* Note: freqDDRBus is the MCLK frequency, not the data rate. */
+ sysInfo->freqDDRBus = sysInfo->freqSystemBus;
+
+#ifdef CFG_DDR_CLK_FREQ
+ {
+ u32 ddr_ratio = (in_be32(gur + MPC85xx_GUTS_PORPLLSR_OFFSET) &
+ MPC85xx_PORPLLSR_DDR_RATIO) >>
+ MPC85xx_PORPLLSR_DDR_RATIO_SHIFT;
+ if (ddr_ratio != 0x7)
+ sysInfo->freqDDRBus = ddr_ratio * CFG_DDR_CLK_FREQ;
+ }
+#endif
+
+ lcrr_div = in_be32(LBC_BASE_ADDR + FSL_LBC_LCCR) & LCRR_CLKDIV;
+
+ if (lcrr_div == 2 || lcrr_div == 4 || lcrr_div == 8) {
+ /*
+ * The entire PQ38 family use the same bit-representation
+ * for twice the clock divider values.
+ */
+ lcrr_div *= 2;
+
+ sysInfo->freqLocalBus = sysInfo->freqSystemBus / lcrr_div;
+ } else {
+ /* In case anyone cares what the unknown value is */
+ sysInfo->freqLocalBus = lcrr_div;
+ }
+}
+
+unsigned long get_bus_freq(ulong dummy)
+{
+ struct sys_info sys_info;
+
+ get_sys_info(&sys_info);
+
+ return sys_info.freqSystemBus;
+}
diff --git a/arch/ppc/mach-mpc85xx/time.c b/arch/ppc/mach-mpc85xx/time.c
new file mode 100644
index 0000000..4e36bad
--- /dev/null
+++ b/arch/ppc/mach-mpc85xx/time.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012 GE Intelligent Platforms, Inc.
+ * (C) Copyright 2000, 2001
+ * Wolfgang Denk, DENX Software Engineering, wd at 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 <clock.h>
+#include <init.h>
+#include <mach/clocks.h>
+#include <asm/common.h>
+
+uint64_t ppc_clocksource_read(void)
+{
+ return get_ticks();
+}
+
+static struct clocksource cs = {
+ .read = ppc_clocksource_read,
+ .mask = CLOCKSOURCE_MASK(64),
+};
+
+static int clocksource_init(void)
+{
+ /* reset time base */
+ asm ("li 3,0 ; mttbu 3 ; mttbl 3 ;");
+
+ clocks_calc_mult_shift(&cs.mult, &cs.shift, get_timebase_clock(),
+ NSEC_PER_SEC, 10);
+
+ init_clock(&cs);
+
+ return 0;
+}
+
+core_initcall(clocksource_init);
--
1.7.1
More information about the barebox
mailing list