summaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/Kbuild6
-rw-r--r--arch/powerpc/Kconfig25
-rw-r--r--arch/powerpc/Makefile66
-rw-r--r--arch/powerpc/boards/.gitignore3
-rw-r--r--arch/powerpc/boards/freescale-p1010rdb/Makefile7
-rw-r--r--arch/powerpc/boards/freescale-p1010rdb/config.h58
-rw-r--r--arch/powerpc/boards/freescale-p1010rdb/ddr.c58
-rw-r--r--arch/powerpc/boards/freescale-p1010rdb/defaultenv-freescale-p1010rdb/bin/init2
-rw-r--r--arch/powerpc/boards/freescale-p1010rdb/defaultenv-freescale-p1010rdb/config2
-rw-r--r--arch/powerpc/boards/freescale-p1010rdb/law.c24
-rw-r--r--arch/powerpc/boards/freescale-p1010rdb/p1010rdb.c214
-rw-r--r--arch/powerpc/boards/freescale-p1010rdb/p1010rdb.h14
-rw-r--r--arch/powerpc/boards/freescale-p1010rdb/tlb.c59
-rw-r--r--arch/powerpc/boards/freescale-p1022ds/Makefile8
-rw-r--r--arch/powerpc/boards/freescale-p1022ds/config.h55
-rw-r--r--arch/powerpc/boards/freescale-p1022ds/ddr.c124
-rw-r--r--arch/powerpc/boards/freescale-p1022ds/defaultenv-freescale-p1022ds/bin/init2
-rw-r--r--arch/powerpc/boards/freescale-p1022ds/defaultenv-freescale-p1022ds/config2
-rw-r--r--arch/powerpc/boards/freescale-p1022ds/ics307_clk.c46
-rw-r--r--arch/powerpc/boards/freescale-p1022ds/law.c24
-rw-r--r--arch/powerpc/boards/freescale-p1022ds/p1022ds.c186
-rw-r--r--arch/powerpc/boards/freescale-p1022ds/p1022ds.h14
-rw-r--r--arch/powerpc/boards/freescale-p1022ds/tlb.c59
-rw-r--r--arch/powerpc/boards/freescale-p2020rdb/Makefile6
-rw-r--r--arch/powerpc/boards/freescale-p2020rdb/config.h85
-rw-r--r--arch/powerpc/boards/freescale-p2020rdb/defaultenv-freescale-p2020rdb/bin/init2
-rw-r--r--arch/powerpc/boards/freescale-p2020rdb/defaultenv-freescale-p2020rdb/config2
-rw-r--r--arch/powerpc/boards/freescale-p2020rdb/law.c24
-rw-r--r--arch/powerpc/boards/freescale-p2020rdb/p2020rdb.c266
-rw-r--r--arch/powerpc/boards/freescale-p2020rdb/tlb.c55
-rw-r--r--arch/powerpc/boards/owc-da923rc/Makefile9
-rw-r--r--arch/powerpc/boards/owc-da923rc/config.h53
-rw-r--r--arch/powerpc/boards/owc-da923rc/da923rc.c218
-rw-r--r--arch/powerpc/boards/owc-da923rc/ddr.c169
-rw-r--r--arch/powerpc/boards/owc-da923rc/defaultenv-owc-da923rc/bin/boot9
-rw-r--r--arch/powerpc/boards/owc-da923rc/defaultenv-owc-da923rc/bin/init26
-rw-r--r--arch/powerpc/boards/owc-da923rc/defaultenv-owc-da923rc/config4
-rw-r--r--arch/powerpc/boards/owc-da923rc/law.c24
-rw-r--r--arch/powerpc/boards/owc-da923rc/nand.c94
-rw-r--r--arch/powerpc/boards/owc-da923rc/product_data.c84
-rw-r--r--arch/powerpc/boards/owc-da923rc/product_data.h63
-rw-r--r--arch/powerpc/boards/owc-da923rc/tlb.c69
-rw-r--r--arch/powerpc/boards/pcm030/Makefile4
-rw-r--r--arch/powerpc/boards/pcm030/barebox.lds.S124
-rw-r--r--arch/powerpc/boards/pcm030/config.h30
-rw-r--r--arch/powerpc/boards/pcm030/eeprom.c118
-rw-r--r--arch/powerpc/boards/pcm030/env/init/mtdparts-nor6
-rw-r--r--arch/powerpc/boards/pcm030/env/nv/linux.bootargs.console1
-rw-r--r--arch/powerpc/boards/pcm030/mt46v32m16-75.h39
-rw-r--r--arch/powerpc/boards/pcm030/pcm030.c210
-rw-r--r--arch/powerpc/configs/owc_da923rc_defconfig51
-rw-r--r--arch/powerpc/configs/p1010rdb_defconfig39
-rw-r--r--arch/powerpc/configs/p1022ds_defconfig39
-rw-r--r--arch/powerpc/configs/p2020rdb_defconfig42
-rw-r--r--arch/powerpc/configs/pcm030_defconfig46
-rw-r--r--arch/powerpc/cpu-85xx/Makefile7
-rw-r--r--arch/powerpc/cpu-85xx/fixed_ivor.S54
-rw-r--r--arch/powerpc/cpu-85xx/mmu.c61
-rw-r--r--arch/powerpc/cpu-85xx/resetvec.S4
-rw-r--r--arch/powerpc/cpu-85xx/start.S1314
-rw-r--r--arch/powerpc/cpu-85xx/tlb.c191
-rw-r--r--arch/powerpc/cpu-85xx/traps.c265
-rw-r--r--arch/powerpc/ddr-8xxx/Makefile6
-rw-r--r--arch/powerpc/ddr-8xxx/common_timing_params.h46
-rw-r--r--arch/powerpc/ddr-8xxx/ctrl_regs.c779
-rw-r--r--arch/powerpc/ddr-8xxx/ddr.h112
-rw-r--r--arch/powerpc/ddr-8xxx/ddr2_dimm_params.c296
-rw-r--r--arch/powerpc/ddr-8xxx/ddr3_dimm_params.c193
-rw-r--r--arch/powerpc/ddr-8xxx/ddr_setctrl.c90
-rw-r--r--arch/powerpc/ddr-8xxx/lc_common_dimm_params.c255
-rw-r--r--arch/powerpc/ddr-8xxx/main.c246
-rw-r--r--arch/powerpc/ddr-8xxx/options.c147
-rw-r--r--arch/powerpc/ddr-8xxx/util.c100
-rw-r--r--arch/powerpc/include/asm/atomic.h95
-rw-r--r--arch/powerpc/include/asm/barebox.lds.h5
-rw-r--r--arch/powerpc/include/asm/bitops.h195
-rw-r--r--arch/powerpc/include/asm/bitsperlong.h3
-rw-r--r--arch/powerpc/include/asm/byteorder.h12
-rw-r--r--arch/powerpc/include/asm/cache.h89
-rw-r--r--arch/powerpc/include/asm/common.h35
-rw-r--r--arch/powerpc/include/asm/config.h40
-rw-r--r--arch/powerpc/include/asm/dma.h13
-rw-r--r--arch/powerpc/include/asm/elf.h412
-rw-r--r--arch/powerpc/include/asm/fsl_ddr_dimm_params.h69
-rw-r--r--arch/powerpc/include/asm/fsl_ddr_sdram.h195
-rw-r--r--arch/powerpc/include/asm/fsl_ifc.h267
-rw-r--r--arch/powerpc/include/asm/fsl_law.h92
-rw-r--r--arch/powerpc/include/asm/fsl_lbc.h71
-rw-r--r--arch/powerpc/include/asm/io.h257
-rw-r--r--arch/powerpc/include/asm/linkage.h5
-rw-r--r--arch/powerpc/include/asm/mmu.h571
-rw-r--r--arch/powerpc/include/asm/module.h18
-rw-r--r--arch/powerpc/include/asm/pci_io.h45
-rw-r--r--arch/powerpc/include/asm/posix_types.h3
-rw-r--r--arch/powerpc/include/asm/ppc_asm.tmpl207
-rw-r--r--arch/powerpc/include/asm/ppc_defs.h84
-rw-r--r--arch/powerpc/include/asm/processor.h1153
-rw-r--r--arch/powerpc/include/asm/ptrace.h108
-rw-r--r--arch/powerpc/include/asm/sections.h3
-rw-r--r--arch/powerpc/include/asm/setjmp.h21
-rw-r--r--arch/powerpc/include/asm/sigcontext.h17
-rw-r--r--arch/powerpc/include/asm/signal.h156
-rw-r--r--arch/powerpc/include/asm/status_led.h79
-rw-r--r--arch/powerpc/include/asm/string.h29
-rw-r--r--arch/powerpc/include/asm/swab.h90
-rw-r--r--arch/powerpc/include/asm/types.h16
-rw-r--r--arch/powerpc/include/asm/unaligned.h18
-rw-r--r--arch/powerpc/include/asm/word-at-a-time.h162
-rw-r--r--arch/powerpc/lib/Makefile14
-rw-r--r--arch/powerpc/lib/asm-offsets.c21
-rw-r--r--arch/powerpc/lib/bat_rw.c126
-rw-r--r--arch/powerpc/lib/board.c65
-rw-r--r--arch/powerpc/lib/crtsavres.S232
-rw-r--r--arch/powerpc/lib/extable.c76
-rw-r--r--arch/powerpc/lib/kgdb.c325
-rw-r--r--arch/powerpc/lib/misc.S42
-rw-r--r--arch/powerpc/lib/module.c294
-rw-r--r--arch/powerpc/lib/ppclinux.c119
-rw-r--r--arch/powerpc/lib/ppcstring.S216
-rw-r--r--arch/powerpc/lib/reloc.S40
-rw-r--r--arch/powerpc/lib/setjmp.S86
-rw-r--r--arch/powerpc/lib/ticks.S35
-rw-r--r--arch/powerpc/mach-mpc5xxx/Kconfig39
-rw-r--r--arch/powerpc/mach-mpc5xxx/Makefile11
-rw-r--r--arch/powerpc/mach-mpc5xxx/cpu.c234
-rw-r--r--arch/powerpc/mach-mpc5xxx/cpu_init.c49
-rw-r--r--arch/powerpc/mach-mpc5xxx/firmware_sc_task_bestcomm.impl.S363
-rw-r--r--arch/powerpc/mach-mpc5xxx/include/mach/clock.h16
-rw-r--r--arch/powerpc/mach-mpc5xxx/include/mach/mpc5xxx.h790
-rw-r--r--arch/powerpc/mach-mpc5xxx/include/mach/sdma.h90
-rw-r--r--arch/powerpc/mach-mpc5xxx/loadtask.c79
-rw-r--r--arch/powerpc/mach-mpc5xxx/reginfo.c63
-rw-r--r--arch/powerpc/mach-mpc5xxx/speed.c101
-rw-r--r--arch/powerpc/mach-mpc5xxx/start.S736
-rw-r--r--arch/powerpc/mach-mpc5xxx/time.c45
-rw-r--r--arch/powerpc/mach-mpc5xxx/traps.c196
-rw-r--r--arch/powerpc/mach-mpc85xx/.gitignore3
-rw-r--r--arch/powerpc/mach-mpc85xx/Kconfig106
-rw-r--r--arch/powerpc/mach-mpc85xx/Makefile14
-rw-r--r--arch/powerpc/mach-mpc85xx/barebox.lds.S154
-rw-r--r--arch/powerpc/mach-mpc85xx/cpu.c103
-rw-r--r--arch/powerpc/mach-mpc85xx/cpu_init.c218
-rw-r--r--arch/powerpc/mach-mpc85xx/cpuid.c72
-rw-r--r--arch/powerpc/mach-mpc85xx/eth-devices.c54
-rw-r--r--arch/powerpc/mach-mpc85xx/fdt.c154
-rw-r--r--arch/powerpc/mach-mpc85xx/fsl_gpio.c31
-rw-r--r--arch/powerpc/mach-mpc85xx/fsl_i2c.c254
-rw-r--r--arch/powerpc/mach-mpc85xx/fsl_law.c154
-rw-r--r--arch/powerpc/mach-mpc85xx/include/mach/clock.h20
-rw-r--r--arch/powerpc/mach-mpc85xx/include/mach/config_mpc85xx.h64
-rw-r--r--arch/powerpc/mach-mpc85xx/include/mach/early_udelay.h33
-rw-r--r--arch/powerpc/mach-mpc85xx/include/mach/ffs64.h20
-rw-r--r--arch/powerpc/mach-mpc85xx/include/mach/fsl_i2c.h17
-rw-r--r--arch/powerpc/mach-mpc85xx/include/mach/gianfar.h30
-rw-r--r--arch/powerpc/mach-mpc85xx/include/mach/gpio.h15
-rw-r--r--arch/powerpc/mach-mpc85xx/include/mach/immap_85xx.h199
-rw-r--r--arch/powerpc/mach-mpc85xx/include/mach/mmu.h52
-rw-r--r--arch/powerpc/mach-mpc85xx/include/mach/mpc85xx.h25
-rw-r--r--arch/powerpc/mach-mpc85xx/speed.c131
-rw-r--r--arch/powerpc/mach-mpc85xx/time.c45
160 files changed, 18341 insertions, 0 deletions
diff --git a/arch/powerpc/Kbuild b/arch/powerpc/Kbuild
new file mode 100644
index 0000000000..e9f7b32848
--- /dev/null
+++ b/arch/powerpc/Kbuild
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-$(CONFIG_ARCH_MPC85XX) += cpu-85xx/
+obj-y += lib/
+obj-$(CONFIG_FSL_DDR2) += ddr-8xxx/
+obj-$(CONFIG_FSL_DDR3) += ddr-8xxx/
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
new file mode 100644
index 0000000000..ba875767b2
--- /dev/null
+++ b/arch/powerpc/Kconfig
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config PPC
+ bool
+ select HAVE_CONFIGURABLE_TEXT_BASE
+ select HAS_KALLSYMS
+ select HAS_MODULES
+ select HAS_CACHE
+ select GENERIC_FIND_NEXT_BIT
+ select OFTREE
+ select ARCH_HAS_SJLJ
+ default y
+
+choice
+ prompt "Processor type"
+
+config ARCH_MPC5XXX
+ bool "Freescale MPC5xxx"
+
+config ARCH_MPC85XX
+ bool "Freescale MPC85xx"
+endchoice
+
+source "arch/powerpc/mach-mpc5xxx/Kconfig"
+source "arch/powerpc/mach-mpc85xx/Kconfig"
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
new file mode 100644
index 0000000000..ebd8fe60d3
--- /dev/null
+++ b/arch/powerpc/Makefile
@@ -0,0 +1,66 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+KBUILD_DEFCONFIG := p2020rdb_defconfig
+
+KBUILD_CPPFLAGS += -ffixed-r14 -m32 \
+ -meabi -D __PPC__ \
+ -fno-strict-aliasing
+
+KBUILD_CPPFLAGS += $(call cc-option,-mno-spe)
+KBUILD_CPPFLAGS += $(call cc-option,-mspe=no)
+
+ifdef CONFIG_RELOCATABLE
+KBUILD_CPPFLAGS += -fPIC -mrelocatable
+endif
+
+ifdef CONFIG_MPC85xx
+KBUILD_CPPFLAGS += -Wa,-me500x2 -msoft-float -mno-string
+endif
+
+board-$(CONFIG_MACH_PHYCORE_MPC5200B_TINY) := pcm030
+board-$(CONFIG_P1010RDB) := freescale-p1010rdb
+board-$(CONFIG_P2020RDB) := freescale-p2020rdb
+board-$(CONFIG_P1022DS) := freescale-p1022ds
+board-$(CONFIG_DA923RC) := owc-da923rc
+
+machine-$(CONFIG_ARCH_MPC5200) := mpc5xxx
+machine-$(CONFIG_ARCH_MPC85XX) := mpc85xx
+
+TEXT_BASE = $(CONFIG_TEXT_BASE)
+
+KBUILD_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE)
+
+# Add cleanup flags
+ifndef CONFIG_MODULES
+KBUILD_CPPFLAGS += -fdata-sections -ffunction-sections
+LDFLAGS_barebox += --gc-sections
+endif
+
+machdirs := $(patsubst %,arch/powerpc/mach-%/,$(machine-y))
+
+KBUILD_CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs))
+
+archprepare: maketools
+
+PHONY += maketools
+
+
+ifneq ($(board-y),)
+BOARD := arch/powerpc/boards/$(board-y)/
+else
+BOARD :=
+endif
+
+ifneq ($(machine-y),)
+MACH := arch/powerpc/mach-$(machine-y)/
+else
+MACH :=
+endif
+
+common-y += $(BOARD) $(MACH) arch/powerpc/
+
+ifdef CONFIG_MPC85xx
+lds-y += $(MACH)/barebox.lds
+else
+lds-y += $(BOARD)/barebox.lds
+endif
diff --git a/arch/powerpc/boards/.gitignore b/arch/powerpc/boards/.gitignore
new file mode 100644
index 0000000000..03987a7009
--- /dev/null
+++ b/arch/powerpc/boards/.gitignore
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+barebox.lds
diff --git a/arch/powerpc/boards/freescale-p1010rdb/Makefile b/arch/powerpc/boards/freescale-p1010rdb/Makefile
new file mode 100644
index 0000000000..e54ee8ee43
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p1010rdb/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-y += p1010rdb.o
+obj-y += law.o
+obj-y += tlb.o
+obj-y += ddr.o
+bbenv-$(CONFIG_DEFAULT_ENVIRONMENT_GENERIC) += defaultenv-freescale-p1010rdb
diff --git a/arch/powerpc/boards/freescale-p1010rdb/config.h b/arch/powerpc/boards/freescale-p1010rdb/config.h
new file mode 100644
index 0000000000..4f67183507
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p1010rdb/config.h
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define CFG_SYS_CLK_FREQ 66666666
+#define CFG_DDR_CLK_FREQ 66666666
+
+#define CFG_CHIP_SELECTS_PER_CTRL 1
+
+/*
+ * Memory map
+ *
+ * 0x0000_0000 0x3fff_ffff DDR 1G cacheable
+ *
+ * Localbus non-cacheable
+ * 0xee0_0000 0xefff_ffff FLASH 32M non-cacheable
+ * 0xffb0_0000 0xffb0_0fff PIXIS 4K Cacheable
+ * 0xffd0_0000 0xffd0_3fff L1 for stack 16K Cacheable TLB0
+ */
+#define CFG_SDRAM_BASE 0x00000000
+
+#define CFG_CCSRBAR_DEFAULT 0xff700000
+#define CFG_CCSRBAR 0xffe00000
+#define CFG_CCSRBAR_PHYS CFG_CCSRBAR
+#define CFG_IMMR CFG_CCSRBAR
+
+#define CFG_INIT_RAM_ADDR 0xffd00000
+#define CFG_INIT_RAM_SIZE 0x00004000
+#define CFG_INIT_BI_SIZE 0x00000100
+#define CFG_INIT_SP_OFFSET (CFG_INIT_RAM_SIZE - CFG_INIT_BI_SIZE)
+
+#define CFG_BOOT_BLOCK 0xe0000000
+#define CFG_BOOT_BLOCK_PHYS CFG_BOOT_BLOCK
+#define CFG_FLASH_BASE 0xee000000
+#define CFG_FLASH_BASE_PHYS CFG_FLASH_BASE
+#define CFG_CPLD_BASE 0xffb00000
+#define CFG_CPLD_BASE_PHYS CFG_CPLD_BASE
+
+#define CFG_IFC_CSPR0 (CSPR_PHYS_ADDR(CFG_FLASH_BASE_PHYS) | \
+ CSPR_PORT_SIZE_16 | CSPR_MSEL_NOR | \
+ CSPR_V)
+#define CFG_IFC_CSOR0 CSOR_NOR_ADM_SHIFT(7)
+#define CFG_IFC_AMASK0 IFC_AMASK(32*1024*1024)
+
+#endif /* __CONFIG_H */
diff --git a/arch/powerpc/boards/freescale-p1010rdb/ddr.c b/arch/powerpc/boards/freescale-p1010rdb/ddr.c
new file mode 100644
index 0000000000..14fa426726
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p1010rdb/ddr.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ * Authors: Srikanth Srinivasan <srikanth.srinivasan@freescale.com>
+ * Timur Tabi <timur@freescale.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <init.h>
+#include <mach/fsl_i2c.h>
+#include <mach/immap_85xx.h>
+#include <mach/clock.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/fsl_lbc.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/fsl_ddr_dimm_params.h>
+#include "p1010rdb.h"
+
+static const u8 spd_addr = 0x52;
+
+void fsl_ddr_board_info(struct ddr_board_info_s *info)
+{
+ p1010rdb_early_init();
+
+ info->fsl_ddr_ver = 0;
+ info->ddr_base = IOMEM(MPC85xx_DDR_ADDR);
+ /* Actual number of chip select used */
+ info->cs_per_ctrl = CFG_CHIP_SELECTS_PER_CTRL;
+ info->dimm_slots_per_ctrl = 1;
+ info->i2c_bus = 1;
+ info->i2c_slave = 0x7f;
+ info->i2c_speed = 400000;
+ info->i2c_base = IOMEM(I2C2_BASE_ADDR);
+ info->spd_i2c_addr = &spd_addr;
+}
+
+void fsl_ddr_board_options(struct memctl_options_s *popts,
+ struct dimm_params_s *pdimm)
+{
+ popts->cs_local_opts[0].odt_rd_cfg = FSL_DDR_ODT_NEVER;
+ popts->cs_local_opts[0].odt_wr_cfg = FSL_DDR_ODT_CS;
+ popts->cs_local_opts[0].odt_rtt_norm = DDR3_RTT_40_OHM;
+ popts->cs_local_opts[0].odt_rtt_wr = DDR3_RTT_OFF;
+
+ popts->clk_adjust = 6;
+ popts->cpo_override = 0x1f;
+ popts->write_data_delay = 2;
+ /* Write leveling override */
+ popts->wrlvl_en = 1;
+ popts->wrlvl_override = 1;
+ popts->wrlvl_sample = 0xf;
+ popts->wrlvl_start = 0x8;
+ popts->trwt_override = 1;
+ popts->trwt = 0;
+ popts->dll_rst_dis = 1;
+}
diff --git a/arch/powerpc/boards/freescale-p1010rdb/defaultenv-freescale-p1010rdb/bin/init b/arch/powerpc/boards/freescale-p1010rdb/defaultenv-freescale-p1010rdb/bin/init
new file mode 100644
index 0000000000..c0e04c1f2d
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p1010rdb/defaultenv-freescale-p1010rdb/bin/init
@@ -0,0 +1,2 @@
+#!/bin/sh
+source /env/config
diff --git a/arch/powerpc/boards/freescale-p1010rdb/defaultenv-freescale-p1010rdb/config b/arch/powerpc/boards/freescale-p1010rdb/defaultenv-freescale-p1010rdb/config
new file mode 100644
index 0000000000..bffd86882e
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p1010rdb/defaultenv-freescale-p1010rdb/config
@@ -0,0 +1,2 @@
+#!/bin/sh
+export bootargs="root=/dev/nfs rw ip=bootp console=ttyS0,115200" \ No newline at end of file
diff --git a/arch/powerpc/boards/freescale-p1010rdb/law.c b/arch/powerpc/boards/freescale-p1010rdb/law.c
new file mode 100644
index 0000000000..6edfbc2fb8
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p1010rdb/law.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2009-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 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.
+ *
+ */
+
+#include <common.h>
+#include <asm/fsl_law.h>
+
+struct law_entry law_table[] = {
+ FSL_SET_LAW(CFG_BOOT_BLOCK_PHYS, LAW_SIZE_256M, LAW_TRGT_IF_IFC),
+ FSL_SET_LAW(CFG_CPLD_BASE_PHYS, LAW_SIZE_128K, LAW_TRGT_IF_IFC),
+};
+
+int num_law_entries = ARRAY_SIZE(law_table);
diff --git a/arch/powerpc/boards/freescale-p1010rdb/p1010rdb.c b/arch/powerpc/boards/freescale-p1010rdb/p1010rdb.c
new file mode 100644
index 0000000000..e769933412
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p1010rdb/p1010rdb.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2014 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.
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <platform_data/serial-ns16550.h>
+#include <net.h>
+#include <types.h>
+#include <i2c/i2c.h>
+#include <gpio.h>
+#include <envfs.h>
+#include <memory.h>
+#include <asm/cache.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/fsl_law.h>
+#include <asm/fsl_ifc.h>
+#include <mach/mpc85xx.h>
+#include <mach/mmu.h>
+#include <mach/immap_85xx.h>
+#include <mach/gianfar.h>
+#include <mach/clock.h>
+#include <mach/early_udelay.h>
+#include <of.h>
+
+#include "p1010rdb.h"
+
+static struct gfar_info_struct gfar_info[] = {
+ {
+ .phyaddr = 1,
+ .tbiana = 0,
+ .tbicr = 0,
+ .mdiobus_tbi = 0,
+ },
+ {
+ .phyaddr = 0,
+ .tbiana = 0x1a0,
+ .tbicr = 0x9140,
+ .mdiobus_tbi = 1,
+ },
+ {
+ .phyaddr = 2,
+ .tbiana = 0x1a0,
+ .tbicr = 0x9140,
+ .mdiobus_tbi = 2,
+ },
+};
+
+struct i2c_platform_data i2cplat[] = {
+ { .bitrate = 400000, },
+ { .bitrate = 400000, },
+};
+
+void p1010rdb_early_init(void)
+{
+ void __iomem *ifc = IFC_BASE_ADDR;
+ void __iomem *gur = IOMEM(MPC85xx_GUTS_ADDR);
+
+ /* Clock configuration to access CPLD using IFC(GPCM) */
+ setbits_be32(ifc + FSL_IFC_GCR_OFFSET,
+ 1 << IFC_GCR_TBCTL_TRN_TIME_SHIFT);
+
+ /* Erratum A003549 */
+ setbits_be32(gur + MPC85xx_GUTS_PMUXCR_OFFSET,
+ MPC85xx_PMUXCR_LCLK_IFC_CS3);
+
+ /* Update CS0 timings to access boot flash */
+ set_ifc_ftim(IFC_CS0, IFC_FTIM0, FTIM0_NOR_TACSE(0x4) |
+ FTIM0_NOR_TEADC(0x5) | FTIM0_NOR_TEAHC(0x5));
+ set_ifc_ftim(IFC_CS0, IFC_FTIM1, FTIM1_NOR_TACO(0x1e) |
+ FTIM1_NOR_TRAD_NOR(0x0f));
+ set_ifc_ftim(IFC_CS0, IFC_FTIM2, FTIM2_NOR_TCS(0x4) |
+ FTIM2_NOR_TCH(0x4) | FTIM2_NOR_TWP(0x1c));
+ set_ifc_ftim(IFC_CS0, IFC_FTIM3, 0);
+
+ /* Map the CPLD */
+ set_ifc_cspr(IFC_CS3, CSPR_PHYS_ADDR(CFG_CPLD_BASE_PHYS) |
+ CSPR_PORT_SIZE_8 | CSPR_MSEL_GPCM | CSPR_V);
+ set_ifc_csor(IFC_CS3, 0);
+ set_ifc_amask(IFC_CS3, IFC_AMASK(64*1024));
+ set_ifc_ftim(IFC_CS3, IFC_FTIM0, FTIM0_GPCM_TACSE(0xe) |
+ FTIM0_GPCM_TEADC(0x0e) | FTIM0_GPCM_TEAHC(0x0e));
+ set_ifc_ftim(IFC_CS3, IFC_FTIM1, FTIM1_GPCM_TACO(0x1e) |
+ FTIM1_GPCM_TRAD(0x0f));
+ set_ifc_ftim(IFC_CS3, IFC_FTIM2, FTIM2_GPCM_TCS(0xe) |
+ FTIM2_GPCM_TCH(0) | FTIM2_GPCM_TWP(0x1f));
+ set_ifc_ftim(IFC_CS3, IFC_FTIM3, 0);
+
+ /* PCIe reset through GPIO 4 */
+ gpio_direction_output(4, 1);
+}
+
+static void board_eth_init(void)
+{
+ fsl_eth_init(1, &gfar_info[0]);
+ fsl_eth_init(2, &gfar_info[1]);
+ fsl_eth_init(3, &gfar_info[2]);
+}
+
+static int p1010rdb_devices_init(void)
+{
+ add_cfi_flash_device(DEVICE_ID_DYNAMIC, CFG_FLASH_BASE, 32 << 20, 0);
+ devfs_add_partition("nor0", 0x1f80000, 0x80000, DEVFS_PARTITION_FIXED,
+ "self0");
+ devfs_add_partition("nor0", 0x1f60000, 0x10000, DEVFS_PARTITION_FIXED,
+ "env0");
+ add_generic_device("i2c-fsl", 0, NULL, I2C1_BASE_ADDR, 0x100,
+ IORESOURCE_MEM, &i2cplat[0]);
+ add_generic_device("i2c-fsl", 1, NULL, I2C2_BASE_ADDR, 0x100,
+ IORESOURCE_MEM, &i2cplat[1]);
+ board_eth_init();
+
+ if (IS_ENABLED(CONFIG_DEFAULT_ENVIRONMENT_GENERIC))
+ defaultenv_append_directory(defaultenv_freescale_p1010rdb);
+
+ return 0;
+}
+
+device_initcall(p1010rdb_devices_init);
+
+static struct NS16550_plat serial_plat = {
+ .clock = 0,
+ .shift = 0,
+};
+
+static int p1010rdb_console_init(void)
+{
+ barebox_set_model("Freescale P1010RDB");
+ barebox_set_hostname("p1010rdb");
+
+ serial_plat.clock = fsl_get_bus_freq(0);
+ add_ns16550_device(1, CFG_IMMR + 0x4500, 16,
+ IORESOURCE_MEM | IORESOURCE_MEM_8BIT, &serial_plat);
+ return 0;
+}
+
+console_initcall(p1010rdb_console_init);
+
+static int p1010rdb_mem_init(void)
+{
+ barebox_add_memory_bank("ram0", 0x0, fsl_get_effective_memsize());
+ return 0;
+}
+
+mem_initcall(p1010rdb_mem_init);
+
+static int p1010rdb_board_init_r(void)
+{
+ const uint32_t flashbase = CFG_BOOT_BLOCK;
+ const u8 flash_esel = e500_find_tlb_idx((void *)flashbase, 1);
+
+ /* Flush d-cache and invalidate i-cache of any FLASH data */
+ flush_dcache();
+ invalidate_icache();
+
+ /* invalidate existing TLB entry for flash */
+ e500_disable_tlb(flash_esel);
+
+ /*
+ * Remap Boot flash region to caching-inhibited
+ * so that flash can be erased properly.
+ */
+ e500_set_tlb(1, flashbase, CFG_BOOT_BLOCK_PHYS,
+ MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
+ 0, flash_esel, BOOKE_PAGESZ_256M, 1);
+
+ fsl_l2_cache_init();
+
+ return 0;
+}
+
+core_initcall(p1010rdb_board_init_r);
+
+static int fdt_board_setup(struct device_node *blob, void *unused)
+{
+ struct device_node *node;
+
+ node = of_find_compatible_node(blob, NULL, "fsl,esdhc");
+ if (node)
+ of_delete_node(node);
+
+ node = of_find_compatible_node(blob, NULL, "fsl,starlite-tdm");
+ if (node)
+ of_delete_node(node);
+
+ node = of_find_compatible_node(blob, NULL, "fsl,p1010-flexcan");
+ if (node)
+ of_delete_node(node);
+
+ node = of_find_compatible_node(blob, NULL, "fsl,p1010-flexcan");
+ if (node)
+ of_delete_node(node);
+
+ return 0;
+}
+
+static int of_register_p1010rdb_fixup(void)
+{
+ return of_register_fixup(fdt_board_setup, NULL);
+}
+late_initcall(of_register_p1010rdb_fixup);
diff --git a/arch/powerpc/boards/freescale-p1010rdb/p1010rdb.h b/arch/powerpc/boards/freescale-p1010rdb/p1010rdb.h
new file mode 100644
index 0000000000..f325ff48fd
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p1010rdb/p1010rdb.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2014 GE Intelligent Platforms, 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.
+ */
+void p1010rdb_early_init(void);
diff --git a/arch/powerpc/boards/freescale-p1010rdb/tlb.c b/arch/powerpc/boards/freescale-p1010rdb/tlb.c
new file mode 100644
index 0000000000..23ef0f2ade
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p1010rdb/tlb.c
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ *
+ */
+
+#include <common.h>
+#include <mach/mmu.h>
+
+struct fsl_e_tlb_entry tlb_table[] = {
+ /* TLB 0 - for temp stack in cache */
+ FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR, CFG_INIT_RAM_ADDR,
+ MAS3_SX | MAS3_SW | MAS3_SR, 0,
+ 0, 0, BOOKE_PAGESZ_4K, 0),
+ FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR + (4 * 1024),
+ CFG_INIT_RAM_ADDR + (4 * 1024),
+ MAS3_SX | MAS3_SW | MAS3_SR, 0,
+ 0, 0, BOOKE_PAGESZ_4K, 0),
+ FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR + (8 * 1024),
+ CFG_INIT_RAM_ADDR + (8 * 1024),
+ MAS3_SX | MAS3_SW | MAS3_SR, 0,
+ 0, 0, BOOKE_PAGESZ_4K, 0),
+ FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR + (12 * 1024),
+ CFG_INIT_RAM_ADDR + (12 * 1024),
+ MAS3_SX | MAS3_SW | MAS3_SR, 0,
+ 0, 0, BOOKE_PAGESZ_4K, 0),
+
+ /* TLB 1 */
+ /* *I*** - Covers boot page */
+ FSL_SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000,
+ MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
+ 0, 0, BOOKE_PAGESZ_4K, 1),
+
+ /* *I*G* - CCSRBAR */
+ FSL_SET_TLB_ENTRY(1, CFG_CCSRBAR, CFG_CCSRBAR_PHYS,
+ MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
+ 0, 1, BOOKE_PAGESZ_1M, 1),
+
+ /* W**G* - Flash, localbus */
+ /* This will be changed to *I*G* after relocation to RAM. */
+ FSL_SET_TLB_ENTRY(1, CFG_BOOT_BLOCK, CFG_BOOT_BLOCK_PHYS,
+ MAS3_SX | MAS3_SR, MAS2_M | MAS2_W | MAS2_G,
+ 0, 2, BOOKE_PAGESZ_256M, 1),
+
+ FSL_SET_TLB_ENTRY(1, CFG_CPLD_BASE, CFG_CPLD_BASE_PHYS,
+ MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
+ 0, 6, BOOKE_PAGESZ_128K, 1),
+};
+
+int num_tlb_entries = ARRAY_SIZE(tlb_table);
diff --git a/arch/powerpc/boards/freescale-p1022ds/Makefile b/arch/powerpc/boards/freescale-p1022ds/Makefile
new file mode 100644
index 0000000000..1d969d48eb
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p1022ds/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-y += p1022ds.o
+obj-y += law.o
+obj-y += tlb.o
+obj-y += ddr.o
+obj-y += ics307_clk.o
+bbenv-$(CONFIG_DEFAULT_ENVIRONMENT_GENERIC) += defaultenv-freescale-p1022ds
diff --git a/arch/powerpc/boards/freescale-p1022ds/config.h b/arch/powerpc/boards/freescale-p1022ds/config.h
new file mode 100644
index 0000000000..666b9ff987
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p1022ds/config.h
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#ifndef __ASSEMBLY__
+extern unsigned long ics307_clk_freq(unsigned int reg);
+#endif
+#define CFG_SYS_CLK_FREQ ics307_clk_freq(25)
+#define CFG_DDR_CLK_FREQ ics307_clk_freq(28)
+
+#define CFG_CHIP_SELECTS_PER_CTRL 2
+
+/*
+ * Memory map
+ *
+ * 0x0000_0000 0x7fff_ffff DDR 2G cacheable
+ *
+ * Localbus non-cacheable
+ * 0xe800_0000 0xefff_ffff FLASH 128M non-cacheable
+ * 0xffdf_0000 0xffdf_0fff PIXIS 4K Cacheable
+ * 0xffd0_0000 0xffd0_3fff L1 for stack 16K Cacheable TLB0
+ */
+#define CFG_SDRAM_BASE 0x00000000
+
+#define CFG_CCSRBAR_DEFAULT 0xff700000
+#define CFG_CCSRBAR 0xffe00000
+#define CFG_CCSRBAR_PHYS CFG_CCSRBAR
+#define CFG_IMMR CFG_CCSRBAR
+
+#define CFG_INIT_RAM_ADDR 0xffd00000
+#define CFG_INIT_RAM_SIZE 0x00004000
+#define CFG_INIT_BI_SIZE 0x00000100
+#define CFG_INIT_SP_OFFSET (CFG_INIT_RAM_SIZE - CFG_INIT_BI_SIZE)
+
+#define CFG_BOOT_BLOCK 0xe0000000
+#define CFG_BOOT_BLOCK_PHYS CFG_BOOT_BLOCK
+#define CFG_FLASH_BASE 0xe8000000
+#define CFG_FLASH_BASE_PHYS CFG_FLASH_BASE
+#define CFG_PIXIS_BASE 0xffdf0000
+#define CFG_PIXIS_BASE_PHYS CFG_PIXIS_BASE
+
+#endif /* __CONFIG_H */
diff --git a/arch/powerpc/boards/freescale-p1022ds/ddr.c b/arch/powerpc/boards/freescale-p1022ds/ddr.c
new file mode 100644
index 0000000000..3a8298f928
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p1022ds/ddr.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ * Authors: Srikanth Srinivasan <srikanth.srinivasan@freescale.com>
+ * Timur Tabi <timur@freescale.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <init.h>
+#include <mach/fsl_i2c.h>
+#include <mach/immap_85xx.h>
+#include <mach/clock.h>
+#include <asm/io.h>
+#include <asm/fsl_lbc.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/fsl_ddr_dimm_params.h>
+#include "p1022ds.h"
+
+static const u8 spd_addr = 0x51;
+
+void fsl_ddr_board_info(struct ddr_board_info_s *info)
+{
+ /*
+ * Early mapping is needed to access the clock
+ * parameters in the FPGA.
+ */
+ p1022ds_lbc_early_init();
+
+ info->fsl_ddr_ver = 0;
+ info->ddr_base = IOMEM(MPC85xx_DDR_ADDR);
+ /* Actual number of chip select used */
+ info->cs_per_ctrl = CFG_CHIP_SELECTS_PER_CTRL;
+ info->dimm_slots_per_ctrl = 1;
+ info->i2c_bus = 1;
+ info->i2c_slave = 0x7f;
+ info->i2c_speed = 400000;
+ info->i2c_base = IOMEM(I2C2_BASE_ADDR);
+ info->spd_i2c_addr = &spd_addr;
+}
+
+struct board_specific_parameters {
+ u32 n_ranks;
+ u32 datarate_mhz_high;
+ u32 clk_adjust; /* Range: 0-8 */
+ u32 cpo; /* Range: 2-31 */
+ u32 write_data_delay; /* Range: 0-6 */
+ u32 force_2t;
+};
+
+/*
+ * This table contains all valid speeds we want to override with board
+ * specific parameters. datarate_mhz_high values need to be in ascending order
+ * for each n_ranks group.
+ */
+static const struct board_specific_parameters dimm0[] = {
+ /*
+ * memory controller 0
+ * num| hi| clk| cpo|wrdata|2T
+ * ranks| mhz|adjst| | delay|
+ */
+ { 1, 549, 5, 31, 3, 0 },
+ { 1, 850, 5, 31, 5, 0 },
+ { 2, 549, 5, 31, 3, 0 },
+ { 2, 850, 5, 31, 5, 0 },
+ { }
+};
+
+void fsl_ddr_board_options(struct memctl_options_s *popts,
+ struct dimm_params_s *pdimm)
+{
+ const struct board_specific_parameters *pbsp, *pbsp_highest = NULL;
+ unsigned long ddr_freq;
+ uint32_t i;
+
+ for (i = 0; i < popts->board_info->cs_per_ctrl; i++) {
+ popts->cs_local_opts[i].odt_rd_cfg = 0;
+ popts->cs_local_opts[i].odt_wr_cfg = 1;
+ popts->cs_local_opts[i].odt_rtt_wr = DDR3_RTT_OFF;
+ }
+ popts->cs_local_opts[0].odt_rtt_norm = DDR3_RTT_40_OHM;
+ popts->cs_local_opts[1].odt_rtt_norm = DDR3_RTT_OFF;
+
+ pbsp = dimm0;
+
+ ddr_freq = fsl_get_ddr_freq(0) / 1000000;
+ /*
+ * To have optimal parameters specific to the board, do a fine
+ * adjustment of DDR parameters depending on the DDR data rate.
+ */
+ while (pbsp->datarate_mhz_high) {
+ if (pbsp->n_ranks == pdimm->n_ranks) {
+ if (ddr_freq <= pbsp->datarate_mhz_high) {
+ popts->clk_adjust = pbsp->clk_adjust;
+ popts->cpo_override = pbsp->cpo;
+ popts->write_data_delay =
+ pbsp->write_data_delay;
+ popts->twoT_en = pbsp->force_2t;
+ goto found;
+ }
+ pbsp_highest = pbsp;
+ }
+ pbsp++;
+ }
+
+ /* Use highest parameters if none were found */
+ if (pbsp_highest) {
+ popts->clk_adjust = pbsp->clk_adjust;
+ popts->cpo_override = pbsp->cpo;
+ popts->write_data_delay = pbsp->write_data_delay;
+ popts->twoT_en = pbsp->force_2t;
+ }
+
+found:
+ popts->half_strength_driver_enable = 1;
+
+ /* Per AN4039, enable ZQ calibration. */
+ popts->zq_en = 1;
+
+ popts->auto_self_refresh_en = 1;
+ popts->sr_it = 0xb;
+
+ popts->dll_rst_dis = 1;
+}
diff --git a/arch/powerpc/boards/freescale-p1022ds/defaultenv-freescale-p1022ds/bin/init b/arch/powerpc/boards/freescale-p1022ds/defaultenv-freescale-p1022ds/bin/init
new file mode 100644
index 0000000000..c0e04c1f2d
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p1022ds/defaultenv-freescale-p1022ds/bin/init
@@ -0,0 +1,2 @@
+#!/bin/sh
+source /env/config
diff --git a/arch/powerpc/boards/freescale-p1022ds/defaultenv-freescale-p1022ds/config b/arch/powerpc/boards/freescale-p1022ds/defaultenv-freescale-p1022ds/config
new file mode 100644
index 0000000000..bffd86882e
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p1022ds/defaultenv-freescale-p1022ds/config
@@ -0,0 +1,2 @@
+#!/bin/sh
+export bootargs="root=/dev/nfs rw ip=bootp console=ttyS0,115200" \ No newline at end of file
diff --git a/arch/powerpc/boards/freescale-p1022ds/ics307_clk.c b/arch/powerpc/boards/freescale-p1022ds/ics307_clk.c
new file mode 100644
index 0000000000..f7c5bbde99
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p1022ds/ics307_clk.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+/* decode S[0-2] to Output Divider (OD) */
+static u8 ics307_s_to_od[] = {
+ 10, 2, 8, 4, 5, 7, 3, 6
+};
+
+/* Calculate frequency being generated by ICS307-02 clock chip. */
+unsigned long ics307_clk_freq(unsigned int reg)
+{
+ const unsigned long input_freq = 33333000;
+ void __iomem *fpga_base = IOMEM(CFG_PIXIS_BASE);
+ unsigned char cw0, cw1, cw2;
+ unsigned long vdw, rdw, od, freq;
+
+ cw0 = in_8(fpga_base + reg);
+ cw1 = in_8(fpga_base + reg + 1);
+ cw2 = in_8(fpga_base + reg + 2);
+ vdw = ((cw1 << 1) & 0x1fe) + ((cw2 >> 7) & 1);
+ rdw = cw2 & 0x7f;
+ od = ics307_s_to_od[cw0 & 0x7];
+ /*
+ * CLK1 Freq = Input Frequency * 2 * (VDW + 8) / ((RDW + 2) * OD)
+ *
+ * cw0: C1 C0 TTL F1 F0 S2 S1 S0
+ * cw1: V8 V7 V6 V5 V4 V3 V2 V1
+ * cw2: V0 R6 R5 R4 R3 R2 R1 R0
+ *
+ * R6:R0 = Reference Divider Word (RDW)
+ * V8:V0 = VCO Divider Word (VDW)
+ * S2:S0 = Output Divider Select (OD)
+ * F1:F0 = Function of CLK2 Output
+ * TTL = duty cycle
+ * C1:C0 = internal load capacitance for crystal
+ */
+ freq = input_freq * 2 * (vdw + 8) / ((rdw + 2) * od);
+
+ return freq;
+}
diff --git a/arch/powerpc/boards/freescale-p1022ds/law.c b/arch/powerpc/boards/freescale-p1022ds/law.c
new file mode 100644
index 0000000000..79cc20dd6e
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p1022ds/law.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2009-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 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.
+ *
+ */
+
+#include <common.h>
+#include <asm/fsl_law.h>
+
+struct law_entry law_table[] = {
+ FSL_SET_LAW(CFG_BOOT_BLOCK_PHYS, LAW_SIZE_256M, LAW_TRGT_IF_LBC),
+ FSL_SET_LAW(CFG_PIXIS_BASE_PHYS, LAW_SIZE_4K, LAW_TRGT_IF_LBC),
+};
+
+int num_law_entries = ARRAY_SIZE(law_table);
diff --git a/arch/powerpc/boards/freescale-p1022ds/p1022ds.c b/arch/powerpc/boards/freescale-p1022ds/p1022ds.c
new file mode 100644
index 0000000000..fd07b6f89f
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p1022ds/p1022ds.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2014 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.
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <platform_data/serial-ns16550.h>
+#include <net.h>
+#include <types.h>
+#include <i2c/i2c.h>
+#include <memory.h>
+#include <envfs.h>
+#include <asm/cache.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/fsl_law.h>
+#include <mach/mpc85xx.h>
+#include <mach/mmu.h>
+#include <mach/immap_85xx.h>
+#include <mach/gianfar.h>
+#include <mach/clock.h>
+#include <mach/early_udelay.h>
+
+#include "p1022ds.h"
+
+/* Define attributes for eTSEC1 and eTSEC2 */
+static struct gfar_info_struct gfar_info[] = {
+ {
+ .phyaddr = 1,
+ .tbiana = 0,
+ .tbicr = 0,
+ .mdiobus_tbi = 0,
+ },
+ {
+ .phyaddr = 2,
+ .tbiana = 0,
+ .tbicr = 0,
+ .mdiobus_tbi = 0,
+ },
+};
+
+struct i2c_platform_data i2cplat[] = {
+ { .bitrate = 400000, },
+ { .bitrate = 400000, },
+};
+
+void p1022ds_lbc_early_init(void)
+{
+ void __iomem *gur = IOMEM(MPC85xx_GUTS_ADDR);
+ void __iomem *lbc = LBC_BASE_ADDR;
+
+ /* Set the local bus monitor timeout value to the maximum */
+ clrsetbits_be32(lbc + FSL_LBC_LBCR_OFFSET, 0xff0f, 0xf);
+ /* Set the pin muxing to enable ETSEC2. */
+ clrbits_be32(gur + MPC85xx_GUTS_PMUXCR2_OFFSET, 0x001f8000);
+ /* Set pmuxcr to allow both i2c1 and i2c2 */
+ setbits_be32(gur + MPC85xx_GUTS_PMUXCR_OFFSET, 0x1000);
+
+ /* Map the boot flash and FPGA */
+ fsl_set_lbc_br(0, BR_PHYS_ADDR(CFG_FLASH_BASE_PHYS) | BR_PS_16 | BR_V);
+ fsl_set_lbc_or(0, 0xf8000ff7);
+ fsl_set_lbc_br(2, BR_PHYS_ADDR(CFG_PIXIS_BASE_PHYS) | BR_PS_8 | BR_V);
+ fsl_set_lbc_or(2, 0xffff8ff7);
+}
+
+static void board_eth_init(void)
+{
+ struct i2c_adapter *adapter;
+ struct i2c_client client;
+ char mac[6];
+ int ret, ix;
+
+ adapter = i2c_get_adapter(1);
+ client.addr = 0x57;
+ client.adapter = adapter;
+
+ for (ix = 0; ix < 2; ix++) {
+ int mac_offset;
+
+ mac_offset = 0x42 + (sizeof(mac) * ix);
+ ret = i2c_read_reg(&client, mac_offset, mac, sizeof(mac));
+ if (ret != sizeof(mac))
+ pr_err("Fail to retrieve MAC address\n");
+ else
+ eth_register_ethaddr(ix, mac);
+ }
+
+ fsl_eth_init(1, &gfar_info[0]);
+ fsl_eth_init(2, &gfar_info[1]);
+}
+
+static int p1022ds_devices_init(void)
+{
+ add_cfi_flash_device(DEVICE_ID_DYNAMIC, CFG_FLASH_BASE, 128 << 20, 0);
+ devfs_add_partition("nor0", 0x7f80000, 0x80000, DEVFS_PARTITION_FIXED,
+ "self0");
+ devfs_add_partition("nor0", 0x7f00000, 0x10000, DEVFS_PARTITION_FIXED,
+ "env0");
+ add_generic_device("i2c-fsl", 0, NULL, I2C1_BASE_ADDR, 0x100,
+ IORESOURCE_MEM, &i2cplat[0]);
+ add_generic_device("i2c-fsl", 1, NULL, I2C2_BASE_ADDR, 0x100,
+ IORESOURCE_MEM, &i2cplat[1]);
+
+ board_eth_init();
+
+ if (IS_ENABLED(CONFIG_DEFAULT_ENVIRONMENT_GENERIC))
+ defaultenv_append_directory(defaultenv_freescale_p1022ds);
+
+ return 0;
+}
+
+device_initcall(p1022ds_devices_init);
+
+static struct NS16550_plat serial_plat = {
+ .clock = 0,
+ .shift = 0,
+};
+
+static int p1022ds_console_init(void)
+{
+ barebox_set_model("Freescale P1022DS");
+ barebox_set_hostname("p1022ds");
+
+ serial_plat.clock = fsl_get_bus_freq(0);
+ add_ns16550_device(DEVICE_ID_DYNAMIC, CFG_IMMR + 0x4500, 16,
+ IORESOURCE_MEM | IORESOURCE_MEM_8BIT, &serial_plat);
+ return 0;
+}
+
+console_initcall(p1022ds_console_init);
+
+static int p1022ds_mem_init(void)
+{
+ barebox_add_memory_bank("ram0", 0x0, fsl_get_effective_memsize());
+ return 0;
+}
+
+mem_initcall(p1022ds_mem_init);
+
+static int p1022ds_board_init_r(void)
+{
+ void __iomem *fpga = IOMEM(CFG_PIXIS_BASE);
+ const uint32_t flashbase = CFG_BOOT_BLOCK;
+ const u8 flash_esel = e500_find_tlb_idx((void *)flashbase, 1);
+
+ /* Enable SPI */
+ out_8(fpga + 8, (in_8(fpga + 8) & ~(0xc0)) | (0x80));
+
+ /* Map the NAND flash */
+ fsl_set_lbc_br(1, BR_PHYS_ADDR(0xff800000) | BR_PS_8 |
+ (2 << BR_DECC_SHIFT) | BR_MS_FCM | BR_V);
+ fsl_set_lbc_or(1, 0xffff8796);
+
+ /* Flush d-cache and invalidate i-cache of any FLASH data */
+ flush_dcache();
+ invalidate_icache();
+
+ /* invalidate existing TLB entry for flash */
+ e500_disable_tlb(flash_esel);
+
+ /*
+ * Remap Boot flash region to caching-inhibited
+ * so that flash can be erased properly.
+ */
+ e500_set_tlb(1, flashbase, CFG_BOOT_BLOCK_PHYS,
+ MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
+ 0, flash_esel, BOOKE_PAGESZ_256M, 1);
+
+ fsl_l2_cache_init();
+
+ return 0;
+}
+
+core_initcall(p1022ds_board_init_r);
diff --git a/arch/powerpc/boards/freescale-p1022ds/p1022ds.h b/arch/powerpc/boards/freescale-p1022ds/p1022ds.h
new file mode 100644
index 0000000000..cbc2aca644
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p1022ds/p1022ds.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2014 GE Intelligent Platforms, 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.
+ */
+void p1022ds_lbc_early_init(void);
diff --git a/arch/powerpc/boards/freescale-p1022ds/tlb.c b/arch/powerpc/boards/freescale-p1022ds/tlb.c
new file mode 100644
index 0000000000..86ab43aec0
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p1022ds/tlb.c
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ *
+ */
+
+#include <common.h>
+#include <mach/mmu.h>
+
+struct fsl_e_tlb_entry tlb_table[] = {
+ /* TLB 0 - for temp stack in cache */
+ FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR, CFG_INIT_RAM_ADDR,
+ MAS3_SX | MAS3_SW | MAS3_SR, 0,
+ 0, 0, BOOKE_PAGESZ_4K, 0),
+ FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR + (4 * 1024),
+ CFG_INIT_RAM_ADDR + (4 * 1024),
+ MAS3_SX | MAS3_SW | MAS3_SR, 0,
+ 0, 0, BOOKE_PAGESZ_4K, 0),
+ FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR + (8 * 1024),
+ CFG_INIT_RAM_ADDR + (8 * 1024),
+ MAS3_SX | MAS3_SW | MAS3_SR, 0,
+ 0, 0, BOOKE_PAGESZ_4K, 0),
+ FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR + (12 * 1024),
+ CFG_INIT_RAM_ADDR + (12 * 1024),
+ MAS3_SX | MAS3_SW | MAS3_SR, 0,
+ 0, 0, BOOKE_PAGESZ_4K, 0),
+
+ /* TLB 1 */
+ /* *I*** - Covers boot page */
+ FSL_SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000,
+ MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
+ 0, 0, BOOKE_PAGESZ_4K, 1),
+
+ /* *I*G* - CCSRBAR */
+ FSL_SET_TLB_ENTRY(1, CFG_CCSRBAR, CFG_CCSRBAR_PHYS,
+ MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
+ 0, 1, BOOKE_PAGESZ_1M, 1),
+
+ /* W**G* - Flash/promjet, localbus */
+ /* This will be changed to *I*G* after relocation to RAM. */
+ FSL_SET_TLB_ENTRY(1, CFG_BOOT_BLOCK, CFG_BOOT_BLOCK_PHYS,
+ MAS3_SX | MAS3_SR, MAS2_M | MAS2_W | MAS2_G,
+ 0, 2, BOOKE_PAGESZ_256M, 1),
+
+ FSL_SET_TLB_ENTRY(1, CFG_PIXIS_BASE, CFG_PIXIS_BASE_PHYS,
+ MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
+ 0, 7, BOOKE_PAGESZ_4K, 1),
+};
+
+int num_tlb_entries = ARRAY_SIZE(tlb_table);
diff --git a/arch/powerpc/boards/freescale-p2020rdb/Makefile b/arch/powerpc/boards/freescale-p2020rdb/Makefile
new file mode 100644
index 0000000000..ff0cdd657c
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p2020rdb/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-y += p2020rdb.o
+obj-y += law.o
+obj-y += tlb.o
+bbenv-$(CONFIG_DEFAULT_ENVIRONMENT_GENERIC) += defaultenv-freescale-p2020rdb
diff --git a/arch/powerpc/boards/freescale-p2020rdb/config.h b/arch/powerpc/boards/freescale-p2020rdb/config.h
new file mode 100644
index 0000000000..0d3e095016
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p2020rdb/config.h
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ * P2020RDB board configuration file
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#ifndef __ASSEMBLY__
+extern unsigned long get_board_sys_clk(unsigned long dummy);
+#endif
+#define CFG_SYS_CLK_FREQ get_board_sys_clk(0)
+#define CFG_DDR_CLK_FREQ 66666666
+
+/*
+ * Base addresses -- Note these are effective addresses where the
+ * actual resources get mapped (not physical addresses)
+ */
+#define CFG_CCSRBAR_DEFAULT 0xff700000
+
+#define CFG_CCSRBAR 0xffe00000 /* relocated CCSRBAR */
+#define CFG_CCSRBAR_PHYS CFG_CCSRBAR
+
+#define CFG_IMMR CFG_CCSRBAR
+
+/* DDR Setup */
+
+#define CFG_CHIP_SELECTS_PER_CTRL 1
+
+#define CFG_SDRAM_BASE 0x00000000
+
+/* These timings are adjusted for a 667Mhz clock. */
+#define CFG_SYS_DDR_CS0_BNDS 0x0000003f /* 1GB */
+#define CFG_SYS_DDR_CS0_CONFIG 0x80014202
+#define CFG_SYS_DDR_TIMING_3 0x00030000
+#define CFG_SYS_DDR_TIMING_0 0x55770802
+#define CFG_SYS_DDR_TIMING_1 0x5f599543
+#define CFG_SYS_DDR_TIMING_2 0x0fa074d1
+
+#define CFG_SYS_DDR_CONTROL 0xc3000000
+#define CFG_SYS_DDR_CONTROL2 0x24401000
+#define CFG_SYS_DDR_MODE_1 0x00040852
+#define CFG_SYS_DDR_MODE_2 0x00000000
+#define CFG_SYS_MD_CNTL 0x00000000
+#define CFG_SYS_DDR_INTERVAL 0x0a280100
+
+#define CFG_SYS_DDR_DATA_INIT 0xdeadbeef
+#define CFG_SYS_DDR_CLK_CTRL 0x03000000
+
+/*
+ * Memory map
+ *
+ * 0x0000_0000 0x3fff_ffff DDR 1G cacheablen
+ *
+ * Localbus non-cacheable
+ * 0xef00_0000 0xefff_ffff FLASH 16M non-cacheable
+ * 0xffd0_0000 0xffd0_3fff L1 for stack 16K Cacheable TLB0
+ */
+
+/*
+ * Local Bus Definitions
+ */
+#define CFG_FLASH_BASE 0xef000000
+#define CFG_FLASH_BASE_PHYS CFG_FLASH_BASE
+
+#define CFG_INIT_RAM_ADDR 0xffd00000 /* stack in RAM */
+/* Leave 256 bytes for global data */
+#define CFG_INIT_SP_OFFSET (0x00004000 - 256)
+
+#endif /* __CONFIG_H */
diff --git a/arch/powerpc/boards/freescale-p2020rdb/defaultenv-freescale-p2020rdb/bin/init b/arch/powerpc/boards/freescale-p2020rdb/defaultenv-freescale-p2020rdb/bin/init
new file mode 100644
index 0000000000..4d7b03e26d
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p2020rdb/defaultenv-freescale-p2020rdb/bin/init
@@ -0,0 +1,2 @@
+#!/bin/sh
+source /env/config \ No newline at end of file
diff --git a/arch/powerpc/boards/freescale-p2020rdb/defaultenv-freescale-p2020rdb/config b/arch/powerpc/boards/freescale-p2020rdb/defaultenv-freescale-p2020rdb/config
new file mode 100644
index 0000000000..23e0ba2a5d
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p2020rdb/defaultenv-freescale-p2020rdb/config
@@ -0,0 +1,2 @@
+#!/bin/sh
+export bootargs="root=/dev/nfs rw ip=bootp" \ No newline at end of file
diff --git a/arch/powerpc/boards/freescale-p2020rdb/law.c b/arch/powerpc/boards/freescale-p2020rdb/law.c
new file mode 100644
index 0000000000..e76b9cb0f5
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p2020rdb/law.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2009-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 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.
+ *
+ */
+
+#include <common.h>
+#include <asm/fsl_law.h>
+#include <asm/mmu.h>
+
+struct law_entry law_table[] = {
+ FSL_SET_LAW(CFG_FLASH_BASE_PHYS, LAW_SIZE_16M, LAW_TRGT_IF_LBC),
+};
+
+int num_law_entries = ARRAY_SIZE(law_table);
diff --git a/arch/powerpc/boards/freescale-p2020rdb/p2020rdb.c b/arch/powerpc/boards/freescale-p2020rdb/p2020rdb.c
new file mode 100644
index 0000000000..2c154db77c
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p2020rdb/p2020rdb.c
@@ -0,0 +1,266 @@
+/*
+ * 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.
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <platform_data/serial-ns16550.h>
+#include <types.h>
+#include <i2c/i2c.h>
+#include <memory.h>
+#include <envfs.h>
+#include <asm/cache.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/fsl_law.h>
+#include <mach/mpc85xx.h>
+#include <mach/mmu.h>
+#include <mach/immap_85xx.h>
+#include <mach/gianfar.h>
+#include <mach/clock.h>
+#include <mach/early_udelay.h>
+
+#define VSC7385_RST_SET 0x00080000
+#define SLIC_RST_SET 0x00040000
+#define SGMII_PHY_RST_SET 0x00020000
+#define PCIE_RST_SET 0x00010000
+#define RGMII_PHY_RST_SET 0x02000000
+
+#define USB_RST_CLR 0x04000000
+
+#define GPIO_DIR 0x060f0000
+
+#define BOARD_PERI_RST_SET (VSC7385_RST_SET | SLIC_RST_SET | \
+ SGMII_PHY_RST_SET | PCIE_RST_SET | \
+ RGMII_PHY_RST_SET)
+
+#define SYSCLK_MASK 0x00200000
+#define BOARDREV_MASK 0x10100000
+#define BOARDREV_B 0x10100000
+#define BOARDREV_C 0x00100000
+#define BOARDREV_D 0x00000000
+
+#define SYSCLK_66 66666666
+#define SYSCLK_50 50000000
+#define SYSCLK_100 100000000
+
+/* Define attributes for eTSEC2 and eTSEC3 */
+static struct gfar_info_struct gfar_info[] = {
+ {
+ .phyaddr = 0,
+ .tbiana = 0x1a0,
+ .tbicr = 0x9140,
+ .mdiobus_tbi = 1,
+ },
+ {
+ .phyaddr = 1,
+ .tbiana = 0,
+ .tbicr = 0,
+ .mdiobus_tbi = 2,
+ },
+};
+
+/* I2C busses. */
+struct i2c_platform_data i2cplat = {
+ .bitrate = 400000,
+};
+
+static int devices_init(void)
+{
+ add_cfi_flash_device(DEVICE_ID_DYNAMIC, CFG_FLASH_BASE, 16 << 20, 0);
+ devfs_add_partition("nor0", 0xf60000, 0x8000, DEVFS_PARTITION_FIXED,
+ "env0");
+ devfs_add_partition("nor0", 0xf80000, 0x80000, DEVFS_PARTITION_FIXED,
+ "self0");
+ add_generic_device("i2c-fsl", 0, NULL, I2C1_BASE_ADDR,
+ 0x100, IORESOURCE_MEM, &i2cplat);
+ add_generic_device("i2c-fsl", 1, NULL, I2C2_BASE_ADDR,
+ 0x100, IORESOURCE_MEM, &i2cplat);
+
+ fsl_eth_init(2, &gfar_info[0]);
+ fsl_eth_init(3, &gfar_info[1]);
+
+ if (IS_ENABLED(CONFIG_DEFAULT_ENVIRONMENT_GENERIC))
+ defaultenv_append_directory(defaultenv_freescale_p2020rdb);
+
+ return 0;
+}
+
+device_initcall(devices_init);
+
+static struct NS16550_plat serial_plat = {
+ .clock = 0,
+ .shift = 0,
+};
+
+static int p2020_console_init(void)
+{
+ barebox_set_model("Freescale P2020RDB");
+ barebox_set_hostname("p2020rdb");
+
+ serial_plat.clock = fsl_get_bus_freq(0);
+
+ add_ns16550_device(DEVICE_ID_DYNAMIC, 0xffe04500, 16,
+ IORESOURCE_MEM | IORESOURCE_MEM_8BIT,
+ &serial_plat);
+ return 0;
+}
+
+console_initcall(p2020_console_init);
+
+static int mem_init(void)
+{
+ barebox_add_memory_bank("ram0", 0x0, 1024 << 20);
+
+ return 0;
+}
+mem_initcall(mem_init);
+
+/*
+ * fixed_sdram: fixed sdram settings.
+ */
+phys_size_t fixed_sdram(void)
+{
+ void __iomem *regs = (void __iomem *)(MPC85xx_DDR_ADDR);
+ int sdram_cfg = (SDRAM_CFG_MEM_EN | SDRAM_CFG_SREN |
+ SDRAM_CFG_SDRAM_TYPE_DDR2);
+ phys_size_t dram_size;
+
+ /* If already enabled (running from RAM), get out */
+ if (in_be32(regs + DDR_OFF(SDRAM_CFG)) & SDRAM_CFG_MEM_EN)
+ return fsl_get_effective_memsize();
+
+ out_be32(regs + DDR_OFF(CS0_BNDS), CFG_SYS_DDR_CS0_BNDS);
+ out_be32(regs + DDR_OFF(CS0_CONFIG), CFG_SYS_DDR_CS0_CONFIG);
+ out_be32(regs + DDR_OFF(TIMING_CFG_3), CFG_SYS_DDR_TIMING_3);
+ out_be32(regs + DDR_OFF(TIMING_CFG_0), CFG_SYS_DDR_TIMING_0);
+ out_be32(regs + DDR_OFF(TIMING_CFG_1), CFG_SYS_DDR_TIMING_1);
+ out_be32(regs + DDR_OFF(TIMING_CFG_2), CFG_SYS_DDR_TIMING_2);
+ out_be32(regs + DDR_OFF(SDRAM_CFG_2), CFG_SYS_DDR_CONTROL2);
+ out_be32(regs + DDR_OFF(SDRAM_MODE), CFG_SYS_DDR_MODE_1);
+ out_be32(regs + DDR_OFF(SDRAM_MODE_2), CFG_SYS_DDR_MODE_2);
+ out_be32(regs + DDR_OFF(SDRAM_MD_CNTL), CFG_SYS_MD_CNTL);
+ /* Basic refresh rate (7.8us),high temp is 3.9us */
+ out_be32(regs + DDR_OFF(SDRAM_INTERVAL),
+ CFG_SYS_DDR_INTERVAL);
+ out_be32(regs + DDR_OFF(SDRAM_DATA_INIT),
+ CFG_SYS_DDR_DATA_INIT);
+ out_be32(regs + DDR_OFF(SDRAM_CLK_CNTL),
+ CFG_SYS_DDR_CLK_CTRL);
+
+ out_be32(regs + DDR_OFF(SDRAM_INIT_ADDR), 0);
+ out_be32(regs + DDR_OFF(SDRAM_INIT_ADDR_EXT), 0);
+ /*
+ * Wait 200us for the DDR clock to stabilize.
+ */
+ early_udelay(200);
+ asm volatile ("sync;isync");
+
+ out_be32(regs + DDR_OFF(SDRAM_CFG), sdram_cfg);
+
+ dram_size = fsl_get_effective_memsize();
+ if (fsl_set_ddr_laws(0, dram_size, LAW_TRGT_IF_DDR) < 0)
+ return 0;
+
+ return dram_size;
+}
+
+unsigned long get_board_sys_clk(ulong dummy)
+{
+ u32 val_gpdat, sysclk_gpio, board_rev_gpio;
+ void __iomem *gpio_regs = (void __iomem *)MPC85xx_GPIO_ADDR;
+
+ val_gpdat = in_be32(gpio_regs + MPC85xx_GPIO_GPDAT);
+ sysclk_gpio = val_gpdat & SYSCLK_MASK;
+ board_rev_gpio = val_gpdat & BOARDREV_MASK;
+
+ if (board_rev_gpio == BOARDREV_C) {
+ if (sysclk_gpio == 0)
+ return SYSCLK_66;
+ else
+ return SYSCLK_100;
+ } else if (board_rev_gpio == BOARDREV_B) {
+ if (sysclk_gpio == 0)
+ return SYSCLK_66;
+ else
+ return SYSCLK_50;
+ } else if (board_rev_gpio == BOARDREV_D) {
+ if (sysclk_gpio == 0)
+ return SYSCLK_66;
+ else
+ return SYSCLK_100;
+ }
+ return 0;
+}
+
+static void checkboard(void)
+{
+ u32 val_gpdat, board_rev_gpio;
+ void __iomem *gpio_regs = (void __iomem *)MPC85xx_GPIO_ADDR;
+
+ val_gpdat = in_be32(gpio_regs + MPC85xx_GPIO_GPDAT);
+ board_rev_gpio = val_gpdat & BOARDREV_MASK;
+
+ if ((board_rev_gpio != BOARDREV_C) && (board_rev_gpio != BOARDREV_B) &&
+ (board_rev_gpio != BOARDREV_D))
+ panic("Unexpected Board REV %x detected!!\n", board_rev_gpio);
+
+ setbits_be32((gpio_regs + MPC85xx_GPIO_GPDIR), GPIO_DIR);
+
+ /*
+ * Bringing the following peripherals out of reset via GPIOs
+ * 0 = reset and 1 = out of reset
+ * GPIO12 - Reset to Ethernet Switch
+ * GPIO13 - Reset to SLIC/SLAC devices
+ * GPIO14 - Reset to SGMII_PHY_N
+ * GPIO15 - Reset to PCIe slots
+ * GPIO6 - Reset to RGMII PHY
+ * GPIO5 - Reset to USB3300 devices 1 = reset and 0 = out of reset
+ */
+ clrsetbits_be32((gpio_regs + MPC85xx_GPIO_GPDAT), USB_RST_CLR,
+ BOARD_PERI_RST_SET);
+}
+
+static int board_init_r(void)
+{
+ const unsigned int flashbase = CFG_FLASH_BASE;
+ const u8 flash_esel = e500_find_tlb_idx((void *)flashbase, 1);
+
+ checkboard();
+
+ /* Map the whole boot flash */
+ fsl_set_lbc_br(0, BR_PHYS_ADDR(CFG_FLASH_BASE_PHYS) | BR_PS_16 | BR_V);
+ fsl_set_lbc_or(0, 0xff000ff7);
+
+ /* Flush d-cache and invalidate i-cache of any FLASH data */
+ flush_dcache();
+ invalidate_icache();
+
+ /* invalidate existing TLB entry for flash */
+ e500_disable_tlb(flash_esel);
+
+ /*
+ * Remap Boot flash region to caching-inhibited
+ * so that flash can be erased properly.
+ */
+ e500_set_tlb(1, flashbase, CFG_FLASH_BASE_PHYS,
+ MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+ 0, flash_esel, BOOKE_PAGESZ_16M, 1);
+
+ fsl_l2_cache_init();
+
+ return 0;
+}
+core_initcall(board_init_r);
diff --git a/arch/powerpc/boards/freescale-p2020rdb/tlb.c b/arch/powerpc/boards/freescale-p2020rdb/tlb.c
new file mode 100644
index 0000000000..e5b1789b28
--- /dev/null
+++ b/arch/powerpc/boards/freescale-p2020rdb/tlb.c
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ *
+ */
+
+#include <common.h>
+#include <mach/mmu.h>
+
+struct fsl_e_tlb_entry tlb_table[] = {
+ /* TLB 0 - for temp stack in cache */
+ FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR, CFG_INIT_RAM_ADDR,
+ MAS3_SX|MAS3_SW|MAS3_SR, 0,
+ 0, 0, BOOKE_PAGESZ_4K, 0),
+ FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR + (4 * 1024),
+ CFG_INIT_RAM_ADDR + (4 * 1024),
+ MAS3_SX|MAS3_SW|MAS3_SR, 0,
+ 0, 0, BOOKE_PAGESZ_4K, 0),
+ FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR + (8 * 1024),
+ CFG_INIT_RAM_ADDR + (8 * 1024),
+ MAS3_SX|MAS3_SW|MAS3_SR, 0,
+ 0, 0, BOOKE_PAGESZ_4K, 0),
+ FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR + (12 * 1024),
+ CFG_INIT_RAM_ADDR + (12 * 1024),
+ MAS3_SX|MAS3_SW|MAS3_SR, 0,
+ 0, 0, BOOKE_PAGESZ_4K, 0),
+
+ /* TLB 1 */
+ /* *I*** - Covers boot page */
+ FSL_SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000,
+ MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+ 0, 0, BOOKE_PAGESZ_4K, 1),
+
+ /* *I*G* - CCSRBAR */
+ FSL_SET_TLB_ENTRY(1, CFG_CCSRBAR, CFG_CCSRBAR_PHYS,
+ MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+ 0, 1, BOOKE_PAGESZ_1M, 1),
+
+ /* W**G* - Flash/promjet, localbus */
+ /* This will be changed to *I*G* after relocation to RAM. */
+ FSL_SET_TLB_ENTRY(1, CFG_FLASH_BASE, CFG_FLASH_BASE_PHYS,
+ MAS3_SX|MAS3_SR, MAS2_W|MAS2_G,
+ 0, 2, BOOKE_PAGESZ_16M, 1),
+};
+
+int num_tlb_entries = ARRAY_SIZE(tlb_table);
diff --git a/arch/powerpc/boards/owc-da923rc/Makefile b/arch/powerpc/boards/owc-da923rc/Makefile
new file mode 100644
index 0000000000..78b6885c08
--- /dev/null
+++ b/arch/powerpc/boards/owc-da923rc/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-y += da923rc.o
+obj-y += tlb.o
+obj-y += law.o
+obj-y += ddr.o
+obj-y += nand.o
+obj-y += product_data.o
+bbenv-$(CONFIG_DEFAULT_ENVIRONMENT_GENERIC) += defaultenv-owc-da923rc
diff --git a/arch/powerpc/boards/owc-da923rc/config.h b/arch/powerpc/boards/owc-da923rc/config.h
new file mode 100644
index 0000000000..3895324e95
--- /dev/null
+++ b/arch/powerpc/boards/owc-da923rc/config.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2013 GE Intelligent Platforms, 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.
+ *
+ * DA923RC board configuration file.
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define CFG_SYS_CLK_FREQ 66666666
+
+#define CFG_FLASH_CFI_WIDTH FLASH_CFI_16BIT
+#define CFG_CHIP_SELECTS_PER_CTRL 1
+
+/*
+ * Memory map
+ *
+ * 0x0000_0000 0x1fff_ffff DDR 512MB Cacheable
+ * 0xe000_0000 0xe00f_ffff CCSR 1M non-cacheable
+ * 0xf400_0000 0xf400_3fff L1 for stack 4K Cacheable TLB0
+ *
+ */
+#define CFG_SDRAM_BASE 0x00000000
+
+#define CFG_CCSRBAR_DEFAULT 0xff700000
+#define CFG_CCSRBAR 0xe0000000
+#define CFG_CCSRBAR_PHYS CFG_CCSRBAR
+#define CFG_IMMR CFG_CCSRBAR
+
+/* Initial memory for global storage and stack. */
+#define CFG_INIT_RAM_ADDR 0xf4000000
+#define CFG_INIT_RAM_SIZE 0x00004000
+#define CFG_INIT_BI_SIZE 0x100
+#define CFG_INIT_SP_OFFSET (CFG_INIT_RAM_SIZE - CFG_INIT_BI_SIZE)
+
+#define BOOT_BLOCK 0xfc000000
+
+#define BOARD_TYPE_UNKNOWN -1
+#define BOARD_TYPE_NONE 0
+#define BOARD_TYPE_DA923 1
+#define BOARD_TYPE_GBX460 2
+
+#endif /* __CONFIG_H */
diff --git a/arch/powerpc/boards/owc-da923rc/da923rc.c b/arch/powerpc/boards/owc-da923rc/da923rc.c
new file mode 100644
index 0000000000..b9eb2520cf
--- /dev/null
+++ b/arch/powerpc/boards/owc-da923rc/da923rc.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2013 GE Intelligent Platforms, Inc.
+ * Copyright 2019 Abaco Systems, 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.
+ *
+ * Abaco Systems DA923RC/GBX460 board support.
+ */
+
+#include <common.h>
+#include <console.h>
+#include <init.h>
+#include <memory.h>
+#include <driver.h>
+#include <asm/io.h>
+#include <net.h>
+#include <gpio.h>
+#include <envfs.h>
+#include <platform_data/serial-ns16550.h>
+#include <environment.h>
+#include <i2c/i2c.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/cache.h>
+#include <mach/mmu.h>
+#include <mach/mpc85xx.h>
+#include <mach/immap_85xx.h>
+#include <mach/gianfar.h>
+#include <mach/gpio.h>
+#include <mach/clock.h>
+#include <mach/fsl_i2c.h>
+#include "product_data.h"
+
+static struct gfar_info_struct gfar_info[] = {
+ {
+ .phyaddr = 7,
+ .tbiana = 0,
+ .tbicr = 0,
+ .mdiobus_tbi = 0,
+ },
+};
+
+struct i2c_platform_data i2cplat[] = {
+ {
+ .bitrate = 400000,
+ },
+ {
+ .bitrate = 400000,
+ },
+};
+
+static struct board_info binfo;
+
+static int board_eth_init(void)
+{
+ void __iomem *gur = IOMEM(MPC85xx_GUTS_ADDR);
+ struct owc_product_data product;
+ int st;
+
+ /* Toggle eth0 reset pin */
+ gpio_set_value(4, 0);
+ udelay(5);
+ gpio_set_value(4, 1);
+
+ /* Disable eTSEC3 */
+ out_be32(gur + MPC85xx_DEVDISR_OFFSET,
+ in_be32(gur + MPC85xx_DEVDISR_OFFSET) &
+ ~MPC85xx_DEVDISR_TSEC3);
+
+ st = owc_get_product_data(&product);
+ if (((product.v2.mac.count > 0) && (product.v2.mac.count <= MAX_MAC))
+ && (st == 0))
+ eth_register_ethaddr(0, (const char *)&product.v2.mac.mac[0]);
+
+ fsl_eth_init(1, &gfar_info[0]);
+
+ return 0;
+}
+
+static int da923rc_devices_init(void)
+{
+ add_cfi_flash_device(0, 0xfe000000, 32 << 20, 0);
+ devfs_add_partition("nor0", 0x0, 0x8000, DEVFS_PARTITION_FIXED, "env0");
+ devfs_add_partition("nor0", 0x1f80000, 8 << 16, DEVFS_PARTITION_FIXED,
+ "self0");
+ add_generic_device("i2c-fsl", 0, NULL, I2C1_BASE_ADDR, 0x100,
+ IORESOURCE_MEM, &i2cplat[0]);
+ add_generic_device("i2c-fsl", 1, NULL, I2C2_BASE_ADDR, 0x100,
+ IORESOURCE_MEM, &i2cplat[1]);
+
+ board_eth_init();
+
+ if (IS_ENABLED(CONFIG_DEFAULT_ENVIRONMENT_GENERIC))
+ defaultenv_append_directory(defaultenv_owc_da923rc);
+
+ return 0;
+}
+
+device_initcall(da923rc_devices_init);
+
+static struct NS16550_plat serial_plat = {
+ .clock = 0,
+ .shift = 0,
+};
+
+static int da923rc_console_init(void)
+{
+ if (binfo.bid == BOARD_TYPE_DA923)
+ barebox_set_model("DA923RC");
+ else if (binfo.bid == BOARD_TYPE_GBX460)
+ barebox_set_model("GBX460");
+ else
+ barebox_set_model("unknown");
+
+ serial_plat.clock = fsl_get_bus_freq(0);
+ add_ns16550_device(1, CFG_CCSRBAR + 0x4600, 16,
+ IORESOURCE_MEM | IORESOURCE_MEM_8BIT,
+ &serial_plat);
+ return 0;
+}
+
+console_initcall(da923rc_console_init);
+
+static int da923rc_mem_init(void)
+{
+ barebox_add_memory_bank("ram0", 0x0, fsl_get_effective_memsize());
+ return 0;
+}
+
+mem_initcall(da923rc_mem_init);
+
+static int da923rc_board_init_r(void)
+{
+ void __iomem *lbc = LBC_BASE_ADDR;
+ void __iomem *ecm = IOMEM(MPC85xx_ECM_ADDR);
+ void __iomem *pci = IOMEM(PCI1_BASE_ADDR);
+ const unsigned int flashbase = (BOOT_BLOCK + 0x2000000);
+ uint8_t flash_esel;
+
+ da923rc_boardinfo_get(&binfo);
+
+ flush_dcache();
+ invalidate_icache();
+
+ /* Clear LBC error interrupts */
+ out_be32(lbc + FSL_LBC_LTESR_OFFSET, 0xffffffff);
+ /* Enable LBC error interrupts */
+ out_be32(lbc + FSL_LBC_LTEIR_OFFSET, 0xffffffff);
+ /* Clear ecm errors */
+ out_be32(ecm + MPC85xx_ECM_EEDR_OFFSET, 0xffffffff);
+ /* Enable ecm errors */
+ out_be32(ecm + MPC85xx_ECM_EEER_OFFSET, 0xffffffff);
+
+ /* Re-map boot flash */
+ fsl_set_lbc_br(0, BR_PHYS_ADDR(0xfe000000) | BR_PS_16 | BR_V);
+ fsl_set_lbc_or(0, 0xfe006e21);
+
+ /* Invalidate TLB entry for boot block */
+ flash_esel = e500_find_tlb_idx((void *)flashbase, 1);
+ e500_disable_tlb(flash_esel);
+ flash_esel = e500_find_tlb_idx((void *)(flashbase + 0x1000000), 1);
+ e500_disable_tlb(flash_esel);
+
+ /* Boot block back to cache inhibited. */
+ e500_set_tlb(1, BOOT_BLOCK + (2 * 0x1000000),
+ BOOT_BLOCK + (2 * 0x1000000),
+ MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G | MAS2_M,
+ 0, 2, BOOKE_PAGESZ_16M, 1);
+ e500_set_tlb(1, BOOT_BLOCK + (3 * 0x1000000),
+ BOOT_BLOCK + (3 * 0x1000000),
+ MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G | MAS2_M,
+ 0, 3, BOOKE_PAGESZ_16M, 1);
+
+ fsl_l2_cache_init();
+
+ fsl_enable_gpiout();
+ /* Enable NOR low voltage programming (gpio 2) and write (gpio 3). */
+ gpio_set_value(2, 1);
+ gpio_set_value(3, 1);
+
+ /* Enable write to NAND flash */
+ if (binfo.bid == BOARD_TYPE_GBX460) {
+ /* Map CPLD */
+ fsl_set_lbc_br(3, BR_PHYS_ADDR(0xfc010000) | BR_PS_16 | BR_V);
+ fsl_set_lbc_or(3, 0xffffe001);
+ /* Enable all reset */
+ out_be16(IOMEM(0xfc010044), 0xffff);
+ gpio_set_value(6, 1);
+ }
+
+ /* Board reset and PHY reset. Disable CS3. */
+ if (binfo.bid == BOARD_TYPE_DA923) {
+ gpio_set_value(0, 0);
+ gpio_set_value(1, 1);
+ /* De-assert Board reset */
+ udelay(1000);
+ gpio_set_value(0, 1);
+ }
+
+ /* Enable PCI error reporting */
+ out_be32(pci + 0xe00, 0x80000040);
+ out_be32(pci + 0xe08, 0x6bf);
+ out_be32(pci + 0xe0c, 0xbb1fa001);
+ /* 32-bytes cacheline size */
+ out_be32(pci, 0x8000000c);
+ out_le32(pci + 4, 0x00008008);
+
+ return 0;
+}
+
+postcore_initcall(da923rc_board_init_r);
diff --git a/arch/powerpc/boards/owc-da923rc/ddr.c b/arch/powerpc/boards/owc-da923rc/ddr.c
new file mode 100644
index 0000000000..fc0c50cdcd
--- /dev/null
+++ b/arch/powerpc/boards/owc-da923rc/ddr.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2013 GE Intelligent Platforms, 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.
+ *
+ * Board specific DDR tuning.
+ */
+
+#include <common.h>
+#include <mach/fsl_i2c.h>
+#include <mach/immap_85xx.h>
+#include <mach/clock.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/fsl_ddr_dimm_params.h>
+#include "product_data.h"
+
+static struct board_info *binfo =
+ (struct board_info *)(CFG_INIT_RAM_ADDR + CFG_INIT_RAM_SIZE -
+ sizeof(struct board_info));
+
+static u8 spd_addr = 0x50;
+
+static int da923rc_boardinfo_init(void)
+{
+ void __iomem *i2c = IOMEM(I2C1_BASE_ADDR);
+ uint8_t id;
+ int ret;
+
+ memset(binfo, 0, sizeof(struct board_info));
+
+ binfo->bid = BOARD_TYPE_UNKNOWN;
+ /* Read made from flash, use the DDR I2C API. */
+ fsl_i2c_init(i2c, 400000, 0x7f);
+ /* Read board id from offset 0. */
+ ret = fsl_i2c_read(i2c, 0x3b, 0, 1, &id, sizeof(uint8_t));
+ fsl_i2c_stop(i2c);
+
+ if (ret == 0) {
+ /*
+ * Board ID:
+ * 0-2 Hardware board
+ * revision
+ * 3-5 Board ID
+ * 000b/010b/100b - DA923, 001 - GBX460
+ * 6-7 Undefined 00
+ */
+ binfo->rev = id & 7;
+ id &= 0x38;
+ id >>= 3;
+ switch (id) {
+ case 0:
+ case 2:
+ case 4:
+ binfo->bid = BOARD_TYPE_DA923;
+ break;
+ case 1:
+ binfo->bid = BOARD_TYPE_GBX460;
+ break;
+ default:
+ binfo->bid = BOARD_TYPE_NONE;
+ }
+ }
+
+ return ret;
+}
+
+void da923rc_boardinfo_get(struct board_info *bi)
+{
+ memcpy(bi, binfo, sizeof(struct board_info));
+}
+
+void fsl_ddr_board_info(struct ddr_board_info_s *info)
+{
+ info->fsl_ddr_ver = 0;
+ info->ddr_base = IOMEM(MPC85xx_DDR_ADDR);
+ /* Actual number of chip select used */
+ info->cs_per_ctrl = 1;
+ info->dimm_slots_per_ctrl = 1;
+ info->i2c_bus = 0;
+ info->i2c_slave = 0x7f;
+ info->i2c_speed = 400000;
+ info->i2c_base = IOMEM(I2C1_BASE_ADDR);
+ info->spd_i2c_addr = &spd_addr;
+}
+
+void fsl_ddr_board_options(struct memctl_options_s *popts,
+ struct dimm_params_s *pdimm)
+{
+ da923rc_boardinfo_init();
+
+ /*
+ * Clock adjustment in 1/8-cycle
+ * 0 = Clock is launched aligned with address/command
+ * ...
+ * 6 = 3/4 cycle late
+ * 7 = 7/8 cycle late
+ * 8 = 1 cycle late
+ */
+ popts->clk_adjust = 8;
+
+ /*
+ * /MCAS-to-preamble override. Defines the number of DRAM cycles
+ * between when a read is issued and when the corresponding DQS
+ * preamble is valid for the memory controller.
+ *
+ * Factors to consider for CPO:
+ * - frequency
+ * - ddr type
+ */
+ popts->cpo_override = 9;
+
+ /*
+ * Write command to write data strobe timing adjustment.
+ * Factors to consider for write data delay:
+ * - number of DIMMs
+ *
+ * 1 = 1/4 clock delay
+ * 2 = 1/2 clock delay
+ * 3 = 3/4 clock delay
+ * 4 = 1 clock delay
+ * 5 = 5/4 clock delay
+ * 6 = 3/2 clock delay
+ */
+ popts->write_data_delay = 3;
+
+ /* 2T timing disabled. */
+ popts->twoT_en = 0;
+ if (pdimm->registered_dimm != 0)
+ hang();
+
+ /*
+ * Factors to consider for half-strength driver enable:
+ * - number of DIMMs installed
+ */
+ popts->half_strength_driver_enable = 1;
+
+ /* Enable additive latency override. */
+ popts->additive_latency_override = 1;
+ popts->additive_latency_override_value = 1;
+
+ /* 50000ps is valid for a 16-bit wide data bus */
+ popts->tFAW_window_four_activates_ps = 50000;
+
+ /* Allow ECC */
+ popts->ECC_mode = 1;
+ popts->data_init = 0;
+
+ /* DLL reset disable */
+ popts->dll_rst_dis = 1;
+
+ /* Powerdown timings in number of tCK. */
+ popts->txard = 2;
+ popts->txp = 2;
+ popts->taxpd = 8;
+
+ /* Load mode timing in number of tCK. */
+ popts->tmrd = 2;
+
+ /* Assert ODT only during writes to CSn */
+ popts->cs_local_opts[0].odt_wr_cfg = FSL_DDR_ODT_CS;
+}
diff --git a/arch/powerpc/boards/owc-da923rc/defaultenv-owc-da923rc/bin/boot b/arch/powerpc/boards/owc-da923rc/defaultenv-owc-da923rc/bin/boot
new file mode 100644
index 0000000000..ce7da18e63
--- /dev/null
+++ b/arch/powerpc/boards/owc-da923rc/defaultenv-owc-da923rc/bin/boot
@@ -0,0 +1,9 @@
+#!/bin/sh
+#Load the firmware images from the NOR UBIFS file system and boot
+
+readlink /mnt/active symlink
+
+bootargs="ubi.mtd=nand root=ubi0:fs-active rootfstype=ubifs rw panic=25"
+cp /mnt/$symlink/uImage /
+cp /mnt/$symlink/dtb /
+bootm -o /dtb /uImage \ No newline at end of file
diff --git a/arch/powerpc/boards/owc-da923rc/defaultenv-owc-da923rc/bin/init b/arch/powerpc/boards/owc-da923rc/defaultenv-owc-da923rc/bin/init
new file mode 100644
index 0000000000..80cc2cffb3
--- /dev/null
+++ b/arch/powerpc/boards/owc-da923rc/defaultenv-owc-da923rc/bin/init
@@ -0,0 +1,26 @@
+#!/bin/sh
+export PATH=/env/bin
+
+source /env/config
+
+#Define a 26MB partition in flash starting at offset 0x20000
+addpart -n /dev/nor0 0x1a00000@0x20000(boot)
+ubiattach /dev/boot
+
+if [ $? -ne 0 ]; then
+ echo "Fail to attach UBI device"
+ exit 1;
+fi
+
+mkdir /mnt
+mount -t ubifs /dev/ubi0.boot /mnt
+
+echo
+echo -n "Hit ctrl-c to stop autoboot: "
+timeout -c 5
+
+if [ $? -ne 0 ]; then
+ exit 0
+fi
+
+boot
diff --git a/arch/powerpc/boards/owc-da923rc/defaultenv-owc-da923rc/config b/arch/powerpc/boards/owc-da923rc/defaultenv-owc-da923rc/config
new file mode 100644
index 0000000000..79e2606a71
--- /dev/null
+++ b/arch/powerpc/boards/owc-da923rc/defaultenv-owc-da923rc/config
@@ -0,0 +1,4 @@
+#!/bin/sh
+export bootargs="root=/dev/nfs rw ip=bootp"
+eth0.ipaddr=192.168.0.136
+eth0.serverip=192.168.0.102
diff --git a/arch/powerpc/boards/owc-da923rc/law.c b/arch/powerpc/boards/owc-da923rc/law.c
new file mode 100644
index 0000000000..3d32c7e677
--- /dev/null
+++ b/arch/powerpc/boards/owc-da923rc/law.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2013 GE Intelligent Platforms, 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.
+ */
+
+#include <common.h>
+#include <asm/fsl_law.h>
+
+struct law_entry law_table[] = {
+ FSL_SET_LAW(0xf8000000, LAW_SIZE_128M, LAW_TRGT_IF_LBC),
+ FSL_SET_LAW(0xc0000000, LAW_SIZE_256M, LAW_TRGT_IF_PCI),
+ FSL_SET_LAW(0xe1000000, LAW_SIZE_64K, LAW_TRGT_IF_PCI),
+};
+
+int num_law_entries = ARRAY_SIZE(law_table);
diff --git a/arch/powerpc/boards/owc-da923rc/nand.c b/arch/powerpc/boards/owc-da923rc/nand.c
new file mode 100644
index 0000000000..550d790570
--- /dev/null
+++ b/arch/powerpc/boards/owc-da923rc/nand.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2013 GE Intelligent Platforms, Inc
+ * (C) Copyright 2008 Wolfgang Grandegger <wg@denx.de>
+ * (C) Copyright 2006
+ * Thomas Waehner, TQ-System GmbH, thomas.waehner@tqs.de.
+ *
+ * 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.
+ *
+ * This code only cares about setting up the UPM state machine for Linux
+ * to use the NAND.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <asm/io.h>
+#include <asm/fsl_lbc.h>
+#include <mach/immap_85xx.h>
+
+/* NAND UPM tables for a 25Mhz bus frequency. */
+static const u32 upm_patt_25[] = {
+ /* Single read data */
+ 0xcff02c30, 0x0ff02c30, 0x0ff02c34, 0x0ff32c30,
+ 0xfff32c31, 0xfff32c30, 0xfffffc30, 0xfffffc30,
+ /* UPM Read Burst RAM array entry -> NAND Write CMD */
+ 0xcfaf2c30, 0x0faf2c30, 0x0faf2c30, 0x0fff2c34,
+ 0xfffffc31, 0xfffffc30, 0xfffffc30, 0xfffffc30,
+ /* UPM Read Burst RAM array entry -> NAND Write ADDR */
+ 0xcfa3ec30, 0x0fa3ec30, 0x0fa3ec30, 0x0ff3ec34,
+ 0xfff3ec31, 0xfffffc30, 0xfffffc30, 0xfffffc30,
+ /* UPM Write Single RAM array entry -> NAND Write Data */
+ 0x0ff32c30, 0x0fa32c30, 0x0fa32c34, 0x0ff32c30,
+ 0xfff32c31, 0xfff0fc30, 0xfff0fc30, 0xfff0fc30,
+ /* Default */
+ 0xfff3fc30, 0xfff3fc30, 0xfff6fc30, 0xfffcfc30,
+ 0xfffcfc30, 0xfffcfc30, 0xfffcfc30, 0xfffcfc30,
+ 0xfffcfc30, 0xfffcfc30, 0xfffcfc30, 0xfffcfc30,
+ 0xfffdfc30, 0xfffffc30, 0xfffffc30, 0xfffffc31,
+ 0xfffffc30, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+};
+
+static void upm_write(uint8_t addr, uint32_t val)
+{
+ void __iomem *lbc = LBC_BASE_ADDR;
+
+ out_be32(lbc + FSL_LBC_MDR_OFFSET, val);
+ clrsetbits_be32(lbc + FSL_LBC_MAMR_OFFSET, MxMR_MAD_MSK,
+ MxMR_OP_WARR | (addr & MxMR_MAD_MSK));
+
+ /* dummy access to perform write */
+ out_8(IOMEM(0xfc000000), 0);
+ clrbits_be32(lbc + FSL_LBC_MAMR_OFFSET, MxMR_OP_WARR);
+}
+
+static int board_nand_init(void)
+{
+ void __iomem *mxmr = IOMEM(LBC_BASE_ADDR + FSL_LBC_MAMR_OFFSET);
+ int j;
+
+ /* Base register CS2:
+ * - 0xfc000000
+ * - 8-bit data width
+ * - UPMA
+ */
+ fsl_set_lbc_br(2, BR_PHYS_ADDR(0xfc000000) | BR_PS_8 | BR_MS_UPMA |
+ BR_V);
+
+ /*
+ * Otions register:
+ * - 32KB window.
+ * - Buffer control disabled.
+ * - External address latch delay.
+ */
+ fsl_set_lbc_or(2, 0xffffe001);
+
+ for (j = 0; j < 64; j++)
+ upm_write(j, upm_patt_25[j]);
+
+ out_be32(mxmr, MxMR_OP_NORM | MxMR_GPL_x4DIS);
+
+ return 0;
+}
+
+device_initcall(board_nand_init);
diff --git a/arch/powerpc/boards/owc-da923rc/product_data.c b/arch/powerpc/boards/owc-da923rc/product_data.c
new file mode 100644
index 0000000000..5135afdd2a
--- /dev/null
+++ b/arch/powerpc/boards/owc-da923rc/product_data.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2013 GE Intelligent Platforms Inc.
+ * Copyright 2019 Abaco Systems 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.
+ *
+ * Retrieve and check the product data.
+ */
+
+#include <common.h>
+#include <crc.h>
+#include <i2c/i2c.h>
+#include <mach/immap_85xx.h>
+#include <mach/fsl_i2c.h>
+#include "product_data.h"
+
+static int owc_pd_header_check(unsigned short header)
+{
+ if (header != 0xa5a5)
+ return -1;
+ else
+ return 0;
+}
+
+static int owc_is_data_valid(struct owc_product_data *v)
+{
+ int crc, ret = 0;
+ const unsigned char *p = (const unsigned char *)v;
+
+ if (owc_pd_header_check(v->v1.pdh.tag))
+ return -1;
+
+ switch (v->v1.pdh.version) {
+ case PDVERSION_V1:
+ case PDVERSION_V1bis:
+ crc = crc32(0, p, sizeof(struct product_data_v1) - 4);
+ if (crc != v->v1.crc32)
+ ret = -1;
+ break;
+ case PDVERSION_V2:
+ crc = crc32(0, p, sizeof(struct product_data_v2) - 4);
+ if (crc != v->v2.crc32)
+ ret = -1;
+ break;
+ default:
+ ret = -1;
+ }
+
+ return ret;
+}
+
+int owc_get_product_data(struct owc_product_data *productp)
+{
+ struct i2c_adapter *adapter;
+ struct i2c_client client;
+ unsigned int width = 0;
+ int ret;
+
+ adapter = i2c_get_adapter(0);
+ client.addr = 0x51;
+ client.adapter = adapter;
+ ret = i2c_read_reg(&client, 0, (uint8_t *) productp,
+ sizeof(unsigned short));
+
+ /* If there is no valid header, it may be a 16-bit eeprom. */
+ if (owc_pd_header_check(productp->v1.pdh.tag))
+ width = I2C_ADDR_16_BIT;
+
+ ret = i2c_read_reg(&client, width, (uint8_t *) productp,
+ sizeof(struct owc_product_data));
+
+ if (ret == sizeof(struct owc_product_data))
+ ret = owc_is_data_valid(productp);
+
+ return ret;
+}
diff --git a/arch/powerpc/boards/owc-da923rc/product_data.h b/arch/powerpc/boards/owc-da923rc/product_data.h
new file mode 100644
index 0000000000..cbbb8d377f
--- /dev/null
+++ b/arch/powerpc/boards/owc-da923rc/product_data.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2013 GE Intelligent Platforms, Inc.
+ * Copyright 2019 Abaco Systems, Inc.
+ *
+ * The product data structure and function prototypes.
+ *
+ * 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.
+ */
+
+struct board_info {
+ uint32_t bid;
+ uint32_t rev;
+};
+
+#define MAX_MAC 8
+enum product_data_version {
+ PDVERSION_V1 = 1,
+ PDVERSION_V1bis = 0x10,
+ PDVERSION_V2 = 2,
+ PDVERSION_MAX = PDVERSION_V2,
+};
+
+struct __attribute__ ((__packed__)) product_data_header {
+ unsigned short tag;
+ unsigned char version;
+ unsigned short len;
+};
+
+struct __attribute__ ((__packed__)) mac {
+ unsigned char count;
+ unsigned char mac[MAX_MAC][6];
+};
+
+struct __attribute__ ((__packed__)) product_data_v1 {
+ struct product_data_header pdh;
+ struct mac mac;
+ int crc32;
+};
+
+struct __attribute__ ((__packed__)) product_data_v2 {
+ struct product_data_header pdh;
+ struct mac mac;
+ char sn[8];
+ int crc32;
+};
+
+struct __attribute__ ((__packed__)) owc_product_data {
+ union {
+ struct product_data_v1 v1;
+ struct product_data_v2 v2;
+ };
+};
+
+extern int owc_get_product_data(struct owc_product_data *productp);
+extern void da923rc_boardinfo_get(struct board_info *bi);
diff --git a/arch/powerpc/boards/owc-da923rc/tlb.c b/arch/powerpc/boards/owc-da923rc/tlb.c
new file mode 100644
index 0000000000..889e2743b7
--- /dev/null
+++ b/arch/powerpc/boards/owc-da923rc/tlb.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2013 GE Intelligent Platforms, 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.
+ */
+
+#include <common.h>
+#include <mach/mmu.h>
+
+struct fsl_e_tlb_entry tlb_table[] = {
+ /* TLB 0 - for temp stack in cache */
+ FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR, CFG_INIT_RAM_ADDR,
+ MAS3_SX | MAS3_SW | MAS3_SR, 0,
+ 0, 0, BOOKE_PAGESZ_4K, 0),
+ FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR + (4 * 1024),
+ CFG_INIT_RAM_ADDR + (4 * 1024),
+ MAS3_SX | MAS3_SW | MAS3_SR, 0,
+ 0, 0, BOOKE_PAGESZ_4K, 0),
+ FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR + (8 * 1024),
+ CFG_INIT_RAM_ADDR + (8 * 1024),
+ MAS3_SX | MAS3_SW | MAS3_SR, 0,
+ 0, 0, BOOKE_PAGESZ_4K, 0),
+ FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR + (12 * 1024),
+ CFG_INIT_RAM_ADDR + (12 * 1024),
+ MAS3_SX | MAS3_SW | MAS3_SR, 0,
+ 0, 0, BOOKE_PAGESZ_4K, 0),
+ /*
+ * TLB 0/1: 2x16M Cache inhibited, guarded
+ * CPLD and NAND in cache-inhibited area.
+ */
+ FSL_SET_TLB_ENTRY(1, BOOT_BLOCK, BOOT_BLOCK,
+ MAS3_SX | MAS3_SW | MAS3_SR,
+ MAS2_W | MAS2_I | MAS2_G | MAS2_M,
+ 0, 0, BOOKE_PAGESZ_16M, 1),
+ FSL_SET_TLB_ENTRY(1, BOOT_BLOCK + 0x1000000,
+ BOOT_BLOCK + 0x1000000,
+ MAS3_SX | MAS3_SW | MAS3_SR,
+ MAS2_W | MAS2_I | MAS2_G | MAS2_M,
+ 0, 1, BOOKE_PAGESZ_16M, 1),
+ /*
+ * The boot flash is mapped with the cache enabled.
+ * TLB 2/3: 2x16M Cacheable Write-through, guarded
+ */
+ FSL_SET_TLB_ENTRY(1, BOOT_BLOCK + (2 * 0x1000000),
+ BOOT_BLOCK + (2 * 0x1000000),
+ MAS3_SX | MAS3_SW | MAS3_SR,
+ MAS2_W | MAS2_G | MAS2_M,
+ 0, 2, BOOKE_PAGESZ_16M, 1),
+ FSL_SET_TLB_ENTRY(1, BOOT_BLOCK + (3 * 0x1000000),
+ BOOT_BLOCK + (3 * 0x1000000),
+ MAS3_SX | MAS3_SW | MAS3_SR,
+ MAS2_W | MAS2_G | MAS2_M,
+ 0, 3, BOOKE_PAGESZ_16M, 1),
+
+ FSL_SET_TLB_ENTRY(1, CFG_CCSRBAR, CFG_CCSRBAR_PHYS,
+ MAS3_SX | MAS3_SW | MAS3_SR,
+ MAS2_I | MAS2_G,
+ 0, 4, BOOKE_PAGESZ_64M, 1),
+};
+
+int num_tlb_entries = ARRAY_SIZE(tlb_table);
diff --git a/arch/powerpc/boards/pcm030/Makefile b/arch/powerpc/boards/pcm030/Makefile
new file mode 100644
index 0000000000..95dd061043
--- /dev/null
+++ b/arch/powerpc/boards/pcm030/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-y += pcm030.o eeprom.o
+extra-y += barebox.lds
diff --git a/arch/powerpc/boards/pcm030/barebox.lds.S b/arch/powerpc/boards/pcm030/barebox.lds.S
new file mode 100644
index 0000000000..146b63fe88
--- /dev/null
+++ b/arch/powerpc/boards/pcm030/barebox.lds.S
@@ -0,0 +1,124 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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.
+ *
+ */
+
+#include <asm/barebox.lds.h>
+
+OUTPUT_ARCH(BAREBOX_OUTPUT_ARCH)
+ENTRY(_start)
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ . = TEXT_BASE;
+
+ .text :
+ {
+ _text = .;
+ _stext = .;
+ arch/powerpc/mach-mpc5xxx/start.o (.text)
+ *(.text*)
+ *(.got1*)
+ . = ALIGN(16);
+ *(.rodata*)
+ *(.rodata1*)
+ *(.rodata.str1.4)
+ RO_DATA_SECTION
+ }
+
+ /* Read-only sections, merged into text segment: */
+/*
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+*/
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x0FFF) & 0xFFFFF000;
+ _etext = .;
+ PROVIDE (erotext = .);
+ _sdata = .;
+ .reloc :
+ {
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+ __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+
+ .data :
+ {
+ *(.data*)
+ *(.data1*)
+ *(.sdata*)
+ *(.sdata2*)
+ *(.dynamic*)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(4096);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(4096);
+ __init_end = .;
+
+ __init_size = __init_end - _start;
+
+ __bss_start = .;
+ .bss :
+ {
+ *(.sbss*) *(.scommon*)
+ *(.dynbss*)
+ *(.bss*)
+ *(COMMON)
+ }
+ __bss_stop = .;
+ _end = . ;
+ PROVIDE (end = .);
+}
diff --git a/arch/powerpc/boards/pcm030/config.h b/arch/powerpc/boards/pcm030/config.h
new file mode 100644
index 0000000000..24cf9dc4ff
--- /dev/null
+++ b/arch/powerpc/boards/pcm030/config.h
@@ -0,0 +1,30 @@
+/*
+ * (C) Copyright 2003-2005
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2006
+ * Eric Schumann, Phytec Messatechnik GmbH
+ *
+ * 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.
+ *
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <mach/mpc5xxx.h>
+
+#define CFG_MPC5XXX_CLKIN 33333000 /* ... running at 33.333MHz */
+
+#define CFG_HID0_INIT HID0_ICE | HID0_ICFI
+#define CFG_HID0_FINAL HID0_ICE
+
+#endif /* __CONFIG_H */
diff --git a/arch/powerpc/boards/pcm030/eeprom.c b/arch/powerpc/boards/pcm030/eeprom.c
new file mode 100644
index 0000000000..aa00f361cd
--- /dev/null
+++ b/arch/powerpc/boards/pcm030/eeprom.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2015 Juergen Borleis <kernel@pengutronix.de>
+ *
+ * Based on code from:
+ * Copyright (C) 2013 Jan Luebbe <j.luebbe@pengutronix.de>
+ *
+ * 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.
+ */
+#include <common.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fs.h>
+#include <globalvar.h>
+#include <xfuncs.h>
+#include <init.h>
+#include <net.h>
+
+#define PCM030_EEPROM_DEVICE "/dev/eeprom0"
+
+/*
+ * The first 2048 bytes contain the U-Boot environment shipped with the boards.
+ * After that an area begins where some board specific and partially unique data
+ * is stored. All of this data is plain test, string delimiter is the semicolon.
+ * the last string terminates with a '\0'.
+ * One example found in the 'product' area: PCM-030-02REI;017822;0050C2875974\0
+ * The first string seems to be the product type, the second string some kind
+ * of serial number and the last string the boards unique MAC.
+ */
+struct pcm030_eeprom {
+ char env[0x800]; /* u-boot environment */
+ char product[0x80]; /* <product>;<serno>;<mac>\0 */
+} __attribute__((packed));
+
+static void pcm030_read_factory_data(const struct pcm030_eeprom *buf)
+{
+ unsigned u, l;
+ char *board, *serial;
+ char *full_mac = "xx:xx:xx:xx:xx:xx";
+ u8 enetaddr[6];
+
+ u = 0;
+
+ for (l = 0; (l + u) < sizeof(buf->product); l++) {
+ if (buf->product[u + l] != ';')
+ continue;
+ board = xstrndup(&buf->product[u], l);
+ u += l + 1;
+ globalvar_add_simple("model.type", board);
+ free(board);
+ }
+
+ for (l = 0; (l + u) < sizeof(buf->product); l++) {
+ if (buf->product[u + l] != ';')
+ continue;
+ serial = xstrndup(&buf->product[u], l);
+ u += l + 1;
+ globalvar_add_simple("model.serial", serial);
+ free(serial);
+ }
+
+ /* for the MAC do a simple duck test */
+ if (buf->product[u] != ';' && buf->product[u + 12] == '\0') {
+ full_mac[0] = buf->product[u + 0];
+ full_mac[1] = buf->product[u + 1];
+ full_mac[3] = buf->product[u + 2];
+ full_mac[4] = buf->product[u + 3];
+ full_mac[6] = buf->product[u + 4];
+ full_mac[7] = buf->product[u + 5];
+ full_mac[9] = buf->product[u + 6];
+ full_mac[10] = buf->product[u + 7];
+ full_mac[12] = buf->product[u + 8];
+ full_mac[13] = buf->product[u + 9];
+ full_mac[15] = buf->product[u + 10];
+ full_mac[16] = buf->product[u + 11];
+ string_to_ethaddr(full_mac, enetaddr);
+ eth_register_ethaddr(0, enetaddr);
+ return;
+ }
+
+ printf("EEPROM contains no ethernet MAC\n");
+}
+
+static int pcm030_eeprom_read(void)
+{
+ int fd, ret;
+ struct pcm030_eeprom *buf;
+
+ fd = open(PCM030_EEPROM_DEVICE, O_RDONLY);
+ if (fd < 0) {
+ perror("failed to open " PCM030_EEPROM_DEVICE);
+ return fd;
+ }
+
+ buf = xmalloc(sizeof(struct pcm030_eeprom));
+
+ ret = pread(fd, buf, sizeof(struct pcm030_eeprom), 0);
+ if (ret < sizeof(struct pcm030_eeprom)) {
+ perror("failed to read " PCM030_EEPROM_DEVICE);
+ goto out;
+ }
+
+ pcm030_read_factory_data(buf);
+ ret = 0;
+out:
+ free(buf);
+ close(fd);
+
+ return ret;
+}
+late_initcall(pcm030_eeprom_read);
diff --git a/arch/powerpc/boards/pcm030/env/init/mtdparts-nor b/arch/powerpc/boards/pcm030/env/init/mtdparts-nor
new file mode 100644
index 0000000000..44c07ead21
--- /dev/null
+++ b/arch/powerpc/boards/pcm030/env/init/mtdparts-nor
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+mtdparts="512k(nor0.bareboxlow),4M(nor0.kernel),512k(nor0.oftree),26M(nor0.root),512k(nor0.barebox),512k(nor0.bareboxenv)"
+kernelname="physmap-flash.0"
+
+mtdparts-add -d nor0 -k ${kernelname} -p ${mtdparts}
diff --git a/arch/powerpc/boards/pcm030/env/nv/linux.bootargs.console b/arch/powerpc/boards/pcm030/env/nv/linux.bootargs.console
new file mode 100644
index 0000000000..31ce0e71eb
--- /dev/null
+++ b/arch/powerpc/boards/pcm030/env/nv/linux.bootargs.console
@@ -0,0 +1 @@
+console=ttyPSC0,115200
diff --git a/arch/powerpc/boards/pcm030/mt46v32m16-75.h b/arch/powerpc/boards/pcm030/mt46v32m16-75.h
new file mode 100644
index 0000000000..5509a11f52
--- /dev/null
+++ b/arch/powerpc/boards/pcm030/mt46v32m16-75.h
@@ -0,0 +1,39 @@
+/*
+ * (C) Copyright 2004
+ * Mark Jonas, Freescale Semiconductor, mark.jonas@motorola.com.
+ *
+ * Eric Schumann, Phytec Messtechnik
+ * adapted for mt46v32m16-75 DDR-RAM
+ *
+ * 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.
+ *
+ */
+
+#define SDRAM_DDR 1 /* is DDR */
+
+/* Settings for XLB = 132 MHz */
+#define SDRAM_MODE 0x018D0000
+#define SDRAM_EMODE 0x40090000
+#define SDRAM_CONTROL 0x715f0f00
+#define SDRAM_CONFIG1 0x73722930
+#define SDRAM_CONFIG2 0x47770000
+
+
+/* Settings for XLB = 99 MHz */
+/*
+#define SDRAM_MODE 0x008D0000
+#define SDRAM_EMODE 0x40090000
+#define SDRAM_CONTROL 0x714b0f00
+#define SDRAM_CONFIG1 0x63611730
+#define SDRAM_CONFIG2 0x47670000
+*/
+
+#define SDRAM_TAPDELAY 0x10000000 /* reserved Bit in MPC5200 B3-Step */
diff --git a/arch/powerpc/boards/pcm030/pcm030.c b/arch/powerpc/boards/pcm030/pcm030.c
new file mode 100644
index 0000000000..2bdbc6695d
--- /dev/null
+++ b/arch/powerpc/boards/pcm030/pcm030.c
@@ -0,0 +1,210 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2004
+ * Mark Jonas, Freescale Semiconductor, mark.jonas@motorola.com.
+ *
+ * (C) Copyright 2006
+ * Eric Schumann, Phytec Messtechnik GmbH
+ *
+ * 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.
+ *
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <init.h>
+#include <platform_data/eth-fec.h>
+#include <types.h>
+#include <memory.h>
+#include <linux/sizes.h>
+#include <linux/stat.h>
+#include <asm/io.h>
+#include <fs.h>
+#include <i2c/i2c.h>
+
+static struct fec_platform_data fec_info = {
+ .xcv_type = PHY_INTERFACE_MODE_MII,
+};
+
+static struct i2c_board_info pcm030_i2c_devices[] = {
+ { I2C_BOARD_INFO("pcf8563", 0x51), },
+ { I2C_BOARD_INFO("24c32", 0x52), },
+};
+
+struct i2c_platform_data pcm030_i2c_plat = {
+ .bitrate = 100000,
+};
+
+static int devices_init (void)
+{
+ struct stat s;
+ int ret;
+
+ /*
+ * Flash can be 16MB or 32MB, setup for the last 32MB no matter
+ * what we find later.
+ */
+ mpc5200_setup_cs(MPC5200_BOOTCS, 0xfe000000, SZ_32M, 0x0008fd00);
+ add_cfi_flash_device(DEVICE_ID_DYNAMIC, 0xfe000000, 32 * 1024 * 1024, 0);
+
+ add_generic_device("fec_mpc5xxx", DEVICE_ID_DYNAMIC, NULL, MPC5XXX_FEC, 0x200,
+ IORESOURCE_MEM, &fec_info);
+ i2c_register_board_info(0, pcm030_i2c_devices, ARRAY_SIZE(pcm030_i2c_devices));
+ add_generic_device("i2c-fsl", DEVICE_ID_DYNAMIC, NULL, MPC5XXX_I2C2, 0x100,
+ IORESOURCE_MEM, &pcm030_i2c_plat);
+
+ ret = stat("/dev/nor0", &s);
+ if (ret)
+ return 0;
+
+ devfs_add_partition("nor0", s.st_size - SZ_1M, SZ_512K, DEVFS_PARTITION_FIXED, "self0");
+ devfs_add_partition("nor0", s.st_size - SZ_512K, SZ_512K, DEVFS_PARTITION_FIXED, "env0");
+
+ return 0;
+}
+
+device_initcall(devices_init);
+
+static int console_init(void)
+{
+ barebox_set_model("Phytec phyCORE MPC5200 tiny");
+ barebox_set_hostname("mpc5200");
+
+ add_generic_device("mpc5xxx_serial", DEVICE_ID_DYNAMIC, NULL, MPC5XXX_PSC3, 0x200,
+ IORESOURCE_MEM, NULL);
+ add_generic_device("mpc5xxx_serial", DEVICE_ID_DYNAMIC, NULL, MPC5XXX_PSC6, 0x200,
+ IORESOURCE_MEM, NULL);
+ return 0;
+}
+
+console_initcall(console_init);
+
+static int mem_init(void)
+{
+ unsigned long sdramsize;
+
+ sdramsize = mpc5200_get_sdram_size(0) + mpc5200_get_sdram_size(1);
+
+ barebox_add_memory_bank("ram0", 0x0, sdramsize);
+
+ return 0;
+}
+mem_initcall(mem_init);
+
+#include "mt46v32m16-75.h"
+
+static void sdram_start (int hi_addr)
+{
+ long hi_addr_bit = hi_addr ? 0x01000000 : 0;
+
+ /* unlock mode register */
+ *(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000000 | hi_addr_bit;
+ __asm__ volatile ("sync");
+
+ /* precharge all banks */
+ *(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000002 | hi_addr_bit;
+ __asm__ volatile ("sync");
+
+#if SDRAM_DDR
+ /* set mode register: extended mode */
+ *(vu_long *)MPC5XXX_SDRAM_MODE = SDRAM_EMODE;
+ __asm__ volatile ("sync");
+
+ /* set mode register: reset DLL */
+ *(vu_long *)MPC5XXX_SDRAM_MODE = SDRAM_MODE | 0x04000000;
+ __asm__ volatile ("sync");
+#endif
+
+ /* precharge all banks */
+ *(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000002 | hi_addr_bit;
+ __asm__ volatile ("sync");
+
+ /* auto refresh */
+ *(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000004 | hi_addr_bit;
+ __asm__ volatile ("sync");
+
+ /* set mode register */
+ *(vu_long *)MPC5XXX_SDRAM_MODE = SDRAM_MODE;
+ __asm__ volatile ("sync");
+
+ /* normal operation */
+ *(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | hi_addr_bit;
+ __asm__ volatile ("sync");
+}
+
+/* Called from assembly */
+void initdram(int board_type);
+
+void initdram (int board_type)
+{
+ ulong dramsize = 0;
+
+ ulong test1, test2;
+
+ /* Setup pin multiplexing */
+
+ /* PSC6=UART, PSC3=UART ; Ether=100MBit with MD */
+ *(vu_long *)MPC5XXX_GPS_PORT_CONFIG = 0x00559c10;
+ *(vu_long *)MPC5XXX_CS_BURST = 0x00000000;
+ *(vu_long *)MPC5XXX_CS_DEADCYCLE = 0x33333333;
+
+ /*
+ * Make USB work due to the special base crystal frequency:
+ * 33,3330MHz * 16 = 533,328MHz main clock, but should be 528 MHz Clock
+ */
+ out_be32((void *)MPC5XXX_CDM_48_FDC, 0x00015555);
+
+ mpc5200_setup_bus_clocks(1, 4);
+
+ if (get_pc() > SZ_128M) {
+ /* setup SDRAM chip selects */
+ *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0x0000001b;/* 256MB at 0x0 */
+ *(vu_long *)MPC5XXX_SDRAM_CS1CFG = 0x10000000;/* disabled */
+ __asm__ volatile ("sync");
+
+ /* setup config registers */
+ *(vu_long *)MPC5XXX_SDRAM_CONFIG1 = SDRAM_CONFIG1;
+ *(vu_long *)MPC5XXX_SDRAM_CONFIG2 = SDRAM_CONFIG2;
+ __asm__ volatile ("sync");
+
+#if SDRAM_DDR && SDRAM_TAPDELAY
+ /* set tap delay */
+ *(vu_long *)MPC5XXX_CDM_PORCFG = SDRAM_TAPDELAY;
+ __asm__ volatile ("sync");
+#endif
+
+ /* find RAM size using SDRAM CS0 only */
+ sdram_start(0);
+ test1 = get_ram_size((ulong *)0, 0x10000000);
+ sdram_start(1);
+ test2 = get_ram_size((ulong *)0, 0x10000000);
+ if (test1 > test2) {
+ sdram_start(0);
+ dramsize = test1;
+ } else {
+ dramsize = test2;
+ }
+
+ /* memory smaller than 1MB is impossible */
+ if (dramsize < (1 << 20)) {
+ dramsize = 0;
+ }
+
+ /* set SDRAM CS0 size according to the amount of RAM found */
+ if (dramsize > 0) {
+ *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0x13 + __builtin_ffs(dramsize >> 20) - 1;
+ } else {
+ *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0; /* disabled */
+ }
+ }
+}
diff --git a/arch/powerpc/configs/owc_da923rc_defconfig b/arch/powerpc/configs/owc_da923rc_defconfig
new file mode 100644
index 0000000000..183ddb15f9
--- /dev/null
+++ b/arch/powerpc/configs/owc_da923rc_defconfig
@@ -0,0 +1,51 @@
+CONFIG_ARCH_MPC85XX=y
+CONFIG_DA923RC=y
+CONFIG_BAREBOX_MAX_IMAGE_SIZE=0x80000
+CONFIG_MALLOC_SIZE=0x4000000
+CONFIG_RELOCATABLE=y
+CONFIG_PROMPT="OWBOOT> "
+CONFIG_BAUDRATE=9600
+CONFIG_GLOB=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+CONFIG_LONGHELP=y
+CONFIG_CMD_IOMEM=y
+# CONFIG_CMD_VERSION is not set
+CONFIG_CMD_GO=y
+CONFIG_CMD_RESET=y
+CONFIG_CMD_PARTITION=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_LOADENV=y
+CONFIG_CMD_PRINTENV=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_READLINK=y
+CONFIG_CMD_UNCOMPRESS=y
+CONFIG_CMD_GETOPT=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_MIITOOL=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_TFTP=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_FLASH=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_OFTREE=y
+CONFIG_NET=y
+CONFIG_DRIVER_SERIAL_NS16550=y
+CONFIG_DRIVER_NET_GIANFAR=y
+# CONFIG_SPI is not set
+CONFIG_I2C=y
+CONFIG_I2C_IMX=y
+CONFIG_MTD=y
+CONFIG_DRIVER_CFI=y
+# CONFIG_DRIVER_CFI_BANK_WIDTH_1 is not set
+# CONFIG_DRIVER_CFI_BANK_WIDTH_4 is not set
+CONFIG_CFI_BUFFER_WRITE=y
+CONFIG_MTD_UBI=y
+CONFIG_FS_TFTP=y
+CONFIG_FS_UBIFS=y
+CONFIG_FS_UBIFS_COMPRESSION_LZO=y
+CONFIG_ZLIB=y
+CONFIG_BZLIB=y
diff --git a/arch/powerpc/configs/p1010rdb_defconfig b/arch/powerpc/configs/p1010rdb_defconfig
new file mode 100644
index 0000000000..73c02c2e7f
--- /dev/null
+++ b/arch/powerpc/configs/p1010rdb_defconfig
@@ -0,0 +1,39 @@
+CONFIG_ARCH_MPC85XX=y
+CONFIG_MALLOC_SIZE=0x4000000
+CONFIG_RELOCATABLE=y
+CONFIG_GLOB=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+CONFIG_BOOTM_VERBOSE=y
+CONFIG_LONGHELP=y
+CONFIG_CMD_IOMEM=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_RESET=y
+CONFIG_CMD_PARTITION=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_LOADENV=y
+CONFIG_CMD_PRINTENV=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_MIITOOL=y
+CONFIG_CMD_TFTP=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_FLASH=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_BAREBOX_UPDATE=y
+CONFIG_CMD_OFTREE=y
+CONFIG_NET=y
+CONFIG_DRIVER_SERIAL_NS16550=y
+CONFIG_DRIVER_NET_GIANFAR=y
+CONFIG_I2C=y
+CONFIG_I2C_IMX=y
+CONFIG_MTD=y
+CONFIG_DRIVER_CFI=y
+# CONFIG_DRIVER_CFI_BANK_WIDTH_1 is not set
+# CONFIG_DRIVER_CFI_BANK_WIDTH_4 is not set
+CONFIG_CFI_BUFFER_WRITE=y
+CONFIG_FS_TFTP=y
+CONFIG_ZLIB=y
+CONFIG_BZLIB=y
diff --git a/arch/powerpc/configs/p1022ds_defconfig b/arch/powerpc/configs/p1022ds_defconfig
new file mode 100644
index 0000000000..fce3eabaf9
--- /dev/null
+++ b/arch/powerpc/configs/p1022ds_defconfig
@@ -0,0 +1,39 @@
+CONFIG_ARCH_MPC85XX=y
+CONFIG_P1022DS=y
+CONFIG_MALLOC_SIZE=0x4000000
+CONFIG_RELOCATABLE=y
+CONFIG_GLOB=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+CONFIG_BOOTM_VERBOSE=y
+CONFIG_LONGHELP=y
+CONFIG_CMD_IOMEM=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_RESET=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_LOADENV=y
+CONFIG_CMD_PRINTENV=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_MIITOOL=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_TFTP=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_FLASH=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_BAREBOX_UPDATE=y
+CONFIG_CMD_OFTREE=y
+CONFIG_NET=y
+CONFIG_DRIVER_SERIAL_NS16550=y
+CONFIG_DRIVER_NET_GIANFAR=y
+CONFIG_I2C=y
+CONFIG_I2C_IMX=y
+CONFIG_MTD=y
+CONFIG_DRIVER_CFI=y
+# CONFIG_DRIVER_CFI_INTEL is not set
+# CONFIG_DRIVER_CFI_BANK_WIDTH_1 is not set
+# CONFIG_DRIVER_CFI_BANK_WIDTH_4 is not set
+CONFIG_FS_TFTP=y
+CONFIG_ZLIB=y
+CONFIG_BZLIB=y
diff --git a/arch/powerpc/configs/p2020rdb_defconfig b/arch/powerpc/configs/p2020rdb_defconfig
new file mode 100644
index 0000000000..6cc0328727
--- /dev/null
+++ b/arch/powerpc/configs/p2020rdb_defconfig
@@ -0,0 +1,42 @@
+CONFIG_ARCH_MPC85XX=y
+CONFIG_P2020RDB=y
+CONFIG_MALLOC_SIZE=0x2800000
+CONFIG_RELOCATABLE=y
+CONFIG_GLOB=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+CONFIG_LONGHELP=y
+CONFIG_CMD_IOMEM=y
+# CONFIG_CMD_VERSION is not set
+CONFIG_CMD_GO=y
+CONFIG_CMD_RESET=y
+CONFIG_CMD_PARTITION=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_LOADENV=y
+CONFIG_CMD_PRINTENV=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_READLINK=y
+CONFIG_CMD_UNCOMPRESS=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_MIITOOL=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_TFTP=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_FLASH=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_OFTREE=y
+CONFIG_NET=y
+CONFIG_DRIVER_SERIAL_NS16550=y
+CONFIG_DRIVER_NET_GIANFAR=y
+CONFIG_I2C=y
+CONFIG_I2C_IMX=y
+CONFIG_MTD=y
+CONFIG_DRIVER_CFI=y
+# CONFIG_DRIVER_CFI_INTEL is not set
+# CONFIG_DRIVER_CFI_BANK_WIDTH_1 is not set
+# CONFIG_DRIVER_CFI_BANK_WIDTH_4 is not set
+CONFIG_FS_TFTP=y
+CONFIG_ZLIB=y
+CONFIG_BZLIB=y
diff --git a/arch/powerpc/configs/pcm030_defconfig b/arch/powerpc/configs/pcm030_defconfig
new file mode 100644
index 0000000000..b97a8d5d0c
--- /dev/null
+++ b/arch/powerpc/configs/pcm030_defconfig
@@ -0,0 +1,46 @@
+CONFIG_TEXT_BASE=0x3e00000
+CONFIG_MALLOC_SIZE=0x1000000
+CONFIG_HUSH_FANCY_PROMPT=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+CONFIG_BOOTM_SHOW_TYPE=y
+CONFIG_PARTITION=y
+CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
+CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/powerpc/boards/pcm030/env"
+CONFIG_LONGHELP=y
+CONFIG_CMD_IOMEM=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_REGINFO=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_RESET=y
+CONFIG_CMD_UIMAGE=y
+CONFIG_CMD_PARTITION=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_LOADENV=y
+CONFIG_CMD_MAGICVAR=y
+CONFIG_CMD_MAGICVAR_HELP=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_UNCOMPRESS=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_TFTP=y
+CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_CRC=y
+CONFIG_CMD_CRC_CMP=y
+CONFIG_CMD_FLASH=y
+CONFIG_CMD_OFTREE=y
+CONFIG_CMD_TIME=y
+CONFIG_NET=y
+CONFIG_DRIVER_NET_MPC5200=y
+CONFIG_I2C=y
+CONFIG_I2C_IMX=y
+CONFIG_MTD=y
+CONFIG_DRIVER_CFI=y
+CONFIG_CFI_BUFFER_WRITE=y
+CONFIG_EEPROM_AT24=y
+CONFIG_FS_TFTP=y
+CONFIG_ZLIB=y
diff --git a/arch/powerpc/cpu-85xx/Makefile b/arch/powerpc/cpu-85xx/Makefile
new file mode 100644
index 0000000000..c7c5c8a006
--- /dev/null
+++ b/arch/powerpc/cpu-85xx/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-y += traps.o
+obj-y += tlb.o
+obj-$(CONFIG_MMU) += mmu.o
+extra-y += start.o
+extra-y += resetvec.o
diff --git a/arch/powerpc/cpu-85xx/fixed_ivor.S b/arch/powerpc/cpu-85xx/fixed_ivor.S
new file mode 100644
index 0000000000..2cdb8d414e
--- /dev/null
+++ b/arch/powerpc/cpu-85xx/fixed_ivor.S
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * Kumar Gala <kumar.gala@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ */
+
+/* This file is intended to be included by other asm code since
+ * we will want to execute this on both the primary core when
+ * it does a bootm and the secondary core's that get released
+ * out of the spin table.
+ */
+
+#define SET_IVOR(vector_number, vector_offset) \
+ li r3,vector_offset@l; \
+ mtspr SPRN_IVOR##vector_number,r3;
+
+#define SET_GIVOR(vector_number, vector_offset) \
+ li r3,vector_offset@l; \
+ mtspr SPRN_GIVOR##vector_number,r3;
+
+ SET_IVOR(0, 0x020) /* Critical Input */
+ SET_IVOR(1, 0x000) /* Machine Check */
+ SET_IVOR(2, 0x060) /* Data Storage */
+ SET_IVOR(3, 0x080) /* Instruction Storage */
+ SET_IVOR(4, 0x0a0) /* External Input */
+ SET_IVOR(5, 0x0c0) /* Alignment */
+ SET_IVOR(6, 0x0e0) /* Program */
+ SET_IVOR(7, 0x100) /* FP Unavailable */
+ SET_IVOR(8, 0x120) /* System Call */
+ SET_IVOR(9, 0x140) /* Auxiliary Processor Unavailable */
+ SET_IVOR(10, 0x160) /* Decrementer */
+ SET_IVOR(11, 0x180) /* Fixed Interval Timer */
+ SET_IVOR(12, 0x1a0) /* Watchdog Timer */
+ SET_IVOR(13, 0x1c0) /* Data TLB Error */
+ SET_IVOR(14, 0x1e0) /* Instruction TLB Error */
+ SET_IVOR(15, 0x040) /* Debug */
+
+ /* e500v1 & e500v2 only */
+ 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/powerpc/cpu-85xx/mmu.c b/arch/powerpc/cpu-85xx/mmu.c
new file mode 100644
index 0000000000..b484acbf80
--- /dev/null
+++ b/arch/powerpc/cpu-85xx/mmu.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2014 GE Intelligent Platforms, 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.
+ */
+
+#include <common.h>
+#include <asm/cache.h>
+#include <mmu.h>
+#include <mach/mmu.h>
+
+int arch_remap_range(void *virt_addr, phys_addr_t phys_addr, size_t size, unsigned flags)
+{
+ uint32_t ptr, start, tsize, valid, wimge, pte_flags;
+ unsigned long epn;
+ phys_addr_t rpn = 0;
+ int esel = 0;
+
+ if (phys_addr != virt_to_phys(virt_addr))
+ return -ENOSYS;
+
+ switch (flags) {
+ case MAP_UNCACHED:
+ pte_flags = MAS2_I;
+ break;
+ case MAP_CACHED:
+ pte_flags = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ptr = start = (uint32_t)virt_addr;
+ wimge = pte_flags | MAS2_M;
+
+ while (ptr < (start + size)) {
+ esel = e500_find_tlb_idx((void *)ptr, 1);
+ if (esel != -1)
+ break;
+ e500_read_tlbcam_entry(esel, &valid, &tsize, &epn,
+ &rpn);
+ if (flags & MAS2_I) {
+ flush_dcache();
+ invalidate_icache();
+ }
+ e500_set_tlb(1, epn, rpn, MAS3_SX|MAS3_SW|MAS3_SR,
+ (u8)wimge, 0, esel, tsize, 1);
+ /* convert tsize to bytes to increment address. */
+ ptr += (1ULL << ((tsize) + 10));
+ }
+
+ return 0;
+}
diff --git a/arch/powerpc/cpu-85xx/resetvec.S b/arch/powerpc/cpu-85xx/resetvec.S
new file mode 100644
index 0000000000..b21cc0f19d
--- /dev/null
+++ b/arch/powerpc/cpu-85xx/resetvec.S
@@ -0,0 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+ .section .resetvec,"ax"
+ b _start_e500
diff --git a/arch/powerpc/cpu-85xx/start.S b/arch/powerpc/cpu-85xx/start.S
new file mode 100644
index 0000000000..82c2c0ad8c
--- /dev/null
+++ b/arch/powerpc/cpu-85xx/start.S
@@ -0,0 +1,1314 @@
+/*
+ * Copyright 2004, 2007-2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2003 Motorola,Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/*
+ * 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 <asm/processor.h>
+#include <asm/ppc_asm.tmpl>
+#include <asm/ppc_defs.h>
+#include <asm/cache.h>
+
+#include <mach/mpc85xx.h>
+#include <mach/mmu.h>
+
+#undef MSR_KERNEL
+#define MSR_KERNEL ( MSR_ME ) /* Machine Check */
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r14 to access the GOT
+ */
+ START_GOT
+ GOT_ENTRY(_GOT2_TABLE_)
+ GOT_ENTRY(_FIXUP_TABLE_)
+
+ GOT_ENTRY(_start)
+ GOT_ENTRY(_start_of_vectors)
+ GOT_ENTRY(_end_of_vectors)
+ GOT_ENTRY(transfer_to_handler)
+ GOT_ENTRY(__init_end)
+ GOT_ENTRY(__bss_start)
+ GOT_ENTRY(__bss_stop)
+ 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:
+/* Enable debug exception */
+ li r1,MSR_DE
+ mtmsr r1
+
+#ifdef FSL_ERRATUM_A005125
+ msync
+ isync
+ mfspr r3, SPRN_HDBCR0
+ oris r3, r3, 0x0080
+ mtspr SPRN_HDBCR0, r3
+#endif
+
+/* 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 */
+
+
+ .macro create_tlb1_entry esel ts tsize epn wimg rpn \
+ perm phy_high scratch
+ lis \scratch, FSL_BOOKE_MAS0(1, \esel, 0)@h
+ ori \scratch, \scratch, FSL_BOOKE_MAS0(1, \esel, 0)@l
+ mtspr MAS0, \scratch
+ lis \scratch, FSL_BOOKE_MAS1(1, 1, 0, \ts, \tsize)@h
+ ori \scratch, \scratch, FSL_BOOKE_MAS1(1, 1, 0, \ts, \tsize)@l
+ mtspr MAS1, \scratch
+ lis \scratch, FSL_BOOKE_MAS2(\epn, \wimg)@h
+ ori \scratch, \scratch, FSL_BOOKE_MAS2(\epn, \wimg)@l
+ mtspr MAS2, \scratch
+ lis \scratch, FSL_BOOKE_MAS3(\rpn, 0, \perm)@h
+ ori \scratch, \scratch, FSL_BOOKE_MAS3(\rpn, 0, \perm)@l
+ mtspr MAS3, \scratch
+ lis \scratch, \phy_high@h
+ ori \scratch, \scratch, \phy_high@l
+ mtspr MAS7, \scratch
+ isync
+ msync
+ tlbwe
+ isync
+ .endm
+
+ .macro create_tlb0_entry esel ts tsize epn wimg rpn perm phy_high \
+ scratch
+ lis \scratch, FSL_BOOKE_MAS0(0, \esel, 0)@h
+ ori \scratch, \scratch, FSL_BOOKE_MAS0(0, \esel, 0)@l
+ mtspr MAS0, \scratch
+ lis \scratch, FSL_BOOKE_MAS1(1, 0, 0, \ts, \tsize)@h
+ ori \scratch, \scratch, FSL_BOOKE_MAS1(1, 0, 0, \ts, \tsize)@l
+ mtspr MAS1, \scratch
+ lis \scratch, FSL_BOOKE_MAS2(\epn, \wimg)@h
+ ori \scratch, \scratch, FSL_BOOKE_MAS2(\epn, \wimg)@l
+ mtspr MAS2, \scratch
+ lis \scratch, FSL_BOOKE_MAS3(\rpn, 0, \perm)@h
+ ori \scratch, \scratch, FSL_BOOKE_MAS3(\rpn, 0, \perm)@l
+ mtspr MAS3, \scratch
+ lis \scratch, \phy_high@h
+ ori \scratch, \scratch, \phy_high@l
+ mtspr MAS7, \scratch
+ isync
+ msync
+ tlbwe
+ isync
+ .endm
+
+ /* Setup interrupt vectors */
+ lis r1,TEXT_BASE@h
+ mtspr IVPR,r1
+
+ lis r3,(TEXT_BASE & 0xffff)@h
+ ori r3,r3,(TEXT_BASE & 0xffff)@l
+
+ addi r4,r3,CriticalInput - _start + _START_OFFSET
+ mtspr IVOR0,r4 /* 0: Critical input */
+ addi r4,r3,MachineCheck - _start + _START_OFFSET
+ mtspr IVOR1,r4 /* 1: Machine check */
+ addi r4,r3,DataStorage - _start + _START_OFFSET
+ mtspr IVOR2,r4 /* 2: Data storage */
+ addi r4,r3,InstStorage - _start + _START_OFFSET
+ mtspr IVOR3,r4 /* 3: Instruction storage */
+ addi r4,r3,ExtInterrupt - _start + _START_OFFSET
+ mtspr IVOR4,r4 /* 4: External interrupt */
+ addi r4,r3,Alignment - _start + _START_OFFSET
+ mtspr IVOR5,r4 /* 5: Alignment */
+ addi r4,r3,ProgramCheck - _start + _START_OFFSET
+ mtspr IVOR6,r4 /* 6: Program check */
+ addi r4,r3,FPUnavailable - _start + _START_OFFSET
+ mtspr IVOR7,r4 /* 7: floating point unavailable */
+ addi r4,r3,SystemCall - _start + _START_OFFSET
+ mtspr IVOR8,r4 /* 8: System call */
+ /* 9: Auxiliary processor unavailable(unsupported) */
+ addi r4,r3,Decrementer - _start + _START_OFFSET
+ mtspr IVOR10,r4 /* 10: Decrementer */
+ addi r4,r3,IntervalTimer - _start + _START_OFFSET
+ mtspr IVOR11,r4 /* 11: Interval timer */
+ addi r4,r3,WatchdogTimer - _start + _START_OFFSET
+ mtspr IVOR12,r4 /* 12: Watchdog timer */
+ addi r4,r3,DataTLBError - _start + _START_OFFSET
+ mtspr IVOR13,r4 /* 13: Data TLB error */
+ addi r4,r3,InstructionTLBError - _start + _START_OFFSET
+ mtspr IVOR14,r4 /* 14: Instruction TLB error */
+ addi r4,r3,DebugBreakpoint - _start + _START_OFFSET
+ mtspr IVOR15,r4 /* 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@h /* Enable machine check */
+ ori r0,r0,HID0_TBEN@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@l /* if we are rev 5.0 or greater set MBDD */
+ blt 1f
+ /* Set MBDD bit also */
+ ori r0, r0, HID1_MBDD@l
+1:
+ mtspr HID1,r0
+
+ /* Enable Branch Prediction */
+#if defined(CONFIG_BTB)
+ lis r0,BUCSR_ENABLE@h
+ ori r0,r0,BUCSR_ENABLE@l
+ mtspr SPRN_BUCSR,r0
+#endif
+
+/*
+ * Search for the TLB that covers the code we're executing, and shrink it
+ * so that it covers only this 4K page. That will ensure that any other
+ * TLB we create won't interfere with it. We assume that the TLB exists,
+ * which is why we don't check the Valid bit of MAS1. We also assume
+ * it is in TLB1.
+ *
+ * This is necessary, for example, when booting from the on-chip ROM,
+ * which (oddly) creates a single 4GB TLB that covers CCSR and DDR.
+ */
+ bl nexti /* Find our address */
+nexti: mflr r1 /* R1 = our PC */
+ li r2, 0
+ mtspr MAS6, r2 /* Assume the current PID and AS are 0 */
+ isync
+ msync
+ tlbsx 0, r1 /* This must succeed */
+
+ mfspr r14, MAS0 /* Save ESEL for later */
+ rlwinm r14, r14, 16, 0xfff
+
+ /* Set the size of the TLB to 4KB */
+ mfspr r3, MAS1
+ li r2, 0xF80
+ andc r3, r3, r2 /* Clear the TSIZE bits */
+ ori r3, r3, MAS1_TSIZE(BOOKE_PAGESZ_4K)@l
+ oris r3, r3, MAS1_IPROT@h
+ mtspr MAS1, r3
+
+ /*
+ * Set the base address of the TLB to our PC. We assume that
+ * virtual == physical. We also assume that MAS2_EPN == MAS3_RPN.
+ */
+ lis r3, MAS2_EPN@h
+ ori r3, r3, MAS2_EPN@l /* R3 = MAS2_EPN */
+
+ and r1, r1, r3 /* Our PC, rounded down to the nearest page */
+
+ mfspr r2, MAS2
+ andc r2, r2, r3
+ or r2, r2, r1
+ mtspr MAS2, r2 /* Set the EPN to our PC base address */
+
+ mfspr r2, MAS3
+ andc r2, r2, r3
+ or r2, r2, r1
+ mtspr MAS3, r2 /* Set the RPN to our PC base address */
+
+ isync
+ msync
+ tlbwe
+
+ /*
+ * Clear out any other TLB entries that may exist, to avoid conflicts.
+ * Our TLB entry is in r14.
+ */
+ li r0, TLBIVAX_ALL | TLBIVAX_TLB0
+ tlbivax 0, r0
+ tlbsync
+
+ mfspr r4, SPRN_TLB1CFG
+ rlwinm r4, r4, 0, TLBnCFG_NENTRY_MASK
+
+ li r3, 0
+ mtspr MAS1, r3
+1: cmpw r3, r14
+ rlwinm r5, r3, 16, MAS0_ESEL_MSK
+ addi r3, r3, 1
+ beq 2f /* skip the entry we're executing from */
+
+ oris r5, r5, MAS0_TLBSEL(1)@h
+ mtspr MAS0, r5
+
+ isync
+ tlbwe
+ isync
+ msync
+
+2: cmpw r3, r4
+ blt 1b
+
+#if defined(PPC_E500_DEBUG_TLB)
+/*
+ * TLB entry for debuggging in AS1
+ * Create temporary TLB entry in AS0 to handle debug exception
+ * As on debug exception MSR is cleared i.e. Address space is changed
+ * to 0. A TLB entry (in AS0) is required to handle debug exception generated
+ * in AS1.
+ *
+ * TLB entry is created for IVPR + IVOR15 to map on valid OP code address
+ * because flash's virtual address maps to 0xff800000 - 0xffffffff.
+ * and this window is outside of 4K boot window.
+ */
+ create_tlb1_entry PPC_E500_DEBUG_TLB, \
+ 0, BOOKE_PAGESZ_4M, \
+ TEXT_BASE & 0xffc00000, MAS2_I|MAS2_G, \
+ 0xffc00000, MAS3_SX|MAS3_SW|MAS3_SR, \
+ 0, r6
+
+#endif
+/*
+ * Relocate CCSR, if necessary. We relocate CCSR if (obviously) the default
+ * location is not where we want it. This typically happens on a 36-bit
+ * system, where we want to move CCSR to near the top of 36-bit address space.
+ *
+ * To move CCSR, we create two temporary TLBs, one for the old location, and
+ * another for the new location. On CoreNet systems, we also need to create
+ * a special, temporary LAW.
+ *
+ * As a general rule, TLB0 is used for short-term TLBs, and TLB1 is used for
+ * long-term TLBs, so we use TLB0 here.
+ */
+#if (CFG_CCSRBAR_DEFAULT != CFG_CCSRBAR_PHYS)
+create_ccsr_new_tlb:
+ /*
+ * Create a TLB for the new location of CCSR. Register R8 is reserved
+ * for the virtual address of this TLB (CFG_CCSRBAR).
+ */
+ lis r8, CFG_CCSRBAR@h
+ ori r8, r8, CFG_CCSRBAR@l
+ lis r9, (CFG_CCSRBAR + 0x1000)@h
+ ori r9, r9, (CFG_CCSRBAR + 0x1000)@l
+ create_tlb0_entry 0, \
+ 0, BOOKE_PAGESZ_4K, \
+ CFG_CCSRBAR, MAS2_I|MAS2_G, \
+ CFG_CCSRBAR_PHYS, MAS3_SW|MAS3_SR, \
+ 0, r3
+
+ /*
+ * Create a TLB for the current location of CCSR. Register R9 is
+ * reserved for the virtual address of this TLB (CFG_CCSRBAR + 0x1000).
+ */
+create_ccsr_old_tlb:
+ create_tlb0_entry 1, \
+ 0, BOOKE_PAGESZ_4K, \
+ CFG_CCSRBAR + 0x1000, MAS2_I|MAS2_G, \
+ CFG_CCSRBAR_DEFAULT, MAS3_SW|MAS3_SR, \
+ 0, r3
+
+ /*
+ * We have a TLB for what we think is the current (old) CCSR. Let's
+ * verify that, otherwise we won't be able to move it.
+ * CFG_CCSRBAR_DEFAULT is always a 32-bit number, so we only
+ * need to compare the lower 32 bits of CCSRBAR on CoreNet systems.
+ */
+verify_old_ccsr:
+ lis r0, CFG_CCSRBAR_DEFAULT@h
+ ori r0, r0, CFG_CCSRBAR_DEFAULT@l
+ lwz r1, 0(r9)
+ slwi r1, r1, 12
+ cmpl 0, r0, r1
+
+ /*
+ * If the value we read from CCSRBAR is not what we expect, then
+ * enter an infinite loop. This will at least allow a debugger to
+ * halt execution and examine TLBs, etc. There's no point in going
+ * on.
+ */
+infinite_debug_loop:
+ bne infinite_debug_loop
+
+ /*
+ * Read the current value of CCSRBAR using a load word instruction
+ * followed by an isync. This forces all accesses to configuration
+ * space to complete.
+ */
+write_new_ccsrbar:
+ sync
+ lwz r0, 0(r9)
+ isync
+ lis r0, (CFG_CCSRBAR_PHYS >> 12)@h
+ ori r0, r0, (CFG_CCSRBAR_PHYS >> 12)@l
+ stw r0, 0(r9)
+ sync
+ isync
+
+ /*
+ * Read the contents of CCSRBAR from its new location, followed by
+ * another isync.
+ */
+ lwz r0, 0(r8)
+ isync
+#endif
+
+ /* Enable/invalidate the I-Cache */
+ lis r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@h
+ ori r2,r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@l
+ mtspr SPRN_L1CSR1,r2
+1:
+ mfspr r3,SPRN_L1CSR1
+ and. r1,r3,r2
+ bne 1b
+
+ lis r3,(L1CSR1_CPE|L1CSR1_ICE)@h
+ ori r3,r3,(L1CSR1_CPE|L1CSR1_ICE)@l
+ mtspr SPRN_L1CSR1,r3
+ isync
+2:
+ mfspr r3,SPRN_L1CSR1
+ andi. r1,r3,L1CSR1_ICE@l
+ beq 2b
+
+ /* Enable/invalidate the D-Cache */
+ lis r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@h
+ ori r2,r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@l
+ mtspr SPRN_L1CSR0,r2
+1:
+ mfspr r3,SPRN_L1CSR0
+ and. r1,r3,r2
+ bne 1b
+
+ lis r3,(L1CSR0_CPE|L1CSR0_DCE)@h
+ ori r3,r3,(L1CSR0_CPE|L1CSR0_DCE)@l
+ mtspr SPRN_L1CSR0,r3
+ isync
+2:
+ mfspr r3,SPRN_L1CSR0
+ andi. r1,r3,L1CSR0_DCE@l
+ beq 2b
+
+create_init_ram_area:
+ 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 */
+ create_tlb1_entry 15, \
+ 1, BOOKE_PAGESZ_4M, \
+ TEXT_BASE & 0xffc00000, MAS2_I|MAS2_G, \
+ 0xffc00000, MAS3_SX|MAS3_SW|MAS3_SR, \
+ 0, r6
+
+ /* create a temp mapping in AS=1 to the stack */
+ create_tlb1_entry 14, \
+ 1, BOOKE_PAGESZ_16K, \
+ CFG_INIT_RAM_ADDR, 0, \
+ CFG_INIT_RAM_ADDR, MAS3_SX|MAS3_SW|MAS3_SR, \
+ 0, r6
+
+ lis r6,MSR_IS|MSR_DS|MSR_DE@h
+ ori r6,r6,MSR_IS|MSR_DS|MSR_DE@l
+ lis r7,switch_as@h
+ ori r7,r7,switch_as@l
+
+ mtspr SPRN_SRR0,r7
+ mtspr SPRN_SRR1,r6
+ rfi
+
+switch_as:
+/* L1 DCache is used for initial RAM */
+
+ /* Allocate initial RAM in data cache. */
+ lis r3,CFG_INIT_RAM_ADDR@h
+ ori r3,r3,CFG_INIT_RAM_ADDR@l
+ mfspr r2, L1CFG0
+ andi. r2, r2, 0x1ff
+ /* cache size * 1024 / (2 * L1 line size) */
+ slwi r2, r2, (10 - 1 - L1_CACHE_SHIFT)
+ mtctr r2
+ li r0,0
+1:
+ dcbz r0,r3
+ dcbtls 0,r0,r3
+ addi r3,r3,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@h
+ ori r3,r3,TEXT_BASE@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 r3,(CFG_INIT_RAM_ADDR)@h
+ ori r3,r3,((CFG_INIT_SP_OFFSET-16)&~0xf)@l
+ li r0,0
+ stw r0,0(r3) /* Terminate Back Chain */
+ stw r0,+4(r3) /* NULL return address. */
+ mr r1,r3 /* Transfer to SP(r1) */
+
+ 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 initdram
+ b relocate_code
+ isync
+
+ . = EXC_OFF_SYS_RESET
+ .globl _start_of_vectors
+_start_of_vectors:
+
+/* Critical input. */
+ CRIT_EXCEPTION(0x0100, CriticalInput, CritcalInputException)
+
+/* Machine check */
+ MCK_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. */
+ STD_EXCEPTION(0x0300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. */
+ STD_EXCEPTION(0x0400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+ STD_EXCEPTION(0x0500, ExtInterrupt, UnknownException)
+
+/* 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@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
+
+.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 e500_write_tlb(mas0, mas1, mas2, mas3, mas7)
+ */
+ .globl e500_write_tlb
+e500_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 = end_of_ram
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+ .globl relocate_code
+relocate_code:
+ mr r9, r3 /* Save end of RAM */
+
+ GET_GOT
+ lis r4,TEXT_BASE@h
+ ori r4,r4,TEXT_BASE@l
+ lwz r5,GOT(__bss_stop) /* size */
+ sub r5,r5,r4
+ sub r3, r3, r5
+ lwz r5,GOT(__init_end) /* Copy to init_end only */
+ sub r5,r5,r4
+ mr r1, r3
+ mr r10, r3
+ li r6,CACHELINE_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
+
+ /*
+ * 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
+
+ /*
+ * As IVPR is going to point RAM address,
+ * Make sure IVOR15 has valid opcode to support debugger
+ */
+ mtspr IVOR15,r0
+
+ /*
+ * Re-point the IVPR at RAM
+ */
+ mtspr IVPR,r10
+
+ 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@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_stop)
+
+ cmplw 0,r3,r4
+ beq 6f
+
+ li r0,0
+5:
+ stw r0,0(r3)
+ addi r3,r3,4
+ cmplw 0,r3,r4
+ blt 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_ExtInterrupt - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_Alignment - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_ProgramCheck - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_FPUnavailable - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_Decrementer - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_IntervalTimer - _start + _START_OFFSET
+ li r8,_end_of_vectors - _start + _START_OFFSET
+2:
+ bl trap_reloc
+ addi r7,r7,0x100 /* next exception vector */
+ cmplw 0,r7,r8
+ blt 2b
+
+ /* Update IVORs as per relocated vector table address */
+ li r7,0x0100
+ mtspr IVOR0,r7 /* 0: Critical input */
+ li r7,0x0200
+ mtspr IVOR1,r7 /* 1: Machine check */
+ li r7,0x0300
+ mtspr IVOR2,r7 /* 2: Data storage */
+ li r7,0x0400
+ mtspr IVOR3,r7 /* 3: Instruction storage */
+ li r7,0x0500
+ mtspr IVOR4,r7 /* 4: External interrupt */
+ li r7,0x0600
+ mtspr IVOR5,r7 /* 5: Alignment */
+ li r7,0x0700
+ mtspr IVOR6,r7 /* 6: Program check */
+ li r7,0x0800
+ mtspr IVOR7,r7 /* 7: floating point unavailable */
+ li r7,0x0900
+ mtspr IVOR8,r7 /* 8: System call */
+ /* 9: Auxiliary processor unavailable(unsupported) */
+ li r7,0x0a00
+ mtspr IVOR10,r7 /* 10: Decrementer */
+ li r7,0x0b00
+ mtspr IVOR11,r7 /* 11: Interval timer */
+ li r7,0x0c00
+ mtspr IVOR12,r7 /* 12: Watchdog timer */
+ li r7,0x0d00
+ mtspr IVOR13,r7 /* 13: Data TLB error */
+ li r7,0x0e00
+ mtspr IVOR14,r7 /* 14: Instruction TLB error */
+ li r7,0x0f00
+ mtspr IVOR15,r7 /* 15: Debug */
+
+ 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
+ dcblc r0,r3
+ addi r3,r3,CACHELINE_SIZE
+ bdnz 1b
+ sync
+
+ /* Invalidate the TLB entries for the cache */
+ lis r3,CFG_INIT_RAM_ADDR@h
+ ori r3,r3,CFG_INIT_RAM_ADDR@l
+ tlbivax 0,r3
+ addi r3,r3,0x1000
+ tlbivax 0,r3
+ addi r3,r3,0x1000
+ tlbivax 0,r3
+ addi r3,r3,0x1000
+ tlbivax 0,r3
+ isync
+ blr
+
+.globl flush_dcache
+flush_dcache:
+ mfspr r3,SPRN_L1CFG0
+
+ rlwinm r5,r3,9,3 /* Extract cache block size */
+ twlgti r5,1 /* Only 32 and 64 byte cache blocks
+ * are currently defined.
+ */
+ li r4,32
+ subfic r6,r5,2 /* r6 = log2(1KiB / cache block size) -
+ * log2(number of ways)
+ */
+ slw r5,r4,r5 /* r5 = cache block size */
+
+ rlwinm r7,r3,0,0xff /* Extract number of KiB in the cache */
+ mulli r7,r7,13 /* An 8-way cache will require 13
+ * loads per set.
+ */
+ slw r7,r7,r6
+
+ /* save off HID0 and set DCFA */
+ mfspr r8,SPRN_HID0
+ ori r9,r8,HID0_DCFA@l
+ mtspr SPRN_HID0,r9
+ isync
+
+ lis r4,0
+ mtctr r7
+
+1: lwz r3,0(r4) /* Load... */
+ add r4,r4,r5
+ bdnz 1b
+
+ msync
+ lis r4,0
+ mtctr r7
+
+1: dcbf 0,r4 /* ...and flush. */
+ add r4,r4,r5
+ bdnz 1b
+
+ /* restore HID0 */
+ mtspr SPRN_HID0,r8
+ isync
+
+ blr
+
+.globl setup_ivors
+setup_ivors:
+
+#include "fixed_ivor.S"
+ blr
diff --git a/arch/powerpc/cpu-85xx/tlb.c b/arch/powerpc/cpu-85xx/tlb.c
new file mode 100644
index 0000000000..2c59806ec2
--- /dev/null
+++ b/arch/powerpc/cpu-85xx/tlb.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2012 GE Intelligent Platforms, Inc.
+ *
+ * Copyright 2008-2009 Freescale Semiconductor, Inc.
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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.
+ *
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/config.h>
+#include <linux/log2.h>
+#include <mach/mmu.h>
+
+void e500_invalidate_tlb(u8 tlb)
+{
+ if (tlb == 0)
+ mtspr(MMUCSR0, 0x4);
+ if (tlb == 1)
+ mtspr(MMUCSR0, 0x2);
+}
+
+void e500_init_tlbs(void)
+{
+ int i;
+
+ for (i = 0; i < num_tlb_entries; i++) {
+ e500_write_tlb(tlb_table[i].mas0,
+ tlb_table[i].mas1,
+ tlb_table[i].mas2,
+ tlb_table[i].mas3,
+ tlb_table[i].mas7);
+ }
+
+ return ;
+}
+
+void e500_read_tlbcam_entry(int idx, u32 *valid, u32 *tsize,
+ unsigned long *epn, phys_addr_t *rpn)
+{
+ u32 _mas1;
+
+ mtspr(MAS0, FSL_BOOKE_MAS0(1, idx, 0));
+ asm volatile("tlbre;isync");
+ _mas1 = mfspr(MAS1);
+
+ *valid = (_mas1 & MAS1_VALID);
+ *tsize = (_mas1 >> 7) & 0x1f;
+ *epn = mfspr(MAS2) & MAS2_EPN;
+ *rpn = mfspr(MAS3) & MAS3_RPN;
+}
+
+int e500_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 e500_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);
+
+ e500_write_tlb(_mas0, _mas1, _mas2, _mas3, _mas7);
+}
+
+void e500_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 inline void tlbsx(const unsigned *addr)
+{
+ __asm__ __volatile__ ("tlbsx 0,%0" : : "r" (addr), "m" (*addr));
+}
+
+int e500_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("Address 0x%p not found in TLB %d\n", addr, tlbsel);
+}
+
+static unsigned int e500_setup_ddr_tlbs_phys(phys_addr_t p_addr,
+ unsigned int memsize_in_meg)
+{
+ int i;
+ unsigned int tlb_size, max_cam, tsize_mask;
+ unsigned int wimge = MAS2_M;
+ unsigned int ram_tlb_address = (unsigned int)CFG_SDRAM_BASE;
+ u64 size, memsize = (u64)memsize_in_meg << 20;
+
+ size = min(memsize, MAX_MEM_MAPPED);
+ if ((mfspr(SPRN_MMUCFG) & MMUCFG_MAVN) == MMUCFG_MAVN_V1) {
+ /* Convert (4^max) kB to (2^max) bytes */
+ max_cam = ((mfspr(SPRN_TLB1CFG) >> 16) & 0xf) * 2 + 10;
+ tsize_mask = ~1U;
+ } else {
+ /* Convert (2^max) kB to (2^max) bytes */
+ max_cam = __ilog2(mfspr(SPRN_TLB1PS)) + 10;
+ tsize_mask = ~0U;
+ }
+
+ for (i = 0; size && i < 8; i++) {
+ int ram_tlb_index = e500_find_free_tlbcam();
+ u32 camsize = __ilog2_u64(size) & tsize_mask;
+ u32 align = __ilog2(ram_tlb_address) & tsize_mask;
+
+ if (ram_tlb_index == -1)
+ break;
+
+ if (align == -2)
+ align = max_cam;
+ if (camsize > align)
+ camsize = align;
+
+ if (camsize > max_cam)
+ camsize = max_cam;
+
+ tlb_size = camsize - 10;
+
+ e500_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;
+}
+
+inline unsigned int e500_setup_ddr_tlbs(unsigned int memsize_in_meg)
+{
+ return e500_setup_ddr_tlbs_phys(CFG_SDRAM_BASE, memsize_in_meg);
+}
diff --git a/arch/powerpc/cpu-85xx/traps.c b/arch/powerpc/cpu-85xx/traps.c
new file mode 100644
index 0000000000..51c85775fc
--- /dev/null
+++ b/arch/powerpc/cpu-85xx/traps.c
@@ -0,0 +1,265 @@
+/*
+ * linux/arch/powerpc/kernel/traps.c
+ *
+ * Copyright 2007 Freescale Semiconductor.
+ * Copyright (C) 2003 Motorola
+ * Modified by Xianghua Xiao(x.xiao@motorola.com)
+ *
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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.
+ *
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <init.h>
+#include <asm/processor.h>
+#include <mach/mpc85xx.h>
+
+int machinecheck_count;
+int machinecheck_error;
+
+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
+ */
+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");
+}
+
+static 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 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 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/powerpc/ddr-8xxx/Makefile b/arch/powerpc/ddr-8xxx/Makefile
new file mode 100644
index 0000000000..651fe050f6
--- /dev/null
+++ b/arch/powerpc/ddr-8xxx/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-y += main.o util.o ctrl_regs.o options.o lc_common_dimm_params.o
+obj-y += ddr_setctrl.o
+obj-$(CONFIG_FSL_DDR2) += ddr2_dimm_params.o
+obj-$(CONFIG_FSL_DDR3) += ddr3_dimm_params.o
diff --git a/arch/powerpc/ddr-8xxx/common_timing_params.h b/arch/powerpc/ddr-8xxx/common_timing_params.h
new file mode 100644
index 0000000000..85a1e2868f
--- /dev/null
+++ b/arch/powerpc/ddr-8xxx/common_timing_params.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#ifndef COMMON_TIMING_PARAMS_H
+#define COMMON_TIMING_PARAMS_H
+
+struct common_timing_params_s {
+ uint32_t tCKmin_X_ps;
+ uint32_t tCKmax_ps;
+ uint32_t tCKmax_max_ps;
+ uint32_t tRCD_ps;
+ uint32_t tRP_ps;
+ uint32_t tRAS_ps;
+ uint32_t tWR_ps; /* maximum = 63750 ps */
+ uint32_t tWTR_ps; /* maximum = 63750 ps */
+ uint32_t tRFC_ps; /* maximum = 255 ns + 256 ns + .75 ns
+ = 511750 ps */
+ uint32_t tRRD_ps; /* maximum = 63750 ps */
+ uint32_t tRC_ps; /* maximum = 254 ns + .75 ns = 254750 ps */
+ uint32_t refresh_rate_ps;
+ uint32_t extended_op_srt;
+ uint32_t tIS_ps; /* byte 32, spd->ca_setup */
+ uint32_t tIH_ps; /* byte 33, spd->ca_hold */
+ uint32_t tDS_ps; /* byte 34, spd->data_setup */
+ uint32_t tDH_ps; /* byte 35, spd->data_hold */
+ uint32_t tRTP_ps; /* byte 38, spd->trtp */
+ uint32_t tDQSQ_max_ps; /* byte 44, spd->tdqsq */
+ uint32_t tQHS_ps; /* byte 45, spd->tqhs */
+ uint32_t ndimms_present;
+ uint32_t lowest_common_SPD_caslat;
+ uint32_t highest_common_derated_caslat;
+ uint32_t additive_latency;
+ uint32_t all_DIMMs_burst_lengths_bitmask;
+ uint32_t all_DIMMs_registered;
+ uint32_t all_DIMMs_unbuffered;
+ uint32_t all_DIMMs_ECC_capable;
+ uint64_t total_mem;
+ uint64_t base_address;
+};
+
+#endif
diff --git a/arch/powerpc/ddr-8xxx/ctrl_regs.c b/arch/powerpc/ddr-8xxx/ctrl_regs.c
new file mode 100644
index 0000000000..187f450c39
--- /dev/null
+++ b/arch/powerpc/ddr-8xxx/ctrl_regs.c
@@ -0,0 +1,779 @@
+/*
+ * Copyright 2008-2012 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.
+ */
+
+/*
+ * Generic driver for Freescale DDR2/DDR3 memory controller.
+ * Based on code from spd_sdram.c
+ * Author: James Yang [at freescale.com]
+ */
+
+#include <common.h>
+#include <asm/fsl_ddr_sdram.h>
+#include "ddr.h"
+
+static uint32_t compute_cas_write_latency(void)
+{
+ uint32_t cwl;
+ const uint32_t mclk_ps = get_memory_clk_period_ps();
+
+ if (mclk_ps >= 2500)
+ cwl = 5;
+ else if (mclk_ps >= 1875)
+ cwl = 6;
+ else if (mclk_ps >= 1500)
+ cwl = 7;
+ else if (mclk_ps >= 1250)
+ cwl = 8;
+ else if (mclk_ps >= 1070)
+ cwl = 9;
+ else if (mclk_ps >= 935)
+ cwl = 10;
+ else if (mclk_ps >= 833)
+ cwl = 11;
+ else if (mclk_ps >= 750)
+ cwl = 12;
+ else
+ cwl = 12;
+
+ return cwl;
+}
+
+static void set_csn_config(int dimm_number, int i,
+ struct fsl_ddr_cfg_regs_s *ddr,
+ const struct memctl_options_s *popts,
+ const struct dimm_params_s *dimm)
+{
+ uint32_t cs_n_en = 0, ap_n_en = 0, odt_rd_cfg = 0, odt_wr_cfg = 0,
+ ba_bits_cs_n = 0, row_bits_cs_n = 0, col_bits_cs_n = 0,
+ n_banks_per_sdram_device;
+ int go_config = 0;
+
+ switch (i) {
+ case 0:
+ if (dimm[dimm_number].n_ranks > 0)
+ go_config = 1;
+ break;
+ case 1:
+ if ((dimm_number == 0 && dimm[0].n_ranks > 1) ||
+ (dimm_number == 1 && dimm[1].n_ranks > 0))
+ go_config = 1;
+ break;
+ case 2:
+ if ((dimm_number == 0 && dimm[0].n_ranks > 2) ||
+ (dimm_number >= 1 && dimm[dimm_number].n_ranks > 0))
+ go_config = 1;
+ break;
+ case 3:
+ if ((dimm_number == 0 && dimm[0].n_ranks > 3) ||
+ (dimm_number == 1 && dimm[1].n_ranks > 1) ||
+ (dimm_number == 3 && dimm[3].n_ranks > 0))
+ go_config = 1;
+ break;
+ default:
+ break;
+ }
+
+ if (go_config) {
+ /* Chip Select enable */
+ cs_n_en = 1;
+ /* CSn auto-precharge enable */
+ ap_n_en = popts->cs_local_opts[i].auto_precharge;
+ /* ODT for reads configuration */
+ odt_rd_cfg = popts->cs_local_opts[i].odt_rd_cfg;
+ /* ODT for writes configuration */
+ odt_wr_cfg = popts->cs_local_opts[i].odt_wr_cfg;
+ /* Num of bank bits for SDRAM on CSn */
+ n_banks_per_sdram_device =
+ dimm[dimm_number].n_banks_per_sdram_device;
+ ba_bits_cs_n = __ilog2(n_banks_per_sdram_device) - 2;
+ /* Num of row bits for SDRAM on CSn */
+ row_bits_cs_n = dimm[dimm_number].n_row_addr - 12;
+ /* Num of ocl bits for SDRAM on CSn */
+ col_bits_cs_n = dimm[dimm_number].n_col_addr - 8;
+ }
+
+ ddr->cs[i].config = (((cs_n_en & 0x1) << 31)
+ | ((ap_n_en & 0x1) << 23)
+ | ((odt_rd_cfg & 0x7) << 20)
+ | ((odt_wr_cfg & 0x7) << 16)
+ | ((ba_bits_cs_n & 0x3) << 14)
+ | ((row_bits_cs_n & 0x7) << 8)
+ | ((col_bits_cs_n & 0x7) << 0));
+}
+
+static void set_timing_cfg_0(struct fsl_ddr_cfg_regs_s *ddr,
+ const struct memctl_options_s *popts,
+ const struct dimm_params_s *dimm)
+{
+ uint32_t trwt_mclk = 0, twrt_mclk = 0, act_pd_exit_mclk,
+ pre_pd_exit_mclk, taxpd_mclk, tmrd_mclk, txp,
+ data_rate = fsl_get_ddr_freq(0);
+
+ if (popts->sdram_type == SDRAM_TYPE_DDR2) {
+ act_pd_exit_mclk = popts->txard;
+ pre_pd_exit_mclk = popts->txp;
+ taxpd_mclk = popts->taxpd;
+ tmrd_mclk = popts->tmrd;
+ } else {
+ /*
+ * tXARD is not part of the DDR3 specification, use the
+ * parameter txp instead of it. That is:
+ * txp=max(3nCK, 7.5ns). As well, use tAXPD=1.
+ */
+ txp = max_t(uint32_t, (get_memory_clk_period_ps() * 3), 7500);
+ data_rate = fsl_get_ddr_freq(0);
+ tmrd_mclk = 4;
+
+ /* for faster clock, need more time for data setup */
+ if (popts->trwt_override)
+ trwt_mclk = popts->trwt;
+ else if (data_rate / 1000000 > 1800)
+ trwt_mclk = 2;
+ else
+ trwt_mclk = 0;
+
+ if (data_rate / 1000000 > 1150)
+ twrt_mclk = 1;
+ else
+ twrt_mclk = 0;
+
+ taxpd_mclk = 1;
+ if (popts->dynamic_power == 0) {
+ act_pd_exit_mclk = 1;
+ pre_pd_exit_mclk = 1;
+ } else {
+ /* act_pd_exit_mclk = tXARD, see above */
+ act_pd_exit_mclk = picos_to_mclk(txp);
+ /* Mode register MR0[A12] is '1' - fast exit */
+ pre_pd_exit_mclk = act_pd_exit_mclk;
+ }
+ }
+
+ ddr->timing_cfg_0 = (((trwt_mclk & 0x3) << 30)
+ | ((twrt_mclk & 0x3) << 28)
+ | ((act_pd_exit_mclk & 0xf) << 20)
+ | ((pre_pd_exit_mclk & 0xf) << 16)
+ | ((taxpd_mclk & 0xf) << 8)
+ | ((tmrd_mclk & 0x1f) << 0)
+ );
+}
+
+static void set_timing_cfg_3(struct fsl_ddr_cfg_regs_s *ddr,
+ const struct memctl_options_s *popts,
+ const struct common_timing_params_s *dimm,
+ uint32_t cas_latency, uint32_t additive_latency)
+{
+ uint32_t ext_pretoact, ext_acttopre, ext_acttorw, ext_refrec, ext_wrrec;
+
+ ext_pretoact = picos_to_mclk(dimm->tRP_ps) >> 4;
+ ext_acttopre = picos_to_mclk(dimm->tRAS_ps) >> 4;
+ ext_acttorw = picos_to_mclk(dimm->tRCD_ps) >> 4;
+ cas_latency = ((cas_latency << 1) - 1) >> 4;
+ additive_latency = additive_latency >> 4;
+ ext_refrec = (picos_to_mclk(dimm->tRFC_ps) - 8) >> 4;
+ /* ext_wrrec only deals with 16 clock and above, or 14 with OTF */
+ ext_wrrec = (picos_to_mclk(dimm->tWR_ps) +
+ (popts->otf_burst_chop_en ? 2 : 0)) >> 4;
+
+ ddr->timing_cfg_3 = (((ext_pretoact & 0x1) << 28)
+ | ((ext_acttopre & 0x3) << 24)
+ | ((ext_acttorw & 0x1) << 22)
+ | ((ext_refrec & 0x1F) << 16)
+ | ((cas_latency & 0x3) << 12)
+ | ((additive_latency & 0x1) << 10)
+ | ((ext_wrrec & 0x1) << 8)
+ );
+}
+
+static void set_timing_cfg_1(struct fsl_ddr_cfg_regs_s *ddr,
+ const struct memctl_options_s *popts,
+ const struct common_timing_params_s *dimm,
+ uint32_t cas_latency)
+{
+ uint32_t pretoact_mclk, acttopre_mclk, acttorw_mclk, refrec_ctrl,
+ wrrec_mclk, acttoact_mclk, wrtord_mclk;
+ /* DDR_SDRAM_MODE doesn't support 9,11,13,15 */
+ static const u8 wrrec_table[] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 10, 10, 12, 12, 14, 14, 0, 0
+ };
+
+ pretoact_mclk = picos_to_mclk(dimm->tRP_ps);
+ acttopre_mclk = picos_to_mclk(dimm->tRAS_ps);
+ acttorw_mclk = picos_to_mclk(dimm->tRCD_ps);
+
+ /*
+ * Translate CAS Latency to a DDR controller field value:
+ *
+ * CAS Lat DDR II Ctrl
+ * Clocks SPD Bit Value
+ * ------- ------- ------
+ * 1.0 0001
+ * 1.5 0010
+ * 2.0 2 0011
+ * 2.5 0100
+ * 3.0 3 0101
+ * 3.5 0110
+ * 4.0 4 0111
+ * 4.5 1000
+ * 5.0 5 1001
+ */
+ cas_latency = (cas_latency << 1) - 1;
+ refrec_ctrl = picos_to_mclk(dimm->tRFC_ps) - 8;
+ acttoact_mclk = picos_to_mclk(dimm->tRRD_ps);
+
+ wrrec_mclk = picos_to_mclk(dimm->tWR_ps);
+ if (wrrec_mclk <= 16)
+ wrrec_mclk = wrrec_table[wrrec_mclk - 1];
+ if (popts->otf_burst_chop_en)
+ wrrec_mclk += 2;
+
+ wrtord_mclk = picos_to_mclk(dimm->tWTR_ps);
+ if (popts->sdram_type == SDRAM_TYPE_DDR2) {
+ wrtord_mclk = max_t(uint32_t, wrtord_mclk, 2);
+ } else {
+ wrtord_mclk = max_t(uint32_t, wrtord_mclk, 4);
+ acttoact_mclk = max_t(uint32_t, acttoact_mclk, 4);
+ }
+
+ if (popts->otf_burst_chop_en)
+ wrtord_mclk += 2;
+
+ ddr->timing_cfg_1 = (((pretoact_mclk & 0x0F) << 28)
+ | ((acttopre_mclk & 0x0F) << 24)
+ | ((acttorw_mclk & 0xF) << 20)
+ | ((cas_latency & 0xF) << 16)
+ | ((refrec_ctrl & 0xF) << 12)
+ | ((wrrec_mclk & 0x0F) << 8)
+ | ((acttoact_mclk & 0x0F) << 4)
+ | ((wrtord_mclk & 0x0F) << 0));
+}
+
+static void set_timing_cfg_2(struct fsl_ddr_cfg_regs_s *ddr,
+ const struct memctl_options_s *popts,
+ const struct common_timing_params_s *dimm,
+ uint32_t cas_latency, uint32_t additive_latency)
+{
+ uint32_t cpo, rd_to_pre, wr_data_delay, cke_pls, four_act;
+
+ cpo = popts->cpo_override;
+ rd_to_pre = picos_to_mclk(dimm->tRTP_ps);
+ if (popts->sdram_type == SDRAM_TYPE_DDR2) {
+ cas_latency = cas_latency - 1;
+ rd_to_pre = max_t(uint32_t, rd_to_pre, 2);
+ } else {
+ cas_latency = compute_cas_write_latency();
+ rd_to_pre = max_t(uint32_t, rd_to_pre, 4);
+ }
+
+ if (popts->otf_burst_chop_en)
+ rd_to_pre += 2;
+
+ wr_data_delay = popts->write_data_delay;
+ cke_pls = picos_to_mclk(popts->tCKE_clock_pulse_width_ps);
+ four_act = picos_to_mclk(popts->tFAW_window_four_activates_ps);
+
+ ddr->timing_cfg_2 = (((additive_latency & 0xf) << 28)
+ | ((cpo & 0x1f) << 23)
+ | ((cas_latency & 0xf) << 19)
+ | ((rd_to_pre & 7) << 13)
+ | ((wr_data_delay & 7) << 10)
+ | ((cke_pls & 0x7) << 6)
+ | ((four_act & 0x3f) << 0));
+}
+
+static void set_ddr_sdram_cfg(struct fsl_ddr_cfg_regs_s *ddr,
+ const struct memctl_options_s *popts,
+ const struct common_timing_params_s *dimm)
+{
+ uint32_t mem_en, sren, ecc_en, sdram_type, dyn_pwr, dbw, twoT_en, hse,
+ threet_en, eight_be = 0;
+
+ mem_en = 1;
+ sren = popts->self_refresh_in_sleep;
+ if (dimm->all_DIMMs_ECC_capable)
+ ecc_en = popts->ECC_mode;
+ else
+ ecc_en = 0;
+
+ sdram_type = popts->sdram_type;
+ twoT_en = popts->twoT_en;
+ dyn_pwr = popts->dynamic_power;
+ dbw = popts->data_bus_width;
+ hse = popts->half_strength_driver_enable;
+ threet_en = popts->threet_en;
+
+ if (sdram_type == SDRAM_TYPE_DDR3)
+ if ((popts->burst_length == DDR_BL8) || (dbw == 1))
+ eight_be = 1;
+
+ ddr->ddr_sdram_cfg = (((mem_en & 0x1) << 31)
+ | ((sren & 0x1) << 30)
+ | ((ecc_en & 0x1) << 29)
+ | ((sdram_type & 0x7) << 24)
+ | ((dyn_pwr & 0x1) << 21)
+ | ((dbw & 0x3) << 19)
+ | ((eight_be & 0x1) << 18)
+ | ((threet_en & 0x1) << 16)
+ | ((twoT_en & 0x1) << 15)
+ | ((hse & 0x1) << 3));
+}
+
+static void set_ddr_sdram_cfg_2(struct fsl_ddr_cfg_regs_s *ddr,
+ const struct memctl_options_s *popts)
+{
+ struct ddr_board_info_s *bi = popts->board_info;
+ uint32_t i, dll_rst_dis, dqs_cfg, odt_cfg = 0, num_pr, d_init = 0,
+ obc_cfg = 0, x4_en, md_en = 0, rcw_en = 0;
+
+ dll_rst_dis = popts->dll_rst_dis;
+ dqs_cfg = popts->DQS_config;
+
+ /*
+ * Check for On-Die Termination options and
+ * assert ODT only during reads to DRAM.
+ */
+ for (i = 0; i < bi->cs_per_ctrl; i++)
+ if (popts->cs_local_opts[i].odt_rd_cfg ||
+ popts->cs_local_opts[i].odt_wr_cfg) {
+ odt_cfg = SDRAM_CFG2_ODT_ONLY_READ;
+ break;
+ }
+
+ /* Default number of posted refresh */
+ num_pr = 1;
+
+ if (popts->ECC_init_using_memctl) {
+ d_init = 1;
+ ddr->ddr_data_init = popts->data_init;
+ }
+
+ if (popts->sdram_type == SDRAM_TYPE_DDR3) {
+ obc_cfg = popts->otf_burst_chop_en;
+ md_en = popts->mirrored_dimm;
+ }
+
+ x4_en = popts->x4_en ? 1 : 0;
+
+ ddr->ddr_sdram_cfg_2 = (((dll_rst_dis & 0x1) << 29)
+ | ((dqs_cfg & 0x3) << 26)
+ | ((odt_cfg & 0x3) << 21)
+ | ((num_pr & 0xf) << 12)
+ | (x4_en << 10)
+ | ((obc_cfg & 0x1) << 6)
+ | ((d_init & 0x1) << 4)
+ | ((rcw_en & 0x1) << 2)
+ | ((md_en & 0x1) << 0)
+ );
+}
+
+static void set_ddr_sdram_mode_2(struct fsl_ddr_cfg_regs_s *ddr,
+ const struct memctl_options_s *popts,
+ const struct common_timing_params_s *dimm)
+{
+ uint16_t esdmode2;
+ uint32_t rtt_wr, srt = 0, cwl;
+
+ cwl = compute_cas_write_latency() - 5;
+
+ if (popts->rtt_override)
+ rtt_wr = popts->rtt_wr_override_value;
+ else
+ rtt_wr = popts->cs_local_opts[0].odt_rtt_wr;
+
+ if (dimm->extended_op_srt)
+ srt = dimm->extended_op_srt;
+
+ esdmode2 = (((rtt_wr & 0x3) << 9)
+ | ((srt & 0x1) << 7)
+ | ((cwl & 0x7) << 3)
+ );
+
+ ddr->ddr_sdram_mode_2 = (esdmode2 & 0xffff) << 16;
+}
+
+static void
+set_ddr_sdram_interval(struct fsl_ddr_cfg_regs_s *ddr,
+ const struct memctl_options_s *popts,
+ const struct common_timing_params_s *dimm)
+{
+ uint32_t refint, bstopre;
+
+ refint = picos_to_mclk(dimm->refresh_rate_ps);
+ /* Precharge interval */
+ bstopre = popts->bstopre;
+
+ ddr->ddr_sdram_interval = (((refint & 0xFFFF) << 16)
+ | ((bstopre & 0x3FFF) << 0));
+}
+
+static void set_ddr3_sdram_mode(struct fsl_ddr_cfg_regs_s *ddr,
+ const struct memctl_options_s *popts,
+ const struct common_timing_params_s *dimm,
+ uint32_t cas_latency, uint32_t additive_latency)
+{
+ uint16_t esdmode, sdmode;
+ /* Mode Register - MR1 */
+ uint32_t rtt, al;
+ /* Mode Register - MR0 */
+ uint32_t dll_on, wr = 0, dll_rst, mode, caslat = 4, bt, bl, wr_mclk;
+ /*
+ * DDR_SDRAM_MODE doesn't support 9,11,13,15
+ * Please refer JEDEC Standard No. 79-3E for Mode Register MR0
+ * for this table
+ */
+ static const u8 wr_table[] = {1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 0, 0};
+ uint8_t cas_latency_table[] = { /* From 5 to 16 clocks */
+ 0x2, 0x4, 0x6, 0x8, 0xa, 0xc, 0xe, 0x1, 0x3, 0x5, 0x7, 0x9,
+ };
+ const unsigned int mclk_ps = get_memory_clk_period_ps();
+
+ if (popts->rtt_override)
+ rtt = popts->rtt_override_value;
+ else
+ rtt = popts->cs_local_opts[0].odt_rtt_norm;
+
+ if (additive_latency == (cas_latency - 1))
+ al = 1;
+ else if (additive_latency == (cas_latency - 2))
+ al = 2;
+ else
+ al = 0;
+
+ /*
+ * The esdmode value will also be used for writing
+ * MR1 during write leveling for DDR3, although the
+ * bits specifically related to the write leveling
+ * scheme will be handled automatically by the DDR
+ * controller. So wrlvl_en is set to 0 here.
+ */
+ esdmode = (((rtt & 0x4) << 7)
+ | ((rtt & 0x2) << 5)
+ | ((al & 0x3) << 3)
+ | ((rtt & 0x1) << 2)
+ );
+
+ /*
+ * DLL control for precharge PD
+ * 0=slow exit DLL off (tXPDLL)
+ * 1=fast exit DLL on (tXP)
+ */
+ dll_on = 1;
+
+ wr_mclk = (dimm->tWR_ps + mclk_ps - 1) / mclk_ps;
+ if (wr_mclk <= 16)
+ wr = wr_table[wr_mclk - 5];
+
+ dll_rst = 0; /* dll no reset */
+ mode = 0; /* normal mode */
+
+ /* look up table to get the cas latency bits */
+ if (cas_latency >= 5 && cas_latency <= 16)
+ caslat = cas_latency_table[cas_latency - 5];
+
+ /* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */
+ bt = 0;
+
+ switch (popts->burst_length) {
+ case DDR_BL8:
+ bl = 0;
+ break;
+ case DDR_OTF:
+ bl = 1;
+ break;
+ case DDR_BC4:
+ bl = 2;
+ break;
+ default:
+ bl = 1;
+ break;
+ }
+
+ sdmode = (((dll_on & 0x1) << 12)
+ | ((wr & 0x7) << 9)
+ | ((dll_rst & 0x1) << 8)
+ | ((mode & 0x1) << 7)
+ | (((caslat >> 1) & 0x7) << 4)
+ | ((bt & 0x1) << 3)
+ | ((caslat & 1) << 2)
+ | ((bl & 0x3) << 0)
+ );
+
+ ddr->ddr_sdram_mode = (((esdmode & 0xffff) << 16)
+ | ((sdmode & 0xffff) << 0)
+ );
+}
+
+static void set_ddr2_sdram_mode(struct fsl_ddr_cfg_regs_s *ddr,
+ const struct memctl_options_s *popts,
+ const struct common_timing_params_s *dimm,
+ uint32_t cas_latency, uint32_t additive_latency)
+{
+ uint16_t esdmode, sdmode;
+ uint32_t dqs_en, rtt, al, wr, bl;
+ const uint32_t mclk_ps = get_memory_clk_period_ps();
+
+ /* DQS# Enable: 0=enable, 1=disable */
+ dqs_en = !popts->DQS_config;
+ /* Posted CAS# additive latency (AL) */
+ al = additive_latency;
+ /* Internal Termination Resistor */
+ if (popts->rtt_override)
+ rtt = popts->rtt_override_value;
+ else
+ rtt = popts->cs_local_opts[0].odt_rtt_norm;
+
+ /*
+ * Extended SDRAM mode.
+ * The variable also selects:
+ * - OCD set to exit mode
+ * - all outputs bit i.e DQ, DQS, RDQS output enabled
+ * - RDQS ball disabled
+ * - DQS ball enabled
+ * - DLL enabled
+ * - Output drive strength: full strength.
+ */
+ esdmode = (((dqs_en & 0x1) << 10)
+ | ((rtt & 0x2) << 5)
+ | ((al & 0x7) << 3)
+ | ((rtt & 0x1) << 2));
+
+ /* Write recovery */
+ wr = ((dimm->tWR_ps + mclk_ps - 1) / mclk_ps) - 1;
+
+ switch (popts->burst_length) {
+ case DDR_BL4:
+ bl = 2;
+ break;
+ case DDR_BL8:
+ bl = 3;
+ break;
+ default:
+ bl = 2;
+ break;
+ }
+
+ /* SDRAM mode
+ * The variable also selects:
+ * - power down mode: fast exit (normal)
+ * - DLL reset disabled.
+ * - burst type: sequential
+ */
+ sdmode = (((wr & 0x7) << 9)
+ | ((cas_latency & 0x7) << 4)
+ | ((bl & 0x7) << 0));
+
+ ddr->ddr_sdram_mode = (((esdmode & 0xFFFF) << 16)
+ | ((sdmode & 0xFFFF) << 0));
+}
+
+static void set_ddrx_sdram_mode(struct fsl_ddr_cfg_regs_s *ddr,
+ const struct memctl_options_s *popts,
+ const struct common_timing_params_s *dimm,
+ uint32_t cas_latency, uint32_t additive_latency)
+{
+ if (popts->sdram_type == SDRAM_TYPE_DDR2)
+ set_ddr2_sdram_mode(ddr, popts, dimm, cas_latency,
+ additive_latency);
+ else
+ set_ddr3_sdram_mode(ddr, popts, dimm, cas_latency,
+ additive_latency);
+}
+
+uint32_t check_fsl_memctl_config_regs(const struct fsl_ddr_cfg_regs_s *ddr)
+{
+ /*
+ * DDR_SDRAM_CFG[RD_EN] and DDR_SDRAM_CFG[2T_EN should not
+ * be set at the same time.
+ */
+ if ((ddr->ddr_sdram_cfg & 0x10000000) &&
+ (ddr->ddr_sdram_cfg & 0x00008000))
+ return 1;
+
+ return 0;
+}
+
+static void set_timing_cfg_4(struct fsl_ddr_cfg_regs_s *ddr,
+ const struct memctl_options_s *popts)
+{
+ uint32_t rrt = 0, wwt = 0, dll_lock = 1;
+
+ if (popts->burst_length != DDR_BL8)
+ rrt = wwt = 2;
+
+ ddr->timing_cfg_4 = (((rrt & 0xf) << 20)
+ | ((wwt & 0xf) << 16)
+ | (dll_lock & 0x3)
+ );
+}
+
+static void set_timing_cfg_5(struct fsl_ddr_cfg_regs_s *ddr,
+ const struct memctl_options_s *popts,
+ uint32_t cas_latency)
+{
+ uint32_t rodt_on, rodt_off = 4, wodt_on = 1, wodt_off = 4;
+
+ /* rodt_on = timing_cfg_1[caslat] - timing_cfg_2[wrlat] + 1 */
+ rodt_on = cas_latency - ((ddr->timing_cfg_2 & 0x00780000) >> 19) + 1;
+
+ ddr->timing_cfg_5 = (((rodt_on & 0x1f) << 24)
+ | ((rodt_off & 0x7) << 20)
+ | ((wodt_on & 0x1f) << 12)
+ | ((wodt_off & 0x7) << 8)
+ );
+}
+
+static void set_ddr_zq_cntl(struct fsl_ddr_cfg_regs_s *ddr, uint32_t zq_en)
+{
+ uint32_t zqinit = 0, zqoper = 0, zqcs = 0;
+
+ if (zq_en) {
+ zqinit = 9;
+ zqoper = 8;
+ zqcs = 6;
+ }
+
+ ddr->ddr_zq_cntl = (((zq_en & 0x1) << 31)
+ | ((zqinit & 0xf) << 24)
+ | ((zqoper & 0xf) << 16)
+ | ((zqcs & 0xf) << 8)
+ );
+}
+
+static void set_ddr_wrlvl_cntl(struct fsl_ddr_cfg_regs_s *ddr,
+ uint32_t wrlvl_en, const struct memctl_options_s *popts)
+{
+ uint32_t wrlvl_mrd = 0, wrlvl_odten = 0, wrlvl_dqsen = 0,
+ wrlvl_wlr = 0, wrlvl_start = 0, wrlvl_smpl = 0;
+
+ /* Enable write leveling for DDR3 due to fly-by topology */
+ if (wrlvl_en) {
+ wrlvl_mrd = 0x6;
+ wrlvl_odten = 0x7;
+ wrlvl_dqsen = 0x5;
+ /*
+ * Write leveling sample time at least need 6 clocks
+ * higher than tWLO to allow enough time for progagation
+ * delay and sampling the prime data bits.
+ */
+ wrlvl_smpl = 0xf;
+ /*
+ * Write leveling repetition time. At least tWLO + 6 clocks
+ * Set it to 64
+ */
+ wrlvl_wlr = 0x6;
+ /*
+ * Write leveling start time
+ * The value use for the DQS_ADJUST for the first sample
+ * when write leveling is enabled. It probably needs to be
+ * overriden per platform.
+ */
+ wrlvl_start = 0x8;
+ if (popts->wrlvl_override) {
+ wrlvl_smpl = popts->wrlvl_sample;
+ wrlvl_start = popts->wrlvl_start;
+ }
+ }
+
+ ddr->ddr_wrlvl_cntl = (((wrlvl_en & 0x1) << 31)
+ | ((wrlvl_mrd & 0x7) << 24)
+ | ((wrlvl_odten & 0x7) << 20)
+ | ((wrlvl_dqsen & 0x7) << 16)
+ | ((wrlvl_smpl & 0xf) << 12)
+ | ((wrlvl_wlr & 0x7) << 8)
+ | ((wrlvl_start & 0x1f) << 0)
+ );
+}
+
+uint32_t
+compute_fsl_memctl_config_regs(const struct memctl_options_s *popts,
+ struct fsl_ddr_cfg_regs_s *ddr,
+ const struct common_timing_params_s *dimm,
+ const struct dimm_params_s *dimmp,
+ uint32_t dbw_cap_adj)
+{
+ struct ddr_board_info_s *binfo = popts->board_info;
+ uint32_t cas_latency, additive_latency, i, cs_per_dimm,
+ dimm_number, zq_en, wrlvl_en, sr_it = 0;
+ uint64_t ea, sa, rank_density;
+
+ if (dimm == NULL)
+ return 1;
+
+ memset(ddr, 0, sizeof(struct fsl_ddr_cfg_regs_s));
+
+ /* Process overrides first. */
+ if (popts->cas_latency_override)
+ cas_latency = popts->cas_latency_override_value;
+ else
+ cas_latency = dimm->lowest_common_SPD_caslat;
+
+ if (popts->additive_latency_override)
+ additive_latency = popts->additive_latency_override_value;
+ else
+ additive_latency = dimm->additive_latency;
+
+ if (popts->auto_self_refresh_en)
+ sr_it = popts->sr_it;
+
+ /* Chip Select Memory Bounds (CSn_BNDS) */
+ for (i = 0; i < binfo->cs_per_ctrl; i++) {
+ cs_per_dimm = binfo->cs_per_ctrl / binfo->dimm_slots_per_ctrl;
+ dimm_number = i / cs_per_dimm;
+ rank_density =
+ dimmp[dimm_number].rank_density >> dbw_cap_adj;
+
+ if (dimmp[dimm_number].n_ranks == 0)
+ continue;
+
+ sa = dimmp[dimm_number].base_address;
+ ea = sa + rank_density - 1;
+ if (dimmp[dimm_number].n_ranks > (i % cs_per_dimm)) {
+ sa += (i % cs_per_dimm) * rank_density;
+ ea += (i % cs_per_dimm) * rank_density;
+ } else {
+ sa = 0;
+ ea = 0;
+ }
+ sa >>= 24;
+ ea >>= 24;
+
+ ddr->cs[i].bnds =
+ (((sa & 0xffff) << 16) | ((ea & 0xffff) << 0));
+ set_csn_config(dimm_number, i, ddr, popts, dimmp);
+ }
+
+ set_timing_cfg_0(ddr, popts, dimmp);
+ set_timing_cfg_3(ddr, popts, dimm, cas_latency, additive_latency);
+ set_timing_cfg_1(ddr, popts, dimm, cas_latency);
+ set_timing_cfg_2(ddr, popts, dimm, cas_latency, additive_latency);
+
+ ddr->ddr_cdr1 = popts->ddr_cdr1;
+ ddr->ddr_cdr1 = popts->ddr_cdr2;
+
+ set_ddr_sdram_cfg(ddr, popts, dimm);
+ set_ddr_sdram_cfg_2(ddr, popts);
+ set_ddrx_sdram_mode(ddr, popts, dimm, cas_latency, additive_latency);
+ if (popts->sdram_type == SDRAM_TYPE_DDR3) {
+ set_ddr_sdram_mode_2(ddr, popts, dimm);
+ set_timing_cfg_4(ddr, popts);
+ set_timing_cfg_5(ddr, popts, cas_latency);
+ zq_en = (popts->zq_en) ? 1 : 0;
+ set_ddr_zq_cntl(ddr, zq_en);
+ wrlvl_en = (popts->wrlvl_en) ? 1 : 0;
+ set_ddr_wrlvl_cntl(ddr, wrlvl_en, popts);
+ }
+ set_ddr_sdram_interval(ddr, popts, dimm);
+
+ ddr->ddr_data_init = popts->data_init;
+ ddr->ddr_sdram_clk_cntl = (popts->clk_adjust & 0xF) << 23;
+
+ ddr->ddr_sr_cntr = (sr_it & 0xf) << 16;
+
+ return check_fsl_memctl_config_regs(ddr);
+}
diff --git a/arch/powerpc/ddr-8xxx/ddr.h b/arch/powerpc/ddr-8xxx/ddr.h
new file mode 100644
index 0000000000..8560e37167
--- /dev/null
+++ b/arch/powerpc/ddr-8xxx/ddr.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2013 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_MAIN_H
+#define FSL_DDR_MAIN_H
+
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/fsl_ddr_dimm_params.h>
+#include <mach/fsl_i2c.h>
+#include <mach/clock.h>
+#include "common_timing_params.h"
+
+#ifdef CONFIG_MPC85xx
+#include <mach/immap_85xx.h>
+#endif
+
+/* Record of computed register values. */
+struct fsl_ddr_cfg_regs_s {
+ struct {
+ uint32_t bnds;
+ uint32_t config;
+ uint32_t config_2;
+ } cs[MAX_CHIP_SELECTS_PER_CTRL];
+ uint32_t timing_cfg_3;
+ uint32_t timing_cfg_0;
+ uint32_t timing_cfg_1;
+ uint32_t timing_cfg_2;
+ uint32_t ddr_sdram_cfg;
+ uint32_t ddr_sdram_cfg_2;
+ uint32_t ddr_sdram_mode;
+ uint32_t ddr_sdram_mode_2;
+ uint32_t ddr_sdram_mode_3;
+ uint32_t ddr_sdram_mode_4;
+ uint32_t ddr_sdram_mode_5;
+ uint32_t ddr_sdram_mode_6;
+ uint32_t ddr_sdram_mode_7;
+ uint32_t ddr_sdram_mode_8;
+ uint32_t ddr_sdram_md_cntl;
+ uint32_t ddr_sdram_interval;
+ uint32_t ddr_data_init;
+ uint32_t ddr_sdram_clk_cntl;
+ uint32_t ddr_init_addr;
+ uint32_t ddr_init_ext_addr;
+ uint32_t timing_cfg_4;
+ uint32_t timing_cfg_5;
+ uint32_t ddr_zq_cntl;
+ uint32_t ddr_wrlvl_cntl;
+ uint32_t ddr_wrlvl_cntl_2;
+ uint32_t ddr_wrlvl_cntl_3;
+ uint32_t ddr_sr_cntr;
+ uint32_t ddr_sdram_rcw_1;
+ uint32_t ddr_sdram_rcw_2;
+ uint32_t ddr_cdr1;
+ uint32_t ddr_cdr2;
+ uint32_t err_disable;
+ uint32_t err_int_en;
+ uint32_t debug[32];
+};
+
+/*
+ * Data Structures
+ *
+ * All data structures have to be on the stack
+ */
+struct fsl_ddr_info_s {
+ generic_spd_eeprom_t
+ spd_installed_dimms[MAX_DIMM_SLOTS_PER_CTLR];
+ struct dimm_params_s
+ dimm_params[MAX_DIMM_SLOTS_PER_CTLR];
+ struct memctl_options_s memctl_opts;
+ struct common_timing_params_s common_timing_params;
+ struct fsl_ddr_cfg_regs_s fsl_ddr_config_reg;
+ struct ddr_board_info_s board_info;
+};
+
+uint32_t mclk_to_picos(uint32_t mclk);
+uint32_t get_memory_clk_period_ps(void);
+uint32_t picos_to_mclk(uint32_t picos);
+uint32_t check_fsl_memctl_config_regs(const struct fsl_ddr_cfg_regs_s *ddr);
+uint64_t fsl_ddr_compute(struct fsl_ddr_info_s *pinfo);
+uint32_t compute_fsl_memctl_config_regs(
+ const struct memctl_options_s *popts,
+ struct fsl_ddr_cfg_regs_s *ddr,
+ const struct common_timing_params_s *common_dimm,
+ const struct dimm_params_s *dimm_parameters,
+ uint32_t dbw_capacity_adjust);
+uint32_t compute_dimm_parameters(
+ const generic_spd_eeprom_t *spdin,
+ struct dimm_params_s *pdimm);
+void compute_lowest_common_dimm_parameters(
+ const struct fsl_ddr_info_s *pinfo,
+ struct common_timing_params_s *outpdimm,
+ uint32_t number_of_dimms);
+uint32_t populate_memctl_options(
+ int all_DIMMs_registered,
+ struct memctl_options_s *popts,
+ struct dimm_params_s *pdimm);
+int fsl_ddr_set_lawbar(
+ const struct common_timing_params_s *memctl_common_params,
+ uint32_t memctl_interleaved);
+int fsl_ddr_get_spd(
+ generic_spd_eeprom_t *ctrl_dimms_spd,
+ struct ddr_board_info_s *binfo);
+int fsl_ddr_set_memctl_regs(
+ const struct fsl_ddr_info_s *info);
+#endif
diff --git a/arch/powerpc/ddr-8xxx/ddr2_dimm_params.c b/arch/powerpc/ddr-8xxx/ddr2_dimm_params.c
new file mode 100644
index 0000000000..80d01ab366
--- /dev/null
+++ b/arch/powerpc/ddr-8xxx/ddr2_dimm_params.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/fsl_ddr_sdram.h>
+#include "ddr.h"
+/*
+ * Calculate the Density of each Physical Rank.
+ * Returned size is in bytes.
+ *
+ * Table comes from Byte 31 of JEDEC SPD Spec.
+ *
+ * DDR II
+ * Bit Size Size
+ * --- -----
+ * 7 high 512MB
+ * 6 256MB
+ * 5 128MB
+ * 4 16GB
+ * 3 8GB
+ * 2 4GB
+ * 1 2GB
+ * 0 low 1GB
+ *
+ * Reorder Table to be linear by stripping the bottom
+ * 2 or 5 bits off and shifting them up to the top.
+ *
+ */
+static uint64_t compute_ranksize(uint32_t mem_type, unsigned char row_dens)
+{
+ uint64_t bsize;
+
+ bsize = ((row_dens >> 5) | ((row_dens & 31) << 3));
+ bsize <<= 27ULL;
+
+ return bsize;
+}
+
+/*
+ * Convert a two-nibble BCD value into a cycle time.
+ * While the spec calls for nano-seconds, picos are returned.
+ */
+static uint32_t convert_bcd_tenths_to_cycle_time_ps(uint32_t spd_val)
+{
+ uint32_t tenths_ps[16] = {
+ 0,
+ 100,
+ 200,
+ 300,
+ 400,
+ 500,
+ 600,
+ 700,
+ 800,
+ 900,
+ 250,
+ 330,
+ 660,
+ 750,
+ 0,
+ 0
+ };
+ uint32_t whole_ns = (spd_val & 0xF0) >> 4;
+ uint32_t tenth_ns = spd_val & 0x0F;
+ uint32_t ps = (whole_ns * 1000) + tenths_ps[tenth_ns];
+
+ return ps;
+}
+
+static uint32_t convert_bcd_hundredths_to_cycle_time_ps(uint32_t spd_val)
+{
+ uint32_t tenth_ns = (spd_val & 0xF0) >> 4;
+ uint32_t hundredth_ns = spd_val & 0x0F;
+ uint32_t ps = (tenth_ns * 100) + (hundredth_ns * 10);
+
+ return ps;
+}
+
+static uint32_t byte40_table_ps[8] = {
+ 0,
+ 250,
+ 330,
+ 500,
+ 660,
+ 750,
+ 0,
+ 0
+};
+
+static uint32_t
+compute_trfc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trfc)
+{
+ uint32_t trfc_ps;
+
+ trfc_ps = (((trctrfc_ext & 0x1) * 256) + trfc) * 1000;
+ trfc_ps += byte40_table_ps[(trctrfc_ext >> 1) & 0x7];
+
+ return trfc_ps;
+}
+
+static uint32_t
+compute_trc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trc)
+{
+ uint32_t trc_ps;
+
+ trc_ps = (trc * 1000);
+ trc_ps += byte40_table_ps[(trctrfc_ext >> 4) & 0x7];
+
+ return trc_ps;
+}
+
+/*
+ * Determine Refresh Rate.
+ * Table from SPD Spec, Byte 12, converted to picoseconds and
+ * filled in with "default" normal values.
+ */
+static uint32_t determine_refresh_rate_ps(const uint32_t spd_refresh)
+{
+ uint32_t refresh_time_ps[8] = {
+ 15625000, /* 0 Normal 1.00x */
+ 3900000, /* 1 Reduced .25x */
+ 7800000, /* 2 Extended .50x */
+ 31300000, /* 3 Extended 2.00x */
+ 62500000, /* 4 Extended 4.00x */
+ 125000000, /* 5 Extended 8.00x */
+ 15625000, /* 6 Normal 1.00x filler */
+ 15625000, /* 7 Normal 1.00x filler */
+ };
+
+ return refresh_time_ps[spd_refresh & 0x7];
+}
+
+/*
+ * The purpose of this function is to compute a suitable
+ * CAS latency given the DRAM clock period. The SPD only
+ * defines at most 3 CAS latencies. Typically the slower in
+ * frequency the DIMM runs at, the shorter its CAS latency can.
+ * be. If the DIMM is operating at a sufficiently low frequency,
+ * it may be able to run at a CAS latency shorter than the
+ * shortest SPD-defined CAS latency.
+ *
+ * If a CAS latency is not found, 0 is returned.
+ *
+ * Do this by finding in the standard speed table the longest
+ * tCKmin that doesn't exceed the value of mclk_ps (tCK).
+ *
+ * An assumption made is that the SDRAM device allows the
+ * CL to be programmed for a value that is lower than those
+ * advertised by the SPD. This is not always the case,
+ * as those modes not defined in the SPD are optional.
+ *
+ * CAS latency de-rating based upon values JEDEC Standard No. 79-2C
+ * Table 40, "DDR2 SDRAM standard speed bins and tCK, tRCD, tRP, tRAS,
+ * and tRC for corresponding bin"
+ *
+ * ordinal 2, ddr2_speed_bins[1] contains tCK for CL=3
+ * Not certain if any good value exists for CL=2
+ */
+ /* CL2 CL3 CL4 CL5 CL6 CL7 */
+static uint16_t ddr2_speed_bins[] = { 0, 5000, 3750, 3000, 2500, 1875 };
+
+static uint32_t compute_derated_DDR2_CAS_latency(uint32_t mclk_ps)
+{
+ const uint32_t num_speed_bins = ARRAY_SIZE(ddr2_speed_bins);
+ uint32_t lowest_tCKmin_found = 0, lowest_tCKmin_CL = 0, i, x;
+
+ for (i = 0; i < num_speed_bins; i++) {
+ x = ddr2_speed_bins[i];
+ if (x && (x <= mclk_ps) && (x >= lowest_tCKmin_found)) {
+ lowest_tCKmin_found = x;
+ lowest_tCKmin_CL = i + 2;
+ }
+ }
+
+ return lowest_tCKmin_CL;
+}
+
+/*
+ * compute_dimm_parameters for DDR2 SPD
+ *
+ * Compute DIMM parameters based upon the SPD information in SPD.
+ * Writes the results to the dimm_params_s structure pointed by pdimm.
+ */
+uint32_t
+compute_dimm_parameters(const generic_spd_eeprom_t *spdin,
+ struct dimm_params_s *pdimm)
+{
+ const struct ddr2_spd_eeprom *spd = spdin;
+ int retval;
+
+ if (spd->mem_type != SPD_MEMTYPE_DDR2)
+ goto error;
+
+ retval = ddr2_spd_check(spd);
+ if (retval)
+ goto error;
+
+ /*
+ * The part name in ASCII in the SPD EEPROM is not null terminated.
+ * Guarantee null termination here by presetting all bytes to 0
+ * and copying the part name in ASCII from the SPD onto it
+ */
+ memset(pdimm->mpart, 0, sizeof(pdimm->mpart));
+ memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1);
+
+ /* DIMM organization parameters */
+ pdimm->n_ranks = (spd->mod_ranks & 0x7) + 1;
+ pdimm->rank_density = compute_ranksize(spd->mem_type, spd->rank_dens);
+ pdimm->capacity = pdimm->n_ranks * pdimm->rank_density;
+ pdimm->data_width = spd->dataw;
+ pdimm->primary_sdram_width = spd->primw;
+ pdimm->ec_sdram_width = spd->ecw;
+
+ /* These are all the types defined by the JEDEC DDR2 SPD 1.3 spec */
+ switch (spd->dimm_type) {
+ case DDR2_SPD_DIMMTYPE_RDIMM:
+ case DDR2_SPD_DIMMTYPE_72B_SO_RDIMM:
+ case DDR2_SPD_DIMMTYPE_MINI_RDIMM:
+ /* Registered/buffered DIMMs */
+ pdimm->registered_dimm = 1;
+ break;
+
+ case DDR2_SPD_DIMMTYPE_UDIMM:
+ case DDR2_SPD_DIMMTYPE_SO_DIMM:
+ case DDR2_SPD_DIMMTYPE_MICRO_DIMM:
+ case DDR2_SPD_DIMMTYPE_MINI_UDIMM:
+ /* Unbuffered DIMMs */
+ pdimm->registered_dimm = 0;
+ break;
+
+ case DDR2_SPD_DIMMTYPE_72B_SO_CDIMM:
+ default:
+ goto error;
+ }
+
+ pdimm->n_row_addr = spd->nrow_addr;
+ pdimm->n_col_addr = spd->ncol_addr;
+ pdimm->n_banks_per_sdram_device = spd->nbanks;
+ pdimm->edc_config = spd->config;
+ pdimm->burst_lengths_bitmask = spd->burstl;
+ pdimm->row_density = spd->rank_dens;
+
+ /*
+ * Calculate the Maximum Data Rate based on the Minimum Cycle time.
+ * The SPD clk_cycle field (tCKmin) is measured in tenths of
+ * nanoseconds and represented as BCD.
+ */
+ pdimm->tCKmin_X_ps
+ = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle);
+ pdimm->tCKmin_X_minus_1_ps
+ = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle2);
+ pdimm->tCKmin_X_minus_2_ps
+ = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle3);
+ pdimm->tCKmax_ps = convert_bcd_tenths_to_cycle_time_ps(spd->tckmax);
+
+ /*
+ * Compute CAS latencies defined by SPD
+ * The SPD caslat_X should have at least 1 and at most 3 bits set.
+ *
+ * If cas_lat after masking is 0, the __ilog2 function returns
+ * 255 into the variable. This behavior is abused once.
+ */
+ pdimm->caslat_X = __ilog2(spd->cas_lat);
+ pdimm->caslat_X_minus_1 = __ilog2(spd->cas_lat
+ & ~(1 << pdimm->caslat_X));
+ pdimm->caslat_X_minus_2 = __ilog2(spd->cas_lat & ~(1 << pdimm->caslat_X)
+ & ~(1 << pdimm->caslat_X_minus_1));
+ pdimm->caslat_lowest_derated
+ = compute_derated_DDR2_CAS_latency(get_memory_clk_period_ps());
+ pdimm->tRCD_ps = spd->trcd * 250;
+ pdimm->tRP_ps = spd->trp * 250;
+ pdimm->tRAS_ps = spd->tras * 1000;
+ pdimm->tWR_ps = spd->twr * 250;
+ pdimm->tWTR_ps = spd->twtr * 250;
+ pdimm->tRFC_ps = compute_trfc_ps_from_spd(spd->trctrfc_ext, spd->trfc);
+ pdimm->tRRD_ps = spd->trrd * 250;
+ pdimm->tRC_ps = compute_trc_ps_from_spd(spd->trctrfc_ext, spd->trc);
+ pdimm->refresh_rate_ps = determine_refresh_rate_ps(spd->refresh);
+ pdimm->tIS_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_setup);
+ pdimm->tIH_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_hold);
+ pdimm->tDS_ps
+ = convert_bcd_hundredths_to_cycle_time_ps(spd->data_setup);
+ pdimm->tDH_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->data_hold);
+ pdimm->tRTP_ps = spd->trtp * 250;
+ pdimm->tDQSQ_max_ps = spd->tdqsq * 10;
+ pdimm->tQHS_ps = spd->tqhs * 10;
+
+ return 0;
+error:
+ return 1;
+}
diff --git a/arch/powerpc/ddr-8xxx/ddr3_dimm_params.c b/arch/powerpc/ddr-8xxx/ddr3_dimm_params.c
new file mode 100644
index 0000000000..4f44925ab9
--- /dev/null
+++ b/arch/powerpc/ddr-8xxx/ddr3_dimm_params.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor, Inc.
+ * Dave Liu <daveliu@freescale.com>
+ *
+ * calculate the organization and timing parameter
+ * from ddr3 spd, please refer to the spec
+ * JEDEC standard No.21-C 4_01_02_11R18.pdf
+ *
+ * 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_ddr_sdram.h>
+#include "ddr.h"
+
+/*
+ * Calculate the Density of each Physical Rank.
+ * Returned size is in bytes.
+ *
+ * each rank size =
+ * sdram capacity(bit) / 8 * primary bus width / sdram width
+ *
+ * where: sdram capacity = spd byte4[3:0]
+ * primary bus width = spd byte8[2:0]
+ * sdram width = spd byte7[2:0]
+ *
+ * SPD byte4 - sdram density and banks
+ * bit[3:0] size(bit) size(byte)
+ * 0000 256Mb 32MB
+ * 0001 512Mb 64MB
+ * 0010 1Gb 128MB
+ * 0011 2Gb 256MB
+ * 0100 4Gb 512MB
+ * 0101 8Gb 1GB
+ * 0110 16Gb 2GB
+ *
+ * SPD byte8 - module memory bus width
+ * bit[2:0] primary bus width
+ * 000 8bits
+ * 001 16bits
+ * 010 32bits
+ * 011 64bits
+ *
+ * SPD byte7 - module organiztion
+ * bit[2:0] sdram device width
+ * 000 4bits
+ * 001 8bits
+ * 010 16bits
+ * 011 32bits
+ */
+static uint64_t compute_ranksize(const struct ddr3_spd_eeprom *spd)
+{
+ uint64_t bsize;
+ int sdram_cap_bsize = 0, prim_bus_width = 0, sdram_width = 0;
+
+ if ((spd->density_banks & 0xf) < 7)
+ sdram_cap_bsize = (spd->density_banks & 0xf) + 28;
+ if ((spd->bus_width & 0x7) < 4)
+ prim_bus_width = (spd->bus_width & 0x7) + 3;
+ if ((spd->organization & 0x7) < 4)
+ sdram_width = (spd->organization & 0x7) + 2;
+
+ bsize = 1ULL << (sdram_cap_bsize - 3 + prim_bus_width - sdram_width);
+
+ return bsize;
+}
+
+/*
+ * compute_dimm_parameters for DDR3 SPD
+ *
+ * Compute DIMM parameters based upon the SPD information in spd.
+ * Writes the results to the dimm_params_s structure pointed by pdimm.
+ *
+ */
+uint32_t
+compute_dimm_parameters(const generic_spd_eeprom_t *spdin,
+ struct dimm_params_s *pdimm)
+{
+ const struct ddr3_spd_eeprom *spd = spdin;
+ uint32_t mtb_ps;
+ int retval, ftb_tmp;
+
+ if (spd->mem_type != SPD_MEMTYPE_DDR3)
+ goto error;
+
+ retval = ddr3_spd_check(spd);
+ if (retval)
+ goto error;
+
+ memset(pdimm->mpart, 0, sizeof(pdimm->mpart));
+ if ((spd->info_size_crc & 0xf) > 1)
+ memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1);
+
+ /* DIMM organization parameters */
+ pdimm->n_ranks = ((spd->organization >> 3) & 0x7) + 1;
+ pdimm->rank_density = compute_ranksize(spd);
+ pdimm->capacity = pdimm->n_ranks * pdimm->rank_density;
+ pdimm->data_width = pdimm->primary_sdram_width + pdimm->ec_sdram_width;
+ pdimm->primary_sdram_width = 1 << (3 + (spd->bus_width & 0x7));
+ if ((spd->bus_width >> 3) & 0x3)
+ pdimm->ec_sdram_width = 8;
+ else
+ pdimm->ec_sdram_width = 0;
+ pdimm->device_width = 1 << ((spd->organization & 0x7) + 2);
+
+ /* These are the types defined by the JEDEC DDR3 SPD spec */
+ pdimm->mirrored_dimm = 0;
+ pdimm->registered_dimm = 0;
+ switch (spd->module_type & DDR3_SPD_MODULETYPE_MASK) {
+ case DDR3_SPD_MODULETYPE_UDIMM:
+ /* Unbuffered DIMMs */
+ if (spd->mod_section.unbuffered.addr_mapping & 0x1)
+ pdimm->mirrored_dimm = 1;
+ break;
+
+ default:
+ goto error;
+ }
+
+ /* SDRAM device parameters */
+ pdimm->n_row_addr = ((spd->addressing >> 3) & 0x7) + 12;
+ pdimm->n_col_addr = (spd->addressing & 0x7) + 9;
+ pdimm->n_banks_per_sdram_device =
+ 8 << ((spd->density_banks >> 4) & 0x7);
+
+ /*
+ * The SPD spec does not define an ECC bit. The DIMM is considered
+ * to have ECC capability if the extension bus exists.
+ */
+ if (pdimm->ec_sdram_width)
+ pdimm->edc_config = 0x02;
+ else
+ pdimm->edc_config = 0x00;
+
+ /*
+ * The SPD spec does not define the burst length byte.
+ * but the DDR3 spec defines BL8 and BC4, on bit 3 and
+ * bit 2.
+ */
+ pdimm->burst_lengths_bitmask = 0x0c;
+ pdimm->row_density = __ilog2(pdimm->rank_density);
+
+ mtb_ps = (spd->mtb_dividend * 1000) / spd->mtb_divisor;
+ pdimm->mtb_ps = mtb_ps;
+
+ ftb_tmp = spd->ftb_div & 0xf0;
+ pdimm->ftb_10th_ps = ((ftb_tmp >> 4) * 10) / ftb_tmp;
+
+ pdimm->tCKmin_X_ps = spd->tck_min * mtb_ps +
+ (spd->fine_tck_min * ftb_tmp) / 10;
+ pdimm->caslat_X = ((spd->caslat_msb << 8) | spd->caslat_lsb) << 4;
+
+ pdimm->taa_ps = spd->taa_min * mtb_ps +
+ (spd->fine_taa_min * ftb_tmp) / 10;
+
+ pdimm->tRCD_ps = spd->trcd_min * mtb_ps +
+ (spd->fine_trcd_min * ftb_tmp) / 10;
+
+ pdimm->tRP_ps = spd->trp_min * mtb_ps +
+ (spd->fine_trp_min * ftb_tmp) / 10;
+ pdimm->tRAS_ps = (((spd->tras_trc_ext & 0xf) << 8) | spd->tras_min_lsb)
+ * mtb_ps;
+ pdimm->tWR_ps = spd->twr_min * mtb_ps;
+ pdimm->tWTR_ps = spd->twtr_min * mtb_ps;
+ pdimm->tRFC_ps = ((spd->trfc_min_msb << 8) | spd->trfc_min_lsb)
+ * mtb_ps;
+ pdimm->tRRD_ps = spd->trrd_min * mtb_ps;
+ pdimm->tRC_ps = (((spd->tras_trc_ext & 0xf0) << 4) | spd->trc_min_lsb);
+ pdimm->tRC_ps *= mtb_ps;
+ pdimm->tRC_ps += (spd->fine_trc_min * ftb_tmp) / 10;
+
+ pdimm->tRTP_ps = spd->trtp_min * mtb_ps;
+
+ /*
+ * Average periodic refresh interval
+ * tREFI = 7.8 us at normal temperature range
+ * = 3.9 us at ext temperature range
+ */
+ pdimm->refresh_rate_ps = 7800000;
+ if ((spd->therm_ref_opt & 0x1) && !(spd->therm_ref_opt & 0x2)) {
+ pdimm->refresh_rate_ps = 3900000;
+ pdimm->extended_op_srt = 1;
+ }
+
+ pdimm->tfaw_ps = (((spd->tfaw_msb & 0xf) << 8) | spd->tfaw_min)
+ * mtb_ps;
+
+ return 0;
+error:
+ return 1;
+}
diff --git a/arch/powerpc/ddr-8xxx/ddr_setctrl.c b/arch/powerpc/ddr-8xxx/ddr_setctrl.c
new file mode 100644
index 0000000000..115fb42070
--- /dev/null
+++ b/arch/powerpc/ddr-8xxx/ddr_setctrl.c
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/io.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/processor.h>
+#include <mach/early_udelay.h>
+#include "ddr.h"
+
+int fsl_ddr_set_memctl_regs(const struct fsl_ddr_info_s *info)
+{
+ uint32_t i, temp_sdram_cfg;
+ void __iomem *ddr;
+ const struct fsl_ddr_cfg_regs_s *regs;
+
+ regs = &info->fsl_ddr_config_reg;
+ ddr = info->board_info.ddr_base;
+
+ if (in_be32(ddr + DDR_OFF(SDRAM_CFG)) & SDRAM_CFG_MEM_EN)
+ return 0;
+
+ for (i = 0; i < info->board_info.cs_per_ctrl; i++) {
+ out_be32(ddr + DDR_OFF(CS0_BNDS) + (i << 3), regs->cs[i].bnds);
+ out_be32(ddr + DDR_OFF(CS0_CONFIG) + (i << 2),
+ regs->cs[i].config);
+ if (info->memctl_opts.sdram_type == SDRAM_TYPE_DDR3)
+ out_be32(ddr + DDR_OFF(CS0_CONFIG_2) + (i << 2),
+ regs->cs[i].config_2);
+ }
+
+ out_be32(ddr + DDR_OFF(TIMING_CFG_3), regs->timing_cfg_3);
+ out_be32(ddr + DDR_OFF(TIMING_CFG_0), regs->timing_cfg_0);
+ out_be32(ddr + DDR_OFF(TIMING_CFG_1), regs->timing_cfg_1);
+ out_be32(ddr + DDR_OFF(TIMING_CFG_2), regs->timing_cfg_2);
+ out_be32(ddr + DDR_OFF(SDRAM_CFG_2), regs->ddr_sdram_cfg_2);
+ out_be32(ddr + DDR_OFF(SDRAM_MODE), regs->ddr_sdram_mode);
+ out_be32(ddr + DDR_OFF(SDRAM_MODE_2), regs->ddr_sdram_mode_2);
+ out_be32(ddr + DDR_OFF(SDRAM_MD_CNTL), regs->ddr_sdram_md_cntl);
+ out_be32(ddr + DDR_OFF(SDRAM_INTERVAL), regs->ddr_sdram_interval);
+ out_be32(ddr + DDR_OFF(SDRAM_DATA_INIT), regs->ddr_data_init);
+ out_be32(ddr + DDR_OFF(SDRAM_CLK_CNTL), regs->ddr_sdram_clk_cntl);
+ out_be32(ddr + DDR_OFF(SDRAM_INIT_ADDR), regs->ddr_init_addr);
+ out_be32(ddr + DDR_OFF(SDRAM_INIT_ADDR_EXT), regs->ddr_init_ext_addr);
+
+ if (info->memctl_opts.sdram_type == SDRAM_TYPE_DDR3) {
+ out_be32(ddr + DDR_OFF(TIMING_CFG_4), regs->timing_cfg_4);
+ out_be32(ddr + DDR_OFF(TIMING_CFG_5), regs->timing_cfg_5);
+ out_be32(ddr + DDR_OFF(ZQ_CNTL), regs->ddr_zq_cntl);
+ out_be32(ddr + DDR_OFF(WRLVL_CNTL), regs->ddr_wrlvl_cntl);
+
+ if (regs->ddr_wrlvl_cntl_2)
+ out_be32(ddr + DDR_OFF(WRLVL_CNTL_2),
+ regs->ddr_wrlvl_cntl_2);
+ if (regs->ddr_wrlvl_cntl_3)
+ out_be32(ddr + DDR_OFF(WRLVL_CNTL_3),
+ regs->ddr_wrlvl_cntl_3);
+
+ out_be32(ddr + DDR_OFF(SR_CNTL), regs->ddr_sr_cntr);
+ out_be32(ddr + DDR_OFF(SDRAM_RCW_1), regs->ddr_sdram_rcw_1);
+ out_be32(ddr + DDR_OFF(SDRAM_RCW_2), regs->ddr_sdram_rcw_2);
+ out_be32(ddr + DDR_OFF(DDRCDR1), regs->ddr_cdr1);
+ out_be32(ddr + DDR_OFF(DDRCDR2), regs->ddr_cdr2);
+ }
+
+ out_be32(ddr + DDR_OFF(ERR_DISABLE), regs->err_disable);
+ out_be32(ddr + DDR_OFF(ERR_INT_EN), regs->err_int_en);
+
+ temp_sdram_cfg = regs->ddr_sdram_cfg;
+ temp_sdram_cfg &= ~(SDRAM_CFG_MEM_EN);
+ out_be32(ddr + DDR_OFF(SDRAM_CFG), temp_sdram_cfg);
+
+ early_udelay(500);
+ /* Make sure all instructions are completed before enabling memory.*/
+ asm volatile("sync;isync");
+ temp_sdram_cfg = in_be32(ddr + DDR_OFF(SDRAM_CFG)) & ~SDRAM_CFG_BI;
+ out_be32(ddr + DDR_OFF(SDRAM_CFG), temp_sdram_cfg | SDRAM_CFG_MEM_EN);
+ asm volatile("sync;isync");
+
+ while (in_be32(ddr + DDR_OFF(SDRAM_CFG_2)) & SDRAM_CFG2_D_INIT)
+ early_udelay(10000);
+
+ return 0;
+}
diff --git a/arch/powerpc/ddr-8xxx/lc_common_dimm_params.c b/arch/powerpc/ddr-8xxx/lc_common_dimm_params.c
new file mode 100644
index 0000000000..9d90fb76db
--- /dev/null
+++ b/arch/powerpc/ddr-8xxx/lc_common_dimm_params.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright 2008-2012 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 <config.h>
+#include <asm/fsl_ddr_sdram.h>
+
+#include "ddr.h"
+
+static uint32_t
+compute_cas_latency_ddr3(const struct dimm_params_s *dimm_params,
+ uint32_t number_of_dimms)
+{
+ uint32_t i, taamin_ps = 0, tckmin_x_ps = 0, common_caslat,
+ caslat_actual, retry = 16;
+ const uint32_t mclk_ps = get_memory_clk_period_ps();
+
+ /* compute the common CAS latency supported between slots */
+ common_caslat = dimm_params[0].caslat_X;
+ for (i = 1; i < number_of_dimms; i++) {
+ if (dimm_params[i].n_ranks)
+ common_caslat &= dimm_params[i].caslat_X;
+ }
+
+ for (i = 0; i < number_of_dimms; i++) {
+ taamin_ps = max(taamin_ps, dimm_params[i].taa_ps);
+ tckmin_x_ps = max(tckmin_x_ps, dimm_params[i].tCKmin_X_ps);
+ }
+
+ caslat_actual = (taamin_ps + mclk_ps - 1) / mclk_ps;
+ /* check if the dimms support the CAS latency */
+ while (!(common_caslat & (1 << caslat_actual)) && retry > 0) {
+ caslat_actual++;
+ retry--;
+ }
+
+ return caslat_actual;
+}
+
+static unsigned int common_burst_length(
+ const struct dimm_params_s *dimm_params,
+ const unsigned int number_of_dimms)
+{
+ unsigned int i, temp;
+
+ temp = 0xff;
+ for (i = 0; i < number_of_dimms; i++)
+ if (dimm_params[i].n_ranks)
+ temp &= dimm_params[i].burst_lengths_bitmask;
+ return temp;
+}
+
+/* Compute a CAS latency suitable for all DIMMs */
+static unsigned int compute_lowest_caslat(
+ const struct dimm_params_s *dimm_params,
+ const unsigned int number_of_dimms)
+{
+ uint32_t temp1, temp2, i, not_ok, lowest_good_caslat,
+ tCKmin_X_minus_1_ps, tCKmin_X_minus_2_ps;
+ const unsigned int mclk_ps = get_memory_clk_period_ps();
+
+ /*
+ * Step 1: find CAS latency common to all DIMMs using bitwise
+ * operation.
+ */
+ temp1 = 0xFF;
+ for (i = 0; i < number_of_dimms; i++)
+ if (dimm_params[i].n_ranks) {
+ temp2 = 0;
+ temp2 |= 1 << dimm_params[i].caslat_X;
+ temp2 |= 1 << dimm_params[i].caslat_X_minus_1;
+ temp2 |= 1 << dimm_params[i].caslat_X_minus_2;
+ /*
+ * FIXME: If there was no entry for X-2 (X-1) in
+ * the SPD, then caslat_X_minus_2
+ * (caslat_X_minus_1) contains either 255 or
+ * 0xFFFFFFFF because that's what the __ilog2
+ * function returns for an input of 0.
+ * On 32-bit PowerPC, left shift counts with bit
+ * 26 set (that the value of 255 or 0xFFFFFFFF
+ * will have), cause the destination register to
+ * be 0. That is why this works.
+ */
+ temp1 &= temp2;
+ }
+
+ /*
+ * Step 2: check each common CAS latency against tCK of each
+ * DIMM's SPD.
+ */
+ lowest_good_caslat = 0;
+ temp2 = 0;
+ while (temp1) {
+ not_ok = 0;
+ temp2 = __ilog2(temp1);
+
+ for (i = 0; i < number_of_dimms; i++) {
+ if (!dimm_params[i].n_ranks)
+ continue;
+
+ if (dimm_params[i].caslat_X == temp2) {
+ if (mclk_ps >= dimm_params[i].tCKmin_X_ps)
+ continue;
+ else
+ not_ok++;
+ }
+
+ if (dimm_params[i].caslat_X_minus_1 == temp2) {
+ tCKmin_X_minus_1_ps =
+ dimm_params[i].tCKmin_X_minus_1_ps;
+ if (mclk_ps >= tCKmin_X_minus_1_ps)
+ continue;
+ else
+ not_ok++;
+ }
+
+ if (dimm_params[i].caslat_X_minus_2 == temp2) {
+ tCKmin_X_minus_2_ps
+ = dimm_params[i].tCKmin_X_minus_2_ps;
+ if (mclk_ps >= tCKmin_X_minus_2_ps)
+ continue;
+ else
+ not_ok++;
+ }
+ }
+
+ if (!not_ok)
+ lowest_good_caslat = temp2;
+
+ temp1 &= ~(1 << temp2);
+ }
+ return lowest_good_caslat;
+}
+
+/*
+ * compute_lowest_common_dimm_parameters()
+ *
+ * Determine the worst-case DIMM timing parameters from the set of DIMMs
+ * whose parameters have been computed into the array pointed to
+ * by dimm_params.
+ */
+void compute_lowest_common_dimm_parameters(const struct fsl_ddr_info_s *pinfo,
+ struct common_timing_params_s *out,
+ const unsigned int number_of_dimms)
+{
+ uint32_t temp1, i;
+ struct common_timing_params_s tmp = {0};
+ const struct dimm_params_s *dimm = pinfo->dimm_params;
+ const struct memctl_options_s *popts = &pinfo->memctl_opts;
+
+ tmp.tCKmax_ps = 0xFFFFFFFF;
+ tmp.extended_op_srt = 1;
+ temp1 = 0;
+ for (i = 0; i < number_of_dimms; i++) {
+ if (dimm[i].n_ranks == 0) {
+ temp1++;
+ continue;
+ }
+
+ /*
+ * Find minimum tCKmax_ps to find fastest slow speed,
+ * i.e., this is the slowest the whole system can go.
+ */
+ tmp.tCKmax_ps = min(tmp.tCKmax_ps, dimm[i].tCKmax_ps);
+
+ /* Find maximum value to determine slowest speed, delay, etc */
+ tmp.tCKmin_X_ps = max(tmp.tCKmin_X_ps, dimm[i].tCKmin_X_ps);
+ tmp.tCKmax_max_ps = max(tmp.tCKmax_max_ps, dimm[i].tCKmax_ps);
+ tmp.tRCD_ps = max(tmp.tRCD_ps, dimm[i].tRCD_ps);
+ tmp.tRP_ps = max(tmp.tRP_ps, dimm[i].tRP_ps);
+ tmp.tRAS_ps = max(tmp.tRAS_ps, dimm[i].tRAS_ps);
+ tmp.tWR_ps = max(tmp.tWR_ps, dimm[i].tWR_ps);
+ tmp.tWTR_ps = max(tmp.tWTR_ps, dimm[i].tWTR_ps);
+ tmp.tRFC_ps = max(tmp.tRFC_ps, dimm[i].tRFC_ps);
+ tmp.tRRD_ps = max(tmp.tRRD_ps, dimm[i].tRRD_ps);
+ tmp.tRC_ps = max(tmp.tRC_ps, dimm[i].tRC_ps);
+ tmp.tIS_ps = max(tmp.tIS_ps, dimm[i].tIS_ps);
+ tmp.tIH_ps = max(tmp.tIH_ps, dimm[i].tIH_ps);
+ tmp.tDS_ps = max(tmp.tDS_ps, dimm[i].tDS_ps);
+ tmp.tDH_ps = max(tmp.tDH_ps, dimm[i].tDH_ps);
+ tmp.tRTP_ps = max(tmp.tRTP_ps, dimm[i].tRTP_ps);
+ tmp.tQHS_ps = max(tmp.tQHS_ps, dimm[i].tQHS_ps);
+ tmp.refresh_rate_ps = max(tmp.refresh_rate_ps,
+ dimm[i].refresh_rate_ps);
+ tmp.extended_op_srt = min(tmp.extended_op_srt,
+ dimm[i].extended_op_srt);
+ /* Find maximum tDQSQ_max_ps to find slowest timing. */
+ tmp.tDQSQ_max_ps = max(tmp.tDQSQ_max_ps, dimm[i].tDQSQ_max_ps);
+ }
+ tmp.ndimms_present = number_of_dimms - temp1;
+
+ if (temp1 == number_of_dimms)
+ return;
+
+ temp1 = common_burst_length(dimm, number_of_dimms);
+ tmp.all_DIMMs_burst_lengths_bitmask = temp1;
+
+ /* Support only unbuffered DIMMs */
+ tmp.all_DIMMs_registered = 0;
+ tmp.all_DIMMs_unbuffered = 1;
+
+ if (popts->sdram_type == SDRAM_TYPE_DDR3) {
+ tmp.lowest_common_SPD_caslat = compute_cas_latency_ddr3(dimm,
+ number_of_dimms);
+ } else {
+ tmp.lowest_common_SPD_caslat = compute_lowest_caslat(dimm,
+ number_of_dimms);
+ /*
+ * Compute a common 'de-rated' CAS latency.
+ *
+ * The strategy here is to find the *highest* de-rated cas
+ * latency with the assumption that all of the DIMMs will
+ * support a de-rated CAS latency higher than or equal to
+ * their lowest de-rated value.
+ */
+ temp1 = 0;
+ for (i = 0; i < number_of_dimms; i++)
+ temp1 = max(temp1, dimm[i].caslat_lowest_derated);
+ tmp.highest_common_derated_caslat = temp1;
+ }
+
+ temp1 = 1;
+ for (i = 0; i < number_of_dimms; i++)
+ if (dimm[i].n_ranks && !(dimm[i].edc_config & EDC_ECC)) {
+ temp1 = 0;
+ break;
+ }
+ tmp.all_DIMMs_ECC_capable = temp1;
+
+ /*
+ * AL must be less or equal to tRCD. Typically, AL would
+ * be AL = tRCD - 1;
+ *
+ * When ODT read or write is enabled the sum of CAS latency +
+ * additive latency must be at least 3 cycles.
+ */
+ tmp.additive_latency = 0;
+ if (popts->sdram_type == SDRAM_TYPE_DDR2) {
+ if ((tmp.lowest_common_SPD_caslat < 4) &&
+ (picos_to_mclk(tmp.tRCD_ps) >
+ tmp.lowest_common_SPD_caslat))
+ tmp.additive_latency = picos_to_mclk(tmp.tRCD_ps) -
+ tmp.lowest_common_SPD_caslat;
+
+ if (mclk_to_picos(tmp.additive_latency) > tmp.tRCD_ps)
+ tmp.additive_latency = picos_to_mclk(tmp.tRCD_ps);
+ }
+
+ memcpy(out, &tmp, sizeof(struct common_timing_params_s));
+}
diff --git a/arch/powerpc/ddr-8xxx/main.c b/arch/powerpc/ddr-8xxx/main.c
new file mode 100644
index 0000000000..99b877b5ca
--- /dev/null
+++ b/arch/powerpc/ddr-8xxx/main.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2008-2012 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.
+ */
+
+/*
+ * Generic driver for Freescale DDR2 memory controller.
+ * Based on code from spd_sdram.c
+ * Author: James Yang [at freescale.com]
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/fsl_law.h>
+#include <asm/fsl_ddr_sdram.h>
+#include "ddr.h"
+
+static int get_spd(generic_spd_eeprom_t *spd,
+ struct ddr_board_info_s *bi, u8 i2c_address)
+{
+ int ret;
+
+ fsl_i2c_init(bi->i2c_base, bi->i2c_speed, bi->i2c_slave);
+ ret = fsl_i2c_read(bi->i2c_base, i2c_address, 0, 1, (uchar *) spd,
+ sizeof(generic_spd_eeprom_t));
+ fsl_i2c_stop(bi->i2c_base);
+
+ return ret;
+}
+
+int fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd,
+ struct ddr_board_info_s *binfo)
+{
+ uint32_t i;
+ uint8_t i2c_address;
+
+ for (i = 0; i < binfo->dimm_slots_per_ctrl; i++) {
+ if (binfo->spd_i2c_addr == NULL)
+ goto error;
+ i2c_address = binfo->spd_i2c_addr[i];
+ if (get_spd(&(ctrl_dimms_spd[i]), binfo, i2c_address))
+ goto error;
+ }
+
+ return 0;
+error:
+ return 1;
+}
+
+static uint64_t step_assign_addresses(struct fsl_ddr_info_s *pinfo,
+ uint32_t dbw_cap_adj)
+{
+ uint64_t total_mem, current_mem_base, total_ctlr_mem, cap;
+ uint32_t ndimm, dw, j, found = 0;
+
+ ndimm = pinfo->board_info.dimm_slots_per_ctrl;
+ /*
+ * If a reduced data width is requested, but the SPD
+ * specifies a physically wider device, adjust the
+ * computed dimm capacities accordingly before
+ * assigning addresses.
+ */
+ switch (pinfo->memctl_opts.data_bus_width) {
+ case 2:
+ /* 16-bit */
+ for (j = 0; j < ndimm; j++) {
+ if (!pinfo->dimm_params[j].n_ranks)
+ continue;
+ dw = pinfo->dimm_params[j].primary_sdram_width;
+ if ((dw == 72 || dw == 64)) {
+ dbw_cap_adj = 2;
+ break;
+ } else if ((dw == 40 || dw == 32)) {
+ dbw_cap_adj = 1;
+ break;
+ }
+ }
+ break;
+ case 1:
+ /* 32-bit */
+ for (j = 0; j < ndimm; j++) {
+ dw = pinfo->dimm_params[j].data_width;
+ if (pinfo->dimm_params[j].n_ranks
+ && (dw == 72 || dw == 64)) {
+ /*
+ * FIXME: can't really do it
+ * like this because this just
+ * further reduces the memory
+ */
+ found = 1;
+ break;
+ }
+ }
+ if (found)
+ dbw_cap_adj = 1;
+ break;
+ case 0:
+ /* 64-bit */
+ break;
+ default:
+ return 1;
+ }
+
+ current_mem_base = 0ull;
+ total_mem = 0;
+ total_ctlr_mem = 0;
+ pinfo->common_timing_params.base_address = current_mem_base;
+
+ for (j = 0; j < ndimm; j++) {
+ cap = pinfo->dimm_params[j].capacity >> dbw_cap_adj;
+ pinfo->dimm_params[j].base_address = current_mem_base;
+ current_mem_base += cap;
+ total_ctlr_mem += cap;
+
+ }
+
+ pinfo->common_timing_params.total_mem = total_ctlr_mem;
+ total_mem += total_ctlr_mem;
+
+ return total_mem;
+}
+
+static uint32_t retrieve_max_size(struct fsl_ddr_cfg_regs_s *ddr_reg,
+ uint32_t ncs)
+{
+ uint32_t max_end = 0, end, i;
+
+ for (i = 0; i < ncs; i++)
+ if (ddr_reg->cs[i].config & 0x80000000) {
+ end = ddr_reg->cs[i].bnds & 0xFFF;
+ if (end > max_end)
+ max_end = end;
+ }
+
+ return max_end;
+}
+
+static uint32_t compute_dimm_param(struct fsl_ddr_info_s *pinfo, uint32_t ndimm)
+{
+ struct dimm_params_s *pdimm;
+ generic_spd_eeprom_t *spd;
+ uint32_t i, retval;
+
+ spd = &(pinfo->spd_installed_dimms[0]);
+ if (spd->mem_type == SPD_MEMTYPE_DDR3)
+ pinfo->memctl_opts.sdram_type = SDRAM_TYPE_DDR3;
+ else if (spd->mem_type == SPD_MEMTYPE_DDR2)
+ pinfo->memctl_opts.sdram_type = SDRAM_TYPE_DDR2;
+ else
+ return 1;
+
+ for (i = 0; i < ndimm; i++) {
+ spd = &(pinfo->spd_installed_dimms[i]);
+ pdimm = &(pinfo->dimm_params[i]);
+
+ retval = compute_dimm_parameters(spd, pdimm);
+
+ if (retval == 2) /* Fatal error */
+ return 1;
+ }
+
+ return 0;
+}
+
+uint64_t fsl_ddr_compute(struct fsl_ddr_info_s *pinfo)
+{
+ uint64_t total_mem = 0;
+ uint32_t ncs, ndimm, max_end = 0;
+ struct fsl_ddr_cfg_regs_s *ddr_reg;
+ struct common_timing_params_s *timing_params;
+ /* data bus width capacity adjust shift amount */
+ uint32_t dbw_capacity_adjust;
+
+ ddr_reg = &pinfo->fsl_ddr_config_reg;
+ timing_params = &pinfo->common_timing_params;
+ ncs = pinfo->board_info.cs_per_ctrl;
+ ndimm = pinfo->board_info.dimm_slots_per_ctrl;
+ dbw_capacity_adjust = 0;
+ pinfo->memctl_opts.board_info = &pinfo->board_info;
+
+ /* STEP 1: Gather all DIMM SPD data */
+ if (fsl_ddr_get_spd(pinfo->spd_installed_dimms,
+ pinfo->memctl_opts.board_info))
+ return 0;
+
+ /* STEP 2: Compute DIMM parameters from SPD data */
+ if (compute_dimm_param(pinfo, ndimm))
+ return 0;
+
+ /*
+ * STEP 3: Compute a common set of timing parameters
+ * suitable for all of the DIMMs on each memory controller
+ */
+ compute_lowest_common_dimm_parameters(pinfo, timing_params, ndimm);
+
+ /* STEP 4: Gather configuration requirements from user */
+ populate_memctl_options(timing_params->all_DIMMs_registered,
+ &pinfo->memctl_opts,
+ pinfo->dimm_params);
+
+ /* STEP 5: Assign addresses to chip selects */
+ total_mem = step_assign_addresses(pinfo, dbw_capacity_adjust);
+
+ /* STEP 6: compute controller register values */
+ if (timing_params->ndimms_present == 0)
+ memset(ddr_reg, 0, sizeof(struct fsl_ddr_cfg_regs_s));
+
+ compute_fsl_memctl_config_regs(&pinfo->memctl_opts,
+ ddr_reg, timing_params,
+ pinfo->dimm_params,
+ dbw_capacity_adjust);
+
+ max_end = retrieve_max_size(ddr_reg, ncs);
+ total_mem = 1 + (((uint64_t)max_end << 24ULL) | 0xFFFFFFULL);
+
+ return total_mem;
+}
+
+/*
+ * fsl_ddr_sdram():
+ * This is the main function to initialize the memory.
+ *
+ * It returns amount of memory configured in bytes.
+ */
+phys_size_t fsl_ddr_sdram(void)
+{
+ uint64_t total_memory;
+ struct fsl_ddr_info_s info;
+
+ memset(&info, 0, sizeof(struct fsl_ddr_info_s));
+ /* Gather board information on the memory controller and I2C bus. */
+ fsl_ddr_board_info(&info.board_info);
+
+ total_memory = fsl_ddr_compute(&info);
+
+ if (info.common_timing_params.ndimms_present == 0)
+ return 0;
+
+ fsl_ddr_set_memctl_regs(&info);
+ fsl_ddr_set_lawbar(&info.common_timing_params, LAW_TRGT_IF_DDR_1);
+
+ return total_memory;
+}
diff --git a/arch/powerpc/ddr-8xxx/options.c b/arch/powerpc/ddr-8xxx/options.c
new file mode 100644
index 0000000000..ccf5d5e9d8
--- /dev/null
+++ b/arch/powerpc/ddr-8xxx/options.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2008, 2010-2012 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.
+ */
+
+#include <common.h>
+#include <asm/fsl_ddr_sdram.h>
+#include "ddr.h"
+
+uint32_t populate_memctl_options(int all_DIMMs_registered,
+ struct memctl_options_s *popts,
+ struct dimm_params_s *pdimm)
+{
+ const struct ddr_board_info_s *binfo = popts->board_info;
+ uint32_t i;
+
+ for (i = 0; i < binfo->cs_per_ctrl; i++) {
+ popts->cs_local_opts[i].odt_rd_cfg = FSL_DDR_ODT_NEVER;
+ popts->cs_local_opts[i].odt_wr_cfg = FSL_DDR_ODT_ALL;
+ popts->cs_local_opts[i].odt_rtt_norm = DDR2_RTT_50_OHM;
+ popts->cs_local_opts[i].odt_rtt_wr = DDR2_RTT_OFF;
+ popts->cs_local_opts[i].auto_precharge = 0;
+ }
+
+ /* Memory Organization Parameters */
+ popts->registered_dimm_en = all_DIMMs_registered;
+ popts->ECC_mode = 0; /* 0 = disabled, 1 = enabled */
+ popts->ECC_init_using_memctl = 1; /* 0 = use DMA, 1 = use memctl */
+
+ /* Choose DQS config - 1 for DDR2 */
+ popts->DQS_config = 1;
+
+ /* Choose self-refresh during sleep. */
+ popts->self_refresh_in_sleep = 1;
+
+ /* Choose dynamic power management mode. */
+ popts->dynamic_power = 0;
+
+ /*
+ * check first dimm for primary sdram width
+ * assuming all dimms are similar
+ * 0 = 64-bit, 1 = 32-bit, 2 = 16-bit
+ */
+ if (pdimm->n_ranks != 0) {
+ if (popts->sdram_type == SDRAM_TYPE_DDR3) {
+ if (pdimm[0].primary_sdram_width == 64)
+ popts->data_bus_width = 0;
+ else if (pdimm[0].primary_sdram_width == 32)
+ popts->data_bus_width = 1;
+ else if (pdimm[0].primary_sdram_width == 16)
+ popts->data_bus_width = 2;
+ else
+ hang();
+ } else {
+ if ((pdimm->data_width >= 64) &&
+ (pdimm->data_width <= 72))
+ popts->data_bus_width = 0;
+ else if ((pdimm->data_width >= 32) &&
+ (pdimm->data_width <= 40))
+ popts->data_bus_width = 1;
+ else
+ hang();
+ }
+ }
+
+ if (popts->sdram_type == SDRAM_TYPE_DDR3) {
+ if (popts->data_bus_width == 0) {
+ popts->otf_burst_chop_en = 1;
+ popts->burst_length = DDR_OTF;
+ } else {
+ /* 32-bit or 16-bit bus */
+ popts->otf_burst_chop_en = 0;
+ popts->burst_length = DDR_BL8;
+ }
+ popts->mirrored_dimm = pdimm[0].mirrored_dimm;
+ } else {
+ /* Must be a burst length of 4 for DDR2 */
+ popts->burst_length = DDR_BL4;
+ }
+
+ /* Decide whether to use the computed de-rated latency */
+ popts->use_derated_caslat = 0;
+
+ /*
+ * 2T_EN setting
+ *
+ * Factors to consider for 2T_EN:
+ * - number of DIMMs installed
+ * - number of components, number of active ranks
+ * - how much time you want to spend playing around
+ */
+ popts->twoT_en = 0;
+ popts->threet_en = 0;
+
+ /*
+ * Default BSTTOPRE precharge interval
+ *
+ * Set the parameter to 0 for global auto precharge in
+ * the board options function.
+ */
+ popts->bstopre = 0x100;
+
+ /* Minimum CKE pulse width -- tCKE(MIN) */
+ popts->tCKE_clock_pulse_width_ps
+ = mclk_to_picos(FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR);
+
+ /*
+ * Window for four activates -- tFAW
+ *
+ * Set according to specification for the memory used.
+ * The default value below would work for x4/x8 wide memory.
+ *
+ */
+ if (popts->sdram_type == SDRAM_TYPE_DDR2) {
+ popts->tFAW_window_four_activates_ps = 37500;
+ } else {
+ /*
+ * Due to ddr3 dimm fly-by topology, enable write leveling
+ * to meet the tQDSS under different loading.
+ */
+ popts->tFAW_window_four_activates_ps = pdimm[0].tfaw_ps;
+ popts->wrlvl_en = 1;
+ popts->zq_en = 1;
+ popts->wrlvl_override = 0;
+ }
+
+ /*
+ * Default powerdown exit timings.
+ * Set according to specifications for the memory used in
+ * the board options function.
+ */
+ popts->txard = 3;
+ popts->txp = 3;
+ popts->taxpd = 11;
+
+ /* Default value for load mode cycle time */
+ popts->tmrd = 2;
+
+ /* Specific board override parameters. */
+ fsl_ddr_board_options(popts, pdimm);
+
+ return 0;
+}
diff --git a/arch/powerpc/ddr-8xxx/util.c b/arch/powerpc/ddr-8xxx/util.c
new file mode 100644
index 0000000000..4525524926
--- /dev/null
+++ b/arch/powerpc/ddr-8xxx/util.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2008-2012 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_law.h>
+#include <linux/math64.h>
+#include <mach/clock.h>
+#include "ddr.h"
+
+#define ULL_2E12 2000000000000ULL
+#define UL_5POW12 244140625UL
+#define UL_2POW13 (1UL << 13)
+#define ULL_8FS 0xFFFFFFFFULL
+
+/*
+ * Round up mclk_ps to nearest 1 ps in memory controller code
+ * if the error is 0.5ps or more.
+ *
+ * If an imprecise data rate is too high due to rounding error
+ * propagation, compute a suitably rounded mclk_ps to compute
+ * a working memory controller configuration.
+ */
+uint32_t get_memory_clk_period_ps(void)
+{
+ uint32_t result, data_rate = fsl_get_ddr_freq(0);
+ /* Round to nearest 10ps, being careful about 64-bit multiply/divide */
+ uint64_t rem, mclk_ps = ULL_2E12;
+
+ /* Now perform the big divide, the result fits in 32-bits */
+ rem = do_div(mclk_ps, data_rate);
+ if (rem >= (data_rate >> 1))
+ result = mclk_ps + 1;
+ else
+ result = mclk_ps;
+
+ return result;
+}
+
+/* Convert picoseconds into DRAM clock cycles (rounding up if needed). */
+uint32_t picos_to_mclk(uint32_t picos)
+{
+ uint64_t clks, clks_rem;
+ uint32_t data_rate = fsl_get_ddr_freq(0);
+
+ if (!picos)
+ return 0;
+
+ /* First multiply the time by the data rate (32x32 => 64) */
+ clks = picos * (uint64_t)data_rate;
+ /*
+ * Now divide by 5^12 and track the 32-bit remainder, then divide
+ * by 2*(2^12) using shifts (and updating the remainder).
+ */
+ clks_rem = do_div(clks, UL_5POW12);
+ clks_rem += (clks & (UL_2POW13 - 1)) * UL_5POW12;
+ clks >>= 13;
+
+ /* If we had a remainder greater than the 1ps error, then round up */
+ if (clks_rem > data_rate)
+ clks++;
+
+ if (clks > ULL_8FS)
+ clks = ULL_8FS;
+
+ return (uint32_t)clks;
+}
+
+uint32_t mclk_to_picos(unsigned int mclk)
+{
+ return get_memory_clk_period_ps() * mclk;
+}
+
+int fsl_ddr_set_lawbar(
+ const struct common_timing_params_s *params,
+ uint32_t law_memctl)
+{
+ uint64_t base = params->base_address;
+ uint64_t size = params->total_mem;
+
+ if (!params->ndimms_present)
+ goto out;
+
+ if (base >= MAX_MEM_MAPPED)
+ goto error;
+
+ if ((base + size) >= MAX_MEM_MAPPED)
+ size = MAX_MEM_MAPPED - base;
+
+ if (fsl_set_ddr_laws(base, size, law_memctl) < 0)
+ goto error;
+out:
+ return 0;
+error:
+ return 1;
+}
diff --git a/arch/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h
new file mode 100644
index 0000000000..814bf50d63
--- /dev/null
+++ b/arch/powerpc/include/asm/atomic.h
@@ -0,0 +1,95 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * PowerPC atomic operations
+ */
+
+#ifndef _ASM_PPC_ATOMIC_H_
+#define _ASM_PPC_ATOMIC_H_
+
+#ifdef CONFIG_SMP
+typedef struct { volatile int counter; } atomic_t;
+#else
+typedef struct { int counter; } atomic_t;
+#endif
+
+#define ATOMIC_INIT(i) { (i) }
+
+#define atomic_read(v) ((v)->counter)
+#define atomic_set(v,i) (((v)->counter) = (i))
+
+extern void atomic_clear_mask(unsigned long mask, unsigned long *addr);
+extern void atomic_set_mask(unsigned long mask, unsigned long *addr);
+
+static inline int atomic_add_return(int a, atomic_t *v)
+{
+ int t;
+
+ __asm__ __volatile__("\n\
+1: lwarx %0,0,%3\n\
+ add %0,%2,%0\n\
+ stwcx. %0,0,%3\n\
+ bne- 1b"
+ : "=&r" (t), "=m" (*v)
+ : "r" (a), "r" (v), "m" (*v)
+ : "cc");
+
+ return t;
+}
+
+static inline int atomic_sub_return(int a, atomic_t *v)
+{
+ int t;
+
+ __asm__ __volatile__("\n\
+1: lwarx %0,0,%3\n\
+ subf %0,%2,%0\n\
+ stwcx. %0,0,%3\n\
+ bne- 1b"
+ : "=&r" (t), "=m" (*v)
+ : "r" (a), "r" (v), "m" (*v)
+ : "cc");
+
+ return t;
+}
+
+static inline int atomic_inc_return(atomic_t *v)
+{
+ int t;
+
+ __asm__ __volatile__("\n\
+1: lwarx %0,0,%2\n\
+ addic %0,%0,1\n\
+ stwcx. %0,0,%2\n\
+ bne- 1b"
+ : "=&r" (t), "=m" (*v)
+ : "r" (v), "m" (*v)
+ : "cc");
+
+ return t;
+}
+
+static inline int atomic_dec_return(atomic_t *v)
+{
+ int t;
+
+ __asm__ __volatile__("\n\
+1: lwarx %0,0,%2\n\
+ addic %0,%0,-1\n\
+ stwcx. %0,0,%2\n\
+ bne 1b"
+ : "=&r" (t), "=m" (*v)
+ : "r" (v), "m" (*v)
+ : "cc");
+
+ return t;
+}
+
+#define atomic_add(a, v) ((void) atomic_add_return((a), (v)))
+#define atomic_sub(a, v) ((void) atomic_sub_return((a), (v)))
+#define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0)
+#define atomic_inc(v) ((void) atomic_inc_return((v)))
+#define atomic_dec(v) ((void) atomic_dec_return((v)))
+#define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0)
+
+#endif /* _ASM_PPC_ATOMIC_H_ */
diff --git a/arch/powerpc/include/asm/barebox.lds.h b/arch/powerpc/include/asm/barebox.lds.h
new file mode 100644
index 0000000000..14477bd44a
--- /dev/null
+++ b/arch/powerpc/include/asm/barebox.lds.h
@@ -0,0 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#define BAREBOX_OUTPUT_ARCH "powerpc"
+
+#include <asm-generic/barebox.lds.h>
diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h
new file mode 100644
index 0000000000..62b09c7da4
--- /dev/null
+++ b/arch/powerpc/include/asm/bitops.h
@@ -0,0 +1,195 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * bitops.h: Bit string operations on the ppc
+ */
+
+#ifndef _PPC_BITOPS_H
+#define _PPC_BITOPS_H
+
+#include <asm/byteorder.h>
+#include <asm-generic/bitops/ops.h>
+
+/*
+ * Arguably these bit operations don't imply any memory barrier or
+ * SMP ordering, but in fact a lot of drivers expect them to imply
+ * both, since they do on x86 cpus.
+ */
+#ifdef CONFIG_SMP
+#define SMP_WMB "eieio\n"
+#define SMP_MB "\nsync"
+#else
+#define SMP_WMB
+#define SMP_MB
+#endif /* CONFIG_SMP */
+
+#define __INLINE_BITOPS 1
+
+#if __INLINE_BITOPS
+/*
+ * These used to be if'd out here because using : "cc" as a constraint
+ * resulted in errors from egcs. Things may be OK with gcc-2.95.
+ */
+static inline void set_bit(int nr, volatile void * addr)
+{
+ unsigned long old;
+ unsigned long mask = 1 << (nr & 0x1f);
+ unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
+
+ __asm__ __volatile__(SMP_WMB "\
+1: lwarx %0,0,%3\n\
+ or %0,%0,%2\n\
+ stwcx. %0,0,%3\n\
+ bne 1b"
+ SMP_MB
+ : "=&r" (old), "=m" (*p)
+ : "r" (mask), "r" (p), "m" (*p)
+ : "cc" );
+}
+
+static inline void clear_bit(int nr, volatile void *addr)
+{
+ unsigned long old;
+ unsigned long mask = 1 << (nr & 0x1f);
+ unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
+
+ __asm__ __volatile__(SMP_WMB "\
+1: lwarx %0,0,%3\n\
+ andc %0,%0,%2\n\
+ stwcx. %0,0,%3\n\
+ bne 1b"
+ SMP_MB
+ : "=&r" (old), "=m" (*p)
+ : "r" (mask), "r" (p), "m" (*p)
+ : "cc");
+}
+
+static inline void change_bit(int nr, volatile void *addr)
+{
+ unsigned long old;
+ unsigned long mask = 1 << (nr & 0x1f);
+ unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
+
+ __asm__ __volatile__(SMP_WMB "\
+1: lwarx %0,0,%3\n\
+ xor %0,%0,%2\n\
+ stwcx. %0,0,%3\n\
+ bne 1b"
+ SMP_MB
+ : "=&r" (old), "=m" (*p)
+ : "r" (mask), "r" (p), "m" (*p)
+ : "cc");
+}
+
+static inline int test_and_set_bit(int nr, volatile void *addr)
+{
+ unsigned int old, t;
+ unsigned int mask = 1 << (nr & 0x1f);
+ volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
+
+ __asm__ __volatile__(SMP_WMB "\
+1: lwarx %0,0,%4\n\
+ or %1,%0,%3\n\
+ stwcx. %1,0,%4\n\
+ bne 1b"
+ SMP_MB
+ : "=&r" (old), "=&r" (t), "=m" (*p)
+ : "r" (mask), "r" (p), "m" (*p)
+ : "cc");
+
+ return (old & mask) != 0;
+}
+
+static inline int test_and_clear_bit(int nr, volatile void *addr)
+{
+ unsigned int old, t;
+ unsigned int mask = 1 << (nr & 0x1f);
+ volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
+
+ __asm__ __volatile__(SMP_WMB "\
+1: lwarx %0,0,%4\n\
+ andc %1,%0,%3\n\
+ stwcx. %1,0,%4\n\
+ bne 1b"
+ SMP_MB
+ : "=&r" (old), "=&r" (t), "=m" (*p)
+ : "r" (mask), "r" (p), "m" (*p)
+ : "cc");
+
+ return (old & mask) != 0;
+}
+
+static inline int test_and_change_bit(int nr, volatile void *addr)
+{
+ unsigned int old, t;
+ unsigned int mask = 1 << (nr & 0x1f);
+ volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
+
+ __asm__ __volatile__(SMP_WMB "\
+1: lwarx %0,0,%4\n\
+ xor %1,%0,%3\n\
+ stwcx. %1,0,%4\n\
+ bne 1b"
+ SMP_MB
+ : "=&r" (old), "=&r" (t), "=m" (*p)
+ : "r" (mask), "r" (p), "m" (*p)
+ : "cc");
+
+ return (old & mask) != 0;
+}
+#endif /* __INLINE_BITOPS */
+
+/* Return the bit position of the most significant 1 bit in a word */
+static inline int __ilog2(unsigned int x)
+{
+ int lz;
+
+ asm ("cntlzw %0,%1" : "=r" (lz) : "r" (x));
+ return 31 - lz;
+}
+
+static inline int ffz(unsigned int x)
+{
+ if ((x = ~x) == 0)
+ return 32;
+ return __ilog2(x & -x);
+}
+
+static inline int __ffs(unsigned long x)
+{
+ return __ilog2(x & -x);
+}
+
+/*
+ * fls: find last (most-significant) bit set.
+ * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
+ */
+static inline int fls(unsigned int x)
+{
+ int lz;
+
+ asm ("cntlzw %0,%1" : "=r" (lz) : "r" (x));
+ return 32 - lz;
+}
+
+#ifdef __KERNEL__
+
+/*
+ * ffs: find first bit set. This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+static inline int ffs(int x)
+{
+ return __ilog2(x & -x) + 1;
+}
+
+#include <asm-generic/bitops/__fls.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/hweight.h>
+
+#endif /* __KERNEL__ */
+
+#include <asm-generic/bitops/find.h>
+
+#endif /* _PPC_BITOPS_H */
diff --git a/arch/powerpc/include/asm/bitsperlong.h b/arch/powerpc/include/asm/bitsperlong.h
new file mode 100644
index 0000000000..bf000a04cc
--- /dev/null
+++ b/arch/powerpc/include/asm/bitsperlong.h
@@ -0,0 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <asm-generic/bitsperlong.h>
diff --git a/arch/powerpc/include/asm/byteorder.h b/arch/powerpc/include/asm/byteorder.h
new file mode 100644
index 0000000000..aa6cc4fac9
--- /dev/null
+++ b/arch/powerpc/include/asm/byteorder.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_POWERPC_BYTEORDER_H
+#define _ASM_POWERPC_BYTEORDER_H
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/byteorder/big_endian.h>
+
+#endif /* _ASM_POWERPC_BYTEORDER_H */
diff --git a/arch/powerpc/include/asm/cache.h b/arch/powerpc/include/asm/cache.h
new file mode 100644
index 0000000000..c9066099ab
--- /dev/null
+++ b/arch/powerpc/include/asm/cache.h
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * include/asm-ppc/cache.h
+ */
+#ifndef __ARCH_PPC_CACHE_H
+#define __ARCH_PPC_CACHE_H
+
+#include <asm/processor.h>
+
+/* bytes per L1 cache line. CPU dependent */
+#define L1_CACHE_SHIFT 5
+#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
+
+#ifndef CACHELINE_SIZE
+#define CACHELINE_SIZE L1_CACHE_BYTES
+#endif
+
+#define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
+#define L1_CACHE_PAGES 8
+
+#define SMP_CACHE_BYTES L1_CACHE_BYTES
+
+#ifdef MODULE
+#define __cacheline_aligned __attribute__((__aligned__(L1_CACHE_BYTES)))
+#else
+#define __cacheline_aligned \
+ __attribute__((__aligned__(L1_CACHE_BYTES), \
+ __section__(".data.cacheline_aligned")))
+#endif
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+extern void flush_dcache_range(unsigned long start, unsigned long stop);
+extern void clean_dcache_range(unsigned long start, unsigned long stop);
+extern void invalidate_dcache_range(unsigned long start, unsigned long stop);
+extern void flush_dcache(void);
+extern void invalidate_icache(void);
+#ifdef CFG_INIT_RAM_LOCK
+extern void unlock_ram_in_cache(void);
+#endif /* CFG_INIT_RAM_LOCK */
+#endif /* __ASSEMBLY__ */
+
+/* prep registers for L2 */
+#define CACHECRBA 0x80000823 /* Cache configuration register address */
+#define L2CACHE_MASK 0x03 /* Mask for 2 L2 Cache bits */
+#define L2CACHE_512KB 0x00 /* 512KB */
+#define L2CACHE_256KB 0x01 /* 256KB */
+#define L2CACHE_1MB 0x02 /* 1MB */
+#define L2CACHE_NONE 0x03 /* NONE */
+#define L2CACHE_PARITY 0x08 /* Mask for L2 Cache Parity Protected bit */
+
+#ifdef CONFIG_8xx
+/* Cache control on the MPC8xx is provided through some additional
+ * special purpose registers.
+ */
+#define IC_CST 560 /* Instruction cache control/status */
+#define IC_ADR 561 /* Address needed for some commands */
+#define IC_DAT 562 /* Read-only data register */
+#define DC_CST 568 /* Data cache control/status */
+#define DC_ADR 569 /* Address needed for some commands */
+#define DC_DAT 570 /* Read-only data register */
+
+/* Commands. Only the first few are available to the instruction cache.
+*/
+#define IDC_ENABLE 0x02000000 /* Cache enable */
+#define IDC_DISABLE 0x04000000 /* Cache disable */
+#define IDC_LDLCK 0x06000000 /* Load and lock */
+#define IDC_UNLINE 0x08000000 /* Unlock line */
+#define IDC_UNALL 0x0a000000 /* Unlock all */
+#define IDC_INVALL 0x0c000000 /* Invalidate all */
+
+#define DC_FLINE 0x0e000000 /* Flush data cache line */
+#define DC_SFWT 0x01000000 /* Set forced writethrough mode */
+#define DC_CFWT 0x03000000 /* Clear forced writethrough mode */
+#define DC_SLES 0x05000000 /* Set little endian swap mode */
+#define DC_CLES 0x07000000 /* Clear little endian swap mode */
+
+/* Status.
+*/
+#define IDC_ENABLED 0x80000000 /* Cache is enabled */
+#define IDC_CERR1 0x00200000 /* Cache error 1 */
+#define IDC_CERR2 0x00100000 /* Cache error 2 */
+#define IDC_CERR3 0x00080000 /* Cache error 3 */
+
+#define DC_DFWT 0x40000000 /* Data cache is forced write through */
+#define DC_LES 0x20000000 /* Caches are little endian mode */
+#endif /* CONFIG_8xx */
+
+#endif
diff --git a/arch/powerpc/include/asm/common.h b/arch/powerpc/include/asm/common.h
new file mode 100644
index 0000000000..1e1ea4601d
--- /dev/null
+++ b/arch/powerpc/include/asm/common.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __ASM_COMMON_H
+#define __ASM_COMMON_H
+
+extern unsigned long _text_base;
+
+unsigned long long get_ticks(void);
+
+int cpu_init (void);
+
+uint get_pvr (void);
+uint get_svr (void);
+
+void trap_init (ulong);
+
+static inline unsigned long get_pc(void)
+{
+ unsigned long pc;
+
+ __asm__ __volatile__(
+ " mflr 0\n"
+ " bl 1f\n"
+ "1:\n"
+ " mflr %0\n"
+ " mtlr 0\n"
+ : "=r" (pc)
+ :
+ : "0", "memory");
+
+ return pc;
+}
+
+extern unsigned long search_exception_table(unsigned long);
+#endif /* __ASM_COMMON_H */
diff --git a/arch/powerpc/include/asm/config.h b/arch/powerpc/include/asm/config.h
new file mode 100644
index 0000000000..ce6581a83f
--- /dev/null
+++ b/arch/powerpc/include/asm/config.h
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef _ASM_CONFIG_H_
+#define _ASM_CONFIG_H_
+
+#ifdef CONFIG_MPC85xx
+#include <mach/config_mpc85xx.h>
+#endif
+
+#ifndef MAX_MEM_MAPPED
+#if defined(CONFIG_E500)
+#define MAX_MEM_MAPPED (2ULL << 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/powerpc/include/asm/dma.h b/arch/powerpc/include/asm/dma.h
new file mode 100644
index 0000000000..27d269f491
--- /dev/null
+++ b/arch/powerpc/include/asm/dma.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2012 by Marc Kleine-Budde <mkl@pengutronix.de>
+ *
+ * This file is released under the GPLv2
+ *
+ */
+
+#ifndef __ASM_DMA_H
+#define __ASM_DMA_H
+
+/* empty */
+
+#endif /* __ASM_DMA_H */
diff --git a/arch/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h
new file mode 100644
index 0000000000..bb8762b385
--- /dev/null
+++ b/arch/powerpc/include/asm/elf.h
@@ -0,0 +1,412 @@
+#ifndef _ASM_POWERPC_ELF_H
+#define _ASM_POWERPC_ELF_H
+
+#include <asm/types.h>
+#include <asm/ptrace.h>
+#include <asm/string.h>
+
+/* PowerPC relocations defined by the ABIs */
+#define R_PPC_NONE 0
+#define R_PPC_ADDR32 1 /* 32bit absolute address */
+#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */
+#define R_PPC_ADDR16 3 /* 16bit absolute address */
+#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */
+#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */
+#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */
+#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */
+#define R_PPC_ADDR14_BRTAKEN 8
+#define R_PPC_ADDR14_BRNTAKEN 9
+#define R_PPC_REL24 10 /* PC relative 26 bit */
+#define R_PPC_REL14 11 /* PC relative 16 bit */
+#define R_PPC_REL14_BRTAKEN 12
+#define R_PPC_REL14_BRNTAKEN 13
+#define R_PPC_GOT16 14
+#define R_PPC_GOT16_LO 15
+#define R_PPC_GOT16_HI 16
+#define R_PPC_GOT16_HA 17
+#define R_PPC_PLTREL24 18
+#define R_PPC_COPY 19
+#define R_PPC_GLOB_DAT 20
+#define R_PPC_JMP_SLOT 21
+#define R_PPC_RELATIVE 22
+#define R_PPC_LOCAL24PC 23
+#define R_PPC_UADDR32 24
+#define R_PPC_UADDR16 25
+#define R_PPC_REL32 26
+#define R_PPC_PLT32 27
+#define R_PPC_PLTREL32 28
+#define R_PPC_PLT16_LO 29
+#define R_PPC_PLT16_HI 30
+#define R_PPC_PLT16_HA 31
+#define R_PPC_SDAREL16 32
+#define R_PPC_SECTOFF 33
+#define R_PPC_SECTOFF_LO 34
+#define R_PPC_SECTOFF_HI 35
+#define R_PPC_SECTOFF_HA 36
+
+/* PowerPC relocations defined for the TLS access ABI. */
+#define R_PPC_TLS 67 /* none (sym+add)@tls */
+#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */
+#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */
+#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */
+#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */
+#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */
+#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */
+#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */
+#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */
+#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */
+#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */
+#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */
+#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */
+#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */
+#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */
+#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */
+#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */
+#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */
+#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */
+#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */
+#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got@tprel */
+#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got@tprel@l */
+#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */
+#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */
+#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got@dtprel */
+#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got@dtprel@l */
+#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got@dtprel@h */
+#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got@dtprel@ha */
+
+/* keep this the last entry. */
+#define R_PPC_NUM 95
+
+/*
+ * ELF register definitions..
+ *
+ * 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.
+ */
+
+#define ELF_NGREG 48 /* includes nip, msr, lr, etc. */
+#define ELF_NFPREG 33 /* includes fpscr */
+
+typedef unsigned long elf_greg_t64;
+typedef elf_greg_t64 elf_gregset_t64[ELF_NGREG];
+
+typedef unsigned int elf_greg_t32;
+typedef elf_greg_t32 elf_gregset_t32[ELF_NGREG];
+
+/*
+ * ELF_ARCH, CLASS, and DATA are used to set parameters in the core dumps.
+ */
+#ifdef __powerpc64__
+# define ELF_NVRREG32 33 /* includes vscr & vrsave stuffed together */
+# define ELF_NVRREG 34 /* includes vscr & vrsave in split vectors */
+# define ELF_GREG_TYPE elf_greg_t64
+#else
+# define ELF_NEVRREG 34 /* includes acc (as 2) */
+# define ELF_NVRREG 33 /* includes vscr */
+# define ELF_GREG_TYPE elf_greg_t32
+# define ELF_ARCH EM_PPC
+# define ELF_CLASS ELFCLASS32
+# define ELF_DATA ELFDATA2MSB
+#endif /* __powerpc64__ */
+
+#ifndef ELF_ARCH
+# define ELF_ARCH EM_PPC64
+# define ELF_CLASS ELFCLASS64
+# define ELF_DATA ELFDATA2MSB
+ typedef elf_greg_t64 elf_greg_t;
+ typedef elf_gregset_t64 elf_gregset_t;
+#else
+ /* Assumption: ELF_ARCH == EM_PPC and ELF_CLASS == ELFCLASS32 */
+ typedef elf_greg_t32 elf_greg_t;
+ typedef elf_gregset_t32 elf_gregset_t;
+#endif /* ELF_ARCH */
+
+/* Floating point registers */
+typedef double elf_fpreg_t;
+typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
+
+/* Altivec registers */
+/*
+ * The entries with indexes 0-31 contain the corresponding vector registers.
+ * The entry with index 32 contains the vscr as the last word (offset 12)
+ * within the quadword. This allows the vscr to be stored as either a
+ * quadword (since it must be copied via a vector register to/from storage)
+ * or as a word.
+ *
+ * 64-bit kernel notes: The entry at index 33 contains the vrsave as the first
+ * word (offset 0) within the quadword.
+ *
+ * This definition of the VMX state is compatible with the current PPC32
+ * ptrace interface. This allows signal handling and ptrace to use the same
+ * structures. This also simplifies the implementation of a bi-arch
+ * (combined (32- and 64-bit) gdb.
+ *
+ * Note that it's _not_ compatible with 32 bits ucontext which stuffs the
+ * vrsave along with vscr and so only uses 33 vectors for the register set
+ */
+#if 0
+typedef __vector128 elf_vrreg_t;
+typedef elf_vrreg_t elf_vrregset_t[ELF_NVRREG];
+#ifdef __powerpc64__
+typedef elf_vrreg_t elf_vrregset_t32[ELF_NVRREG32];
+#endif
+#endif
+
+#ifdef __KERNEL__
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) ((x)->e_machine == ELF_ARCH)
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE PAGE_SIZE
+
+/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
+ use of this is to invoke "./ld.so someprog" to test out a new version of
+ the loader. We need to make sure that it is out of the way of the program
+ that it will "exec", and that there is sufficient room for the brk. */
+
+#define ELF_ET_DYN_BASE (0x20000000)
+
+extern void * memset(void *, int, __kernel_size_t);
+
+/* Common routine for both 32-bit and 64-bit processes */
+static inline void ppc_elf_core_copy_regs(elf_gregset_t elf_regs,
+ struct pt_regs *regs)
+{
+ int i, nregs;
+
+ memset((void *)elf_regs, 0, sizeof(elf_gregset_t));
+
+ /* Our registers are always unsigned longs, whether we're a 32 bit
+ * process or 64 bit, on either a 64 bit or 32 bit kernel.
+ * Don't use ELF_GREG_TYPE here. */
+ nregs = sizeof(struct pt_regs) / sizeof(unsigned long);
+ if (nregs > ELF_NGREG)
+ nregs = ELF_NGREG;
+
+ for (i = 0; i < nregs; i++) {
+ /* This will correctly truncate 64 bit registers to 32 bits
+ * for a 32 bit process on a 64 bit kernel. */
+ elf_regs[i] = (elf_greg_t)((ELF_GREG_TYPE *)regs)[i];
+ }
+}
+#define ELF_CORE_COPY_REGS(gregs, regs) ppc_elf_core_copy_regs(gregs, regs);
+
+#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs)
+
+#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs)
+
+#endif /* __KERNEL__ */
+
+/* ELF_HWCAP yields a mask that user programs can use to figure out what
+ instruction set this cpu supports. This could be done in userspace,
+ but it's not easy, and we've already done it here. */
+# define ELF_HWCAP (cur_cpu_spec->cpu_user_features)
+
+/* This yields a string that ld.so will use to load implementation
+ specific libraries for optimization. This is more specific in
+ intent than poking at uname or /proc/cpuinfo. */
+
+#define ELF_PLATFORM (cur_cpu_spec->platform)
+
+#ifdef __powerpc64__
+# define ELF_PLAT_INIT(_r, load_addr) do { \
+ _r->gpr[2] = load_addr; \
+} while (0)
+#endif /* __powerpc64__ */
+
+#ifdef __KERNEL__
+
+#ifdef __powerpc64__
+# define SET_PERSONALITY(ex, ibcs2) \
+do { \
+ unsigned long new_flags = 0; \
+ if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \
+ new_flags = _TIF_32BIT; \
+ if ((current_thread_info()->flags & _TIF_32BIT) \
+ != new_flags) \
+ set_thread_flag(TIF_ABI_PENDING); \
+ else \
+ clear_thread_flag(TIF_ABI_PENDING); \
+ if (personality(current->personality) != PER_LINUX32) \
+ set_personality(PER_LINUX); \
+} while (0)
+/*
+ * An executable for which elf_read_implies_exec() returns TRUE will
+ * have the READ_IMPLIES_EXEC personality flag set automatically. This
+ * is only required to work around bugs in old 32bit toolchains. Since
+ * the 64bit ABI has never had these issues dont enable the workaround
+ * even if we have an executable stack.
+ */
+# define elf_read_implies_exec(ex, exec_stk) (test_thread_flag(TIF_32BIT) ? \
+ (exec_stk != EXSTACK_DISABLE_X) : 0)
+#else
+# define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
+#endif /* __powerpc64__ */
+
+#endif /* __KERNEL__ */
+
+extern int dcache_bsize;
+extern int icache_bsize;
+extern int ucache_bsize;
+
+/* vDSO has arch_setup_additional_pages */
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
+struct linux_binprm;
+extern int arch_setup_additional_pages(struct linux_binprm *bprm,
+ int executable_stack);
+#define VDSO_AUX_ENT(a,b) NEW_AUX_ENT(a,b);
+
+/*
+ * The requirements here are:
+ * - keep the final alignment of sp (sp & 0xf)
+ * - make sure the 32-bit value at the first 16 byte aligned position of
+ * AUXV is greater than 16 for glibc compatibility.
+ * AT_IGNOREPPC is used for that.
+ * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
+ * even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
+ */
+#define ARCH_DLINFO \
+do { \
+ /* Handle glibc compatibility. */ \
+ NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
+ NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
+ /* Cache size items */ \
+ NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize); \
+ NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize); \
+ NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize); \
+ VDSO_AUX_ENT(AT_SYSINFO_EHDR, current->mm->context.vdso_base) \
+} while (0)
+
+/* PowerPC64 relocations defined by the ABIs */
+#define R_PPC64_NONE R_PPC_NONE
+#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address. */
+#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned. */
+#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address. */
+#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of abs. address. */
+#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of abs. address. */
+#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */
+#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned. */
+#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN
+#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN
+#define R_PPC64_REL24 R_PPC_REL24 /* PC relative 26 bit, word aligned. */
+#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit. */
+#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN
+#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN
+#define R_PPC64_GOT16 R_PPC_GOT16
+#define R_PPC64_GOT16_LO R_PPC_GOT16_LO
+#define R_PPC64_GOT16_HI R_PPC_GOT16_HI
+#define R_PPC64_GOT16_HA R_PPC_GOT16_HA
+
+#define R_PPC64_COPY R_PPC_COPY
+#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT
+#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT
+#define R_PPC64_RELATIVE R_PPC_RELATIVE
+
+#define R_PPC64_UADDR32 R_PPC_UADDR32
+#define R_PPC64_UADDR16 R_PPC_UADDR16
+#define R_PPC64_REL32 R_PPC_REL32
+#define R_PPC64_PLT32 R_PPC_PLT32
+#define R_PPC64_PLTREL32 R_PPC_PLTREL32
+#define R_PPC64_PLT16_LO R_PPC_PLT16_LO
+#define R_PPC64_PLT16_HI R_PPC_PLT16_HI
+#define R_PPC64_PLT16_HA R_PPC_PLT16_HA
+
+#define R_PPC64_SECTOFF R_PPC_SECTOFF
+#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO
+#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI
+#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA
+#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2. */
+#define R_PPC64_ADDR64 38 /* doubleword64 S + A. */
+#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A). */
+#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A). */
+#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A). */
+#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A). */
+#define R_PPC64_UADDR64 43 /* doubleword64 S + A. */
+#define R_PPC64_REL64 44 /* doubleword64 S + A - P. */
+#define R_PPC64_PLT64 45 /* doubleword64 L + A. */
+#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P. */
+#define R_PPC64_TOC16 47 /* half16* S + A - .TOC. */
+#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.). */
+#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.). */
+#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.). */
+#define R_PPC64_TOC 51 /* doubleword64 .TOC. */
+#define R_PPC64_PLTGOT16 52 /* half16* M + A. */
+#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A). */
+#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A). */
+#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A). */
+
+#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2. */
+#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2. */
+#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2. */
+#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2. */
+#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2. */
+#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2. */
+#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2. */
+#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2. */
+#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2. */
+#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2. */
+#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2. */
+
+/* PowerPC64 relocations defined for the TLS access ABI. */
+#define R_PPC64_TLS 67 /* none (sym+add)@tls */
+#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */
+#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */
+#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */
+#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */
+#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */
+#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */
+#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */
+#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */
+#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */
+#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */
+#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */
+#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */
+#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */
+#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */
+#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */
+#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */
+#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */
+#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */
+#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */
+#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got@tprel */
+#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */
+#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */
+#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */
+#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got@dtprel */
+#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */
+#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got@dtprel@h */
+#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got@dtprel@ha */
+#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */
+#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel@l */
+#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel@higher */
+#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel@highera */
+#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel@highest */
+#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel@highesta */
+#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */
+#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel@l */
+#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel@higher */
+#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */
+#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */
+#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */
+
+/* Keep this the last entry. */
+#define R_PPC64_NUM 107
+
+#ifdef CONFIG_SPU_BASE
+/* Notes used in ET_CORE. Note name is "SPU/<fd>/<filename>". */
+#define NT_SPU 1
+
+extern int arch_notes_size(void);
+extern void arch_write_notes(struct file *file);
+
+#define ELF_CORE_EXTRA_NOTES_SIZE arch_notes_size()
+#define ELF_CORE_WRITE_EXTRA_NOTES arch_write_notes(file)
+
+#define ARCH_HAVE_EXTRA_ELF_NOTES
+#endif /* CONFIG_PPC_CELL */
+
+#endif /* _ASM_POWERPC_ELF_H */
diff --git a/arch/powerpc/include/asm/fsl_ddr_dimm_params.h b/arch/powerpc/include/asm/fsl_ddr_dimm_params.h
new file mode 100644
index 0000000000..9e6f6b4d34
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_ddr_dimm_params.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#ifndef DDR2_DIMM_PARAMS_H
+#define DDR2_DIMM_PARAMS_H
+
+#define EDC_ECC 2
+
+/* Parameters for a DDR2 dimm computed from the SPD */
+struct dimm_params_s {
+ char mpart[19];
+ uint32_t n_ranks;
+ uint64_t rank_density;
+ uint64_t capacity;
+ uint32_t data_width;
+ uint32_t primary_sdram_width;
+ uint32_t ec_sdram_width;
+ uint32_t registered_dimm;
+ uint32_t device_width;
+ /* SDRAM device parameters */
+ uint32_t n_row_addr;
+ uint32_t n_col_addr;
+ uint32_t edc_config; /* 0 = none, 1 = parity, 2 = ECC */
+ uint32_t n_banks_per_sdram_device;
+ uint32_t burst_lengths_bitmask; /* BL=4 bit 2, BL=8 = bit 3 */
+ uint32_t row_density;
+ uint64_t base_address;
+ uint32_t mirrored_dimm;
+ uint32_t mtb_ps;
+ uint32_t ftb_10th_ps;
+ uint32_t taa_ps;
+ uint32_t tfaw_ps;
+ /* SDRAM clock periods */
+ uint32_t tCKmin_X_ps;
+ uint32_t tCKmin_X_minus_1_ps;
+ uint32_t tCKmin_X_minus_2_ps;
+ uint32_t tCKmax_ps;
+ /* SPD-defined CAS latencies */
+ uint32_t caslat_X;
+ uint32_t caslat_X_minus_1;
+ uint32_t caslat_X_minus_2;
+ uint32_t caslat_lowest_derated;
+ /* basic timing parameters */
+ uint32_t tRCD_ps;
+ uint32_t tRP_ps;
+ uint32_t tRAS_ps;
+ uint32_t tWR_ps; /* maximum = 63750 ps */
+ uint32_t tWTR_ps; /* maximum = 63750 ps */
+ uint32_t tRFC_ps; /* max = 255 ns + 256 ns + .75 ns = 511750 ps */
+ uint32_t tRRD_ps; /* maximum = 63750 ps */
+ uint32_t tRC_ps; /* maximum = 254 ns + .75 ns = 254750 ps */
+ uint32_t refresh_rate_ps;
+ uint32_t extended_op_srt;
+ uint32_t tIS_ps; /* byte 32, spd->ca_setup */
+ uint32_t tIH_ps; /* byte 33, spd->ca_hold */
+ uint32_t tDS_ps; /* byte 34, spd->data_setup */
+ uint32_t tDH_ps; /* byte 35, spd->data_hold */
+ uint32_t tRTP_ps; /* byte 38, spd->trtp */
+ uint32_t tDQSQ_max_ps; /* byte 44, spd->tdqsq */
+ uint32_t tQHS_ps; /* byte 45, spd->tqhs */
+ uint32_t rcw[16];
+};
+
+#endif
diff --git a/arch/powerpc/include/asm/fsl_ddr_sdram.h b/arch/powerpc/include/asm/fsl_ddr_sdram.h
new file mode 100644
index 0000000000..b6c0b4dd7a
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_ddr_sdram.h
@@ -0,0 +1,195 @@
+/*
+ * 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
+
+#include <ddr_spd.h>
+
+/* Basic DDR Technology. */
+#define SDRAM_TYPE_DDR1 2
+#define SDRAM_TYPE_DDR2 3
+#define SDRAM_TYPE_LPDDR1 6
+#define SDRAM_TYPE_DDR3 7
+
+#define DDR_BL4 4
+#define DDR_BC4 DDR_BL4
+#define DDR_OTF 6
+#define DDR_BL8 8
+
+#define DDR2_RTT_OFF 0
+#define DDR2_RTT_75_OHM 1
+#define DDR2_RTT_150_OHM 2
+#define DDR2_RTT_50_OHM 3
+#define DDR3_RTT_OFF 0
+#define DDR3_RTT_40_OHM 3
+
+#define FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR (3)
+#if defined(CONFIG_FSL_DDR2)
+typedef struct ddr2_spd_eeprom generic_spd_eeprom_t;
+#define FSL_SDRAM_TYPE SDRAM_TYPE_DDR2
+#elif defined(CONFIG_FSL_DDR3)
+typedef struct ddr3_spd_eeprom generic_spd_eeprom_t;
+#define FSL_SDRAM_TYPE SDRAM_TYPE_DDR3
+#endif
+
+#define FSL_DDR_ODT_NEVER 0x0
+#define FSL_DDR_ODT_CS 0x1
+#define FSL_DDR_ODT_ALL_OTHER_CS 0x2
+#define FSL_DDR_ODT_OTHER_DIMM 0x3
+#define FSL_DDR_ODT_ALL 0x4
+#define FSL_DDR_ODT_SAME_DIMM 0x5
+#define FSL_DDR_ODT_CS_AND_OTHER_DIMM 0x6
+#define FSL_DDR_ODT_OTHER_CS_ONSAMEDIMM 0x7
+
+#define SDRAM_CS_CONFIG_EN 0x80000000
+
+/* 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_16_BE 0x00100000
+#define SDRAM_CFG_8_BE 0x00040000
+#define SDRAM_CFG_NCAP 0x00020000
+#define SDRAM_CFG_2T_EN 0x00008000
+#define SDRAM_CFG_BI 0x00000001
+
+#define SDRAM_CFG2_D_INIT 0x00000010
+#define SDRAM_CFG2_ODT_CFG_MASK 0x00600000
+#define SDRAM_CFG2_ODT_NEVER 0
+#define SDRAM_CFG2_ODT_ONLY_WRITE 1
+#define SDRAM_CFG2_ODT_ONLY_READ 2
+#define SDRAM_CFG2_ODT_ALWAYS 3
+
+#define MAX_CHIP_SELECTS_PER_CTRL 4
+#define MAX_DIMM_SLOTS_PER_CTLR 4
+
+/*
+ * Memory controller characteristics and I2C parameters to
+ * read the SPD data.
+ */
+struct ddr_board_info_s {
+ uint32_t fsl_ddr_ver;
+ void __iomem *ddr_base;
+ uint32_t cs_per_ctrl;
+ uint32_t dimm_slots_per_ctrl;
+ uint32_t i2c_bus;
+ uint32_t i2c_slave;
+ uint32_t i2c_speed;
+ void __iomem *i2c_base;
+ const uint8_t *spd_i2c_addr;
+};
+
+/*
+ * Generalized parameters for memory controller configuration,
+ * might be a little specific to the FSL memory controller
+ */
+struct memctl_options_s {
+ struct ddr_board_info_s *board_info;
+ uint32_t sdram_type;
+ /*
+ * Memory organization parameters
+ *
+ * if DIMM is present in the system
+ * where DIMMs are with respect to chip select
+ * where chip selects are with respect to memory boundaries
+ */
+ uint32_t registered_dimm_en;
+ /* Options local to a Chip Select */
+ struct cs_local_opts_s {
+ uint32_t auto_precharge;
+ uint32_t odt_rd_cfg;
+ uint32_t odt_wr_cfg;
+ uint32_t odt_rtt_norm;
+ uint32_t odt_rtt_wr;
+ } cs_local_opts[MAX_CHIP_SELECTS_PER_CTRL];
+ /* DLL reset disable */
+ uint32_t dll_rst_dis;
+ /* Operational mode parameters */
+ uint32_t ECC_mode;
+ uint32_t ECC_init_using_memctl;
+ uint32_t data_init;
+ /* Use DQS? maybe only with DDR2? */
+ uint32_t DQS_config;
+ uint32_t self_refresh_in_sleep;
+ uint32_t dynamic_power;
+ uint32_t data_bus_width;
+ uint32_t burst_length;
+ uint32_t otf_burst_chop_en;
+ uint32_t mirrored_dimm;
+ uint32_t ap_en;
+ uint32_t x4_en;
+ /* Global Timing Parameters */
+ uint32_t cas_latency_override;
+ uint32_t cas_latency_override_value;
+ uint32_t use_derated_caslat;
+ uint32_t additive_latency_override;
+ uint32_t additive_latency_override_value;
+ uint32_t clk_adjust;
+ uint32_t cpo_override;
+ uint32_t write_data_delay;
+ /* Write leveling */
+ uint32_t wrlvl_override;
+ uint32_t wrlvl_sample;
+ uint32_t wrlvl_start;
+ uint32_t wrlvl_ctl_2;
+ uint32_t wrlvl_ctl_3;
+ uint32_t half_strength_driver_enable;
+ uint32_t twoT_en;
+ uint32_t threet_en;
+ uint32_t bstopre;
+ uint32_t tCKE_clock_pulse_width_ps;
+ uint32_t tFAW_window_four_activates_ps;
+ /* Rtt impedance */
+ uint32_t rtt_override;
+ uint32_t rtt_override_value;
+ uint32_t rtt_wr_override_value;
+ /* Automatic self refresh */
+ uint32_t auto_self_refresh_en;
+ uint32_t sr_it;
+ /* ZQ calibration */
+ uint32_t zq_en;
+ /* Write leveling */
+ uint32_t wrlvl_en;
+ /* RCW override for RDIMM */
+ uint32_t rcw_override;
+ uint32_t rcw_1;
+ uint32_t rcw_2;
+ /* control register 1 */
+ uint32_t ddr_cdr1;
+ uint32_t ddr_cdr2;
+ /* read-to-write turnaround */
+ uint32_t trwt_override;
+ uint32_t trwt;
+ /* Powerdon timings. */
+ uint32_t txp;
+ uint32_t taxpd;
+ uint32_t txard;
+ /* Load mode cycle time */
+ uint32_t tmrd;
+};
+
+extern phys_size_t fsl_ddr_sdram(void);
+extern phys_size_t fixed_sdram(void);
+
+struct dimm_params_s;
+
+void fsl_ddr_board_options(
+ struct memctl_options_s *popts,
+ struct dimm_params_s *pdimm);
+void fsl_ddr_board_info(struct ddr_board_info_s *info);
+
+#endif
diff --git a/arch/powerpc/include/asm/fsl_ifc.h b/arch/powerpc/include/asm/fsl_ifc.h
new file mode 100644
index 0000000000..8faff75033
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_ifc.h
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * Author: Dipen Dudhat <dipen.dudhat@freescale.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __FSL_IFC_H
+#define __FSL_IFC_H
+
+#include <config.h>
+#include <common.h>
+
+/* Big-Endian */
+#define ifc_in32(a) in_be32(a)
+#define ifc_out32(a, v) out_be32(a, v)
+#define ifc_in16(a) in_be16(a)
+
+/*
+ * CSPR - Chip Select Property Register
+ */
+#define CSPR_BA 0xFFFF0000
+#define CSPR_BA_SHIFT 16
+#define CSPR_PORT_SIZE 0x00000180
+#define CSPR_PORT_SIZE_SHIFT 7
+#define CSPR_PORT_SIZE_8 0x00000080
+#define CSPR_PORT_SIZE_16 0x00000100
+#define CSPR_PORT_SIZE_32 0x00000180
+/* Write Protect */
+#define CSPR_WP 0x00000040
+#define CSPR_WP_SHIFT 6
+#define CSPR_MSEL 0x00000006
+#define CSPR_MSEL_SHIFT 1
+#define CSPR_MSEL_NOR 0x00000000
+#define CSPR_MSEL_NAND 0x00000002
+#define CSPR_MSEL_GPCM 0x00000004
+#define CSPR_V 0x00000001
+#define CSPR_V_SHIFT 0
+
+/* Convert an address into the right format for the CSPR Registers */
+#define CSPR_PHYS_ADDR(x) (((uint64_t)x) & 0xffff0000)
+
+/*
+ * Address Mask Register
+ */
+#define IFC_AMASK_MASK 0xFFFF0000
+#define IFC_AMASK_SHIFT 16
+#define IFC_AMASK(n) (IFC_AMASK_MASK << \
+ (__ilog2(n) - IFC_AMASK_SHIFT))
+
+/*
+ * Chip Select Option Register IFC_NAND Machine
+ */
+#define CSOR_NAND_ECC_ENC_EN 0x80000000
+#define CSOR_NAND_ECC_MODE_MASK 0x30000000
+/* 4 bit correction per 520 Byte sector */
+#define CSOR_NAND_ECC_MODE_4 0x00000000
+/* 8 bit correction per 528 Byte sector */
+#define CSOR_NAND_ECC_MODE_8 0x10000000
+#define CSOR_NAND_ECC_DEC_EN 0x04000000
+/* Row Address Length */
+#define CSOR_NAND_RAL_MASK 0x01800000
+#define CSOR_NAND_RAL_SHIFT 20
+#define CSOR_NAND_RAL_1 0x00000000
+#define CSOR_NAND_RAL_2 0x00800000
+#define CSOR_NAND_RAL_3 0x01000000
+#define CSOR_NAND_RAL_4 0x01800000
+/* Page Size 512b, 2k, 4k */
+#define CSOR_NAND_PGS_MASK 0x00180000
+#define CSOR_NAND_PGS_SHIFT 16
+#define CSOR_NAND_PGS_512 0x00000000
+#define CSOR_NAND_PGS_2K 0x00080000
+#define CSOR_NAND_PGS_4K 0x00100000
+#define CSOR_NAND_PGS_8K 0x00180000
+/* Spare region Size */
+#define CSOR_NAND_SPRZ_MASK 0x0000E000
+#define CSOR_NAND_SPRZ_SHIFT 13
+#define CSOR_NAND_SPRZ_16 0x00000000
+#define CSOR_NAND_SPRZ_64 0x00002000
+#define CSOR_NAND_SPRZ_128 0x00004000
+#define CSOR_NAND_SPRZ_210 0x00006000
+#define CSOR_NAND_SPRZ_218 0x00008000
+#define CSOR_NAND_SPRZ_224 0x0000A000
+#define CSOR_NAND_SPRZ_CSOR_EXT 0x0000C000
+/* Pages Per Block */
+#define CSOR_NAND_PB_MASK 0x00000700
+#define CSOR_NAND_PB_SHIFT 8
+#define CSOR_NAND_PB(n) ((__ilog2(n) - 5) << CSOR_NAND_PB_SHIFT)
+/* Time for Read Enable High to Output High Impedance */
+#define CSOR_NAND_TRHZ_MASK 0x0000001C
+#define CSOR_NAND_TRHZ_SHIFT 2
+#define CSOR_NAND_TRHZ_20 0x00000000
+#define CSOR_NAND_TRHZ_40 0x00000004
+#define CSOR_NAND_TRHZ_60 0x00000008
+#define CSOR_NAND_TRHZ_80 0x0000000C
+#define CSOR_NAND_TRHZ_100 0x00000010
+/* Buffer control disable */
+#define CSOR_NAND_BCTLD 0x00000001
+
+/*
+ * Chip Select Option Register - NOR Flash Mode
+ */
+/* Enable Address shift Mode */
+#define CSOR_NOR_ADM_SHFT_MODE_EN 0x80000000
+/* Page Read Enable from NOR device */
+#define CSOR_NOR_PGRD_EN 0x10000000
+/* AVD Toggle Enable during Burst Program */
+#define CSOR_NOR_AVD_TGL_PGM_EN 0x01000000
+/* Address Data Multiplexing Shift */
+#define CSOR_NOR_ADM_MASK 0x0003E000
+#define CSOR_NOR_ADM_SHIFT_SHIFT 13
+#define CSOR_NOR_ADM_SHIFT(n) ((n) << CSOR_NOR_ADM_SHIFT_SHIFT)
+/* Type of the NOR device hooked */
+#define CSOR_NOR_NOR_MODE_AYSNC_NOR 0x00000000
+#define CSOR_NOR_NOR_MODE_AVD_NOR 0x00000020
+/* Time for Read Enable High to Output High Impedance */
+#define CSOR_NOR_TRHZ_MASK 0x0000001C
+#define CSOR_NOR_TRHZ_SHIFT 2
+#define CSOR_NOR_TRHZ_20 0x00000000
+#define CSOR_NOR_TRHZ_40 0x00000004
+#define CSOR_NOR_TRHZ_60 0x00000008
+#define CSOR_NOR_TRHZ_80 0x0000000C
+#define CSOR_NOR_TRHZ_100 0x00000010
+/* Buffer control disable */
+#define CSOR_NOR_BCTLD 0x00000001
+
+/*
+ * Flash Timing Registers (FTIM0 - FTIM2_CSn)
+ */
+
+/*
+ * FTIM0 - NOR Flash Mode
+ */
+#define FTIM0_NOR 0xF03F3F3F
+#define FTIM0_NOR_TACSE_SHIFT 28
+#define FTIM0_NOR_TACSE(n) ((n) << FTIM0_NOR_TACSE_SHIFT)
+#define FTIM0_NOR_TEADC_SHIFT 16
+#define FTIM0_NOR_TEADC(n) ((n) << FTIM0_NOR_TEADC_SHIFT)
+#define FTIM0_NOR_TAVDS_SHIFT 8
+#define FTIM0_NOR_TAVDS(n) ((n) << FTIM0_NOR_TAVDS_SHIFT)
+#define FTIM0_NOR_TEAHC_SHIFT 0
+#define FTIM0_NOR_TEAHC(n) ((n) << FTIM0_NOR_TEAHC_SHIFT)
+/*
+ * FTIM1 - NOR Flash Mode
+ */
+#define FTIM1_NOR 0xFF003F3F
+#define FTIM1_NOR_TACO_SHIFT 24
+#define FTIM1_NOR_TACO(n) ((n) << FTIM1_NOR_TACO_SHIFT)
+#define FTIM1_NOR_TRAD_NOR_SHIFT 8
+#define FTIM1_NOR_TRAD_NOR(n) ((n) << FTIM1_NOR_TRAD_NOR_SHIFT)
+#define FTIM1_NOR_TSEQRAD_NOR_SHIFT 0
+#define FTIM1_NOR_TSEQRAD_NOR(n) ((n) << FTIM1_NOR_TSEQRAD_NOR_SHIFT)
+/*
+ * FTIM2 - NOR Flash Mode
+ */
+#define FTIM2_NOR 0x0F3CFCFF
+#define FTIM2_NOR_TCS_SHIFT 24
+#define FTIM2_NOR_TCS(n) ((n) << FTIM2_NOR_TCS_SHIFT)
+#define FTIM2_NOR_TCH_SHIFT 18
+#define FTIM2_NOR_TCH(n) ((n) << FTIM2_NOR_TCH_SHIFT)
+#define FTIM2_NOR_TWPH_SHIFT 10
+#define FTIM2_NOR_TWPH(n) ((n) << FTIM2_NOR_TWPH_SHIFT)
+#define FTIM2_NOR_TWP_SHIFT 0
+#define FTIM2_NOR_TWP(n) ((n) << FTIM2_NOR_TWP_SHIFT)
+
+/*
+ * FTIM0 - Normal GPCM Mode
+ */
+#define FTIM0_GPCM 0xF03F3F3F
+#define FTIM0_GPCM_TACSE_SHIFT 28
+#define FTIM0_GPCM_TACSE(n) ((n) << FTIM0_GPCM_TACSE_SHIFT)
+#define FTIM0_GPCM_TEADC_SHIFT 16
+#define FTIM0_GPCM_TEADC(n) ((n) << FTIM0_GPCM_TEADC_SHIFT)
+#define FTIM0_GPCM_TAVDS_SHIFT 8
+#define FTIM0_GPCM_TAVDS(n) ((n) << FTIM0_GPCM_TAVDS_SHIFT)
+#define FTIM0_GPCM_TEAHC_SHIFT 0
+#define FTIM0_GPCM_TEAHC(n) ((n) << FTIM0_GPCM_TEAHC_SHIFT)
+/*
+ * FTIM1 - Normal GPCM Mode
+ */
+#define FTIM1_GPCM 0xFF003F00
+#define FTIM1_GPCM_TACO_SHIFT 24
+#define FTIM1_GPCM_TACO(n) ((n) << FTIM1_GPCM_TACO_SHIFT)
+#define FTIM1_GPCM_TRAD_SHIFT 8
+#define FTIM1_GPCM_TRAD(n) ((n) << FTIM1_GPCM_TRAD_SHIFT)
+/*
+ * FTIM2 - Normal GPCM Mode
+ */
+#define FTIM2_GPCM 0x0F3C00FF
+#define FTIM2_GPCM_TCS_SHIFT 24
+#define FTIM2_GPCM_TCS(n) ((n) << FTIM2_GPCM_TCS_SHIFT)
+#define FTIM2_GPCM_TCH_SHIFT 18
+#define FTIM2_GPCM_TCH(n) ((n) << FTIM2_GPCM_TCH_SHIFT)
+#define FTIM2_GPCM_TWP_SHIFT 0
+#define FTIM2_GPCM_TWP(n) ((n) << FTIM2_GPCM_TWP_SHIFT)
+
+/*
+ * General Control Register (GCR)
+ */
+#define IFC_GCR_MASK 0x8000F800
+/* reset all IFC hardware */
+#define IFC_GCR_SOFT_RST_ALL 0x80000000
+/* Turnaroud Time of external buffer */
+#define IFC_GCR_TBCTL_TRN_TIME 0x0000F800
+#define IFC_GCR_TBCTL_TRN_TIME_SHIFT 11
+
+/*
+ * Clock Control Register (CCR)
+ */
+#define IFC_CCR_MASK 0x0F0F8800
+/* Clock division ratio */
+#define IFC_CCR_CLK_DIV_MASK 0x0F000000
+#define IFC_CCR_CLK_DIV_SHIFT 24
+#define IFC_CCR_CLK_DIV(n) ((n-1) << IFC_CCR_CLK_DIV_SHIFT)
+/* IFC Clock Delay */
+#define IFC_CCR_CLK_DLY_MASK 0x000F0000
+#define IFC_CCR_CLK_DLY_SHIFT 16
+#define IFC_CCR_CLK_DLY(n) ((n) << IFC_CCR_CLK_DLY_SHIFT)
+
+#ifndef __ASSEMBLY__
+#include <asm/io.h>
+
+#define IFC_BASE_ADDR ((void __iomem *)IFC_ADDR)
+#define FSL_IFC_CSPRX(i) (0x10 + ((i) * 0xc))
+#define FSL_IFC_CSORX(i) (0x130 + ((i) * 0xc))
+#define FSL_IFC_AMASKX(i) (0xa0 + ((i) * 0xc))
+#define FSL_IFC_CSX_FTIMY(i, j) ((0x1c0 + ((i) * 0x30)) + ((j) * 4))
+
+#define get_ifc_cspr(i) (ifc_in32(IFC_BASE_ADDR + FSL_IFC_CSPRX(i)))
+#define get_ifc_csor(i) (ifc_in32(IFC_BASE_ADDR + FSL_IFC_CSORX(i))
+#define get_ifc_amask(i) (ifc_in32(IFC_BASE_ADDR + FSL_IFC_AMASKX(i)))
+#define get_ifc_ftim(i, j) (ifc_in32(IFC_BASE_ADDR + FSL_IFC_CSX_FTIMY(i, j)))
+
+#define set_ifc_cspr(i, v) (ifc_out32(IFC_BASE_ADDR + FSL_IFC_CSPRX(i), v))
+#define set_ifc_csor(i, v) (ifc_out32(IFC_BASE_ADDR + FSL_IFC_CSORX(i), v))
+#define set_ifc_amask(i, v) (ifc_out32(IFC_BASE_ADDR + FSL_IFC_AMASKX(i), v))
+#define set_ifc_ftim(i, j, v) \
+ (ifc_out32(IFC_BASE_ADDR + FSL_IFC_CSX_FTIMY(i, j), v))
+
+#define FSL_IFC_GCR_OFFSET 0x40c
+#define FSL_IFC_CCR_OFFSET 0x44c
+
+enum ifc_chip_sel {
+ IFC_CS0,
+ IFC_CS1,
+ IFC_CS2,
+ IFC_CS3,
+ IFC_CS4,
+ IFC_CS5,
+ IFC_CS6,
+ IFC_CS7,
+};
+
+enum ifc_ftims {
+ IFC_FTIM0,
+ IFC_FTIM1,
+ IFC_FTIM2,
+ IFC_FTIM3,
+};
+
+#ifdef CONFIG_FSL_ERRATUM_IFC_A002769
+#undef CSPR_MSEL_NOR
+#define CSPR_MSEL_NOR CSPR_MSEL_GPCM
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __FSL_IFC_H */
diff --git a/arch/powerpc/include/asm/fsl_law.h b/arch/powerpc/include/asm/fsl_law.h
new file mode 100644
index 0000000000..7acb63c9de
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_law.h
@@ -0,0 +1,92 @@
+/*
+ * 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 FSL_SET_LAW_ENTRY(idx, a, sz, trgt) \
+ { .index = idx, .addr = a, .size = sz, .trgt_id = trgt }
+
+#define FSL_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 fsl_law_size_bits(sz) (__ilog2_u64(sz) - 1)
+#define fsl_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
+#define LAW_TRGT_IF_IFC LAW_TRGT_IF_LBC
+
+
+#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 fsl_set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id);
+extern void fsl_init_laws(void);
+
+/* define in board code */
+extern struct law_entry law_table[];
+extern int num_law_entries;
+#endif
diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h
new file mode 100644
index 0000000000..cde0864378
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_lbc.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2012 GE Intelligent Platforms, Inc.
+ * Copyright (C) 2004-2008,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 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_DECC_SHIFT 9
+#define BR_V 0x00000001
+#define BR_V_SHIFT 0
+#define BR_MS_FCM 0x00000020
+#define BR_MS_UPMA 0x00000080
+
+/* Convert an address into the right format for the BR registers */
+#define BR_PHYS_ADDR(x) ((x) & 0xffff8000)
+
+/*
+ * 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>
+
+/* 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 fsl_get_lbc_br(x) (in_be32((LBC_BASE_ADDR + FSL_LBC_BRX(x))))
+#define fsl_get_lbc_or(x) (in_be32((LBC_BASE_ADDR + FSL_LBC_ORX(x))))
+#define fsl_set_lbc_br(x, v) (out_be32((LBC_BASE_ADDR + FSL_LBC_BRX(x)), v))
+#define fsl_set_lbc_or(x, v) (out_be32((LBC_BASE_ADDR + FSL_LBC_ORX(x)), v))
+
+#define FSL_LBC_MAR_OFFSET 0x68
+#define FSL_LBC_MAMR_OFFSET 0x70
+#define FSL_LBC_MDR_OFFSET 0x88
+#define FSL_LBC_LTESR_OFFSET 0xB0
+#define FSL_LBC_LTEIR_OFFSET 0xB8
+#define FSL_LBC_LBCR_OFFSET 0xD0
+
+#define MxMR_MAD_MSK 0x0000003f /* Machine Address Mask */
+#define MxMR_GPL_x4DIS 0x00040000 /* GPL_A4 Ouput Line Disable */
+#define MxMR_OP_NORM 0x00000000 /* Normal Operation */
+#define MxMR_OP_WARR 0x10000000 /* Write to Array */
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_PPC_FSL_LBC_H */
diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h
new file mode 100644
index 0000000000..88f14b54f4
--- /dev/null
+++ b/arch/powerpc/include/asm/io.h
@@ -0,0 +1,257 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/* originally from linux source.
+ * removed the dependencies on CONFIG_ values
+ * removed virt_to_phys stuff (and in fact everything surrounded by #if __KERNEL__)
+ * Modified By Rob Taylor, Flying Pig Systems, 2000
+ */
+
+#ifndef _PPC_IO_H
+#define _PPC_IO_H
+
+#include <asm/byteorder.h>
+
+#define SIO_CONFIG_RA 0x398
+#define SIO_CONFIG_RD 0x399
+
+#define _IO_BASE 0
+
+#define readb(addr) in_8((volatile u8 *)(addr))
+#define writeb(b,addr) out_8((volatile u8 *)(addr), (b))
+#if !defined(__BIG_ENDIAN)
+#define readw(addr) (*(volatile u16 *) (addr))
+#define readl(addr) (*(volatile u32 *) (addr))
+#define writew(b,addr) ((*(volatile u16 *) (addr)) = (b))
+#define writel(b,addr) ((*(volatile u32 *) (addr)) = (b))
+#else
+#define readw(addr) in_le16((volatile u16 *)(addr))
+#define readl(addr) in_le32((volatile u32 *)(addr))
+#define writew(b,addr) out_le16((volatile u16 *)(addr),(b))
+#define writel(b,addr) out_le32((volatile u32 *)(addr),(b))
+#endif
+
+/*
+ * The insw/outsw/insl/outsl macros don't do byte-swapping.
+ * They are only used in practice for transferring buffers which
+ * are arrays of bytes, and byte-swapping is not appropriate in
+ * that case. - paulus
+ */
+#define insb(port, buf, ns) _insb((u8 *)((port)+_IO_BASE), (buf), (ns))
+#define outsb(port, buf, ns) _outsb((u8 *)((port)+_IO_BASE), (buf), (ns))
+#define insw(port, buf, ns) _insw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
+#define outsw(port, buf, ns) _outsw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
+#define insl(port, buf, nl) _insl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
+#define outsl(port, buf, nl) _outsl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
+
+#define inb(port) in_8((u8 *)((port)+_IO_BASE))
+#define outb(val, port) out_8((u8 *)((port)+_IO_BASE), (val))
+#if !defined(__BIG_ENDIAN)
+#define inw(port) in_be16((u16 *)((port)+_IO_BASE))
+#define outw(val, port) out_be16((u16 *)((port)+_IO_BASE), (val))
+#define inl(port) in_be32((u32 *)((port)+_IO_BASE))
+#define outl(val, port) out_be32((u32 *)((port)+_IO_BASE), (val))
+#else
+#define inw(port) in_le16((u16 *)((port)+_IO_BASE))
+#define outw(val, port) out_le16((u16 *)((port)+_IO_BASE), (val))
+#define inl(port) in_le32((u32 *)((port)+_IO_BASE))
+#define outl(val, port) out_le32((u32 *)((port)+_IO_BASE), (val))
+#endif
+
+#define inb_p(port) in_8((u8 *)((port)+_IO_BASE))
+#define outb_p(val, port) out_8((u8 *)((port)+_IO_BASE), (val))
+#define inw_p(port) in_le16((u16 *)((port)+_IO_BASE))
+#define outw_p(val, port) out_le16((u16 *)((port)+_IO_BASE), (val))
+#define inl_p(port) in_le32((u32 *)((port)+_IO_BASE))
+#define outl_p(val, port) out_le32((u32 *)((port)+_IO_BASE), (val))
+
+extern void _insb(volatile u8 *port, void *buf, int ns);
+extern void _outsb(volatile u8 *port, const void *buf, int ns);
+extern void _insw(volatile u16 *port, void *buf, int ns);
+extern void _outsw(volatile u16 *port, const void *buf, int ns);
+extern void _insl(volatile u32 *port, void *buf, int nl);
+extern void _outsl(volatile u32 *port, const void *buf, int nl);
+extern void _insw_ns(volatile u16 *port, void *buf, int ns);
+extern void _outsw_ns(volatile u16 *port, const void *buf, int ns);
+extern void _insl_ns(volatile u32 *port, void *buf, int nl);
+extern void _outsl_ns(volatile u32 *port, const void *buf, int nl);
+
+/*
+ * The *_ns versions below don't do byte-swapping.
+ * Neither do the standard versions now, these are just here
+ * for older code.
+ */
+#define insw_ns(port, buf, ns) _insw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
+#define outsw_ns(port, buf, ns) _outsw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
+#define insl_ns(port, buf, nl) _insl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
+#define outsl_ns(port, buf, nl) _outsl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
+
+
+#define IO_SPACE_LIMIT ~0
+
+/*
+ * Enforce In-order Execution of I/O:
+ * Acts as a barrier to ensure all previous I/O accesses have
+ * completed before any further ones are issued.
+ */
+#define eieio() __asm__ __volatile__ ("eieio" : : : "memory");
+#define sync() __asm__ __volatile__ ("sync" : : : "memory");
+
+/* Enforce in-order execution of data I/O.
+ * No distinction between read/write on PPC; use eieio for all three.
+ */
+#define iobarrier_rw() eieio()
+#define iobarrier_r() eieio()
+#define iobarrier_w() eieio()
+
+/*
+ * Non ordered and non-swapping "raw" accessors
+ */
+static inline unsigned char __raw_readb(const volatile void __iomem *addr)
+{
+ return *(volatile unsigned char __force *)(addr);
+}
+static inline unsigned short __raw_readw(const volatile void __iomem *addr)
+{
+ return *(volatile unsigned short __force *)(addr);
+}
+static inline unsigned int __raw_readl(const volatile void __iomem *addr)
+{
+ return *(volatile unsigned int __force *)(addr);
+}
+static inline void __raw_writeb(unsigned char v, volatile void __iomem *addr)
+{
+ *(volatile unsigned char __force *)(addr) = v;
+}
+static inline void __raw_writew(unsigned short v, volatile void __iomem *addr)
+{
+ *(volatile unsigned short __force *)(addr) = v;
+}
+static inline void __raw_writel(unsigned int v, volatile void __iomem *addr)
+{
+ *(volatile unsigned int __force *)(addr) = v;
+}
+
+/*
+ * 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
+ */
+#define in_8 in_8
+static inline u8 in_8(const volatile u8 __iomem *addr)
+{
+ u8 ret;
+
+ __asm__ __volatile__("sync; lbz%U1%X1 %0,%1; twi 0,%0,0; isync"
+ : "=r" (ret) : "m" (*addr));
+ return ret;
+}
+
+#define out_8 out_8
+static inline void out_8(volatile u8 __iomem *addr, u8 val)
+{
+ __asm__ __volatile__("sync;stb%U0%X0 %1,%0" : "=m" (*addr) : "r" (val));
+}
+
+#define in_le16 in_le16
+static inline u16 in_le16(const volatile u16 __iomem *addr)
+{
+ u16 ret;
+
+ __asm__ __volatile__("sync; lhbrx %0,0,%1; twi 0,%0,0; isync"
+ : "=r" (ret) : "r" (addr), "m" (*addr));
+ return ret;
+}
+
+#define in_be16 in_be16
+static inline u16 in_be16(const volatile u16 __iomem *addr)
+{
+ u16 ret;
+
+ __asm__ __volatile__("sync; lhz%U1%X1 %0,%1; twi 0,%0,0; isync"
+ : "=r" (ret) : "m" (*addr));
+ return ret;
+}
+
+#define out_le16 out_le16
+static inline void out_le16(volatile u16 __iomem *addr, u16 val)
+{
+ __asm__ __volatile__("sync; sthbrx %1,0,%2"
+ : "=m" (*addr) : "r" (val), "r" (addr));
+}
+
+#define out_be16 out_be16
+static inline void out_be16(volatile u16 __iomem *addr, u16 val)
+{
+ __asm__ __volatile__("sync;sth%U0%X0 %1,%0" : "=m" (*addr) : "r" (val));
+}
+
+#define in_le32 in_le32
+static inline u32 in_le32(const volatile u32 __iomem *addr)
+{
+ u32 ret;
+
+ __asm__ __volatile__("sync; lwbrx %0,0,%1; twi 0,%0,0; isync"
+ : "=r" (ret) : "r" (addr), "m" (*addr));
+ return ret;
+}
+
+#define in_be32 in_be32
+static inline u32 in_be32(const volatile u32 __iomem *addr)
+{
+ u32 ret;
+
+ __asm__ __volatile__("sync; lwz%U1%X1 %0,%1; twi 0,%0,0; isync"
+ : "=r" (ret) : "m" (*addr));
+ return ret;
+}
+
+#define out_le32 out_le32
+static inline void out_le32(volatile u32 __iomem *addr, u32 val)
+{
+ __asm__ __volatile__("sync; stwbrx %1,0,%2"
+ : "=m" (*addr) : "r" (val), "r" (addr));
+}
+
+#define out_be32 out_be32
+static inline void out_be32(volatile u32 __iomem *addr, u32 val)
+{
+ __asm__ __volatile__("sync;stw%U0%X0 %1,%0" : "=m" (*addr) : "r" (val));
+}
+
+/*
+ * Clear and set bits in one shot. These macros can be used to clear and
+ * set multiple bits in a register using a single call. These macros can
+ * also be used to set a multiple-bit bit pattern using a mask, by
+ * specifying the mask in the 'clear' parameter and the new bit pattern
+ * in the 'set' parameter.
+ */
+#define clrbits(type, addr, clear) \
+ out_##type((addr), in_##type(addr) & ~(clear))
+
+#define setbits(type, addr, set) \
+ out_##type((addr), in_##type(addr) | (set))
+
+#define clrsetbits(type, addr, clear, set) \
+ out_##type((addr), (in_##type(addr) & ~(clear)) | (set))
+
+#define clrbits_be32(addr, clear) clrbits(be32, addr, clear)
+#define setbits_be32(addr, set) setbits(be32, addr, set)
+#define clrsetbits_be32(addr, clear, set) clrsetbits(be32, addr, clear, set)
+
+/* these ones were originally in config.h */
+unsigned char in8(unsigned int);
+void out8(unsigned int, unsigned char);
+unsigned short in16(unsigned int);
+unsigned short in16r(unsigned int);
+void out16(unsigned int, unsigned short value);
+void out16r(unsigned int, unsigned short value);
+unsigned long in32(unsigned int);
+unsigned long in32r(unsigned int);
+void out32(unsigned int, unsigned long value);
+void out32r(unsigned int, unsigned long value);
+void ppcDcbf(unsigned long value);
+void ppcDcbi(unsigned long value);
+void ppcSync(void);
+void ppcDcbz(unsigned long value);
+
+#include <asm-generic/io.h>
+
+#endif
diff --git a/arch/powerpc/include/asm/linkage.h b/arch/powerpc/include/asm/linkage.h
new file mode 100644
index 0000000000..370eb27728
--- /dev/null
+++ b/arch/powerpc/include/asm/linkage.h
@@ -0,0 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_POWERPC_LINKAGE_H
+#define _ASM_POWERPC_LINKAGE_H
+
+#endif /* _ASM_POWERPC_LINKAGE_H */
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h
new file mode 100644
index 0000000000..10b15a47b9
--- /dev/null
+++ b/arch/powerpc/include/asm/mmu.h
@@ -0,0 +1,571 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * PowerPC memory management structures
+ */
+
+#ifndef _PPC_MMU_H_
+#define _PPC_MMU_H_
+
+#ifndef __ASSEMBLY__
+/* Hardware Page Table Entry */
+typedef struct _PTE {
+#ifdef CONFIG_PPC64BRIDGE
+ unsigned long long vsid:52;
+ unsigned long api:5;
+ unsigned long :5;
+ unsigned long h:1;
+ unsigned long v:1;
+ unsigned long long rpn:52;
+#else /* CONFIG_PPC64BRIDGE */
+ unsigned long v:1; /* Entry is valid */
+ unsigned long vsid:24; /* Virtual segment identifier */
+ unsigned long h:1; /* Hash algorithm indicator */
+ unsigned long api:6; /* Abbreviated page index */
+ unsigned long rpn:20; /* Real (physical) page number */
+#endif /* CONFIG_PPC64BRIDGE */
+ unsigned long :3; /* Unused */
+ unsigned long r:1; /* Referenced */
+ unsigned long c:1; /* Changed */
+ unsigned long w:1; /* Write-thru cache mode */
+ unsigned long i:1; /* Cache inhibited */
+ unsigned long m:1; /* Memory coherence */
+ unsigned long g:1; /* Guarded */
+ unsigned long :1; /* Unused */
+ unsigned long pp:2; /* Page protection */
+} PTE;
+
+/* Values for PP (assumes Ks=0, Kp=1) */
+#define PP_RWXX 0 /* Supervisor read/write, User none */
+#define PP_RWRX 1 /* Supervisor read/write, User read */
+#define PP_RWRW 2 /* Supervisor read/write, User read/write */
+#define PP_RXRX 3 /* Supervisor read, User read */
+
+/* Segment Register */
+typedef struct _SEGREG {
+ unsigned long t:1; /* Normal or I/O type */
+ unsigned long ks:1; /* Supervisor 'key' (normally 0) */
+ unsigned long kp:1; /* User 'key' (normally 1) */
+ unsigned long n:1; /* No-execute */
+ unsigned long :4; /* Unused */
+ unsigned long vsid:24; /* Virtual Segment Identifier */
+} SEGREG;
+
+/* Block Address Translation (BAT) Registers */
+typedef struct _P601_BATU { /* Upper part of BAT for 601 processor */
+ unsigned long bepi:15; /* Effective page index (virtual address) */
+ unsigned long :8; /* unused */
+ unsigned long w:1;
+ unsigned long i:1; /* Cache inhibit */
+ unsigned long m:1; /* Memory coherence */
+ unsigned long ks:1; /* Supervisor key (normally 0) */
+ unsigned long kp:1; /* User key (normally 1) */
+ unsigned long pp:2; /* Page access protections */
+} P601_BATU;
+
+typedef struct _BATU { /* Upper part of BAT (all except 601) */
+#ifdef CONFIG_PPC64BRIDGE
+ unsigned long long bepi:47;
+#else /* CONFIG_PPC64BRIDGE */
+ unsigned long bepi:15; /* Effective page index (virtual address) */
+#endif /* CONFIG_PPC64BRIDGE */
+ unsigned long :4; /* Unused */
+ unsigned long bl:11; /* Block size mask */
+ unsigned long vs:1; /* Supervisor valid */
+ unsigned long vp:1; /* User valid */
+} BATU;
+
+typedef struct _P601_BATL { /* Lower part of BAT for 601 processor */
+ unsigned long brpn:15; /* Real page index (physical address) */
+ unsigned long :10; /* Unused */
+ unsigned long v:1; /* Valid bit */
+ unsigned long bl:6; /* Block size mask */
+} P601_BATL;
+
+typedef struct _BATL { /* Lower part of BAT (all except 601) */
+#ifdef CONFIG_PPC64BRIDGE
+ unsigned long long brpn:47;
+#else /* CONFIG_PPC64BRIDGE */
+ unsigned long brpn:15; /* Real page index (physical address) */
+#endif /* CONFIG_PPC64BRIDGE */
+ unsigned long :10; /* Unused */
+ unsigned long w:1; /* Write-thru cache */
+ unsigned long i:1; /* Cache inhibit */
+ unsigned long m:1; /* Memory coherence */
+ unsigned long g:1; /* Guarded (MBZ in IBAT) */
+ unsigned long :1; /* Unused */
+ unsigned long pp:2; /* Page access protections */
+} BATL;
+
+typedef struct _BAT {
+ BATU batu; /* Upper register */
+ BATL batl; /* Lower register */
+} BAT;
+
+typedef struct _P601_BAT {
+ P601_BATU batu; /* Upper register */
+ P601_BATL batl; /* Lower register */
+} P601_BAT;
+
+/*
+ * Simulated two-level MMU. This structure is used by the kernel
+ * to keep track of MMU mappings and is used to update/maintain
+ * the hardware HASH table which is really a cache of mappings.
+ *
+ * The simulated structures mimic the hardware available on other
+ * platforms, notably the 80x86 and 680x0.
+ */
+
+typedef struct _pte {
+ unsigned long page_num:20;
+ unsigned long flags:12; /* Page flags (some unused bits) */
+} pte;
+
+#define PD_SHIFT (10+12) /* Page directory */
+#define PD_MASK 0x02FF
+#define PT_SHIFT (12) /* Page Table */
+#define PT_MASK 0x02FF
+#define PG_SHIFT (12) /* Page Entry */
+
+
+/* MMU context */
+
+typedef struct _MMU_context {
+ SEGREG segs[16]; /* Segment registers */
+ pte **pmap; /* Two-level page-map structure */
+} MMU_context;
+
+extern void _tlbie(unsigned long va); /* invalidate a TLB entry */
+extern void _tlbia(void); /* invalidate all TLB entries */
+
+typedef enum {
+ IBAT0 = 0, IBAT1, IBAT2, IBAT3,
+ DBAT0, DBAT1, DBAT2, DBAT3
+} ppc_bat_t;
+
+extern int read_bat(ppc_bat_t bat, unsigned long *upper, unsigned long *lower);
+extern int write_bat(ppc_bat_t bat, unsigned long upper, unsigned long lower);
+
+#endif /* __ASSEMBLY__ */
+
+/* Block size masks */
+#define BL_128K 0x000
+#define BL_256K 0x001
+#define BL_512K 0x003
+#define BL_1M 0x007
+#define BL_2M 0x00F
+#define BL_4M 0x01F
+#define BL_8M 0x03F
+#define BL_16M 0x07F
+#define BL_32M 0x0FF
+#define BL_64M 0x1FF
+#define BL_128M 0x3FF
+#define BL_256M 0x7FF
+
+/* BAT Access Protection */
+#define BPP_XX 0x00 /* No access */
+#define BPP_RX 0x01 /* Read only */
+#define BPP_RW 0x02 /* Read/write */
+
+/* Used to set up SDR1 register */
+#define HASH_TABLE_SIZE_64K 0x00010000
+#define HASH_TABLE_SIZE_128K 0x00020000
+#define HASH_TABLE_SIZE_256K 0x00040000
+#define HASH_TABLE_SIZE_512K 0x00080000
+#define HASH_TABLE_SIZE_1M 0x00100000
+#define HASH_TABLE_SIZE_2M 0x00200000
+#define HASH_TABLE_SIZE_4M 0x00400000
+#define HASH_TABLE_MASK_64K 0x000
+#define HASH_TABLE_MASK_128K 0x001
+#define HASH_TABLE_MASK_256K 0x003
+#define HASH_TABLE_MASK_512K 0x007
+#define HASH_TABLE_MASK_1M 0x00F
+#define HASH_TABLE_MASK_2M 0x01F
+#define HASH_TABLE_MASK_4M 0x03F
+
+/* Control/status registers for the MPC8xx.
+ * A write operation to these registers causes serialized access.
+ * During software tablewalk, the registers used perform mask/shift-add
+ * operations when written/read. A TLB entry is created when the Mx_RPN
+ * is written, and the contents of several registers are used to
+ * create the entry.
+ */
+#define MI_CTR 784 /* Instruction TLB control register */
+#define MI_GPM 0x80000000 /* Set domain manager mode */
+#define MI_PPM 0x40000000 /* Set subpage protection */
+#define MI_CIDEF 0x20000000 /* Set cache inhibit when MMU dis */
+#define MI_RSV4I 0x08000000 /* Reserve 4 TLB entries */
+#define MI_PPCS 0x02000000 /* Use MI_RPN prob/priv state */
+#define MI_IDXMASK 0x00001f00 /* TLB index to be loaded */
+#define MI_RESETVAL 0x00000000 /* Value of register at reset */
+
+/* These are the Ks and Kp from the PowerPC books. For proper operation,
+ * Ks = 0, Kp = 1.
+ */
+#define MI_AP 786
+#define MI_Ks 0x80000000 /* Should not be set */
+#define MI_Kp 0x40000000 /* Should always be set */
+
+/* The effective page number register. When read, contains the information
+ * about the last instruction TLB miss. When MI_RPN is written, bits in
+ * this register are used to create the TLB entry.
+ */
+#define MI_EPN 787
+#define MI_EPNMASK 0xfffff000 /* Effective page number for entry */
+#define MI_EVALID 0x00000200 /* Entry is valid */
+#define MI_ASIDMASK 0x0000000f /* ASID match value */
+ /* Reset value is undefined */
+
+/* A "level 1" or "segment" or whatever you want to call it register.
+ * For the instruction TLB, it contains bits that get loaded into the
+ * TLB entry when the MI_RPN is written.
+ */
+#define MI_TWC 789
+#define MI_APG 0x000001e0 /* Access protection group (0) */
+#define MI_GUARDED 0x00000010 /* Guarded storage */
+#define MI_PSMASK 0x0000000c /* Mask of page size bits */
+#define MI_PS8MEG 0x0000000c /* 8M page size */
+#define MI_PS512K 0x00000004 /* 512K page size */
+#define MI_PS4K_16K 0x00000000 /* 4K or 16K page size */
+#define MI_SVALID 0x00000001 /* Segment entry is valid */
+ /* Reset value is undefined */
+
+/* Real page number. Defined by the pte. Writing this register
+ * causes a TLB entry to be created for the instruction TLB, using
+ * additional information from the MI_EPN, and MI_TWC registers.
+ */
+#define MI_RPN 790
+
+/* Define an RPN value for mapping kernel memory to large virtual
+ * pages for boot initialization. This has real page number of 0,
+ * large page size, shared page, cache enabled, and valid.
+ * Also mark all subpages valid and write access.
+ */
+#define MI_BOOTINIT 0x000001fd
+
+#define MD_CTR 792 /* Data TLB control register */
+#define MD_GPM 0x80000000 /* Set domain manager mode */
+#define MD_PPM 0x40000000 /* Set subpage protection */
+#define MD_CIDEF 0x20000000 /* Set cache inhibit when MMU dis */
+#define MD_WTDEF 0x10000000 /* Set writethrough when MMU dis */
+#define MD_RSV4I 0x08000000 /* Reserve 4 TLB entries */
+#define MD_TWAM 0x04000000 /* Use 4K page hardware assist */
+#define MD_PPCS 0x02000000 /* Use MI_RPN prob/priv state */
+#define MD_IDXMASK 0x00001f00 /* TLB index to be loaded */
+#define MD_RESETVAL 0x04000000 /* Value of register at reset */
+
+#define M_CASID 793 /* Address space ID (context) to match */
+#define MC_ASIDMASK 0x0000000f /* Bits used for ASID value */
+
+
+/* These are the Ks and Kp from the PowerPC books. For proper operation,
+ * Ks = 0, Kp = 1.
+ */
+#define MD_AP 794
+#define MD_Ks 0x80000000 /* Should not be set */
+#define MD_Kp 0x40000000 /* Should always be set */
+
+/* The effective page number register. When read, contains the information
+ * about the last instruction TLB miss. When MD_RPN is written, bits in
+ * this register are used to create the TLB entry.
+ */
+#define MD_EPN 795
+#define MD_EPNMASK 0xfffff000 /* Effective page number for entry */
+#define MD_EVALID 0x00000200 /* Entry is valid */
+#define MD_ASIDMASK 0x0000000f /* ASID match value */
+ /* Reset value is undefined */
+
+/* The pointer to the base address of the first level page table.
+ * During a software tablewalk, reading this register provides the address
+ * of the entry associated with MD_EPN.
+ */
+#define M_TWB 796
+#define M_L1TB 0xfffff000 /* Level 1 table base address */
+#define M_L1INDX 0x00000ffc /* Level 1 index, when read */
+ /* Reset value is undefined */
+
+/* A "level 1" or "segment" or whatever you want to call it register.
+ * For the data TLB, it contains bits that get loaded into the TLB entry
+ * when the MD_RPN is written. It is also provides the hardware assist
+ * for finding the PTE address during software tablewalk.
+ */
+#define MD_TWC 797
+#define MD_L2TB 0xfffff000 /* Level 2 table base address */
+#define MD_L2INDX 0xfffffe00 /* Level 2 index (*pte), when read */
+#define MD_APG 0x000001e0 /* Access protection group (0) */
+#define MD_GUARDED 0x00000010 /* Guarded storage */
+#define MD_PSMASK 0x0000000c /* Mask of page size bits */
+#define MD_PS8MEG 0x0000000c /* 8M page size */
+#define MD_PS512K 0x00000004 /* 512K page size */
+#define MD_PS4K_16K 0x00000000 /* 4K or 16K page size */
+#define MD_WT 0x00000002 /* Use writethrough page attribute */
+#define MD_SVALID 0x00000001 /* Segment entry is valid */
+ /* Reset value is undefined */
+
+
+/* Real page number. Defined by the pte. Writing this register
+ * causes a TLB entry to be created for the data TLB, using
+ * additional information from the MD_EPN, and MD_TWC registers.
+ */
+#define MD_RPN 798
+
+/* This is a temporary storage register that could be used to save
+ * a processor working register during a tablewalk.
+ */
+#define M_TW 799
+
+/*
+ * At present, all PowerPC 400-class processors share a similar TLB
+ * architecture. The instruction and data sides share a unified,
+ * 64-entry, fully-associative TLB which is maintained totally under
+ * software control. In addition, the instruction side has a
+ * hardware-managed, 4-entry, fully- associative TLB which serves as a
+ * first level to the shared TLB. These two TLBs are known as the UTLB
+ * and ITLB, respectively.
+ */
+
+#define PPC4XX_TLB_SIZE 64
+
+/*
+ * TLB entries are defined by a "high" tag portion and a "low" data
+ * portion. On all architectures, the data portion is 32-bits.
+ *
+ * TLB entries are managed entirely under software control by reading,
+ * writing, and searchoing using the 4xx-specific tlbre, tlbwr, and tlbsx
+ * instructions.
+ */
+
+#define TLB_LO 1
+#define TLB_HI 0
+
+#define TLB_DATA TLB_LO
+#define TLB_TAG TLB_HI
+
+/* Tag portion */
+
+#define TLB_EPN_MASK 0xFFFFFC00 /* Effective Page Number */
+#define TLB_PAGESZ_MASK 0x00000380
+#define TLB_PAGESZ(x) (((x) & 0x7) << 7)
+#define PAGESZ_1K 0
+#define PAGESZ_4K 1
+#define PAGESZ_16K 2
+#define PAGESZ_64K 3
+#define PAGESZ_256K 4
+#define PAGESZ_1M 5
+#define PAGESZ_4M 6
+#define PAGESZ_16M 7
+#define TLB_VALID 0x00000040 /* Entry is valid */
+
+/* Data portion */
+
+#define TLB_RPN_MASK 0xFFFFFC00 /* Real Page Number */
+#define TLB_PERM_MASK 0x00000300
+#define TLB_EX 0x00000200 /* Instruction execution allowed */
+#define TLB_WR 0x00000100 /* Writes permitted */
+#define TLB_ZSEL_MASK 0x000000F0
+#define TLB_ZSEL(x) (((x) & 0xF) << 4)
+#define TLB_ATTR_MASK 0x0000000F
+#define TLB_W 0x00000008 /* Caching is write-through */
+#define TLB_I 0x00000004 /* Caching is inhibited */
+#define TLB_M 0x00000002 /* Memory is coherent */
+#define TLB_G 0x00000001 /* Memory is guarded from prefetch */
+
+/*
+ * e500 support
+ */
+
+#define MAS0_TLBSEL_MSK 0x30000000
+#define MAS0_TLBSEL(x) (((x) << 28) & MAS0_TLBSEL_MSK)
+#define MAS0_ESEL_MSK 0x0FFF0000
+#define MAS0_ESEL(x) (((x) << 16) & MAS0_ESEL_MSK)
+#define MAS0_NV(x) ((x) & 0x00000FFF)
+
+#define MAS1_VALID 0x80000000
+#define MAS1_IPROT 0x40000000
+#define MAS1_TID(x) (((x) << 16) & 0x3FFF0000)
+#define MAS1_TS 0x00001000
+#define MAS1_TSIZE(x) (((x) << 7) & 0x00000F80)
+
+#define MAS2_EPN 0xFFFFF000
+#define MAS2_SHAREN 0x00000200
+#define MAS2_X0 0x00000040
+#define MAS2_X1 0x00000020
+#define MAS2_W 0x00000010
+#define MAS2_I 0x00000008
+#define MAS2_M 0x00000004
+#define MAS2_G 0x00000002
+#define MAS2_E 0x00000001
+
+#define MAS3_RPN 0xFFFFF000
+#define MAS3_U0 0x00000200
+#define MAS3_U1 0x00000100
+#define MAS3_U2 0x00000080
+#define MAS3_U3 0x00000040
+#define MAS3_UX 0x00000020
+#define MAS3_SX 0x00000010
+#define MAS3_UW 0x00000008
+#define MAS3_SW 0x00000004
+#define MAS3_UR 0x00000002
+#define MAS3_SR 0x00000001
+
+#define MAS4_TLBSELD(x) MAS0_TLBSEL(x)
+#define MAS4_TIDDSEL 0x000F0000
+#define MAS4_TSIZED(x) MAS1_TSIZE(x)
+#define MAS4_DSHAREN 0x00001000
+#define MAS4_X0D 0x00000040
+#define MAS4_X1D 0x00000020
+#define MAS4_WD 0x00000010
+#define MAS4_ID 0x00000008
+#define MAS4_MD 0x00000004
+#define MAS4_GD 0x00000002
+#define MAS4_ED 0x00000001
+
+#define MAS6_SPID 0x00FF0000
+#define MAS6_SAS 0x00000001
+
+#define MAS7_RPN 0xFFFFFFFF
+
+#define FSL_BOOKE_MAS0(tlbsel, esel, nv) \
+ (MAS0_TLBSEL(tlbsel) | MAS0_ESEL(esel) | MAS0_NV(nv))
+#define FSL_BOOKE_MAS1(v, iprot, tid, ts, tsize) \
+ ((((v) << 31) & MAS1_VALID) |\
+ (((iprot) << 30) & MAS1_IPROT) |\
+ (MAS1_TID(tid)) |\
+ (((ts) << 12) & MAS1_TS) |\
+ (MAS1_TSIZE(tsize)))
+#define FSL_BOOKE_MAS2(epn, wimge) \
+ (((epn) & MAS3_RPN) | (wimge))
+#define FSL_BOOKE_MAS3(rpn, user, perms) \
+ (((rpn) & MAS3_RPN) | (user) | (perms))
+#define FSL_BOOKE_MAS7(rpn) \
+ (((u64)(rpn)) >> 32)
+
+#define BOOKE_PAGESZ_1K 0
+#define BOOKE_PAGESZ_2K 1
+#define BOOKE_PAGESZ_4K 2
+#define BOOKE_PAGESZ_8K 3
+#define BOOKE_PAGESZ_16K 4
+#define BOOKE_PAGESZ_32K 5
+#define BOOKE_PAGESZ_64K 6
+#define BOOKE_PAGESZ_128K 7
+#define BOOKE_PAGESZ_256K 8
+#define BOOKE_PAGESZ_512K 9
+#define BOOKE_PAGESZ_1M 10
+#define BOOKE_PAGESZ_2M 11
+#define BOOKE_PAGESZ_4M 12
+#define BOOKE_PAGESZ_8M 13
+#define BOOKE_PAGESZ_16M 14
+#define BOOKE_PAGESZ_32M 15
+#define BOOKE_PAGESZ_64M 16
+#define BOOKE_PAGESZ_128M 17
+#define BOOKE_PAGESZ_256M 18
+#define BOOKE_PAGESZ_512M 19
+#define BOOKE_PAGESZ_1G 20
+#define BOOKE_PAGESZ_2G 21
+#define BOOKE_PAGESZ_4G 22
+
+#define TLBIVAX_ALL 4
+#define TLBIVAX_TLB0 0
+
+#if defined(CONFIG_MPC86xx)
+#define LAWBAR_BASE_ADDR 0x00FFFFFF
+#define LAWAR_TRGT_IF 0x01F00000
+#else
+#define LAWBAR_BASE_ADDR 0x000FFFFF
+#define LAWAR_TRGT_IF 0x00F00000
+#endif
+#define LAWAR_EN 0x80000000
+#define LAWAR_SIZE 0x0000003F
+
+#define LAWAR_TRGT_IF_PCI 0x00000000
+#define LAWAR_TRGT_IF_PCI1 0x00000000
+#define LAWAR_TRGT_IF_PCIX 0x00000000
+#define LAWAR_TRGT_IF_PCI2 0x00100000
+#define LAWAR_TRGT_IF_LBC 0x00400000
+#define LAWAR_TRGT_IF_CCSR 0x00800000
+#define LAWAR_TRGT_IF_DDR_INTERLEAVED 0x00B00000
+#define LAWAR_TRGT_IF_RIO 0x00c00000
+#define LAWAR_TRGT_IF_DDR 0x00f00000
+#define LAWAR_TRGT_IF_DDR1 0x00f00000
+#define LAWAR_TRGT_IF_DDR2 0x01600000
+
+#define LAWAR_SIZE_BASE 0xa
+#define LAWAR_SIZE_4K (LAWAR_SIZE_BASE+1)
+#define LAWAR_SIZE_8K (LAWAR_SIZE_BASE+2)
+#define LAWAR_SIZE_16K (LAWAR_SIZE_BASE+3)
+#define LAWAR_SIZE_32K (LAWAR_SIZE_BASE+4)
+#define LAWAR_SIZE_64K (LAWAR_SIZE_BASE+5)
+#define LAWAR_SIZE_128K (LAWAR_SIZE_BASE+6)
+#define LAWAR_SIZE_256K (LAWAR_SIZE_BASE+7)
+#define LAWAR_SIZE_512K (LAWAR_SIZE_BASE+8)
+#define LAWAR_SIZE_1M (LAWAR_SIZE_BASE+9)
+#define LAWAR_SIZE_2M (LAWAR_SIZE_BASE+10)
+#define LAWAR_SIZE_4M (LAWAR_SIZE_BASE+11)
+#define LAWAR_SIZE_8M (LAWAR_SIZE_BASE+12)
+#define LAWAR_SIZE_16M (LAWAR_SIZE_BASE+13)
+#define LAWAR_SIZE_32M (LAWAR_SIZE_BASE+14)
+#define LAWAR_SIZE_64M (LAWAR_SIZE_BASE+15)
+#define LAWAR_SIZE_128M (LAWAR_SIZE_BASE+16)
+#define LAWAR_SIZE_256M (LAWAR_SIZE_BASE+17)
+#define LAWAR_SIZE_512M (LAWAR_SIZE_BASE+18)
+#define LAWAR_SIZE_1G (LAWAR_SIZE_BASE+19)
+#define LAWAR_SIZE_2G (LAWAR_SIZE_BASE+20)
+#define LAWAR_SIZE_4G (LAWAR_SIZE_BASE+21)
+#define LAWAR_SIZE_8G (LAWAR_SIZE_BASE+22)
+#define LAWAR_SIZE_16G (LAWAR_SIZE_BASE+23)
+#define LAWAR_SIZE_32G (LAWAR_SIZE_BASE+24)
+
+#ifdef CONFIG_440SPE
+/*----------------------------------------------------------------------------+
+| Following instructions are not available in Book E mode of the GNU assembler.
++----------------------------------------------------------------------------*/
+#define DCCCI(ra,rb) .long 0x7c000000|\
+ (ra<<16)|(rb<<11)|(454<<1)
+
+#define ICCCI(ra,rb) .long 0x7c000000|\
+ (ra<<16)|(rb<<11)|(966<<1)
+
+#define DCREAD(rt,ra,rb) .long 0x7c000000|\
+ (rt<<21)|(ra<<16)|(rb<<11)|(486<<1)
+
+#define ICREAD(ra,rb) .long 0x7c000000|\
+ (ra<<16)|(rb<<11)|(998<<1)
+
+#define TLBSX(rt,ra,rb) .long 0x7c000000|\
+ (rt<<21)|(ra<<16)|(rb<<11)|(914<<1)
+
+#define TLBWE(rs,ra,ws) .long 0x7c000000|\
+ (rs<<21)|(ra<<16)|(ws<<11)|(978<<1)
+
+#define TLBRE(rt,ra,ws) .long 0x7c000000|\
+ (rt<<21)|(ra<<16)|(ws<<11)|(946<<1)
+
+#define TLBSXDOT(rt,ra,rb) .long 0x7c000001|\
+ (rt<<21)|(ra<<16)|(rb<<11)|(914<<1)
+
+#define MSYNC .long 0x7c000000|\
+ (598<<1)
+
+#define MBAR_INST .long 0x7c000000|\
+ (854<<1)
+
+/*----------------------------------------------------------------------------+
+| Following instruction is not available in PPC405 mode of the GNU assembler.
++----------------------------------------------------------------------------*/
+#define TLBRE(rt,ra,ws) .long 0x7c000000|\
+ (rt<<21)|(ra<<16)|(ws<<11)|(946<<1)
+
+#endif
+
+#ifndef __ASSEMBLY__
+
+#define MAP_ARCH_DEFAULT MAP_CACHED
+
+#ifdef CONFIG_MMU
+#define ARCH_HAS_REMAP
+int arch_remap_range(void *virt_addr, phys_addr_t phys_addr, size_t size, unsigned flags);
+#endif
+
+#endif
+
+#endif /* _PPC_MMU_H_ */
diff --git a/arch/powerpc/include/asm/module.h b/arch/powerpc/include/asm/module.h
new file mode 100644
index 0000000000..e5c10e35da
--- /dev/null
+++ b/arch/powerpc/include/asm/module.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+
+/**/
+struct mod_arch_specific {
+ /* Indices of PLT sections within module. */
+ unsigned int core_plt_section;
+ unsigned int init_plt_section;
+};
+
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Ehdr Elf32_Ehdr
+
+struct ppc_plt_entry {
+ /* 16 byte jump instruction sequence (4 instructions) */
+ unsigned int jump[4];
+};
diff --git a/arch/powerpc/include/asm/pci_io.h b/arch/powerpc/include/asm/pci_io.h
new file mode 100644
index 0000000000..d601a9671e
--- /dev/null
+++ b/arch/powerpc/include/asm/pci_io.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/* originally from linux source (asm-ppc/io.h).
+ * Sanity added by Rob Taylor, Flying Pig Systems, 2000
+ */
+#ifndef _PCI_IO_H_
+#define _PCI_IO_H_
+
+#include "io.h"
+
+
+#define pci_read_le16(addr, dest) \
+ __asm__ __volatile__("lhbrx %0,0,%1" : "=r" (dest) : \
+ "r" (addr), "m" (*addr));
+
+#define pci_write_le16(addr, val) \
+ __asm__ __volatile__("sthbrx %1,0,%2" : "=m" (*addr) : \
+ "r" (val), "r" (addr));
+
+
+#define pci_read_le32(addr, dest) \
+ __asm__ __volatile__("lwbrx %0,0,%1" : "=r" (dest) : \
+ "r" (addr), "m" (*addr));
+
+#define pci_write_le32(addr, val) \
+__asm__ __volatile__("stwbrx %1,0,%2" : "=m" (*addr) : \
+ "r" (val), "r" (addr));
+
+#define pci_readb(addr,b) ((b) = *(volatile u8 *) (addr))
+#define pci_writeb(b,addr) ((*(volatile u8 *) (addr)) = (b))
+
+#if !defined(__BIG_ENDIAN)
+#define pci_readw(addr,b) ((b) = *(volatile u16 *) (addr))
+#define pci_readl(addr,b) ((b) = *(volatile u32 *) (addr))
+#define pci_writew(b,addr) ((*(volatile u16 *) (addr)) = (b))
+#define pci_writel(b,addr) ((*(volatile u32 *) (addr)) = (b))
+#else
+#define pci_readw(addr,b) pci_read_le16((volatile u16 *)(addr),(b))
+#define pci_readl(addr,b) pci_read_le32((volatile u32 *)(addr),(b))
+#define pci_writew(b,addr) pci_write_le16((volatile u16 *)(addr),(b))
+#define pci_writel(b,addr) pci_write_le32((volatile u32 *)(addr),(b))
+#endif
+
+
+#endif /* _PCI_IO_H_ */
diff --git a/arch/powerpc/include/asm/posix_types.h b/arch/powerpc/include/asm/posix_types.h
new file mode 100644
index 0000000000..feaed42471
--- /dev/null
+++ b/arch/powerpc/include/asm/posix_types.h
@@ -0,0 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <asm-generic/posix_types.h>
diff --git a/arch/powerpc/include/asm/ppc_asm.tmpl b/arch/powerpc/include/asm/ppc_asm.tmpl
new file mode 100644
index 0000000000..f4cb84f12c
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc_asm.tmpl
@@ -0,0 +1,207 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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.
+ *
+ */
+
+/*
+ * This file contains all the macros and symbols which define
+ * a PowerPC assembly language environment.
+ */
+#ifndef __PPC_ASM_TMPL__
+#define __PPC_ASM_TMPL__
+
+/*
+ * These definitions simplify the ugly declarations necessary for GOT
+ * definitions.
+ *
+ * Stolen from prepboot/bootldr.h, (C) 1998 Gabriel Paubert, paubert@iram.es
+ *
+ * Uses r14 to access the GOT
+ */
+
+#define START_GOT \
+ .section ".got2","aw"; \
+.LCTOC1 = .+32768
+
+#define END_GOT \
+ .text
+
+#define GET_GOT \
+ bl 1f ; \
+ .text 2 ; \
+0: .long .LCTOC1-1f ; \
+ .text ; \
+1: mflr r14 ; \
+ lwz r0,0b-1b(r14) ; \
+ add r14,r0,r14 ;
+
+#define GOT_ENTRY(NAME) .L_ ## NAME = . - .LCTOC1 ; .long NAME
+
+#define GOT(NAME) .L_ ## NAME (r14)
+
+/* Register names */
+#define r0 0
+#define r1 1
+#define r2 2
+#define r3 3
+#define r4 4
+#define r5 5
+#define r6 6
+#define r7 7
+#define r8 8
+#define r9 9
+#define r10 10
+#define r11 11
+#define r12 12
+#define r13 13
+#define r14 14
+#define r15 15
+#define r16 16
+#define r17 17
+#define r18 18
+#define r19 19
+#define r20 20
+#define r21 21
+#define r22 22
+#define r23 23
+#define r24 24
+#define r25 25
+#define r26 26
+#define r27 27
+#define r28 28
+#define r29 29
+#define r30 30
+#define r31 31
+
+#define curptr r2
+
+#define SYNC \
+ sync; \
+ isync
+
+#if defined(CONFIG_MPC5xxx) || defined(CONFIG_MPC8220)
+
+#define HID0_ICE_BITPOS 16
+#define HID0_DCE_BITPOS 17
+
+#endif
+/*
+ * Macros for storing registers into and loading registers from
+ * exception frames.
+ */
+#define SAVE_GPR(n, base) stw n,GPR0+4*(n)(base)
+#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base)
+#define SAVE_4GPRS(n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base)
+#define SAVE_8GPRS(n, base) SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base)
+#define SAVE_10GPRS(n, base) SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base)
+#define REST_GPR(n, base) lwz n,GPR0+4*(n)(base)
+#define REST_2GPRS(n, base) REST_GPR(n, base); REST_GPR(n+1, base)
+#define REST_4GPRS(n, base) REST_2GPRS(n, base); REST_2GPRS(n+2, base)
+#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base)
+#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base)
+
+/*
+ * GCC sometimes accesses words at negative offsets from the stack
+ * pointer, although the SysV ABI says it shouldn't. To cope with
+ * this, we leave this much untouched space on the stack on exception
+ * entry.
+ */
+#define STACK_UNDERHEAD 64
+
+/*
+ * Exception entry code. This code runs with address translation
+ * turned off, i.e. using physical addresses.
+ * We assume sprg3 has the physical address of the current
+ * task's thread_struct.
+ */
+#define EXCEPTION_PROLOG(reg1, reg2) \
+ mtspr SPRG0,r20; \
+ mtspr SPRG1,r21; \
+ mfcr r20; \
+ subi r21,r1,INT_FRAME_SIZE+STACK_UNDERHEAD; /* alloc exc. frame */\
+ stw r20,_CCR(r21); /* save registers */ \
+ stw r22,GPR22(r21); \
+ stw r23,GPR23(r21); \
+ mfspr r20,SPRG0; \
+ stw r20,GPR20(r21); \
+ mfspr r22,SPRG1; \
+ stw r22,GPR21(r21); \
+ mflr r20; \
+ stw r20,_LINK(r21); \
+ mfctr r22; \
+ stw r22,_CTR(r21); \
+ mfspr r20,XER; \
+ stw r20,_XER(r21); \
+ mfspr r20, DAR_DEAR; \
+ stw r20,_DAR(r21); \
+ mfspr r22,reg1; \
+ mfspr r23,reg2; \
+ stw r0,GPR0(r21); \
+ stw r1,GPR1(r21); \
+ stw r2,GPR2(r21); \
+ stw r1,0(r21); \
+ mr r1,r21; /* set new kernel sp */ \
+ SAVE_4GPRS(3, r21);
+/*
+ * Note: code which follows this uses cr0.eq (set if from kernel),
+ * r21, r22 (SRR0), and r23 (SRR1).
+ */
+
+/*
+ * Exception vectors.
+ *
+ * The data words for `hdlr' and `int_return' are initialized with
+ * OFFSET values only; they must be relocated first before they can
+ * be used!
+ */
+#define COPY_EE(d, s) rlwimi d,s,0,16,16
+#define NOCOPY(d, s)
+#define EXC_XFER_TEMPLATE(label, hdlr, msr, copyee) \
+ bl 1f; \
+1: mflr r20; \
+ lwz r20,(.L_ ## label)-1b+8(r20); \
+ mtlr r20; \
+ li r20,msr; \
+ copyee(r20,r23); \
+ rlwimi r20,r23,0,25,25; \
+ blrl; \
+.L_ ## label : \
+ .long hdlr - _start + _START_OFFSET; \
+ .long int_return - _start + _START_OFFSET; \
+ .long transfer_to_handler - _start + _START_OFFSET
+
+#define STD_EXCEPTION(n, label, hdlr) \
+ . = n; \
+label: \
+ EXCEPTION_PROLOG(SRR0, SRR1); \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ EXC_XFER_TEMPLATE(label, hdlr, MSR_KERNEL, NOCOPY) \
+
+#define CRIT_EXCEPTION(n, label, hdlr) \
+ . = n; \
+label: \
+ EXCEPTION_PROLOG(CSRR0, CSRR1); \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ EXC_XFER_TEMPLATE(label, hdlr, \
+ MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE), NOCOPY) \
+
+#define MCK_EXCEPTION(n, label, hdlr) \
+ . = n; \
+label: \
+ EXCEPTION_PROLOG(MCSRR0, MCSRR1); \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ EXC_XFER_TEMPLATE(label, hdlr, \
+ MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE), NOCOPY) \
+
+#endif /* __PPC_ASM_TMPL__ */
diff --git a/arch/powerpc/include/asm/ppc_defs.h b/arch/powerpc/include/asm/ppc_defs.h
new file mode 100644
index 0000000000..66875fd84b
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc_defs.h
@@ -0,0 +1,84 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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.
+ *
+ */
+
+/*
+ * WARNING! This file is automatically generated - DO NOT EDIT!
+ */
+#define KERNELBASE -1073741824
+#define STATE 0
+#define NEXT_TASK 64
+#define COUNTER 52
+#define PROCESSOR 916
+#define SIGPENDING 8
+#define TSS 576
+#define MM 880
+#define TASK_STRUCT_SIZE 928
+#define KSP 0
+#define PG_TABLES 4
+#define PGD 8
+#define LAST_SYSCALL 20
+#define PT_REGS 12
+#define PF_TRACESYS 32
+#define TASK_FLAGS 4
+#define TSS_FPR0 24
+#define TSS_FPSCR 284
+#define TSS_SMP_FORK_RET 288
+#define TASK_UNION_SIZE 8192
+#define STACK_FRAME_OVERHEAD 16
+#define INT_FRAME_SIZE 192
+#define GPR0 16
+#define GPR1 20
+#define GPR2 24
+#define GPR3 28
+#define GPR4 32
+#define GPR5 36
+#define GPR6 40
+#define GPR7 44
+#define GPR8 48
+#define GPR9 52
+#define GPR10 56
+#define GPR11 60
+#define GPR12 64
+#define GPR13 68
+#define GPR14 72
+#define GPR15 76
+#define GPR16 80
+#define GPR17 84
+#define GPR18 88
+#define GPR19 92
+#define GPR20 96
+#define GPR21 100
+#define GPR22 104
+#define GPR23 108
+#define GPR24 112
+#define GPR25 116
+#define GPR26 120
+#define GPR27 124
+#define GPR28 128
+#define GPR29 132
+#define GPR30 136
+#define GPR31 140
+#define _NIP 144
+#define _MSR 148
+#define _CTR 156
+#define _LINK 160
+#define _CCR 168
+#define _XER 164
+#define _DAR 180
+#define _DSISR 184
+#define ORIG_GPR3 152
+#define RESULT 188
+#define TRAP 176
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
new file mode 100644
index 0000000000..b9b73580c4
--- /dev/null
+++ b/arch/powerpc/include/asm/processor.h
@@ -0,0 +1,1153 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __ASM_PPC_PROCESSOR_H
+#define __ASM_PPC_PROCESSOR_H
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l;})
+
+#include <asm/ptrace.h>
+#include <asm/types.h>
+#include <linux/stringify.h>
+
+/* Machine State Register (MSR) Fields */
+
+#ifdef CONFIG_PPC64BRIDGE
+#define MSR_SF (1<<63)
+#define MSR_ISF (1<<61)
+#endif /* CONFIG_PPC64BRIDGE */
+#define MSR_UCLE (1<<26) /* User-mode cache lock enable (e500) */
+#define MSR_VEC (1<<25) /* Enable AltiVec(74xx) */
+#define MSR_SPE (1<<25) /* Enable SPE(e500) */
+#define MSR_POW (1<<18) /* Enable Power Management */
+#define MSR_WE (1<<18) /* Wait State Enable */
+#define MSR_TGPR (1<<17) /* TLB Update registers in use */
+#define MSR_CE (1<<17) /* Critical Interrupt Enable */
+#define MSR_ILE (1<<16) /* Interrupt Little Endian */
+#define MSR_EE (1<<15) /* External Interrupt Enable */
+#define MSR_PR (1<<14) /* Problem State / Privilege Level */
+#define MSR_FP (1<<13) /* Floating Point enable */
+#define MSR_ME (1<<12) /* Machine Check Enable */
+#define MSR_FE0 (1<<11) /* Floating Exception mode 0 */
+#define MSR_SE (1<<10) /* Single Step */
+#define MSR_DWE (1<<10) /* Debug Wait Enable (4xx) */
+#define MSR_UBLE (1<<10) /* BTB lock enable (e500) */
+#define MSR_BE (1<<9) /* Branch Trace */
+#define MSR_DE (1<<9) /* Debug Exception Enable */
+#define MSR_FE1 (1<<8) /* Floating Exception mode 1 */
+#define MSR_IP (1<<6) /* Exception prefix 0x000/0xFFF */
+#define MSR_IR (1<<5) /* Instruction Relocate */
+#define MSR_IS (1<<5) /* Book E Instruction space */
+#define MSR_DR (1<<4) /* Data Relocate */
+#define MSR_DS (1<<4) /* Book E Data space */
+#define MSR_PE (1<<3) /* Protection Enable */
+#define MSR_PX (1<<2) /* Protection Exclusive Mode */
+#define MSR_PMM (1<<2) /* Performance monitor mark bit (e500) */
+#define MSR_RI (1<<1) /* Recoverable Exception */
+#define MSR_LE (1<<0) /* Little Endian */
+
+#ifdef CONFIG_APUS_FAST_EXCEPT
+#define MSR_ MSR_ME|MSR_IP|MSR_RI
+#else
+#define MSR_ MSR_ME|MSR_RI
+#endif
+#ifndef CONFIG_E500
+#define MSR_KERNEL MSR_|MSR_IR|MSR_DR
+#else
+#define MSR_KERNEL MSR_ME
+#endif
+#define MSR_USER MSR_KERNEL|MSR_PR|MSR_EE
+
+/* Floating Point Status and Control Register (FPSCR) Fields */
+
+#define FPSCR_FX 0x80000000 /* FPU exception summary */
+#define FPSCR_FEX 0x40000000 /* FPU enabled exception summary */
+#define FPSCR_VX 0x20000000 /* Invalid operation summary */
+#define FPSCR_OX 0x10000000 /* Overflow exception summary */
+#define FPSCR_UX 0x08000000 /* Underflow exception summary */
+#define FPSCR_ZX 0x04000000 /* Zero-devide exception summary */
+#define FPSCR_XX 0x02000000 /* Inexact exception summary */
+#define FPSCR_VXSNAN 0x01000000 /* Invalid op for SNaN */
+#define FPSCR_VXISI 0x00800000 /* Invalid op for Inv - Inv */
+#define FPSCR_VXIDI 0x00400000 /* Invalid op for Inv / Inv */
+#define FPSCR_VXZDZ 0x00200000 /* Invalid op for Zero / Zero */
+#define FPSCR_VXIMZ 0x00100000 /* Invalid op for Inv * Zero */
+#define FPSCR_VXVC 0x00080000 /* Invalid op for Compare */
+#define FPSCR_FR 0x00040000 /* Fraction rounded */
+#define FPSCR_FI 0x00020000 /* Fraction inexact */
+#define FPSCR_FPRF 0x0001f000 /* FPU Result Flags */
+#define FPSCR_FPCC 0x0000f000 /* FPU Condition Codes */
+#define FPSCR_VXSOFT 0x00000400 /* Invalid op for software request */
+#define FPSCR_VXSQRT 0x00000200 /* Invalid op for square root */
+#define FPSCR_VXCVI 0x00000100 /* Invalid op for integer convert */
+#define FPSCR_VE 0x00000080 /* Invalid op exception enable */
+#define FPSCR_OE 0x00000040 /* IEEE overflow exception enable */
+#define FPSCR_UE 0x00000020 /* IEEE underflow exception enable */
+#define FPSCR_ZE 0x00000010 /* IEEE zero divide exception enable */
+#define FPSCR_XE 0x00000008 /* FP inexact exception enable */
+#define FPSCR_NI 0x00000004 /* FPU non IEEE-Mode */
+#define FPSCR_RN 0x00000003 /* FPU rounding control */
+
+/* Special Purpose Registers (SPRNs)*/
+
+#define SPRN_CDBCR 0x3D7 /* Cache Debug Control Register */
+#define SPRN_CTR 0x009 /* Count Register */
+#define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */
+#ifndef CONFIG_BOOKE
+#define SPRN_DAC1 0x3F6 /* Data Address Compare 1 */
+#define SPRN_DAC2 0x3F7 /* Data Address Compare 2 */
+#else
+#define SPRN_DAC1 0x13C /* Book E Data Address Compare 1 */
+#define SPRN_DAC2 0x13D /* Book E Data Address Compare 2 */
+#endif /* CONFIG_BOOKE */
+#define SPRN_DAR 0x013 /* Data Address Register */
+#define SPRN_DBAT0L 0x219 /* Data BAT 0 Lower Register */
+#define SPRN_DBAT0U 0x218 /* Data BAT 0 Upper Register */
+#define SPRN_DBAT1L 0x21B /* Data BAT 1 Lower Register */
+#define SPRN_DBAT1U 0x21A /* Data BAT 1 Upper Register */
+#define SPRN_DBAT2L 0x21D /* Data BAT 2 Lower Register */
+#define SPRN_DBAT2U 0x21C /* Data BAT 2 Upper Register */
+#define SPRN_DBAT3L 0x21F /* Data BAT 3 Lower Register */
+#define SPRN_DBAT3U 0x21E /* Data BAT 3 Upper Register */
+#define SPRN_DBAT4L 0x239 /* Data BAT 4 Lower Register */
+#define SPRN_DBAT4U 0x238 /* Data BAT 4 Upper Register */
+#define SPRN_DBAT5L 0x23B /* Data BAT 5 Lower Register */
+#define SPRN_DBAT5U 0x23A /* Data BAT 5 Upper Register */
+#define SPRN_DBAT6L 0x23D /* Data BAT 6 Lower Register */
+#define SPRN_DBAT6U 0x23C /* Data BAT 6 Upper Register */
+#define SPRN_DBAT7L 0x23F /* Data BAT 7 Lower Register */
+#define SPRN_DBAT7U 0x23E /* Data BAT 7 Lower Register */
+#define SPRN_DBCR 0x3F2 /* Debug Control Regsiter */
+#define DBCR_EDM 0x80000000
+#define DBCR_IDM 0x40000000
+#define DBCR_RST(x) (((x) & 0x3) << 28)
+#define DBCR_RST_NONE 0
+#define DBCR_RST_CORE 1
+#define DBCR_RST_CHIP 2
+#define DBCR_RST_SYSTEM 3
+#define DBCR_IC 0x08000000 /* Instruction Completion Debug Evnt */
+#define DBCR_BT 0x04000000 /* Branch Taken Debug Event */
+#define DBCR_EDE 0x02000000 /* Exception Debug Event */
+#define DBCR_TDE 0x01000000 /* TRAP Debug Event */
+#define DBCR_FER 0x00F80000 /* First Events Remaining Mask */
+#define DBCR_FT 0x00040000 /* Freeze Timers on Debug Event */
+#define DBCR_IA1 0x00020000 /* Instr. Addr. Compare 1 Enable */
+#define DBCR_IA2 0x00010000 /* Instr. Addr. Compare 2 Enable */
+#define DBCR_D1R 0x00008000 /* Data Addr. Compare 1 Read Enable */
+#define DBCR_D1W 0x00004000 /* Data Addr. Compare 1 Write Enable */
+#define DBCR_D1S(x) (((x) & 0x3) << 12) /* Data Adrr. Compare 1 Size */
+#define DAC_BYTE 0
+#define DAC_HALF 1
+#define DAC_WORD 2
+#define DAC_QUAD 3
+#define DBCR_D2R 0x00000800 /* Data Addr. Compare 2 Read Enable */
+#define DBCR_D2W 0x00000400 /* Data Addr. Compare 2 Write Enable */
+#define DBCR_D2S(x) (((x) & 0x3) << 8) /* Data Addr. Compare 2 Size */
+#define DBCR_SBT 0x00000040 /* Second Branch Taken Debug Event */
+#define DBCR_SED 0x00000020 /* Second Exception Debug Event */
+#define DBCR_STD 0x00000010 /* Second Trap Debug Event */
+#define DBCR_SIA 0x00000008 /* Second IAC Enable */
+#define DBCR_SDA 0x00000004 /* Second DAC Enable */
+#define DBCR_JOI 0x00000002 /* JTAG Serial Outbound Int. Enable */
+#define DBCR_JII 0x00000001 /* JTAG Serial Inbound Int. Enable */
+#ifndef CONFIG_BOOKE
+#define SPRN_DBCR0 0x3F2 /* Debug Control Register 0 */
+#else
+#define SPRN_DBCR0 0x134 /* Book E Debug Control Register 0 */
+#endif /* CONFIG_BOOKE */
+#ifndef CONFIG_BOOKE
+#define SPRN_DBCR1 0x3BD /* Debug Control Register 1 */
+#define SPRN_DBSR 0x3F0 /* Debug Status Register */
+#else
+#define SPRN_DBCR1 0x135 /* Book E Debug Control Register 1 */
+#define SPRN_DBSR 0x130 /* Book E Debug Status Register */
+#define DBSR_IC 0x08000000 /* Book E Instruction Completion */
+#define DBSR_TIE 0x01000000 /* Book E Trap Instruction Event */
+#endif /* CONFIG_BOOKE */
+#define SPRN_DCCR 0x3FA /* Data Cache Cacheability Register */
+#define DCCR_NOCACHE 0 /* Noncacheable */
+#define DCCR_CACHE 1 /* Cacheable */
+#define SPRN_DCMP 0x3D1 /* Data TLB Compare Register */
+#define SPRN_DCWR 0x3BA /* Data Cache Write-thru Register */
+#define DCWR_COPY 0 /* Copy-back */
+#define DCWR_WRITE 1 /* Write-through */
+#ifndef CONFIG_BOOKE
+#define SPRN_DEAR 0x3D5 /* Data Error Address Register */
+#else
+#define SPRN_DEAR 0x03D /* Book E Data Error Address Register */
+#endif /* CONFIG_BOOKE */
+#define SPRN_DEC 0x016 /* Decrement Register */
+#define SPRN_DMISS 0x3D0 /* Data TLB Miss Register */
+#define SPRN_DSISR 0x012 /* Data Storage Interrupt Status Register */
+#define SPRN_EAR 0x11A /* External Address Register */
+#ifndef CONFIG_BOOKE
+#define SPRN_ESR 0x3D4 /* Exception Syndrome Register */
+#else
+#define SPRN_ESR 0x03E /* Book E Exception Syndrome Register */
+#endif /* CONFIG_BOOKE */
+#define ESR_IMCP 0x80000000 /* Instr. Machine Check - Protection */
+#define ESR_IMCN 0x40000000 /* Instr. Machine Check - Non-config */
+#define ESR_IMCB 0x20000000 /* Instr. Machine Check - Bus error */
+#define ESR_IMCT 0x10000000 /* Instr. Machine Check - Timeout */
+#define ESR_PIL 0x08000000 /* Program Exception - Illegal */
+#define ESR_PPR 0x04000000 /* Program Exception - Priveleged */
+#define ESR_PTR 0x02000000 /* Program Exception - Trap */
+#define ESR_DST 0x00800000 /* Storage Exception - Data miss */
+#define ESR_DIZ 0x00400000 /* Storage Exception - Zone fault */
+#define SPRN_EVPR 0x3D6 /* Exception Vector Prefix Register */
+#define SPRN_HASH1 0x3D2 /* Primary Hash Address Register */
+#define SPRN_HASH2 0x3D3 /* Secondary Hash Address Resgister */
+#define SPRN_HID0 0x3F0 /* Hardware Implementation Register 0 */
+
+#define HID0_ICE_SHIFT 15
+#define HID0_DCE_SHIFT 14
+#define HID0_DLOCK_SHIFT 12
+
+#define HID0_EMCP (1<<31) /* Enable Machine Check pin */
+#define HID0_EBA (1<<29) /* Enable Bus Address Parity */
+#define HID0_EBD (1<<28) /* Enable Bus Data Parity */
+#define HID0_SBCLK (1<<27)
+#define HID0_EICE (1<<26)
+#define HID0_ECLK (1<<25)
+#define HID0_PAR (1<<24)
+#define HID0_DOZE (1<<23)
+#define HID0_NAP (1<<22)
+#define HID0_SLEEP (1<<21)
+#define HID0_DPM (1<<20)
+#define HID0_ICE (1<<HID0_ICE_SHIFT) /* Instruction Cache Enable */
+#define HID0_DCE (1<<HID0_DCE_SHIFT) /* Data Cache Enable */
+#define HID0_TBEN (1<<14) /* Time Base Enable */
+#define HID0_ILOCK (1<<13) /* Instruction Cache Lock */
+#define HID0_DLOCK (1<<HID0_DLOCK_SHIFT) /* Data Cache Lock */
+#define HID0_ICFI (1<<11) /* Instr. Cache Flash Invalidate */
+#define HID0_DCFI (1<<10) /* Data Cache Flash Invalidate */
+#define HID0_DCI HID0_DCFI
+#define HID0_SPD (1<<9) /* Speculative disable */
+#define HID0_SGE (1<<7) /* Store Gathering Enable */
+#define HID0_SIED HID_SGE /* Serial Instr. Execution [Disable] */
+#define HID0_DCFA (1<<6) /* Data Cache Flush Assist */
+#define HID0_BTIC (1<<5) /* Branch Target Instruction Cache Enable */
+#define HID0_ABE (1<<3) /* Address Broadcast Enable */
+#define HID0_BHTE (1<<2) /* Branch History Table Enable */
+#define HID0_BTCD (1<<1) /* Branch target cache disable */
+#define SPRN_HID1 0x3F1 /* Hardware Implementation Register 1 */
+#define HID1_RFXE (1<<17) /* Read Fault Exception Enable */
+#define HID1_ASTME (1<<13) /* Address bus streaming mode */
+#define HID1_ABE (1<<12) /* Address broadcast enable */
+#define HID1_MBDD (1<<6) /* optimized sync instruction */
+#define SPRN_IABR 0x3F2 /* Instruction Address Breakpoint Register */
+#ifndef CONFIG_BOOKE
+#define SPRN_IAC1 0x3F4 /* Instruction Address Compare 1 */
+#define SPRN_IAC2 0x3F5 /* Instruction Address Compare 2 */
+#else
+#define SPRN_IAC1 0x138 /* Book E Instruction Address Compare 1 */
+#define SPRN_IAC2 0x139 /* Book E Instruction Address Compare 2 */
+#endif /* CONFIG_BOOKE */
+#define SPRN_IBAT0L 0x211 /* Instruction BAT 0 Lower Register */
+#define SPRN_IBAT0U 0x210 /* Instruction BAT 0 Upper Register */
+#define SPRN_IBAT1L 0x213 /* Instruction BAT 1 Lower Register */
+#define SPRN_IBAT1U 0x212 /* Instruction BAT 1 Upper Register */
+#define SPRN_IBAT2L 0x215 /* Instruction BAT 2 Lower Register */
+#define SPRN_IBAT2U 0x214 /* Instruction BAT 2 Upper Register */
+#define SPRN_IBAT3L 0x217 /* Instruction BAT 3 Lower Register */
+#define SPRN_IBAT3U 0x216 /* Instruction BAT 3 Upper Register */
+#define SPRN_IBAT4L 0x231 /* Instruction BAT 4 Lower Register */
+#define SPRN_IBAT4U 0x230 /* Instruction BAT 4 Upper Register */
+#define SPRN_IBAT5L 0x233 /* Instruction BAT 5 Lower Register */
+#define SPRN_IBAT5U 0x232 /* Instruction BAT 5 Upper Register */
+#define SPRN_IBAT6L 0x235 /* Instruction BAT 6 Lower Register */
+#define SPRN_IBAT6U 0x234 /* Instruction BAT 6 Upper Register */
+#define SPRN_IBAT7L 0x237 /* Instruction BAT 7 Lower Register */
+#define SPRN_IBAT7U 0x236 /* Instruction BAT 7 Upper Register */
+#define SPRN_ICCR 0x3FB /* Instruction Cache Cacheability Register */
+#define ICCR_NOCACHE 0 /* Noncacheable */
+#define ICCR_CACHE 1 /* Cacheable */
+#define SPRN_ICDBDR 0x3D3 /* Instruction Cache Debug Data Register */
+#define SPRN_ICMP 0x3D5 /* Instruction TLB Compare Register */
+#define SPRN_ICTC 0x3FB /* Instruction Cache Throttling Control Reg */
+#define SPRN_IMISS 0x3D4 /* Instruction TLB Miss Register */
+#define SPRN_IMMR 0x27E /* Internal Memory Map Register */
+#define SPRN_LDSTCR 0x3F8 /* Load/Store Control Register */
+#define SPRN_L2CR 0x3F9 /* Level 2 Cache Control Regsiter */
+#define SPRN_LR 0x008 /* Link Register */
+#define SPRN_MBAR 0x137 /* System memory base address */
+#define SPRN_MMCR0 0x3B8 /* Monitor Mode Control Register 0 */
+#define SPRN_MMCR1 0x3BC /* Monitor Mode Control Register 1 */
+#define SPRN_PBL1 0x3FC /* Protection Bound Lower 1 */
+#define SPRN_PBL2 0x3FE /* Protection Bound Lower 2 */
+#define SPRN_PBU1 0x3FD /* Protection Bound Upper 1 */
+#define SPRN_PBU2 0x3FF /* Protection Bound Upper 2 */
+#ifndef CONFIG_BOOKE
+#define SPRN_PID 0x3B1 /* Process ID */
+#define SPRN_PIR 0x3FF /* Processor Identification Register */
+#else
+#define SPRN_PID 0x030 /* Book E Process ID */
+#define SPRN_PIR 0x11E /* Book E Processor Identification Register */
+#endif /* CONFIG_BOOKE */
+#define SPRN_PIT 0x3DB /* Programmable Interval Timer */
+#define SPRN_PMC1 0x3B9 /* Performance Counter Register 1 */
+#define SPRN_PMC2 0x3BA /* Performance Counter Register 2 */
+#define SPRN_PMC3 0x3BD /* Performance Counter Register 3 */
+#define SPRN_PMC4 0x3BE /* Performance Counter Register 4 */
+#define SPRN_PVR 0x11F /* Processor Version Register */
+#define SPRN_RPA 0x3D6 /* Required Physical Address Register */
+#define SPRN_SDA 0x3BF /* Sampled Data Address Register */
+#define SPRN_SDR1 0x019 /* MMU Hash Base Register */
+#define SPRN_SGR 0x3B9 /* Storage Guarded Register */
+#define SGR_NORMAL 0
+#define SGR_GUARDED 1
+#define SPRN_SIA 0x3BB /* Sampled Instruction Address Register */
+#define SPRN_SPRG0 0x110 /* Special Purpose Register General 0 */
+#define SPRN_SPRG1 0x111 /* Special Purpose Register General 1 */
+#define SPRN_SPRG2 0x112 /* Special Purpose Register General 2 */
+#define SPRN_SPRG3 0x113 /* Special Purpose Register General 3 */
+#define SPRN_SRR0 0x01A /* Save/Restore Register 0 */
+#define SPRN_SRR1 0x01B /* Save/Restore Register 1 */
+#define SPRN_SRR2 0x3DE /* Save/Restore Register 2 */
+#define SPRN_SRR3 0x3DF /* Save/Restore Register 3 */
+#ifdef CONFIG_BOOKE
+#define SPRN_SVR 0x3FF /* System Version Register */
+#else
+#define SPRN_SVR 0x11E /* System Version Register */
+#endif
+#define SPRN_TBHI 0x3DC /* Time Base High */
+#define SPRN_TBHU 0x3CC /* Time Base High User-mode */
+#define SPRN_TBLO 0x3DD /* Time Base Low */
+#define SPRN_TBLU 0x3CD /* Time Base Low User-mode */
+#define SPRN_TBRL 0x10C /* Time Base Read Lower Register */
+#define SPRN_TBRU 0x10D /* Time Base Read Upper Register */
+#define SPRN_TBWL 0x11C /* Time Base Write Lower Register */
+#define SPRN_TBWU 0x11D /* Time Base Write Upper Register */
+#ifndef CONFIG_BOOKE
+#define SPRN_TCR 0x3DA /* Timer Control Register */
+#else
+#define SPRN_TCR 0x154 /* Book E Timer Control Register */
+#endif /* CONFIG_BOOKE */
+#define TCR_WP(x) (((x)&0x3)<<30) /* WDT Period */
+#define WP_2_17 0 /* 2^17 clocks */
+#define WP_2_21 1 /* 2^21 clocks */
+#define WP_2_25 2 /* 2^25 clocks */
+#define WP_2_29 3 /* 2^29 clocks */
+#define TCR_WRC(x) (((x)&0x3)<<28) /* WDT Reset Control */
+#define WRC_NONE 0 /* No reset will occur */
+#define WRC_CORE 1 /* Core reset will occur */
+#define WRC_CHIP 2 /* Chip reset will occur */
+#define WRC_SYSTEM 3 /* System reset will occur */
+#define TCR_WIE 0x08000000 /* WDT Interrupt Enable */
+#define TCR_PIE 0x04000000 /* PIT Interrupt Enable */
+#define TCR_FP(x) (((x)&0x3)<<24) /* FIT Period */
+#define FP_2_9 0 /* 2^9 clocks */
+#define FP_2_13 1 /* 2^13 clocks */
+#define FP_2_17 2 /* 2^17 clocks */
+#define FP_2_21 3 /* 2^21 clocks */
+#define TCR_FIE 0x00800000 /* FIT Interrupt Enable */
+#define TCR_ARE 0x00400000 /* Auto Reload Enable */
+#define SPRN_THRM1 0x3FC /* Thermal Management Register 1 */
+#define THRM1_TIN (1<<0)
+#define THRM1_TIV (1<<1)
+#define THRM1_THRES (0x7f<<2)
+#define THRM1_TID (1<<29)
+#define THRM1_TIE (1<<30)
+#define THRM1_V (1<<31)
+#define SPRN_THRM2 0x3FD /* Thermal Management Register 2 */
+#define SPRN_THRM3 0x3FE /* Thermal Management Register 3 */
+#define THRM3_E (1<<31)
+#define SPRN_TLBMISS 0x3D4 /* 980 7450 TLB Miss Register */
+#ifndef CONFIG_BOOKE
+#define SPRN_TSR 0x3D8 /* Timer Status Register */
+#else
+#define SPRN_TSR 0x150 /* Book E Timer Status Register */
+#endif /* CONFIG_BOOKE */
+#define TSR_ENW 0x80000000 /* Enable Next Watchdog */
+#define TSR_WIS 0x40000000 /* WDT Interrupt Status */
+#define TSR_WRS(x) (((x)&0x3)<<28) /* WDT Reset Status */
+#define WRS_NONE 0 /* No WDT reset occurred */
+#define WRS_CORE 1 /* WDT forced core reset */
+#define WRS_CHIP 2 /* WDT forced chip reset */
+#define WRS_SYSTEM 3 /* WDT forced system reset */
+#define TSR_PIS 0x08000000 /* PIT Interrupt Status */
+#define TSR_FIS 0x04000000 /* FIT Interrupt Status */
+#define SPRN_UMMCR0 0x3A8 /* User Monitor Mode Control Register 0 */
+#define SPRN_UMMCR1 0x3AC /* User Monitor Mode Control Register 0 */
+#define SPRN_UPMC1 0x3A9 /* User Performance Counter Register 1 */
+#define SPRN_UPMC2 0x3AA /* User Performance Counter Register 2 */
+#define SPRN_UPMC3 0x3AD /* User Performance Counter Register 3 */
+#define SPRN_UPMC4 0x3AE /* User Performance Counter Register 4 */
+#define SPRN_USIA 0x3AB /* User Sampled Instruction Address Register */
+#define SPRN_XER 0x001 /* Fixed Point Exception Register */
+#define SPRN_ZPR 0x3B0 /* Zone Protection Register */
+
+/* Book E definitions */
+#define SPRN_DECAR 0x036 /* Decrementer Auto Reload Register */
+#define SPRN_CSRR0 0x03A /* Critical SRR0 */
+#define SPRN_CSRR1 0x03B /* Critical SRR0 */
+#define SPRN_IVPR 0x03F /* Interrupt Vector Prefix Register */
+#define SPRN_USPRG0 0x100 /* User Special Purpose Register General 0 */
+#define SPRN_SPRG4R 0x104 /* Special Purpose Register General 4 Read */
+#define SPRN_SPRG5R 0x105 /* Special Purpose Register General 5 Read */
+#define SPRN_SPRG6R 0x106 /* Special Purpose Register General 6 Read */
+#define SPRN_SPRG7R 0x107 /* Special Purpose Register General 7 Read */
+#define SPRN_SPRG4W 0x114 /* Special Purpose Register General 4 Write */
+#define SPRN_SPRG5W 0x115 /* Special Purpose Register General 5 Write */
+#define SPRN_SPRG6W 0x116 /* Special Purpose Register General 6 Write */
+#define SPRN_SPRG7W 0x117 /* Special Purpose Register General 7 Write */
+#define SPRN_DBCR2 0x136 /* Debug Control Register 2 */
+#define SPRN_IAC3 0x13A /* Instruction Address Compare 3 */
+#define SPRN_IAC4 0x13B /* Instruction Address Compare 4 */
+#define SPRN_DVC1 0x13E /* Data Value Compare Register 1 */
+#define SPRN_DVC2 0x13F /* Data Value Compare Register 2 */
+#define SPRN_IVOR0 0x190 /* Interrupt Vector Offset Register 0 */
+#define SPRN_IVOR1 0x191 /* Interrupt Vector Offset Register 1 */
+#define SPRN_IVOR2 0x192 /* Interrupt Vector Offset Register 2 */
+#define SPRN_IVOR3 0x193 /* Interrupt Vector Offset Register 3 */
+#define SPRN_IVOR4 0x194 /* Interrupt Vector Offset Register 4 */
+#define SPRN_IVOR5 0x195 /* Interrupt Vector Offset Register 5 */
+#define SPRN_IVOR6 0x196 /* Interrupt Vector Offset Register 6 */
+#define SPRN_IVOR7 0x197 /* Interrupt Vector Offset Register 7 */
+#define SPRN_IVOR8 0x198 /* Interrupt Vector Offset Register 8 */
+#define SPRN_IVOR9 0x199 /* Interrupt Vector Offset Register 9 */
+#define SPRN_IVOR10 0x19a /* Interrupt Vector Offset Register 10 */
+#define SPRN_IVOR11 0x19b /* Interrupt Vector Offset Register 11 */
+#define SPRN_IVOR12 0x19c /* Interrupt Vector Offset Register 12 */
+#define SPRN_IVOR13 0x19d /* Interrupt Vector Offset Register 13 */
+#define SPRN_IVOR14 0x19e /* Interrupt Vector Offset Register 14 */
+#define SPRN_IVOR15 0x19f /* Interrupt Vector Offset Register 15 */
+
+/* e500 definitions */
+#define SPRN_L1CFG0 0x203 /* L1 Cache Configuration Register 0 */
+#define SPRN_L1CSR0 0x3f2 /* L1 Cache Control and Status Register 0 */
+#define L1CSR0_CPE 0x00010000 /* Data Cache Parity Enable */
+#define L1CSR0_DCLFR 0x00000100 /* D-Cache Lock Flash Reset */
+#define L1CSR0_DCFI 0x00000002 /* Data Cache Flash Invalidate */
+#define L1CSR0_DCE 0x00000001 /* Data Cache Enable */
+#define SPRN_L1CSR1 0x3f3 /* L1 Cache Control and Status Register 1 */
+#define L1CSR1_CPE 0x00010000 /* I-Cache Parity Enable */
+#define L1CSR1_ICLFR 0x00000100 /* I-Cache Lock Flash Reset */
+#define L1CSR1_ICFI 0x00000002 /* Instruction Cache Flash Invalidate */
+#define L1CSR1_ICE 0x00000001 /* Instruction Cache Enable */
+
+#define SPRN_TLB0CFG 0x2B0 /* TLB 0 Config Register */
+#define SPRN_TLB1CFG 0x2B1 /* TLB 1 Config Register */
+#define SPRN_TLB1PS 0x159 /* TLB 1 Page Size Register */
+#define TLBnCFG_NENTRY_MASK 0x00000fff
+#define SPRN_MMUCSR0 0x3f4 /* MMU control and status register 0 */
+#define SPRN_MMUCFG 0x3f7 /* MMU Configuration Register */
+#define MMUCFG_MAVN 0x00000003 /* MMU Architecture Version Number */
+#define MMUCFG_MAVN_V1 0x00000000 /* v1.0 */
+#define MMUCFG_MAVN_V2 0x00000001 /* v2.0 */
+#define SPRN_MAS0 0x270 /* MMU Assist Register 0 */
+#define SPRN_MAS1 0x271 /* MMU Assist Register 1 */
+#define SPRN_MAS2 0x272 /* MMU Assist Register 2 */
+#define SPRN_MAS3 0x273 /* MMU Assist Register 3 */
+#define SPRN_MAS4 0x274 /* MMU Assist Register 4 */
+#define SPRN_MAS5 0x275 /* MMU Assist Register 5 */
+#define SPRN_MAS6 0x276 /* MMU Assist Register 6 */
+#define SPRN_MAS7 0x3B0 /* MMU Assist Register 7 */
+
+#define SPRN_IVOR32 0x210 /* Interrupt Vector Offset Register 32 */
+#define SPRN_IVOR33 0x211 /* Interrupt Vector Offset Register 33 */
+#define SPRN_IVOR34 0x212 /* Interrupt Vector Offset Register 34 */
+#define SPRN_IVOR35 0x213 /* Interrupt Vector Offset Register 35 */
+#define SPRN_SPEFSCR 0x200 /* SPE & Embedded FP Status & Control */
+
+#define SPRN_MCSRR0 0x23a /* Machine Check Save and Restore Register 0 */
+#define SPRN_MCSRR1 0x23b /* Machine Check Save and Restore Register 1 */
+#define SPRN_BUCSR 0x3f5 /* Branch Control and Status Register */
+#define BUCSR_STAC_EN 0x01000000 /* Segment target addr cache enable */
+#define BUCSR_LS_EN 0x00400000 /* Link stack enable */
+#define BUCSR_BBFI 0x00000200 /* Branch buffer flash invalidate */
+#define BUCSR_BPEN 0x00000001 /* Branch prediction enable */
+#define BUCSR_ENABLE (BUCSR_STAC_EN|BUCSR_LS_EN|BUCSR_BBFI|BUCSR_BPEN)
+#define SPRN_BBEAR 0x201 /* Branch Buffer Entry Address Register */
+#define SPRN_BBTAR 0x202 /* Branch Buffer Target Address Register */
+#define SPRN_PID1 0x279 /* Process ID Register 1 */
+#define SPRN_PID2 0x27a /* Process ID Register 2 */
+#define SPRN_MCSR 0x23c /* Machine Check Syndrome register */
+#define SPRN_MCAR 0x23d /* Machine Check Address register */
+#define ESR_ST 0x00800000 /* Store Operation */
+
+#if defined(CONFIG_MPC86xx)
+#define SPRN_MSSCRO 0x3f6
+#endif
+
+#define SPRN_HDBCR0 0x3d0
+
+/* Short-hand versions for a number of the above SPRNs */
+
+#define CTR SPRN_CTR /* Counter Register */
+#define DAR SPRN_DAR /* Data Address Register */
+#define DABR SPRN_DABR /* Data Address Breakpoint Register */
+#define DAC1 SPRN_DAC1 /* Data Address Register 1 */
+#define DAC2 SPRN_DAC2 /* Data Address Register 2 */
+#define DBAT0L SPRN_DBAT0L /* Data BAT 0 Lower Register */
+#define DBAT0U SPRN_DBAT0U /* Data BAT 0 Upper Register */
+#define DBAT1L SPRN_DBAT1L /* Data BAT 1 Lower Register */
+#define DBAT1U SPRN_DBAT1U /* Data BAT 1 Upper Register */
+#define DBAT2L SPRN_DBAT2L /* Data BAT 2 Lower Register */
+#define DBAT2U SPRN_DBAT2U /* Data BAT 2 Upper Register */
+#define DBAT3L SPRN_DBAT3L /* Data BAT 3 Lower Register */
+#define DBAT3U SPRN_DBAT3U /* Data BAT 3 Upper Register */
+#define DBAT4L SPRN_DBAT4L /* Data BAT 4 Lower Register */
+#define DBAT4U SPRN_DBAT4U /* Data BAT 4 Upper Register */
+#define DBAT5L SPRN_DBAT5L /* Data BAT 5 Lower Register */
+#define DBAT5U SPRN_DBAT5U /* Data BAT 5 Upper Register */
+#define DBAT6L SPRN_DBAT6L /* Data BAT 6 Lower Register */
+#define DBAT6U SPRN_DBAT6U /* Data BAT 6 Upper Register */
+#define DBAT7L SPRN_DBAT7L /* Data BAT 7 Lower Register */
+#define DBAT7U SPRN_DBAT7U /* Data BAT 7 Upper Register */
+#define DBCR0 SPRN_DBCR0 /* Debug Control Register 0 */
+#define DBCR1 SPRN_DBCR1 /* Debug Control Register 1 */
+#define DBSR SPRN_DBSR /* Debug Status Register */
+#define DCMP SPRN_DCMP /* Data TLB Compare Register */
+#define DEC SPRN_DEC /* Decrement Register */
+#define DMISS SPRN_DMISS /* Data TLB Miss Register */
+#define DSISR SPRN_DSISR /* Data Storage Interrupt Status Register */
+#define EAR SPRN_EAR /* External Address Register */
+#define ESR SPRN_ESR /* Exception Syndrome Register */
+#define HASH1 SPRN_HASH1 /* Primary Hash Address Register */
+#define HASH2 SPRN_HASH2 /* Secondary Hash Address Register */
+#define HID0 SPRN_HID0 /* Hardware Implementation Register 0 */
+#define HID1 SPRN_HID1 /* Hardware Implementation Register 1 */
+#define IABR SPRN_IABR /* Instruction Address Breakpoint Register */
+#define IAC1 SPRN_IAC1 /* Instruction Address Register 1 */
+#define IAC2 SPRN_IAC2 /* Instruction Address Register 2 */
+#define IBAT0L SPRN_IBAT0L /* Instruction BAT 0 Lower Register */
+#define IBAT0U SPRN_IBAT0U /* Instruction BAT 0 Upper Register */
+#define IBAT1L SPRN_IBAT1L /* Instruction BAT 1 Lower Register */
+#define IBAT1U SPRN_IBAT1U /* Instruction BAT 1 Upper Register */
+#define IBAT2L SPRN_IBAT2L /* Instruction BAT 2 Lower Register */
+#define IBAT2U SPRN_IBAT2U /* Instruction BAT 2 Upper Register */
+#define IBAT3L SPRN_IBAT3L /* Instruction BAT 3 Lower Register */
+#define IBAT3U SPRN_IBAT3U /* Instruction BAT 3 Upper Register */
+#define IBAT4L SPRN_IBAT4L /* Instruction BAT 4 Lower Register */
+#define IBAT4U SPRN_IBAT4U /* Instruction BAT 4 Upper Register */
+#define IBAT5L SPRN_IBAT5L /* Instruction BAT 5 Lower Register */
+#define IBAT5U SPRN_IBAT5U /* Instruction BAT 5 Upper Register */
+#define IBAT6L SPRN_IBAT6L /* Instruction BAT 6 Lower Register */
+#define IBAT6U SPRN_IBAT6U /* Instruction BAT 6 Upper Register */
+#define IBAT7L SPRN_IBAT7L /* Instruction BAT 7 Lower Register */
+#define IBAT7U SPRN_IBAT7U /* Instruction BAT 7 Lower Register */
+#define ICMP SPRN_ICMP /* Instruction TLB Compare Register */
+#define IMISS SPRN_IMISS /* Instruction TLB Miss Register */
+#define IMMR SPRN_IMMR /* PPC 860/821 Internal Memory Map Register */
+#define LDSTCR SPRN_LDSTCR /* Load/Store Control Register */
+#define L2CR SPRN_L2CR /* PPC 750 L2 control register */
+#define LR SPRN_LR
+#define MBAR SPRN_MBAR /* System memory base address */
+#if defined(CONFIG_MPC86xx)
+#define MSSCR0 SPRN_MSSCRO
+#endif
+#if defined(CONFIG_E500) || defined(CONFIG_MPC86xx)
+#define PIR SPRN_PIR
+#endif
+#define SVR SPRN_SVR /* System-On-Chip Version Register */
+#define PVR SPRN_PVR /* Processor Version */
+#define RPA SPRN_RPA /* Required Physical Address Register */
+#define SDR1 SPRN_SDR1 /* MMU hash base register */
+#define SPR0 SPRN_SPRG0 /* Supervisor Private Registers */
+#define SPR1 SPRN_SPRG1
+#define SPR2 SPRN_SPRG2
+#define SPR3 SPRN_SPRG3
+#define SPRG0 SPRN_SPRG0
+#define SPRG1 SPRN_SPRG1
+#define SPRG2 SPRN_SPRG2
+#define SPRG3 SPRN_SPRG3
+#define SRR0 SPRN_SRR0 /* Save and Restore Register 0 */
+#define SRR1 SPRN_SRR1 /* Save and Restore Register 1 */
+#define SVR SPRN_SVR /* System Version Register */
+#define TBRL SPRN_TBRL /* Time Base Read Lower Register */
+#define TBRU SPRN_TBRU /* Time Base Read Upper Register */
+#define TBWL SPRN_TBWL /* Time Base Write Lower Register */
+#define TBWU SPRN_TBWU /* Time Base Write Upper Register */
+#define TCR SPRN_TCR /* Timer Control Register */
+#define TSR SPRN_TSR /* Timer Status Register */
+#define ICTC 1019
+#define THRM1 SPRN_THRM1 /* Thermal Management Register 1 */
+#define THRM2 SPRN_THRM2 /* Thermal Management Register 2 */
+#define THRM3 SPRN_THRM3 /* Thermal Management Register 3 */
+#define XER SPRN_XER
+
+#define DECAR SPRN_DECAR
+#define CSRR0 SPRN_CSRR0
+#define CSRR1 SPRN_CSRR1
+#define IVPR SPRN_IVPR
+#define USPRG0 SPRN_USPRG0
+#define SPRG4R SPRN_SPRG4R
+#define SPRG5R SPRN_SPRG5R
+#define SPRG6R SPRN_SPRG6R
+#define SPRG7R SPRN_SPRG7R
+#define SPRG4W SPRN_SPRG4W
+#define SPRG5W SPRN_SPRG5W
+#define SPRG6W SPRN_SPRG6W
+#define SPRG7W SPRN_SPRG7W
+#define DEAR SPRN_DEAR
+#define DBCR2 SPRN_DBCR2
+#define IAC3 SPRN_IAC3
+#define IAC4 SPRN_IAC4
+#define DVC1 SPRN_DVC1
+#define DVC2 SPRN_DVC2
+#define IVOR0 SPRN_IVOR0
+#define IVOR1 SPRN_IVOR1
+#define IVOR2 SPRN_IVOR2
+#define IVOR3 SPRN_IVOR3
+#define IVOR4 SPRN_IVOR4
+#define IVOR5 SPRN_IVOR5
+#define IVOR6 SPRN_IVOR6
+#define IVOR7 SPRN_IVOR7
+#define IVOR8 SPRN_IVOR8
+#define IVOR9 SPRN_IVOR9
+#define IVOR10 SPRN_IVOR10
+#define IVOR11 SPRN_IVOR11
+#define IVOR12 SPRN_IVOR12
+#define IVOR13 SPRN_IVOR13
+#define IVOR14 SPRN_IVOR14
+#define IVOR15 SPRN_IVOR15
+#define IVOR32 SPRN_IVOR32
+#define IVOR33 SPRN_IVOR33
+#define IVOR34 SPRN_IVOR34
+#define IVOR35 SPRN_IVOR35
+#define MCSRR0 SPRN_MCSRR0
+#define MCSRR1 SPRN_MCSRR1
+#define L1CSR0 SPRN_L1CSR0
+#define L1CSR1 SPRN_L1CSR1
+#define L1CFG0 SPRN_L1CFG0
+#define MCSR SPRN_MCSR
+#define MMUCSR0 SPRN_MMUCSR0
+#define BUCSR SPRN_BUCSR
+#define PID0 SPRN_PID
+#define PID1 SPRN_PID1
+#define PID2 SPRN_PID2
+#define MAS0 SPRN_MAS0
+#define MAS1 SPRN_MAS1
+#define MAS2 SPRN_MAS2
+#define MAS3 SPRN_MAS3
+#define MAS4 SPRN_MAS4
+#define MAS5 SPRN_MAS5
+#define MAS6 SPRN_MAS6
+#define MAS7 SPRN_MAS7
+#define MAS8 SPRN_MAS8
+
+#if defined(CONFIG_MPC85xx)
+#define DAR_DEAR DEAR
+#else
+#define DAR_DEAR DAR
+#endif
+/* Device Control Registers */
+
+#define DCRN_BEAR 0x090 /* Bus Error Address Register */
+#define DCRN_BESR 0x091 /* Bus Error Syndrome Register */
+#define BESR_DSES 0x80000000 /* Data-Side Error Status */
+#define BESR_DMES 0x40000000 /* DMA Error Status */
+#define BESR_RWS 0x20000000 /* Read/Write Status */
+#define BESR_ETMASK 0x1C000000 /* Error Type */
+#define ET_PROT 0
+#define ET_PARITY 1
+#define ET_NCFG 2
+#define ET_BUSERR 4
+#define ET_BUSTO 6
+#define DCRN_DMACC0 0x0C4 /* DMA Chained Count Register 0 */
+#define DCRN_DMACC1 0x0CC /* DMA Chained Count Register 1 */
+#define DCRN_DMACC2 0x0D4 /* DMA Chained Count Register 2 */
+#define DCRN_DMACC3 0x0DC /* DMA Chained Count Register 3 */
+#define DCRN_DMACR0 0x0C0 /* DMA Channel Control Register 0 */
+#define DCRN_DMACR1 0x0C8 /* DMA Channel Control Register 1 */
+#define DCRN_DMACR2 0x0D0 /* DMA Channel Control Register 2 */
+#define DCRN_DMACR3 0x0D8 /* DMA Channel Control Register 3 */
+#define DCRN_DMACT0 0x0C1 /* DMA Count Register 0 */
+#define DCRN_DMACT1 0x0C9 /* DMA Count Register 1 */
+#define DCRN_DMACT2 0x0D1 /* DMA Count Register 2 */
+#define DCRN_DMACT3 0x0D9 /* DMA Count Register 3 */
+#define DCRN_DMADA0 0x0C2 /* DMA Destination Address Register 0 */
+#define DCRN_DMADA1 0x0CA /* DMA Destination Address Register 1 */
+#define DCRN_DMADA2 0x0D2 /* DMA Destination Address Register 2 */
+#define DCRN_DMADA3 0x0DA /* DMA Destination Address Register 3 */
+#define DCRN_DMASA0 0x0C3 /* DMA Source Address Register 0 */
+#define DCRN_DMASA1 0x0CB /* DMA Source Address Register 1 */
+#define DCRN_DMASA2 0x0D3 /* DMA Source Address Register 2 */
+#define DCRN_DMASA3 0x0DB /* DMA Source Address Register 3 */
+#define DCRN_DMASR 0x0E0 /* DMA Status Register */
+#define DCRN_EXIER 0x042 /* External Interrupt Enable Register */
+#define EXIER_CIE 0x80000000 /* Critical Interrupt Enable */
+#define EXIER_SRIE 0x08000000 /* Serial Port Rx Int. Enable */
+#define EXIER_STIE 0x04000000 /* Serial Port Tx Int. Enable */
+#define EXIER_JRIE 0x02000000 /* JTAG Serial Port Rx Int. Enable */
+#define EXIER_JTIE 0x01000000 /* JTAG Serial Port Tx Int. Enable */
+#define EXIER_D0IE 0x00800000 /* DMA Channel 0 Interrupt Enable */
+#define EXIER_D1IE 0x00400000 /* DMA Channel 1 Interrupt Enable */
+#define EXIER_D2IE 0x00200000 /* DMA Channel 2 Interrupt Enable */
+#define EXIER_D3IE 0x00100000 /* DMA Channel 3 Interrupt Enable */
+#define EXIER_E0IE 0x00000010 /* External Interrupt 0 Enable */
+#define EXIER_E1IE 0x00000008 /* External Interrupt 1 Enable */
+#define EXIER_E2IE 0x00000004 /* External Interrupt 2 Enable */
+#define EXIER_E3IE 0x00000002 /* External Interrupt 3 Enable */
+#define EXIER_E4IE 0x00000001 /* External Interrupt 4 Enable */
+#define DCRN_EXISR 0x040 /* External Interrupt Status Register */
+#define DCRN_IOCR 0x0A0 /* Input/Output Configuration Register */
+#define IOCR_E0TE 0x80000000
+#define IOCR_E0LP 0x40000000
+#define IOCR_E1TE 0x20000000
+#define IOCR_E1LP 0x10000000
+#define IOCR_E2TE 0x08000000
+#define IOCR_E2LP 0x04000000
+#define IOCR_E3TE 0x02000000
+#define IOCR_E3LP 0x01000000
+#define IOCR_E4TE 0x00800000
+#define IOCR_E4LP 0x00400000
+#define IOCR_EDT 0x00080000
+#define IOCR_SOR 0x00040000
+#define IOCR_EDO 0x00008000
+#define IOCR_2XC 0x00004000
+#define IOCR_ATC 0x00002000
+#define IOCR_SPD 0x00001000
+#define IOCR_BEM 0x00000800
+#define IOCR_PTD 0x00000400
+#define IOCR_ARE 0x00000080
+#define IOCR_DRC 0x00000020
+#define IOCR_RDM(x) (((x) & 0x3) << 3)
+#define IOCR_TCS 0x00000004
+#define IOCR_SCS 0x00000002
+#define IOCR_SPC 0x00000001
+
+/* System-On-Chip Version Register */
+
+/* System-On-Chip Version Register (SVR) field extraction */
+
+#define SVR_VER(svr) (((svr) >> 16) & 0xFFFF) /* Version field */
+#define SVR_REV(svr) (((svr) >> 0) & 0xFFFF) /* Revision field */
+
+#define SVR_CID(svr) (((svr) >> 28) & 0x0F) /* Company or manufacturer ID */
+#define SVR_SOCOP(svr) (((svr) >> 22) & 0x3F) /* SOC integration options */
+#define SVR_SID(svr) (((svr) >> 16) & 0x3F) /* SOC ID */
+#define SVR_PROC(svr) (((svr) >> 12) & 0x0F) /* Process revision field */
+#define SVR_MFG(svr) (((svr) >> 8) & 0x0F) /* Manufacturing revision */
+#define SVR_MJREV(svr) (((svr) >> 4) & 0x0F) /* Major SOC design revision indicator */
+#define SVR_MNREV(svr) (((svr) >> 0) & 0x0F) /* Minor SOC design revision indicator */
+
+/* System-On-Chip Version Numbers (version field only) */
+#define SVR_MPC5200 0x8011
+
+/* Processor Version Register */
+
+/* Processor Version Register (PVR) field extraction */
+
+#define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) /* Version field */
+#define PVR_REV(pvr) (((pvr) >> 0) & 0xFFFF) /* Revison field */
+
+/*
+ * AMCC has further subdivided the standard PowerPC 16-bit version and
+ * revision subfields of the PVR for the PowerPC 403s into the following:
+ */
+
+#define PVR_FAM(pvr) (((pvr) >> 20) & 0xFFF) /* Family field */
+#define PVR_MEM(pvr) (((pvr) >> 16) & 0xF) /* Member field */
+#define PVR_CORE(pvr) (((pvr) >> 12) & 0xF) /* Core field */
+#define PVR_CFG(pvr) (((pvr) >> 8) & 0xF) /* Configuration field */
+#define PVR_MAJ(pvr) (((pvr) >> 4) & 0xF) /* Major revision field */
+#define PVR_MIN(pvr) (((pvr) >> 0) & 0xF) /* Minor revision field */
+
+/* Processor Version Numbers */
+
+#define PVR_403GA 0x00200000
+#define PVR_403GB 0x00200100
+#define PVR_403GC 0x00200200
+#define PVR_403GCX 0x00201400
+#define PVR_405GP 0x40110000
+#define PVR_405GP_RB 0x40110040
+#define PVR_405GP_RC 0x40110082
+#define PVR_405GP_RD 0x401100C4
+#define PVR_405GP_RE 0x40110145 /* same as pc405cr rev c */
+#define PVR_405CR_RA 0x40110041
+#define PVR_405CR_RB 0x401100C5
+#define PVR_405CR_RC 0x40110145 /* same as pc405gp rev e */
+#define PVR_405EP_RA 0x51210950
+#define PVR_405GPR_RB 0x50910951
+#define PVR_440GP_RB 0x40120440
+#define PVR_440GP_RC 0x40120481
+#define PVR_440EP_RA 0x42221850
+#define PVR_440EP_RB 0x422218D3 /* 440EP rev B and 440GR rev A have same PVR */
+#define PVR_440EP_RC 0x422218D4 /* 440EP rev C and 440GR rev B have same PVR */
+#define PVR_440GR_RA 0x422218D3 /* 440EP rev B and 440GR rev A have same PVR */
+#define PVR_440GR_RB 0x422218D4 /* 440EP rev C and 440GR rev B have same PVR */
+#define PVR_440EPX1_RA 0x216218D0 /* 440EPX rev A with Security / Kasumi */
+#define PVR_440EPX2_RA 0x216218D4 /* 440EPX rev A without Security / Kasumi */
+#define PVR_440GRX1_RA 0x216218D8 /* 440GRX rev A with Security / Kasumi */
+#define PVR_440GRX2_RA 0x216218DC /* 440GRX rev A without Security / Kasumi */
+#define PVR_440GX_RA 0x51B21850
+#define PVR_440GX_RB 0x51B21851
+#define PVR_440GX_RC 0x51B21892
+#define PVR_440GX_RF 0x51B21894
+#define PVR_405EP_RB 0x51210950
+#define PVR_440SP_RA 0x53221850
+#define PVR_440SP_RB 0x53221891
+#define PVR_440SP_RC 0x53221892
+#define PVR_440SPe_RA 0x53421890
+#define PVR_440SPe_RB 0x53421891
+#define PVR_601 0x00010000
+#define PVR_602 0x00050000
+#define PVR_603 0x00030000
+#define PVR_603e 0x00060000
+#define PVR_603ev 0x00070000
+#define PVR_603r 0x00071000
+#define PVR_604 0x00040000
+#define PVR_604e 0x00090000
+#define PVR_604r 0x000A0000
+#define PVR_620 0x00140000
+#define PVR_740 0x00080000
+#define PVR_750 PVR_740
+#define PVR_740P 0x10080000
+#define PVR_750P PVR_740P
+#define PVR_7400 0x000C0000
+#define PVR_7410 0x800C0000
+#define PVR_7450 0x80000000
+
+#define PVR_85xx 0x80200000
+#define PVR_85xx_REV1 (PVR_85xx | 0x0010)
+#define PVR_85xx_REV2 (PVR_85xx | 0x0020)
+
+#define PVR_86xx 0x80040000
+#define PVR_86xx_REV1 (PVR_86xx | 0x0010)
+
+/*
+ * For the 8xx processors, all of them report the same PVR family for
+ * the PowerPC core. The various versions of these processors must be
+ * differentiated by the version number in the Communication Processor
+ * Module (CPM).
+ */
+#define PVR_821 0x00500000
+#define PVR_823 PVR_821
+#define PVR_850 PVR_821
+#define PVR_860 PVR_821
+#define PVR_7400 0x000C0000
+#define PVR_8240 0x00810100
+
+/*
+ * PowerQUICC II family processors report different PVR values depending
+ * on silicon process (HiP3, HiP4, HiP7, etc.)
+ */
+#define PVR_8260 PVR_8240
+#define PVR_8260_HIP3 0x00810101
+#define PVR_8260_HIP4 0x80811014
+#define PVR_8260_HIP7 0x80822011
+#define PVR_8260_HIP7R1 0x80822013
+#define PVR_8260_HIP7RA 0x80822014
+
+
+/*
+ * System Version Register
+ */
+
+/* System Version Register (SVR) field extraction */
+
+#define SVR_VER(svr) (((svr) >> 16) & 0xFFFF) /* Version field */
+#define SVR_REV(svr) (((svr) >> 0) & 0xFFFF) /* Revison field */
+
+#define SVR_SUBVER(svr) (((svr) >> 8) & 0xFF) /* Process/MFG sub-version */
+
+#define SVR_FAM(svr) (((svr) >> 20) & 0xFFF) /* Family field */
+#define SVR_MEM(svr) (((svr) >> 16) & 0xF) /* Member field */
+
+#define SVR_MAJ(svr) (((svr) >> 4) & 0xF) /* Major revision field*/
+#define SVR_MIN(svr) (((svr) >> 0) & 0xF) /* Minor revision field*/
+
+/* Some parts define SVR[0:23] as the SOC version */
+#define SVR_SOC_VER(svr) (((svr) >> 8) & 0xFFF7FF) /* SOC w/o E bit */
+#define IS_E_PROCESSOR(svr) ((svr) & 0x80000)
+
+/*
+ * SVR_VER() Version Values
+ */
+
+#define SVR_8540 0x8030
+#define SVR_8560 0x8070
+#define SVR_8555 0x8079
+#define SVR_8541 0x807A
+#define SVR_8548 0x8031
+#define SVR_8548_E 0x8039
+#define SVR_8641 0x8090
+#define SVR_8544 0x803401
+#define SVR_8544_E 0x803C01
+#define SVR_P1010 0x80F100
+#define SVR_P1022 0x80E600
+#define SVR_P2020 0x80E200
+#define SVR_P2020_E 0x80EA00
+
+#define SVR_Unknown 0xFFFFFF
+
+
+/* I am just adding a single entry for 8260 boards. I think we may be
+ * able to combine mbx, fads, rpxlite, bseip, and classic into a single
+ * generic 8xx as well. The boards containing these processors are either
+ * identical at the processor level (due to the high integration) or so
+ * wildly different that testing _machine at run time is best replaced by
+ * conditional compilation by board type (found in their respective .h file).
+ * -- Dan
+ */
+#define _MACH_prep 0x00000001
+#define _MACH_Pmac 0x00000002 /* pmac or pmac clone (non-chrp) */
+#define _MACH_chrp 0x00000004 /* chrp machine */
+#define _MACH_mbx 0x00000008 /* Motorola MBX board */
+#define _MACH_apus 0x00000010 /* amiga with phase5 powerup */
+#define _MACH_fads 0x00000020 /* Motorola FADS board */
+#define _MACH_rpxlite 0x00000040 /* RPCG RPX-Lite 8xx board */
+#define _MACH_bseip 0x00000080 /* Bright Star Engineering ip-Engine */
+#define _MACH_yk 0x00000100 /* Motorola Yellowknife */
+#define _MACH_gemini 0x00000200 /* Synergy Microsystems gemini board */
+#define _MACH_classic 0x00000400 /* RPCG RPX-Classic 8xx board */
+#define _MACH_oak 0x00000800 /* IBM "Oak" 403 eval. board */
+#define _MACH_walnut 0x00001000 /* AMCC "Walnut" 405GP eval. board */
+#define _MACH_8260 0x00002000 /* Generic 8260 */
+#define _MACH_sandpoint 0x00004000 /* Motorola SPS Processor eval board */
+#define _MACH_tqm860 0x00008000 /* TQM860/L */
+#define _MACH_tqm8xxL 0x00010000 /* TQM8xxL */
+#define _MACH_hidden_dragon 0x00020000 /* Motorola Hidden Dragon eval board */
+
+
+/* see residual.h for these */
+#define _PREP_Motorola 0x01 /* motorola prep */
+#define _PREP_Firm 0x02 /* firmworks prep */
+#define _PREP_IBM 0x00 /* ibm prep */
+#define _PREP_Bull 0x03 /* bull prep */
+#define _PREP_Radstone 0x04 /* Radstone Technology PLC prep */
+
+/*
+ * Radstone board types
+ */
+#define RS_SYS_TYPE_PPC1 0
+#define RS_SYS_TYPE_PPC2 1
+#define RS_SYS_TYPE_PPC1a 2
+#define RS_SYS_TYPE_PPC2a 3
+#define RS_SYS_TYPE_PPC4 4
+#define RS_SYS_TYPE_PPC4a 5
+#define RS_SYS_TYPE_PPC2ep 6
+
+/* these are arbitrary */
+#define _CHRP_Motorola 0x04 /* motorola chrp, the cobra */
+#define _CHRP_IBM 0x05 /* IBM chrp, the longtrail and longtrail 2 */
+
+#define _GLOBAL(n)\
+ .globl n;\
+n:
+
+/* Macros for setting and retrieving special purpose registers */
+
+#define mfdcr(rn) ({unsigned int rval; \
+ asm volatile("mfdcr %0," __stringify(rn) \
+ : "=r" (rval)); rval;})
+#define mtdcr(rn, v) asm volatile("mtdcr " __stringify(rn) ",%0" : : "r" (v))
+
+#define mfmsr() ({unsigned int rval; \
+ asm volatile("mfmsr %0" : "=r" (rval)); rval;})
+#define mtmsr(v) asm volatile("mtmsr %0" : : "r" (v))
+
+#define mfspr(rn) ({unsigned int rval; \
+ asm volatile("mfspr %0," __stringify(rn) \
+ : "=r" (rval)); rval;})
+#define mtspr(rn, v) asm volatile("mtspr " __stringify(rn) ",%0" : : "r" (v))
+
+#define tlbie(v) asm volatile("tlbie %0 \n sync" : : "r" (v))
+
+/* Segment Registers */
+
+#define SR0 0
+#define SR1 1
+#define SR2 2
+#define SR3 3
+#define SR4 4
+#define SR5 5
+#define SR6 6
+#define SR7 7
+#define SR8 8
+#define SR9 9
+#define SR10 10
+#define SR11 11
+#define SR12 12
+#define SR13 13
+#define SR14 14
+#define SR15 15
+
+#ifndef __ASSEMBLY__
+
+struct cpu_type {
+ char name[15];
+ u32 soc_ver;
+ u32 num_cores;
+};
+
+struct cpu_type *identify_cpu(u32 ver);
+
+#if defined(CONFIG_MPC85xx)
+#define LINUX_TLB1_MAX_ADDR ((void *)(64 << 20))
+#define CPU_TYPE_ENTRY(n, v, nc) \
+ { .name = #n, .soc_ver = SVR_##v, .num_cores = (nc), }
+#else
+#define LINUX_TLB1_MAX_ADDR ((void *)0xffffffff)
+#endif
+#ifndef CONFIG_MACH_SPECIFIC
+extern int _machine;
+extern int have_of;
+#endif /* CONFIG_MACH_SPECIFIC */
+
+/* what kind of prep workstation we are */
+extern int _prep_type;
+/*
+ * This is used to identify the board type from a given PReP board
+ * vendor. Board revision is also made available.
+ */
+extern unsigned char ucSystemType;
+extern unsigned char ucBoardRev;
+extern unsigned char ucBoardRevMaj, ucBoardRevMin;
+
+struct task_struct;
+void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp);
+void release_thread(struct task_struct *);
+
+/*
+ * Create a new kernel thread.
+ */
+extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
+
+/*
+ * Bus types
+ */
+#define EISA_bus 0
+#define EISA_bus__is_a_macro /* for versions in ksyms.c */
+#define MCA_bus 0
+#define MCA_bus__is_a_macro /* for versions in ksyms.c */
+
+/* Lazy FPU handling on uni-processor */
+extern struct task_struct *last_task_used_math;
+extern struct task_struct *last_task_used_altivec;
+
+/*
+ * this is the minimum allowable io space due to the location
+ * of the io areas on prep (first one at 0x80000000) but
+ * as soon as I get around to remapping the io areas with the BATs
+ * to match the mac we can raise this. -- Cort
+ */
+#define TASK_SIZE (0x80000000UL)
+
+/* This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE (TASK_SIZE / 8 * 3)
+
+typedef struct {
+ unsigned long seg;
+} mm_segment_t;
+
+struct thread_struct {
+ unsigned long ksp; /* Kernel stack pointer */
+ unsigned long wchan; /* Event task is sleeping on */
+ struct pt_regs *regs; /* Pointer to saved register state */
+ mm_segment_t fs; /* for get_fs() validation */
+ void *pgdir; /* root of page-table tree */
+ signed long last_syscall;
+ double fpr[32]; /* Complete floating point set */
+ unsigned long fpscr_pad; /* fpr ... fpscr must be contiguous */
+ unsigned long fpscr; /* Floating point status */
+#ifdef CONFIG_ALTIVEC
+ vector128 vr[32]; /* Complete AltiVec set */
+ vector128 vscr; /* AltiVec status */
+ unsigned long vrsave;
+#endif /* CONFIG_ALTIVEC */
+};
+
+#define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack)
+
+#define INIT_THREAD { \
+ INIT_SP, /* ksp */ \
+ 0, /* wchan */ \
+ (struct pt_regs *)INIT_SP - 1, /* regs */ \
+ KERNEL_DS, /*fs*/ \
+ swapper_pg_dir, /* pgdir */ \
+ 0, /* last_syscall */ \
+ {0}, 0, 0 \
+}
+
+/*
+ * Note: the vm_start and vm_end fields here should *not*
+ * be in kernel space. (Could vm_end == vm_start perhaps?)
+ */
+#define INIT_MMAP { &init_mm, 0, 0x1000, NULL, \
+ PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, \
+ 1, NULL, NULL }
+
+/*
+ * Return saved PC of a blocked thread. For now, this is the "user" PC
+ */
+static inline unsigned long thread_saved_pc(struct thread_struct *t)
+{
+ return (t->regs) ? t->regs->nip : 0;
+}
+
+#define copy_segments(tsk, mm) do { } while (0)
+#define release_segments(mm) do { } while (0)
+#define forget_segments() do { } while (0)
+
+unsigned long get_wchan(struct task_struct *p);
+
+#define KSTK_EIP(tsk) ((tsk)->thread.regs->nip)
+#define KSTK_ESP(tsk) ((tsk)->thread.regs->gpr[1])
+
+/*
+ * NOTE! The task struct and the stack go together
+ */
+#define THREAD_SIZE (2*PAGE_SIZE)
+#define alloc_task_struct() \
+ ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
+#define free_task_struct(p) free_pages((unsigned long)(p),1)
+#define get_task_struct(tsk) atomic_inc(&mem_map[MAP_NR(tsk)].count)
+
+/* in process.c - for early bootup debug -- Cort */
+int ll_printk(const char *, ...);
+void ll_puts(const char *);
+
+#define init_task (init_task_union.task)
+#define init_stack (init_task_union.stack)
+
+/* In misc.c */
+void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
+
+void CritcalInputException(struct pt_regs *regs);
+void MachineCheckException(struct pt_regs *regs);
+void AlignmentException(struct pt_regs *regs);
+void ProgramCheckException(struct pt_regs *regs);
+void PITException(struct pt_regs *regs);
+void UnknownException(struct pt_regs *regs);
+void DebugException(struct pt_regs *regs);
+
+#endif /* ndef ASSEMBLY*/
+
+#ifdef CONFIG_MACH_SPECIFIC
+#if defined(CONFIG_8xx)
+#define _machine _MACH_8xx
+#define have_of 0
+#elif defined(CONFIG_OAK)
+#define _machine _MACH_oak
+#define have_of 0
+#elif defined(CONFIG_WALNUT)
+#define _machine _MACH_walnut
+#define have_of 0
+#elif defined(CONFIG_APUS)
+#define _machine _MACH_apus
+#define have_of 0
+#elif defined(CONFIG_GEMINI)
+#define _machine _MACH_gemini
+#define have_of 0
+#elif defined(CONFIG_8260)
+#define _machine _MACH_8260
+#define have_of 0
+#elif defined(CONFIG_SANDPOINT)
+#define _machine _MACH_sandpoint
+#elif defined(CONFIG_HIDDEN_DRAGON)
+#define _machine _MACH_hidden_dragon
+#define have_of 0
+#else
+#error "Machine not defined correctly"
+#endif
+#endif /* CONFIG_MACH_SPECIFIC */
+
+#endif /* __ASM_PPC_PROCESSOR_H */
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h
new file mode 100644
index 0000000000..c7800576d5
--- /dev/null
+++ b/arch/powerpc/include/asm/ptrace.h
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _PPC_PTRACE_H
+#define _PPC_PTRACE_H
+
+/*
+ * This struct defines the way the registers are stored on the
+ * kernel stack during a system call or other kernel entry.
+ *
+ * this should only contain volatile regs
+ * since we can keep non-volatile in the thread_struct
+ * should set this up when only volatiles are saved
+ * by intr code.
+ *
+ * Since this is going on the stack, *CARE MUST BE TAKEN* to insure
+ * that the overall structure is a multiple of 16 bytes in length.
+ *
+ * Note that the offsets of the fields in this struct correspond with
+ * the PT_* values below. This simplifies arch/ppc/kernel/ptrace.c.
+ */
+
+
+#ifndef __ASSEMBLY__
+#ifdef CONFIG_PPC64BRIDGE
+#define PPC_REG unsigned long /*long*/
+#else
+#define PPC_REG unsigned long
+#endif
+struct pt_regs {
+ PPC_REG gpr[32];
+ PPC_REG nip;
+ PPC_REG msr;
+ PPC_REG orig_gpr3; /* Used for restarting system calls */
+ PPC_REG ctr;
+ PPC_REG link;
+ PPC_REG xer;
+ PPC_REG ccr;
+ PPC_REG mq; /* 601 only (not used at present) */
+ /* Used on APUS to hold IPL value. */
+ PPC_REG trap; /* Reason for being here */
+ PPC_REG dar; /* Fault registers */
+ PPC_REG dsisr;
+ PPC_REG result; /* Result of a system call */
+};
+#endif
+
+#define STACK_FRAME_OVERHEAD 16 /* size of minimum stack frame */
+
+/* Size of stack frame allocated when calling signal handler. */
+#define __SIGNAL_FRAMESIZE 64
+
+#define instruction_pointer(regs) ((regs)->nip)
+#define user_mode(regs) (((regs)->msr & MSR_PR) != 0)
+
+/*
+ * Offsets used by 'ptrace' system call interface.
+ * These can't be changed without breaking binary compatibility
+ * with MkLinux, etc.
+ */
+#define PT_R0 0
+#define PT_R1 1
+#define PT_R2 2
+#define PT_R3 3
+#define PT_R4 4
+#define PT_R5 5
+#define PT_R6 6
+#define PT_R7 7
+#define PT_R8 8
+#define PT_R9 9
+#define PT_R10 10
+#define PT_R11 11
+#define PT_R12 12
+#define PT_R13 13
+#define PT_R14 14
+#define PT_R15 15
+#define PT_R16 16
+#define PT_R17 17
+#define PT_R18 18
+#define PT_R19 19
+#define PT_R20 20
+#define PT_R21 21
+#define PT_R22 22
+#define PT_R23 23
+#define PT_R24 24
+#define PT_R25 25
+#define PT_R26 26
+#define PT_R27 27
+#define PT_R28 28
+#define PT_R29 29
+#define PT_R30 30
+#define PT_R31 31
+
+#define PT_NIP 32
+#define PT_MSR 33
+#ifdef __KERNEL__
+#define PT_ORIG_R3 34
+#endif
+#define PT_CTR 35
+#define PT_LNK 36
+#define PT_XER 37
+#define PT_CCR 38
+#define PT_MQ 39
+
+#define PT_FPR0 48 /* each FP reg occupies 2 slots in this space */
+#define PT_FPR31 (PT_FPR0 + 2*31)
+#define PT_FPSCR (PT_FPR0 + 2*32 + 1)
+
+#endif
diff --git a/arch/powerpc/include/asm/sections.h b/arch/powerpc/include/asm/sections.h
new file mode 100644
index 0000000000..c6dd0eead2
--- /dev/null
+++ b/arch/powerpc/include/asm/sections.h
@@ -0,0 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <asm-generic/sections.h>
diff --git a/arch/powerpc/include/asm/setjmp.h b/arch/powerpc/include/asm/setjmp.h
new file mode 100644
index 0000000000..91bfcdb7f4
--- /dev/null
+++ b/arch/powerpc/include/asm/setjmp.h
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
+ * (C) Copyright 2016 Alexander Graf <agraf@suse.de>
+ */
+
+#ifndef _SETJMP_H_
+#define _SETJMP_H_ 1
+
+#include <asm/types.h>
+
+typedef struct __jmp_buf_internal_tag {
+ long int __regs[24];
+} jmp_buf[1];
+
+int setjmp(jmp_buf jmp) __attribute__((returns_twice));
+void longjmp(jmp_buf jmp, int ret) __attribute__((noreturn));
+
+int initjmp(jmp_buf jmp, void __attribute__((noreturn)) (*func)(void), void *stack_top);
+
+#endif /* _SETJMP_H_ */
diff --git a/arch/powerpc/include/asm/sigcontext.h b/arch/powerpc/include/asm/sigcontext.h
new file mode 100644
index 0000000000..78648b089c
--- /dev/null
+++ b/arch/powerpc/include/asm/sigcontext.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _ASM_PPC_SIGCONTEXT_H
+#define _ASM_PPC_SIGCONTEXT_H
+
+#include <asm/ptrace.h>
+
+
+struct sigcontext_struct {
+ unsigned long _unused[4];
+ int signal;
+ unsigned long handler;
+ unsigned long oldmask;
+ struct pt_regs *regs;
+};
+
+#endif
diff --git a/arch/powerpc/include/asm/signal.h b/arch/powerpc/include/asm/signal.h
new file mode 100644
index 0000000000..851fc7d41c
--- /dev/null
+++ b/arch/powerpc/include/asm/signal.h
@@ -0,0 +1,156 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _ASMPPC_SIGNAL_H
+#define _ASMPPC_SIGNAL_H
+
+#include <linux/types.h>
+
+/* Avoid too many header ordering problems. */
+struct siginfo;
+
+/* Most things should be clean enough to redefine this at will, if care
+ is taken to make libc match. */
+
+#define _NSIG 64
+#define _NSIG_BPW 32
+#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
+
+typedef unsigned long old_sigset_t; /* at least 32 bits */
+
+typedef struct {
+ unsigned long sig[_NSIG_WORDS];
+} sigset_t;
+
+#define SIGHUP 1
+#define SIGINT 2
+#define SIGQUIT 3
+#define SIGILL 4
+#define SIGTRAP 5
+#define SIGABRT 6
+#define SIGIOT 6
+#define SIGBUS 7
+#define SIGFPE 8
+#define SIGKILL 9
+#define SIGUSR1 10
+#define SIGSEGV 11
+#define SIGUSR2 12
+#define SIGPIPE 13
+#define SIGALRM 14
+#define SIGTERM 15
+#define SIGSTKFLT 16
+#define SIGCHLD 17
+#define SIGCONT 18
+#define SIGSTOP 19
+#define SIGTSTP 20
+#define SIGTTIN 21
+#define SIGTTOU 22
+#define SIGURG 23
+#define SIGXCPU 24
+#define SIGXFSZ 25
+#define SIGVTALRM 26
+#define SIGPROF 27
+#define SIGWINCH 28
+#define SIGIO 29
+#define SIGPOLL SIGIO
+/*
+#define SIGLOST 29
+*/
+#define SIGPWR 30
+#define SIGSYS 31
+#define SIGUNUSED 31
+
+/* These should not be considered constants from userland. */
+#define SIGRTMIN 32
+#define SIGRTMAX (_NSIG-1)
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK is not currently supported, but will allow sigaltstack(2).
+ * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define SA_NOCLDSTOP 0x00000001
+#define SA_NOCLDWAIT 0x00000002 /* not supported yet */
+#define SA_SIGINFO 0x00000004
+#define SA_ONSTACK 0x08000000
+#define SA_RESTART 0x10000000
+#define SA_NODEFER 0x40000000
+#define SA_RESETHAND 0x80000000
+
+#define SA_NOMASK SA_NODEFER
+#define SA_ONESHOT SA_RESETHAND
+#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */
+
+#define SA_RESTORER 0x04000000
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK 1
+#define SS_DISABLE 2
+
+#define MINSIGSTKSZ 2048
+#define SIGSTKSZ 8192
+#ifdef __KERNEL__
+
+/*
+ * These values of sa_flags are used only by the kernel as part of the
+ * irq handling routines.
+ *
+ * SA_INTERRUPT is also used by the irq handling routines.
+ * SA_SHIRQ is for shared interrupt support on PCI and EISA.
+ */
+#define SA_PROBE SA_ONESHOT
+#define SA_SAMPLE_RANDOM SA_RESTART
+#define SA_SHIRQ 0x04000000
+#endif
+
+#define SIG_BLOCK 0 /* for blocking signals */
+#define SIG_UNBLOCK 1 /* for unblocking signals */
+#define SIG_SETMASK 2 /* for setting the signal mask */
+
+/* Type of a signal handler. */
+typedef void (*__sighandler_t)(int);
+
+#define SIG_DFL ((__sighandler_t)0) /* default signal handling */
+#define SIG_IGN ((__sighandler_t)1) /* ignore signal */
+#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */
+
+struct old_sigaction {
+ __sighandler_t sa_handler;
+ old_sigset_t sa_mask;
+ unsigned long sa_flags;
+ void (*sa_restorer)(void);
+};
+
+struct sigaction {
+ __sighandler_t sa_handler;
+ unsigned long sa_flags;
+ void (*sa_restorer)(void);
+ sigset_t sa_mask; /* mask last for extensibility */
+};
+
+struct k_sigaction {
+ struct sigaction sa;
+};
+
+typedef struct sigaltstack {
+ void *ss_sp;
+ int ss_flags;
+ size_t ss_size;
+} stack_t;
+
+#ifdef __KERNEL__
+#include <asm/sigcontext.h>
+
+#endif
+
+#endif
diff --git a/arch/powerpc/include/asm/status_led.h b/arch/powerpc/include/asm/status_led.h
new file mode 100644
index 0000000000..129aa6614a
--- /dev/null
+++ b/arch/powerpc/include/asm/status_led.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * asm/status_led.h
+ *
+ * MPC8xx/MPC8260/MPC5xx based status led support functions
+ */
+
+#ifndef __ASM_STATUS_LED_H__
+#define __ASM_STATUS_LED_H__
+
+/* if not overriden */
+#ifndef CONFIG_BOARD_SPECIFIC_LED
+# if defined(CONFIG_8xx)
+# include <mpc8xx.h>
+# elif defined(CONFIG_8260)
+# include <mpc8260.h>
+# elif defined(CONFIG_5xx)
+# include <mpc5xx.h>
+# else
+# error CPU specific Status LED header file missing.
+#endif
+
+/* led_id_t is unsigned long mask */
+typedef unsigned long led_id_t;
+
+static inline void __led_init (led_id_t mask, int state)
+{
+ volatile immap_t *immr = (immap_t *) CFG_IMMR;
+
+#ifdef STATUS_LED_PAR
+ immr->STATUS_LED_PAR &= ~mask;
+#endif
+#ifdef STATUS_LED_ODR
+ immr->STATUS_LED_ODR &= ~mask;
+#endif
+
+#if (STATUS_LED_ACTIVE == 0)
+ if (state == STATUS_LED_ON)
+ immr->STATUS_LED_DAT &= ~mask;
+ else
+ immr->STATUS_LED_DAT |= mask;
+#else
+ if (state == STATUS_LED_ON)
+ immr->STATUS_LED_DAT |= mask;
+ else
+ immr->STATUS_LED_DAT &= ~mask;
+#endif
+#ifdef STATUS_LED_DIR
+ immr->STATUS_LED_DIR |= mask;
+#endif
+}
+
+static inline void __led_toggle (led_id_t mask)
+{
+ ((immap_t *) CFG_IMMR)->STATUS_LED_DAT ^= mask;
+}
+
+static inline void __led_set (led_id_t mask, int state)
+{
+ volatile immap_t *immr = (immap_t *) CFG_IMMR;
+
+#if (STATUS_LED_ACTIVE == 0)
+ if (state == STATUS_LED_ON)
+ immr->STATUS_LED_DAT &= ~mask;
+ else
+ immr->STATUS_LED_DAT |= mask;
+#else
+ if (state == STATUS_LED_ON)
+ immr->STATUS_LED_DAT |= mask;
+ else
+ immr->STATUS_LED_DAT &= ~mask;
+#endif
+
+}
+
+#endif
+
+#endif /* __ASM_STATUS_LED_H__ */
diff --git a/arch/powerpc/include/asm/string.h b/arch/powerpc/include/asm/string.h
new file mode 100644
index 0000000000..b06bb4cbff
--- /dev/null
+++ b/arch/powerpc/include/asm/string.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _PPC_STRING_H_
+#define _PPC_STRING_H_
+
+#define __HAVE_ARCH_STRCPY
+#define __HAVE_ARCH_STRNCPY
+#define __HAVE_ARCH_STRLEN
+#define __HAVE_ARCH_STRCMP
+#define __HAVE_ARCH_STRCAT
+#define __HAVE_ARCH_MEMSET
+#define __HAVE_ARCH_BCOPY
+#define __HAVE_ARCH_MEMCPY
+#define __HAVE_ARCH_MEMMOVE
+#define __HAVE_ARCH_MEMCMP
+#define __HAVE_ARCH_MEMCHR
+
+extern char * strcpy(char *,const char *);
+extern char * strncpy(char *,const char *, __kernel_size_t);
+extern __kernel_size_t strlen(const char *);
+extern int strcmp(const char *,const char *);
+extern char * strcat(char *, const char *);
+extern void * memset(void *,int,__kernel_size_t);
+extern void * memcpy(void *,const void *,__kernel_size_t);
+extern void * memmove(void *,const void *,__kernel_size_t);
+extern int memcmp(const void *,const void *,__kernel_size_t);
+extern void * memchr(const void *,int,__kernel_size_t);
+
+#endif
diff --git a/arch/powerpc/include/asm/swab.h b/arch/powerpc/include/asm/swab.h
new file mode 100644
index 0000000000..110488e641
--- /dev/null
+++ b/arch/powerpc/include/asm/swab.h
@@ -0,0 +1,90 @@
+#ifndef _ASM_POWERPC_SWAB_H
+#define _ASM_POWERPC_SWAB_H
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+
+#ifdef __GNUC__
+
+#ifndef __powerpc64__
+#define __SWAB_64_THRU_32__
+#endif /* __powerpc64__ */
+
+#ifdef __KERNEL__
+
+static inline __u16 ld_le16(const volatile __u16 *addr)
+{
+ __u16 val;
+
+ __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
+ return val;
+}
+#define __arch_swab16p ld_le16
+
+static inline void st_le16(volatile __u16 *addr, const __u16 val)
+{
+ __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
+}
+
+static inline void __arch_swab16s(__u16 *addr)
+{
+ st_le16(addr, *addr);
+}
+#define __arch_swab16s __arch_swab16s
+
+static inline __u32 ld_le32(const volatile __u32 *addr)
+{
+ __u32 val;
+
+ __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
+ return val;
+}
+#define __arch_swab32p ld_le32
+
+static inline void st_le32(volatile __u32 *addr, const __u32 val)
+{
+ __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
+}
+
+static inline void __arch_swab32s(__u32 *addr)
+{
+ st_le32(addr, *addr);
+}
+#define __arch_swab32s __arch_swab32s
+
+static inline __attribute_const__ __u16 __arch_swab16(__u16 value)
+{
+ __u16 result;
+
+ __asm__("rlwimi %0,%1,8,16,23"
+ : "=r" (result)
+ : "r" (value), "0" (value >> 8));
+ return result;
+}
+#define __arch_swab16 __arch_swab16
+
+static inline __attribute_const__ __u32 __arch_swab32(__u32 value)
+{
+ __u32 result;
+
+ __asm__("rlwimi %0,%1,24,16,23\n\t"
+ "rlwimi %0,%1,8,8,15\n\t"
+ "rlwimi %0,%1,24,0,7"
+ : "=r" (result)
+ : "r" (value), "0" (value >> 24));
+ return result;
+}
+#define __arch_swab32 __arch_swab32
+
+#endif /* __KERNEL__ */
+
+#endif /* __GNUC__ */
+
+#endif /* _ASM_POWERPC_SWAB_H */
diff --git a/arch/powerpc/include/asm/types.h b/arch/powerpc/include/asm/types.h
new file mode 100644
index 0000000000..c2c501828b
--- /dev/null
+++ b/arch/powerpc/include/asm/types.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _PPC_TYPES_H
+#define _PPC_TYPES_H
+
+#include <asm-generic/int-ll64.h>
+
+#ifndef __ASSEMBLY__
+
+typedef struct {
+ __u32 u[4];
+} __attribute((aligned(16))) vector128;
+
+#endif /* __ASSEMBLY__ */
+
+#endif
diff --git a/arch/powerpc/include/asm/unaligned.h b/arch/powerpc/include/asm/unaligned.h
new file mode 100644
index 0000000000..a28cc24b12
--- /dev/null
+++ b/arch/powerpc/include/asm/unaligned.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _ASM_PPC_UNALIGNED_H
+#define _ASM_PPC_UNALIGNED_H
+
+#ifdef __KERNEL__
+
+/*
+ * The PowerPC can do unaligned accesses itself in big endian mode.
+ */
+#include <linux/unaligned/access_ok.h>
+#include <linux/unaligned/generic.h>
+
+#define get_unaligned __get_unaligned_be
+#define put_unaligned __put_unaligned_be
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_PPC_UNALIGNED_H */
diff --git a/arch/powerpc/include/asm/word-at-a-time.h b/arch/powerpc/include/asm/word-at-a-time.h
new file mode 100644
index 0000000000..029740c6de
--- /dev/null
+++ b/arch/powerpc/include/asm/word-at-a-time.h
@@ -0,0 +1,162 @@
+#ifndef _ASM_WORD_AT_A_TIME_H
+#define _ASM_WORD_AT_A_TIME_H
+
+/*
+ * Word-at-a-time interfaces for PowerPC.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+
+#ifdef __BIG_ENDIAN__
+
+struct word_at_a_time {
+ const unsigned long high_bits, low_bits;
+};
+
+#define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0xfe) + 1, REPEAT_BYTE(0x7f) }
+
+/* Bit set in the bytes that have a zero */
+static inline long prep_zero_mask(unsigned long val, unsigned long rhs, const struct word_at_a_time *c)
+{
+ unsigned long mask = (val & c->low_bits) + c->low_bits;
+ return ~(mask | rhs);
+}
+
+#define create_zero_mask(mask) (mask)
+
+static inline long find_zero(unsigned long mask)
+{
+ long leading_zero_bits;
+
+#ifdef __powerpc64__
+ asm ("cntlzd %0,%1" : "=r" (leading_zero_bits) : "r" (mask));
+#else
+ asm ("cntlzw %0,%1" : "=r" (leading_zero_bits) : "r" (mask));
+#endif
+
+ return leading_zero_bits >> 3;
+}
+
+static inline unsigned long has_zero(unsigned long val, unsigned long *data, const struct word_at_a_time *c)
+{
+ unsigned long rhs = val | c->low_bits;
+ *data = rhs;
+ return (val + c->high_bits) & ~rhs;
+}
+
+static inline unsigned long zero_bytemask(unsigned long mask)
+{
+ return ~1ul << __fls(mask);
+}
+
+#else
+
+#ifdef CONFIG_64BIT
+
+/* unused */
+struct word_at_a_time {
+};
+
+#define WORD_AT_A_TIME_CONSTANTS { }
+
+/* This will give us 0xff for a NULL char and 0x00 elsewhere */
+static inline unsigned long has_zero(unsigned long a, unsigned long *bits, const struct word_at_a_time *c)
+{
+ unsigned long ret;
+ unsigned long zero = 0;
+
+ asm("cmpb %0,%1,%2" : "=r" (ret) : "r" (a), "r" (zero));
+ *bits = ret;
+
+ return ret;
+}
+
+static inline unsigned long prep_zero_mask(unsigned long a, unsigned long bits, const struct word_at_a_time *c)
+{
+ return bits;
+}
+
+/* Alan Modra's little-endian strlen tail for 64-bit */
+static inline unsigned long create_zero_mask(unsigned long bits)
+{
+ unsigned long leading_zero_bits;
+ long trailing_zero_bit_mask;
+
+ asm("addi %1,%2,-1\n\t"
+ "andc %1,%1,%2\n\t"
+ "popcntd %0,%1"
+ : "=r" (leading_zero_bits), "=&r" (trailing_zero_bit_mask)
+ : "b" (bits));
+
+ return leading_zero_bits;
+}
+
+static inline unsigned long find_zero(unsigned long mask)
+{
+ return mask >> 3;
+}
+
+/* This assumes that we never ask for an all 1s bitmask */
+static inline unsigned long zero_bytemask(unsigned long mask)
+{
+ return (1UL << mask) - 1;
+}
+
+#else /* 32-bit case */
+
+struct word_at_a_time {
+ const unsigned long one_bits, high_bits;
+};
+
+#define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x01), REPEAT_BYTE(0x80) }
+
+/*
+ * This is largely generic for little-endian machines, but the
+ * optimal byte mask counting is probably going to be something
+ * that is architecture-specific. If you have a reliably fast
+ * bit count instruction, that might be better than the multiply
+ * and shift, for example.
+ */
+
+/* Carl Chatfield / Jan Achrenius G+ version for 32-bit */
+static inline long count_masked_bytes(long mask)
+{
+ /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */
+ long a = (0x0ff0001+mask) >> 23;
+ /* Fix the 1 for 00 case */
+ return a & mask;
+}
+
+static inline unsigned long create_zero_mask(unsigned long bits)
+{
+ bits = (bits - 1) & ~bits;
+ return bits >> 7;
+}
+
+static inline unsigned long find_zero(unsigned long mask)
+{
+ return count_masked_bytes(mask);
+}
+
+/* Return nonzero if it has a zero */
+static inline unsigned long has_zero(unsigned long a, unsigned long *bits, const struct word_at_a_time *c)
+{
+ unsigned long mask = ((a - c->one_bits) & ~a) & c->high_bits;
+ *bits = mask;
+ return mask;
+}
+
+static inline unsigned long prep_zero_mask(unsigned long a, unsigned long bits, const struct word_at_a_time *c)
+{
+ return bits;
+}
+
+/* The mask we created is directly usable as a bytemask */
+#define zero_bytemask(mask) (mask)
+
+#endif /* CONFIG_64BIT */
+
+#endif /* __BIG_ENDIAN__ */
+
+#endif /* _ASM_WORD_AT_A_TIME_H */
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
new file mode 100644
index 0000000000..65729953e6
--- /dev/null
+++ b/arch/powerpc/lib/Makefile
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-y += bat_rw.o
+obj-y += board.o
+obj-y += extable.o
+obj-y += kgdb.o
+obj-y += ppcstring.o
+obj-y += ticks.o
+obj-y += misc.o
+obj-$(CONFIG_CMD_BOOTM) += ppclinux.o
+obj-$(CONFIG_MODULES) += module.o
+obj-y += crtsavres.o
+obj-y += reloc.o
+obj-y += setjmp.o
diff --git a/arch/powerpc/lib/asm-offsets.c b/arch/powerpc/lib/asm-offsets.c
new file mode 100644
index 0000000000..bef280edd7
--- /dev/null
+++ b/arch/powerpc/lib/asm-offsets.c
@@ -0,0 +1,21 @@
+/*
+ * This program is used to generate definitions needed by
+ * assembly language modules.
+ *
+ * We use the technique used in the OSF Mach kernel code:
+ * generate asm statements containing #defines,
+ * compile this file to assembler, and then extract the
+ * #defines from the assembly-language output.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kbuild.h>
+
+int main(void)
+{
+ return 0;
+}
diff --git a/arch/powerpc/lib/bat_rw.c b/arch/powerpc/lib/bat_rw.c
new file mode 100644
index 0000000000..bffa504aea
--- /dev/null
+++ b/arch/powerpc/lib/bat_rw.c
@@ -0,0 +1,126 @@
+/*
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.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.
+ *
+ *
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+
+int write_bat (ppc_bat_t bat, unsigned long upper, unsigned long lower)
+{
+ switch (bat) {
+ case IBAT0:
+ mtspr (IBAT0L, lower);
+ mtspr (IBAT0U, upper);
+ break;
+
+ case IBAT1:
+ mtspr (IBAT1L, lower);
+ mtspr (IBAT1U, upper);
+ break;
+
+ case IBAT2:
+ mtspr (IBAT2L, lower);
+ mtspr (IBAT2U, upper);
+ break;
+
+ case IBAT3:
+ mtspr (IBAT3L, lower);
+ mtspr (IBAT3U, upper);
+ break;
+
+ case DBAT0:
+ mtspr (DBAT0L, lower);
+ mtspr (DBAT0U, upper);
+ break;
+
+ case DBAT1:
+ mtspr (DBAT1L, lower);
+ mtspr (DBAT1U, upper);
+ break;
+
+ case DBAT2:
+ mtspr (DBAT2L, lower);
+ mtspr (DBAT2U, upper);
+ break;
+
+ case DBAT3:
+ mtspr (DBAT3L, lower);
+ mtspr (DBAT3U, upper);
+ break;
+
+ default:
+ return (-1);
+ }
+
+ return (0);
+}
+
+int read_bat (ppc_bat_t bat, unsigned long *upper, unsigned long *lower)
+{
+ unsigned long register u;
+ unsigned long register l;
+
+ switch (bat) {
+ case IBAT0:
+ l = mfspr (IBAT0L);
+ u = mfspr (IBAT0U);
+ break;
+
+ case IBAT1:
+ l = mfspr (IBAT1L);
+ u = mfspr (IBAT1U);
+ break;
+
+ case IBAT2:
+ l = mfspr (IBAT2L);
+ u = mfspr (IBAT2U);
+ break;
+
+ case IBAT3:
+ l = mfspr (IBAT3L);
+ u = mfspr (IBAT3U);
+ break;
+
+ case DBAT0:
+ l = mfspr (DBAT0L);
+ u = mfspr (DBAT0U);
+ break;
+
+ case DBAT1:
+ l = mfspr (DBAT1L);
+ u = mfspr (DBAT1U);
+ break;
+
+ case DBAT2:
+ l = mfspr (DBAT2L);
+ u = mfspr (DBAT2U);
+ break;
+
+ case DBAT3:
+ l = mfspr (DBAT3L);
+ u = mfspr (DBAT3U);
+ break;
+
+ default:
+ return (-1);
+ }
+
+ *upper = u;
+ *lower = l;
+
+ return (0);
+}
diff --git a/arch/powerpc/lib/board.c b/arch/powerpc/lib/board.c
new file mode 100644
index 0000000000..a6111606b6
--- /dev/null
+++ b/arch/powerpc/lib/board.c
@@ -0,0 +1,65 @@
+/*
+ * (C) Copyright 2000-2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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.
+ *
+ */
+
+#include <debug_ll.h>
+#include <common.h>
+#include <command.h>
+#include <malloc.h>
+#include <memory.h>
+#include <init.h>
+#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.
+ *
+ ************************************************************************
+ */
+
+/* Called from assembly */
+void board_init_r (ulong end_of_ram);
+
+void board_init_r (ulong end_of_ram)
+{
+ unsigned long malloc_end;
+
+ asm ("sync ; isync");
+
+#ifdef CONFIG_MPC85xx
+ _text_base = end_of_ram;
+#endif
+
+ malloc_end = (_text_base - STACK_SIZE) & ~(4095);
+
+ debug("malloc_end: 0x%08lx\n", malloc_end);
+ debug("TEXT_BASE after relocation: 0x%08lx\n", _text_base);
+
+ mem_malloc_init((void *)(malloc_end - MALLOC_SIZE), (void *)(malloc_end - 1));
+
+ /*
+ * Setup trap handlers
+ */
+ trap_init (0);
+
+ /* Initialization complete - start the monitor */
+
+ start_barebox();
+}
+
diff --git a/arch/powerpc/lib/crtsavres.S b/arch/powerpc/lib/crtsavres.S
new file mode 100644
index 0000000000..b0fbbfc997
--- /dev/null
+++ b/arch/powerpc/lib/crtsavres.S
@@ -0,0 +1,232 @@
+/*
+ * Special support for eabi and SVR4
+ *
+ * Copyright (C) 1995, 1996, 1998, 2000, 2001 Free Software Foundation, Inc.
+ * Copyright 2008 Freescale Semiconductor, Inc.
+ * Written By Michael Meissner
+ *
+ * Based on gcc/config/rs6000/crtsavres.asm from gcc
+ * 64 bit additions from reading the PPC elf64abi document.
+ *
+ * This file 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, or (at your option) any
+ * later version.
+ *
+ * In addition to the permissions in the GNU General Public License, the
+ * Free Software Foundation gives you unlimited permission to link the
+ * compiled version of this file with other programs, and to distribute
+ * those programs without any restriction coming from the use of this
+ * file. (The General Public License restrictions do apply in other
+ * respects; for example, they cover modification of the file, and
+ * distribution when not linked into another program.)
+ *
+ * This file 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.
+ *
+ * As a special exception, if you link this library with files
+ * compiled with GCC to produce an executable, this does not cause
+ * the resulting executable to be covered by the GNU General Public License.
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ */
+
+#include <linux/stringify.h>
+#include <asm/ppc_asm.tmpl>
+
+#define N_FUN 36
+
+#define _GLOBAL(n) \
+ .text; \
+ .stabs __stringify(n:F-1),N_FUN,0,0,n;\
+ .globl n; \
+n:
+
+ .file "crtsavres.S"
+ .section ".text"
+
+/* Routines for saving integer registers, called by the compiler. */
+/* Called with r11 pointing to the stack header word of the caller of the */
+/* function, just beyond the end of the integer save area. */
+
+_GLOBAL(_savegpr_14)
+_GLOBAL(_save32gpr_14)
+ stw 14,-72(11) /* save gp registers */
+_GLOBAL(_savegpr_15)
+_GLOBAL(_save32gpr_15)
+ stw 15,-68(11)
+_GLOBAL(_savegpr_16)
+_GLOBAL(_save32gpr_16)
+ stw 16,-64(11)
+_GLOBAL(_savegpr_17)
+_GLOBAL(_save32gpr_17)
+ stw 17,-60(11)
+_GLOBAL(_savegpr_18)
+_GLOBAL(_save32gpr_18)
+ stw 18,-56(11)
+_GLOBAL(_savegpr_19)
+_GLOBAL(_save32gpr_19)
+ stw 19,-52(11)
+_GLOBAL(_savegpr_20)
+_GLOBAL(_save32gpr_20)
+ stw 20,-48(11)
+_GLOBAL(_savegpr_21)
+_GLOBAL(_save32gpr_21)
+ stw 21,-44(11)
+_GLOBAL(_savegpr_22)
+_GLOBAL(_save32gpr_22)
+ stw 22,-40(11)
+_GLOBAL(_savegpr_23)
+_GLOBAL(_save32gpr_23)
+ stw 23,-36(11)
+_GLOBAL(_savegpr_24)
+_GLOBAL(_save32gpr_24)
+ stw 24,-32(11)
+_GLOBAL(_savegpr_25)
+_GLOBAL(_save32gpr_25)
+ stw 25,-28(11)
+_GLOBAL(_savegpr_26)
+_GLOBAL(_save32gpr_26)
+ stw 26,-24(11)
+_GLOBAL(_savegpr_27)
+_GLOBAL(_save32gpr_27)
+ stw 27,-20(11)
+_GLOBAL(_savegpr_28)
+_GLOBAL(_save32gpr_28)
+ stw 28,-16(11)
+_GLOBAL(_savegpr_29)
+_GLOBAL(_save32gpr_29)
+ stw 29,-12(11)
+_GLOBAL(_savegpr_30)
+_GLOBAL(_save32gpr_30)
+ stw 30,-8(11)
+_GLOBAL(_savegpr_31)
+_GLOBAL(_save32gpr_31)
+ stw 31,-4(11)
+ blr
+
+/* Routines for restoring integer registers, called by the compiler. */
+/* Called with r11 pointing to the stack header word of the caller of the */
+/* function, just beyond the end of the integer restore area. */
+
+_GLOBAL(_restgpr_14)
+_GLOBAL(_rest32gpr_14)
+ lwz 14,-72(11) /* restore gp registers */
+_GLOBAL(_restgpr_15)
+_GLOBAL(_rest32gpr_15)
+ lwz 15,-68(11)
+_GLOBAL(_restgpr_16)
+_GLOBAL(_rest32gpr_16)
+ lwz 16,-64(11)
+_GLOBAL(_restgpr_17)
+_GLOBAL(_rest32gpr_17)
+ lwz 17,-60(11)
+_GLOBAL(_restgpr_18)
+_GLOBAL(_rest32gpr_18)
+ lwz 18,-56(11)
+_GLOBAL(_restgpr_19)
+_GLOBAL(_rest32gpr_19)
+ lwz 19,-52(11)
+_GLOBAL(_restgpr_20)
+_GLOBAL(_rest32gpr_20)
+ lwz 20,-48(11)
+_GLOBAL(_restgpr_21)
+_GLOBAL(_rest32gpr_21)
+ lwz 21,-44(11)
+_GLOBAL(_restgpr_22)
+_GLOBAL(_rest32gpr_22)
+ lwz 22,-40(11)
+_GLOBAL(_restgpr_23)
+_GLOBAL(_rest32gpr_23)
+ lwz 23,-36(11)
+_GLOBAL(_restgpr_24)
+_GLOBAL(_rest32gpr_24)
+ lwz 24,-32(11)
+_GLOBAL(_restgpr_25)
+_GLOBAL(_rest32gpr_25)
+ lwz 25,-28(11)
+_GLOBAL(_restgpr_26)
+_GLOBAL(_rest32gpr_26)
+ lwz 26,-24(11)
+_GLOBAL(_restgpr_27)
+_GLOBAL(_rest32gpr_27)
+ lwz 27,-20(11)
+_GLOBAL(_restgpr_28)
+_GLOBAL(_rest32gpr_28)
+ lwz 28,-16(11)
+_GLOBAL(_restgpr_29)
+_GLOBAL(_rest32gpr_29)
+ lwz 29,-12(11)
+_GLOBAL(_restgpr_30)
+_GLOBAL(_rest32gpr_30)
+ lwz 30,-8(11)
+_GLOBAL(_restgpr_31)
+_GLOBAL(_rest32gpr_31)
+ lwz 31,-4(11)
+ blr
+
+/* Routines for restoring integer registers, called by the compiler. */
+/* Called with r11 pointing to the stack header word of the caller of the */
+/* function, just beyond the end of the integer restore area. */
+
+_GLOBAL(_restgpr_14_x)
+_GLOBAL(_rest32gpr_14_x)
+ lwz 14,-72(11) /* restore gp registers */
+_GLOBAL(_restgpr_15_x)
+_GLOBAL(_rest32gpr_15_x)
+ lwz 15,-68(11)
+_GLOBAL(_restgpr_16_x)
+_GLOBAL(_rest32gpr_16_x)
+ lwz 16,-64(11)
+_GLOBAL(_restgpr_17_x)
+_GLOBAL(_rest32gpr_17_x)
+ lwz 17,-60(11)
+_GLOBAL(_restgpr_18_x)
+_GLOBAL(_rest32gpr_18_x)
+ lwz 18,-56(11)
+_GLOBAL(_restgpr_19_x)
+_GLOBAL(_rest32gpr_19_x)
+ lwz 19,-52(11)
+_GLOBAL(_restgpr_20_x)
+_GLOBAL(_rest32gpr_20_x)
+ lwz 20,-48(11)
+_GLOBAL(_restgpr_21_x)
+_GLOBAL(_rest32gpr_21_x)
+ lwz 21,-44(11)
+_GLOBAL(_restgpr_22_x)
+_GLOBAL(_rest32gpr_22_x)
+ lwz 22,-40(11)
+_GLOBAL(_restgpr_23_x)
+_GLOBAL(_rest32gpr_23_x)
+ lwz 23,-36(11)
+_GLOBAL(_restgpr_24_x)
+_GLOBAL(_rest32gpr_24_x)
+ lwz 24,-32(11)
+_GLOBAL(_restgpr_25_x)
+_GLOBAL(_rest32gpr_25_x)
+ lwz 25,-28(11)
+_GLOBAL(_restgpr_26_x)
+_GLOBAL(_rest32gpr_26_x)
+ lwz 26,-24(11)
+_GLOBAL(_restgpr_27_x)
+_GLOBAL(_rest32gpr_27_x)
+ lwz 27,-20(11)
+_GLOBAL(_restgpr_28_x)
+_GLOBAL(_rest32gpr_28_x)
+ lwz 28,-16(11)
+_GLOBAL(_restgpr_29_x)
+_GLOBAL(_rest32gpr_29_x)
+ lwz 29,-12(11)
+_GLOBAL(_restgpr_30_x)
+_GLOBAL(_rest32gpr_30_x)
+ lwz 30,-8(11)
+_GLOBAL(_restgpr_31_x)
+_GLOBAL(_rest32gpr_31_x)
+ lwz 0,4(11)
+ lwz 31,-4(11)
+ mtlr 0
+ mr 1,11
+ blr
+
diff --git a/arch/powerpc/lib/extable.c b/arch/powerpc/lib/extable.c
new file mode 100644
index 0000000000..e7adffa4e0
--- /dev/null
+++ b/arch/powerpc/lib/extable.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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.
+ *
+ */
+#include <common.h>
+
+/*
+ * The exception table consists of pairs of addresses: the first is the
+ * address of an instruction that is allowed to fault, and the second is
+ * the address at which the program should continue. No registers are
+ * modified, so it is entirely up to the continuation code to figure out
+ * what to do.
+ *
+ * All the routines below use bits of fixup code that are out of line
+ * with the main instruction path. This means when everything is well,
+ * we don't even have to jump over them. Further, they do not intrude
+ * on our cache or tlb entries.
+ */
+
+struct exception_table_entry
+{
+ unsigned long insn, fixup;
+};
+
+extern const struct exception_table_entry __start___ex_table[];
+extern const struct exception_table_entry __stop___ex_table[];
+
+static inline unsigned long
+search_one_table(const struct exception_table_entry *first,
+ const struct exception_table_entry *last,
+ unsigned long value)
+{
+ while (first <= last) {
+ const struct exception_table_entry *mid;
+ long diff;
+
+ mid = (last - first) / 2 + first;
+ diff = mid->insn - value;
+ if (diff == 0)
+ return mid->fixup;
+ else if (diff < 0)
+ first = mid+1;
+ else
+ last = mid-1;
+ }
+ return 0;
+}
+
+int ex_tab_message = 1;
+
+unsigned long
+search_exception_table(unsigned long addr)
+{
+ unsigned long ret;
+
+ /* There is only the kernel to search. */
+ ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
+ if (ex_tab_message)
+ printf("Bus Fault @ 0x%08lx, fixup 0x%08lx\n", addr, ret);
+ if (ret) return ret;
+
+ return 0;
+}
diff --git a/arch/powerpc/lib/kgdb.c b/arch/powerpc/lib/kgdb.c
new file mode 100644
index 0000000000..bbe7a80d27
--- /dev/null
+++ b/arch/powerpc/lib/kgdb.c
@@ -0,0 +1,325 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <common.h>
+#include <command.h>
+
+#ifdef CONFIG_KGDB
+
+#include <kgdb.h>
+#include <asm/signal.h>
+#include <asm/processor.h>
+
+#define PC_REGNUM 64
+#define SP_REGNUM 1
+
+void breakinst(void);
+
+int
+kgdb_setjmp(long *buf)
+{
+ asm ("mflr 0; stw 0,0(%0);"
+ "stw 1,4(%0); stw 2,8(%0);"
+ "mfcr 0; stw 0,12(%0);"
+ "stmw 13,16(%0)"
+ : : "r" (buf));
+ /* XXX should save fp regs as well */
+ return 0;
+}
+
+void
+kgdb_longjmp(long *buf, int val)
+{
+ if (val == 0)
+ val = 1;
+ asm ("lmw 13,16(%0);"
+ "lwz 0,12(%0); mtcrf 0x38,0;"
+ "lwz 0,0(%0); lwz 1,4(%0); lwz 2,8(%0);"
+ "mtlr 0; mr 3,%1"
+ : : "r" (buf), "r" (val));
+}
+
+static inline unsigned long
+get_msr(void)
+{
+ unsigned long msr;
+ asm volatile("mfmsr %0" : "=r" (msr):);
+ return msr;
+}
+
+static inline void
+set_msr(unsigned long msr)
+{
+ asm volatile("mtmsr %0" : : "r" (msr));
+}
+
+/* Convert the SPARC hardware trap type code to a unix signal number. */
+/*
+ * This table contains the mapping between PowerPC hardware trap types, and
+ * signals, which are primarily what GDB understands.
+ */
+static struct hard_trap_info
+{
+ unsigned int tt; /* Trap type code for powerpc */
+ unsigned char signo; /* Signal that we map this trap into */
+} hard_trap_info[] = {
+ { 0x200, SIGSEGV }, /* machine check */
+ { 0x300, SIGSEGV }, /* address error (store) */
+ { 0x400, SIGBUS }, /* instruction bus error */
+ { 0x500, SIGINT }, /* interrupt */
+ { 0x600, SIGBUS }, /* alingment */
+ { 0x700, SIGTRAP }, /* breakpoint trap */
+ { 0x800, SIGFPE }, /* fpu unavail */
+ { 0x900, SIGALRM }, /* decrementer */
+ { 0xa00, SIGILL }, /* reserved */
+ { 0xb00, SIGILL }, /* reserved */
+ { 0xc00, SIGCHLD }, /* syscall */
+ { 0xd00, SIGTRAP }, /* single-step/watch */
+ { 0xe00, SIGFPE }, /* fp assist */
+ { 0, 0} /* Must be last */
+};
+
+static int
+computeSignal(unsigned int tt)
+{
+ struct hard_trap_info *ht;
+
+ for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+ if (ht->tt == tt)
+ return ht->signo;
+
+ return SIGHUP; /* default for things we don't know about */
+}
+
+void
+kgdb_enter(struct pt_regs *regs, kgdb_data *kdp)
+{
+ unsigned long msr;
+
+ kdp->private[0] = msr = get_msr();
+ set_msr(msr & ~MSR_EE); /* disable interrupts */
+
+ if (regs->nip == (unsigned long)breakinst) {
+ /* Skip over breakpoint trap insn */
+ regs->nip += 4;
+ }
+ regs->msr &= ~MSR_SE;
+
+ /* reply to host that an exception has occurred */
+ kdp->sigval = computeSignal(regs->trap);
+
+ kdp->nregs = 2;
+
+ kdp->regs[0].num = PC_REGNUM;
+ kdp->regs[0].val = regs->nip;
+
+ kdp->regs[1].num = SP_REGNUM;
+ kdp->regs[1].val = regs->gpr[SP_REGNUM];
+}
+
+void
+kgdb_exit(struct pt_regs *regs, kgdb_data *kdp)
+{
+ unsigned long msr = kdp->private[0];
+
+ if (kdp->extype & KGDBEXIT_WITHADDR)
+ regs->nip = kdp->exaddr;
+
+ switch (kdp->extype & KGDBEXIT_TYPEMASK) {
+
+ case KGDBEXIT_KILL:
+ case KGDBEXIT_CONTINUE:
+ set_msr(msr);
+ break;
+
+ case KGDBEXIT_SINGLE:
+ regs->msr |= MSR_SE;
+ break;
+ }
+}
+
+int
+kgdb_trap(struct pt_regs *regs)
+{
+ return (regs->trap);
+}
+
+/* return the value of the CPU registers.
+ * some of them are non-PowerPC names :(
+ * they are stored in gdb like:
+ * struct {
+ * u32 gpr[32];
+ * f64 fpr[32];
+ * u32 pc, ps, cnd, lr; (ps=msr)
+ * u32 cnt, xer, mq;
+ * }
+ */
+
+#define SPACE_REQUIRED ((32*4)+(32*8)+(6*4))
+
+#ifdef CONFIG_8260
+/* store floating double indexed */
+#define STFDI(n,p) __asm__ __volatile__ ("stfd " #n ",%0" : "=o"(p[2*n]))
+/* store floating double multiple */
+#define STFDM(p) { STFDI( 0,p); STFDI( 1,p); STFDI( 2,p); STFDI( 3,p); \
+ STFDI( 4,p); STFDI( 5,p); STFDI( 6,p); STFDI( 7,p); \
+ STFDI( 8,p); STFDI( 9,p); STFDI(10,p); STFDI(11,p); \
+ STFDI(12,p); STFDI(13,p); STFDI(14,p); STFDI(15,p); \
+ STFDI(16,p); STFDI(17,p); STFDI(18,p); STFDI(19,p); \
+ STFDI(20,p); STFDI(21,p); STFDI(22,p); STFDI(23,p); \
+ STFDI(24,p); STFDI(25,p); STFDI(26,p); STFDI(27,p); \
+ STFDI(28,p); STFDI(29,p); STFDI(30,p); STFDI(31,p); }
+#endif
+
+int
+kgdb_getregs(struct pt_regs *regs, char *buf, int max)
+{
+ int i;
+ unsigned long *ptr = (unsigned long *)buf;
+
+ if (max < SPACE_REQUIRED)
+ kgdb_error(KGDBERR_NOSPACE);
+
+ if ((unsigned long)ptr & 3)
+ kgdb_error(KGDBERR_ALIGNFAULT);
+
+ /* General Purpose Regs */
+ for (i = 0; i < 32; i++)
+ *ptr++ = regs->gpr[i];
+
+ /* Floating Point Regs */
+#ifdef CONFIG_8260
+ STFDM(ptr);
+ ptr += 32*2;
+#else
+ for (i = 0; i < 32; i++) {
+ *ptr++ = 0;
+ *ptr++ = 0;
+ }
+#endif
+
+ /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
+ *ptr++ = regs->nip;
+ *ptr++ = regs->msr;
+ *ptr++ = regs->ccr;
+ *ptr++ = regs->link;
+ *ptr++ = regs->ctr;
+ *ptr++ = regs->xer;
+
+ return (SPACE_REQUIRED);
+}
+
+/* set the value of the CPU registers */
+
+#ifdef CONFIG_8260
+/* load floating double */
+#define LFD(n,v) __asm__ __volatile__ ("lfd " #n ",%0" :: "o"(v))
+/* load floating double indexed */
+#define LFDI(n,p) __asm__ __volatile__ ("lfd " #n ",%0" :: "o"((p)[2*n]))
+/* load floating double multiple */
+#define LFDM(p) { LFDI( 0,p); LFDI( 1,p); LFDI( 2,p); LFDI( 3,p); \
+ LFDI( 4,p); LFDI( 5,p); LFDI( 6,p); LFDI( 7,p); \
+ LFDI( 8,p); LFDI( 9,p); LFDI(10,p); LFDI(11,p); \
+ LFDI(12,p); LFDI(13,p); LFDI(14,p); LFDI(15,p); \
+ LFDI(16,p); LFDI(17,p); LFDI(18,p); LFDI(19,p); \
+ LFDI(20,p); LFDI(21,p); LFDI(22,p); LFDI(23,p); \
+ LFDI(24,p); LFDI(25,p); LFDI(26,p); LFDI(27,p); \
+ LFDI(28,p); LFDI(29,p); LFDI(30,p); LFDI(31,p); }
+#endif
+
+void
+kgdb_putreg(struct pt_regs *regs, int regno, char *buf, int length)
+{
+ unsigned long *ptr = (unsigned long *)buf;
+
+ if (regno < 0 || regno >= 70)
+ kgdb_error(KGDBERR_BADPARAMS);
+ else if (regno >= 32 && regno < 64) {
+ if (length < 8)
+ kgdb_error(KGDBERR_NOSPACE);
+ }
+ else {
+ if (length < 4)
+ kgdb_error(KGDBERR_NOSPACE);
+ }
+
+ if ((unsigned long)ptr & 3)
+ kgdb_error(KGDBERR_ALIGNFAULT);
+
+ if (regno >= 0 && regno < 32)
+ regs->gpr[regno] = *ptr;
+ else switch (regno) {
+
+#ifdef CONFIG_8260
+#define caseF(n) \
+ case (n) + 32: LFD(n, *ptr); break;
+
+caseF( 0) caseF( 1) caseF( 2) caseF( 3) caseF( 4) caseF( 5) caseF( 6) caseF( 7)
+caseF( 8) caseF( 9) caseF(10) caseF(11) caseF(12) caseF(13) caseF(14) caseF(15)
+caseF(16) caseF(17) caseF(18) caseF(19) caseF(20) caseF(21) caseF(22) caseF(23)
+caseF(24) caseF(25) caseF(26) caseF(27) caseF(28) caseF(29) caseF(30) caseF(31)
+
+#undef caseF
+#endif
+
+ case 64: regs->nip = *ptr; break;
+ case 65: regs->msr = *ptr; break;
+ case 66: regs->ccr = *ptr; break;
+ case 67: regs->link = *ptr; break;
+ case 68: regs->ctr = *ptr; break;
+ case 69: regs->ctr = *ptr; break;
+
+ default:
+ kgdb_error(KGDBERR_BADPARAMS);
+ }
+}
+
+void
+kgdb_putregs(struct pt_regs *regs, char *buf, int length)
+{
+ int i;
+ unsigned long *ptr = (unsigned long *)buf;
+
+ if (length < SPACE_REQUIRED)
+ kgdb_error(KGDBERR_NOSPACE);
+
+ if ((unsigned long)ptr & 3)
+ kgdb_error(KGDBERR_ALIGNFAULT);
+
+ /*
+ * If the stack pointer has moved, you should pray.
+ * (cause only god can help you).
+ */
+
+ /* General Purpose Regs */
+ for (i = 0; i < 32; i++)
+ regs->gpr[i] = *ptr++;
+
+ /* Floating Point Regs */
+#ifdef CONFIG_8260
+ LFDM(ptr);
+#endif
+ ptr += 32*2;
+
+ /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
+ regs->nip = *ptr++;
+ regs->msr = *ptr++;
+ regs->ccr = *ptr++;
+ regs->link = *ptr++;
+ regs->ctr = *ptr++;
+ regs->xer = *ptr++;
+}
+
+/* This function will generate a breakpoint exception. It is used at the
+ beginning of a program to sync up with a debugger and can be used
+ otherwise as a quick means to stop program execution and "break" into
+ the debugger. */
+
+void
+kgdb_breakpoint(int argc, char *argv[])
+{
+ asm(" .globl breakinst\n\
+ breakinst: .long 0x7d821008\n\
+ ");
+}
+
+#endif /* CFG_CMD_KGDB */
diff --git a/arch/powerpc/lib/misc.S b/arch/powerpc/lib/misc.S
new file mode 100644
index 0000000000..024d26ed58
--- /dev/null
+++ b/arch/powerpc/lib/misc.S
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <asm/ppc_asm.tmpl>
+#include <linux/errno.h>
+
+ .globl __ashrdi3
+__ashrdi3:
+ subfic r6,r5,32
+ srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
+ addi r7,r5,32 # could be xori, or addi with -32
+ slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
+ rlwinm r8,r7,0,32 # t3 = (count < 32) ? 32 : 0
+ sraw r7,r3,r7 # t2 = MSW >> (count-32)
+ or r4,r4,r6 # LSW |= t1
+ slw r7,r7,r8 # t2 = (count < 32) ? 0 : t2
+ sraw r3,r3,r5 # MSW = MSW >> count
+ or r4,r4,r7 # LSW |= t2
+ blr
+
+ .globl __ashldi3
+__ashldi3:
+ subfic r6,r5,32
+ slw r3,r3,r5 # MSW = count > 31 ? 0 : MSW << count
+ addi r7,r5,32 # could be xori, or addi with -32
+ srw r6,r4,r6 # t1 = count > 31 ? 0 : LSW >> (32-count)
+ slw r7,r4,r7 # t2 = count < 32 ? 0 : LSW << (count-32)
+ or r3,r3,r6 # MSW |= t1
+ slw r4,r4,r5 # LSW = LSW << count
+ or r3,r3,r7 # MSW |= t2
+ blr
+
+ .globl __lshrdi3
+__lshrdi3:
+ subfic r6,r5,32
+ srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
+ addi r7,r5,32 # could be xori, or addi with -32
+ slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
+ srw r7,r3,r7 # t2 = count < 32 ? 0 : MSW >> (count-32)
+ or r4,r4,r6 # LSW |= t1
+ srw r3,r3,r5 # MSW = MSW >> count
+ or r4,r4,r7 # LSW |= t2
+ blr
diff --git a/arch/powerpc/lib/module.c b/arch/powerpc/lib/module.c
new file mode 100644
index 0000000000..9ec6095571
--- /dev/null
+++ b/arch/powerpc/lib/module.c
@@ -0,0 +1,294 @@
+/* Kernel module help for PPC.
+ Copyright (C) 2001 Rusty Russell.
+
+ 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.
+
+*/
+
+#define DEBUG
+
+#include <common.h>
+#include <elf.h>
+#include <module.h>
+#include <malloc.h>
+#include <errno.h>
+
+//#include "setup.h"
+
+//LIST_HEAD(module_bug_list);
+
+/* Count how many different relocations (different symbol, different
+ addend) */
+static unsigned int count_relocs(const Elf32_Rela *rela, unsigned int num)
+{
+ unsigned int i, j, ret = 0;
+
+ /* Sure, this is order(n^2), but it's usually short, and not
+ time critical */
+ for (i = 0; i < num; i++) {
+ for (j = 0; j < i; j++) {
+ /* If this addend appeared before, it's
+ already been counted */
+ if (ELF32_R_SYM(rela[i].r_info)
+ == ELF32_R_SYM(rela[j].r_info)
+ && rela[i].r_addend == rela[j].r_addend)
+ break;
+ }
+ if (j == i) ret++;
+ }
+ return ret;
+}
+
+#if 0
+/* Get the potential trampolines size required of the init and
+ non-init sections */
+static unsigned long get_plt_size(const Elf32_Ehdr *hdr,
+ const Elf32_Shdr *sechdrs,
+ const char *secstrings,
+ int is_init)
+{
+ unsigned long ret = 0;
+ unsigned i;
+
+ /* Everything marked ALLOC (this includes the exported
+ symbols) */
+ for (i = 1; i < hdr->e_shnum; i++) {
+ /* If it's called *.init*, and we're not init, we're
+ not interested */
+ if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0)
+ != is_init)
+ continue;
+
+ /* We don't want to look at debug sections. */
+ if (strstr(secstrings + sechdrs[i].sh_name, ".debug") != 0)
+ continue;
+
+ if (sechdrs[i].sh_type == SHT_RELA) {
+ debug("Found relocations in section %u\n", i);
+ debug("Ptr: %p. Number: %u\n",
+ (void *)hdr + sechdrs[i].sh_offset,
+ sechdrs[i].sh_size / sizeof(Elf32_Rela));
+ ret += count_relocs((void *)hdr
+ + sechdrs[i].sh_offset,
+ sechdrs[i].sh_size
+ / sizeof(Elf32_Rela))
+ * sizeof(struct ppc_plt_entry);
+ }
+ }
+
+ return ret;
+}
+#endif
+#if 0
+int module_frob_arch_sections(Elf32_Ehdr *hdr,
+ Elf32_Shdr *sechdrs,
+ char *secstrings,
+ struct module *me)
+{
+ unsigned int i;
+
+ /* Find .plt and .init.plt sections */
+ for (i = 0; i < hdr->e_shnum; i++) {
+ if (strcmp(secstrings + sechdrs[i].sh_name, ".init.plt") == 0)
+ me->arch.init_plt_section = i;
+ else if (strcmp(secstrings + sechdrs[i].sh_name, ".plt") == 0)
+ me->arch.core_plt_section = i;
+ }
+ if (!me->arch.core_plt_section || !me->arch.init_plt_section) {
+ printf("Module doesn't contain .plt or .init.plt sections.\n");
+ return -ENOEXEC;
+ }
+
+ /* Override their sizes */
+ sechdrs[me->arch.core_plt_section].sh_size
+ = get_plt_size(hdr, sechdrs, secstrings, 0);
+ sechdrs[me->arch.init_plt_section].sh_size
+ = get_plt_size(hdr, sechdrs, secstrings, 1);
+ return 0;
+}
+#endif
+
+int apply_relocate(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *module)
+{
+ printf("%s: Non-ADD RELOCATION unsupported\n",
+ module->name);
+ return -ENOEXEC;
+}
+
+static inline int entry_matches(struct ppc_plt_entry *entry, Elf32_Addr val)
+{
+ if (entry->jump[0] == 0x3d600000 + ((val + 0x8000) >> 16)
+ && entry->jump[1] == 0x396b0000 + (val & 0xffff))
+ return 1;
+ return 0;
+}
+
+/* Set up a trampoline in the PLT to bounce us to the distant function */
+static uint32_t do_plt_call(void *location,
+ Elf32_Addr val,
+ Elf32_Shdr *sechdrs,
+ struct module *mod)
+{
+ struct ppc_plt_entry *entry;
+
+ debug("Doing plt for call to 0x%x at 0x%x\n", val, (unsigned int)location);
+ /* Init, or core PLT? */
+ if (location >= mod->module_core
+ && location < mod->module_core + mod->core_size)
+ entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr;
+ else
+ entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr;
+
+ /* Find this entry, or if that fails, the next avail. entry */
+ while (entry->jump[0]) {
+ if (entry_matches(entry, val)) return (uint32_t)entry;
+ entry++;
+ }
+
+ /* Stolen from Paul Mackerras as well... */
+ entry->jump[0] = 0x3d600000+((val+0x8000)>>16); /* lis r11,sym@ha */
+ entry->jump[1] = 0x396b0000 + (val&0xffff); /* addi r11,r11,sym@l*/
+ entry->jump[2] = 0x7d6903a6; /* mtctr r11 */
+ entry->jump[3] = 0x4e800420; /* bctr */
+
+ debug("Initialized plt for 0x%x at %p\n", val, entry);
+ return (uint32_t)entry;
+}
+
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *module)
+{
+ unsigned int i;
+ Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
+ Elf32_Sym *sym;
+ uint32_t *location;
+ uint32_t value;
+
+ debug("Applying ADD relocate section %u to %u\n", relsec,
+ sechdrs[relsec].sh_info);
+ for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
+ /* This is where to make the change */
+ location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+ + rela[i].r_offset;
+ /* This is the symbol it is referring to. Note that all
+ undefined symbols have been resolved. */
+ sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+ + ELF32_R_SYM(rela[i].r_info);
+ /* `Everything is relative'. */
+ value = sym->st_value + rela[i].r_addend;
+
+ switch (ELF32_R_TYPE(rela[i].r_info)) {
+ case R_PPC_ADDR32:
+ /* Simply set it */
+ *(uint32_t *)location = value;
+ break;
+
+ case R_PPC_ADDR16_LO:
+ /* Low half of the symbol */
+ *(uint16_t *)location = value;
+ break;
+
+ case R_PPC_ADDR16_HI:
+ /* Higher half of the symbol */
+ *(uint16_t *)location = (value >> 16);
+ break;
+
+ case R_PPC_ADDR16_HA:
+ /* Sign-adjusted lower 16 bits: PPC ELF ABI says:
+ (((x >> 16) + ((x & 0x8000) ? 1 : 0))) & 0xFFFF.
+ This is the same, only sane.
+ */
+ *(uint16_t *)location = (value + 0x8000) >> 16;
+ break;
+
+ case R_PPC_REL24:
+ if ((int)(value - (uint32_t)location) < -0x02000000
+ || (int)(value - (uint32_t)location) >= 0x02000000)
+ value = do_plt_call(location, value,
+ sechdrs, module);
+
+ /* Only replace bits 2 through 26 */
+ debug("REL24 value = %08X. location = %08X\n",
+ value, (uint32_t)location);
+ debug("Location before: %08X.\n",
+ *(uint32_t *)location);
+ *(uint32_t *)location
+ = (*(uint32_t *)location & ~0x03fffffc)
+ | ((value - (uint32_t)location)
+ & 0x03fffffc);
+ debug("Location after: %08X.\n",
+ *(uint32_t *)location);
+ debug("ie. jump to %08X+%08X = %08X\n",
+ *(uint32_t *)location & 0x03fffffc,
+ (uint32_t)location,
+ (*(uint32_t *)location & 0x03fffffc)
+ + (uint32_t)location);
+ break;
+
+ case R_PPC_REL32:
+ /* 32-bit relative jump. */
+ *(uint32_t *)location = value - (uint32_t)location;
+ break;
+
+ default:
+ printf("%s: unknown ADD relocation: %u\n",
+ module->name,
+ ELF32_R_TYPE(rela[i].r_info));
+ return -ENOEXEC;
+ }
+ }
+ return 0;
+}
+
+static const Elf_Shdr *find_section(const Elf_Ehdr *hdr,
+ const Elf_Shdr *sechdrs,
+ const char *name)
+{
+ char *secstrings;
+ unsigned int i;
+
+ secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+ for (i = 1; i < hdr->e_shnum; i++)
+ if (strcmp(secstrings+sechdrs[i].sh_name, name) == 0)
+ return &sechdrs[i];
+ return NULL;
+}
+
+#if 0
+int module_finalize(const Elf_Ehdr *hdr,
+ const Elf_Shdr *sechdrs,
+ struct module *me)
+{
+ const Elf_Shdr *sect;
+ int err;
+
+ err = module_bug_finalize(hdr, sechdrs, me);
+ if (err) /* never true, currently */
+ return err;
+
+ /* Apply feature fixups */
+ sect = find_section(hdr, sechdrs, "__ftr_fixup");
+ if (sect != NULL)
+ do_feature_fixups(cur_cpu_spec->cpu_features,
+ (void *)sect->sh_addr,
+ (void *)sect->sh_addr + sect->sh_size);
+
+ return 0;
+}
+#endif
+
diff --git a/arch/powerpc/lib/ppclinux.c b/arch/powerpc/lib/ppclinux.c
new file mode 100644
index 0000000000..9b8404962c
--- /dev/null
+++ b/arch/powerpc/lib/ppclinux.c
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#define DEBUG
+
+#include <common.h>
+#include <command.h>
+#include <image.h>
+#include <init.h>
+#include <malloc.h>
+#include <environment.h>
+#include <asm/bitops.h>
+#include <asm/processor.h>
+#include <boot.h>
+#include <bootm.h>
+#include <errno.h>
+#include <restart.h>
+#include <fs.h>
+
+static struct fdt_header *bootm_relocate_fdt(struct image_data *data,
+ struct fdt_header *fdt)
+{
+ void *os = (void *)data->os_address;
+ void *newfdt;
+
+ if (os < LINUX_TLB1_MAX_ADDR) {
+ /* The kernel is within the boot TLB mapping.
+ * Put the DTB above if there is no space
+ * below.
+ */
+ if (os < (void *)fdt->totalsize) {
+ os = (void *)PAGE_ALIGN((phys_addr_t)os +
+ data->os->header.ih_size);
+ os += fdt->totalsize;
+ if (os < LINUX_TLB1_MAX_ADDR)
+ os = LINUX_TLB1_MAX_ADDR;
+ }
+ }
+
+ if (os > LINUX_TLB1_MAX_ADDR) {
+ pr_crit("Unable to relocate DTB to Linux TLB\n");
+ return NULL;
+ }
+
+ newfdt = (void *)PAGE_ALIGN_DOWN((phys_addr_t)os - fdt->totalsize);
+ memcpy(newfdt, fdt, fdt->totalsize);
+ free(fdt);
+
+ pr_info("Relocating device tree to 0x%p\n", newfdt);
+ return newfdt;
+}
+
+static int do_bootm_linux(struct image_data *data)
+{
+ void (*kernel)(void *, void *, unsigned long,
+ unsigned long, unsigned long);
+ int ret;
+ struct fdt_header *fdt;
+
+ ret = bootm_load_os(data, data->os_address);
+ if (ret)
+ return ret;
+
+ fdt = of_get_fixed_tree(data->of_root_node);
+ if (!fdt) {
+ pr_err("bootm: No devicetree given.\n");
+ return -EINVAL;
+ }
+
+ if (data->dryrun)
+ return 0;
+
+ ret = of_overlay_load_firmware();
+ if (ret)
+ return ret;
+
+ /* Relocate the device tree if outside the initial
+ * Linux mapped TLB.
+ */
+ if (IS_ENABLED(CONFIG_MPC85xx)) {
+ if (((void *)fdt + fdt->totalsize) > LINUX_TLB1_MAX_ADDR) {
+ fdt = bootm_relocate_fdt(data, fdt);
+ if (!fdt)
+ goto error;
+ }
+ }
+
+ fdt_add_reserve_map(fdt);
+
+ kernel = (void *)(data->os_address + data->os_entry);
+
+ /*
+ * Linux Kernel Parameters (passing device tree):
+ * r3: ptr to OF flat tree, followed by the board info data
+ * r4: physical pointer to the kernel itself
+ * r5: NULL
+ * r6: NULL
+ * r7: NULL
+ */
+ kernel(fdt, kernel, 0, 0, 0);
+
+ restart_machine();
+
+error:
+ return -1;
+}
+
+static struct image_handler handler = {
+ .name = "PowerPC Linux",
+ .bootm = do_bootm_linux,
+ .filetype = filetype_uimage,
+ .ih_os = IH_OS_LINUX,
+};
+
+static int ppclinux_register_image_handler(void)
+{
+ return register_image_handler(&handler);
+}
+
+late_initcall(ppclinux_register_image_handler);
diff --git a/arch/powerpc/lib/ppcstring.S b/arch/powerpc/lib/ppcstring.S
new file mode 100644
index 0000000000..55f96cc9a4
--- /dev/null
+++ b/arch/powerpc/lib/ppcstring.S
@@ -0,0 +1,216 @@
+/*
+ * String handling functions for PowerPC.
+ *
+ * Copyright (C) 1996 Paul Mackerras.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <asm/ppc_asm.tmpl>
+#include <linux/errno.h>
+
+ .globl strcpy
+strcpy:
+ addi r5,r3,-1
+ addi r4,r4,-1
+1: lbzu r0,1(r4)
+ cmpwi 0,r0,0
+ stbu r0,1(r5)
+ bne 1b
+ blr
+
+ .globl strncpy
+strncpy:
+ cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+ addi r6,r3,-1
+ addi r4,r4,-1
+1: lbzu r0,1(r4)
+ cmpwi 0,r0,0
+ stbu r0,1(r6)
+ bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */
+ blr
+
+ .globl strcat
+strcat:
+ addi r5,r3,-1
+ addi r4,r4,-1
+1: lbzu r0,1(r5)
+ cmpwi 0,r0,0
+ bne 1b
+ addi r5,r5,-1
+1: lbzu r0,1(r4)
+ cmpwi 0,r0,0
+ stbu r0,1(r5)
+ bne 1b
+ blr
+
+ .globl strcmp
+strcmp:
+ addi r5,r3,-1
+ addi r4,r4,-1
+1: lbzu r3,1(r5)
+ cmpwi 1,r3,0
+ lbzu r0,1(r4)
+ subf. r3,r0,r3
+ beqlr 1
+ beq 1b
+ blr
+
+ .globl strlen
+strlen:
+ addi r4,r3,-1
+1: lbzu r0,1(r4)
+ cmpwi 0,r0,0
+ bne 1b
+ subf r3,r3,r4
+ blr
+
+ .globl memset
+memset:
+ rlwimi r4,r4,8,16,23
+ rlwimi r4,r4,16,0,15
+ addi r6,r3,-4
+ cmplwi 0,r5,4
+ blt 7f
+ stwu r4,4(r6)
+ beqlr
+ andi. r0,r6,3
+ add r5,r0,r5
+ subf r6,r0,r6
+ rlwinm r0,r5,32-2,2,31
+ mtctr r0
+ bdz 6f
+1: stwu r4,4(r6)
+ bdnz 1b
+6: andi. r5,r5,3
+7: cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+ addi r6,r6,3
+8: stbu r4,1(r6)
+ bdnz 8b
+ blr
+
+ .globl bcopy
+bcopy:
+ mr r6,r3
+ mr r3,r4
+ mr r4,r6
+ b memcpy
+
+ .globl memmove
+memmove:
+ cmplw 0,r3,r4
+ bgt backwards_memcpy
+ /* fall through */
+
+ .globl memcpy
+memcpy:
+ rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
+ addi r6,r3,-4
+ addi r4,r4,-4
+ beq 2f /* if less than 8 bytes to do */
+ andi. r0,r6,3 /* get dest word aligned */
+ mtctr r7
+ bne 5f
+1: lwz r7,4(r4)
+ lwzu r8,8(r4)
+ stw r7,4(r6)
+ stwu r8,8(r6)
+ bdnz 1b
+ andi. r5,r5,7
+2: cmplwi 0,r5,4
+ blt 3f
+ lwzu r0,4(r4)
+ addi r5,r5,-4
+ stwu r0,4(r6)
+3: cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+ addi r4,r4,3
+ addi r6,r6,3
+4: lbzu r0,1(r4)
+ stbu r0,1(r6)
+ bdnz 4b
+ blr
+5: subfic r0,r0,4
+ mtctr r0
+6: lbz r7,4(r4)
+ addi r4,r4,1
+ stb r7,4(r6)
+ addi r6,r6,1
+ bdnz 6b
+ subf r5,r0,r5
+ rlwinm. r7,r5,32-3,3,31
+ beq 2b
+ mtctr r7
+ b 1b
+
+ .globl backwards_memcpy
+backwards_memcpy:
+ rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
+ add r6,r3,r5
+ add r4,r4,r5
+ beq 2f
+ andi. r0,r6,3
+ mtctr r7
+ bne 5f
+1: lwz r7,-4(r4)
+ lwzu r8,-8(r4)
+ stw r7,-4(r6)
+ stwu r8,-8(r6)
+ bdnz 1b
+ andi. r5,r5,7
+2: cmplwi 0,r5,4
+ blt 3f
+ lwzu r0,-4(r4)
+ subi r5,r5,4
+ stwu r0,-4(r6)
+3: cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+4: lbzu r0,-1(r4)
+ stbu r0,-1(r6)
+ bdnz 4b
+ blr
+5: mtctr r0
+6: lbzu r7,-1(r4)
+ stbu r7,-1(r6)
+ bdnz 6b
+ subf r5,r0,r5
+ rlwinm. r7,r5,32-3,3,31
+ beq 2b
+ mtctr r7
+ b 1b
+
+ .globl memcmp
+memcmp:
+ cmpwi 0,r5,0
+ ble- 2f
+ mtctr r5
+ addi r6,r3,-1
+ addi r4,r4,-1
+1: lbzu r3,1(r6)
+ lbzu r0,1(r4)
+ subf. r3,r0,r3
+ bdnzt 2,1b
+ blr
+2: li r3,0
+ blr
+
+ .global memchr
+memchr:
+ cmpwi 0,r5,0
+ ble- 2f
+ mtctr r5
+ addi r3,r3,-1
+1: lbzu r0,1(r3)
+ cmpw 0,r0,r4
+ bdnzf 2,1b
+ beqlr
+2: li r3,0
+ blr
diff --git a/arch/powerpc/lib/reloc.S b/arch/powerpc/lib/reloc.S
new file mode 100644
index 0000000000..ad598e6f82
--- /dev/null
+++ b/arch/powerpc/lib/reloc.S
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2009 Wolfgang Denk <wd@denx.de>
+ *
+ * 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.
+ *
+ */
+
+#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/powerpc/lib/setjmp.S b/arch/powerpc/lib/setjmp.S
new file mode 100644
index 0000000000..021a57eebc
--- /dev/null
+++ b/arch/powerpc/lib/setjmp.S
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * This is a simple version of setjmp and longjmp for the PowerPC.
+ * Ian Lance Taylor, Cygnus Support, 9 Feb 1994.
+ */
+
+#include <linux/linkage.h>
+#include <asm/ppc_asm.tmpl>
+
+ENTRY(setjmp)
+ addi r3,r3,7 # align to 8 byte boundary
+ rlwinm r3,r3,0,0,28
+ stw r1,0(r3) # offset 0
+ stwu r2,4(r3) # offset 4
+ stwu r13,4(r3) # offset 8
+ stwu r14,4(r3) # offset 12
+ stwu r15,4(r3) # offset 16
+ stwu r16,4(r3) # offset 20
+ stwu r17,4(r3) # offset 24
+ stwu r18,4(r3) # offset 28
+ stwu r19,4(r3) # offset 32
+ stwu r20,4(r3) # offset 36
+ stwu r21,4(r3) # offset 40
+ stwu r22,4(r3) # offset 44
+ stwu r23,4(r3) # offset 48
+ stwu r24,4(r3) # offset 52
+ stwu r25,4(r3) # offset 56
+ stwu r26,4(r3) # offset 60
+ stwu r27,4(r3) # offset 64
+ stwu r28,4(r3) # offset 68
+ stwu r29,4(r3) # offset 72
+ stwu r30,4(r3) # offset 76
+ stwu r31,4(r3) # offset 80
+ mflr r4
+ stwu r4,4(r3) # offset 84
+ mfcr r4
+ stwu r4,4(r3) # offset 88
+
+ li r3,0
+ blr
+END(setjmp)
+
+ENTRY(longjmp)
+ addi r3,r3,7 # align to 8 byte boundary
+ rlwinm r3,r3,0,0,28
+ lwz r1,0(r3) # offset 0
+ lwzu r2,4(r3) # offset 4
+ lwzu r13,4(r3) # offset 8
+ lwzu r14,4(r3) # offset 12
+ lwzu r15,4(r3) # offset 16
+ lwzu r16,4(r3) # offset 20
+ lwzu r17,4(r3) # offset 24
+ lwzu r18,4(r3) # offset 28
+ lwzu r19,4(r3) # offset 32
+ lwzu r20,4(r3) # offset 36
+ lwzu r21,4(r3) # offset 40
+ lwzu r22,4(r3) # offset 44
+ lwzu r23,4(r3) # offset 48
+ lwzu r24,4(r3) # offset 52
+ lwzu r25,4(r3) # offset 56
+ lwzu r26,4(r3) # offset 60
+ lwzu r27,4(r3) # offset 64
+ lwzu r28,4(r3) # offset 68
+ lwzu r29,4(r3) # offset 72
+ lwzu r30,4(r3) # offset 76
+ lwzu r31,4(r3) # offset 80
+ lwzu r5,4(r3) # offset 84
+ mtlr r5
+ lwzu r5,4(r3) # offset 88
+ mtcrf 255,r5
+
+ mr. r3,r4
+ bclr+ 4,2
+ li r3,1
+ blr
+END(longjmp)
+
+ENTRY(initjmp)
+ addi r3,r3,7 # align to 8 byte boundary
+ rlwinm r3,r3,0,0,28
+ stw r5,0(r3) # offset 0
+ stwu r4,88(r3) # offset 88
+ li r3,0
+ blr
+END(initjmp)
diff --git a/arch/powerpc/lib/ticks.S b/arch/powerpc/lib/ticks.S
new file mode 100644
index 0000000000..e923f17b63
--- /dev/null
+++ b/arch/powerpc/lib/ticks.S
@@ -0,0 +1,35 @@
+/*
+ * (C) Copyright 2000, 2001
+ * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com.
+ * base on code by
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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.
+ *
+ */
+
+#include <asm/ppc_asm.tmpl>
+#include <asm/ppc_defs.h>
+#include <config.h>
+
+/*
+ * unsigned long long get_ticks(void);
+ *
+ * read timebase as "long long"
+ */
+ .globl get_ticks
+get_ticks:
+1: mftbu r3
+ mftb r4
+ mftbu r5
+ cmp 0,r3,r5
+ bne 1b
+ blr
diff --git a/arch/powerpc/mach-mpc5xxx/Kconfig b/arch/powerpc/mach-mpc5xxx/Kconfig
new file mode 100644
index 0000000000..e78c2fa350
--- /dev/null
+++ b/arch/powerpc/mach-mpc5xxx/Kconfig
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+if ARCH_MPC5XXX
+
+config ARCH_TEXT_BASE
+ hex
+ default 0x00000000 if RELOCATABLE
+ default 0x01000000 if MACH_PHYCORE_MPC5200B_TINY
+
+config HAS_REGINFO
+ bool
+ default y if ARCH_MPC5200
+
+choice
+ prompt "Select your board"
+
+config MACH_PHYCORE_MPC5200B_TINY
+ bool "Phycore mpc5200b tiny"
+ help
+ Say Y here if you are using the Phytec Phycore MPC5200B Tiny
+ board aka pcm030.
+endchoice
+
+config MPC5200
+ bool
+ depends on MACH_PHYCORE_MPC5200B_TINY
+ default y
+
+config ARCH_MPC5200
+ bool
+ depends on MACH_PHYCORE_MPC5200B_TINY
+ default y
+
+config MPC5xxx
+ bool
+ depends on MACH_PHYCORE_MPC5200B_TINY
+ default y
+
+endif
diff --git a/arch/powerpc/mach-mpc5xxx/Makefile b/arch/powerpc/mach-mpc5xxx/Makefile
new file mode 100644
index 0000000000..9fc45c08bb
--- /dev/null
+++ b/arch/powerpc/mach-mpc5xxx/Makefile
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-y += cpu.o
+obj-y += cpu_init.o
+obj-y += loadtask.o
+obj-y += speed.o
+obj-y += traps.o
+obj-y += time.o
+extra-y += start.o
+obj-$(CONFIG_MPC5200) += firmware_sc_task_bestcomm.impl.o
+obj-$(CONFIG_REGINFO) += reginfo.o
diff --git a/arch/powerpc/mach-mpc5xxx/cpu.c b/arch/powerpc/mach-mpc5xxx/cpu.c
new file mode 100644
index 0000000000..9c99bdd26f
--- /dev/null
+++ b/arch/powerpc/mach-mpc5xxx/cpu.c
@@ -0,0 +1,234 @@
+/*
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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.
+ *
+ */
+
+/*
+ * CPU specific code for the MPC5xxx CPUs
+ */
+
+#include <common.h>
+#include <command.h>
+#include <mach/mpc5xxx.h>
+#include <asm/processor.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <init.h>
+#include <types.h>
+#include <errno.h>
+#include <of.h>
+#include <restart.h>
+#include <mach/clock.h>
+#include <asm-generic/memory_layout.h>
+#include <memory.h>
+
+/* ------------------------------------------------------------------------- */
+
+static int mpc5xxx_reserve_region(void)
+{
+ struct resource *r;
+
+ /* keep this in sync with the assembler routines setting up the stack */
+ r = request_sdram_region("stack", _text_base - STACK_SIZE, STACK_SIZE);
+ if (r == NULL) {
+ pr_err("Failed to request stack region at: 0x%08lx/0x%08lx\n",
+ _text_base - STACK_SIZE, _text_base - 1);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+coredevice_initcall(mpc5xxx_reserve_region);
+
+static void __noreturn mpc5xxx_restart_soc(struct restart_handler *rst)
+{
+ ulong msr;
+ /* Interrupts and MMU off */
+ __asm__ __volatile__ ("mfmsr %0":"=r" (msr):);
+
+ msr &= ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR);
+ __asm__ __volatile__ ("mtmsr %0"::"r" (msr));
+
+ /* Charge the watchdog timer */
+ *(vu_long *)(MPC5XXX_GPT0_COUNTER) = 0x0001000f;
+ *(vu_long *)(MPC5XXX_GPT0_ENABLE) = 0x9004; /* wden|ce|timer_ms */
+ hang();
+}
+
+static int restart_register_feature(void)
+{
+ return restart_handler_register_fn("soc-wdt", mpc5xxx_restart_soc);
+}
+coredevice_initcall(restart_register_feature);
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef CONFIG_OFTREE
+static int of_mpc5200_fixup(struct device_node *root, void *unused)
+{
+ struct device_node *node;
+
+ int div = in_8((void*)CFG_MBAR + 0x204) & 0x0020 ? 8 : 4;
+
+ node = of_find_node_by_path_from(root, "/cpus/PowerPC,5200@0");
+ if (!node) {
+ pr_err("Cannot find node '/cpus/PowerPC,5200@0' for proper CPU frequency fixup\n");
+ return -EINVAL;
+ }
+
+ of_property_write_u32(node, "timebase-frequency", get_timebase_clock());
+ of_property_write_u32(node, "bus-frequency", get_bus_clock());
+ of_property_write_u32(node, "clock-frequency", get_cpu_clock());
+
+ node = of_find_node_by_path_from(root, "/soc5200@f0000000");
+ if (!node) {
+ pr_err("Cannot find node '/soc5200@f0000000' for proper SOC frequency fixup\n");
+ return -EINVAL;
+ }
+
+ of_property_write_u32(node, "bus-frequency", get_ipb_clock());
+ of_property_write_u32(node, "system-frequency", get_bus_clock() * div);
+
+ return 0;
+}
+
+static int of_register_mpc5200_fixup(void)
+{
+ return of_register_fixup(of_mpc5200_fixup, NULL);
+}
+late_initcall(of_register_mpc5200_fixup);
+#endif
+
+unsigned long mpc5200_get_sdram_size(unsigned int cs)
+{
+ unsigned long size;
+
+ if (cs > 1)
+ return 0;
+
+ /* retrieve size of memory connected to SDRAM CS0 */
+ size = *(vu_long *)(MPC5XXX_SDRAM_CS0CFG + (cs * 4)) & 0xFF;
+ if (size >= 0x13)
+ size = (1 << (size - 0x13)) << 20;
+ else
+ size = 0;
+
+ return size;
+}
+
+int mpc5200_setup_bus_clocks(unsigned int ipbdiv, unsigned long pcidiv)
+{
+ u32 cdmcfg = *(vu_long *)MPC5XXX_CDM_CFG;
+
+ cdmcfg &= ~0x103;
+
+ switch (ipbdiv) {
+ case 1:
+ break;
+ case 2:
+ cdmcfg |= 0x100;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (pcidiv) {
+ case 1:
+ if (ipbdiv == 2)
+ return -EINVAL;
+ break;
+ case 2:
+ if (ipbdiv == 1)
+ cdmcfg |= 0x1; /* ipb / 2 */
+ break;
+ case 4:
+ cdmcfg |= 0x2; /* xlb / 4 */
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *(vu_long *)MPC5XXX_CDM_CFG = cdmcfg;
+
+ return 0;
+}
+
+struct mpc5200_cs {
+ void *start;
+ void *stop;
+ void *cfg;
+ unsigned int addecr;
+};
+
+static struct mpc5200_cs chipselects[] = {
+ {
+ .start = (void *)MPC5XXX_CS0_START,
+ .stop = (void *)MPC5XXX_CS0_STOP,
+ .cfg = (void *)MPC5XXX_CS0_CFG,
+ .addecr = 1 << 16,
+ }, {
+ .start = (void *)MPC5XXX_CS1_START,
+ .stop = (void *)MPC5XXX_CS1_STOP,
+ .cfg = (void *)MPC5XXX_CS1_CFG,
+ .addecr = 1 << 17,
+ }, {
+ .start = (void *)MPC5XXX_CS2_START,
+ .stop = (void *)MPC5XXX_CS2_STOP,
+ .cfg = (void *)MPC5XXX_CS2_CFG,
+ .addecr = 1 << 18,
+ }, {
+ .start = (void *)MPC5XXX_CS3_START,
+ .stop = (void *)MPC5XXX_CS3_STOP,
+ .cfg = (void *)MPC5XXX_CS3_CFG,
+ .addecr = 1 << 19,
+ }, {
+ .start = (void *)MPC5XXX_CS4_START,
+ .stop = (void *)MPC5XXX_CS4_STOP,
+ .cfg = (void *)MPC5XXX_CS4_CFG,
+ .addecr = 1 << 20,
+ }, {
+ .start = (void *)MPC5XXX_CS5_START,
+ .stop = (void *)MPC5XXX_CS5_STOP,
+ .cfg = (void *)MPC5XXX_CS5_CFG,
+ .addecr = 1 << 21,
+ }, {
+ .start = (void *)MPC5XXX_CS6_START,
+ .stop = (void *)MPC5XXX_CS6_STOP,
+ .cfg = (void *)MPC5XXX_CS6_CFG,
+ .addecr = 1 << 26,
+ }, {
+ .start = (void *)MPC5XXX_CS7_START,
+ .stop = (void *)MPC5XXX_CS7_STOP,
+ .cfg = (void *)MPC5XXX_CS7_CFG,
+ .addecr = 1 << 27,
+ }, {
+ .start = (void *)MPC5XXX_BOOTCS_START,
+ .stop = (void *)MPC5XXX_BOOTCS_STOP,
+ .cfg = (void *)MPC5XXX_CS0_CFG,
+ .addecr = 1 << 25,
+ },
+};
+
+void mpc5200_setup_cs(int cs, unsigned long start, unsigned long size, u32 cfg)
+{
+ u32 addecr;
+
+ out_be32(chipselects[cs].start, START_REG(start));
+ out_be32(chipselects[cs].stop, STOP_REG(start, size));
+ out_be32(chipselects[cs].cfg, cfg);
+
+ addecr = in_be32((void *)MPC5XXX_ADDECR);
+ addecr |= chipselects[cs].addecr | 1;
+ out_be32((void *)MPC5XXX_ADDECR, addecr);
+}
diff --git a/arch/powerpc/mach-mpc5xxx/cpu_init.c b/arch/powerpc/mach-mpc5xxx/cpu_init.c
new file mode 100644
index 0000000000..949e49f871
--- /dev/null
+++ b/arch/powerpc/mach-mpc5xxx/cpu_init.c
@@ -0,0 +1,49 @@
+/*
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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.
+ *
+ */
+
+#include <common.h>
+#include <mach/mpc5xxx.h>
+#include <types.h>
+
+/*
+ * Breath some life into the CPU...
+ *
+ * initialize a bunch of registers.
+ */
+int cpu_init(void)
+{
+ /* enable timebase */
+ *(vu_long *)(MPC5XXX_XLBARB + 0x40) |= (1 << 13);
+
+ /* Enable snooping for RAM */
+ *(vu_long *)(MPC5XXX_XLBARB + 0x40) |= (1 << 15);
+ *(vu_long *)(MPC5XXX_XLBARB + 0x70) = 0 | 0x1d;
+
+ /* Configure the XLB Arbiter */
+ *(vu_long *)MPC5XXX_XLBARB_MPRIEN = 0xff;
+ *(vu_long *)MPC5XXX_XLBARB_MPRIVAL = 0x11111111;
+
+ /* mask all interrupts */
+ *(vu_long *)MPC5XXX_ICTL_PER_MASK = 0xffffff00;
+
+ *(vu_long *)MPC5XXX_ICTL_CRIT |= 0x0001ffff;
+ *(vu_long *)MPC5XXX_ICTL_EXT &= ~0x00000f00;
+ /* route critical ints to normal ints */
+ *(vu_long *)MPC5XXX_ICTL_EXT |= 0x00000001;
+
+ return 0;
+}
+
diff --git a/arch/powerpc/mach-mpc5xxx/firmware_sc_task_bestcomm.impl.S b/arch/powerpc/mach-mpc5xxx/firmware_sc_task_bestcomm.impl.S
new file mode 100644
index 0000000000..17213053d2
--- /dev/null
+++ b/arch/powerpc/mach-mpc5xxx/firmware_sc_task_bestcomm.impl.S
@@ -0,0 +1,363 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * Copyright (C) 2001, Software Center, Motorola China.
+ *
+ * This file contains microcode for the FEC controller of the MPC5200 CPU.
+ */
+
+/* sas/sccg, gas target */
+.section smartdmaInitData,"aw",@progbits /* Initialized data for task variables */
+.section smartdmaTaskTable,"aw",@progbits /* Task tables */
+.align 9
+
+.globl taskTable
+taskTable:
+
+.globl scEthernetRecv_Entry
+scEthernetRecv_Entry: /* Task 0 */
+.long scEthernetRecv_TDT - taskTable /* Task 0 Descriptor Table */
+.long scEthernetRecv_TDT - taskTable + 0x000000a4
+.long scEthernetRecv_VarTab - taskTable /* Task 0 Variable Table */
+.long scEthernetRecv_FDT - taskTable + 0x03 /* Task 0 Function Descriptor Table & Flags */
+.long 0x00000000
+.long 0x00000000
+.long scEthernetRecv_CSave - taskTable /* Task 0 context save space */
+.long 0xf0000000
+
+.globl scEthernetXmit_Entry
+scEthernetXmit_Entry: /* Task 1 */
+.long scEthernetXmit_TDT - taskTable /* Task 1 Descriptor Table */
+.long scEthernetXmit_TDT - taskTable + 0x000000d0
+.long scEthernetXmit_VarTab - taskTable /* Task 1 Variable Table */
+.long scEthernetXmit_FDT - taskTable + 0x03 /* Task 1 Function Descriptor Table & Flags */
+.long 0x00000000
+.long 0x00000000
+.long scEthernetXmit_CSave - taskTable /* Task 1 context save space */
+.long 0xf0000000
+
+
+.globl scEthernetRecv_TDT
+scEthernetRecv_TDT: /* Task 0 Descriptor Table */
+.long 0xc4c50000 /* 0000: LCDEXT: idx0 = var9 + var10; idx0 once var0; idx0 += inc0 */
+.long 0x84c5e000 /* 0004: LCD: idx1 = var9 + var11; ; idx1 += inc0 */
+.long 0x10001f08 /* 0008: DRD1A: var7 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x10000380 /* 000C: DRD1A: var0 = *idx0; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x00000f88 /* 0010: DRD1A: var3 = *idx1; FN=0 init=0 WS=0 RS=0 */
+.long 0x81980000 /* 0014: LCD: idx0 = var3; idx0 once var0; idx0 += inc0 */
+.long 0x10000780 /* 0018: DRD1A: var1 = *idx0; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x60000000 /* 001C: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long 0x010cf04c /* 0020: DRD2B1: var4 = EU3(); EU3(var1,var12) */
+.long 0x82180349 /* 0024: LCD: idx0 = var4; idx0 != var13; idx0 += inc1 */
+.long 0x81c68004 /* 0028: LCD: idx1 = var3 + var13 + 4; idx1 once var0; idx1 += inc0 */
+.long 0x70000000 /* 002C: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long 0x018cf04e /* 0030: DRD2B1: var6 = EU3(); EU3(var1,var14) */
+.long 0x70000000 /* 0034: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long 0x020cf04f /* 0038: DRD2B1: var8 = EU3(); EU3(var1,var15) */
+.long 0x00000b88 /* 003C: DRD1A: var2 = *idx1; FN=0 init=0 WS=0 RS=0 */
+.long 0x8000d184 /* 0040: LCDEXT: idx1 = 0xf0003184; ; */
+.long 0xc6990452 /* 0044: LCDEXT: idx2 = var13; idx2 < var17; idx2 += inc2 */
+.long 0x81486010 /* 0048: LCD: idx3 = var2 + var16; ; idx3 += inc2 */
+.long 0x006acf88 /* 004C: DRD1A: *idx3 = *idx1; FN=0 init=3 WS=1 RS=1 */
+.long 0x8000d184 /* 0050: LCDEXT: idx1 = 0xf0003184; ; */
+.long 0x86810492 /* 0054: LCD: idx2 = var13, idx3 = var2; idx2 < var18; idx2 += inc2, idx3 += inc2 */
+.long 0x006acf88 /* 0058: DRD1A: *idx3 = *idx1; FN=0 init=3 WS=1 RS=1 */
+.long 0x8000d184 /* 005C: LCDEXT: idx1 = 0xf0003184; ; */
+.long 0x868184d2 /* 0060: LCD: idx2 = var13, idx3 = var3; idx2 < var19; idx2 += inc2, idx3 += inc2 */
+.long 0x000acf88 /* 0064: DRD1A: *idx3 = *idx1; FN=0 init=0 WS=1 RS=1 */
+.long 0xc318839b /* 0068: LCDEXT: idx1 = var6; idx1 == var14; idx1 += inc3 */
+.long 0x80190000 /* 006C: LCD: idx2 = var0; idx2 once var0; idx2 += inc0 */
+.long 0x04008468 /* 0070: DRD1A: idx1 = var13; FN=0 INT init=0 WS=0 RS=0 */
+.long 0xc4038358 /* 0074: LCDEXT: idx1 = var8, idx2 = var7; idx1 == var13; idx1 += inc3, idx2 += inc0 */
+.long 0x81c50000 /* 0078: LCD: idx3 = var3 + var10; idx3 once var0; idx3 += inc0 */
+.long 0x1000cb18 /* 007C: DRD1A: *idx2 = idx3; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x00000f18 /* 0080: DRD1A: var3 = idx3; FN=0 init=0 WS=0 RS=0 */
+.long 0xc4188364 /* 0084: LCDEXT: idx1 = var8; idx1 > var13; idx1 += inc4 */
+.long 0x83990000 /* 0088: LCD: idx2 = var7; idx2 once var0; idx2 += inc0 */
+.long 0x10000c00 /* 008C: DRD1A: var3 = var0; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x0000c800 /* 0090: DRD1A: *idx2 = var0; FN=0 init=0 WS=0 RS=0 */
+.long 0x81988000 /* 0094: LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */
+.long 0x10000788 /* 0098: DRD1A: var1 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x60000000 /* 009C: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long 0x080cf04c /* 00A0: DRD2B1: idx0 = EU3(); EU3(var1,var12) */
+.long 0x000001f8 /* 00A4(:0): NOP */
+
+
+.globl scEthernetXmit_TDT
+scEthernetXmit_TDT: /* Task 1 Descriptor Table */
+.long 0x80024800 /* 0000: LCDEXT: idx0 = 0xf0008800; ; */
+.long 0x85c60004 /* 0004: LCD: idx1 = var11 + var12 + 4; idx1 once var0; idx1 += inc0 */
+.long 0x10002308 /* 0008: DRD1A: var8 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x10000f88 /* 000C: DRD1A: var3 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x00000380 /* 0010: DRD1A: var0 = *idx0; FN=0 init=0 WS=0 RS=0 */
+.long 0x81980000 /* 0014: LCD: idx0 = var3; idx0 once var0; idx0 += inc0 */
+.long 0x10000780 /* 0018: DRD1A: var1 = *idx0; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x60000000 /* 001C: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long 0x024cf04d /* 0020: DRD2B1: var9 = EU3(); EU3(var1,var13) */
+.long 0x84980309 /* 0024: LCD: idx0 = var9; idx0 != var12; idx0 += inc1 */
+.long 0xc0004003 /* 0028: LCDEXT: idx1 = 0x00000003; ; */
+.long 0x81c60004 /* 002C: LCD: idx2 = var3 + var12 + 4; idx2 once var0; idx2 += inc0 */
+.long 0x70000000 /* 0030: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long 0x010cf04e /* 0034: DRD2B1: var4 = EU3(); EU3(var1,var14) */
+.long 0x70000000 /* 0038: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long 0x014cf04f /* 003C: DRD2B1: var5 = EU3(); EU3(var1,var15) */
+.long 0x70000000 /* 0040: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long 0x028cf050 /* 0044: DRD2B1: var10 = EU3(); EU3(var1,var16) */
+.long 0x70000000 /* 0048: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long 0x018cf051 /* 004C: DRD2B1: var6 = EU3(); EU3(var1,var17) */
+.long 0x10000b90 /* 0050: DRD1A: var2 = *idx2; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x60000000 /* 0054: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long 0x01ccf0a1 /* 0058: DRD2B1: var7 = EU3(); EU3(var2,idx1) */
+.long 0xc2988312 /* 005C: LCDEXT: idx1 = var5; idx1 > var12; idx1 += inc2 */
+.long 0x83490000 /* 0060: LCD: idx2 = var6 + var18; idx2 once var0; idx2 += inc0 */
+.long 0x00001b10 /* 0064: DRD1A: var6 = idx2; FN=0 init=0 WS=0 RS=0 */
+.long 0x8000d1a4 /* 0068: LCDEXT: idx1 = 0xf00031a4; ; */
+.long 0x8301031c /* 006C: LCD: idx2 = var6, idx3 = var2; idx2 > var12; idx2 += inc3, idx3 += inc4 */
+.long 0x008ac798 /* 0070: DRD1A: *idx1 = *idx3; FN=0 init=4 WS=1 RS=1 */
+.long 0x8000d1a4 /* 0074: LCDEXT: idx1 = 0xf00031a4; ; */
+.long 0xc1430000 /* 0078: LCDEXT: idx2 = var2 + var6; idx2 once var0; idx2 += inc0 */
+.long 0x82998312 /* 007C: LCD: idx3 = var5; idx3 > var12; idx3 += inc2 */
+.long 0x088ac790 /* 0080: DRD1A: *idx1 = *idx2; FN=0 TFD init=4 WS=1 RS=1 */
+.long 0x81988000 /* 0084: LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */
+.long 0x60000001 /* 0088: DRD2A: EU0=0 EU1=0 EU2=0 EU3=1 EXT init=0 WS=0 RS=0 */
+.long 0x0c4cfc4d /* 008C: DRD2B1: *idx1 = EU3(); EU3(*idx1,var13) */
+.long 0xc21883ad /* 0090: LCDEXT: idx1 = var4; idx1 == var14; idx1 += inc5 */
+.long 0x80190000 /* 0094: LCD: idx2 = var0; idx2 once var0; idx2 += inc0 */
+.long 0x04008460 /* 0098: DRD1A: idx1 = var12; FN=0 INT init=0 WS=0 RS=0 */
+.long 0xc4052305 /* 009C: LCDEXT: idx1 = var8, idx2 = var10; idx2 == var12; idx1 += inc0, idx2 += inc5 */
+.long 0x81c98000 /* 00A0: LCD: idx3 = var3 + var19; idx3 once var0; idx3 += inc0 */
+.long 0x1000c718 /* 00A4: DRD1A: *idx1 = idx3; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x00000f18 /* 00A8: DRD1A: var3 = idx3; FN=0 init=0 WS=0 RS=0 */
+.long 0xc4188000 /* 00AC: LCDEXT: idx1 = var8; idx1 once var0; idx1 += inc0 */
+.long 0x85190312 /* 00B0: LCD: idx2 = var10; idx2 > var12; idx2 += inc2 */
+.long 0x10000c00 /* 00B4: DRD1A: var3 = var0; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x1000c400 /* 00B8: DRD1A: *idx1 = var0; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x00008860 /* 00BC: DRD1A: idx2 = var12; FN=0 init=0 WS=0 RS=0 */
+.long 0x81988000 /* 00C0: LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */
+.long 0x10000788 /* 00C4: DRD1A: var1 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x60000000 /* 00C8: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long 0x080cf04d /* 00CC: DRD2B1: idx0 = EU3(); EU3(var1,var13) */
+.long 0x000001f8 /* 00D0(:0): NOP */
+
+.align 8
+
+.globl scEthernetRecv_VarTab
+scEthernetRecv_VarTab: /* Task 0 Variable Table */
+.long 0x00000000 /* var[0] */
+.long 0x00000000 /* var[1] */
+.long 0x00000000 /* var[2] */
+.long 0x00000000 /* var[3] */
+.long 0x00000000 /* var[4] */
+.long 0x00000000 /* var[5] */
+.long 0x00000000 /* var[6] */
+.long 0x00000000 /* var[7] */
+.long 0x00000000 /* var[8] */
+.long 0xf0008800 /* var[9] */
+.long 0x00000008 /* var[10] */
+.long 0x0000000c /* var[11] */
+.long 0x80000000 /* var[12] */
+.long 0x00000000 /* var[13] */
+.long 0x10000000 /* var[14] */
+.long 0x20000000 /* var[15] */
+.long 0x000005e4 /* var[16] */
+.long 0x0000000e /* var[17] */
+.long 0x000005e0 /* var[18] */
+.long 0x00000004 /* var[19] */
+.long 0x00000000 /* var[20] */
+.long 0x00000000 /* var[21] */
+.long 0x00000000 /* var[22] */
+.long 0x00000000 /* var[23] */
+.long 0x00000000 /* inc[0] */
+.long 0x60000000 /* inc[1] */
+.long 0x20000001 /* inc[2] */
+.long 0x80000000 /* inc[3] */
+.long 0x40000000 /* inc[4] */
+.long 0x00000000 /* inc[5] */
+.long 0x00000000 /* inc[6] */
+.long 0x00000000 /* inc[7] */
+
+.align 8
+
+.globl scEthernetXmit_VarTab
+scEthernetXmit_VarTab: /* Task 1 Variable Table */
+.long 0x00000000 /* var[0] */
+.long 0x00000000 /* var[1] */
+.long 0x00000000 /* var[2] */
+.long 0x00000000 /* var[3] */
+.long 0x00000000 /* var[4] */
+.long 0x00000000 /* var[5] */
+.long 0x00000000 /* var[6] */
+.long 0x00000000 /* var[7] */
+.long 0x00000000 /* var[8] */
+.long 0x00000000 /* var[9] */
+.long 0x00000000 /* var[10] */
+.long 0xf0008800 /* var[11] */
+.long 0x00000000 /* var[12] */
+.long 0x80000000 /* var[13] */
+.long 0x10000000 /* var[14] */
+.long 0x08000000 /* var[15] */
+.long 0x20000000 /* var[16] */
+.long 0x0000ffff /* var[17] */
+.long 0xffffffff /* var[18] */
+.long 0x00000008 /* var[19] */
+.long 0x00000000 /* var[20] */
+.long 0x00000000 /* var[21] */
+.long 0x00000000 /* var[22] */
+.long 0x00000000 /* var[23] */
+.long 0x00000000 /* inc[0] */
+.long 0x60000000 /* inc[1] */
+.long 0x40000000 /* inc[2] */
+.long 0x4000ffff /* inc[3] */
+.long 0xe0000001 /* inc[4] */
+.long 0x80000000 /* inc[5] */
+.long 0x00000000 /* inc[6] */
+.long 0x00000000 /* inc[7] */
+
+.align 8
+
+.globl scEthernetRecv_FDT
+scEthernetRecv_FDT: /* Task 0 Function Descriptor Table */
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x21800000 /* and(), EU# 3 */
+.long 0x21400000 /* andn(), EU# 3 */
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+
+.align 8
+
+.globl scEthernetXmit_FDT
+scEthernetXmit_FDT: /* Task 1 Function Descriptor Table */
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x21800000 /* and(), EU# 3 */
+.long 0x21400000 /* andn(), EU# 3 */
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+
+
+.globl scEthernetRecv_CSave
+scEthernetRecv_CSave: /* Task 0 context save space */
+.space 128, 0x0
+
+
+.globl scEthernetXmit_CSave
+scEthernetXmit_CSave: /* Task 1 context save space */
+.space 128, 0x0
+
diff --git a/arch/powerpc/mach-mpc5xxx/include/mach/clock.h b/arch/powerpc/mach-mpc5xxx/include/mach/clock.h
new file mode 100644
index 0000000000..1813740eb1
--- /dev/null
+++ b/arch/powerpc/mach-mpc5xxx/include/mach/clock.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __ASM_ARCH_CLOCKS_H
+#define __ASM_ARCH_CLOCKS_H
+
+unsigned long get_bus_clock(void);
+unsigned long get_cpu_clock(void);
+unsigned long get_ipb_clock(void);
+unsigned long get_pci_clock(void);
+unsigned long get_timebase_clock(void);
+static inline unsigned long fsl_get_i2c_freq(void)
+{
+ return get_ipb_clock();
+}
+
+#endif /* __ASM_ARCH_CLOCKS_H */
diff --git a/arch/powerpc/mach-mpc5xxx/include/mach/mpc5xxx.h b/arch/powerpc/mach-mpc5xxx/include/mach/mpc5xxx.h
new file mode 100644
index 0000000000..6949b1d950
--- /dev/null
+++ b/arch/powerpc/mach-mpc5xxx/include/mach/mpc5xxx.h
@@ -0,0 +1,790 @@
+/*
+ * arch/powerpc/mach-mpc5xxx/include/mach/mpc5xxx.h
+ *
+ * Prototypes, etc. for the Motorola MGT5xxx/MPC5xxx
+ * embedded cpu chips
+ *
+ * 2003 (c) MontaVista, Software, Inc.
+ * Author: Dale Farnsworth <dfarnsworth@mvista.com>
+ *
+ * 2003 (C) Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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.
+ *
+ */
+#ifndef __ASMPPC_MPC5XXX_H
+#define __ASMPPC_MPC5XXX_H
+
+/* Processor name */
+#if defined(CONFIG_MPC5200)
+#define CPU_ID_STR "MPC5200"
+#elif defined(CONFIG_MGT5100)
+#define CPU_ID_STR "MGT5100"
+#endif
+
+/* Exception offsets (PowerPC standard) */
+#define EXC_OFF_SYS_RESET 0x0100
+#define _START_OFFSET EXC_OFF_SYS_RESET
+
+#define CFG_MBAR 0xf0000000
+
+/* useful macros for manipulating CSx_START/STOP */
+#if defined(CONFIG_MGT5100)
+#define START_REG(start) ((start) >> 15)
+#define STOP_REG(start, size) (((start) + (size) - 1) >> 15)
+#elif defined(CONFIG_MPC5200)
+#define START_REG(start) ((start) >> 16)
+#define STOP_REG(start, size) (((start) + (size) - 1) >> 16)
+#endif
+
+/* Internal memory map */
+
+#define MPC5XXX_CS0_START (CFG_MBAR + 0x0004)
+#define MPC5XXX_CS0_STOP (CFG_MBAR + 0x0008)
+#define MPC5XXX_CS1_START (CFG_MBAR + 0x000c)
+#define MPC5XXX_CS1_STOP (CFG_MBAR + 0x0010)
+#define MPC5XXX_CS2_START (CFG_MBAR + 0x0014)
+#define MPC5XXX_CS2_STOP (CFG_MBAR + 0x0018)
+#define MPC5XXX_CS3_START (CFG_MBAR + 0x001c)
+#define MPC5XXX_CS3_STOP (CFG_MBAR + 0x0020)
+#define MPC5XXX_CS4_START (CFG_MBAR + 0x0024)
+#define MPC5XXX_CS4_STOP (CFG_MBAR + 0x0028)
+#define MPC5XXX_CS5_START (CFG_MBAR + 0x002c)
+#define MPC5XXX_CS5_STOP (CFG_MBAR + 0x0030)
+#define MPC5XXX_BOOTCS_START (CFG_MBAR + 0x004c)
+#define MPC5XXX_BOOTCS_STOP (CFG_MBAR + 0x0050)
+#define MPC5XXX_ADDECR (CFG_MBAR + 0x0054)
+
+#if defined(CONFIG_MGT5100)
+#define MPC5XXX_SDRAM_START (CFG_MBAR + 0x0034)
+#define MPC5XXX_SDRAM_STOP (CFG_MBAR + 0x0038)
+#define MPC5XXX_PCI1_START (CFG_MBAR + 0x003c)
+#define MPC5XXX_PCI1_STOP (CFG_MBAR + 0x0040)
+#define MPC5XXX_PCI2_START (CFG_MBAR + 0x0044)
+#define MPC5XXX_PCI2_STOP (CFG_MBAR + 0x0048)
+#elif defined(CONFIG_MPC5200)
+#define MPC5XXX_CS6_START (CFG_MBAR + 0x0058)
+#define MPC5XXX_CS6_STOP (CFG_MBAR + 0x005c)
+#define MPC5XXX_CS7_START (CFG_MBAR + 0x0060)
+#define MPC5XXX_CS7_STOP (CFG_MBAR + 0x0064)
+#define MPC5XXX_SDRAM_CS0CFG (CFG_MBAR + 0x0034)
+#define MPC5XXX_SDRAM_CS1CFG (CFG_MBAR + 0x0038)
+#endif
+
+#define MPC5XXX_SDRAM (CFG_MBAR + 0x0100)
+#define MPC5XXX_CDM (CFG_MBAR + 0x0200)
+#define MPC5XXX_LPB (CFG_MBAR + 0x0300)
+#define MPC5XXX_ICTL (CFG_MBAR + 0x0500)
+#define MPC5XXX_GPT (CFG_MBAR + 0x0600)
+#define MPC5XXX_GPIO (CFG_MBAR + 0x0b00)
+#define MPC5XXX_WU_GPIO (CFG_MBAR + 0x0c00)
+#define MPC5XXX_PCI (CFG_MBAR + 0x0d00)
+#define MPC5XXX_SPI (CFG_MBAR + 0x0f00)
+#define MPC5XXX_USB (CFG_MBAR + 0x1000)
+#define MPC5XXX_SDMA (CFG_MBAR + 0x1200)
+#define MPC5XXX_XLBARB (CFG_MBAR + 0x1f00)
+
+#if defined(CONFIG_MGT5100)
+#define MPC5XXX_PSC1 (CFG_MBAR + 0x2000)
+#define MPC5XXX_PSC2 (CFG_MBAR + 0x2400)
+#define MPC5XXX_PSC3 (CFG_MBAR + 0x2800)
+#elif defined(CONFIG_MPC5200)
+#define MPC5XXX_PSC1 (CFG_MBAR + 0x2000)
+#define MPC5XXX_PSC2 (CFG_MBAR + 0x2200)
+#define MPC5XXX_PSC3 (CFG_MBAR + 0x2400)
+#define MPC5XXX_PSC4 (CFG_MBAR + 0x2600)
+#define MPC5XXX_PSC5 (CFG_MBAR + 0x2800)
+#define MPC5XXX_PSC6 (CFG_MBAR + 0x2c00)
+#endif
+
+#define MPC5XXX_FEC (CFG_MBAR + 0x3000)
+#define MPC5XXX_ATA (CFG_MBAR + 0x3A00)
+
+#define MPC5XXX_I2C1 (CFG_MBAR + 0x3D00)
+#define MPC5XXX_I2C2 (CFG_MBAR + 0x3D40)
+
+#if defined(CONFIG_MGT5100)
+#define MPC5XXX_SRAM (CFG_MBAR + 0x4000)
+#define MPC5XXX_SRAM_SIZE (8*1024)
+#elif defined(CONFIG_MPC5200)
+#define MPC5XXX_SRAM (CFG_MBAR + 0x8000)
+#define MPC5XXX_SRAM_SIZE (16*1024)
+#endif
+
+/* SDRAM Controller */
+#define MPC5XXX_SDRAM_MODE (MPC5XXX_SDRAM + 0x0000)
+#define MPC5XXX_SDRAM_CTRL (MPC5XXX_SDRAM + 0x0004)
+#define MPC5XXX_SDRAM_CONFIG1 (MPC5XXX_SDRAM + 0x0008)
+#define MPC5XXX_SDRAM_CONFIG2 (MPC5XXX_SDRAM + 0x000c)
+#if defined(CONFIG_MGT5100)
+#define MPC5XXX_SDRAM_XLBSEL (MPC5XXX_SDRAM + 0x0010)
+#endif
+#define MPC5XXX_SDRAM_SDELAY (MPC5XXX_SDRAM + 0x0090)
+
+/* Clock Distribution Module */
+#define MPC5XXX_CDM_JTAGID (MPC5XXX_CDM + 0x0000)
+#define MPC5XXX_CDM_PORCFG (MPC5XXX_CDM + 0x0004)
+#define MPC5XXX_CDM_CFG (MPC5XXX_CDM + 0x000c)
+#define MPC5XXX_CDM_48_FDC (MPC5XXX_CDM + 0x0010)
+#define MPC5XXX_CDM_SRESET (MPC5XXX_CDM + 0x0020)
+
+/* Local Plus Bus interface */
+#define MPC5XXX_CS0_CFG (MPC5XXX_LPB + 0x0000)
+#define MPC5XXX_CS1_CFG (MPC5XXX_LPB + 0x0004)
+#define MPC5XXX_CS2_CFG (MPC5XXX_LPB + 0x0008)
+#define MPC5XXX_CS3_CFG (MPC5XXX_LPB + 0x000c)
+#define MPC5XXX_CS4_CFG (MPC5XXX_LPB + 0x0010)
+#define MPC5XXX_CS5_CFG (MPC5XXX_LPB + 0x0014)
+#define MPC5XXX_BOOTCS_CFG MPC5XXX_CS0_CFG
+#define MPC5XXX_CS_CTRL (MPC5XXX_LPB + 0x0018)
+#define MPC5XXX_CS_STATUS (MPC5XXX_LPB + 0x001c)
+#if defined(CONFIG_MPC5200)
+#define MPC5XXX_CS6_CFG (MPC5XXX_LPB + 0x0020)
+#define MPC5XXX_CS7_CFG (MPC5XXX_LPB + 0x0024)
+#define MPC5XXX_CS_BURST (MPC5XXX_LPB + 0x0028)
+#define MPC5XXX_CS_DEADCYCLE (MPC5XXX_LPB + 0x002c)
+#endif
+
+#if defined(CONFIG_MPC5200)
+/* XLB Arbiter registers */
+#define MPC5XXX_XLBARB_CFG (MPC5XXX_XLBARB + 0x40)
+#define MPC5XXX_XLBARB_MPRIEN (MPC5XXX_XLBARB + 0x64)
+#define MPC5XXX_XLBARB_MPRIVAL (MPC5XXX_XLBARB + 0x68)
+#endif
+
+/* GPIO registers */
+#define MPC5XXX_GPS_PORT_CONFIG (MPC5XXX_GPIO + 0x0000)
+
+/* Standard GPIO registers (simple, output only and simple interrupt */
+#define MPC5XXX_GPIO_ENABLE (MPC5XXX_GPIO + 0x0004)
+#define MPC5XXX_GPIO_ODE (MPC5XXX_GPIO + 0x0008)
+#define MPC5XXX_GPIO_DIR (MPC5XXX_GPIO + 0x000c)
+#define MPC5XXX_GPIO_DATA_O (MPC5XXX_GPIO + 0x0010)
+#define MPC5XXX_GPIO_DATA_I (MPC5XXX_GPIO + 0x0014)
+#define MPC5XXX_GPIO_OO_ENABLE (MPC5XXX_GPIO + 0x0018)
+#define MPC5XXX_GPIO_OO_DATA (MPC5XXX_GPIO + 0x001C)
+#define MPC5XXX_GPIO_SI_ENABLE (MPC5XXX_GPIO + 0x0020)
+#define MPC5XXX_GPIO_SI_ODE (MPC5XXX_GPIO + 0x0024)
+#define MPC5XXX_GPIO_SI_DIR (MPC5XXX_GPIO + 0x0028)
+#define MPC5XXX_GPIO_SI_DATA (MPC5XXX_GPIO + 0x002C)
+#define MPC5XXX_GPIO_SI_IEN (MPC5XXX_GPIO + 0x0030)
+#define MPC5XXX_GPIO_SI_ITYPE (MPC5XXX_GPIO + 0x0034)
+#define MPC5XXX_GPIO_SI_MEN (MPC5XXX_GPIO + 0x0038)
+#define MPC5XXX_GPIO_SI_STATUS (MPC5XXX_GPIO + 0x003C)
+
+/* WakeUp GPIO registers */
+#define MPC5XXX_WU_GPIO_ENABLE (MPC5XXX_WU_GPIO + 0x0000)
+#define MPC5XXX_WU_GPIO_ODE (MPC5XXX_WU_GPIO + 0x0004)
+#define MPC5XXX_WU_GPIO_DIR (MPC5XXX_WU_GPIO + 0x0008)
+#define MPC5XXX_WU_GPIO_DATA_O (MPC5XXX_WU_GPIO + 0x000c)
+#define MPC5XXX_WU_GPIO_DATA_I (MPC5XXX_WU_GPIO + 0x0020)
+
+/* GPIO pins */
+#define GPIO_WKUP_7 0x80000000UL
+#define GPIO_PSC6_0 0x10000000UL
+#define GPIO_PSC3_9 0x04000000UL
+#define GPIO_PSC1_4 0x01000000UL
+
+/* PCI registers */
+#define MPC5XXX_PCI_CMD (MPC5XXX_PCI + 0x04)
+#define MPC5XXX_PCI_CFG (MPC5XXX_PCI + 0x0c)
+#define MPC5XXX_PCI_BAR0 (MPC5XXX_PCI + 0x10)
+#define MPC5XXX_PCI_BAR1 (MPC5XXX_PCI + 0x14)
+#if defined(CONFIG_MGT5100)
+#define MPC5XXX_PCI_CTRL (MPC5XXX_PCI + 0x68)
+#define MPC5XXX_PCI_VALMSKR (MPC5XXX_PCI + 0x6c)
+#define MPC5XXX_PCI_VALMSKW (MPC5XXX_PCI + 0x70)
+#define MPC5XXX_PCI_SUBW1 (MPC5XXX_PCI + 0x74)
+#define MPC5XXX_PCI_SUBW2 (MPC5XXX_PCI + 0x78)
+#define MPC5XXX_PCI_WINCOMMAND (MPC5XXX_PCI + 0x7c)
+#elif defined(CONFIG_MPC5200)
+#define MPC5XXX_PCI_GSCR (MPC5XXX_PCI + 0x60)
+#define MPC5XXX_PCI_TBATR0 (MPC5XXX_PCI + 0x64)
+#define MPC5XXX_PCI_TBATR1 (MPC5XXX_PCI + 0x68)
+#define MPC5XXX_PCI_TCR (MPC5XXX_PCI + 0x6c)
+#define MPC5XXX_PCI_IW0BTAR (MPC5XXX_PCI + 0x70)
+#define MPC5XXX_PCI_IW1BTAR (MPC5XXX_PCI + 0x74)
+#define MPC5XXX_PCI_IW2BTAR (MPC5XXX_PCI + 0x78)
+#define MPC5XXX_PCI_IWCR (MPC5XXX_PCI + 0x80)
+#define MPC5XXX_PCI_ICR (MPC5XXX_PCI + 0x84)
+#define MPC5XXX_PCI_ISR (MPC5XXX_PCI + 0x88)
+#define MPC5XXX_PCI_ARB (MPC5XXX_PCI + 0x8c)
+#define MPC5XXX_PCI_CAR (MPC5XXX_PCI + 0xf8)
+#endif
+
+/* Interrupt Controller registers */
+#define MPC5XXX_ICTL_PER_MASK (MPC5XXX_ICTL + 0x0000)
+#define MPC5XXX_ICTL_PER_PRIO1 (MPC5XXX_ICTL + 0x0004)
+#define MPC5XXX_ICTL_PER_PRIO2 (MPC5XXX_ICTL + 0x0008)
+#define MPC5XXX_ICTL_PER_PRIO3 (MPC5XXX_ICTL + 0x000c)
+#define MPC5XXX_ICTL_EXT (MPC5XXX_ICTL + 0x0010)
+#define MPC5XXX_ICTL_CRIT (MPC5XXX_ICTL + 0x0014)
+#define MPC5XXX_ICTL_MAIN_PRIO1 (MPC5XXX_ICTL + 0x0018)
+#define MPC5XXX_ICTL_MAIN_PRIO2 (MPC5XXX_ICTL + 0x001c)
+#define MPC5XXX_ICTL_STS (MPC5XXX_ICTL + 0x0024)
+#define MPC5XXX_ICTL_CRIT_STS (MPC5XXX_ICTL + 0x0028)
+#define MPC5XXX_ICTL_MAIN_STS (MPC5XXX_ICTL + 0x002c)
+#define MPC5XXX_ICTL_PER_STS (MPC5XXX_ICTL + 0x0030)
+#define MPC5XXX_ICTL_BUS_STS (MPC5XXX_ICTL + 0x0038)
+
+#define NR_IRQS 64
+
+/* IRQ mapping - these are our logical IRQ numbers */
+#define MPC5XXX_CRIT_IRQ_NUM 4
+#define MPC5XXX_MAIN_IRQ_NUM 17
+#define MPC5XXX_SDMA_IRQ_NUM 17
+#define MPC5XXX_PERP_IRQ_NUM 23
+
+#define MPC5XXX_CRIT_IRQ_BASE 1
+#define MPC5XXX_MAIN_IRQ_BASE (MPC5XXX_CRIT_IRQ_BASE + MPC5XXX_CRIT_IRQ_NUM)
+#define MPC5XXX_SDMA_IRQ_BASE (MPC5XXX_MAIN_IRQ_BASE + MPC5XXX_MAIN_IRQ_NUM)
+#define MPC5XXX_PERP_IRQ_BASE (MPC5XXX_SDMA_IRQ_BASE + MPC5XXX_SDMA_IRQ_NUM)
+
+#define MPC5XXX_IRQ0 (MPC5XXX_CRIT_IRQ_BASE + 0)
+#define MPC5XXX_SLICE_TIMER_0_IRQ (MPC5XXX_CRIT_IRQ_BASE + 1)
+#define MPC5XXX_HI_INT_IRQ (MPC5XXX_CRIT_IRQ_BASE + 2)
+#define MPC5XXX_CCS_IRQ (MPC5XXX_CRIT_IRQ_BASE + 3)
+
+#define MPC5XXX_IRQ1 (MPC5XXX_MAIN_IRQ_BASE + 1)
+#define MPC5XXX_IRQ2 (MPC5XXX_MAIN_IRQ_BASE + 2)
+#define MPC5XXX_IRQ3 (MPC5XXX_MAIN_IRQ_BASE + 3)
+#define MPC5XXX_RTC_PINT_IRQ (MPC5XXX_MAIN_IRQ_BASE + 5)
+#define MPC5XXX_RTC_SINT_IRQ (MPC5XXX_MAIN_IRQ_BASE + 6)
+#define MPC5XXX_RTC_GPIO_STD_IRQ (MPC5XXX_MAIN_IRQ_BASE + 7)
+#define MPC5XXX_RTC_GPIO_WKUP_IRQ (MPC5XXX_MAIN_IRQ_BASE + 8)
+#define MPC5XXX_TMR0_IRQ (MPC5XXX_MAIN_IRQ_BASE + 9)
+#define MPC5XXX_TMR1_IRQ (MPC5XXX_MAIN_IRQ_BASE + 10)
+#define MPC5XXX_TMR2_IRQ (MPC5XXX_MAIN_IRQ_BASE + 11)
+#define MPC5XXX_TMR3_IRQ (MPC5XXX_MAIN_IRQ_BASE + 12)
+#define MPC5XXX_TMR4_IRQ (MPC5XXX_MAIN_IRQ_BASE + 13)
+#define MPC5XXX_TMR5_IRQ (MPC5XXX_MAIN_IRQ_BASE + 14)
+#define MPC5XXX_TMR6_IRQ (MPC5XXX_MAIN_IRQ_BASE + 15)
+#define MPC5XXX_TMR7_IRQ (MPC5XXX_MAIN_IRQ_BASE + 16)
+
+#define MPC5XXX_SDMA_IRQ (MPC5XXX_PERP_IRQ_BASE + 0)
+#define MPC5XXX_PSC1_IRQ (MPC5XXX_PERP_IRQ_BASE + 1)
+#define MPC5XXX_PSC2_IRQ (MPC5XXX_PERP_IRQ_BASE + 2)
+#define MPC5XXX_PSC3_IRQ (MPC5XXX_PERP_IRQ_BASE + 3)
+#define MPC5XXX_PSC6_IRQ (MPC5XXX_PERP_IRQ_BASE + 4)
+#define MPC5XXX_IRDA_IRQ (MPC5XXX_PERP_IRQ_BASE + 4)
+#define MPC5XXX_FEC_IRQ (MPC5XXX_PERP_IRQ_BASE + 5)
+#define MPC5XXX_USB_IRQ (MPC5XXX_PERP_IRQ_BASE + 6)
+#define MPC5XXX_ATA_IRQ (MPC5XXX_PERP_IRQ_BASE + 7)
+#define MPC5XXX_PCI_CNTRL_IRQ (MPC5XXX_PERP_IRQ_BASE + 8)
+#define MPC5XXX_PCI_SCIRX_IRQ (MPC5XXX_PERP_IRQ_BASE + 9)
+#define MPC5XXX_PCI_SCITX_IRQ (MPC5XXX_PERP_IRQ_BASE + 10)
+#define MPC5XXX_PSC4_IRQ (MPC5XXX_PERP_IRQ_BASE + 11)
+#define MPC5XXX_PSC5_IRQ (MPC5XXX_PERP_IRQ_BASE + 12)
+#define MPC5XXX_SPI_MODF_IRQ (MPC5XXX_PERP_IRQ_BASE + 13)
+#define MPC5XXX_SPI_SPIF_IRQ (MPC5XXX_PERP_IRQ_BASE + 14)
+#define MPC5XXX_I2C1_IRQ (MPC5XXX_PERP_IRQ_BASE + 15)
+#define MPC5XXX_I2C2_IRQ (MPC5XXX_PERP_IRQ_BASE + 16)
+#define MPC5XXX_MSCAN1_IRQ (MPC5XXX_PERP_IRQ_BASE + 17)
+#define MPC5XXX_MSCAN2_IRQ (MPC5XXX_PERP_IRQ_BASE + 18)
+#define MPC5XXX_IR_RX_IRQ (MPC5XXX_PERP_IRQ_BASE + 19)
+#define MPC5XXX_IR_TX_IRQ (MPC5XXX_PERP_IRQ_BASE + 20)
+#define MPC5XXX_XLB_ARB_IRQ (MPC5XXX_PERP_IRQ_BASE + 21)
+#define MPC5XXX_BDLC_IRQ (MPC5XXX_PERP_IRQ_BASE + 22)
+
+/* General Purpose Timers registers */
+#define MPC5XXX_GPT0_ENABLE (MPC5XXX_GPT + 0x0)
+#define MPC5XXX_GPT0_COUNTER (MPC5XXX_GPT + 0x4)
+#define MPC5XXX_GPT0_STATUS (MPC5XXX_GPT + 0x0C)
+#define MPC5XXX_GPT1_ENABLE (MPC5XXX_GPT + 0x10)
+#define MPC5XXX_GPT1_COUNTER (MPC5XXX_GPT + 0x14)
+#define MPC5XXX_GPT1_STATUS (MPC5XXX_GPT + 0x1C)
+#define MPC5XXX_GPT2_ENABLE (MPC5XXX_GPT + 0x20)
+#define MPC5XXX_GPT2_COUNTER (MPC5XXX_GPT + 0x24)
+#define MPC5XXX_GPT2_STATUS (MPC5XXX_GPT + 0x2C)
+#define MPC5XXX_GPT3_ENABLE (MPC5XXX_GPT + 0x30)
+#define MPC5XXX_GPT3_COUNTER (MPC5XXX_GPT + 0x34)
+#define MPC5XXX_GPT3_STATUS (MPC5XXX_GPT + 0x3C)
+#define MPC5XXX_GPT4_ENABLE (MPC5XXX_GPT + 0x40)
+#define MPC5XXX_GPT4_COUNTER (MPC5XXX_GPT + 0x44)
+#define MPC5XXX_GPT4_STATUS (MPC5XXX_GPT + 0x4C)
+#define MPC5XXX_GPT5_ENABLE (MPC5XXX_GPT + 0x50)
+#define MPC5XXX_GPT5_STATUS (MPC5XXX_GPT + 0x5C)
+#define MPC5XXX_GPT5_COUNTER (MPC5XXX_GPT + 0x54)
+#define MPC5XXX_GPT6_ENABLE (MPC5XXX_GPT + 0x60)
+#define MPC5XXX_GPT6_COUNTER (MPC5XXX_GPT + 0x64)
+#define MPC5XXX_GPT6_STATUS (MPC5XXX_GPT + 0x6C)
+#define MPC5XXX_GPT7_ENABLE (MPC5XXX_GPT + 0x70)
+#define MPC5XXX_GPT7_COUNTER (MPC5XXX_GPT + 0x74)
+#define MPC5XXX_GPT7_STATUS (MPC5XXX_GPT + 0x7C)
+
+#define MPC5XXX_GPT_GPIO_PIN(status) ((0x00000100 & (status)) >> 8)
+
+#define MPC5XXX_GPT7_PWMCFG (MPC5XXX_GPT + 0x78)
+
+/* ATA registers */
+#define MPC5XXX_ATA_HOST_CONFIG (MPC5XXX_ATA + 0x0000)
+#define MPC5XXX_ATA_PIO1 (MPC5XXX_ATA + 0x0008)
+#define MPC5XXX_ATA_PIO2 (MPC5XXX_ATA + 0x000C)
+#define MPC5XXX_ATA_SHARE_COUNT (MPC5XXX_ATA + 0x002C)
+
+/* I2Cn control register bits */
+#define I2C_EN 0x80
+#define I2C_IEN 0x40
+#define I2C_STA 0x20
+#define I2C_TX 0x10
+#define I2C_TXAK 0x08
+#define I2C_RSTA 0x04
+#define I2C_INIT_MASK (I2C_EN | I2C_STA | I2C_TX | I2C_RSTA)
+
+/* I2Cn status register bits */
+#define I2C_CF 0x80
+#define I2C_AAS 0x40
+#define I2C_BB 0x20
+#define I2C_AL 0x10
+#define I2C_SRW 0x04
+#define I2C_IF 0x02
+#define I2C_RXAK 0x01
+
+/* Programmable Serial Controller (PSC) status register bits */
+#define PSC_SR_CDE 0x0080
+#define PSC_SR_RXRDY 0x0100
+#define PSC_SR_RXFULL 0x0200
+#define PSC_SR_TXRDY 0x0400
+#define PSC_SR_TXEMP 0x0800
+#define PSC_SR_OE 0x1000
+#define PSC_SR_PE 0x2000
+#define PSC_SR_FE 0x4000
+#define PSC_SR_RB 0x8000
+
+/* PSC Command values */
+#define PSC_RX_ENABLE 0x0001
+#define PSC_RX_DISABLE 0x0002
+#define PSC_TX_ENABLE 0x0004
+#define PSC_TX_DISABLE 0x0008
+#define PSC_SEL_MODE_REG_1 0x0010
+#define PSC_RST_RX 0x0020
+#define PSC_RST_TX 0x0030
+#define PSC_RST_ERR_STAT 0x0040
+#define PSC_RST_BRK_CHG_INT 0x0050
+#define PSC_START_BRK 0x0060
+#define PSC_STOP_BRK 0x0070
+
+/* PSC Rx FIFO status bits */
+#define PSC_RX_FIFO_ERR 0x0040
+#define PSC_RX_FIFO_UF 0x0020
+#define PSC_RX_FIFO_OF 0x0010
+#define PSC_RX_FIFO_FR 0x0008
+#define PSC_RX_FIFO_FULL 0x0004
+#define PSC_RX_FIFO_ALARM 0x0002
+#define PSC_RX_FIFO_EMPTY 0x0001
+
+/* PSC interrupt mask bits */
+#define PSC_IMR_TXRDY 0x0100
+#define PSC_IMR_RXRDY 0x0200
+#define PSC_IMR_DB 0x0400
+#define PSC_IMR_IPC 0x8000
+
+/* PSC input port change bits */
+#define PSC_IPCR_CTS 0x01
+#define PSC_IPCR_DCD 0x02
+
+/* PSC mode fields */
+#define PSC_MODE_5_BITS 0x00
+#define PSC_MODE_6_BITS 0x01
+#define PSC_MODE_7_BITS 0x02
+#define PSC_MODE_8_BITS 0x03
+#define PSC_MODE_PAREVEN 0x00
+#define PSC_MODE_PARODD 0x04
+#define PSC_MODE_PARFORCE 0x08
+#define PSC_MODE_PARNONE 0x10
+#define PSC_MODE_ERR 0x20
+#define PSC_MODE_FFULL 0x40
+#define PSC_MODE_RXRTS 0x80
+
+#define PSC_MODE_ONE_STOP_5_BITS 0x00
+#define PSC_MODE_ONE_STOP 0x07
+#define PSC_MODE_TWO_STOP 0x0f
+
+/* ATA config fields */
+#define MPC5xxx_ATA_HOSTCONF_SMR 0x80000000UL /* State machine
+ reset */
+#define MPC5xxx_ATA_HOSTCONF_FR 0x40000000UL /* FIFO Reset */
+#define MPC5xxx_ATA_HOSTCONF_IE 0x02000000UL /* Enable interrupt
+ in PIO */
+#define MPC5xxx_ATA_HOSTCONF_IORDY 0x01000000UL /* Drive supports
+ IORDY protocol */
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+struct mpc5xxx_psc {
+ volatile u8 mode; /* PSC + 0x00 */
+ volatile u8 reserved0[3];
+ union { /* PSC + 0x04 */
+ volatile u16 status;
+ volatile u16 clock_select;
+ } sr_csr;
+#define psc_status sr_csr.status
+#define psc_clock_select sr_csr.clock_select
+ volatile u16 reserved1;
+ volatile u8 command; /* PSC + 0x08 */
+ volatile u8 reserved2[3];
+ union { /* PSC + 0x0c */
+ volatile u8 buffer_8;
+ volatile u16 buffer_16;
+ volatile u32 buffer_32;
+ } buffer;
+#define psc_buffer_8 buffer.buffer_8
+#define psc_buffer_16 buffer.buffer_16
+#define psc_buffer_32 buffer.buffer_32
+ union { /* PSC + 0x10 */
+ volatile u8 ipcr;
+ volatile u8 acr;
+ } ipcr_acr;
+#define psc_ipcr ipcr_acr.ipcr
+#define psc_acr ipcr_acr.acr
+ volatile u8 reserved3[3];
+ union { /* PSC + 0x14 */
+ volatile u16 isr;
+ volatile u16 imr;
+ } isr_imr;
+#define psc_isr isr_imr.isr
+#define psc_imr isr_imr.imr
+ volatile u16 reserved4;
+ volatile u8 ctur; /* PSC + 0x18 */
+ volatile u8 reserved5[3];
+ volatile u8 ctlr; /* PSC + 0x1c */
+ volatile u8 reserved6[3];
+ volatile u16 ccr; /* PSC + 0x20 */
+ volatile u8 reserved7[14];
+ volatile u8 ivr; /* PSC + 0x30 */
+ volatile u8 reserved8[3];
+ volatile u8 ip; /* PSC + 0x34 */
+ volatile u8 reserved9[3];
+ volatile u8 op1; /* PSC + 0x38 */
+ volatile u8 reserved10[3];
+ volatile u8 op0; /* PSC + 0x3c */
+ volatile u8 reserved11[3];
+ volatile u32 sicr; /* PSC + 0x40 */
+ volatile u8 ircr1; /* PSC + 0x44 */
+ volatile u8 reserved12[3];
+ volatile u8 ircr2; /* PSC + 0x44 */
+ volatile u8 reserved13[3];
+ volatile u8 irsdr; /* PSC + 0x4c */
+ volatile u8 reserved14[3];
+ volatile u8 irmdr; /* PSC + 0x50 */
+ volatile u8 reserved15[3];
+ volatile u8 irfdr; /* PSC + 0x54 */
+ volatile u8 reserved16[3];
+ volatile u16 rfnum; /* PSC + 0x58 */
+ volatile u16 reserved17;
+ volatile u16 tfnum; /* PSC + 0x5c */
+ volatile u16 reserved18;
+ volatile u32 rfdata; /* PSC + 0x60 */
+ volatile u16 rfstat; /* PSC + 0x64 */
+ volatile u16 reserved20;
+ volatile u8 rfcntl; /* PSC + 0x68 */
+ volatile u8 reserved21[5];
+ volatile u16 rfalarm; /* PSC + 0x6e */
+ volatile u16 reserved22;
+ volatile u16 rfrptr; /* PSC + 0x72 */
+ volatile u16 reserved23;
+ volatile u16 rfwptr; /* PSC + 0x76 */
+ volatile u16 reserved24;
+ volatile u16 rflrfptr; /* PSC + 0x7a */
+ volatile u16 reserved25;
+ volatile u16 rflwfptr; /* PSC + 0x7e */
+ volatile u32 tfdata; /* PSC + 0x80 */
+ volatile u16 tfstat; /* PSC + 0x84 */
+ volatile u16 reserved26;
+ volatile u8 tfcntl; /* PSC + 0x88 */
+ volatile u8 reserved27[5];
+ volatile u16 tfalarm; /* PSC + 0x8e */
+ volatile u16 reserved28;
+ volatile u16 tfrptr; /* PSC + 0x92 */
+ volatile u16 reserved29;
+ volatile u16 tfwptr; /* PSC + 0x96 */
+ volatile u16 reserved30;
+ volatile u16 tflrfptr; /* PSC + 0x9a */
+ volatile u16 reserved31;
+ volatile u16 tflwfptr; /* PSC + 0x9e */
+};
+
+struct mpc5xxx_intr {
+ volatile u32 per_mask; /* INTR + 0x00 */
+ volatile u32 per_pri1; /* INTR + 0x04 */
+ volatile u32 per_pri2; /* INTR + 0x08 */
+ volatile u32 per_pri3; /* INTR + 0x0c */
+ volatile u32 ctrl; /* INTR + 0x10 */
+ volatile u32 main_mask; /* INTR + 0x14 */
+ volatile u32 main_pri1; /* INTR + 0x18 */
+ volatile u32 main_pri2; /* INTR + 0x1c */
+ volatile u32 reserved1; /* INTR + 0x20 */
+ volatile u32 enc_status; /* INTR + 0x24 */
+ volatile u32 crit_status; /* INTR + 0x28 */
+ volatile u32 main_status; /* INTR + 0x2c */
+ volatile u32 per_status; /* INTR + 0x30 */
+ volatile u32 reserved2; /* INTR + 0x34 */
+ volatile u32 per_error; /* INTR + 0x38 */
+};
+
+struct mpc5xxx_gpio {
+ volatile u32 port_config; /* GPIO + 0x00 */
+ volatile u32 simple_gpioe; /* GPIO + 0x04 */
+ volatile u32 simple_ode; /* GPIO + 0x08 */
+ volatile u32 simple_ddr; /* GPIO + 0x0c */
+ volatile u32 simple_dvo; /* GPIO + 0x10 */
+ volatile u32 simple_ival; /* GPIO + 0x14 */
+ volatile u8 outo_gpioe; /* GPIO + 0x18 */
+ volatile u8 reserved1[3]; /* GPIO + 0x19 */
+ volatile u8 outo_dvo; /* GPIO + 0x1c */
+ volatile u8 reserved2[3]; /* GPIO + 0x1d */
+ volatile u8 sint_gpioe; /* GPIO + 0x20 */
+ volatile u8 reserved3[3]; /* GPIO + 0x21 */
+ volatile u8 sint_ode; /* GPIO + 0x24 */
+ volatile u8 reserved4[3]; /* GPIO + 0x25 */
+ volatile u8 sint_ddr; /* GPIO + 0x28 */
+ volatile u8 reserved5[3]; /* GPIO + 0x29 */
+ volatile u8 sint_dvo; /* GPIO + 0x2c */
+ volatile u8 reserved6[3]; /* GPIO + 0x2d */
+ volatile u8 sint_inten; /* GPIO + 0x30 */
+ volatile u8 reserved7[3]; /* GPIO + 0x31 */
+ volatile u16 sint_itype; /* GPIO + 0x34 */
+ volatile u16 reserved8; /* GPIO + 0x36 */
+ volatile u8 gpio_control; /* GPIO + 0x38 */
+ volatile u8 reserved9[3]; /* GPIO + 0x39 */
+ volatile u8 sint_istat; /* GPIO + 0x3c */
+ volatile u8 sint_ival; /* GPIO + 0x3d */
+ volatile u8 bus_errs; /* GPIO + 0x3e */
+ volatile u8 reserved10; /* GPIO + 0x3f */
+};
+
+struct mpc5xxx_sdma {
+ volatile u32 taskBar; /* SDMA + 0x00 */
+ volatile u32 currentPointer; /* SDMA + 0x04 */
+ volatile u32 endPointer; /* SDMA + 0x08 */
+ volatile u32 variablePointer; /* SDMA + 0x0c */
+
+ volatile u8 IntVect1; /* SDMA + 0x10 */
+ volatile u8 IntVect2; /* SDMA + 0x11 */
+ volatile u16 PtdCntrl; /* SDMA + 0x12 */
+
+ volatile u32 IntPend; /* SDMA + 0x14 */
+ volatile u32 IntMask; /* SDMA + 0x18 */
+
+ volatile u16 tcr_0; /* SDMA + 0x1c */
+ volatile u16 tcr_1; /* SDMA + 0x1e */
+ volatile u16 tcr_2; /* SDMA + 0x20 */
+ volatile u16 tcr_3; /* SDMA + 0x22 */
+ volatile u16 tcr_4; /* SDMA + 0x24 */
+ volatile u16 tcr_5; /* SDMA + 0x26 */
+ volatile u16 tcr_6; /* SDMA + 0x28 */
+ volatile u16 tcr_7; /* SDMA + 0x2a */
+ volatile u16 tcr_8; /* SDMA + 0x2c */
+ volatile u16 tcr_9; /* SDMA + 0x2e */
+ volatile u16 tcr_a; /* SDMA + 0x30 */
+ volatile u16 tcr_b; /* SDMA + 0x32 */
+ volatile u16 tcr_c; /* SDMA + 0x34 */
+ volatile u16 tcr_d; /* SDMA + 0x36 */
+ volatile u16 tcr_e; /* SDMA + 0x38 */
+ volatile u16 tcr_f; /* SDMA + 0x3a */
+
+ volatile u8 IPR0; /* SDMA + 0x3c */
+ volatile u8 IPR1; /* SDMA + 0x3d */
+ volatile u8 IPR2; /* SDMA + 0x3e */
+ volatile u8 IPR3; /* SDMA + 0x3f */
+ volatile u8 IPR4; /* SDMA + 0x40 */
+ volatile u8 IPR5; /* SDMA + 0x41 */
+ volatile u8 IPR6; /* SDMA + 0x42 */
+ volatile u8 IPR7; /* SDMA + 0x43 */
+ volatile u8 IPR8; /* SDMA + 0x44 */
+ volatile u8 IPR9; /* SDMA + 0x45 */
+ volatile u8 IPR10; /* SDMA + 0x46 */
+ volatile u8 IPR11; /* SDMA + 0x47 */
+ volatile u8 IPR12; /* SDMA + 0x48 */
+ volatile u8 IPR13; /* SDMA + 0x49 */
+ volatile u8 IPR14; /* SDMA + 0x4a */
+ volatile u8 IPR15; /* SDMA + 0x4b */
+ volatile u8 IPR16; /* SDMA + 0x4c */
+ volatile u8 IPR17; /* SDMA + 0x4d */
+ volatile u8 IPR18; /* SDMA + 0x4e */
+ volatile u8 IPR19; /* SDMA + 0x4f */
+ volatile u8 IPR20; /* SDMA + 0x50 */
+ volatile u8 IPR21; /* SDMA + 0x51 */
+ volatile u8 IPR22; /* SDMA + 0x52 */
+ volatile u8 IPR23; /* SDMA + 0x53 */
+ volatile u8 IPR24; /* SDMA + 0x54 */
+ volatile u8 IPR25; /* SDMA + 0x55 */
+ volatile u8 IPR26; /* SDMA + 0x56 */
+ volatile u8 IPR27; /* SDMA + 0x57 */
+ volatile u8 IPR28; /* SDMA + 0x58 */
+ volatile u8 IPR29; /* SDMA + 0x59 */
+ volatile u8 IPR30; /* SDMA + 0x5a */
+ volatile u8 IPR31; /* SDMA + 0x5b */
+
+ volatile u32 res1; /* SDMA + 0x5c */
+ volatile u32 res2; /* SDMA + 0x60 */
+ volatile u32 res3; /* SDMA + 0x64 */
+ volatile u32 MDEDebug; /* SDMA + 0x68 */
+ volatile u32 ADSDebug; /* SDMA + 0x6c */
+ volatile u32 Value1; /* SDMA + 0x70 */
+ volatile u32 Value2; /* SDMA + 0x74 */
+ volatile u32 Control; /* SDMA + 0x78 */
+ volatile u32 Status; /* SDMA + 0x7c */
+ volatile u32 EU00; /* SDMA + 0x80 */
+ volatile u32 EU01; /* SDMA + 0x84 */
+ volatile u32 EU02; /* SDMA + 0x88 */
+ volatile u32 EU03; /* SDMA + 0x8c */
+ volatile u32 EU04; /* SDMA + 0x90 */
+ volatile u32 EU05; /* SDMA + 0x94 */
+ volatile u32 EU06; /* SDMA + 0x98 */
+ volatile u32 EU07; /* SDMA + 0x9c */
+ volatile u32 EU10; /* SDMA + 0xa0 */
+ volatile u32 EU11; /* SDMA + 0xa4 */
+ volatile u32 EU12; /* SDMA + 0xa8 */
+ volatile u32 EU13; /* SDMA + 0xac */
+ volatile u32 EU14; /* SDMA + 0xb0 */
+ volatile u32 EU15; /* SDMA + 0xb4 */
+ volatile u32 EU16; /* SDMA + 0xb8 */
+ volatile u32 EU17; /* SDMA + 0xbc */
+ volatile u32 EU20; /* SDMA + 0xc0 */
+ volatile u32 EU21; /* SDMA + 0xc4 */
+ volatile u32 EU22; /* SDMA + 0xc8 */
+ volatile u32 EU23; /* SDMA + 0xcc */
+ volatile u32 EU24; /* SDMA + 0xd0 */
+ volatile u32 EU25; /* SDMA + 0xd4 */
+ volatile u32 EU26; /* SDMA + 0xd8 */
+ volatile u32 EU27; /* SDMA + 0xdc */
+ volatile u32 EU30; /* SDMA + 0xe0 */
+ volatile u32 EU31; /* SDMA + 0xe4 */
+ volatile u32 EU32; /* SDMA + 0xe8 */
+ volatile u32 EU33; /* SDMA + 0xec */
+ volatile u32 EU34; /* SDMA + 0xf0 */
+ volatile u32 EU35; /* SDMA + 0xf4 */
+ volatile u32 EU36; /* SDMA + 0xf8 */
+ volatile u32 EU37; /* SDMA + 0xfc */
+};
+
+struct mpc5xxx_i2c {
+ volatile u32 madr; /* I2Cn + 0x00 */
+ volatile u32 mfdr; /* I2Cn + 0x04 */
+ volatile u32 mcr; /* I2Cn + 0x08 */
+ volatile u32 msr; /* I2Cn + 0x0C */
+ volatile u32 mdr; /* I2Cn + 0x10 */
+};
+
+struct mpc5xxx_spi {
+ volatile u8 cr1; /* SPI + 0x0F00 */
+ volatile u8 cr2; /* SPI + 0x0F01 */
+ volatile u8 reserved1[2];
+ volatile u8 brr; /* SPI + 0x0F04 */
+ volatile u8 sr; /* SPI + 0x0F05 */
+ volatile u8 reserved2[3];
+ volatile u8 dr; /* SPI + 0x0F09 */
+ volatile u8 reserved3[3];
+ volatile u8 pdr; /* SPI + 0x0F0D */
+ volatile u8 reserved4[2];
+ volatile u8 ddr; /* SPI + 0x0F10 */
+};
+
+
+struct mpc5xxx_gpt {
+ volatile u32 emsr; /* GPT + Timer# * 0x10 + 0x00 */
+ volatile u32 cir; /* GPT + Timer# * 0x10 + 0x04 */
+ volatile u32 pwmcr; /* GPT + Timer# * 0x10 + 0x08 */
+ volatile u32 sr; /* GPT + Timer# * 0x10 + 0x0c */
+};
+
+struct mpc5xxx_gpt_0_7 {
+ struct mpc5xxx_gpt gpt0;
+ struct mpc5xxx_gpt gpt1;
+ struct mpc5xxx_gpt gpt2;
+ struct mpc5xxx_gpt gpt3;
+ struct mpc5xxx_gpt gpt4;
+ struct mpc5xxx_gpt gpt5;
+ struct mpc5xxx_gpt gpt6;
+ struct mpc5xxx_gpt gpt7;
+};
+
+struct mscan_buffer {
+ volatile u8 idr[0x8]; /* 0x00 */
+ volatile u8 dsr[0x10]; /* 0x08 */
+ volatile u8 dlr; /* 0x18 */
+ volatile u8 tbpr; /* 0x19 */ /* This register is not applicable for receive buffers */
+ volatile u16 rsrv1; /* 0x1A */
+ volatile u8 tsrh; /* 0x1C */
+ volatile u8 tsrl; /* 0x1D */
+ volatile u16 rsrv2; /* 0x1E */
+};
+
+struct mpc5xxx_mscan {
+ volatile u8 canctl0; /* MSCAN + 0x00 */
+ volatile u8 canctl1; /* MSCAN + 0x01 */
+ volatile u16 rsrv1; /* MSCAN + 0x02 */
+ volatile u8 canbtr0; /* MSCAN + 0x04 */
+ volatile u8 canbtr1; /* MSCAN + 0x05 */
+ volatile u16 rsrv2; /* MSCAN + 0x06 */
+ volatile u8 canrflg; /* MSCAN + 0x08 */
+ volatile u8 canrier; /* MSCAN + 0x09 */
+ volatile u16 rsrv3; /* MSCAN + 0x0A */
+ volatile u8 cantflg; /* MSCAN + 0x0C */
+ volatile u8 cantier; /* MSCAN + 0x0D */
+ volatile u16 rsrv4; /* MSCAN + 0x0E */
+ volatile u8 cantarq; /* MSCAN + 0x10 */
+ volatile u8 cantaak; /* MSCAN + 0x11 */
+ volatile u16 rsrv5; /* MSCAN + 0x12 */
+ volatile u8 cantbsel; /* MSCAN + 0x14 */
+ volatile u8 canidac; /* MSCAN + 0x15 */
+ volatile u16 rsrv6[3]; /* MSCAN + 0x16 */
+ volatile u8 canrxerr; /* MSCAN + 0x1C */
+ volatile u8 cantxerr; /* MSCAN + 0x1D */
+ volatile u16 rsrv7; /* MSCAN + 0x1E */
+ volatile u8 canidar0; /* MSCAN + 0x20 */
+ volatile u8 canidar1; /* MSCAN + 0x21 */
+ volatile u16 rsrv8; /* MSCAN + 0x22 */
+ volatile u8 canidar2; /* MSCAN + 0x24 */
+ volatile u8 canidar3; /* MSCAN + 0x25 */
+ volatile u16 rsrv9; /* MSCAN + 0x26 */
+ volatile u8 canidmr0; /* MSCAN + 0x28 */
+ volatile u8 canidmr1; /* MSCAN + 0x29 */
+ volatile u16 rsrv10; /* MSCAN + 0x2A */
+ volatile u8 canidmr2; /* MSCAN + 0x2C */
+ volatile u8 canidmr3; /* MSCAN + 0x2D */
+ volatile u16 rsrv11; /* MSCAN + 0x2E */
+ volatile u8 canidar4; /* MSCAN + 0x30 */
+ volatile u8 canidar5; /* MSCAN + 0x31 */
+ volatile u16 rsrv12; /* MSCAN + 0x32 */
+ volatile u8 canidar6; /* MSCAN + 0x34 */
+ volatile u8 canidar7; /* MSCAN + 0x35 */
+ volatile u16 rsrv13; /* MSCAN + 0x36 */
+ volatile u8 canidmr4; /* MSCAN + 0x38 */
+ volatile u8 canidmr5; /* MSCAN + 0x39 */
+ volatile u16 rsrv14; /* MSCAN + 0x3A */
+ volatile u8 canidmr6; /* MSCAN + 0x3C */
+ volatile u8 canidmr7; /* MSCAN + 0x3D */
+ volatile u16 rsrv15; /* MSCAN + 0x3E */
+
+ struct mscan_buffer canrxfg; /* MSCAN + 0x40 */ /* Foreground receive buffer */
+ struct mscan_buffer cantxfg; /* MSCAN + 0x60 */ /* Foreground transmit buffer */
+ };
+
+/* function prototypes */
+void loadtask(int basetask, int tasks);
+
+/* retrieve configured sdram size connected to a chipselect */
+unsigned long mpc5200_get_sdram_size(unsigned int cs);
+
+/* configure a local plus bus chip select */
+#define MPC5200_BOOTCS 8
+void mpc5200_setup_cs(int cs, unsigned long start, unsigned long size, u32 cfg);
+
+/* configure bus speeds. Both dividers are relative to xlb clock */
+int mpc5200_setup_bus_clocks(unsigned int ipbdiv, unsigned long pcidiv);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASMPPC_MPC5XXX_H */
diff --git a/arch/powerpc/mach-mpc5xxx/include/mach/sdma.h b/arch/powerpc/mach-mpc5xxx/include/mach/sdma.h
new file mode 100644
index 0000000000..176ed3e892
--- /dev/null
+++ b/arch/powerpc/mach-mpc5xxx/include/mach/sdma.h
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * This file is based on code
+ * (C) Copyright Motorola, Inc., 2000
+ *
+ * odin smartdma header file
+ */
+
+#ifndef __MPC5XXX_SDMA_H
+#define __MPC5XXX_SDMA_H
+
+#include <common.h>
+#include <mach/mpc5xxx.h>
+
+/* Task number assignment */
+#define FEC_RECV_TASK_NO 0
+#define FEC_XMIT_TASK_NO 1
+
+/*---------------------------------------------------------------------*/
+
+/* Stuff for Ethernet Tx/Rx tasks */
+
+/*---------------------------------------------------------------------*/
+
+/* Layout of Ethernet controller Parameter SRAM area:
+----------------------------------------------------------------
+0x00: TBD_BASE, base address of TX BD ring
+0x04: TBD_NEXT, address of next TX BD to be processed
+0x08: RBD_BASE, base address of RX BD ring
+0x0C: RBD_NEXT, address of next RX BD to be processed
+---------------------------------------------------------------
+ALL PARAMETERS ARE ALL LONGWORDS (FOUR BYTES EACH).
+*/
+
+/* base address of SRAM area to store parameters used by Ethernet tasks */
+#define FEC_PARAM_BASE (MPC5XXX_SRAM + 0x0800)
+
+/* base address of SRAM area for buffer descriptors */
+#define FEC_BD_BASE (MPC5XXX_SRAM + 0x0820)
+
+/*---------------------------------------------------------------------*/
+
+/* common shortcuts used by driver C code */
+
+/*---------------------------------------------------------------------*/
+
+/* Disable SmartDMA task */
+#define SDMA_TASK_DISABLE(tasknum) do { \
+ volatile ushort *tcr = (ushort *)(MPC5XXX_SDMA + 0x0000001c + 2 * tasknum); \
+ *tcr = (*tcr) & (~0x8000); \
+} while (0)
+
+/* Enable SmartDMA task */
+#define SDMA_TASK_ENABLE(tasknum) do { \
+ volatile ushort *tcr = (ushort *) (MPC5XXX_SDMA + 0x0000001c + 2 * tasknum); \
+ *tcr = (*tcr) | 0x8000; \
+} while (0)
+
+/* Enable interrupt */
+#define SDMA_INT_ENABLE(tasknum) do { \
+ struct mpc5xxx_sdma *sdma = (struct mpc5xxx_sdma *)MPC5XXX_SDMA; \
+ sdma->IntMask &= ~(1 << tasknum); \
+} while (0)
+
+/* Disable interrupt */
+#define SDMA_INT_DISABLE(tasknum) do { \
+ struct mpc5xxx_sdma *sdma = (struct mpc5xxx_sdma *)MPC5XXX_SDMA; \
+ sdma->IntMask |= (1 << tasknum); \
+} while (0)
+
+
+/* Clear interrupt pending bits */
+#define SDMA_CLEAR_IEVENT(tasknum) do { \
+ struct mpc5xxx_sdma *sdma = (struct mpc5xxx_sdma *)MPC5XXX_SDMA; \
+ sdma->IntPend = (1 << tasknum); \
+} while (0)
+
+/* get interrupt pending bit of a task */
+#define SDMA_GET_PENDINGBIT(tasknum) \
+ ((*(vu_long *)(MPC5XXX_SDMA + 0x14)) & (1<<(tasknum)))
+
+/* get interrupt mask bit of a task */
+#define SDMA_GET_MASKBIT(tasknum) \
+ ((*(vu_long *)(MPC5XXX_SDMA + 0x18)) & (1<<(tasknum)))
+
+#endif /* __MPC5XXX_SDMA_H */
diff --git a/arch/powerpc/mach-mpc5xxx/loadtask.c b/arch/powerpc/mach-mpc5xxx/loadtask.c
new file mode 100644
index 0000000000..e2489983ee
--- /dev/null
+++ b/arch/powerpc/mach-mpc5xxx/loadtask.c
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * This file is based on code
+ * (C) Copyright Motorola, Inc., 2000
+ */
+
+#include <common.h>
+#include <mach/mpc5xxx.h>
+#include <types.h>
+
+/* BestComm/SmartComm microcode */
+extern int taskTable;
+
+void loadtask(int basetask, int tasks)
+{
+ int *sram = (int *)MPC5XXX_SRAM;
+ int *task_org = &taskTable;
+ unsigned int start, offset, end;
+ int i;
+
+#ifdef DEBUG
+ printf("basetask = %d, tasks = %d\n", basetask, tasks);
+ printf("task_org = 0x%08x\n", (unsigned int)task_org);
+#endif
+
+ /* setup TaskBAR register */
+ *(vu_long *)MPC5XXX_SDMA = MPC5XXX_SRAM;
+
+ /* relocate task table entries */
+ offset = (unsigned int)sram;
+ for (i = basetask; i < basetask + tasks; i++) {
+ sram[i * 8 + 0] = task_org[i * 8 + 0] + offset;
+ sram[i * 8 + 1] = task_org[i * 8 + 1] + offset;
+ sram[i * 8 + 2] = task_org[i * 8 + 2] + offset;
+ sram[i * 8 + 3] = task_org[i * 8 + 3] + offset;
+ sram[i * 8 + 4] = task_org[i * 8 + 4];
+ sram[i * 8 + 5] = task_org[i * 8 + 5];
+ sram[i * 8 + 6] = task_org[i * 8 + 6] + offset;
+ sram[i * 8 + 7] = task_org[i * 8 + 7];
+ }
+
+ /* relocate task descriptors */
+ start = (sram[basetask * 8] - (unsigned int)sram);
+ end = (sram[(basetask + tasks - 1) * 8 + 1] - (unsigned int)sram);
+
+#ifdef DEBUG
+ printf ("TDT start = 0x%08x, end = 0x%08x\n", start, end);
+#endif
+
+ start /= 4;
+ end /= 4;
+ for (i = start; i <= end; i++) {
+ sram[i] = task_org[i];
+ }
+
+ /* relocate variables */
+ start = (sram[basetask * 8 + 2] - (unsigned int)sram);
+ end = (sram[(basetask + tasks - 1) * 8 + 2] + 256 - (unsigned int)sram);
+ start /= 4;
+ end /= 4;
+ for (i = start; i < end; i++) {
+ sram[i] = task_org[i];
+ }
+
+ /* relocate function decriptors */
+ start = ((sram[basetask * 8 + 3] & 0xfffffffc) - (unsigned int)sram);
+ end = ((sram[(basetask + tasks - 1) * 8 + 3] & 0xfffffffc) + 256 - (unsigned int)sram);
+ start /= 4;
+ end /= 4;
+ for (i = start; i < end; i++) {
+ sram[i] = task_org[i];
+ }
+
+ asm volatile ("sync");
+}
diff --git a/arch/powerpc/mach-mpc5xxx/reginfo.c b/arch/powerpc/mach-mpc5xxx/reginfo.c
new file mode 100644
index 0000000000..64816faffc
--- /dev/null
+++ b/arch/powerpc/mach-mpc5xxx/reginfo.c
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <stdio.h>
+#include <common.h>
+#include <config.h>
+#include <mach/mpc5xxx.h>
+#include <asm/io.h>
+
+void reginfo(void)
+{
+ puts ("\nMPC5200 registers\n");
+ printf ("MBAR=%08x\n", CFG_MBAR);
+ puts ("Memory map registers\n");
+ printf ("\tCS0: start %08X\tstop %08X\tconfig %08X\ten %d\n",
+ in_be32((void*)MPC5XXX_CS0_START),
+ in_be32((void*)MPC5XXX_CS0_STOP),
+ in_be32((void*)MPC5XXX_CS0_CFG),
+ in_be32((void*)MPC5XXX_ADDECR) & 0x00010000 ? 1 : 0);
+ printf ("\tCS1: start %08X\tstop %08X\tconfig %08X\ten %d\n",
+ in_be32((void*)MPC5XXX_CS1_START),
+ in_be32((void*)MPC5XXX_CS1_STOP),
+ in_be32((void*)MPC5XXX_CS1_CFG),
+ in_be32((void*)MPC5XXX_ADDECR) & 0x00020000 ? 1 : 0);
+ printf ("\tCS2: start %08X\tstop %08X\tconfig %08X\ten %d\n",
+ in_be32((void*)MPC5XXX_CS2_START),
+ in_be32((void*)MPC5XXX_CS2_STOP),
+ in_be32((void*)MPC5XXX_CS2_CFG),
+ in_be32((void*)MPC5XXX_ADDECR) & 0x00040000 ? 1 : 0);
+ printf ("\tCS3: start %08X\tstop %08X\tconfig %08X\ten %d\n",
+ in_be32((void*)MPC5XXX_CS3_START),
+ in_be32((void*)MPC5XXX_CS3_STOP),
+ in_be32((void*)MPC5XXX_CS3_CFG),
+ in_be32((void*)MPC5XXX_ADDECR) & 0x00080000 ? 1 : 0);
+ printf ("\tCS4: start %08X\tstop %08X\tconfig %08X\ten %d\n",
+ in_be32((void*)MPC5XXX_CS4_START),
+ in_be32((void*)MPC5XXX_CS4_STOP),
+ in_be32((void*)MPC5XXX_CS4_CFG),
+ in_be32((void*)MPC5XXX_ADDECR) & 0x00100000 ? 1 : 0);
+ printf ("\tCS5: start %08X\tstop %08X\tconfig %08X\ten %d\n",
+ in_be32((void*)MPC5XXX_CS5_START),
+ in_be32((void*)MPC5XXX_CS5_STOP),
+ in_be32((void*)MPC5XXX_CS5_CFG),
+ in_be32((void*)MPC5XXX_ADDECR) & 0x00200000 ? 1 : 0);
+ printf ("\tCS6: start %08X\tstop %08X\tconfig %08X\ten %d\n",
+ in_be32((void*)MPC5XXX_CS6_START),
+ in_be32((void*)MPC5XXX_CS6_STOP),
+ in_be32((void*)MPC5XXX_CS6_CFG),
+ in_be32((void*)MPC5XXX_ADDECR) & 0x04000000 ? 1 : 0);
+ printf ("\tCS7: start %08X\tstop %08X\tconfig %08X\ten %d\n",
+ in_be32((void*)MPC5XXX_CS7_START),
+ in_be32((void*)MPC5XXX_CS7_STOP),
+ in_be32((void*)MPC5XXX_CS7_CFG),
+ in_be32((void*)MPC5XXX_ADDECR) & 0x08000000 ? 1 : 0);
+ printf ("\tBOOTCS: start %08X\tstop %08X\tconfig %08X\ten %d\n",
+ in_be32((void*)MPC5XXX_BOOTCS_START),
+ in_be32((void*)MPC5XXX_BOOTCS_STOP),
+ in_be32((void*)MPC5XXX_BOOTCS_CFG),
+ in_be32((void*)MPC5XXX_ADDECR) & 0x02000000 ? 1 : 0);
+ printf ("\tSDRAMCS0: %08X\n",
+ in_be32((void*)MPC5XXX_SDRAM_CS0CFG));
+ printf ("\tSDRAMCS1: %08X\n",
+ in_be32((void*)MPC5XXX_SDRAM_CS1CFG));
+}
diff --git a/arch/powerpc/mach-mpc5xxx/speed.c b/arch/powerpc/mach-mpc5xxx/speed.c
new file mode 100644
index 0000000000..760d923bcf
--- /dev/null
+++ b/arch/powerpc/mach-mpc5xxx/speed.c
@@ -0,0 +1,101 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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.
+ *
+ */
+
+#include <common.h>
+#include <mach/mpc5xxx.h>
+#include <init.h>
+#include <asm/processor.h>
+#include <types.h>
+#include <mach/clock.h>
+
+/* Bus-to-Core Multipliers */
+
+static int bus2core[] = {
+ 3, 2, 2, 2, 4, 4, 5, 9,
+ 6, 11, 8, 10, 3, 12, 7, 0,
+ 6, 5, 13, 2, 14, 4, 15, 9,
+ 0, 11, 8, 10, 16, 12, 7, 0
+};
+
+unsigned long get_bus_clock(void)
+{
+ unsigned long val, vco;
+
+#if !defined(CFG_MPC5XXX_CLKIN)
+#error clock measuring not implemented yet - define CFG_MPC5XXX_CLKIN
+#endif
+
+ val = *(vu_long *)MPC5XXX_CDM_PORCFG;
+ if (val & (1 << 6))
+ vco = CFG_MPC5XXX_CLKIN * 12;
+ else
+ vco = CFG_MPC5XXX_CLKIN * 16;
+
+ if (val & (1 << 5))
+ return vco / 8;
+ else
+ return vco / 4;
+}
+
+unsigned long get_cpu_clock(void)
+{
+ unsigned long val;
+ val = *(vu_long *)MPC5XXX_CDM_PORCFG;
+ return get_bus_clock() * bus2core[val & 0x1f] / 2;
+}
+
+unsigned long get_ipb_clock(void)
+{
+ unsigned long val;
+
+ val = *(vu_long *)MPC5XXX_CDM_CFG;
+ if (val & (1 << 8))
+ return get_bus_clock() / 2;
+ else
+ return get_bus_clock();
+}
+
+unsigned long get_pci_clock(void)
+{
+ unsigned long val;
+
+ val = *(vu_long *)MPC5XXX_CDM_CFG;
+ switch (val & 3) {
+ case 0:
+ return get_ipb_clock();
+ case 1:
+ return get_ipb_clock() / 2;
+ default:
+ return get_bus_clock() / 4;
+ }
+}
+
+unsigned long get_timebase_clock(void)
+{
+ return (get_bus_clock() + 3L) / 4L;
+}
+
+static int prt_mpc5xxx_clks (void)
+{
+ printf(" Bus %ld MHz, IPB %ld MHz, PCI %ld MHz\n",
+ get_bus_clock() / 1000000, get_ipb_clock() / 1000000,
+ get_pci_clock() / 1000000);
+
+ return 0;
+}
+
+late_initcall(prt_mpc5xxx_clks);
+
diff --git a/arch/powerpc/mach-mpc5xxx/start.S b/arch/powerpc/mach-mpc5xxx/start.S
new file mode 100644
index 0000000000..31648a6529
--- /dev/null
+++ b/arch/powerpc/mach-mpc5xxx/start.S
@@ -0,0 +1,736 @@
+/*
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ * Copyright (C) 2000 - 2003 Wolfgang Denk <wd@denx.de>
+ *
+ * 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.
+ *
+ */
+
+/*
+ * barebox - Startup Code for MPC5xxx CPUs
+ */
+#include <config.h>
+
+#include <asm/ppc_asm.tmpl>
+#include <asm/ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+/* We don't want the MMU yet.
+*/
+#undef MSR_KERNEL
+/* Floating Point enable, Machine Check and Recoverable Interr. */
+#ifdef DEBUG
+#define MSR_KERNEL (MSR_FP|MSR_RI)
+#else
+#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
+#endif
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r14 to access the GOT
+ */
+ START_GOT
+ GOT_ENTRY(_GOT2_TABLE_)
+ GOT_ENTRY(_FIXUP_TABLE_)
+
+ GOT_ENTRY(_start)
+ GOT_ENTRY(_start_of_vectors)
+ GOT_ENTRY(_end_of_vectors)
+ GOT_ENTRY(transfer_to_handler)
+
+ GOT_ENTRY(__init_end)
+ GOT_ENTRY(_end)
+ GOT_ENTRY(__bss_start)
+ END_GOT
+
+/*
+ * Exception vectors
+ */
+ .text
+ /*
+ * Second stage loader entry. When entered here we assume that spr 311
+ * is set to the current MBAR address.
+ */
+ mfspr r4, MBAR
+ b setup_mbar
+ . = EXC_OFF_SYS_RESET
+ .globl _start
+_start:
+ /*
+ * Reset entry. When entered here we assume that MBAR is at reset default
+ * 0x80000000.
+ */
+ lis r4, 0x80000000@h
+ ori r4, r4, 0x80000000@l
+
+setup_mbar:
+ /* r4 == current MBAR */
+ mfmsr r5 /* save msr contents */
+
+ /* Switch MBAR to 0xf0000000 */
+ lis r3, 0xf0000000@h
+ ori r3, r3, 0xf0000000@l
+ mtspr MBAR, r3
+ rlwinm r3, r3, 16, 16, 31
+ stw r3, 0(r4)
+
+ /* Initialise the MPC5xxx processor core */
+ /*--------------------------------------------------------------*/
+
+ bl init_5xxx_core
+
+ /* initialize some things that are hard to access from C */
+ /*--------------------------------------------------------------*/
+
+ /* set up stack in on-chip SRAM */
+ lis r1, (MPC5XXX_SRAM + MPC5XXX_SRAM_SIZE)@h
+ ori r1, r1, (MPC5XXX_SRAM + MPC5XXX_SRAM_SIZE)@l
+ li r0, 0 /* Make room for stack frame header and */
+ stwu r0, -4(r1) /* clear final stack frame so that */
+ stwu r0, -4(r1) /* stack backtraces terminate cleanly */
+
+ /* let the C-code set up the rest */
+ /* */
+ /* Be careful to keep code relocatable ! */
+ /*--------------------------------------------------------------*/
+
+ GET_GOT /* initialize GOT access */
+
+ /* r3: IMMR */
+ bl cpu_init /* run low-level CPU init code (in Flash)*/
+
+ mr r3, r21
+ /* r3: BOOTFLAG */
+ bl initdram /* initialize sdram */
+ /* r3: End of RAM */
+
+ b _continue_init
+/*
+ * Vector Table
+ */
+
+ .globl _start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+ STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. */
+ STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. */
+ STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* 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)
+
+ STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+ /* I guess we could implement decrementer, and may have
+ * to someday for timekeeping.
+ */
+ STD_EXCEPTION(0x900, Decrementer, UnknownException)
+ STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+ STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+ STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+ STD_EXCEPTION(0xd00, SingleStep, UnknownException)
+
+ STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+ STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+
+ STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
+#ifdef DEBUG
+ . = 0x1300
+ /*
+ * This exception occurs when the program counter matches the
+ * Instruction Address Breakpoint Register (IABR).
+ *
+ * I want the cpu to halt if this occurs so I can hunt around
+ * with the debugger and look at things.
+ *
+ * When DEBUG is defined, both machine check enable (in the MSR)
+ * and checkstop reset enable (in the reset mode register) are
+ * turned off and so a checkstop condition will result in the cpu
+ * halting.
+ *
+ * I force the cpu into a checkstop condition by putting an illegal
+ * instruction here (at least this is the theory).
+ *
+ * well - that didnt work, so just do an infinite loop!
+ */
+1: b 1b
+#else
+ STD_EXCEPTION(0x1300, InstructionBreakpoint, DebugException)
+#endif
+ STD_EXCEPTION(0x1400, SMI, UnknownException)
+
+ STD_EXCEPTION(0x1500, Trap_15, UnknownException)
+ STD_EXCEPTION(0x1600, Trap_16, UnknownException)
+ STD_EXCEPTION(0x1700, Trap_17, UnknownException)
+ STD_EXCEPTION(0x1800, Trap_18, UnknownException)
+ STD_EXCEPTION(0x1900, Trap_19, UnknownException)
+ STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
+ STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
+ STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
+ STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
+ STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
+ STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
+ STD_EXCEPTION(0x2000, Trap_20, UnknownException)
+ STD_EXCEPTION(0x2100, Trap_21, UnknownException)
+ STD_EXCEPTION(0x2200, Trap_22, UnknownException)
+ STD_EXCEPTION(0x2300, Trap_23, UnknownException)
+ STD_EXCEPTION(0x2400, Trap_24, UnknownException)
+ STD_EXCEPTION(0x2500, Trap_25, UnknownException)
+ STD_EXCEPTION(0x2600, Trap_26, UnknownException)
+ STD_EXCEPTION(0x2700, Trap_27, UnknownException)
+ STD_EXCEPTION(0x2800, Trap_28, UnknownException)
+ STD_EXCEPTION(0x2900, Trap_29, UnknownException)
+ STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
+ STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
+ STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
+ STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
+ STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
+ STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
+
+
+ .globl _end_of_vectors
+_end_of_vectors:
+
+ . = 0x3000
+
+_continue_init:
+ mr r9, r3 /* Save copy of end of RAM */
+
+#ifdef CONFIG_RELOCATABLE
+ lis r10, (_end - _start)@h /* Size */
+ ori r10, r10, (_end - _start)@l
+ sub r3, r3, r10
+ subi r3, r3, 0x100
+#else
+ lis r3, (TEXT_BASE)@h /* Destination Address */
+ ori r3, r3, (TEXT_BASE)@l
+#endif
+
+ mr r1, r3 /* Set new stack just below barebox code */
+ subi r1, r1, 0x10
+
+ mr r10, r3 /* Save copy of Destination Address */
+
+ bl calc_source /* Calculate Source Address */
+calc_source:
+ mfspr r4, LR
+ subi r4, r4, (calc_source - _start)
+ subi r4, r4, 0x100
+
+ lis r5, __init_size@h /* Size */
+ ori r5, r5, __init_size@l
+
+before_relocate:
+ /*
+ * We are now ready to copy barebox to RAM.
+ *
+ * destination = r3
+ * source = r4
+ * size = r5
+ *
+ */
+
+ li r6, CACHELINE_SIZE
+
+ /*
+ * Fix GOT pointer:
+ *
+ * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
+ *
+ * Offset:
+ */
+ sub r15, r10, r4
+
+ /* First our own GOT */
+ add r14, r14, r15
+ /* then the one used by the C code */
+ add r30, r30, r15
+
+ /*
+ * Now relocate code
+ */
+
+ cmplw cr1,r3,r4
+ addi r0,r5,3
+ srwi. r0,r0,2
+ beq cr1,4f /* In place copy is not necessary */
+ beq 7f /* Protect against 0 count */
+ mtctr r0
+ bge cr1,2f
+
+ la r8,-4(r4)
+ la r7,-4(r3)
+1: lwzu r0,4(r8)
+ stwu r0,4(r7)
+ bdnz 1b
+ b 4f
+
+2: slwi r0,r0,2
+ add r8,r4,r0
+ add r7,r3,r0
+3: lwzu r0,-4(r8)
+ stwu r0,-4(r7)
+ bdnz 3b
+
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4: cmpwi r6,0
+ add r5,r3,r5
+ beq 7f /* Always flush prefetch queue in any case */
+ subi r0,r6,1
+ andc r3,r3,r0
+ mfspr r7,HID0 /* don't do dcbst if dcache is disabled */
+ rlwinm r7,r7,HID0_DCE_BITPOS+1,31,31
+ cmpwi r7,0
+ beq 9f
+ mr r4,r3
+5: dcbst 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 5b
+ sync /* Wait for all dcbst to complete on bus */
+9: mfspr r7,HID0 /* don't do icbi if icache is disabled */
+ rlwinm r7,r7,HID0_ICE_BITPOS+1,31,31
+ cmpwi r7,0
+ beq 7f
+ mr r4,r3
+6: icbi 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 6b
+7: sync /* Wait for all icbi to complete on bus */
+ isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+
+ addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+ mtlr r0
+ blr
+
+in_ram:
+
+ /*
+ * Relocation Function, r14 point to got2+0x8000
+ *
+ * Adjust got2 pointers, no need to check for 0, this code
+ * already puts a few entries in the table.
+ */
+ li r0,__got2_entries@sectoff@l
+ la r3,GOT(_GOT2_TABLE_)
+ lwz r11,GOT(_GOT2_TABLE_)
+ mtctr r0
+ sub r11,r3,r11
+ addi r3,r3,-4
+1: lwzu r0,4(r3)
+ add r0,r0,r11
+ stw r0,0(r3)
+ bdnz 1b
+
+ /*
+ * Now adjust the fixups and the pointers to the fixups
+ * in case we need to move ourselves again.
+ */
+2: li r0,__fixup_entries@sectoff@l
+ lwz r3,GOT(_FIXUP_TABLE_)
+ cmpwi r0,0
+ mtctr r0
+ addi r3,r3,-4
+ beq 4f
+3: lwzu r4,4(r3)
+ lwzux r0,r4,r11
+ add r0,r0,r11
+ stw r10,0(r3)
+ stw r0,0(r4)
+ bdnz 3b
+4:
+clear_bss:
+ /*
+ * Now clear BSS segment
+ */
+ lwz r3,GOT(__bss_start)
+ lwz r4,GOT(_end)
+
+ cmplw 0, r3, r4
+ beq 6f
+
+ li r0, 0
+5:
+ stw r0, 0(r3)
+ addi r3, r3, 4
+ cmplw 0, r3, r4
+ bne 5b
+6:
+
+ mr r3, r9 /* end of RAM */
+ bl board_init_r
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+ .globl transfer_to_handler
+transfer_to_handler:
+ stw r22,_NIP(r21)
+ lis r22,MSR_POW@h
+ andc r23,r23,r22
+ stw r23,_MSR(r21)
+ SAVE_GPR(7, r21)
+ SAVE_4GPRS(8, r21)
+ SAVE_8GPRS(12, r21)
+ SAVE_8GPRS(24, r21)
+ mflr r23
+ andi. r24,r23,0x3f00 /* get vector offset */
+ stw r24,TRAP(r21)
+ li r22,0
+ stw r22,RESULT(r21)
+ lwz r24,0(r23) /* virtual address of handler */
+ lwz r23,4(r23) /* where to go when done */
+ mtspr SRR0,r24
+ mtspr SRR1,r20
+ mtlr r23
+ SYNC
+ rfi /* jump to handler, enable MMU */
+
+int_return:
+ mfmsr r28 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r28,r28,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r28
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SRR0,r2
+ mtspr SRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfi
+
+/*
+ * This code initialises the MPC5xxx processor core
+ * (conforms to PowerPC 603e spec)
+ * Note: expects original MSR contents to be in r5.
+ */
+
+ .globl init_5xx_core
+init_5xxx_core:
+
+ /* Initialize machine status; enable machine check interrupt */
+ /*--------------------------------------------------------------*/
+
+ li r3, MSR_KERNEL /* Set ME and RI flags */
+ rlwimi r3, r5, 0, 25, 25 /* preserve IP bit set by HRCW */
+#ifdef DEBUG
+ rlwimi r3, r5, 0, 21, 22 /* debugger might set SE & BE bits */
+#endif
+ SYNC /* Some chip revs need this... */
+ mtmsr r3
+ SYNC
+ mtspr SRR1, r3 /* Make SRR1 match MSR */
+
+ /* Initialize the Hardware Implementation-dependent Registers */
+ /* HID0 also contains cache control */
+ /*--------------------------------------------------------------*/
+
+ lis r3, CFG_HID0_INIT@h
+ ori r3, r3, CFG_HID0_INIT@l
+ SYNC
+ mtspr HID0, r3
+
+ lis r3, CFG_HID0_FINAL@h
+ ori r3, r3, CFG_HID0_FINAL@l
+ SYNC
+ mtspr HID0, r3
+
+ /* clear all BAT's */
+ /*--------------------------------------------------------------*/
+
+ li r0, 0
+ mtspr DBAT0U, r0
+ mtspr DBAT0L, r0
+ mtspr DBAT1U, r0
+ mtspr DBAT1L, r0
+ mtspr DBAT2U, r0
+ mtspr DBAT2L, r0
+ mtspr DBAT3U, r0
+ mtspr DBAT3L, r0
+ mtspr DBAT4U, r0
+ mtspr DBAT4L, r0
+ mtspr DBAT5U, r0
+ mtspr DBAT5L, r0
+ mtspr DBAT6U, r0
+ mtspr DBAT6L, r0
+ mtspr DBAT7U, r0
+ mtspr DBAT7L, r0
+ mtspr IBAT0U, r0
+ mtspr IBAT0L, r0
+ mtspr IBAT1U, r0
+ mtspr IBAT1L, r0
+ mtspr IBAT2U, r0
+ mtspr IBAT2L, r0
+ mtspr IBAT3U, r0
+ mtspr IBAT3L, r0
+ mtspr IBAT4U, r0
+ mtspr IBAT4L, r0
+ mtspr IBAT5U, r0
+ mtspr IBAT5L, r0
+ mtspr IBAT6U, r0
+ mtspr IBAT6L, r0
+ mtspr IBAT7U, r0
+ mtspr IBAT7L, r0
+ SYNC
+
+ /* invalidate all tlb's */
+ /* */
+ /* From the 603e User Manual: "The 603e provides the ability to */
+ /* invalidate a TLB entry. The TLB Invalidate Entry (tlbie) */
+ /* instruction invalidates the TLB entry indexed by the EA, and */
+ /* operates on both the instruction and data TLBs simultaneously*/
+ /* invalidating four TLB entries (both sets in each TLB). The */
+ /* index corresponds to bits 15-19 of the EA. To invalidate all */
+ /* entries within both TLBs, 32 tlbie instructions should be */
+ /* issued, incrementing this field by one each time." */
+ /* */
+ /* "Note that the tlbia instruction is not implemented on the */
+ /* 603e." */
+ /* */
+ /* bits 15-19 correspond to addresses 0x00000000 to 0x0001F000 */
+ /* incrementing by 0x1000 each time. The code below is sort of */
+ /* based on code in "flush_tlbs" from arch/ppc/kernel/head.S */
+ /* */
+ /*--------------------------------------------------------------*/
+
+ li r3, 32
+ mtctr r3
+ li r3, 0
+1: tlbie r3
+ addi r3, r3, 0x1000
+ bdnz 1b
+ SYNC
+
+ /* Done! */
+ /*--------------------------------------------------------------*/
+
+ blr
+
+/* Cache functions.
+ *
+ * Note: requires that all cache bits in
+ * HID0 are in the low half word.
+ */
+ .globl icache_enable
+icache_enable:
+ mfspr r3, HID0
+ ori r3, r3, HID0_ICE
+ lis r4, 0
+ ori r4, r4, HID0_ILOCK
+ andc r3, r3, r4
+ ori r4, r3, HID0_ICFI
+ isync
+ mtspr HID0, r4 /* sets enable and invalidate, clears lock */
+ isync
+ mtspr HID0, r3 /* clears invalidate */
+ blr
+
+ .globl icache_disable
+icache_disable:
+ mfspr r3, HID0
+ lis r4, 0
+ ori r4, r4, HID0_ICE|HID0_ILOCK
+ andc r3, r3, r4
+ ori r4, r3, HID0_ICFI
+ isync
+ mtspr HID0, r4 /* sets invalidate, clears enable and lock */
+ isync
+ mtspr HID0, r3 /* clears invalidate */
+ blr
+
+ .globl icache_status
+icache_status:
+ mfspr r3, HID0
+ rlwinm r3, r3, HID0_ICE_BITPOS + 1, 31, 31
+ blr
+
+ .globl dcache_enable
+dcache_enable:
+ mfspr r3, HID0
+ ori r3, r3, HID0_DCE
+ lis r4, 0
+ ori r4, r4, HID0_DLOCK
+ andc r3, r3, r4
+ ori r4, r3, HID0_DCI
+ sync
+ mtspr HID0, r4 /* sets enable and invalidate, clears lock */
+ sync
+ mtspr HID0, r3 /* clears invalidate */
+ blr
+
+ .globl dcache_disable
+dcache_disable:
+ mfspr r3, HID0
+ lis r4, 0
+ ori r4, r4, HID0_DCE|HID0_DLOCK
+ andc r3, r3, r4
+ ori r4, r3, HID0_DCI
+ sync
+ mtspr HID0, r4 /* sets invalidate, clears enable and lock */
+ sync
+ mtspr HID0, r3 /* clears invalidate */
+ blr
+
+ .globl dcache_status
+dcache_status:
+ mfspr r3, HID0
+ rlwinm r3, r3, HID0_DCE_BITPOS + 1, 31, 31
+ blr
+
+ .globl get_svr
+get_svr:
+ mfspr r3, SVR
+ blr
+
+ .globl get_pvr
+get_pvr:
+ mfspr r3, PVR
+ blr
+
+ /*
+ * Copy exception vector code to low memory
+ *
+ * r3: dest_addr
+ * r7: source address, r8: end address, r9: target address
+ */
+ .globl trap_init
+trap_init:
+ lwz r7, GOT(_start)
+ lwz r8, GOT(_end_of_vectors)
+
+ li r9, 0x100 /* reset vector always at 0x100 */
+
+ cmplw 0, r7, r8
+ bgelr /* return if r7>=r8 - just in case */
+
+ mflr r4 /* save link register */
+1:
+ lwz r0, 0(r7)
+ stw r0, 0(r9)
+ addi r7, r7, 4
+ addi r9, r9, 4
+ cmplw 0, r7, r8
+ bne 1b
+
+ /*
+ * relocate `hdlr' and `int_return' entries
+ */
+ li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+ li r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 2b
+
+ li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+ li r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 3b
+
+ li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
+ li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 4b
+
+ mfmsr r3 /* now that the vectors have */
+ lis r7, MSR_IP@h /* relocated into low memory */
+ ori r7, r7, MSR_IP@l /* MSR[IP] can be turned off */
+ andc r3, r3, r7 /* (if it was on) */
+ SYNC /* Some chip revs need this... */
+ mtmsr r3
+ SYNC
+
+ mtlr r4 /* restore link register */
+ blr
+
+.globl _text_base
+_text_base:
+ .long TEXT_BASE
+
+.globl _barebox_start
+_barebox_start:
+ .long _start
+
+.globl _bss_start
+_bss_start:
+ .long __bss_start
+
+.globl _bss_end
+_bss_end:
+ .long _end
diff --git a/arch/powerpc/mach-mpc5xxx/time.c b/arch/powerpc/mach-mpc5xxx/time.c
new file mode 100644
index 0000000000..d690d50f0d
--- /dev/null
+++ b/arch/powerpc/mach-mpc5xxx/time.c
@@ -0,0 +1,45 @@
+/*
+ * (C) Copyright 2000, 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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.
+ *
+ */
+
+#include <common.h>
+#include <clock.h>
+#include <init.h>
+#include <mach/clock.h>
+#include <asm/common.h>
+
+static uint64_t ppc_clocksource_read(void)
+{
+ return get_ticks();
+}
+
+static struct clocksource cs = {
+ .read = ppc_clocksource_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 15,
+ .priority = 80,
+};
+
+static int clocksource_init(void)
+{
+ /* reset time base */
+ asm ("li 3,0 ; mttbu 3 ; mttbl 3 ;");
+
+ cs.mult = clocksource_hz2mult(get_timebase_clock(), cs.shift);
+
+ return init_clock(&cs);
+}
+
+core_initcall(clocksource_init);
diff --git a/arch/powerpc/mach-mpc5xxx/traps.c b/arch/powerpc/mach-mpc5xxx/traps.c
new file mode 100644
index 0000000000..e93b5d6d75
--- /dev/null
+++ b/arch/powerpc/mach-mpc5xxx/traps.c
@@ -0,0 +1,196 @@
+/*
+ * linux/arch/ppc/kernel/traps.c
+ *
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ * fixed Machine Check Reasons by Reinhard Meyer (r.meyer@emk-elektronik.de)
+ *
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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.
+ *
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/processor.h>
+
+#ifdef CONFIG_KGDB
+int (*debugger_exception_handler)(struct pt_regs *) = 0;
+#endif
+
+/* 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");
+}
+
+static 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;
+
+ /* Probing PCI using config cycles cause this exception
+ * when a device is not present. Catch it and return to
+ * the PCI exception handler.
+ */
+ if ((fixup = search_exception_table(regs->nip)) != 0) {
+ regs->nip = fixup;
+ return;
+ }
+
+#ifdef CONFIG_KGDB
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ printf("Machine check in kernel mode.\n");
+ printf("Caused by (from msr): ");
+ printf("regs %p ",regs);
+ /* refer to 603e Manual (MPC603EUM/AD), chapter 4.5.2.1 */
+ switch( regs->msr & 0x000F0000)
+ {
+ case (0x80000000>>12) :
+ printf("Machine check signal - probably due to mm fault\n"
+ "with mmu off\n");
+ break;
+ case (0x80000000>>13) :
+ printf("Transfer error ack signal\n");
+ break;
+ case (0x80000000>>14) :
+ printf("Data parity signal\n");
+ break;
+ case (0x80000000>>15) :
+ printf("Address parity signal\n");
+ break;
+ default:
+ printf("Unknown values in msr\n");
+ }
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("machine check");
+}
+
+void
+AlignmentException(struct pt_regs *regs)
+{
+#ifdef 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)
+{
+#ifdef CONFIG_KGDB
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Program Check Exception");
+}
+
+void
+UnknownException(struct pt_regs *regs)
+{
+#ifdef 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);
+}
+
+#ifdef CONFIG_BEDBUG
+extern void do_bedbug_breakpoint(struct pt_regs *);
+#endif
+
+void
+DebugException(struct pt_regs *regs)
+{
+
+ printf("Debugger trap at @ %lx\n", regs->nip );
+ show_regs(regs);
+#ifdef CONFIG_BEDBUG
+ do_bedbug_breakpoint( regs );
+#endif
+}
diff --git a/arch/powerpc/mach-mpc85xx/.gitignore b/arch/powerpc/mach-mpc85xx/.gitignore
new file mode 100644
index 0000000000..03987a7009
--- /dev/null
+++ b/arch/powerpc/mach-mpc85xx/.gitignore
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+barebox.lds
diff --git a/arch/powerpc/mach-mpc85xx/Kconfig b/arch/powerpc/mach-mpc85xx/Kconfig
new file mode 100644
index 0000000000..550c554286
--- /dev/null
+++ b/arch/powerpc/mach-mpc85xx/Kconfig
@@ -0,0 +1,106 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+if ARCH_MPC85XX
+
+config MMU
+ default y
+
+config BTB
+ bool
+ default y
+
+config TEXT_BASE
+ hex
+ default 0xeff80000 if P1010RDB || P2020RDB || P1022DS
+ default 0xfff80000 if DA923RC
+
+config RESET_VECTOR_ADDRESS
+ hex
+ default 0xfffffffc if DA923RC
+ default 0xeffffffc if P1010RDB || P2020RDB || P1022DS
+
+config MPC85xx
+ bool
+ default y
+
+config BOOKE
+ bool
+ default y
+
+config E500
+ bool
+ default y
+
+choice
+ prompt "Select your board"
+config P1010RDB
+ bool "P1010RDB"
+ select P1010
+ select DDR_SPD
+ select FSL_DDR3
+ help
+ Say Y here if you are using the Freescale P1010RDB
+
+config P2020RDB
+ bool "P2020RDB"
+ select P2020
+ select FSL_ELBC
+ help
+ Say Y here if you are using the Freescale P2020RDB
+
+config P1022DS
+ bool "P1022DS"
+ select P1022
+ select DDR_SPD
+ select FSL_DDR3
+ select FSL_ELBC
+ help
+ Say Y here if you are using the Freescale P1022DS
+
+config DA923RC
+ bool "DA923RC"
+ select MPC8544
+ select DDR_SPD
+ select FSL_DDR2
+ help
+ Say Y here if you are using the GE Intelligent Platforms DA923RC
+endchoice
+endif
+
+config P1010
+ select FSL_IFC
+ select FSL_ERRATUM_IFC_A002769
+ select FSL_ERRATUM_P1010_A003549
+ select FSL_ERRATUM_IFC_A003399
+ bool
+
+config P2020
+ bool
+
+config P1022
+ bool
+
+config MPC8544
+ bool
+
+config FSL_DDR2
+ bool
+
+config FSL_DDR3
+ bool
+
+config FSL_IFC
+ bool
+
+config FSL_ELBC
+ bool
+
+config FSL_ERRATUM_IFC_A002769
+ bool
+
+config FSL_ERRATUM_IFC_A003399
+ bool
+
+config FSL_ERRATUM_P1010_A003549
+ bool
+
diff --git a/arch/powerpc/mach-mpc85xx/Makefile b/arch/powerpc/mach-mpc85xx/Makefile
new file mode 100644
index 0000000000..3e23c1b812
--- /dev/null
+++ b/arch/powerpc/mach-mpc85xx/Makefile
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-y += cpuid.o
+obj-y += cpu.o
+obj-y += cpu_init.o
+obj-y += fsl_law.o
+obj-y += speed.o
+obj-y +=time.o
+obj-y += fsl_gpio.o
+obj-y += fsl_i2c.o
+obj-$(CONFIG_MP) += mp.o
+obj-$(CONFIG_OFTREE) += fdt.o
+obj-$(CONFIG_DRIVER_NET_GIANFAR) += eth-devices.o
+extra-y += barebox.lds
diff --git a/arch/powerpc/mach-mpc85xx/barebox.lds.S b/arch/powerpc/mach-mpc85xx/barebox.lds.S
new file mode 100644
index 0000000000..6e348d4db3
--- /dev/null
+++ b/arch/powerpc/mach-mpc85xx/barebox.lds.S
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2013 GE Intelligent Platforms, Inc.
+ * Copyright 2007-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.
+ */
+
+#include <asm/barebox.lds.h>
+
+#ifdef CONFIG_RESET_VECTOR_ADDRESS
+#define RESET_VECTOR_ADDRESS CONFIG_RESET_VECTOR_ADDRESS
+#else
+#define RESET_VECTOR_ADDRESS 0xfffffffc
+#endif
+
+OUTPUT_ARCH(BAREBOX_OUTPUT_ARCH)
+ENTRY(_start_e500)
+
+PHDRS
+{
+ text PT_LOAD;
+ bss PT_LOAD;
+}
+
+SECTIONS
+{
+ . = TEXT_BASE;
+ _stext = .;
+ PROVIDE (stext = .);
+
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata)}
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ *(.text*)
+ *(.got1*)
+
+ } :text
+ _etext = .;
+ PROVIDE (etext = .);
+ _sdata = .;
+
+ .barebox_imd : { BAREBOX_IMD }
+
+ .rodata :
+ {
+ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+ RO_DATA_SECTION
+ } :text
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ KEEP(*(.got))
+ _GOT2_TABLE_ = .;
+ KEEP(*(.got2))
+ PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4);
+ _FIXUP_TABLE_ = .;
+ KEEP(*(.fixup))
+ }
+ __got2_entries = ((_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2);
+ __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+ .data :
+ {
+ *(.data*)
+ *(.data1*)
+ *(.sdata*)
+ *(.sdata2*)
+ *(.dynamic*)
+ CONSTRUCTORS
+ }
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+ __init_size = __init_end - _start;
+
+ .bootpg RESET_VECTOR_ADDRESS - 0xffc :
+ {
+ _text = .;
+ arch/powerpc/cpu-85xx/start.o (.bootpg)
+ } :text = 0xffff
+
+ .resetvec RESET_VECTOR_ADDRESS :
+ {
+ KEEP(*(.resetvec))
+ arch/powerpc/cpu-85xx/resetvec.o (.resetvec)
+ } :text = 0xffff
+
+ . = RESET_VECTOR_ADDRESS + 0x4;
+
+#if (RESET_VECTOR_ADDRESS == 0xfffffffc)
+ /* This avoids wrapping around to offset 0 */
+ . |= 0x10;
+#endif
+
+ __bss_start = .;
+ .bss :
+ {
+ *(.sbss*) *(.scommon*)
+ *(.dynbss*)
+ *(.bss*)
+ *(COMMON)
+ } :bss
+ . = ALIGN(4);
+ __bss_stop = .;
+ _end = . ;
+ PROVIDE (end = .);
+}
diff --git a/arch/powerpc/mach-mpc85xx/cpu.c b/arch/powerpc/mach-mpc85xx/cpu.c
new file mode 100644
index 0000000000..2119352f84
--- /dev/null
+++ b/arch/powerpc/mach-mpc85xx/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@motorola.com)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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.
+ *
+ */
+
+#include <config.h>
+#include <common.h>
+#include <memory.h>
+#include <init.h>
+#include <restart.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <asm-generic/memory_layout.h>
+#include <mach/mmu.h>
+#include <mach/immap_85xx.h>
+#include <mach/mpc85xx.h>
+
+static void __noreturn mpc85xx_restart_soc(struct restart_handler *rst)
+{
+ 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);
+
+ hang();
+}
+
+static int restart_register_feature(void)
+{
+ restart_handler_register_fn("soc", mpc85xx_restart_soc);
+
+ return 0;
+}
+coredevice_initcall(restart_register_feature);
+
+/* Called from assembly */
+long int initdram(int board_type);
+
+long int initdram(int board_type)
+{
+ phys_size_t dram_size = 0;
+
+ if (IS_ENABLED(CONFIG_DDR_SPD))
+ dram_size = fsl_ddr_sdram();
+ else
+ dram_size = fixed_sdram();
+ dram_size = e500_setup_ddr_tlbs(dram_size / 0x100000);
+ dram_size *= 0x100000;
+
+ return dram_size;
+}
+
+/*
+ * Return the memory size based on the configuration registers.
+ */
+phys_size_t fsl_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 * 4)) &
+ 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;
+}
+
+static int fsl_reserve_region(void)
+{
+ request_sdram_region("stack", _text_base - STACK_SIZE,
+ STACK_SIZE);
+ return 0;
+}
+coredevice_initcall(fsl_reserve_region);
diff --git a/arch/powerpc/mach-mpc85xx/cpu_init.c b/arch/powerpc/mach-mpc85xx/cpu_init.c
new file mode 100644
index 0000000000..3259945fda
--- /dev/null
+++ b/arch/powerpc/mach-mpc85xx/cpu_init.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2012 GE Intelligent Platforms, Inc.
+ *
+ * Copyright 2007-2011 Freescale Semiconductor, Inc.
+ *
+ * (C) Copyright 2003 Motorola Inc.
+ * Modified by Xianghua Xiao, X.Xiao@motorola.com
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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.
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <asm/processor.h>
+#include <asm/cache.h>
+#include <asm/fsl_law.h>
+#include <asm/fsl_ifc.h>
+#include <mach/mpc85xx.h>
+#include <mach/mmu.h>
+#include <mach/immap_85xx.h>
+
+/* NOR workaround for P1010 erratum A003399 */
+#if defined(CONFIG_FSL_ERRATUM_P1010_A003549)
+#define SRAM_BASE_ADDR 0x100
+static void setup_ifc(void)
+{
+ u32 mas0, mas1, mas2, mas3, mas7;
+ phys_addr_t flash_phys = CFG_FLASH_BASE_PHYS;
+
+ /*
+ * Adjust the TLB we were running out of to match the phys addr of the
+ * chip select we are adjusting and will return to.
+ */
+ flash_phys += (~CFG_IFC_AMASK0) + 1 - 4*1024*1024;
+ mas0 = MAS0_TLBSEL(1) | MAS0_ESEL(15);
+ mas1 = MAS1_VALID | MAS1_TID(0) | MAS1_TS | MAS1_IPROT |
+ MAS1_TSIZE(BOOKE_PAGESZ_4M);
+ mas2 = FSL_BOOKE_MAS2(CONFIG_TEXT_BASE, MAS2_I|MAS2_G);
+ mas3 = FSL_BOOKE_MAS3(flash_phys, 0, MAS3_SW|MAS3_SR|MAS3_SX);
+ mas7 = FSL_BOOKE_MAS7(flash_phys);
+ mtspr(MAS0, mas0);
+ mtspr(MAS1, mas1);
+ mtspr(MAS2, mas2);
+ mtspr(MAS3, mas3);
+ mtspr(MAS7, mas7);
+ asm volatile("isync;msync;tlbwe;isync");
+
+#if defined(PPC_E500_DEBUG_TLB)
+ /*
+ * TLB entry for debuggging in AS1
+ * Create temporary TLB entry in AS0 to handle debug exception
+ * As on debug exception MSR is cleared i.e. Address space is
+ * changed to 0. A TLB entry (in AS0) is required to handle
+ * debug exception generated * in AS1.
+ *
+ * TLB entry is created for IVPR + IVOR15 to map on valid OP
+ * code address because flash's physical address is going to
+ * change as CFG_FLASH_BASE_PHYS.
+ */
+ mas0 = MAS0_TLBSEL(1) | MAS0_ESEL(PPC_E500_DEBUG_TLB);
+ mas1 = MAS1_VALID | MAS1_TID(0) | MAS1_IPROT |
+ MAS1_TSIZE(BOOKE_PAGESZ_4M);
+ mas2 = FSL_BOOKE_MAS2(CONFIG_TEXT_BASE, MAS2_I|MAS2_G);
+ mas3 = FSL_BOOKE_MAS3(flash_phys, 0, MAS3_SW|MAS3_SR|MAS3_SX);
+ mas7 = FSL_BOOKE_MAS7(flash_phys);
+
+ mtspr(MAS0, mas0);
+ mtspr(MAS1, mas1);
+ mtspr(MAS2, mas2);
+ mtspr(MAS3, mas3);
+ mtspr(MAS7, mas7);
+
+ asm volatile("isync;msync;tlbwe;isync");
+#endif
+ set_ifc_cspr(0, CFG_IFC_CSPR0);
+ set_ifc_csor(0, CFG_IFC_CSOR0);
+ set_ifc_amask(0, CFG_IFC_AMASK0);
+}
+
+static void fsl_erratum_ifc_a003399(void)
+{
+ u32 mas0, mas1, mas2, mas3, mas7;
+ void __iomem *l2cache = IOMEM(MPC85xx_L2_ADDR);
+ void (*setup_ifc_sram)(void) = (void *)SRAM_BASE_ADDR;
+ u32 *dst, *src, ix;
+
+ /* TLB for SRAM */
+ mas0 = MAS0_TLBSEL(1) | MAS0_ESEL(9);
+ mas1 = MAS1_VALID | MAS1_TID(0) | MAS1_TS |
+ MAS1_TSIZE(BOOKE_PAGESZ_1M);
+ mas2 = FSL_BOOKE_MAS2(SRAM_BASE_ADDR, MAS2_I);
+ mas3 = FSL_BOOKE_MAS3(SRAM_BASE_ADDR, 0,
+ MAS3_SX | MAS3_SW | MAS3_SR);
+ mas7 = FSL_BOOKE_MAS7(0);
+ e500_write_tlb(mas0, mas1, mas2, mas3, mas7);
+
+ out_be32(l2cache + MPC85xx_L2_L2SRBAR0_OFFSET, SRAM_BASE_ADDR);
+ out_be32(l2cache + MPC85xx_L2_L2ERRDIS_OFFSET,
+ (MPC85xx_L2ERRDIS_MBECC | MPC85xx_L2ERRDIS_SBECC));
+ out_be32(l2cache + MPC85xx_L2_CTL_OFFSET,
+ (MPC85xx_L2CTL_L2E | MPC85xx_L2CTL_L2SRAM_ENTIRE));
+ /*
+ * Copy the code in setup_ifc to L2SRAM. Do a word copy
+ * because NOR Flash on P1010 does not support byte
+ * access (Erratum IFC-A002769)
+ */
+ dst = (u32 *) SRAM_BASE_ADDR;
+ src = (u32 *) setup_ifc;
+ for (ix = 0; ix < 1024; ix++)
+ *dst++ = *src++;
+ setup_ifc_sram();
+
+ clrbits_be32(l2cache + MPC85xx_L2_CTL_OFFSET,
+ (MPC85xx_L2CTL_L2E | MPC85xx_L2CTL_L2SRAM_ENTIRE));
+ out_be32(l2cache + MPC85xx_L2_L2SRBAR0_OFFSET, 0x0);
+}
+#else
+static void fsl_erratum_ifc_a003399(void) {}
+#endif
+
+int fsl_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;
+}
+
+#if defined(CONFIG_FSL_ERRATUM_P1010_A003549)
+static void fsl_erratum_p1010_a003549(void)
+{
+ void __iomem *guts = IOMEM(MPC85xx_GUTS_ADDR);
+
+ setbits_be32(guts + MPC85xx_GUTS_PMUXCR_OFFSET,
+ MPC85xx_PMUXCR_LCLK_IFC_CS3);
+}
+#else
+static void fsl_erratum_p1010_a003549(void) {}
+#endif
+
+/* Called from assembly */
+void cpu_init_early_f(void);
+
+void cpu_init_early_f(void)
+{
+ u32 mas0, mas1, mas2, mas3, mas7;
+
+ mas0 = MAS0_TLBSEL(1) | MAS0_ESEL(13);
+ mas1 = MAS1_VALID | MAS1_TID(0) | MAS1_TS |
+ MAS1_TSIZE(BOOKE_PAGESZ_1M);
+ 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);
+
+ e500_write_tlb(mas0, mas1, mas2, mas3, mas7);
+
+ fsl_erratum_p1010_a003549();
+ fsl_init_laws();
+ fsl_erratum_ifc_a003399();
+
+ e500_invalidate_tlb(1);
+ e500_init_tlbs();
+}
+
+static int cpu_init_r(void)
+{
+ e500_disable_tlb(14);
+ e500_disable_tlb(15);
+
+ return 0;
+}
+core_initcall(cpu_init_r);
diff --git a/arch/powerpc/mach-mpc85xx/cpuid.c b/arch/powerpc/mach-mpc85xx/cpuid.c
new file mode 100644
index 0000000000..28f08ca292
--- /dev/null
+++ b/arch/powerpc/mach-mpc85xx/cpuid.c
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ *
+ * 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.
+ *
+ */
+
+#include <config.h>
+#include <common.h>
+#include <command.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <mach/immap_85xx.h>
+#include <mach/mpc85xx.h>
+
+struct cpu_type cpu_type_list[] = {
+ CPU_TYPE_ENTRY(8544, 8544, 1),
+ CPU_TYPE_ENTRY(8544, 8544_E, 1),
+ CPU_TYPE_ENTRY(P1010, P1010, 1),
+ CPU_TYPE_ENTRY(P1022, P1022, 2),
+ 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 fsl_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/powerpc/mach-mpc85xx/eth-devices.c b/arch/powerpc/mach-mpc85xx/eth-devices.c
new file mode 100644
index 0000000000..b1e830a37b
--- /dev/null
+++ b/arch/powerpc/mach-mpc85xx/eth-devices.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012 GE Intelligent Platforms, 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.
+ *
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <init.h>
+#include <mach/immap_85xx.h>
+#include <mach/gianfar.h>
+
+static int fsl_phy_init(void)
+{
+ int i;
+ void __iomem *base = IOMEM(GFAR_BASE_ADDR + GFAR_TBIPA_OFFSET);
+
+ /*
+ * The TBI address must be initialised to enable the PHY to
+ * link up after the MDIO reset.
+ */
+ out_be32(base, GFAR_TBIPA_END);
+ /* All ports access external PHYs via the "gfar-mdio" device */
+ add_generic_device("gfar-mdio", 0, NULL, MDIO_BASE_ADDR,
+ 0x1000, IORESOURCE_MEM, NULL);
+
+ for (i = 1; i < FSL_NUM_TSEC; i++) {
+ out_be32(base + (i * 0x1000), GFAR_TBIPA_END - i);
+ /* Use "gfar-tbiphy" devices to access internal PHY. */
+ add_generic_device("gfar-tbiphy", i, NULL,
+ MDIO_BASE_ADDR + (i * 0x1000),
+ 0x1000, IORESOURCE_MEM, NULL);
+ }
+ return 0;
+}
+
+coredevice_initcall(fsl_phy_init);
+
+int fsl_eth_init(int num, struct gfar_info_struct *gf)
+{
+ add_generic_device("gfar", DEVICE_ID_DYNAMIC, NULL,
+ GFAR_BASE_ADDR + ((num - 1) * 0x1000), 0x1000,
+ IORESOURCE_MEM, gf);
+ return 0;
+}
diff --git a/arch/powerpc/mach-mpc85xx/fdt.c b/arch/powerpc/mach-mpc85xx/fdt.c
new file mode 100644
index 0000000000..de0114ad64
--- /dev/null
+++ b/arch/powerpc/mach-mpc85xx/fdt.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2013 GE Intelligent Platforms, Inc.
+ * Copyright 2007-2011 Freescale Semiconductor, Inc.
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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.
+ *
+ * Based on U-Boot arch/powerpc/cpu/mpc85xx/fdt.c and
+ * common/fdt_support.c - version git-2b26201.
+ */
+#include <common.h>
+#include <init.h>
+#include <errno.h>
+#include <environment.h>
+#include <asm/processor.h>
+#include <mach/clock.h>
+#include <of.h>
+
+static void of_setup_crypto_node(void *blob)
+{
+ struct device_node *crypto_node;
+
+ crypto_node = of_find_compatible_node(blob, NULL, "fsl,sec2.0");
+ if (crypto_node == NULL)
+ return;
+
+ of_delete_node(crypto_node);
+}
+
+/* These properties specify whether the hardware supports the stashing
+ * of buffer descriptors in L2 cache.
+ */
+static void fdt_add_enet_stashing(void *fdt)
+{
+ struct device_node *node;
+
+ node = of_find_compatible_node(fdt, NULL, "gianfar");
+ while (node) {
+ of_set_property(node, "bd-stash", NULL, 0, 1);
+ of_property_write_u32(node, "rx-stash-len", 96);
+ of_property_write_u32(node, "rx-stash-idx", 0);
+ node = of_find_compatible_node(node, NULL, "gianfar");
+ }
+
+ node = of_find_compatible_node(fdt, NULL, "fsl,etsec2");
+ while (node) {
+ of_set_property(node, "bd-stash", NULL, 0, 1);
+ of_property_write_u32(node, "rx-stash-len", 96);
+ of_property_write_u32(node, "rx-stash-idx", 0);
+ node = of_find_compatible_node(node, NULL, "fsl,etsec2");
+ }
+}
+
+static int fdt_stdout_setup(struct device_node *blob)
+{
+ struct device_node *node, *alias;
+ char sername[9] = { 0 };
+ const char *prop;
+ struct console_device *cdev;
+ int len;
+
+ node = of_create_node(blob, "/chosen");
+ if (node == NULL) {
+ pr_err("%s: could not open /chosen node\n", __func__);
+ goto error;
+ }
+
+ cdev = console_get_first_active();
+ if (cdev)
+ sprintf(sername, "serial%d", cdev->dev->id);
+ else
+ sprintf(sername, "serial%d", 0);
+
+ alias = of_find_node_by_path_from(blob, "/aliases");
+ if (!alias) {
+ pr_err("%s: could not get aliases node.\n", __func__);
+ goto error;
+ }
+ prop = of_get_property(alias, sername, &len);
+ of_set_property(node, "linux,stdout-path", prop, len, 1);
+
+ return 0;
+error:
+ return -ENODEV;
+}
+
+static int fdt_cpu_setup(struct device_node *blob, void *unused)
+{
+ struct device_node *node;
+ struct sys_info sysinfo;
+
+ /* delete crypto node if not on an E-processor */
+ if (!IS_E_PROCESSOR(get_svr()))
+ of_setup_crypto_node(blob);
+
+ fdt_add_enet_stashing(blob);
+ fsl_get_sys_info(&sysinfo);
+
+ node = of_find_node_by_type(blob, "cpu");
+ while (node) {
+ const uint32_t *reg;
+
+ of_property_write_u32(node, "timebase-frequency",
+ fsl_get_timebase_clock());
+ of_property_write_u32(node, "bus-frequency",
+ sysinfo.freqSystemBus);
+ reg = of_get_property(node, "reg", NULL);
+ of_property_write_u32(node, "clock-frequency",
+ sysinfo.freqProcessor[*reg]);
+ node = of_find_node_by_type(node, "cpu");
+ }
+
+ node = of_find_node_by_type(blob, "soc");
+ if (node)
+ of_property_write_u32(node, "bus-frequency",
+ sysinfo.freqSystemBus);
+
+ node = of_find_compatible_node(blob, NULL, "fsl,elbc");
+ if (node)
+ of_property_write_u32(node, "bus-frequency",
+ sysinfo.freqLocalBus);
+
+ node = of_find_compatible_node(blob, NULL, "ns16550");
+ while (node) {
+ of_property_write_u32(node, "clock-frequency",
+ sysinfo.freqSystemBus);
+ node = of_find_compatible_node(node, NULL, "ns16550");
+ }
+
+ node = of_find_compatible_node(blob, NULL, "fsl,mpic");
+ if (node)
+ of_property_write_u32(node, "clock-frequency",
+ sysinfo.freqSystemBus);
+
+ fdt_stdout_setup(blob);
+
+ return 0;
+}
+
+static int of_register_mpc85xx_fixup(void)
+{
+ return of_register_fixup(fdt_cpu_setup, NULL);
+}
+late_initcall(of_register_mpc85xx_fixup);
diff --git a/arch/powerpc/mach-mpc85xx/fsl_gpio.c b/arch/powerpc/mach-mpc85xx/fsl_gpio.c
new file mode 100644
index 0000000000..85994dcf1b
--- /dev/null
+++ b/arch/powerpc/mach-mpc85xx/fsl_gpio.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013 GE Intelligent Platforms, 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.
+ *
+ * Minimal GPIO support.
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <mach/gpio.h>
+#include <mach/immap_85xx.h>
+
+#ifdef CONFIG_MPC8544
+/* Enable all GPIO output pins */
+void fsl_enable_gpiout(void)
+{
+ void __iomem *gpiocr = IOMEM(MPC85xx_GUTS_ADDR + MPC85xx_GPIOCR_OFFSET);
+
+ out_be32(gpiocr, in_be32(gpiocr) | MPC85xx_GPIOCR_GPOUT);
+}
+#endif
diff --git a/arch/powerpc/mach-mpc85xx/fsl_i2c.c b/arch/powerpc/mach-mpc85xx/fsl_i2c.c
new file mode 100644
index 0000000000..8cf80713f6
--- /dev/null
+++ b/arch/powerpc/mach-mpc85xx/fsl_i2c.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2013 GE Intelligent Platforms, Inc
+ * Copyright 2006,2009 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Early I2C support functions to read SPD data or board
+ * information.
+ * Based on U-Boot drivers/i2c/fsl_i2c.c
+ */
+#include <common.h>
+#include <i2c/i2c.h>
+#include <mach/clock.h>
+#include <mach/immap_85xx.h>
+#include <mach/early_udelay.h>
+#include <mach/fsl_i2c.h>
+
+/* FSL I2C registers */
+#define FSL_I2C_ADR 0x00
+#define FSL_I2C_FDR 0x04
+#define FSL_I2C_CR 0x08
+#define FSL_I2C_SR 0x0C
+#define FSL_I2C_DR 0x10
+#define FSL_I2C_DFSRR 0x14
+
+/* Bits of FSL I2C registers */
+#define I2C_SR_RXAK 0x01
+#define I2C_SR_MIF 0x02
+#define I2C_SR_MAL 0x10
+#define I2C_SR_MBB 0x20
+#define I2C_SR_MCF 0x80
+#define I2C_CR_RSTA 0x04
+#define I2C_CR_TXAK 0x08
+#define I2C_CR_MTX 0x10
+#define I2C_CR_MSTA 0x20
+#define I2C_CR_MEN 0x80
+
+/*
+ * Set the I2C bus speed for a given I2C device
+ *
+ * parameters:
+ * - i2c: the I2C base address.
+ * - i2c_clk: I2C bus clock frequency.
+ * - speed: the desired speed of the bus.
+ *
+ * The I2C device must be stopped before calling this function.
+ *
+ * The return value is the actual bus speed that is set.
+ */
+static uint32_t fsl_set_i2c_bus_speed(const void __iomem *i2c,
+ uint32_t i2c_clk, uint32_t speed)
+{
+ uint8_t dfsr, fdr = 0x31; /* Default if no FDR found */
+ uint16_t a, b, ga, gb, bin_gb, bin_ga, divider;
+ uint32_t c_div, est_div;
+
+ divider = min((uint16_t)(i2c_clk / speed), (uint16_t) -1);
+ /* Condition 1: dfsr <= 50/T */
+ dfsr = (5 * (i2c_clk / 1000)) / 100000;
+ if (!dfsr)
+ dfsr = 1;
+ est_div = ~0;
+
+ /*
+ * Bus speed is calculated as per Freescale AN2919.
+ * a, b and dfsr matches identifiers A,B and C as in the
+ * application note.
+ */
+ for (ga = 0x4, a = 10; a <= 30; ga++, a += 2) {
+ for (gb = 0; gb < 8; gb++) {
+ b = 16 << gb;
+ c_div = b * (a + (((3 * dfsr) / b) * 2));
+
+ if ((c_div > divider) && (c_div < est_div)) {
+ est_div = c_div;
+ bin_gb = gb << 2;
+ bin_ga = (ga & 0x3) | ((ga & 0x4) << 3);
+ fdr = bin_gb | bin_ga;
+ speed = i2c_clk / est_div;
+ }
+ }
+ if (a == 20)
+ a += 2;
+ if (a == 24)
+ a += 4;
+ }
+ writeb(dfsr, i2c + FSL_I2C_DFSRR); /* set default filter */
+ writeb(fdr, i2c + FSL_I2C_FDR); /* set bus speed */
+
+ return speed;
+}
+
+void fsl_i2c_init(void __iomem *i2c, int speed, int slaveadd)
+{
+ uint32_t i2c_clk;
+
+ i2c_clk = fsl_get_i2c_freq();
+ writeb(0, i2c + FSL_I2C_CR);
+ early_udelay(5);
+
+ fsl_set_i2c_bus_speed(i2c, i2c_clk, speed);
+ writeb(slaveadd << 1, i2c + FSL_I2C_ADR);
+ writeb(0x0, i2c + FSL_I2C_SR);
+ writeb(I2C_CR_MEN, i2c + FSL_I2C_CR);
+}
+
+static uint32_t fsl_usec2ticks(uint32_t usec)
+{
+ ulong ticks;
+
+ if (usec < 1000) {
+ ticks = (usec * (fsl_get_timebase_clock() / 1000));
+ ticks = (ticks + 500) / 1000;
+ } else {
+ ticks = (usec / 10);
+ ticks *= (fsl_get_timebase_clock() / 100000);
+ }
+
+ return ticks;
+}
+
+static int fsl_i2c_wait4bus(void __iomem *i2c)
+{
+ uint64_t timeval = get_ticks();
+ const uint64_t timeout = fsl_usec2ticks(20000);
+
+ while (readb(i2c + FSL_I2C_SR) & I2C_SR_MBB)
+ if ((get_ticks() - timeval) > timeout)
+ return -1;
+
+ return 0;
+}
+
+void fsl_i2c_stop(void __iomem *i2c)
+{
+ writeb(I2C_CR_MEN, i2c + FSL_I2C_CR);
+}
+
+static int fsl_i2c_wait(void __iomem *i2c, int write)
+{
+ const uint64_t timeout = fsl_usec2ticks(100000);
+ uint64_t timeval = get_ticks();
+ int csr;
+
+ do {
+ csr = readb(i2c + FSL_I2C_SR);
+ if (csr & I2C_SR_MIF)
+ break;
+ } while ((get_ticks() - timeval) < timeout);
+
+ if ((get_ticks() - timeval) > timeout)
+ goto error;
+
+ csr = readb(i2c + FSL_I2C_SR);
+ writeb(0x0, i2c + FSL_I2C_SR);
+
+ if (csr & I2C_SR_MAL)
+ goto error;
+
+ if (!(csr & I2C_SR_MCF))
+ goto error;
+
+ if (write == 0 && (csr & I2C_SR_RXAK))
+ goto error;
+
+ return 0;
+error:
+ return -1;
+}
+
+static int __i2c_write(void __iomem *i2c, uint8_t *data, int length)
+{
+ int i;
+
+ for (i = 0; i < length; i++) {
+ writeb(data[i], i2c + FSL_I2C_DR);
+ if (fsl_i2c_wait(i2c, 0) < 0)
+ break;
+ }
+
+ return i;
+}
+
+static int __i2c_read(void __iomem *i2c, uint8_t *data, int length)
+{
+ int i;
+ uint8_t val = I2C_CR_MEN | I2C_CR_MSTA;
+
+ if (length == 1)
+ writeb(val | I2C_CR_TXAK, i2c + FSL_I2C_CR);
+ else
+ writeb(val, i2c + FSL_I2C_CR);
+
+ readb(i2c + FSL_I2C_DR);
+ for (i = 0; i < length; i++) {
+ if (fsl_i2c_wait(i2c, 1) < 0)
+ break;
+
+ /* Generate ack on last next to last byte */
+ if (i == length - 2)
+ writeb(val | I2C_CR_TXAK, i2c + FSL_I2C_CR);
+ /* Do not generate stop on last byte */
+ if (i == length - 1)
+ writeb(val | I2C_CR_MTX, i2c + FSL_I2C_CR);
+
+ data[i] = readb(i2c + FSL_I2C_DR);
+ }
+
+ return i;
+}
+
+static int
+fsl_i2c_write_addr(void __iomem *i2c, uint8_t dev, uint8_t dir, int rsta)
+{
+ uint8_t val = I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_MTX;
+
+ if (rsta)
+ val |= I2C_CR_RSTA;
+ writeb(val, i2c + FSL_I2C_CR);
+ writeb((dev << 1) | dir, i2c + FSL_I2C_DR);
+
+ if (fsl_i2c_wait(i2c, 0) < 0)
+ return 0;
+
+ return 1;
+}
+
+int fsl_i2c_read(void __iomem *i2c, uint8_t dev, uint addr, int alen,
+ uint8_t *data, int length)
+{
+ int i = -1;
+ uint8_t *a = (uint8_t *)&addr;
+
+ if (alen && (fsl_i2c_wait4bus(i2c) >= 0) &&
+ (fsl_i2c_write_addr(i2c, dev, 0, 0) != 0) &&
+ (__i2c_write(i2c, &a[4 - alen], alen) == alen))
+ i = 0;
+
+ if (length && fsl_i2c_write_addr(i2c, dev, 1, 1) != 0)
+ i = __i2c_read(i2c, data, length);
+
+ if (i == length)
+ return 0;
+
+ return -1;
+}
diff --git a/arch/powerpc/mach-mpc85xx/fsl_law.c b/arch/powerpc/mach-mpc85xx/fsl_law.c
new file mode 100644
index 0000000000..e3c765f30f
--- /dev/null
+++ b/arch/powerpc/mach-mpc85xx/fsl_law.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2012 GE Intelligent Platforms, Inc.
+ *
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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.
+ *
+ */
+
+#include <common.h>
+#include <asm/config.h>
+#include <asm/fsl_law.h>
+#include <mach/ffs64.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 fsl_get_law_base_addr(int idx)
+{
+ return (phys_addr_t)in_be32(LAWBAR_ADDR(idx)) << LAWBAR_SHIFT;
+}
+
+static inline void fsl_set_law_base_addr(int idx, phys_addr_t addr)
+{
+ out_be32(LAWBAR_ADDR(idx), addr >> LAWBAR_SHIFT);
+}
+
+static void fsl_set_law(u8 idx, phys_addr_t addr, enum law_size sz,
+ enum law_trgt_if id)
+{
+ out_be32(LAWAR_ADDR(idx), 0);
+ fsl_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 fsl_is_free_law(int idx)
+{
+ u32 lawar;
+
+ lawar = in_be32(LAWAR_ADDR(idx));
+ if (!(lawar & LAW_EN))
+ return 1;
+
+ return 0;
+}
+
+static void fsl_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 (fsl_is_free_law(idx)) {
+ fsl_set_law(idx, addr, sz, id);
+ break;
+ }
+ }
+
+ if (idx >= FSL_HW_NUM_LAWS)
+ panic("No more LAWS available\n");
+}
+
+static void fsl_set_last_law(phys_addr_t addr, enum law_size sz,
+ enum law_trgt_if id)
+{
+ int idx;
+
+ for (idx = (FSL_HW_NUM_LAWS - 1); idx >= 0; idx--) {
+ if (fsl_is_free_law(idx)) {
+ fsl_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 fsl_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;
+
+ fsl_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;
+
+ fsl_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 fsl_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)
+ fsl_set_next_law(law_table[i].addr,
+ law_table[i].size,
+ law_table[i].trgt_id);
+ else
+ fsl_set_law(law_table[i].index, law_table[i].addr,
+ law_table[i].size, law_table[i].trgt_id);
+ }
+}
diff --git a/arch/powerpc/mach-mpc85xx/include/mach/clock.h b/arch/powerpc/mach-mpc85xx/include/mach/clock.h
new file mode 100644
index 0000000000..bfd9cf4d8e
--- /dev/null
+++ b/arch/powerpc/mach-mpc85xx/include/mach/clock.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __ASM_ARCH_CLOCKS_H
+#define __ASM_ARCH_CLOCKS_H
+
+#include <mach/config_mpc85xx.h>
+
+struct sys_info {
+ unsigned long freqProcessor[MAX_CPUS];
+ unsigned long freqSystemBus;
+ unsigned long freqDDRBus;
+ unsigned long freqLocalBus;
+};
+
+unsigned long fsl_get_bus_freq(ulong dummy);
+unsigned long fsl_get_ddr_freq(ulong dummy);
+unsigned long fsl_get_timebase_clock(void);
+unsigned long fsl_get_i2c_freq(void);
+void fsl_get_sys_info(struct sys_info *sysInfo);
+#endif /* __ASM_ARCH_CLOCKS_H */
diff --git a/arch/powerpc/mach-mpc85xx/include/mach/config_mpc85xx.h b/arch/powerpc/mach-mpc85xx/include/mach/config_mpc85xx.h
new file mode 100644
index 0000000000..fad2c47d11
--- /dev/null
+++ b/arch/powerpc/mach-mpc85xx/include/mach/config_mpc85xx.h
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef _ASM_MPC85xx_CONFIG_H_
+#define _ASM_MPC85xx_CONFIG_H_
+
+#define RESET_VECTOR 0xfffffffc
+
+/* 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
+#define FSL_NUM_TSEC 3
+#define FSL_ERRATUM_A005125
+#define PPC_E500_DEBUG_TLB 2
+
+#elif defined(CONFIG_MPC8544)
+#define MAX_CPUS 1
+#define FSL_NUM_LAWS 10
+#define FSL_NUM_TSEC 2
+#define FSL_ERRATUM_A005125
+#define PPC_E500_DEBUG_TLB 0
+
+#elif defined(CONFIG_P1022)
+#define MAX_CPUS 2
+#define FSL_NUM_LAWS 12
+#define FSL_NUM_TSEC 2
+#define FSL_SEC_COMPAT 2
+#define PPC_E500_DEBUG_TLB 2
+#define FSL_TSECV2
+#define FSL_ERRATUM_A005125
+
+#elif defined(CONFIG_P1010)
+#define MAX_CPUS 1
+#define FSL_NUM_LAWS 12
+#define FSL_NUM_TSEC 3
+#define FSL_SEC_COMPAT 4
+#define FSL_ERRATUM_A005125
+#define PPC_E500_DEBUG_TLB 2
+#define FSL_TSECV2
+
+#else
+#error Processor type not defined for this platform
+#endif
+
+#endif /* _ASM_MPC85xx_CONFIG_H_ */
diff --git a/arch/powerpc/mach-mpc85xx/include/mach/early_udelay.h b/arch/powerpc/mach-mpc85xx/include/mach/early_udelay.h
new file mode 100644
index 0000000000..12020dd96d
--- /dev/null
+++ b/arch/powerpc/mach-mpc85xx/include/mach/early_udelay.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2012 GE Intelligent Platforms, Inc.
+ *
+ * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net>
+ *
+ * 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.
+ *
+ */
+
+#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/powerpc/mach-mpc85xx/include/mach/ffs64.h b/arch/powerpc/mach-mpc85xx/include/mach/ffs64.h
new file mode 100644
index 0000000000..045498c513
--- /dev/null
+++ b/arch/powerpc/mach-mpc85xx/include/mach/ffs64.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013 GE Intelligent Platforms, 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.
+ *
+ */
+#include <linux/log2.h>
+
+static inline int ffs64(u64 x)
+{
+ return __ilog2_u64(x & -x) + 1ull;
+}
diff --git a/arch/powerpc/mach-mpc85xx/include/mach/fsl_i2c.h b/arch/powerpc/mach-mpc85xx/include/mach/fsl_i2c.h
new file mode 100644
index 0000000000..d187c6cf49
--- /dev/null
+++ b/arch/powerpc/mach-mpc85xx/include/mach/fsl_i2c.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2013 GE Intelligent Platforms, 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.
+ */
+void fsl_i2c_init(void __iomem *i2c, int speed, int slaveadd);
+int fsl_i2c_read(void __iomem *i2c, uint8_t dev, uint addr, int alen,
+ uint8_t *data, int length);
+void fsl_i2c_stop(void __iomem *i2c);
diff --git a/arch/powerpc/mach-mpc85xx/include/mach/gianfar.h b/arch/powerpc/mach-mpc85xx/include/mach/gianfar.h
new file mode 100644
index 0000000000..660cb1e98f
--- /dev/null
+++ b/arch/powerpc/mach-mpc85xx/include/mach/gianfar.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2012 GE Intelligent Platforms, Inc.
+ * Copyright 2004, 2007, 2009 Freescale Semiconductor, Inc.
+ * (C) Copyright 2003, Motorola, Inc.
+ * based on tsec.h by Xianghua Xiao and Andy Fleming 2003-2009
+ *
+ * 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.
+ *
+ * Platform data for the Motorola Triple Speed Ethernet Controller
+ */
+
+#define GFAR_TBIPA_OFFSET 0x030 /* TBI PHY address */
+#define GFAR_TBIPA_END 0x1f /* Last valid PHY address */
+
+struct gfar_info_struct {
+ unsigned int phyaddr;
+ unsigned int tbiana;
+ unsigned int tbicr;
+ unsigned int mdiobus_tbi;
+};
+
+int fsl_eth_init(int num, struct gfar_info_struct *gf);
diff --git a/arch/powerpc/mach-mpc85xx/include/mach/gpio.h b/arch/powerpc/mach-mpc85xx/include/mach/gpio.h
new file mode 100644
index 0000000000..b41ecc5214
--- /dev/null
+++ b/arch/powerpc/mach-mpc85xx/include/mach/gpio.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2013 GE Intelligent Platforms, 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.
+ */
+
+#ifndef _MACH_PPC_GPIO_H
+#define _MACH_PPC_GPIO_H
+
+extern void fsl_enable_gpiout(void);
+
+#endif /* _MACH_PPC_GPIO_H */
diff --git a/arch/powerpc/mach-mpc85xx/include/mach/immap_85xx.h b/arch/powerpc/mach-mpc85xx/include/mach/immap_85xx.h
new file mode 100644
index 0000000000..d348f86dac
--- /dev/null
+++ b/arch/powerpc/mach-mpc85xx/include/mach/immap_85xx.h
@@ -0,0 +1,199 @@
+/*
+ * MPC85xx Internal Memory Map
+ *
+ * Copyright 2007-2011 Freescale Semiconductor, Inc.
+ *
+ * Copyright(c) 2002,2003 Motorola Inc.
+ * Xianghua Xiao (x.xiao@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.
+ *
+ */
+
+#ifndef __IMMAP_85xx__
+#define __IMMAP_85xx__
+
+#include <asm/types.h>
+#include <asm/fsl_lbc.h>
+#include <asm/fsl_ifc.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_PCI1_OFFSET 0x8000
+
+#define MPC85xx_GPIO_OFFSET 0xf000
+#define MPC85xx_IFC_OFFSET 0x1e000
+#define MPC85xx_L2_OFFSET 0x20000
+#ifdef FSL_TSECV2
+#define TSEC1_OFFSET 0xB0000
+#else
+#define TSEC1_OFFSET 0x24000
+#endif
+
+#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 IFC_ADDR (CFG_IMMR + MPC85xx_IFC_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 */
+#define MPC85xx_ECM_EEDR_OFFSET 0xE00 /* ECM error detect register */
+#define MPC85xx_ECM_EEER_OFFSET 0xE08 /* ECM error enable register */
+
+/*
+ * 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
+/* Chip Select 0, 1, 2, 3 Configuration 2 */
+#define MPC85xx_DDR_CS0_CONFIG_2_OFFSET 0x0c0
+#define MPC85xx_DDR_CS1_CONFIG_2_OFFSET 0x0c4
+#define MPC85xx_DDR_CS2_CONFIG_2_OFFSET 0x0c8
+#define MPC85xx_DDR_CS3_CONFIG_2_OFFSET 0x0cc
+/* 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
+/* SDRAM Timing Configuration 4,5 */
+#define MPC85xx_DDR_TIMING_CFG_4_OFFSET 0x160
+#define MPC85xx_DDR_TIMING_CFG_5_OFFSET 0x164
+/* DDR ZQ calibration control */
+#define MPC85xx_DDR_ZQ_CNTL_OFFSET 0x170
+/* DDR write leveling control */
+#define MPC85xx_DDR_WRLVL_CNTL_OFFSET 0x174
+/* Self Refresh Counter */
+#define MPC85xx_DDR_SR_CNTL_OFFSET 0x17c
+/* DDR SDRAM Register Control Word */
+#define MPC85xx_DDR_SDRAM_RCW_1_OFFSET 0x180
+#define MPC85xx_DDR_SDRAM_RCW_2_OFFSET 0x184
+/* DDR write leveling control */
+#define MPC85xx_DDR_WRLVL_CNTL_2_OFFSET 0x190
+#define MPC85xx_DDR_WRLVL_CNTL_3_OFFSET 0x194
+/* DDR Control Driver */
+#define MPC85xx_DDR_DDRCDR1_OFFSET 0xb28
+#define MPC85xx_DDR_DDRCDR2_OFFSET 0xb2c
+/* DDR IP block revision */
+#define MPC85xx_DDR_IP_REV1_OFFSET 0xbf8
+#define MPC85xx_DDR_IP_REV2_OFFSET 0xbfc
+/* Memory Error Disable */
+#define MPC85xx_DDR_ERR_DISABLE_OFFSET 0xe44
+#define MPC85xx_DDR_ERR_INT_EN_OFFSET 0xe48
+
+#define DDR_OFF(REGNAME) (MPC85xx_DDR_##REGNAME##_OFFSET)
+
+/*
+ * GPIO Register Offsets
+ */
+#define MPC85xx_GPIO_GPDIR 0x00
+#define MPC85xx_GPIO_GPDAT 0x08
+#define MPC85xx_GPIO_GPDIR_OFFSET 0x00
+#define MPC85xx_GPIO_GPDAT_OFFSET 0x08
+
+/* Global Utilities Registers */
+#define MPC85xx_GPIOCR_OFFSET 0x30
+#define MPC85xx_GPIOCR_GPOUT 0x00000200
+#define MPC85xx_GPOUTDR_OFFSET 0x40
+#define MPC85xx_GPIOBIT(i) (1 << (31 - i))
+#define MPC85xx_GPINDR_OFFSET 0x50
+
+#define MPC85xx_DEVDISR_OFFSET 0x70
+#define MPC85xx_DEVDISR_TSEC1 0x00000080
+#define MPC85xx_DEVDISR_TSEC2 0x00000040
+#define MPC85xx_DEVDISR_TSEC3 0x00000020
+
+/*
+ * L2 Cache Register Offsets
+ */
+#define MPC85xx_L2_CTL_OFFSET 0x0 /* L2 configuration 0 */
+#define MPC85xx_L2CTL_L2E 0x80000000
+#define MPC85xx_L2CTL_L2SRAM_ENTIRE 0x00010000
+#define MPC85xx_L2_L2SRBAR0_OFFSET 0x100
+#define MPC85xx_L2_L2ERRDIS_OFFSET 0xe44
+#define MPC85xx_L2ERRDIS_MBECC 0x00000008
+#define MPC85xx_L2ERRDIS_SBECC 0x00000004
+
+/* 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_PORDEVSR2_OFFSET 0x14
+#define MPC85xx_PORDEVSR2_SEC_CFG 0x00000080
+#define MPC85xx_GUTS_PMUXCR_OFFSET 0x60
+#define MPC85xx_PMUXCR_LCLK_IFC_CS3 0x000000C0
+#define MPC85xx_GUTS_PMUXCR2_OFFSET 0x64
+#define MPC85xx_GUTS_DEVDISR_OFFSET 0x70
+#define MPC85xx_DEVDISR_TB0 0x00004000
+#define MPC85xx_DEVDISR_TB1 0x00001000
+#define MPC85xx_GUTS_RSTCR_OFFSET 0xb0
+
+#define GFAR_BASE_ADDR (CFG_IMMR + TSEC1_OFFSET)
+#define MDIO_BASE_ADDR (CFG_IMMR + 0x24000)
+
+#define I2C1_BASE_ADDR (CFG_IMMR + 0x3000)
+#define I2C2_BASE_ADDR (CFG_IMMR + 0x3100)
+
+/* Global Timer Registers */
+#define MPC8xxx_PIC_TFRR_OFFSET 0x10F0
+
+#define PCI1_BASE_ADDR (CFG_IMMR + MPC85xx_PCI1_OFFSET)
+#endif /*__IMMAP_85xx__*/
diff --git a/arch/powerpc/mach-mpc85xx/include/mach/mmu.h b/arch/powerpc/mach-mpc85xx/include/mach/mmu.h
new file mode 100644
index 0000000000..e2ecc62ef0
--- /dev/null
+++ b/arch/powerpc/mach-mpc85xx/include/mach/mmu.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2012 GE Intelligent Platforms, 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 _MPC85XX_MMU_H_
+#define _MPC85XX_MMU_H_
+
+#ifdef CONFIG_E500
+#include <asm/mmu.h>
+
+#ifndef __ASSEMBLY__
+extern int e500_find_free_tlbcam(void);
+extern void e500_read_tlbcam_entry(int idx, u32 *valid, u32 *tsize,
+ unsigned long *epn, phys_addr_t *rpn);
+extern void e500_read_tlbcam_entry(int idx, u32 *valid, u32 *tsize,
+ unsigned long *epn, phys_addr_t *rpn);
+extern void e500_set_tlb(u8 tlb, u32 epn, u64 rpn, u8 perms, u8 wimge,
+ u8 ts, u8 esel, u8 tsize, u8 iprot);
+extern void e500_disable_tlb(u8 esel);
+extern void e500_invalidate_tlb(u8 tlb);
+extern void e500_init_tlbs(void);
+extern int e500_find_tlb_idx(void *addr, u8 tlbsel);
+extern void e500_init_used_tlb_cams(void);
+
+extern unsigned int e500_setup_ddr_tlbs(unsigned int memsize_in_meg);
+extern void e500_write_tlb(u32 _mas0, u32 _mas1, u32 _mas2, u32 _mas3,
+ u32 _mas7);
+
+#define FSL_SET_TLB_ENTRY(_tlb, _epn, _rpn, _perms, _wimge, _ts, _esel, _sz,\
+ _iprot) \
+ { .mas0 = FSL_BOOKE_MAS0(_tlb, _esel, 0), \
+ .mas1 = FSL_BOOKE_MAS1(1, _iprot, 0, _ts, _sz), \
+ .mas2 = FSL_BOOKE_MAS2(_epn, _wimge), \
+ .mas3 = FSL_BOOKE_MAS3(_rpn, 0, _perms), \
+ .mas7 = FSL_BOOKE_MAS7(_rpn), }
+
+struct fsl_e_tlb_entry {
+ u32 mas0;
+ u32 mas1;
+ u32 mas2;
+ u32 mas3;
+ u32 mas7;
+};
+extern struct fsl_e_tlb_entry tlb_table[];
+extern int num_tlb_entries;
+#endif
+#endif
+#endif /* _MPC85XX_MMU_H_ */
diff --git a/arch/powerpc/mach-mpc85xx/include/mach/mpc85xx.h b/arch/powerpc/mach-mpc85xx/include/mach/mpc85xx.h
new file mode 100644
index 0000000000..5491f0b08d
--- /dev/null
+++ b/arch/powerpc/mach-mpc85xx/include/mach/mpc85xx.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * 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
+
+#ifndef __ASSEMBLY__
+int fsl_l2_cache_init(void);
+int fsl_cpu_numcores(void);
+
+phys_size_t fsl_get_effective_memsize(void);
+
+#endif /* __ASSEMBLY__ */
+
+#define END_OF_MEM (fsl_get_effective_memsize())
+
+#endif /* __MPC85xx_H__ */
diff --git a/arch/powerpc/mach-mpc85xx/speed.c b/arch/powerpc/mach-mpc85xx/speed.c
new file mode 100644
index 0000000000..16ce72d846
--- /dev/null
+++ b/arch/powerpc/mach-mpc85xx/speed.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2012 GE Intelligent Platforms, Inc.
+ *
+ * Copyright 2004, 2007-2011 Freescale Semiconductor, Inc.
+ *
+ * (C) Copyright 2003 Motorola Inc.
+ * Xianghua Xiao, (X.Xiao@motorola.com)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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.
+ *
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <mach/clock.h>
+#include <mach/immap_85xx.h>
+#include <mach/mpc85xx.h>
+
+void fsl_get_sys_info(struct sys_info *sysInfo)
+{
+ void __iomem *gur = (void __iomem *)(MPC85xx_GUTS_ADDR);
+ uint plat_ratio, e500_ratio, half_freqSystemBus, lcrr_div, ccr;
+ 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 < fsl_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
+
+ if (IS_ENABLED(CONFIG_FSL_IFC)) {
+ void __iomem *ifc = IFC_BASE_ADDR;
+
+ ccr = in_be32(ifc + FSL_IFC_CCR_OFFSET);
+ ccr = ((ccr & IFC_CCR_CLK_DIV_MASK) >> IFC_CCR_CLK_DIV_SHIFT);
+ sysInfo->freqLocalBus = sysInfo->freqSystemBus / (ccr + 1);
+ } else {
+ 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 fsl_get_bus_freq(ulong dummy)
+{
+ struct sys_info sys_info;
+
+ fsl_get_sys_info(&sys_info);
+
+ return sys_info.freqSystemBus;
+}
+
+unsigned long fsl_get_ddr_freq(ulong dummy)
+{
+ struct sys_info sys_info;
+
+ fsl_get_sys_info(&sys_info);
+
+ return sys_info.freqDDRBus;
+}
+
+unsigned long fsl_get_timebase_clock(void)
+{
+ struct sys_info sysinfo;
+
+ fsl_get_sys_info(&sysinfo);
+
+ return (sysinfo.freqSystemBus + 4UL)/8UL;
+}
+
+unsigned long fsl_get_i2c_freq(void)
+{
+ uint svr;
+ struct sys_info sysinfo;
+ void __iomem *gur = IOMEM(MPC85xx_GUTS_ADDR);
+
+ fsl_get_sys_info(&sysinfo);
+
+ svr = get_svr();
+ if ((svr == SVR_8544) || (svr == SVR_8544_E)) {
+ if (in_be32(gur + MPC85xx_GUTS_PORDEVSR2_OFFSET) &
+ MPC85xx_PORDEVSR2_SEC_CFG)
+ return sysinfo.freqSystemBus / 3;
+ }
+
+ return sysinfo.freqSystemBus / 2;
+}
diff --git a/arch/powerpc/mach-mpc85xx/time.c b/arch/powerpc/mach-mpc85xx/time.c
new file mode 100644
index 0000000000..5981995ac2
--- /dev/null
+++ b/arch/powerpc/mach-mpc85xx/time.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012 GE Intelligent Platforms, Inc.
+ * (C) Copyright 2000, 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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.
+ *
+ */
+
+#include <common.h>
+#include <clock.h>
+#include <init.h>
+#include <mach/clock.h>
+
+static uint64_t ppc_clocksource_read(void)
+{
+ return get_ticks();
+}
+
+static struct clocksource cs = {
+ .read = ppc_clocksource_read,
+ .mask = CLOCKSOURCE_MASK(64),
+ .priority = 80,
+};
+
+static int clocksource_init(void)
+{
+ /* reset time base */
+ asm ("li 3,0 ; mttbu 3 ; mttbl 3 ;");
+
+ clocks_calc_mult_shift(&cs.mult, &cs.shift,
+ fsl_get_timebase_clock(), NSEC_PER_SEC, 10);
+
+ return init_clock(&cs);
+}
+
+core_initcall(clocksource_init);