aboutsummaryrefslogtreecommitdiffstats
path: root/roms/u-boot/drivers/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'roms/u-boot/drivers/cpu')
-rw-r--r--roms/u-boot/drivers/cpu/Kconfig21
-rw-r--r--roms/u-boot/drivers/cpu/Makefile14
-rw-r--r--roms/u-boot/drivers/cpu/at91_cpu.c123
-rw-r--r--roms/u-boot/drivers/cpu/bmips_cpu.c522
-rw-r--r--roms/u-boot/drivers/cpu/cpu-uclass.c142
-rw-r--r--roms/u-boot/drivers/cpu/cpu_sandbox.c96
-rw-r--r--roms/u-boot/drivers/cpu/imx8_cpu.c236
-rw-r--r--roms/u-boot/drivers/cpu/mpc83xx_cpu.c354
-rw-r--r--roms/u-boot/drivers/cpu/mpc83xx_cpu.h126
-rw-r--r--roms/u-boot/drivers/cpu/riscv_cpu.c170
10 files changed, 1804 insertions, 0 deletions
diff --git a/roms/u-boot/drivers/cpu/Kconfig b/roms/u-boot/drivers/cpu/Kconfig
new file mode 100644
index 000000000..3d5729f6d
--- /dev/null
+++ b/roms/u-boot/drivers/cpu/Kconfig
@@ -0,0 +1,21 @@
+config CPU
+ bool "Enable CPU drivers using Driver Model"
+ help
+ This allows drivers to be provided for CPUs and their type to be
+ specified in the board's device tree. For boards which support
+ multiple CPUs, then normally have to be set up in U-Boot so that
+ they can work correctly in the OS. This provides a framework for
+ finding out information about available CPUs and making changes.
+
+config CPU_MPC83XX
+ bool "Enable MPC83xx CPU driver"
+ depends on CPU
+ select CLK_MPC83XX
+ help
+ Support CPU cores for SoCs of the MPC83xx series.
+
+config CPU_RISCV
+ bool "Enable RISC-V CPU driver"
+ depends on CPU && RISCV
+ help
+ Support CPU cores for RISC-V architecture.
diff --git a/roms/u-boot/drivers/cpu/Makefile b/roms/u-boot/drivers/cpu/Makefile
new file mode 100644
index 000000000..c8532637c
--- /dev/null
+++ b/roms/u-boot/drivers/cpu/Makefile
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c) 2015 Google, Inc
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+
+obj-$(CONFIG_CPU) += cpu-uclass.o
+
+obj-$(CONFIG_ARCH_BMIPS) += bmips_cpu.o
+obj-$(CONFIG_ARCH_IMX8) += imx8_cpu.o
+obj-$(CONFIG_ARCH_AT91) += at91_cpu.o
+obj-$(CONFIG_CPU_MPC83XX) += mpc83xx_cpu.o
+obj-$(CONFIG_CPU_RISCV) += riscv_cpu.o
+obj-$(CONFIG_SANDBOX) += cpu_sandbox.o
diff --git a/roms/u-boot/drivers/cpu/at91_cpu.c b/roms/u-boot/drivers/cpu/at91_cpu.c
new file mode 100644
index 000000000..9ef1b3102
--- /dev/null
+++ b/roms/u-boot/drivers/cpu/at91_cpu.c
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Claudiu Beznea <claudiu.beznea@microchip.com>
+ */
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <div64.h>
+#include <linux/clk-provider.h>
+
+struct at91_cpu_plat {
+ const char *name;
+ ulong cpufreq_mhz;
+ ulong mckfreq_mhz;
+ ulong xtalfreq_mhz;
+};
+
+extern char *get_cpu_name(void);
+
+const char *at91_cpu_get_name(void)
+{
+ return get_cpu_name();
+}
+
+int at91_cpu_get_desc(const struct udevice *dev, char *buf, int size)
+{
+ struct at91_cpu_plat *plat = dev_get_plat(dev);
+
+ snprintf(buf, size, "%s\n"
+ "Crystal frequency: %8lu MHz\n"
+ "CPU clock : %8lu MHz\n"
+ "Master clock : %8lu MHz\n",
+ plat->name, plat->xtalfreq_mhz, plat->cpufreq_mhz,
+ plat->mckfreq_mhz);
+
+ return 0;
+}
+
+static int at91_cpu_get_info(const struct udevice *dev, struct cpu_info *info)
+{
+ struct at91_cpu_plat *plat = dev_get_plat(dev);
+
+ info->cpu_freq = plat->cpufreq_mhz * 1000000;
+ info->features = BIT(CPU_FEAT_L1_CACHE);
+
+ return 0;
+}
+
+static int at91_cpu_get_count(const struct udevice *dev)
+{
+ return 1;
+}
+
+static int at91_cpu_get_vendor(const struct udevice *dev, char *buf, int size)
+{
+ snprintf(buf, size, "Microchip Technology Inc.");
+
+ return 0;
+}
+
+static const struct cpu_ops at91_cpu_ops = {
+ .get_desc = at91_cpu_get_desc,
+ .get_info = at91_cpu_get_info,
+ .get_count = at91_cpu_get_count,
+ .get_vendor = at91_cpu_get_vendor,
+};
+
+static const struct udevice_id at91_cpu_ids[] = {
+ { .compatible = "arm,cortex-a7" },
+ { /* Sentinel. */ }
+};
+
+static int at91_cpu_probe(struct udevice *dev)
+{
+ struct at91_cpu_plat *plat = dev_get_plat(dev);
+ struct clk clk;
+ ulong rate;
+ int ret;
+
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (ret)
+ return ret;
+
+ rate = clk_get_rate(&clk);
+ if (!rate)
+ return -ENOTSUPP;
+ plat->cpufreq_mhz = DIV_ROUND_CLOSEST_ULL(rate, 1000000);
+
+ ret = clk_get_by_index(dev, 1, &clk);
+ if (ret)
+ return ret;
+
+ rate = clk_get_rate(&clk);
+ if (!rate)
+ return -ENOTSUPP;
+ plat->mckfreq_mhz = DIV_ROUND_CLOSEST_ULL(rate, 1000000);
+
+ ret = clk_get_by_index(dev, 2, &clk);
+ if (ret)
+ return ret;
+
+ rate = clk_get_rate(&clk);
+ if (!rate)
+ return -ENOTSUPP;
+ plat->xtalfreq_mhz = DIV_ROUND_CLOSEST_ULL(rate, 1000000);
+
+ plat->name = get_cpu_name();
+
+ return 0;
+}
+
+U_BOOT_DRIVER(cpu_at91_drv) = {
+ .name = "at91-cpu",
+ .id = UCLASS_CPU,
+ .of_match = at91_cpu_ids,
+ .ops = &at91_cpu_ops,
+ .probe = at91_cpu_probe,
+ .plat_auto = sizeof(struct at91_cpu_plat),
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/roms/u-boot/drivers/cpu/bmips_cpu.c b/roms/u-boot/drivers/cpu/bmips_cpu.c
new file mode 100644
index 000000000..172bc9980
--- /dev/null
+++ b/roms/u-boot/drivers/cpu/bmips_cpu.c
@@ -0,0 +1,522 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/arch/mips/bcm63xx/cpu.c:
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ * Copyright (C) 2009 Florian Fainelli <florian@openwrt.org>
+ */
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <errno.h>
+#include <init.h>
+#include <asm/io.h>
+#include <linux/bitops.h>
+
+#define REV_CHIPID_SHIFT 16
+#define REV_CHIPID_MASK (0xffff << REV_CHIPID_SHIFT)
+#define REV_LONG_CHIPID_SHIFT 12
+#define REV_LONG_CHIPID_MASK (0xfffff << REV_LONG_CHIPID_SHIFT)
+#define REV_REVID_SHIFT 0
+#define REV_REVID_MASK (0xff << REV_REVID_SHIFT)
+
+#define REG_BCM6328_OTP 0x62c
+#define BCM6328_TP1_DISABLED BIT(9)
+
+#define REG_BCM6318_STRAP_OVRDBUS 0x900
+#define OVRDBUS_6318_FREQ_SHIFT 23
+#define OVRDBUS_6318_FREQ_MASK (0x3 << OVRDBUS_6318_FREQ_SHIFT)
+
+#define REG_BCM6328_MISC_STRAPBUS 0x1a40
+#define STRAPBUS_6328_FCVO_SHIFT 7
+#define STRAPBUS_6328_FCVO_MASK (0x1f << STRAPBUS_6328_FCVO_SHIFT)
+
+#define REG_BCM6348_PERF_MIPSPLLCFG 0x34
+#define MIPSPLLCFG_6348_M1CPU_SHIFT 6
+#define MIPSPLLCFG_6348_M1CPU_MASK (0x7 << MIPSPLLCFG_6348_M1CPU_SHIFT)
+#define MIPSPLLCFG_6348_N2_SHIFT 15
+#define MIPSPLLCFG_6348_N2_MASK (0x1F << MIPSPLLCFG_6348_N2_SHIFT)
+#define MIPSPLLCFG_6348_N1_SHIFT 20
+#define MIPSPLLCFG_6348_N1_MASK (0x7 << MIPSPLLCFG_6348_N1_SHIFT)
+
+#define REG_BCM6358_DDR_DMIPSPLLCFG 0x12b8
+#define DMIPSPLLCFG_6358_M1_SHIFT 0
+#define DMIPSPLLCFG_6358_M1_MASK (0xff << DMIPSPLLCFG_6358_M1_SHIFT)
+#define DMIPSPLLCFG_6358_N1_SHIFT 23
+#define DMIPSPLLCFG_6358_N1_MASK (0x3f << DMIPSPLLCFG_6358_N1_SHIFT)
+#define DMIPSPLLCFG_6358_N2_SHIFT 29
+#define DMIPSPLLCFG_6358_N2_MASK (0x7 << DMIPSPLLCFG_6358_N2_SHIFT)
+
+#define REG_BCM6362_MISC_STRAPBUS 0x1814
+#define STRAPBUS_6362_FCVO_SHIFT 1
+#define STRAPBUS_6362_FCVO_MASK (0x1f << STRAPBUS_6362_FCVO_SHIFT)
+
+#define REG_BCM6368_DDR_DMIPSPLLCFG 0x12a0
+#define DMIPSPLLCFG_6368_P1_SHIFT 0
+#define DMIPSPLLCFG_6368_P1_MASK (0xf << DMIPSPLLCFG_6368_P1_SHIFT)
+#define DMIPSPLLCFG_6368_P2_SHIFT 4
+#define DMIPSPLLCFG_6368_P2_MASK (0xf << DMIPSPLLCFG_6368_P2_SHIFT)
+#define DMIPSPLLCFG_6368_NDIV_SHIFT 16
+#define DMIPSPLLCFG_6368_NDIV_MASK (0x1ff << DMIPSPLLCFG_6368_NDIV_SHIFT)
+#define REG_BCM6368_DDR_DMIPSPLLDIV 0x12a4
+#define DMIPSPLLDIV_6368_MDIV_SHIFT 0
+#define DMIPSPLLDIV_6368_MDIV_MASK (0xff << DMIPSPLLDIV_6368_MDIV_SHIFT)
+
+#define REG_BCM63268_MISC_STRAPBUS 0x1814
+#define STRAPBUS_63268_FCVO_SHIFT 21
+#define STRAPBUS_63268_FCVO_MASK (0xf << STRAPBUS_63268_FCVO_SHIFT)
+
+#define REG_BCM6838_OTP_BRCMBITS0 0x440
+#define VIPER_6838_FREQ_SHIFT 18
+#define VIPER_6838_FREQ_MASK (0x7 << VIPER_6838_FREQ_SHIFT)
+
+struct bmips_cpu_priv;
+
+struct bmips_cpu_hw {
+ int (*get_cpu_desc)(struct bmips_cpu_priv *priv, char *buf, int size);
+ ulong (*get_cpu_freq)(struct bmips_cpu_priv *);
+ int (*get_cpu_count)(struct bmips_cpu_priv *);
+};
+
+struct bmips_cpu_priv {
+ void __iomem *regs;
+ const struct bmips_cpu_hw *hw;
+};
+
+/* Specific CPU Ops */
+static int bmips_short_cpu_desc(struct bmips_cpu_priv *priv, char *buf,
+ int size)
+{
+ unsigned short cpu_id;
+ unsigned char cpu_rev;
+ u32 val;
+
+ val = readl_be(priv->regs);
+ cpu_id = (val & REV_CHIPID_MASK) >> REV_CHIPID_SHIFT;
+ cpu_rev = (val & REV_REVID_MASK) >> REV_REVID_SHIFT;
+
+ snprintf(buf, size, "BCM%04X%02X", cpu_id, cpu_rev);
+
+ return 0;
+}
+
+static int bmips_long_cpu_desc(struct bmips_cpu_priv *priv, char *buf,
+ int size)
+{
+ unsigned int cpu_id;
+ unsigned char cpu_rev;
+ u32 val;
+
+ val = readl_be(priv->regs);
+ cpu_id = (val & REV_LONG_CHIPID_MASK) >> REV_LONG_CHIPID_SHIFT;
+ cpu_rev = (val & REV_REVID_MASK) >> REV_REVID_SHIFT;
+
+ snprintf(buf, size, "BCM%05X%02X", cpu_id, cpu_rev);
+
+ return 0;
+}
+
+static ulong bcm3380_get_cpu_freq(struct bmips_cpu_priv *priv)
+{
+ return 333000000;
+}
+
+static ulong bcm6318_get_cpu_freq(struct bmips_cpu_priv *priv)
+{
+ unsigned int mips_pll_fcvo;
+
+ mips_pll_fcvo = readl_be(priv->regs + REG_BCM6318_STRAP_OVRDBUS);
+ mips_pll_fcvo = (mips_pll_fcvo & OVRDBUS_6318_FREQ_MASK)
+ >> OVRDBUS_6318_FREQ_SHIFT;
+
+ switch (mips_pll_fcvo) {
+ case 0:
+ return 166000000;
+ case 1:
+ return 400000000;
+ case 2:
+ return 250000000;
+ case 3:
+ return 333000000;
+ default:
+ return 0;
+ }
+}
+
+static ulong bcm6328_get_cpu_freq(struct bmips_cpu_priv *priv)
+{
+ unsigned int mips_pll_fcvo;
+
+ mips_pll_fcvo = readl_be(priv->regs + REG_BCM6328_MISC_STRAPBUS);
+ mips_pll_fcvo = (mips_pll_fcvo & STRAPBUS_6328_FCVO_MASK)
+ >> STRAPBUS_6328_FCVO_SHIFT;
+
+ switch (mips_pll_fcvo) {
+ case 0x12:
+ case 0x14:
+ case 0x19:
+ return 160000000;
+ case 0x1c:
+ return 192000000;
+ case 0x13:
+ case 0x15:
+ return 200000000;
+ case 0x1a:
+ return 384000000;
+ case 0x16:
+ return 400000000;
+ default:
+ return 320000000;
+ }
+}
+
+static ulong bcm6338_get_cpu_freq(struct bmips_cpu_priv *priv)
+{
+ return 240000000;
+}
+
+static ulong bcm6348_get_cpu_freq(struct bmips_cpu_priv *priv)
+{
+ unsigned int tmp, n1, n2, m1;
+
+ tmp = readl_be(priv->regs + REG_BCM6348_PERF_MIPSPLLCFG);
+ n1 = (tmp & MIPSPLLCFG_6348_N1_MASK) >> MIPSPLLCFG_6348_N1_SHIFT;
+ n2 = (tmp & MIPSPLLCFG_6348_N2_MASK) >> MIPSPLLCFG_6348_N2_SHIFT;
+ m1 = (tmp & MIPSPLLCFG_6348_M1CPU_MASK) >> MIPSPLLCFG_6348_M1CPU_SHIFT;
+
+ return (16 * 1000000 * (n1 + 1) * (n2 + 2)) / (m1 + 1);
+}
+
+static ulong bcm6358_get_cpu_freq(struct bmips_cpu_priv *priv)
+{
+ unsigned int tmp, n1, n2, m1;
+
+ tmp = readl_be(priv->regs + REG_BCM6358_DDR_DMIPSPLLCFG);
+ n1 = (tmp & DMIPSPLLCFG_6358_N1_MASK) >> DMIPSPLLCFG_6358_N1_SHIFT;
+ n2 = (tmp & DMIPSPLLCFG_6358_N2_MASK) >> DMIPSPLLCFG_6358_N2_SHIFT;
+ m1 = (tmp & DMIPSPLLCFG_6358_M1_MASK) >> DMIPSPLLCFG_6358_M1_SHIFT;
+
+ return (16 * 1000000 * n1 * n2) / m1;
+}
+
+static ulong bcm6362_get_cpu_freq(struct bmips_cpu_priv *priv)
+{
+ unsigned int mips_pll_fcvo;
+
+ mips_pll_fcvo = readl_be(priv->regs + REG_BCM6362_MISC_STRAPBUS);
+ mips_pll_fcvo = (mips_pll_fcvo & STRAPBUS_6362_FCVO_MASK)
+ >> STRAPBUS_6362_FCVO_SHIFT;
+
+ switch (mips_pll_fcvo) {
+ case 0x03:
+ case 0x0b:
+ case 0x13:
+ case 0x1b:
+ return 240000000;
+ case 0x04:
+ case 0x0c:
+ case 0x14:
+ case 0x1c:
+ return 160000000;
+ case 0x05:
+ case 0x0e:
+ case 0x16:
+ case 0x1e:
+ case 0x1f:
+ return 400000000;
+ case 0x06:
+ return 440000000;
+ case 0x07:
+ case 0x17:
+ return 384000000;
+ case 0x15:
+ case 0x1d:
+ return 200000000;
+ default:
+ return 320000000;
+ }
+}
+
+static ulong bcm6368_get_cpu_freq(struct bmips_cpu_priv *priv)
+{
+ unsigned int tmp, p1, p2, ndiv, m1;
+
+ tmp = readl_be(priv->regs + REG_BCM6368_DDR_DMIPSPLLCFG);
+ p1 = (tmp & DMIPSPLLCFG_6368_P1_MASK) >> DMIPSPLLCFG_6368_P1_SHIFT;
+ p2 = (tmp & DMIPSPLLCFG_6368_P2_MASK) >> DMIPSPLLCFG_6368_P2_SHIFT;
+ ndiv = (tmp & DMIPSPLLCFG_6368_NDIV_MASK) >>
+ DMIPSPLLCFG_6368_NDIV_SHIFT;
+
+ tmp = readl_be(priv->regs + REG_BCM6368_DDR_DMIPSPLLDIV);
+ m1 = (tmp & DMIPSPLLDIV_6368_MDIV_MASK) >> DMIPSPLLDIV_6368_MDIV_SHIFT;
+
+ return (((64 * 1000000) / p1) * p2 * ndiv) / m1;
+}
+
+static ulong bcm63268_get_cpu_freq(struct bmips_cpu_priv *priv)
+{
+ unsigned int mips_pll_fcvo;
+
+ mips_pll_fcvo = readl_be(priv->regs + REG_BCM63268_MISC_STRAPBUS);
+ mips_pll_fcvo = (mips_pll_fcvo & STRAPBUS_63268_FCVO_MASK)
+ >> STRAPBUS_63268_FCVO_SHIFT;
+
+ switch (mips_pll_fcvo) {
+ case 0x3:
+ case 0xe:
+ return 320000000;
+ case 0xa:
+ return 333000000;
+ case 0x2:
+ case 0xb:
+ case 0xf:
+ return 400000000;
+ default:
+ return 0;
+ }
+}
+
+static ulong bcm6838_get_cpu_freq(struct bmips_cpu_priv *priv)
+{
+ unsigned int mips_viper_freq;
+
+ mips_viper_freq = readl_be(priv->regs + REG_BCM6838_OTP_BRCMBITS0);
+ mips_viper_freq = (mips_viper_freq & VIPER_6838_FREQ_MASK)
+ >> VIPER_6838_FREQ_SHIFT;
+
+ switch (mips_viper_freq) {
+ case 0x0:
+ return 600000000;
+ case 0x1:
+ return 400000000;
+ case 0x2:
+ return 240000000;
+ default:
+ return 0;
+ }
+}
+
+static int bcm6328_get_cpu_count(struct bmips_cpu_priv *priv)
+{
+ u32 val = readl_be(priv->regs + REG_BCM6328_OTP);
+
+ if (val & BCM6328_TP1_DISABLED)
+ return 1;
+ else
+ return 2;
+}
+
+static int bcm6345_get_cpu_count(struct bmips_cpu_priv *priv)
+{
+ return 1;
+}
+
+static int bcm6358_get_cpu_count(struct bmips_cpu_priv *priv)
+{
+ return 2;
+}
+
+static const struct bmips_cpu_hw bmips_cpu_bcm3380 = {
+ .get_cpu_desc = bmips_short_cpu_desc,
+ .get_cpu_freq = bcm3380_get_cpu_freq,
+ .get_cpu_count = bcm6358_get_cpu_count,
+};
+
+static const struct bmips_cpu_hw bmips_cpu_bcm6318 = {
+ .get_cpu_desc = bmips_short_cpu_desc,
+ .get_cpu_freq = bcm6318_get_cpu_freq,
+ .get_cpu_count = bcm6345_get_cpu_count,
+};
+
+static const struct bmips_cpu_hw bmips_cpu_bcm6328 = {
+ .get_cpu_desc = bmips_long_cpu_desc,
+ .get_cpu_freq = bcm6328_get_cpu_freq,
+ .get_cpu_count = bcm6328_get_cpu_count,
+};
+
+static const struct bmips_cpu_hw bmips_cpu_bcm6338 = {
+ .get_cpu_desc = bmips_short_cpu_desc,
+ .get_cpu_freq = bcm6338_get_cpu_freq,
+ .get_cpu_count = bcm6345_get_cpu_count,
+};
+
+static const struct bmips_cpu_hw bmips_cpu_bcm6348 = {
+ .get_cpu_desc = bmips_short_cpu_desc,
+ .get_cpu_freq = bcm6348_get_cpu_freq,
+ .get_cpu_count = bcm6345_get_cpu_count,
+};
+
+static const struct bmips_cpu_hw bmips_cpu_bcm6358 = {
+ .get_cpu_desc = bmips_short_cpu_desc,
+ .get_cpu_freq = bcm6358_get_cpu_freq,
+ .get_cpu_count = bcm6358_get_cpu_count,
+};
+
+static const struct bmips_cpu_hw bmips_cpu_bcm6362 = {
+ .get_cpu_desc = bmips_short_cpu_desc,
+ .get_cpu_freq = bcm6362_get_cpu_freq,
+ .get_cpu_count = bcm6358_get_cpu_count,
+};
+
+static const struct bmips_cpu_hw bmips_cpu_bcm6368 = {
+ .get_cpu_desc = bmips_short_cpu_desc,
+ .get_cpu_freq = bcm6368_get_cpu_freq,
+ .get_cpu_count = bcm6358_get_cpu_count,
+};
+
+static const struct bmips_cpu_hw bmips_cpu_bcm63268 = {
+ .get_cpu_desc = bmips_long_cpu_desc,
+ .get_cpu_freq = bcm63268_get_cpu_freq,
+ .get_cpu_count = bcm6358_get_cpu_count,
+};
+
+static const struct bmips_cpu_hw bmips_cpu_bcm6838 = {
+ .get_cpu_desc = bmips_short_cpu_desc,
+ .get_cpu_freq = bcm6838_get_cpu_freq,
+ .get_cpu_count = bcm6358_get_cpu_count,
+};
+
+/* Generic CPU Ops */
+static int bmips_cpu_get_desc(const struct udevice *dev, char *buf, int size)
+{
+ struct bmips_cpu_priv *priv = dev_get_priv(dev);
+ const struct bmips_cpu_hw *hw = priv->hw;
+
+ return hw->get_cpu_desc(priv, buf, size);
+}
+
+static int bmips_cpu_get_info(const struct udevice *dev, struct cpu_info *info)
+{
+ struct bmips_cpu_priv *priv = dev_get_priv(dev);
+ const struct bmips_cpu_hw *hw = priv->hw;
+
+ info->cpu_freq = hw->get_cpu_freq(priv);
+ info->features = BIT(CPU_FEAT_L1_CACHE);
+ info->features |= BIT(CPU_FEAT_MMU);
+ info->features |= BIT(CPU_FEAT_DEVICE_ID);
+
+ return 0;
+}
+
+static int bmips_cpu_get_count(const struct udevice *dev)
+{
+ struct bmips_cpu_priv *priv = dev_get_priv(dev);
+ const struct bmips_cpu_hw *hw = priv->hw;
+
+ return hw->get_cpu_count(priv);
+}
+
+static int bmips_cpu_get_vendor(const struct udevice *dev, char *buf, int size)
+{
+ snprintf(buf, size, "Broadcom");
+
+ return 0;
+}
+
+static const struct cpu_ops bmips_cpu_ops = {
+ .get_desc = bmips_cpu_get_desc,
+ .get_info = bmips_cpu_get_info,
+ .get_count = bmips_cpu_get_count,
+ .get_vendor = bmips_cpu_get_vendor,
+};
+
+/* BMIPS CPU driver */
+int bmips_cpu_bind(struct udevice *dev)
+{
+ struct cpu_plat *plat = dev_get_parent_plat(dev);
+
+ plat->cpu_id = dev_read_u32_default(dev, "reg", -1);
+ plat->device_id = read_c0_prid();
+
+ return 0;
+}
+
+int bmips_cpu_probe(struct udevice *dev)
+{
+ struct bmips_cpu_priv *priv = dev_get_priv(dev);
+ const struct bmips_cpu_hw *hw =
+ (const struct bmips_cpu_hw *)dev_get_driver_data(dev);
+
+ priv->regs = dev_remap_addr(dev_get_parent(dev));
+ if (!priv->regs)
+ return -EINVAL;
+
+ priv->hw = hw;
+
+ return 0;
+}
+
+static const struct udevice_id bmips_cpu_ids[] = {
+ {
+ .compatible = "brcm,bcm3380-cpu",
+ .data = (ulong)&bmips_cpu_bcm3380,
+ }, {
+ .compatible = "brcm,bcm6318-cpu",
+ .data = (ulong)&bmips_cpu_bcm6318,
+ }, {
+ .compatible = "brcm,bcm6328-cpu",
+ .data = (ulong)&bmips_cpu_bcm6328,
+ }, {
+ .compatible = "brcm,bcm6338-cpu",
+ .data = (ulong)&bmips_cpu_bcm6338,
+ }, {
+ .compatible = "brcm,bcm6348-cpu",
+ .data = (ulong)&bmips_cpu_bcm6348,
+ }, {
+ .compatible = "brcm,bcm6358-cpu",
+ .data = (ulong)&bmips_cpu_bcm6358,
+ }, {
+ .compatible = "brcm,bcm6362-cpu",
+ .data = (ulong)&bmips_cpu_bcm6362,
+ }, {
+ .compatible = "brcm,bcm6368-cpu",
+ .data = (ulong)&bmips_cpu_bcm6368,
+ }, {
+ .compatible = "brcm,bcm63268-cpu",
+ .data = (ulong)&bmips_cpu_bcm63268,
+ }, {
+ .compatible = "brcm,bcm6838-cpu",
+ .data = (ulong)&bmips_cpu_bcm6838,
+ },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(bmips_cpu_drv) = {
+ .name = "bmips_cpu",
+ .id = UCLASS_CPU,
+ .of_match = bmips_cpu_ids,
+ .bind = bmips_cpu_bind,
+ .probe = bmips_cpu_probe,
+ .priv_auto = sizeof(struct bmips_cpu_priv),
+ .ops = &bmips_cpu_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
+
+#ifdef CONFIG_DISPLAY_CPUINFO
+int print_cpuinfo(void)
+{
+ struct cpu_info cpu;
+ struct udevice *dev;
+ int err;
+ char desc[100];
+
+ err = uclass_get_device(UCLASS_CPU, 0, &dev);
+ if (err)
+ return 0;
+
+ err = cpu_get_info(dev, &cpu);
+ if (err)
+ return 0;
+
+ err = cpu_get_desc(dev, desc, sizeof(desc));
+ if (err)
+ return 0;
+
+ printf("Chip ID: %s, MIPS: ", desc);
+ print_freq(cpu.cpu_freq, "\n");
+
+ return 0;
+}
+#endif
diff --git a/roms/u-boot/drivers/cpu/cpu-uclass.c b/roms/u-boot/drivers/cpu/cpu-uclass.c
new file mode 100644
index 000000000..1c338bad9
--- /dev/null
+++ b/roms/u-boot/drivers/cpu/cpu-uclass.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <errno.h>
+#include <log.h>
+#include <dm/lists.h>
+#include <dm/root.h>
+#include <linux/err.h>
+
+int cpu_probe_all(void)
+{
+ struct udevice *cpu;
+ int ret;
+
+ ret = uclass_first_device(UCLASS_CPU, &cpu);
+ if (ret) {
+ debug("%s: No CPU found (err = %d)\n", __func__, ret);
+ return ret;
+ }
+
+ while (cpu) {
+ ret = uclass_next_device(&cpu);
+ if (ret) {
+ debug("%s: Error while probing CPU (err = %d)\n",
+ __func__, ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+int cpu_is_current(struct udevice *cpu)
+{
+ struct cpu_ops *ops = cpu_get_ops(cpu);
+
+ if (ops->is_current) {
+ if (ops->is_current(cpu))
+ return 1;
+ }
+
+ return -ENOSYS;
+}
+
+struct udevice *cpu_get_current_dev(void)
+{
+ struct udevice *cpu;
+ int ret;
+
+ uclass_foreach_dev_probe(UCLASS_CPU, cpu) {
+ if (cpu_is_current(cpu) > 0)
+ return cpu;
+ }
+
+ /* If can't find current cpu device, use the first dev instead */
+ ret = uclass_first_device_err(UCLASS_CPU, &cpu);
+ if (ret) {
+ debug("%s: Could not get CPU device (err = %d)\n",
+ __func__, ret);
+ return NULL;
+ }
+
+ return cpu;
+}
+
+int cpu_get_desc(const struct udevice *dev, char *buf, int size)
+{
+ struct cpu_ops *ops = cpu_get_ops(dev);
+
+ if (!ops->get_desc)
+ return -ENOSYS;
+
+ return ops->get_desc(dev, buf, size);
+}
+
+int cpu_get_info(const struct udevice *dev, struct cpu_info *info)
+{
+ struct cpu_ops *ops = cpu_get_ops(dev);
+
+ if (!ops->get_info)
+ return -ENOSYS;
+
+ /* Init cpu_info to 0 */
+ memset(info, 0, sizeof(struct cpu_info));
+
+ return ops->get_info(dev, info);
+}
+
+int cpu_get_count(const struct udevice *dev)
+{
+ struct cpu_ops *ops = cpu_get_ops(dev);
+
+ if (!ops->get_count)
+ return -ENOSYS;
+
+ return ops->get_count(dev);
+}
+
+int cpu_get_vendor(const struct udevice *dev, char *buf, int size)
+{
+ struct cpu_ops *ops = cpu_get_ops(dev);
+
+ if (!ops->get_vendor)
+ return -ENOSYS;
+
+ return ops->get_vendor(dev, buf, size);
+}
+
+U_BOOT_DRIVER(cpu_bus) = {
+ .name = "cpu_bus",
+ .id = UCLASS_SIMPLE_BUS,
+ .per_child_plat_auto = sizeof(struct cpu_plat),
+};
+
+static int uclass_cpu_init(struct uclass *uc)
+{
+ struct udevice *dev;
+ ofnode node;
+ int ret;
+
+ node = ofnode_path("/cpus");
+ if (!ofnode_valid(node))
+ return 0;
+
+ ret = device_bind_driver_to_node(dm_root(), "cpu_bus", "cpus", node,
+ &dev);
+
+ return ret;
+}
+
+UCLASS_DRIVER(cpu) = {
+ .id = UCLASS_CPU,
+ .name = "cpu",
+ .flags = DM_UC_FLAG_SEQ_ALIAS,
+ .init = uclass_cpu_init,
+};
diff --git a/roms/u-boot/drivers/cpu/cpu_sandbox.c b/roms/u-boot/drivers/cpu/cpu_sandbox.c
new file mode 100644
index 000000000..fe6772ba5
--- /dev/null
+++ b/roms/u-boot/drivers/cpu/cpu_sandbox.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018
+ * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <cpu.h>
+
+static int cpu_sandbox_get_desc(const struct udevice *dev, char *buf, int size)
+{
+ snprintf(buf, size, "LEG Inc. SuperMegaUltraTurbo CPU No. 1");
+
+ return 0;
+}
+
+static int cpu_sandbox_get_info(const struct udevice *dev,
+ struct cpu_info *info)
+{
+ info->cpu_freq = 42 * 42 * 42 * 42 * 42;
+ info->features = 0x42424242;
+ info->address_width = IS_ENABLED(CONFIG_PHYS_64BIT) ? 64 : 32;
+
+ return 0;
+}
+
+static int cpu_sandbox_get_count(const struct udevice *dev)
+{
+ return 42;
+}
+
+static int cpu_sandbox_get_vendor(const struct udevice *dev, char *buf,
+ int size)
+{
+ snprintf(buf, size, "Languid Example Garbage Inc.");
+
+ return 0;
+}
+
+static const char *cpu_current = "cpu-test1";
+
+void cpu_sandbox_set_current(const char *name)
+{
+ cpu_current = name;
+}
+
+static int cpu_sandbox_is_current(struct udevice *dev)
+{
+ if (!strcmp(dev->name, cpu_current))
+ return 1;
+
+ return 0;
+}
+
+static const struct cpu_ops cpu_sandbox_ops = {
+ .get_desc = cpu_sandbox_get_desc,
+ .get_info = cpu_sandbox_get_info,
+ .get_count = cpu_sandbox_get_count,
+ .get_vendor = cpu_sandbox_get_vendor,
+ .is_current = cpu_sandbox_is_current,
+};
+
+static int cpu_sandbox_bind(struct udevice *dev)
+{
+ int ret;
+ struct cpu_plat *plat = dev_get_parent_plat(dev);
+
+ /* first examine the property in current cpu node */
+ ret = dev_read_u32(dev, "timebase-frequency", &plat->timebase_freq);
+ /* if not found, then look at the parent /cpus node */
+ if (ret)
+ ret = dev_read_u32(dev->parent, "timebase-frequency",
+ &plat->timebase_freq);
+
+ return ret;
+}
+
+static int cpu_sandbox_probe(struct udevice *dev)
+{
+ return 0;
+}
+
+static const struct udevice_id cpu_sandbox_ids[] = {
+ { .compatible = "sandbox,cpu_sandbox" },
+ { }
+};
+
+U_BOOT_DRIVER(cpu_sandbox) = {
+ .name = "cpu_sandbox",
+ .id = UCLASS_CPU,
+ .ops = &cpu_sandbox_ops,
+ .of_match = cpu_sandbox_ids,
+ .bind = cpu_sandbox_bind,
+ .probe = cpu_sandbox_probe,
+};
diff --git a/roms/u-boot/drivers/cpu/imx8_cpu.c b/roms/u-boot/drivers/cpu/imx8_cpu.c
new file mode 100644
index 000000000..abddbef57
--- /dev/null
+++ b/roms/u-boot/drivers/cpu/imx8_cpu.c
@@ -0,0 +1,236 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ */
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <thermal.h>
+#include <asm/global_data.h>
+#include <asm/system.h>
+#include <asm/arch/sci/sci.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch-imx/cpu.h>
+#include <asm/armv8/cpu.h>
+#include <linux/bitops.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct cpu_imx_plat {
+ const char *name;
+ const char *rev;
+ const char *type;
+ u32 cpu_rsrc;
+ u32 cpurev;
+ u32 freq_mhz;
+ u32 mpidr;
+};
+
+const char *get_imx8_type(u32 imxtype)
+{
+ switch (imxtype) {
+ case MXC_CPU_IMX8QXP:
+ case MXC_CPU_IMX8QXP_A0:
+ return "QXP";
+ case MXC_CPU_IMX8QM:
+ return "QM";
+ default:
+ return "??";
+ }
+}
+
+const char *get_imx8_rev(u32 rev)
+{
+ switch (rev) {
+ case CHIP_REV_A:
+ return "A";
+ case CHIP_REV_B:
+ return "B";
+ case CHIP_REV_C:
+ return "C";
+ default:
+ return "?";
+ }
+}
+
+static void set_core_data(struct udevice *dev)
+{
+ struct cpu_imx_plat *plat = dev_get_plat(dev);
+
+ if (device_is_compatible(dev, "arm,cortex-a35")) {
+ plat->cpu_rsrc = SC_R_A35;
+ plat->name = "A35";
+ } else if (device_is_compatible(dev, "arm,cortex-a53")) {
+ plat->cpu_rsrc = SC_R_A53;
+ plat->name = "A53";
+ } else if (device_is_compatible(dev, "arm,cortex-a72")) {
+ plat->cpu_rsrc = SC_R_A72;
+ plat->name = "A72";
+ } else {
+ plat->cpu_rsrc = SC_R_A53;
+ plat->name = "?";
+ }
+}
+
+#if IS_ENABLED(CONFIG_IMX_SCU_THERMAL)
+static int cpu_imx_get_temp(struct cpu_imx_plat *plat)
+{
+ struct udevice *thermal_dev;
+ int cpu_tmp, ret;
+ int idx = 1; /* use "cpu-thermal0" device */
+
+ if (plat->cpu_rsrc == SC_R_A72)
+ idx = 2; /* use "cpu-thermal1" device */
+
+ ret = uclass_get_device(UCLASS_THERMAL, idx, &thermal_dev);
+ if (!ret) {
+ ret = thermal_get_temp(thermal_dev, &cpu_tmp);
+ if (ret)
+ return 0xdeadbeef;
+ } else {
+ return 0xdeadbeef;
+ }
+
+ return cpu_tmp;
+}
+#else
+static int cpu_imx_get_temp(struct cpu_imx_plat *plat)
+{
+ return 0;
+}
+#endif
+
+int cpu_imx_get_desc(const struct udevice *dev, char *buf, int size)
+{
+ struct cpu_imx_plat *plat = dev_get_plat(dev);
+ int ret, temp;
+
+ if (size < 100)
+ return -ENOSPC;
+
+ ret = snprintf(buf, size, "NXP i.MX8%s Rev%s %s at %u MHz",
+ plat->type, plat->rev, plat->name, plat->freq_mhz);
+
+ if (IS_ENABLED(CONFIG_IMX_SCU_THERMAL)) {
+ temp = cpu_imx_get_temp(plat);
+ buf = buf + ret;
+ size = size - ret;
+ if (temp != 0xdeadbeef)
+ ret = snprintf(buf, size, " at %dC", temp);
+ else
+ ret = snprintf(buf, size, " - invalid sensor data");
+ }
+
+ snprintf(buf + ret, size - ret, "\n");
+
+ return 0;
+}
+
+static int cpu_imx_get_info(const struct udevice *dev, struct cpu_info *info)
+{
+ struct cpu_imx_plat *plat = dev_get_plat(dev);
+
+ info->cpu_freq = plat->freq_mhz * 1000;
+ info->features = BIT(CPU_FEAT_L1_CACHE) | BIT(CPU_FEAT_MMU);
+ return 0;
+}
+
+static int cpu_imx_get_count(const struct udevice *dev)
+{
+ ofnode node;
+ int num = 0;
+
+ ofnode_for_each_subnode(node, dev_ofnode(dev->parent)) {
+ const char *device_type;
+
+ if (!ofnode_is_available(node))
+ continue;
+
+ device_type = ofnode_read_string(node, "device_type");
+ if (!device_type)
+ continue;
+
+ if (!strcmp(device_type, "cpu"))
+ num++;
+ }
+
+ return num;
+}
+
+static int cpu_imx_get_vendor(const struct udevice *dev, char *buf, int size)
+{
+ snprintf(buf, size, "NXP");
+ return 0;
+}
+
+static int cpu_imx_is_current(struct udevice *dev)
+{
+ struct cpu_imx_plat *plat = dev_get_plat(dev);
+
+ if (plat->mpidr == (read_mpidr() & 0xffff))
+ return 1;
+
+ return 0;
+}
+
+static const struct cpu_ops cpu_imx8_ops = {
+ .get_desc = cpu_imx_get_desc,
+ .get_info = cpu_imx_get_info,
+ .get_count = cpu_imx_get_count,
+ .get_vendor = cpu_imx_get_vendor,
+ .is_current = cpu_imx_is_current,
+};
+
+static const struct udevice_id cpu_imx8_ids[] = {
+ { .compatible = "arm,cortex-a35" },
+ { .compatible = "arm,cortex-a53" },
+ { .compatible = "arm,cortex-a72" },
+ { }
+};
+
+static ulong imx8_get_cpu_rate(struct udevice *dev)
+{
+ struct cpu_imx_plat *plat = dev_get_plat(dev);
+ ulong rate;
+ int ret;
+
+ ret = sc_pm_get_clock_rate(-1, plat->cpu_rsrc, SC_PM_CLK_CPU,
+ (sc_pm_clock_rate_t *)&rate);
+ if (ret) {
+ printf("Could not read CPU frequency: %d\n", ret);
+ return 0;
+ }
+
+ return rate;
+}
+
+static int imx8_cpu_probe(struct udevice *dev)
+{
+ struct cpu_imx_plat *plat = dev_get_plat(dev);
+ u32 cpurev;
+
+ set_core_data(dev);
+ cpurev = get_cpu_rev();
+ plat->cpurev = cpurev;
+ plat->rev = get_imx8_rev(cpurev & 0xFFF);
+ plat->type = get_imx8_type((cpurev & 0xFF000) >> 12);
+ plat->freq_mhz = imx8_get_cpu_rate(dev) / 1000000;
+ plat->mpidr = dev_read_addr(dev);
+ if (plat->mpidr == FDT_ADDR_T_NONE) {
+ printf("%s: Failed to get CPU reg property\n", __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+U_BOOT_DRIVER(cpu_imx8_drv) = {
+ .name = "imx8x_cpu",
+ .id = UCLASS_CPU,
+ .of_match = cpu_imx8_ids,
+ .ops = &cpu_imx8_ops,
+ .probe = imx8_cpu_probe,
+ .plat_auto = sizeof(struct cpu_imx_plat),
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/roms/u-boot/drivers/cpu/mpc83xx_cpu.c b/roms/u-boot/drivers/cpu/mpc83xx_cpu.c
new file mode 100644
index 000000000..e451c1111
--- /dev/null
+++ b/roms/u-boot/drivers/cpu/mpc83xx_cpu.c
@@ -0,0 +1,354 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018
+ * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
+ */
+
+#include <common.h>
+#include <bitfield.h>
+#include <clk.h>
+#include <cpu.h>
+#include <dm.h>
+#include <log.h>
+#include <vsprintf.h>
+#include <linux/bitops.h>
+
+#include "mpc83xx_cpu.h"
+
+/**
+ * struct mpc83xx_cpu_priv - Private data for MPC83xx CPUs
+ * @e300_type: The e300 core type of the MPC83xx CPU
+ * @family: The MPC83xx family the CPU belongs to
+ * @type: The MPC83xx type of the CPU
+ * @is_e_processor: Flag indicating whether the CPU is a E processor or not
+ * @is_a_variant: Flag indicating whtther the CPU is a A variant or not
+ * @revid: The revision ID of the CPU
+ * @revid.major: The major part of the CPU's revision ID
+ * @revid.minor: The minor part of the CPU's revision ID
+ */
+struct mpc83xx_cpu_priv {
+ enum e300_type e300_type;
+ enum mpc83xx_cpu_family family;
+ enum mpc83xx_cpu_type type;
+ bool is_e_processor;
+ bool is_a_variant;
+ struct {
+ uint major;
+ uint minor;
+ } revid;
+};
+
+int checkcpu(void)
+{
+ /* Activate all CPUs from board_f.c */
+ return cpu_probe_all();
+}
+
+/**
+ * get_spridr() - Read SPRIDR (System Part and Revision ID Register) of CPU
+ *
+ * Return: The SPRIDR value
+ */
+static inline u32 get_spridr(void)
+{
+ immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+
+ return in_be32(&immr->sysconf.spridr);
+}
+
+/**
+ * determine_type() - Determine CPU family of MPC83xx device
+ * @dev: CPU device from which to read CPU family from
+ */
+static inline void determine_family(const struct udevice *dev)
+{
+ struct mpc83xx_cpu_priv *priv = dev_get_priv(dev);
+ /* Upper 12 bits of PARTID field (bits 0-23 in SPRIDR) */
+ const u32 PARTID_FAMILY_MASK = 0xFFF00000;
+
+ switch (bitfield_extract_by_mask(get_spridr(), PARTID_FAMILY_MASK)) {
+ case 0x810:
+ case 0x811:
+ priv->family = FAMILY_830X;
+ break;
+ case 0x80B:
+ priv->family = FAMILY_831X;
+ break;
+ case 0x806:
+ priv->family = FAMILY_832X;
+ break;
+ case 0x803:
+ priv->family = FAMILY_834X;
+ break;
+ case 0x804:
+ priv->family = FAMILY_836X;
+ break;
+ case 0x80C:
+ priv->family = FAMILY_837X;
+ break;
+ default:
+ priv->family = FAMILY_UNKNOWN;
+ }
+}
+
+/**
+ * determine_type() - Determine CPU type of MPC83xx device
+ * @dev: CPU device from which to read CPU type from
+ */
+static inline void determine_type(const struct udevice *dev)
+{
+ struct mpc83xx_cpu_priv *priv = dev_get_priv(dev);
+ /* Upper 16 bits of PVR (Processor Version Register) */
+ const u32 PCR_UPPER_MASK = 0xFFFF0000;
+ u32 val;
+
+ val = bitfield_extract_by_mask(get_spridr(), PCR_UPPER_MASK);
+
+ /* Mask out E-variant bit */
+ switch (val & 0xFFFE) {
+ case 0x8100:
+ priv->type = TYPE_8308;
+ break;
+ case 0x8110:
+ priv->type = TYPE_8309;
+ break;
+ case 0x80B2:
+ priv->type = TYPE_8311;
+ break;
+ case 0x80B0:
+ priv->type = TYPE_8313;
+ break;
+ case 0x80B6:
+ priv->type = TYPE_8314;
+ break;
+ case 0x80B4:
+ priv->type = TYPE_8315;
+ break;
+ case 0x8066:
+ priv->type = TYPE_8321;
+ break;
+ case 0x8062:
+ priv->type = TYPE_8323;
+ break;
+ case 0x8036:
+ priv->type = TYPE_8343;
+ break;
+ case 0x8032:
+ priv->type = TYPE_8347_TBGA;
+ break;
+ case 0x8034:
+ priv->type = TYPE_8347_PBGA;
+ break;
+ case 0x8030:
+ priv->type = TYPE_8349;
+ break;
+ case 0x804A:
+ priv->type = TYPE_8358_TBGA;
+ break;
+ case 0x804E:
+ priv->type = TYPE_8358_PBGA;
+ break;
+ case 0x8048:
+ priv->type = TYPE_8360;
+ break;
+ case 0x80C6:
+ priv->type = TYPE_8377;
+ break;
+ case 0x80C4:
+ priv->type = TYPE_8378;
+ break;
+ case 0x80C2:
+ priv->type = TYPE_8379;
+ break;
+ default:
+ priv->type = TYPE_UNKNOWN;
+ }
+}
+
+/**
+ * determine_e300_type() - Determine e300 core type of MPC83xx device
+ * @dev: CPU device from which to read e300 core type from
+ */
+static inline void determine_e300_type(const struct udevice *dev)
+{
+ struct mpc83xx_cpu_priv *priv = dev_get_priv(dev);
+ /* Upper 16 bits of PVR (Processor Version Register) */
+ const u32 PCR_UPPER_MASK = 0xFFFF0000;
+ u32 pvr = get_pvr();
+
+ switch ((pvr & PCR_UPPER_MASK) >> 16) {
+ case 0x8083:
+ priv->e300_type = E300C1;
+ break;
+ case 0x8084:
+ priv->e300_type = E300C2;
+ break;
+ case 0x8085:
+ priv->e300_type = E300C3;
+ break;
+ case 0x8086:
+ priv->e300_type = E300C4;
+ break;
+ default:
+ priv->e300_type = E300_UNKNOWN;
+ }
+}
+
+/**
+ * determine_revid() - Determine revision ID of CPU device
+ * @dev: CPU device from which to read revision ID
+ */
+static inline void determine_revid(const struct udevice *dev)
+{
+ struct mpc83xx_cpu_priv *priv = dev_get_priv(dev);
+ u32 REVID_MAJOR_MASK;
+ u32 REVID_MINOR_MASK;
+ u32 spridr = get_spridr();
+
+ if (priv->family == FAMILY_834X) {
+ REVID_MAJOR_MASK = 0x0000FF00;
+ REVID_MINOR_MASK = 0x000000FF;
+ } else {
+ REVID_MAJOR_MASK = 0x000000F0;
+ REVID_MINOR_MASK = 0x0000000F;
+ }
+
+ priv->revid.major = bitfield_extract_by_mask(spridr, REVID_MAJOR_MASK);
+ priv->revid.minor = bitfield_extract_by_mask(spridr, REVID_MINOR_MASK);
+}
+
+/**
+ * determine_cpu_data() - Determine CPU information from hardware
+ * @dev: CPU device from which to read information
+ */
+static void determine_cpu_data(const struct udevice *dev)
+{
+ struct mpc83xx_cpu_priv *priv = dev_get_priv(dev);
+ const u32 E_FLAG_MASK = 0x00010000;
+ u32 spridr = get_spridr();
+
+ determine_family(dev);
+ determine_type(dev);
+ determine_e300_type(dev);
+ determine_revid(dev);
+
+ if ((priv->family == FAMILY_834X ||
+ priv->family == FAMILY_836X) && priv->revid.major >= 2)
+ priv->is_a_variant = true;
+
+ priv->is_e_processor = !bitfield_extract_by_mask(spridr, E_FLAG_MASK);
+}
+
+static int mpc83xx_cpu_get_desc(const struct udevice *dev, char *buf, int size)
+{
+ struct mpc83xx_cpu_priv *priv = dev_get_priv(dev);
+ struct clk core_clk;
+ struct clk csb_clk;
+ char core_freq[32];
+ char csb_freq[32];
+ int ret;
+
+ ret = clk_get_by_index((struct udevice *)dev, 0, &core_clk);
+ if (ret) {
+ debug("%s: Failed to get core clock (err = %d)\n",
+ dev->name, ret);
+ return ret;
+ }
+
+ ret = clk_get_by_index((struct udevice *)dev, 1, &csb_clk);
+ if (ret) {
+ debug("%s: Failed to get CSB clock (err = %d)\n",
+ dev->name, ret);
+ return ret;
+ }
+
+ determine_cpu_data(dev);
+
+ snprintf(buf, size,
+ "%s, MPC%s%s%s, Rev: %d.%d at %s MHz, CSB: %s MHz",
+ e300_names[priv->e300_type],
+ cpu_type_names[priv->type],
+ priv->is_e_processor ? "E" : "",
+ priv->is_a_variant ? "A" : "",
+ priv->revid.major,
+ priv->revid.minor,
+ strmhz(core_freq, clk_get_rate(&core_clk)),
+ strmhz(csb_freq, clk_get_rate(&csb_clk)));
+
+ return 0;
+}
+
+static int mpc83xx_cpu_get_info(const struct udevice *dev,
+ struct cpu_info *info)
+{
+ struct clk clock;
+ int ret;
+ ulong freq;
+
+ ret = clk_get_by_index((struct udevice *)dev, 0, &clock);
+ if (ret) {
+ debug("%s: Failed to get core clock (err = %d)\n",
+ dev->name, ret);
+ return ret;
+ }
+
+ freq = clk_get_rate(&clock);
+ if (!freq) {
+ debug("%s: Core clock speed is zero\n", dev->name);
+ return -EINVAL;
+ }
+
+ info->cpu_freq = freq;
+ info->features = BIT(CPU_FEAT_L1_CACHE) | BIT(CPU_FEAT_MMU);
+
+ return 0;
+}
+
+static int mpc83xx_cpu_get_count(const struct udevice *dev)
+{
+ /* We have one e300cX core */
+ return 1;
+}
+
+static int mpc83xx_cpu_get_vendor(const struct udevice *dev, char *buf,
+ int size)
+{
+ snprintf(buf, size, "NXP");
+
+ return 0;
+}
+
+static const struct cpu_ops mpc83xx_cpu_ops = {
+ .get_desc = mpc83xx_cpu_get_desc,
+ .get_info = mpc83xx_cpu_get_info,
+ .get_count = mpc83xx_cpu_get_count,
+ .get_vendor = mpc83xx_cpu_get_vendor,
+};
+
+static int mpc83xx_cpu_probe(struct udevice *dev)
+{
+ return 0;
+}
+
+static const struct udevice_id mpc83xx_cpu_ids[] = {
+ { .compatible = "fsl,mpc83xx", },
+ { .compatible = "fsl,mpc8308", },
+ { .compatible = "fsl,mpc8309", },
+ { .compatible = "fsl,mpc8313", },
+ { .compatible = "fsl,mpc8315", },
+ { .compatible = "fsl,mpc832x", },
+ { .compatible = "fsl,mpc8349", },
+ { .compatible = "fsl,mpc8360", },
+ { .compatible = "fsl,mpc8379", },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(mpc83xx_cpu) = {
+ .name = "mpc83xx_cpu",
+ .id = UCLASS_CPU,
+ .of_match = mpc83xx_cpu_ids,
+ .probe = mpc83xx_cpu_probe,
+ .priv_auto = sizeof(struct mpc83xx_cpu_priv),
+ .ops = &mpc83xx_cpu_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/roms/u-boot/drivers/cpu/mpc83xx_cpu.h b/roms/u-boot/drivers/cpu/mpc83xx_cpu.h
new file mode 100644
index 000000000..2aaa4e188
--- /dev/null
+++ b/roms/u-boot/drivers/cpu/mpc83xx_cpu.h
@@ -0,0 +1,126 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2018
+ * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
+ */
+
+#ifndef _MPC83XX_CPU_H_
+#define _MPC83XX_CPU_H_
+
+/**
+ * enum e300_type - Identifiers for e300 cores
+ * @E300C1: Identifier for e300c1 cores
+ * @E300C2: Identifier for e300c2 cores
+ * @E300C3: Identifier for e300c3 cores
+ * @E300C4: Identifier for e300c4 cores
+ * @E300_UNKNOWN: Identifier for unknown e300 cores
+ */
+enum e300_type {
+ E300C1,
+ E300C2,
+ E300C3,
+ E300C4,
+ E300_UNKNOWN,
+};
+
+/* Array mapping the e300 core types to their human-readable names */
+static const char * const e300_names[] = {
+ [E300C1] = "e300c1",
+ [E300C2] = "e300c2",
+ [E300C3] = "e300c3",
+ [E300C4] = "e300c4",
+ [E300_UNKNOWN] = "Unknown e300",
+};
+
+/**
+ * enum mpc83xx_cpu_family - Identifiers for MPC83xx CPU families
+ * @FAMILY_830X: Identifier for the MPC830x CPU family
+ * @FAMILY_831X: Identifier for the MPC831x CPU family
+ * @FAMILY_832X: Identifier for the MPC832x CPU family
+ * @FAMILY_834X: Identifier for the MPC834x CPU family
+ * @FAMILY_836X: Identifier for the MPC836x CPU family
+ * @FAMILY_837X: Identifier for the MPC837x CPU family
+ * @FAMILY_UNKNOWN: Identifier for an unknown MPC83xx CPU family
+ */
+enum mpc83xx_cpu_family {
+ FAMILY_830X,
+ FAMILY_831X,
+ FAMILY_832X,
+ FAMILY_834X,
+ FAMILY_836X,
+ FAMILY_837X,
+ FAMILY_UNKNOWN,
+};
+
+/**
+ * enum mpc83xx_cpu_type - Identifiers for MPC83xx CPU types
+ * @TYPE_8308: Identifier for the MPC8308 CPU type
+ * @TYPE_8309: Identifier for the MPC8309 CPU type
+ * @TYPE_8311: Identifier for the MPC8311 CPU type
+ * @TYPE_8313: Identifier for the MPC8313 CPU type
+ * @TYPE_8314: Identifier for the MPC8314 CPU type
+ * @TYPE_8315: Identifier for the MPC8315 CPU type
+ * @TYPE_8321: Identifier for the MPC8321 CPU type
+ * @TYPE_8323: Identifier for the MPC8323 CPU type
+ * @TYPE_8343: Identifier for the MPC8343 CPU type
+ * @TYPE_8347_TBGA: Identifier for the MPC8347 CPU type (Tape Ball Grid Array
+ * version)
+ * @TYPE_8347_PBGA: Identifier for the MPC8347 CPU type (Plastic Ball Grid Array
+ * version)
+ * @TYPE_8349: Identifier for the MPC8349 CPU type
+ * @TYPE_8358_TBGA: Identifier for the MPC8358 CPU type (Tape Ball Grid Array
+ * version)
+ * @TYPE_8358_PBGA: Identifier for the MPC8358 CPU type (Plastic Ball Grid Array
+ * version)
+ * @TYPE_8360: Identifier for the MPC8360 CPU type
+ * @TYPE_8377: Identifier for the MPC8377 CPU type
+ * @TYPE_8378: Identifier for the MPC8378 CPU type
+ * @TYPE_8379: Identifier for the MPC8379 CPU type
+ * @TYPE_UNKNOWN: Identifier for an unknown MPC83xx CPU type
+ */
+enum mpc83xx_cpu_type {
+ TYPE_8308,
+ TYPE_8309,
+ TYPE_8311,
+ TYPE_8313,
+ TYPE_8314,
+ TYPE_8315,
+ TYPE_8321,
+ TYPE_8323,
+ TYPE_8343,
+ TYPE_8347_TBGA,
+ TYPE_8347_PBGA,
+ TYPE_8349,
+ TYPE_8358_TBGA,
+ TYPE_8358_PBGA,
+ TYPE_8360,
+ TYPE_8377,
+ TYPE_8378,
+ TYPE_8379,
+ TYPE_UNKNOWN,
+};
+
+/* Array mapping the MCP83xx CPUs to their human-readable names */
+static const char * const cpu_type_names[] = {
+ [TYPE_8308] = "8308",
+ [TYPE_8309] = "8309",
+ [TYPE_8311] = "8311",
+ [TYPE_8313] = "8313",
+ [TYPE_8314] = "8314",
+ [TYPE_8315] = "8315",
+ [TYPE_8321] = "8321",
+ [TYPE_8323] = "8323",
+ [TYPE_8343] = "8343",
+ [TYPE_8347_TBGA] = "8347_TBGA",
+ [TYPE_8347_PBGA] = "8347_PBGA",
+ [TYPE_8349] = "8349",
+ [TYPE_8358_TBGA] = "8358_TBGA",
+ [TYPE_8358_PBGA] = "8358_PBGA",
+ [TYPE_8360] = "8360",
+ [TYPE_8377] = "8377",
+ [TYPE_8378] = "8378",
+ [TYPE_8379] = "8379",
+ [TYPE_UNKNOWN] = "Unknown CPU",
+};
+
+#endif /* !_MPC83XX_CPU_H_ */
diff --git a/roms/u-boot/drivers/cpu/riscv_cpu.c b/roms/u-boot/drivers/cpu/riscv_cpu.c
new file mode 100644
index 000000000..b30dceba3
--- /dev/null
+++ b/roms/u-boot/drivers/cpu/riscv_cpu.c
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+ * Copyright (C) 2020, Sean Anderson <seanga2@gmail.com>
+ */
+
+#include <clk.h>
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <errno.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int riscv_cpu_get_desc(const struct udevice *dev, char *buf, int size)
+{
+ const char *isa;
+
+ isa = dev_read_string(dev, "riscv,isa");
+ if (size < (strlen(isa) + 1))
+ return -ENOSPC;
+
+ strcpy(buf, isa);
+
+ return 0;
+}
+
+static int riscv_cpu_get_info(const struct udevice *dev, struct cpu_info *info)
+{
+ int ret;
+ struct clk clk;
+ const char *mmu;
+ u32 i_cache_size;
+ u32 d_cache_size;
+
+ /* First try getting the frequency from the assigned clock */
+ ret = clk_get_by_index((struct udevice *)dev, 0, &clk);
+ if (!ret) {
+ ret = clk_get_rate(&clk);
+ if (!IS_ERR_VALUE(ret))
+ info->cpu_freq = ret;
+ clk_free(&clk);
+ }
+
+ if (!info->cpu_freq)
+ dev_read_u32(dev, "clock-frequency", (u32 *)&info->cpu_freq);
+
+ mmu = dev_read_string(dev, "mmu-type");
+ if (mmu)
+ info->features |= BIT(CPU_FEAT_MMU);
+
+ /* check if I cache is present */
+ ret = dev_read_u32(dev, "i-cache-size", &i_cache_size);
+ if (ret)
+ /* if not found check if d-cache is present */
+ ret = dev_read_u32(dev, "d-cache-size", &d_cache_size);
+
+ /* if either I or D cache is present set L1 cache feature */
+ if (!ret)
+ info->features |= BIT(CPU_FEAT_L1_CACHE);
+
+ return 0;
+}
+
+static int riscv_cpu_get_count(const struct udevice *dev)
+{
+ ofnode node;
+ int num = 0;
+
+ ofnode_for_each_subnode(node, dev_ofnode(dev->parent)) {
+ const char *device_type;
+
+ /* skip if hart is marked as not available in the device tree */
+ if (!ofnode_is_available(node))
+ continue;
+
+ device_type = ofnode_read_string(node, "device_type");
+ if (!device_type)
+ continue;
+ if (strcmp(device_type, "cpu") == 0)
+ num++;
+ }
+
+ return num;
+}
+
+static int riscv_cpu_bind(struct udevice *dev)
+{
+ struct cpu_plat *plat = dev_get_parent_plat(dev);
+ struct driver *drv;
+ int ret;
+
+ /* save the hart id */
+ plat->cpu_id = dev_read_addr(dev);
+ /* first examine the property in current cpu node */
+ ret = dev_read_u32(dev, "timebase-frequency", &plat->timebase_freq);
+ /* if not found, then look at the parent /cpus node */
+ if (ret)
+ dev_read_u32(dev->parent, "timebase-frequency",
+ &plat->timebase_freq);
+
+ /*
+ * Bind riscv-timer driver on boot hart.
+ *
+ * We only instantiate one timer device which is enough for U-Boot.
+ * Pass the "timebase-frequency" value as the driver data for the
+ * timer device.
+ *
+ * Return value is not checked since it's possible that the timer
+ * driver is not included.
+ */
+ if (plat->cpu_id == gd->arch.boot_hart && plat->timebase_freq) {
+ drv = lists_driver_lookup_name("riscv_timer");
+ if (!drv) {
+ debug("Cannot find the timer driver, not included?\n");
+ return 0;
+ }
+
+ device_bind_with_driver_data(dev, drv, "riscv_timer",
+ plat->timebase_freq, ofnode_null(),
+ NULL);
+ }
+
+ return 0;
+}
+
+static int riscv_cpu_probe(struct udevice *dev)
+{
+ int ret = 0;
+ struct clk clk;
+
+ /* Get a clock if it exists */
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (ret)
+ return 0;
+
+ ret = clk_enable(&clk);
+ clk_free(&clk);
+ if (ret == -ENOSYS || ret == -ENOTSUPP)
+ return 0;
+ else
+ return ret;
+}
+
+static const struct cpu_ops riscv_cpu_ops = {
+ .get_desc = riscv_cpu_get_desc,
+ .get_info = riscv_cpu_get_info,
+ .get_count = riscv_cpu_get_count,
+};
+
+static const struct udevice_id riscv_cpu_ids[] = {
+ { .compatible = "riscv" },
+ { }
+};
+
+U_BOOT_DRIVER(riscv_cpu) = {
+ .name = "riscv_cpu",
+ .id = UCLASS_CPU,
+ .of_match = riscv_cpu_ids,
+ .bind = riscv_cpu_bind,
+ .probe = riscv_cpu_probe,
+ .ops = &riscv_cpu_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};