GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
@@ -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.
@@ -0,0 +1,13 @@
# 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_CPU_MPC83XX) += mpc83xx_cpu.o
obj-$(CONFIG_CPU_RISCV) += riscv_cpu.o
obj-$(CONFIG_SANDBOX) += cpu_sandbox.o
@@ -0,0 +1,520 @@
// 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 <asm/io.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(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(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(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(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_platdata *plat = dev_get_parent_platdata(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_alloc_size = 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
@@ -0,0 +1,104 @@
// 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 <dm/lists.h>
#include <dm/root.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_get_desc(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(struct udevice *dev, struct cpu_info *info)
{
struct cpu_ops *ops = cpu_get_ops(dev);
if (!ops->get_info)
return -ENOSYS;
return ops->get_info(dev, info);
}
int cpu_get_count(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(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_platdata_auto_alloc_size = sizeof(struct cpu_platdata),
};
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,
};
@@ -0,0 +1,61 @@
// 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>
int cpu_sandbox_get_desc(struct udevice *dev, char *buf, int size)
{
snprintf(buf, size, "LEG Inc. SuperMegaUltraTurbo CPU No. 1");
return 0;
}
int cpu_sandbox_get_info(struct udevice *dev, struct cpu_info *info)
{
info->cpu_freq = 42 * 42 * 42 * 42 * 42;
info->features = 0x42424242;
return 0;
}
int cpu_sandbox_get_count(struct udevice *dev)
{
return 42;
}
int cpu_sandbox_get_vendor(struct udevice *dev, char *buf, int size)
{
snprintf(buf, size, "Languid Example Garbage Inc.");
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,
};
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,
.probe = cpu_sandbox_probe,
};
@@ -0,0 +1,182 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2019 NXP
*/
#include <common.h>
#include <cpu.h>
#include <dm.h>
#include <thermal.h>
#include <asm/arch/sci/sci.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch-imx/cpu.h>
#include <asm/armv8/cpu.h>
DECLARE_GLOBAL_DATA_PTR;
struct cpu_imx_platdata {
const char *name;
const char *rev;
const char *type;
u32 cpurev;
u32 freq_mhz;
};
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";
default:
return "?";
}
}
const char *get_core_name(void)
{
if (is_cortex_a35())
return "A35";
else if (is_cortex_a53())
return "A53";
else if (is_cortex_a72())
return "A72";
else
return "?";
}
#if IS_ENABLED(CONFIG_IMX_SCU_THERMAL)
static int cpu_imx_get_temp(void)
{
struct udevice *thermal_dev;
int cpu_tmp, ret;
ret = uclass_get_device_by_name(UCLASS_THERMAL, "cpu-thermal0",
&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(void)
{
return 0;
}
#endif
int cpu_imx_get_desc(struct udevice *dev, char *buf, int size)
{
struct cpu_imx_platdata *plat = dev_get_platdata(dev);
int ret;
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)) {
buf = buf + ret;
size = size - ret;
ret = snprintf(buf, size, " at %dC", cpu_imx_get_temp());
}
snprintf(buf + ret, size - ret, "\n");
return 0;
}
static int cpu_imx_get_info(struct udevice *dev, struct cpu_info *info)
{
struct cpu_imx_platdata *plat = dev_get_platdata(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(struct udevice *dev)
{
return 4;
}
static int cpu_imx_get_vendor(struct udevice *dev, char *buf, int size)
{
snprintf(buf, size, "NXP");
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,
};
static const struct udevice_id cpu_imx8_ids[] = {
{ .compatible = "arm,cortex-a35" },
{ .compatible = "arm,cortex-a53" },
{ }
};
static ulong imx8_get_cpu_rate(void)
{
ulong rate;
int ret;
int type = is_cortex_a35() ? SC_R_A35 : is_cortex_a53() ?
SC_R_A53 : SC_R_A72;
ret = sc_pm_get_clock_rate(-1, type, 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_platdata *plat = dev_get_platdata(dev);
u32 cpurev;
cpurev = get_cpu_rev();
plat->cpurev = cpurev;
plat->name = get_core_name();
plat->rev = get_imx8_rev(cpurev & 0xFFF);
plat->type = get_imx8_type((cpurev & 0xFF000) >> 12);
plat->freq_mhz = imx8_get_cpu_rate() / 1000000;
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,
.platdata_auto_alloc_size = sizeof(struct cpu_imx_platdata),
.flags = DM_FLAG_PRE_RELOC,
};
@@ -0,0 +1,350 @@
// 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 <vsprintf.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(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(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(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(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(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(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(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(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(struct udevice *dev, struct cpu_info *info)
{
struct clk clock;
int ret;
ulong freq;
ret = clk_get_by_index(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(struct udevice *dev)
{
/* We have one e300cX core */
return 1;
}
static int mpc83xx_cpu_get_vendor(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_alloc_size = sizeof(struct mpc83xx_cpu_priv),
.ops = &mpc83xx_cpu_ops,
.flags = DM_FLAG_PRE_RELOC,
};
@@ -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_ */
@@ -0,0 +1,121 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
*/
#include <common.h>
#include <cpu.h>
#include <dm.h>
#include <errno.h>
#include <dm/device-internal.h>
#include <dm/lists.h>
DECLARE_GLOBAL_DATA_PTR;
static int riscv_cpu_get_desc(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(struct udevice *dev, struct cpu_info *info)
{
const char *mmu;
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);
return 0;
}
static int riscv_cpu_get_count(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_platdata *plat = dev_get_parent_platdata(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 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,
.ops = &riscv_cpu_ops,
.flags = DM_FLAG_PRE_RELOC,
};