diff options
Diffstat (limited to 'roms/u-boot/drivers/cpu')
-rw-r--r-- | roms/u-boot/drivers/cpu/Kconfig | 21 | ||||
-rw-r--r-- | roms/u-boot/drivers/cpu/Makefile | 14 | ||||
-rw-r--r-- | roms/u-boot/drivers/cpu/at91_cpu.c | 123 | ||||
-rw-r--r-- | roms/u-boot/drivers/cpu/bmips_cpu.c | 522 | ||||
-rw-r--r-- | roms/u-boot/drivers/cpu/cpu-uclass.c | 142 | ||||
-rw-r--r-- | roms/u-boot/drivers/cpu/cpu_sandbox.c | 96 | ||||
-rw-r--r-- | roms/u-boot/drivers/cpu/imx8_cpu.c | 236 | ||||
-rw-r--r-- | roms/u-boot/drivers/cpu/mpc83xx_cpu.c | 354 | ||||
-rw-r--r-- | roms/u-boot/drivers/cpu/mpc83xx_cpu.h | 126 | ||||
-rw-r--r-- | roms/u-boot/drivers/cpu/riscv_cpu.c | 170 |
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, +}; |