diff options
Diffstat (limited to 'drivers/cpu')
-rw-r--r-- | drivers/cpu/Kconfig | 6 | ||||
-rw-r--r-- | drivers/cpu/Makefile | 1 | ||||
-rw-r--r-- | drivers/cpu/at91_cpu.c | 1 | ||||
-rw-r--r-- | drivers/cpu/bmips_cpu.c | 1 | ||||
-rw-r--r-- | drivers/cpu/cpu-uclass.c | 11 | ||||
-rw-r--r-- | drivers/cpu/cpu_sandbox.c | 7 | ||||
-rw-r--r-- | drivers/cpu/imx8_cpu.c | 39 | ||||
-rw-r--r-- | drivers/cpu/microblaze_cpu.c | 1 | ||||
-rw-r--r-- | drivers/cpu/mpc83xx_cpu.c | 3 | ||||
-rw-r--r-- | drivers/cpu/riscv_cpu.c | 1 | ||||
-rw-r--r-- | drivers/cpu/xtensa_cpu.c | 117 |
11 files changed, 174 insertions, 14 deletions
diff --git a/drivers/cpu/Kconfig b/drivers/cpu/Kconfig index 1c3c810651e..5c06cd9f60e 100644 --- a/drivers/cpu/Kconfig +++ b/drivers/cpu/Kconfig @@ -33,3 +33,9 @@ config CPU_MICROBLAZE select XILINX_MICROBLAZE0_PVR help Support CPU cores for Microblaze architecture. + +config CPU_XTENSA + bool "Enable Xtensa CPU driver" + depends on CPU && XTENSA + help + Support CPU cores for Xtensa architecture. diff --git a/drivers/cpu/Makefile b/drivers/cpu/Makefile index d4bbf6fa5e0..bc75d9b974e 100644 --- a/drivers/cpu/Makefile +++ b/drivers/cpu/Makefile @@ -14,4 +14,5 @@ obj-$(CONFIG_CPU_IMX) += imx8_cpu.o obj-$(CONFIG_CPU_MPC83XX) += mpc83xx_cpu.o obj-$(CONFIG_CPU_RISCV) += riscv_cpu.o obj-$(CONFIG_CPU_MICROBLAZE) += microblaze_cpu.o +obj-$(CONFIG_CPU_XTENSA) += xtensa_cpu.o obj-$(CONFIG_SANDBOX) += cpu_sandbox.o diff --git a/drivers/cpu/at91_cpu.c b/drivers/cpu/at91_cpu.c index 34a3f61c7e9..b45cc6ca1a9 100644 --- a/drivers/cpu/at91_cpu.c +++ b/drivers/cpu/at91_cpu.c @@ -5,7 +5,6 @@ * Author: Claudiu Beznea <claudiu.beznea@microchip.com> */ -#include <common.h> #include <cpu.h> #include <dm.h> #include <div64.h> diff --git a/drivers/cpu/bmips_cpu.c b/drivers/cpu/bmips_cpu.c index 3dd04fa8858..db624ee47fb 100644 --- a/drivers/cpu/bmips_cpu.c +++ b/drivers/cpu/bmips_cpu.c @@ -7,7 +7,6 @@ * Copyright (C) 2009 Florian Fainelli <florian@openwrt.org> */ -#include <common.h> #include <cpu.h> #include <display_options.h> #include <dm.h> diff --git a/drivers/cpu/cpu-uclass.c b/drivers/cpu/cpu-uclass.c index 9772578968b..2c8e46c05e3 100644 --- a/drivers/cpu/cpu-uclass.c +++ b/drivers/cpu/cpu-uclass.c @@ -6,7 +6,6 @@ #define LOG_CATEGORY UCLASS_CPU -#include <common.h> #include <cpu.h> #include <dm.h> #include <errno.h> @@ -105,6 +104,16 @@ int cpu_get_vendor(const struct udevice *dev, char *buf, int size) return ops->get_vendor(dev, buf, size); } +int cpu_release_core(const struct udevice *dev, phys_addr_t addr) +{ + struct cpu_ops *ops = cpu_get_ops(dev); + + if (!ops->release_core) + return -ENOSYS; + + return ops->release_core(dev, addr); +} + U_BOOT_DRIVER(cpu_bus) = { .name = "cpu_bus", .id = UCLASS_SIMPLE_BUS, diff --git a/drivers/cpu/cpu_sandbox.c b/drivers/cpu/cpu_sandbox.c index 2e871fe313c..b1527957831 100644 --- a/drivers/cpu/cpu_sandbox.c +++ b/drivers/cpu/cpu_sandbox.c @@ -4,7 +4,6 @@ * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc */ -#include <common.h> #include <dm.h> #include <cpu.h> @@ -45,6 +44,11 @@ void cpu_sandbox_set_current(const char *name) cpu_current = name; } +static int cpu_sandbox_release_core(const struct udevice *dev, phys_addr_t addr) +{ + return 0; +} + static int cpu_sandbox_is_current(struct udevice *dev) { if (!strcmp(dev->name, cpu_current)) @@ -59,6 +63,7 @@ static const struct cpu_ops cpu_sandbox_ops = { .get_count = cpu_sandbox_get_count, .get_vendor = cpu_sandbox_get_vendor, .is_current = cpu_sandbox_is_current, + .release_core = cpu_sandbox_release_core, }; static int cpu_sandbox_bind(struct udevice *dev) diff --git a/drivers/cpu/imx8_cpu.c b/drivers/cpu/imx8_cpu.c index 98ff95f5ff5..60deca963a6 100644 --- a/drivers/cpu/imx8_cpu.c +++ b/drivers/cpu/imx8_cpu.c @@ -1,13 +1,13 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright 2019 NXP + * Copyright 2019, 2024 NXP */ -#include <common.h> #include <cpu.h> #include <dm.h> #include <thermal.h> #include <asm/global_data.h> +#include <asm/ptrace.h> #include <asm/system.h> #include <firmware/imx/sci/sci.h> #include <asm/arch/sys_proto.h> @@ -16,6 +16,7 @@ #include <imx_thermal.h> #include <linux/bitops.h> #include <linux/clk-provider.h> +#include <linux/psci.h> DECLARE_GLOBAL_DATA_PTR; @@ -32,6 +33,12 @@ struct cpu_imx_plat { static const char *get_imx_type_str(u32 imxtype) { switch (imxtype) { + case MXC_CPU_IMX8MM: + return "8MM"; + case MXC_CPU_IMX8MN: + return "8MN"; + case MXC_CPU_IMX8MP: + return "8MP"; case MXC_CPU_IMX8QXP: case MXC_CPU_IMX8QXP_A0: return "8QXP"; @@ -185,8 +192,6 @@ static int cpu_imx_get_desc(const struct udevice *dev, char *buf, int size) ret = snprintf(buf, size, " - invalid sensor data"); } - snprintf(buf + ret, size - ret, "\n"); - return 0; } @@ -194,7 +199,7 @@ 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->cpu_freq = plat->freq_mhz * 1000000; info->features = BIT(CPU_FEAT_L1_CACHE) | BIT(CPU_FEAT_MMU); return 0; } @@ -237,12 +242,34 @@ static int cpu_imx_is_current(struct udevice *dev) return 0; } +static int cpu_imx_release_core(const struct udevice *dev, phys_addr_t addr) +{ + struct cpu_imx_plat *plat = dev_get_plat(dev); + struct pt_regs regs; + + regs.regs[0] = PSCI_0_2_FN64_CPU_ON; + regs.regs[1] = plat->mpidr; + regs.regs[2] = addr; + regs.regs[3] = 0; + + smc_call(®s); + if (regs.regs[0]) { + printf("Failed to release CPU core (mpidr: 0x%x)\n", plat->mpidr); + return -1; + } + + printf("Released CPU core (mpidr: 0x%x) to address 0x%llx\n", plat->mpidr, addr); + + return 0; +} + static const struct cpu_ops cpu_imx_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, + .release_core = cpu_imx_release_core, }; static const struct udevice_id cpu_imx_ids[] = { @@ -288,7 +315,7 @@ static int imx_cpu_probe(struct udevice *dev) cpurev = get_cpu_rev(); plat->cpurev = cpurev; plat->rev = get_imx_rev_str(cpurev & 0xFFF); - plat->type = get_imx_type_str((cpurev & 0xFF000) >> 12); + plat->type = get_imx_type_str((cpurev & 0x1FF000) >> 12); plat->freq_mhz = imx_get_cpu_rate(dev) / 1000000; plat->mpidr = dev_read_addr(dev); if (plat->mpidr == FDT_ADDR_T_NONE) { diff --git a/drivers/cpu/microblaze_cpu.c b/drivers/cpu/microblaze_cpu.c index a229f6913b0..4e24ada4002 100644 --- a/drivers/cpu/microblaze_cpu.c +++ b/drivers/cpu/microblaze_cpu.c @@ -2,7 +2,6 @@ /* * Copyright (C) 2022, Ovidiu Panait <ovpanait@gmail.com> */ -#include <common.h> #include <cpu.h> #include <dm.h> #include <asm/cpuinfo.h> diff --git a/drivers/cpu/mpc83xx_cpu.c b/drivers/cpu/mpc83xx_cpu.c index e451c11116a..127d3c3af08 100644 --- a/drivers/cpu/mpc83xx_cpu.c +++ b/drivers/cpu/mpc83xx_cpu.c @@ -4,13 +4,12 @@ * 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 <stdio.h> #include <linux/bitops.h> #include "mpc83xx_cpu.h" diff --git a/drivers/cpu/riscv_cpu.c b/drivers/cpu/riscv_cpu.c index d39a943cb84..4fff4658b5f 100644 --- a/drivers/cpu/riscv_cpu.c +++ b/drivers/cpu/riscv_cpu.c @@ -5,7 +5,6 @@ */ #include <clk.h> -#include <common.h> #include <cpu.h> #include <dm.h> #include <errno.h> diff --git a/drivers/cpu/xtensa_cpu.c b/drivers/cpu/xtensa_cpu.c new file mode 100644 index 00000000000..fbb561dd612 --- /dev/null +++ b/drivers/cpu/xtensa_cpu.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2024 Jiaxun Yang <jiaxun.yang@flygoat.com> + */ + +#include <clk.h> +#include <cpu.h> +#include <dm.h> +#include <errno.h> +#include <linux/bitops.h> +#include <linux/err.h> + +#include <asm/arch/core.h> + +static int xtensa_cpu_get_desc(const struct udevice *dev, char *buf, int size) +{ + const char *cpu = XCHAL_CORE_ID; + + if (!cpu || size < (strlen(cpu) + 1)) + return -ENOSPC; + + strcpy(buf, cpu); + + return 0; +} + +static int xtensa_cpu_get_info(const struct udevice *dev, struct cpu_info *info) +{ + struct cpu_plat *plat = dev_get_parent_plat(dev); + + info->cpu_freq = plat->timebase_freq; + +#if XCHAL_HAVE_PTP_MMU + info->features |= BIT(CPU_FEAT_MMU); +#endif +#if XCHAL_ICACHE_SIZE || XCHAL_DCACHE_SIZE + info->features |= BIT(CPU_FEAT_L1_CACHE); +#endif + + return 0; +} + +static int xtensa_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_enabled(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 xtensa_cpu_bind(struct udevice *dev) +{ + struct cpu_plat *plat = dev_get_parent_plat(dev); + + plat->cpu_id = dev_read_addr(dev); + + return 0; +} + +static int xtensa_cpu_probe(struct udevice *dev) +{ + int ret = 0; + struct clk clk; + struct cpu_plat *plat = dev_get_parent_plat(dev); + + asm volatile ("rsr %0, 176\n" + "rsr %1, 208\n" + : "=r"(plat->id[0]), "=r"(plat->id[1])); + + /* Get a clock if it exists */ + ret = clk_get_by_index(dev, 0, &clk); + if (!ret) { + ret = clk_enable(&clk); + if (ret && (ret != -ENOSYS || ret != -ENOTSUPP)) + return ret; + ret = clk_get_rate(&clk); + if (!IS_ERR_VALUE(ret)) + plat->timebase_freq = ret; + } + + return 0; +} + +static const struct cpu_ops xtensa_cpu_ops = { + .get_desc = xtensa_cpu_get_desc, + .get_info = xtensa_cpu_get_info, + .get_count = xtensa_cpu_get_count, +}; + +static const struct udevice_id xtensa_cpu_ids[] = { + { .compatible = "cdns,xtensa-cpu" }, + { } +}; + +U_BOOT_DRIVER(xtensa_cpu) = { + .name = "xtensa_cpu", + .id = UCLASS_CPU, + .of_match = xtensa_cpu_ids, + .bind = xtensa_cpu_bind, + .probe = xtensa_cpu_probe, + .ops = &xtensa_cpu_ops, + .flags = DM_FLAG_PRE_RELOC, +}; |