aboutsummaryrefslogtreecommitdiffstats
path: root/roms/u-boot/arch/powerpc/cpu/mpc8xx
diff options
context:
space:
mode:
Diffstat (limited to 'roms/u-boot/arch/powerpc/cpu/mpc8xx')
-rw-r--r--roms/u-boot/arch/powerpc/cpu/mpc8xx/Kconfig175
-rw-r--r--roms/u-boot/arch/powerpc/cpu/mpc8xx/Makefile14
-rw-r--r--roms/u-boot/arch/powerpc/cpu/mpc8xx/cache.c49
-rw-r--r--roms/u-boot/arch/powerpc/cpu/mpc8xx/config.mk6
-rw-r--r--roms/u-boot/arch/powerpc/cpu/mpc8xx/cpu.c287
-rw-r--r--roms/u-boot/arch/powerpc/cpu/mpc8xx/cpu_init.c192
-rw-r--r--roms/u-boot/arch/powerpc/cpu/mpc8xx/fdt.c30
-rw-r--r--roms/u-boot/arch/powerpc/cpu/mpc8xx/immap.c406
-rw-r--r--roms/u-boot/arch/powerpc/cpu/mpc8xx/interrupts.c252
-rw-r--r--roms/u-boot/arch/powerpc/cpu/mpc8xx/speed.c44
-rw-r--r--roms/u-boot/arch/powerpc/cpu/mpc8xx/start.S542
-rw-r--r--roms/u-boot/arch/powerpc/cpu/mpc8xx/traps.c157
12 files changed, 2154 insertions, 0 deletions
diff --git a/roms/u-boot/arch/powerpc/cpu/mpc8xx/Kconfig b/roms/u-boot/arch/powerpc/cpu/mpc8xx/Kconfig
new file mode 100644
index 000000000..f11231737
--- /dev/null
+++ b/roms/u-boot/arch/powerpc/cpu/mpc8xx/Kconfig
@@ -0,0 +1,175 @@
+menu "mpc8xx CPU"
+ depends on MPC8xx
+
+config SYS_CPU
+ default "mpc8xx"
+
+choice
+ prompt "Target select"
+ optional
+
+config TARGET_MCR3000
+ bool "Support MCR3000 board from CSSI"
+
+endchoice
+
+choice
+ prompt "CPU select"
+ default MPC866
+
+config MPC866
+ bool "MPC866"
+
+config MPC885
+ bool "MPC885"
+
+endchoice
+
+config 8xx_GCLK_FREQ
+ int "CPU GCLK Frequency"
+
+comment "Specific commands"
+
+config CMD_IMMAP
+ bool "Enable various commands to dump IMMR information"
+ help
+ This enables various commands such as:
+
+ siuinfo - print System Interface Unit (SIU) registers
+ memcinfo - print Memory Controller registers
+
+comment "Configuration Registers"
+
+config SYS_SIUMCR
+ hex "SIUMCR register"
+ help
+ SIU Module Configuration (11-6)
+
+config SYS_SYPCR
+ hex "SYPCR register"
+ help
+ System Protection Control (11-9)
+
+config SYS_TBSCR
+ hex "TBSCR register"
+ help
+ Time Base Status and Control (11-26)
+
+config SYS_PISCR
+ hex "PISCR register"
+ help
+ Periodic Interrupt Status and Control (11-31)
+
+config SYS_PLPRCR_BOOL
+ bool "Customise PLPRCR"
+
+config SYS_PLPRCR
+ hex "PLPRCR register"
+ depends on SYS_PLPRCR_BOOL
+ help
+ PLL, Low-Power, and Reset Control Register (15-30)
+
+config SYS_SCCR
+ hex "SCCR register"
+ help
+ System Clock and reset Control Register (15-27)
+
+config SYS_SCCR_MASK
+ hex "MASK for setting SCCR register"
+
+config SYS_DER
+ hex "DER register"
+ help
+ Debug Event Register (37-47)
+
+comment "Memory mapping"
+
+config SYS_BR0_PRELIM
+ hex "Preliminary value for BR0"
+
+config SYS_OR0_PRELIM
+ hex "Preliminary value for OR0"
+
+config SYS_BR1_PRELIM_BOOL
+ bool "Define Bank 1"
+
+config SYS_BR1_PRELIM
+ hex "Preliminary value for BR1"
+ depends on SYS_BR1_PRELIM_BOOL
+
+config SYS_OR1_PRELIM
+ hex "Preliminary value for OR1"
+ depends on SYS_BR1_PRELIM_BOOL
+
+config SYS_BR2_PRELIM_BOOL
+ bool "Define Bank 2"
+
+config SYS_BR2_PRELIM
+ hex "Preliminary value for BR2"
+ depends on SYS_BR2_PRELIM_BOOL
+
+config SYS_OR2_PRELIM
+ hex "Preliminary value for OR2"
+ depends on SYS_BR2_PRELIM_BOOL
+
+config SYS_BR3_PRELIM_BOOL
+ bool "Define Bank 3"
+
+config SYS_BR3_PRELIM
+ hex "Preliminary value for BR3"
+ depends on SYS_BR3_PRELIM_BOOL
+
+config SYS_OR3_PRELIM
+ hex "Preliminary value for OR3"
+ depends on SYS_BR3_PRELIM_BOOL
+
+config SYS_BR4_PRELIM_BOOL
+ bool "Define Bank 4"
+
+config SYS_BR4_PRELIM
+ hex "Preliminary value for BR4"
+ depends on SYS_BR4_PRELIM_BOOL
+
+config SYS_OR4_PRELIM
+ hex "Preliminary value for OR4"
+ depends on SYS_BR4_PRELIM_BOOL
+
+config SYS_BR5_PRELIM_BOOL
+ bool "Define Bank 5"
+
+config SYS_BR5_PRELIM
+ hex "Preliminary value for BR5"
+ depends on SYS_BR5_PRELIM_BOOL
+
+config SYS_OR5_PRELIM
+ hex "Preliminary value for OR5"
+ depends on SYS_BR5_PRELIM_BOOL
+
+config SYS_BR6_PRELIM_BOOL
+ bool "Define Bank 6"
+
+config SYS_BR6_PRELIM
+ hex "Preliminary value for BR6"
+ depends on SYS_BR6_PRELIM_BOOL
+
+config SYS_OR6_PRELIM
+ hex "Preliminary value for OR6"
+ depends on SYS_BR6_PRELIM_BOOL
+
+config SYS_BR7_PRELIM_BOOL
+ bool "Define Bank 7"
+
+config SYS_BR7_PRELIM
+ hex "Preliminary value for BR7"
+ depends on SYS_BR7_PRELIM_BOOL
+
+config SYS_OR7_PRELIM
+ hex "Preliminary value for OR7"
+ depends on SYS_BR7_PRELIM_BOOL
+
+config SYS_IMMR
+ hex "Value for IMMR"
+
+source "board/cssi/MCR3000/Kconfig"
+
+endmenu
diff --git a/roms/u-boot/arch/powerpc/cpu/mpc8xx/Makefile b/roms/u-boot/arch/powerpc/cpu/mpc8xx/Makefile
new file mode 100644
index 000000000..8918a2628
--- /dev/null
+++ b/roms/u-boot/arch/powerpc/cpu/mpc8xx/Makefile
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+extra-y += start.o
+extra-y += traps.o
+obj-y += cpu.o
+obj-y += cpu_init.o
+obj-$(CONFIG_OF_LIBFDT) += fdt.o
+obj-$(CONFIG_CMD_IMMAP) += immap.o
+obj-y += interrupts.o
+obj-y += speed.o
+obj-y += cache.o
diff --git a/roms/u-boot/arch/powerpc/cpu/mpc8xx/cache.c b/roms/u-boot/arch/powerpc/cpu/mpc8xx/cache.c
new file mode 100644
index 000000000..41559009c
--- /dev/null
+++ b/roms/u-boot/arch/powerpc/cpu/mpc8xx/cache.c
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2017
+ * Christophe Leroy, CS Systemes d'Information, christophe.leroy@c-s.fr
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <asm/processor.h>
+#include <asm/ppc.h>
+#include <asm/io.h>
+#include <asm/mmu.h>
+
+int icache_status(void)
+{
+ return !!(mfspr(IC_CST) & IDC_ENABLED);
+}
+
+void icache_enable(void)
+{
+ sync();
+ mtspr(IC_CST, IDC_INVALL);
+ mtspr(IC_CST, IDC_ENABLE);
+}
+
+void icache_disable(void)
+{
+ sync();
+ mtspr(IC_CST, IDC_DISABLE);
+}
+
+int dcache_status(void)
+{
+ return !!(mfspr(IC_CST) & IDC_ENABLED);
+}
+
+void dcache_enable(void)
+{
+ mtspr(MD_CTR, MD_RESETVAL); /* Set cache mode with MMU off */
+ mtspr(DC_CST, IDC_INVALL);
+ mtspr(DC_CST, IDC_ENABLE);
+}
+
+void dcache_disable(void)
+{
+ sync();
+ mtspr(DC_CST, IDC_DISABLE);
+ mtspr(DC_CST, IDC_INVALL);
+}
diff --git a/roms/u-boot/arch/powerpc/cpu/mpc8xx/config.mk b/roms/u-boot/arch/powerpc/cpu/mpc8xx/config.mk
new file mode 100644
index 000000000..00b7ed50a
--- /dev/null
+++ b/roms/u-boot/arch/powerpc/cpu/mpc8xx/config.mk
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2010
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+PLATFORM_CPPFLAGS += -mstring -mcpu=860 -msoft-float
diff --git a/roms/u-boot/arch/powerpc/cpu/mpc8xx/cpu.c b/roms/u-boot/arch/powerpc/cpu/mpc8xx/cpu.c
new file mode 100644
index 000000000..893aecef2
--- /dev/null
+++ b/roms/u-boot/arch/powerpc/cpu/mpc8xx/cpu.c
@@ -0,0 +1,287 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+/*
+ * m8xx.c
+ *
+ * CPU specific code
+ *
+ * written or collected and sometimes rewritten by
+ * Magnus Damm <damm@bitsmart.com>
+ *
+ * minor modifications by
+ * Wolfgang Denk <wd@denx.de>
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <net.h>
+#include <time.h>
+#include <vsprintf.h>
+#include <watchdog.h>
+#include <command.h>
+#include <mpc8xx.h>
+#include <netdev.h>
+#include <asm/cache.h>
+#include <asm/cpm_8xx.h>
+#include <asm/global_data.h>
+#include <linux/compiler.h>
+#include <asm/io.h>
+
+#if defined(CONFIG_OF_LIBFDT)
+#include <linux/libfdt.h>
+#include <fdt_support.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* ------------------------------------------------------------------------- */
+/* L1 i-cache */
+
+int checkicache(void)
+{
+ immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
+ memctl8xx_t __iomem *memctl = &immap->im_memctl;
+ u32 cacheon = rd_ic_cst() & IDC_ENABLED;
+ /* probe in flash memoryarea */
+ u32 k = in_be32(&memctl->memc_br0) & ~0x00007fff;
+ u32 m;
+ u32 lines = -1;
+
+ wr_ic_cst(IDC_UNALL);
+ wr_ic_cst(IDC_INVALL);
+ wr_ic_cst(IDC_DISABLE);
+ __asm__ volatile ("isync");
+
+ while (!((m = rd_ic_cst()) & IDC_CERR2)) {
+ wr_ic_adr(k);
+ wr_ic_cst(IDC_LDLCK);
+ __asm__ volatile ("isync");
+
+ lines++;
+ k += 0x10; /* the number of bytes in a cacheline */
+ }
+
+ wr_ic_cst(IDC_UNALL);
+ wr_ic_cst(IDC_INVALL);
+
+ if (cacheon)
+ wr_ic_cst(IDC_ENABLE);
+ else
+ wr_ic_cst(IDC_DISABLE);
+
+ __asm__ volatile ("isync");
+
+ return lines << 4;
+};
+
+/* ------------------------------------------------------------------------- */
+/* L1 d-cache */
+/* call with cache disabled */
+
+static int checkdcache(void)
+{
+ immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
+ memctl8xx_t __iomem *memctl = &immap->im_memctl;
+ u32 cacheon = rd_dc_cst() & IDC_ENABLED;
+ /* probe in flash memoryarea */
+ u32 k = in_be32(&memctl->memc_br0) & ~0x00007fff;
+ u32 m;
+ u32 lines = -1;
+
+ wr_dc_cst(IDC_UNALL);
+ wr_dc_cst(IDC_INVALL);
+ wr_dc_cst(IDC_DISABLE);
+
+ while (!((m = rd_dc_cst()) & IDC_CERR2)) {
+ wr_dc_adr(k);
+ wr_dc_cst(IDC_LDLCK);
+ lines++;
+ k += 0x10; /* the number of bytes in a cacheline */
+ }
+
+ wr_dc_cst(IDC_UNALL);
+ wr_dc_cst(IDC_INVALL);
+
+ if (cacheon)
+ wr_dc_cst(IDC_ENABLE);
+ else
+ wr_dc_cst(IDC_DISABLE);
+
+ return lines << 4;
+};
+
+static int check_CPU(long clock, uint pvr, uint immr)
+{
+ immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
+ uint k;
+ char buf[32];
+
+ /* the highest 16 bits should be 0x0050 for a 860 */
+
+ if (PVR_VER(pvr) != PVR_VER(PVR_8xx))
+ return -1;
+
+ k = (immr << 16) |
+ in_be16(&immap->im_cpm.cp_dparam16[PROFF_REVNUM / sizeof(u16)]);
+
+ /*
+ * Some boards use sockets so different CPUs can be used.
+ * We have to check chip version in run time.
+ */
+ switch (k) {
+ /* MPC866P/MPC866T/MPC859T/MPC859DSL/MPC852T */
+ case 0x08010004: /* Rev. A.0 */
+ printf("MPC866xxxZPnnA");
+ break;
+ case 0x08000003: /* Rev. 0.3 */
+ printf("MPC866xxxZPnn");
+ break;
+ case 0x09000000: /* 870/875/880/885 */
+ puts("MPC885ZPnn");
+ break;
+
+ default:
+ printf("unknown MPC86x (0x%08x)", k);
+ break;
+ }
+
+ printf(" at %s MHz: ", strmhz(buf, clock));
+
+ print_size(checkicache(), " I-Cache ");
+ print_size(checkdcache(), " D-Cache");
+
+ /* do we have a FEC (860T/P or 852/859/866/885)? */
+
+ out_be32(&immap->im_cpm.cp_fec.fec_addr_low, 0x12345678);
+ if (in_be32(&immap->im_cpm.cp_fec.fec_addr_low) == 0x12345678)
+ printf(" FEC present");
+
+ putc('\n');
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int checkcpu(void)
+{
+ ulong clock = gd->cpu_clk;
+ uint immr = get_immr(); /* Return full IMMR contents */
+ uint pvr = get_pvr();
+
+ puts("CPU: ");
+
+ return check_CPU(clock, pvr, immr);
+}
+
+/* ------------------------------------------------------------------------- */
+
+void upmconfig(uint upm, uint *table, uint size)
+{
+ uint i;
+ uint addr = 0;
+ immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
+ memctl8xx_t __iomem *memctl = &immap->im_memctl;
+
+ for (i = 0; i < size; i++) {
+ out_be32(&memctl->memc_mdr, table[i]); /* (16-15) */
+ out_be32(&memctl->memc_mcr, addr | upm); /* (16-16) */
+ addr++;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ ulong msr, addr;
+
+ immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
+
+ /* Checkstop Reset enable */
+ setbits_be32(&immap->im_clkrst.car_plprcr, PLPRCR_CSR);
+
+ /* Interrupts and MMU off */
+ __asm__ volatile ("mtspr 81, 0");
+ __asm__ volatile ("mfmsr %0" : "=r" (msr));
+
+ msr &= ~0x1030;
+ __asm__ volatile ("mtmsr %0" : : "r" (msr));
+
+ /*
+ * Trying to execute the next instruction at a non-existing address
+ * should cause a machine check, resulting in reset
+ */
+#ifdef CONFIG_SYS_RESET_ADDRESS
+ addr = CONFIG_SYS_RESET_ADDRESS;
+#else
+ /*
+ * note: when CONFIG_SYS_MONITOR_BASE points to a RAM address,
+ * CONFIG_SYS_MONITOR_BASE - sizeof (ulong) is usually a valid address.
+ * Better pick an address known to be invalid on your system and assign
+ * it to CONFIG_SYS_RESET_ADDRESS.
+ * "(ulong)-1" used to be a good choice for many systems...
+ */
+ addr = CONFIG_SYS_MONITOR_BASE - sizeof(ulong);
+#endif
+ ((void (*)(void)) addr)();
+ return 1;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Get timebase clock frequency (like cpu_clk in Hz)
+ *
+ * See sections 14.2 and 14.6 of the User's Manual
+ */
+unsigned long get_tbclk(void)
+{
+ immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
+ ulong oscclk, factor, pll;
+
+ if (in_be32(&immap->im_clkrst.car_sccr) & SCCR_TBS)
+ return gd->cpu_clk / 16;
+
+ pll = in_be32(&immap->im_clkrst.car_plprcr);
+
+#define PLPRCR_val(a) ((pll & PLPRCR_ ## a ## _MSK) >> PLPRCR_ ## a ## _SHIFT)
+
+ /*
+ * For newer PQ1 chips (MPC866/87x/88x families), PLL multiplication
+ * factor is calculated as follows:
+ *
+ * MFN
+ * MFI + -------
+ * MFD + 1
+ * factor = -----------------
+ * (PDF + 1) * 2^S
+ *
+ */
+ factor = (PLPRCR_val(MFI) + PLPRCR_val(MFN) / (PLPRCR_val(MFD) + 1)) /
+ (PLPRCR_val(PDF) + 1) / (1 << PLPRCR_val(S));
+
+ oscclk = gd->cpu_clk / factor;
+
+ if ((in_be32(&immap->im_clkrst.car_sccr) & SCCR_RTSEL) == 0 ||
+ factor > 2)
+ return oscclk / 4;
+
+ return oscclk / 16;
+}
+
+/*
+ * Initializes on-chip ethernet controllers.
+ * to override, implement board_eth_init()
+ */
+int cpu_eth_init(struct bd_info *bis)
+{
+#if defined(CONFIG_MPC8XX_FEC)
+ fec_initialize(bis);
+#endif
+ return 0;
+}
diff --git a/roms/u-boot/arch/powerpc/cpu/mpc8xx/cpu_init.c b/roms/u-boot/arch/powerpc/cpu/mpc8xx/cpu_init.c
new file mode 100644
index 000000000..c8d06b050
--- /dev/null
+++ b/roms/u-boot/arch/powerpc/cpu/mpc8xx/cpu_init.c
@@ -0,0 +1,192 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <watchdog.h>
+
+#include <mpc8xx.h>
+#include <asm/cpm_8xx.h>
+#include <asm/io.h>
+
+/*
+ * Breath some life into the CPU...
+ *
+ * Set up the memory map,
+ * initialize a bunch of registers,
+ * initialize the UPM's
+ */
+void cpu_init_f(immap_t __iomem *immr)
+{
+ memctl8xx_t __iomem *memctl = &immr->im_memctl;
+ ulong reg;
+
+ /* SYPCR - contains watchdog control (11-9) */
+
+#ifndef CONFIG_HW_WATCHDOG
+ /* deactivate watchdog if not enabled in config */
+ out_be32(&immr->im_siu_conf.sc_sypcr, CONFIG_SYS_SYPCR & ~SYPCR_SWE);
+#endif
+
+ WATCHDOG_RESET();
+
+ /* SIUMCR - contains debug pin configuration (11-6) */
+ setbits_be32(&immr->im_siu_conf.sc_siumcr, CONFIG_SYS_SIUMCR);
+ /* initialize timebase status and control register (11-26) */
+ /* unlock TBSCRK */
+
+ out_be32(&immr->im_sitk.sitk_tbscrk, KAPWR_KEY);
+ out_be16(&immr->im_sit.sit_tbscr, CONFIG_SYS_TBSCR | TBSCR_TBE);
+
+ /* Unlock timebase register */
+ out_be32(&immr->im_sitk.sitk_tbk, KAPWR_KEY);
+
+ /* initialize the PIT (11-31) */
+
+ out_be32(&immr->im_sitk.sitk_piscrk, KAPWR_KEY);
+ out_be16(&immr->im_sit.sit_piscr, CONFIG_SYS_PISCR);
+
+ /* System integration timers. Don't change EBDF! (15-27) */
+
+ out_be32(&immr->im_clkrstk.cark_sccrk, KAPWR_KEY);
+ clrsetbits_be32(&immr->im_clkrst.car_sccr, ~CONFIG_SYS_SCCR_MASK,
+ CONFIG_SYS_SCCR);
+
+ /*
+ * MPC866/885 ERRATA GLL2
+ * Description:
+ * In 1:2:1 mode, when HRESET is detected at the positive edge of
+ * EXTCLK, then there will be a loss of phase between
+ * EXTCLK and CLKOUT.
+ *
+ * Workaround:
+ * Reprogram the SCCR:
+ * 1. Write 1'b00 to SCCR[EBDF].
+ * 2. Write 1'b01 to SCCR[EBDF].
+ * 3. Rewrite the desired value to the PLPRCR register.
+ */
+ reg = in_be32(&immr->im_clkrst.car_sccr);
+ /* Are we in mode 1:2:1 ? */
+ if ((reg & SCCR_EBDF11) == SCCR_EBDF01) {
+ clrbits_be32(&immr->im_clkrst.car_sccr, SCCR_EBDF11);
+ setbits_be32(&immr->im_clkrst.car_sccr, SCCR_EBDF01);
+ }
+
+ /* PLL (CPU clock) settings (15-30) */
+
+ out_be32(&immr->im_clkrstk.cark_plprcrk, KAPWR_KEY);
+
+ /* If CONFIG_SYS_PLPRCR (set in the various *_config.h files) tries to
+ * set the MF field, then just copy CONFIG_SYS_PLPRCR over car_plprcr,
+ * otherwise OR in CONFIG_SYS_PLPRCR so we do not change the current MF
+ * field value.
+ *
+ * For newer (starting MPC866) chips PLPRCR layout is different.
+ */
+#ifdef CONFIG_SYS_PLPRCR
+ if ((CONFIG_SYS_PLPRCR & PLPRCR_MFACT_MSK) != 0) /* reset control bits*/
+ out_be32(&immr->im_clkrst.car_plprcr, CONFIG_SYS_PLPRCR);
+ else /* isolate MF-related fields and reset control bits */
+ clrsetbits_be32(&immr->im_clkrst.car_plprcr, ~PLPRCR_MFACT_MSK,
+ CONFIG_SYS_PLPRCR);
+#endif
+
+ /*
+ * Memory Controller:
+ */
+
+ /* Clear everything except Port Size bits & add the "Bank Valid" bit */
+ clrsetbits_be32(&memctl->memc_br0, ~BR_PS_MSK, BR_V);
+
+ /* Map banks 0 (and maybe 1) to the FLASH banks 0 (and 1) at
+ * preliminary addresses - these have to be modified later
+ * when FLASH size has been determined
+ *
+ * Depending on the size of the memory region defined by
+ * CONFIG_SYS_OR0_REMAP some boards (wide address mask) allow to map the
+ * CONFIG_SYS_MONITOR_BASE, while others (narrower address mask) can't
+ * map CONFIG_SYS_MONITOR_BASE.
+ *
+ * For example, for CONFIG_IVMS8, the CONFIG_SYS_MONITOR_BASE is
+ * 0xff000000, but CONFIG_SYS_OR0_REMAP's address mask is 0xfff80000.
+ *
+ * If BR0 wasn't loaded with address base 0xff000000, then BR0's
+ * base address remains as 0x00000000. However, the address mask
+ * have been narrowed to 512Kb, so CONFIG_SYS_MONITOR_BASE wasn't mapped
+ * into the Bank0.
+ *
+ * This is why CONFIG_IVMS8 and similar boards must load BR0 with
+ * CONFIG_SYS_BR0_PRELIM in advance.
+ *
+ * [Thanks to Michael Liao for this explanation.
+ * I owe him a free beer. - wd]
+ */
+
+#if defined(CONFIG_SYS_OR0_REMAP)
+ out_be32(&memctl->memc_or0, CONFIG_SYS_OR0_REMAP);
+#endif
+#if defined(CONFIG_SYS_OR1_REMAP)
+ out_be32(&memctl->memc_or1, CONFIG_SYS_OR1_REMAP);
+#endif
+#if defined(CONFIG_SYS_OR5_REMAP)
+ out_be32(&memctl->memc_or5, CONFIG_SYS_OR5_REMAP);
+#endif
+
+ /* now restrict to preliminary range */
+ out_be32(&memctl->memc_br0, CONFIG_SYS_BR0_PRELIM);
+ out_be32(&memctl->memc_or0, CONFIG_SYS_OR0_PRELIM);
+
+#if (defined(CONFIG_SYS_OR1_PRELIM) && defined(CONFIG_SYS_BR1_PRELIM))
+ out_be32(&memctl->memc_or1, CONFIG_SYS_OR1_PRELIM);
+ out_be32(&memctl->memc_br1, CONFIG_SYS_BR1_PRELIM);
+#endif
+
+#if defined(CONFIG_SYS_OR2_PRELIM) && defined(CONFIG_SYS_BR2_PRELIM)
+ out_be32(&memctl->memc_or2, CONFIG_SYS_OR2_PRELIM);
+ out_be32(&memctl->memc_br2, CONFIG_SYS_BR2_PRELIM);
+#endif
+
+#if defined(CONFIG_SYS_OR3_PRELIM) && defined(CONFIG_SYS_BR3_PRELIM)
+ out_be32(&memctl->memc_or3, CONFIG_SYS_OR3_PRELIM);
+ out_be32(&memctl->memc_br3, CONFIG_SYS_BR3_PRELIM);
+#endif
+
+#if defined(CONFIG_SYS_OR4_PRELIM) && defined(CONFIG_SYS_BR4_PRELIM)
+ out_be32(&memctl->memc_or4, CONFIG_SYS_OR4_PRELIM);
+ out_be32(&memctl->memc_br4, CONFIG_SYS_BR4_PRELIM);
+#endif
+
+#if defined(CONFIG_SYS_OR5_PRELIM) && defined(CONFIG_SYS_BR5_PRELIM)
+ out_be32(&memctl->memc_or5, CONFIG_SYS_OR5_PRELIM);
+ out_be32(&memctl->memc_br5, CONFIG_SYS_BR5_PRELIM);
+#endif
+
+#if defined(CONFIG_SYS_OR6_PRELIM) && defined(CONFIG_SYS_BR6_PRELIM)
+ out_be32(&memctl->memc_or6, CONFIG_SYS_OR6_PRELIM);
+ out_be32(&memctl->memc_br6, CONFIG_SYS_BR6_PRELIM);
+#endif
+
+#if defined(CONFIG_SYS_OR7_PRELIM) && defined(CONFIG_SYS_BR7_PRELIM)
+ out_be32(&memctl->memc_or7, CONFIG_SYS_OR7_PRELIM);
+ out_be32(&memctl->memc_br7, CONFIG_SYS_BR7_PRELIM);
+#endif
+
+ /*
+ * Reset CPM
+ */
+ out_be16(&immr->im_cpm.cp_cpcr, CPM_CR_RST | CPM_CR_FLG);
+ /* Spin until command processed */
+ while (in_be16(&immr->im_cpm.cp_cpcr) & CPM_CR_FLG)
+ ;
+}
+
+/*
+ * initialize higher level parts of CPU like timers
+ */
+int cpu_init_r(void)
+{
+ return 0;
+}
diff --git a/roms/u-boot/arch/powerpc/cpu/mpc8xx/fdt.c b/roms/u-boot/arch/powerpc/cpu/mpc8xx/fdt.c
new file mode 100644
index 000000000..b4a26efe3
--- /dev/null
+++ b/roms/u-boot/arch/powerpc/cpu/mpc8xx/fdt.c
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2008 (C) Bryan O'Donoghue
+ *
+ * Code copied & edited from Freescale mpc85xx stuff.
+ */
+
+#include <common.h>
+#include <time.h>
+#include <asm/global_data.h>
+#include <linux/libfdt.h>
+#include <fdt_support.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void ft_cpu_setup(void *blob, struct bd_info *bd)
+{
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+ "timebase-frequency", get_tbclk(), 1);
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+ "bus-frequency", bd->bi_busfreq, 1);
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+ "clock-frequency", bd->bi_intfreq, 1);
+ do_fixup_by_compat_u32(blob, "fsl,pq1-soc", "clock-frequency",
+ bd->bi_intfreq, 1);
+ do_fixup_by_compat_u32(blob, "fsl,cpm-brg", "clock-frequency",
+ gd->arch.brg_clk, 1);
+
+ fdt_fixup_memory(blob, (u64)gd->ram_base, (u64)gd->ram_size);
+}
diff --git a/roms/u-boot/arch/powerpc/cpu/mpc8xx/immap.c b/roms/u-boot/arch/powerpc/cpu/mpc8xx/immap.c
new file mode 100644
index 000000000..40793c26e
--- /dev/null
+++ b/roms/u-boot/arch/powerpc/cpu/mpc8xx/immap.c
@@ -0,0 +1,406 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+/*
+ * MPC8xx Internal Memory Map Functions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/global_data.h>
+
+#include <asm/immap_8xx.h>
+#include <asm/cpm_8xx.h>
+#include <asm/iopin_8xx.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int do_siuinfo(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
+ sysconf8xx_t __iomem *sc = &immap->im_siu_conf;
+
+ printf("SIUMCR= %08x SYPCR = %08x\n",
+ in_be32(&sc->sc_siumcr), in_be32(&sc->sc_sypcr));
+ printf("SWT = %08x\n", in_be32(&sc->sc_swt));
+ printf("SIPEND= %08x SIMASK= %08x\n",
+ in_be32(&sc->sc_sipend), in_be32(&sc->sc_simask));
+ printf("SIEL = %08x SIVEC = %08x\n",
+ in_be32(&sc->sc_siel), in_be32(&sc->sc_sivec));
+ printf("TESR = %08x SDCR = %08x\n",
+ in_be32(&sc->sc_tesr), in_be32(&sc->sc_sdcr));
+ return 0;
+}
+
+static int do_memcinfo(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
+ memctl8xx_t __iomem *memctl = &immap->im_memctl;
+ int nbanks = 8;
+ uint __iomem *p = &memctl->memc_br0;
+ int i;
+
+ for (i = 0; i < nbanks; i++, p += 2)
+ printf("BR%-2d = %08x OR%-2d = %08x\n",
+ i, in_be32(p), i, in_be32(p + 1));
+
+ printf("MAR = %08x", in_be32(&memctl->memc_mar));
+ printf(" MCR = %08x\n", in_be32(&memctl->memc_mcr));
+ printf("MAMR = %08x MBMR = %08x",
+ in_be32(&memctl->memc_mamr), in_be32(&memctl->memc_mbmr));
+ printf("\nMSTAT = %04x\n", in_be16(&memctl->memc_mstat));
+ printf("MPTPR = %04x MDR = %08x\n",
+ in_be16(&memctl->memc_mptpr), in_be32(&memctl->memc_mdr));
+ return 0;
+}
+
+static int do_carinfo(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
+ car8xx_t __iomem *car = &immap->im_clkrst;
+
+ printf("SCCR = %08x\n", in_be32(&car->car_sccr));
+ printf("PLPRCR= %08x\n", in_be32(&car->car_plprcr));
+ printf("RSR = %08x\n", in_be32(&car->car_rsr));
+ return 0;
+}
+
+static int counter;
+
+static void header(void)
+{
+ char *data = "\
+ -------------------------------- --------------------------------\
+ 00000000001111111111222222222233 00000000001111111111222222222233\
+ 01234567890123456789012345678901 01234567890123456789012345678901\
+ -------------------------------- --------------------------------\
+ ";
+ int i;
+
+ if (counter % 2)
+ putc('\n');
+ counter = 0;
+
+ for (i = 0; i < 4; i++, data += 79)
+ printf("%.79s\n", data);
+}
+
+static void binary(char *label, uint value, int nbits)
+{
+ uint mask = 1 << (nbits - 1);
+ int i, second = (counter++ % 2);
+
+ if (second)
+ putc(' ');
+ puts(label);
+ for (i = 32 + 1; i != nbits; i--)
+ putc(' ');
+
+ while (mask != 0) {
+ if (value & mask)
+ putc('1');
+ else
+ putc('0');
+ mask >>= 1;
+ }
+
+ if (second)
+ putc('\n');
+}
+
+#define PA_NBITS 16
+#define PA_NB_ODR 8
+#define PB_NBITS 18
+#define PB_NB_ODR 16
+#define PC_NBITS 12
+#define PD_NBITS 13
+
+static int do_iopinfo(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
+ iop8xx_t __iomem *iop = &immap->im_ioport;
+ ushort __iomem *l, *r;
+ uint __iomem *R;
+
+ counter = 0;
+ header();
+
+ /*
+ * Ports A & B
+ */
+
+ l = &iop->iop_padir;
+ R = &immap->im_cpm.cp_pbdir;
+ binary("PA_DIR", in_be16(l++), PA_NBITS);
+ binary("PB_DIR", in_be32(R++), PB_NBITS);
+ binary("PA_PAR", in_be16(l++), PA_NBITS);
+ binary("PB_PAR", in_be32(R++), PB_NBITS);
+ binary("PA_ODR", in_be16(l++), PA_NB_ODR);
+ binary("PB_ODR", in_be32(R++), PB_NB_ODR);
+ binary("PA_DAT", in_be16(l++), PA_NBITS);
+ binary("PB_DAT", in_be32(R++), PB_NBITS);
+
+ header();
+
+ /*
+ * Ports C & D
+ */
+
+ l = &iop->iop_pcdir;
+ r = &iop->iop_pddir;
+ binary("PC_DIR", in_be16(l++), PC_NBITS);
+ binary("PD_DIR", in_be16(r++), PD_NBITS);
+ binary("PC_PAR", in_be16(l++), PC_NBITS);
+ binary("PD_PAR", in_be16(r++), PD_NBITS);
+ binary("PC_SO ", in_be16(l++), PC_NBITS);
+ binary(" ", 0, 0);
+ r++;
+ binary("PC_DAT", in_be16(l++), PC_NBITS);
+ binary("PD_DAT", in_be16(r++), PD_NBITS);
+ binary("PC_INT", in_be16(l++), PC_NBITS);
+
+ header();
+ return 0;
+}
+
+/*
+ * set the io pins
+ * this needs a clean up for smaller tighter code
+ * use *uint and set the address based on cmd + port
+ */
+static int do_iopset(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ uint rcode = 0;
+ iopin_t iopin;
+ static uint port;
+ static uint pin;
+ static uint value;
+ static enum {
+ DIR,
+ PAR,
+ SOR,
+ ODR,
+ DAT,
+ INT
+ } cmd = DAT;
+
+ if (argc != 5) {
+ puts("iopset PORT PIN CMD VALUE\n");
+ return 1;
+ }
+ port = argv[1][0] - 'A';
+ if (port > 3)
+ port -= 0x20;
+ if (port > 3)
+ rcode = 1;
+ pin = simple_strtol(argv[2], NULL, 10);
+ if (pin > 31)
+ rcode = 1;
+
+
+ switch (argv[3][0]) {
+ case 'd':
+ if (argv[3][1] == 'a')
+ cmd = DAT;
+ else if (argv[3][1] == 'i')
+ cmd = DIR;
+ else
+ rcode = 1;
+ break;
+ case 'p':
+ cmd = PAR;
+ break;
+ case 'o':
+ cmd = ODR;
+ break;
+ case 's':
+ cmd = SOR;
+ break;
+ case 'i':
+ cmd = INT;
+ break;
+ default:
+ printf("iopset: unknown command %s\n", argv[3]);
+ rcode = 1;
+ }
+ if (argv[4][0] == '1')
+ value = 1;
+ else if (argv[4][0] == '0')
+ value = 0;
+ else
+ rcode = 1;
+ if (rcode == 0) {
+ iopin.port = port;
+ iopin.pin = pin;
+ iopin.flag = 0;
+ switch (cmd) {
+ case DIR:
+ if (value)
+ iopin_set_out(&iopin);
+ else
+ iopin_set_in(&iopin);
+ break;
+ case PAR:
+ if (value)
+ iopin_set_ded(&iopin);
+ else
+ iopin_set_gen(&iopin);
+ break;
+ case SOR:
+ if (value)
+ iopin_set_opt2(&iopin);
+ else
+ iopin_set_opt1(&iopin);
+ break;
+ case ODR:
+ if (value)
+ iopin_set_odr(&iopin);
+ else
+ iopin_set_act(&iopin);
+ break;
+ case DAT:
+ if (value)
+ iopin_set_high(&iopin);
+ else
+ iopin_set_low(&iopin);
+ break;
+ case INT:
+ if (value)
+ iopin_set_falledge(&iopin);
+ else
+ iopin_set_anyedge(&iopin);
+ break;
+ }
+ }
+ return rcode;
+}
+
+static void prbrg(int n, uint val)
+{
+ uint extc = (val >> 14) & 3;
+ uint cd = (val & CPM_BRG_CD_MASK) >> 1;
+ uint div16 = (val & CPM_BRG_DIV16) != 0;
+
+ ulong clock = gd->cpu_clk;
+
+ printf("BRG%d:", n);
+
+ if (val & CPM_BRG_RST)
+ puts(" RESET");
+ else
+ puts(" ");
+
+ if (val & CPM_BRG_EN)
+ puts(" ENABLED");
+ else
+ puts(" DISABLED");
+
+ printf(" EXTC=%d", extc);
+
+ if (val & CPM_BRG_ATB)
+ puts(" ATB");
+ else
+ puts(" ");
+
+ printf(" DIVIDER=%4d", cd);
+ if (extc == 0 && cd != 0) {
+ uint baudrate;
+
+ if (div16)
+ baudrate = (clock / 16) / (cd + 1);
+ else
+ baudrate = clock / (cd + 1);
+
+ printf("=%6d bps", baudrate);
+ } else {
+ puts(" ");
+ }
+
+ if (val & CPM_BRG_DIV16)
+ puts(" DIV16");
+ else
+ puts(" ");
+
+ putc('\n');
+}
+
+static int do_brginfo(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
+ cpm8xx_t __iomem *cp = &immap->im_cpm;
+ uint __iomem *p = &cp->cp_brgc1;
+ int i = 1;
+
+ while (i <= 4)
+ prbrg(i++, in_be32(p++));
+
+ return 0;
+}
+
+#ifdef CONFIG_CMD_REGINFO
+void print_reginfo(void)
+{
+ immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
+ sit8xx_t __iomem *timers = &immap->im_sit;
+
+ printf("\nSystem Configuration registers\n"
+ "\tIMMR\t0x%08X\n", get_immr());
+ do_siuinfo(NULL, 0, 0, NULL);
+
+ printf("Memory Controller Registers\n");
+ do_memcinfo(NULL, 0, 0, NULL);
+
+ printf("\nSystem Integration Timers\n");
+ printf("\tTBSCR\t0x%04X\tRTCSC\t0x%04X\n",
+ in_be16(&timers->sit_tbscr), in_be16(&timers->sit_rtcsc));
+ printf("\tPISCR\t0x%04X\n", in_be16(&timers->sit_piscr));
+}
+#endif
+
+/***************************************************/
+
+U_BOOT_CMD(
+ siuinfo, 1, 1, do_siuinfo,
+ "print System Interface Unit (SIU) registers",
+ ""
+);
+
+U_BOOT_CMD(
+ memcinfo, 1, 1, do_memcinfo,
+ "print Memory Controller registers",
+ ""
+);
+
+U_BOOT_CMD(
+ carinfo, 1, 1, do_carinfo,
+ "print Clocks and Reset registers",
+ ""
+);
+
+U_BOOT_CMD(
+ iopinfo, 1, 1, do_iopinfo,
+ "print I/O Port registers",
+ ""
+);
+
+U_BOOT_CMD(
+ iopset, 5, 0, do_iopset,
+ "set I/O Port registers",
+ "PORT PIN CMD VALUE\nPORT: A-D, PIN: 0-31, CMD: [dat|dir|odr|sor], VALUE: 0|1"
+);
+
+U_BOOT_CMD(
+ brginfo, 1, 1, do_brginfo,
+ "print Baud Rate Generator (BRG) registers",
+ ""
+);
diff --git a/roms/u-boot/arch/powerpc/cpu/mpc8xx/interrupts.c b/roms/u-boot/arch/powerpc/cpu/mpc8xx/interrupts.c
new file mode 100644
index 000000000..eef1951f2
--- /dev/null
+++ b/roms/u-boot/arch/powerpc/cpu/mpc8xx/interrupts.c
@@ -0,0 +1,252 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <irq_func.h>
+#include <mpc8xx.h>
+#include <mpc8xx_irq.h>
+#include <time.h>
+#include <asm/cpm_8xx.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/ptrace.h>
+
+/************************************************************************/
+
+/*
+ * CPM interrupt vector functions.
+ */
+struct interrupt_action {
+ interrupt_handler_t *handler;
+ void *arg;
+};
+
+static struct interrupt_action cpm_vecs[CPMVEC_NR];
+static struct interrupt_action irq_vecs[NR_IRQS];
+
+static void cpm_interrupt_init(void);
+static void cpm_interrupt(void *regs);
+
+/************************************************************************/
+
+void interrupt_init_cpu(unsigned *decrementer_count)
+{
+ immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
+
+ *decrementer_count = get_tbclk() / CONFIG_SYS_HZ;
+
+ /* disable all interrupts */
+ out_be32(&immr->im_siu_conf.sc_simask, 0);
+
+ /* Configure CPM interrupts */
+ cpm_interrupt_init();
+}
+
+/************************************************************************/
+
+/*
+ * Handle external interrupts
+ */
+void external_interrupt(struct pt_regs *regs)
+{
+ immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
+ int irq;
+ ulong simask;
+ ulong vec, v_bit;
+
+ /*
+ * read the SIVEC register and shift the bits down
+ * to get the irq number
+ */
+ vec = in_be32(&immr->im_siu_conf.sc_sivec);
+ irq = vec >> 26;
+ v_bit = 0x80000000UL >> irq;
+
+ /*
+ * Read Interrupt Mask Register and Mask Interrupts
+ */
+ simask = in_be32(&immr->im_siu_conf.sc_simask);
+ clrbits_be32(&immr->im_siu_conf.sc_simask, 0xFFFF0000 >> irq);
+
+ if (!(irq & 0x1)) { /* External Interrupt ? */
+ ulong siel;
+
+ /*
+ * Read Interrupt Edge/Level Register
+ */
+ siel = in_be32(&immr->im_siu_conf.sc_siel);
+
+ if (siel & v_bit) { /* edge triggered interrupt ? */
+ /*
+ * Rewrite SIPEND Register to clear interrupt
+ */
+ out_be32(&immr->im_siu_conf.sc_sipend, v_bit);
+ }
+ }
+
+ if (irq_vecs[irq].handler != NULL) {
+ irq_vecs[irq].handler(irq_vecs[irq].arg);
+ } else {
+ printf("\nBogus External Interrupt IRQ %d Vector %ld\n",
+ irq, vec);
+ /* turn off the bogus interrupt to avoid it from now */
+ simask &= ~v_bit;
+ }
+ /*
+ * Re-Enable old Interrupt Mask
+ */
+ out_be32(&immr->im_siu_conf.sc_simask, simask);
+}
+
+/************************************************************************/
+
+/*
+ * CPM interrupt handler
+ */
+static void cpm_interrupt(void *regs)
+{
+ immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
+ uint vec;
+
+ /*
+ * Get the vector by setting the ACK bit
+ * and then reading the register.
+ */
+ out_be16(&immr->im_cpic.cpic_civr, 1);
+ vec = in_be16(&immr->im_cpic.cpic_civr);
+ vec >>= 11;
+
+ if (cpm_vecs[vec].handler != NULL) {
+ (*cpm_vecs[vec].handler) (cpm_vecs[vec].arg);
+ } else {
+ clrbits_be32(&immr->im_cpic.cpic_cimr, 1 << vec);
+ printf("Masking bogus CPM interrupt vector 0x%x\n", vec);
+ }
+ /*
+ * After servicing the interrupt,
+ * we have to remove the status indicator.
+ */
+ setbits_be32(&immr->im_cpic.cpic_cisr, 1 << vec);
+}
+
+/*
+ * The CPM can generate the error interrupt when there is a race
+ * condition between generating and masking interrupts. All we have
+ * to do is ACK it and return. This is a no-op function so we don't
+ * need any special tests in the interrupt handler.
+ */
+static void cpm_error_interrupt(void *dummy)
+{
+}
+
+/************************************************************************/
+/*
+ * Install and free an interrupt handler
+ */
+void irq_install_handler(int vec, interrupt_handler_t *handler, void *arg)
+{
+ immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
+
+ if ((vec & CPMVEC_OFFSET) != 0) {
+ /* CPM interrupt */
+ vec &= 0xffff;
+ if (cpm_vecs[vec].handler != NULL)
+ printf("CPM interrupt 0x%x replacing 0x%x\n",
+ (uint)handler, (uint)cpm_vecs[vec].handler);
+ cpm_vecs[vec].handler = handler;
+ cpm_vecs[vec].arg = arg;
+ setbits_be32(&immr->im_cpic.cpic_cimr, 1 << vec);
+ } else {
+ /* SIU interrupt */
+ if (irq_vecs[vec].handler != NULL)
+ printf("SIU interrupt %d 0x%x replacing 0x%x\n",
+ vec, (uint)handler, (uint)cpm_vecs[vec].handler);
+ irq_vecs[vec].handler = handler;
+ irq_vecs[vec].arg = arg;
+ setbits_be32(&immr->im_siu_conf.sc_simask, 1 << (31 - vec));
+ }
+}
+
+void irq_free_handler(int vec)
+{
+ immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
+
+ if ((vec & CPMVEC_OFFSET) != 0) {
+ /* CPM interrupt */
+ vec &= 0xffff;
+ clrbits_be32(&immr->im_cpic.cpic_cimr, 1 << vec);
+ cpm_vecs[vec].handler = NULL;
+ cpm_vecs[vec].arg = NULL;
+ } else {
+ /* SIU interrupt */
+ clrbits_be32(&immr->im_siu_conf.sc_simask, 1 << (31 - vec));
+ irq_vecs[vec].handler = NULL;
+ irq_vecs[vec].arg = NULL;
+ }
+}
+
+/************************************************************************/
+
+static void cpm_interrupt_init(void)
+{
+ immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
+ uint cicr;
+
+ /*
+ * Initialize the CPM interrupt controller.
+ */
+
+ cicr = CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1 |
+ ((CPM_INTERRUPT / 2) << 13) | CICR_HP_MASK;
+
+ out_be32(&immr->im_cpic.cpic_cicr, cicr);
+ out_be32(&immr->im_cpic.cpic_cimr, 0);
+
+ /*
+ * Install the error handler.
+ */
+ irq_install_handler(CPMVEC_ERROR, cpm_error_interrupt, NULL);
+
+ setbits_be32(&immr->im_cpic.cpic_cicr, CICR_IEN);
+
+ /*
+ * Install the cpm interrupt handler
+ */
+ irq_install_handler(CPM_INTERRUPT, cpm_interrupt, NULL);
+}
+
+/************************************************************************/
+
+/*
+ * timer_interrupt - gets called when the decrementer overflows,
+ * with interrupts disabled.
+ * Trivial implementation - no need to be really accurate.
+ */
+void timer_interrupt_cpu(struct pt_regs *regs)
+{
+ immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
+
+ /* Reset Timer Expired and Timers Interrupt Status */
+ out_be32(&immr->im_clkrstk.cark_plprcrk, KAPWR_KEY);
+ __asm__ ("nop");
+ /*
+ Clear TEXPS (and TMIST on older chips). SPLSS (on older
+ chips) is cleared too.
+
+ Bitwise OR is a read-modify-write operation so ALL bits
+ which are cleared by writing `1' would be cleared by
+ operations like
+
+ immr->im_clkrst.car_plprcr |= PLPRCR_TEXPS;
+
+ The same can be achieved by simple writing of the PLPRCR
+ to itself. If a bit value should be preserved, read the
+ register, ZERO the bit and write, not OR, the result back.
+ */
+ setbits_be32(&immr->im_clkrst.car_plprcr, 0);
+}
+
+/************************************************************************/
diff --git a/roms/u-boot/arch/powerpc/cpu/mpc8xx/speed.c b/roms/u-boot/arch/powerpc/cpu/mpc8xx/speed.c
new file mode 100644
index 000000000..ad3d3f910
--- /dev/null
+++ b/roms/u-boot/arch/powerpc/cpu/mpc8xx/speed.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <clock_legacy.h>
+#include <mpc8xx.h>
+#include <asm/global_data.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * get_clocks() fills in gd->cpu_clock depending on CONFIG_8xx_GCLK_FREQ
+ */
+int get_clocks(void)
+{
+ immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
+ uint sccr = in_be32(&immap->im_clkrst.car_sccr);
+ uint divider = 1 << (((sccr & SCCR_DFBRG11) >> 11) * 2);
+
+ /*
+ * If for some reason measuring the gclk frequency won't
+ * work, we return the hardwired value.
+ * (For example, the cogent CMA286-60 CPU module has no
+ * separate oscillator for PITRTCLK)
+ */
+ gd->cpu_clk = CONFIG_8xx_GCLK_FREQ;
+
+ if ((sccr & SCCR_EBDF11) == 0) {
+ /* No Bus Divider active */
+ gd->bus_clk = gd->cpu_clk;
+ } else {
+ /* The MPC8xx has only one BDF: half clock speed */
+ gd->bus_clk = gd->cpu_clk / 2;
+ }
+
+ gd->arch.brg_clk = gd->cpu_clk / divider;
+
+ return 0;
+}
diff --git a/roms/u-boot/arch/powerpc/cpu/mpc8xx/start.S b/roms/u-boot/arch/powerpc/cpu/mpc8xx/start.S
new file mode 100644
index 000000000..ed735cdee
--- /dev/null
+++ b/roms/u-boot/arch/powerpc/cpu/mpc8xx/start.S
@@ -0,0 +1,542 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ * Copyright (C) 2000,2001,2002 Wolfgang Denk <wd@denx.de>
+ */
+
+/* U-Boot - Startup Code for PowerPC based Embedded Boards
+ *
+ *
+ * The processor starts at 0x00000100 and the code is executed
+ * from flash. The code is organized to be at an other address
+ * in memory, but as long we don't jump around before relocating,
+ * board_init lies at a quite high address and when the cpu has
+ * jumped there, everything is ok.
+ * This works because the cpu gives the FLASH (CS0) the whole
+ * address space at startup, and board_init lies as a echo of
+ * the flash somewhere up there in the memory map.
+ *
+ * board_init will change CS0 to be positioned at the correct
+ * address and (s)dram will be positioned at address 0
+ */
+#include <asm-offsets.h>
+#include <config.h>
+#include <mpc8xx.h>
+#include <version.h>
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+#include <asm/u-boot.h>
+
+/* We don't want the MMU yet.
+*/
+#undef MSR_KERNEL
+#define MSR_KERNEL ( MSR_ME | MSR_RI ) /* Machine Check and Recoverable Interr. */
+
+/*
+ * 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(__bss_end)
+ GOT_ENTRY(__bss_start)
+ END_GOT
+
+/*
+ * r3 - 1st arg to board_init(): IMMP pointer
+ * r4 - 2nd arg to board_init(): boot flag
+ */
+ .text
+ .long 0x27051956 /* U-Boot Magic Number */
+ .globl version_string
+version_string:
+ .ascii U_BOOT_VERSION_STRING, "\0"
+
+ . = EXC_OFF_SYS_RESET
+ .globl _start
+_start:
+ lis r3, CONFIG_SYS_IMMR@h /* position IMMR */
+ mtspr 638, r3
+
+ /* Initialize machine status; enable machine check interrupt */
+ /*----------------------------------------------------------------------*/
+ li r3, MSR_KERNEL /* Set ME, RI flags */
+ mtmsr r3
+ mtspr SRR1, r3 /* Make SRR1 match MSR */
+
+ mfspr r3, ICR /* clear Interrupt Cause Register */
+
+ /* Initialize debug port registers */
+ /*----------------------------------------------------------------------*/
+ xor r0, r0, r0 /* Clear R0 */
+ mtspr LCTRL1, r0 /* Initialize debug port regs */
+ mtspr LCTRL2, r0
+ mtspr COUNTA, r0
+ mtspr COUNTB, r0
+
+ /* Reset the caches */
+ /*----------------------------------------------------------------------*/
+
+ mfspr r3, IC_CST /* Clear error bits */
+ mfspr r3, DC_CST
+
+ lis r3, IDC_UNALL@h /* Unlock all */
+ mtspr IC_CST, r3
+ mtspr DC_CST, r3
+
+ lis r3, IDC_INVALL@h /* Invalidate all */
+ mtspr IC_CST, r3
+ mtspr DC_CST, r3
+
+ lis r3, IDC_DISABLE@h /* Disable data cache */
+ mtspr DC_CST, r3
+
+ lis r3, IDC_ENABLE@h /* Enable instruction cache */
+ mtspr IC_CST, r3
+
+ /* invalidate all tlb's */
+ /*----------------------------------------------------------------------*/
+
+ tlbia
+ isync
+
+ /*
+ * Calculate absolute address in FLASH and jump there
+ *----------------------------------------------------------------------*/
+
+ lis r3, CONFIG_SYS_MONITOR_BASE@h
+ ori r3, r3, CONFIG_SYS_MONITOR_BASE@l
+ addi r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
+ mtlr r3
+ blr
+
+in_flash:
+
+ /* initialize some SPRs that are hard to access from C */
+ /*----------------------------------------------------------------------*/
+
+ /*
+ * Disable serialized ifetch and show cycles
+ * (i.e. set processor to normal mode).
+ * This is also a silicon bug workaround, see errata
+ */
+
+ li r2, 0x0007
+ mtspr ICTRL, r2
+
+ /* Set up debug mode entry */
+
+ lis r2, CONFIG_SYS_DER@h
+ ori r2, r2, CONFIG_SYS_DER@l
+ mtspr DER, r2
+
+ /* set up the stack on top of internal DPRAM */
+ lis r3, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE)@h
+ ori r3, r3, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE)@l
+ stw r0, -4(r3)
+ stw r0, -8(r3)
+ addi r1, r3, -8
+
+ bl board_init_f_alloc_reserve
+ addi r1, r3, -8
+
+ /* Zeroise the CPM dpram */
+ lis r4, CONFIG_SYS_IMMR@h
+ ori r4, r4, (0x2000 - 4)
+ li r0, (0x2000 / 4)
+ mtctr r0
+ li r0, 0
+1: stwu r0, 4(r4)
+ bdnz 1b
+
+ bl board_init_f_init_reserve
+
+ /* let the C-code set up the rest */
+ /* */
+ /* Be careful to keep code relocatable ! */
+ /*----------------------------------------------------------------------*/
+
+ GET_GOT /* initialize GOT access */
+
+ lis r3, CONFIG_SYS_IMMR@h
+ bl cpu_init_f /* run low-level CPU init code (from Flash) */
+
+ bl board_init_f /* run 1st part of board init code (from Flash) */
+
+ /* NOTREACHED - board_init_f() does not return */
+
+
+ .globl _start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+ STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. "Never" generated on the 860. */
+ STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. "Never" generated on the 860. */
+ STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+ STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
+
+/* Alignment exception. */
+ . = 0x600
+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 */
+ . = 0x700
+ProgramCheck:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+ MSR_KERNEL, COPY_EE)
+
+ /* No FPU on MPC8xx. This exception is not supposed to happen.
+ */
+ STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+ /* I guess we could implement decrementer, and may have
+ * to someday for timekeeping.
+ */
+ STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+ STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+ STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+ STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+ STD_EXCEPTION(0xd00, SingleStep, UnknownException)
+
+ STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+ STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+
+ /* On the MPC8xx, this is a software emulation interrupt. It occurs
+ * for all unimplemented and illegal instructions.
+ */
+ STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
+
+ STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
+ STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
+
+ STD_EXCEPTION(0x1500, Reserved5, UnknownException)
+ STD_EXCEPTION(0x1600, Reserved6, UnknownException)
+ STD_EXCEPTION(0x1700, Reserved7, UnknownException)
+ STD_EXCEPTION(0x1800, Reserved8, UnknownException)
+ STD_EXCEPTION(0x1900, Reserved9, UnknownException)
+ STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
+ STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
+
+ STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
+ STD_EXCEPTION(0x1d00, InstructionBreakpoint, DebugException)
+ STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
+ STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
+
+
+ .globl _end_of_vectors
+_end_of_vectors:
+
+
+ . = 0x2000
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+ .globl transfer_to_handler
+transfer_to_handler:
+ stw r22,_NIP(r21)
+ lis r22,MSR_POW@h
+ andc r23,r23,r22
+ stw r23,_MSR(r21)
+ SAVE_GPR(7, r21)
+ SAVE_4GPRS(8, r21)
+ SAVE_8GPRS(12, r21)
+ SAVE_8GPRS(24, r21)
+ mflr r23
+ andi. r24,r23,0x3f00 /* get vector offset */
+ stw r24,TRAP(r21)
+ li r22,0
+ stw r22,RESULT(r21)
+ mtspr SPRG2,r22 /* r1 is now kernel sp */
+ lwz r24,0(r23) /* virtual address of handler */
+ lwz r23,4(r23) /* where to go when done */
+ mtspr SRR0,r24
+ mtspr SRR1,r20
+ mtlr r23
+ SYNC
+ rfi /* jump to handler, enable MMU */
+
+int_return:
+ mfmsr r28 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r28,r28,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r28
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SRR0,r2
+ mtspr SRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfi
+
+/*------------------------------------------------------------------------------*/
+
+/*
+ * void relocate_code(addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+ .globl relocate_code
+relocate_code:
+ mr r1, r3 /* Set new stack pointer */
+ mr r9, r4 /* Save copy of Global Data pointer */
+ mr r10, r5 /* Save copy of Destination Address */
+
+ GET_GOT
+ mr r3, r5 /* Destination Address */
+ lis r4, CONFIG_SYS_MONITOR_BASE@h /* Source Address */
+ ori r4, r4, CONFIG_SYS_MONITOR_BASE@l
+ lwz r5, GOT(__init_end)
+ sub r5, r5, r4
+ li r6, CONFIG_SYS_CACHELINE_SIZE /* Cache Line Size */
+
+ /*
+ * Fix GOT pointer:
+ *
+ * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
+ *
+ * Offset:
+ */
+ sub r15, r10, r4
+
+ /* First our own GOT */
+ add r12, r12, r15
+ /* 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
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+
+ addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+ mtlr r0
+ blr
+
+in_ram:
+
+ /*
+ * Relocation Function, r12 point to got2+0x8000
+ *
+ * Adjust got2 pointers, no need to check for 0, this code
+ * already puts a few entries in the table.
+ */
+ li r0,__got2_entries@sectoff@l
+ la r3,GOT(_GOT2_TABLE_)
+ lwz r11,GOT(_GOT2_TABLE_)
+ mtctr r0
+ sub r11,r3,r11
+ addi r3,r3,-4
+1: lwzu r0,4(r3)
+ cmpwi r0,0
+ beq- 2f
+ add r0,r0,r11
+ stw r0,0(r3)
+2: bdnz 1b
+
+ /*
+ * Now adjust the fixups and the pointers to the fixups
+ * in case we need to move ourselves again.
+ */
+ li r0,__fixup_entries@sectoff@l
+ lwz r3,GOT(_FIXUP_TABLE_)
+ cmpwi r0,0
+ mtctr r0
+ addi r3,r3,-4
+ beq 4f
+3: lwzu r4,4(r3)
+ lwzux r0,r4,r11
+ 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(__bss_end)
+
+ cmplw 0, r3, r4
+ beq 6f
+
+ li r0, 0
+5:
+ stw r0, 0(r3)
+ addi r3, r3, 4
+ cmplw 0, r3, r4
+ bne 5b
+6:
+
+ mr r3, r9 /* Global Data pointer */
+ mr r4, r10 /* Destination Address */
+ bl board_init_r
+
+ /*
+ * Copy exception vector code to low memory
+ *
+ * r3: dest_addr
+ * r7: source address, r8: end address, r9: target address
+ */
+ .globl trap_init
+trap_init:
+ mflr r4 /* save link register */
+ GET_GOT
+ lwz r7, GOT(_start)
+ lwz r8, GOT(_end_of_vectors)
+
+ li r9, 0x100 /* reset vector always at 0x100 */
+
+ cmplw 0, r7, r8
+ bgelr /* return if r7>=r8 - just in case */
+1:
+ lwz r0, 0(r7)
+ stw r0, 0(r9)
+ addi r7, r7, 4
+ addi r9, r9, 4
+ cmplw 0, r7, r8
+ bne 1b
+
+ /*
+ * relocate `hdlr' and `int_return' entries
+ */
+ li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+ li r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 2b
+
+ li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+ li r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 3b
+
+ li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
+ li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 4b
+
+ mtlr r4 /* restore link register */
+ blr
diff --git a/roms/u-boot/arch/powerpc/cpu/mpc8xx/traps.c b/roms/u-boot/arch/powerpc/cpu/mpc8xx/traps.c
new file mode 100644
index 000000000..56794b08a
--- /dev/null
+++ b/roms/u-boot/arch/powerpc/cpu/mpc8xx/traps.c
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * linux/arch/powerpc/kernel/traps.c
+ *
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <common.h>
+#include <asm/ptrace.h>
+#include <command.h>
+#include <asm/processor.h>
+
+/* Returns 0 if exception not found and fixup otherwise. */
+extern unsigned long search_exception_table(unsigned long);
+
+/* THIS NEEDS CHANGING to use the board info structure.
+*/
+#define END_OF_MEM 0x02000000
+
+/*
+ * Trap & Exception support
+ */
+
+static 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");
+ }
+}
+
+
+static void _exception(int signr, struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Exception in kernel pc %lx signal %d", regs->nip, signr);
+}
+
+void MachineCheckException(struct pt_regs *regs)
+{
+ unsigned long fixup = search_exception_table(regs->nip);
+
+ /* Probing PCI using config cycles cause this exception
+ * when a device is not present. Catch it and return to
+ * the PCI exception handler.
+ */
+ if (fixup != 0) {
+ regs->nip = fixup;
+ return;
+ }
+
+ printf("Machine check in kernel mode.\n");
+ printf("Caused by (from msr): ");
+ printf("regs %p ", regs);
+ switch (regs->msr & 0x000F0000) {
+ case (0x80000000 >> 12):
+ printf("Machine check signal - probably due to mm fault\n"
+ "with mmu off\n");
+ break;
+ case (0x80000000 >> 13):
+ printf("Transfer error ack signal\n");
+ break;
+ case (0x80000000 >> 14):
+ printf("Data parity signal\n");
+ break;
+ case (0x80000000 >> 15):
+ printf("Address parity signal\n");
+ break;
+ default:
+ printf("Unknown values in msr\n");
+ }
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("machine check");
+}
+
+void AlignmentException(struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Alignment Exception");
+}
+
+void ProgramCheckException(struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Program Check Exception");
+}
+
+void SoftEmuException(struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Software Emulation Exception");
+}
+
+
+void UnknownException(struct pt_regs *regs)
+{
+ printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+ regs->nip, regs->msr, regs->trap);
+ _exception(0, regs);
+}
+
+void DebugException(struct pt_regs *regs)
+{
+ printf("Debugger trap at @ %lx\n", regs->nip);
+ show_regs(regs);
+}