summaryrefslogtreecommitdiff
path: root/drivers/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cpu')
-rw-r--r--drivers/cpu/cpu-uclass.c10
-rw-r--r--drivers/cpu/cpu_sandbox.c6
-rw-r--r--drivers/cpu/imx8_cpu.c38
3 files changed, 49 insertions, 5 deletions
diff --git a/drivers/cpu/cpu-uclass.c b/drivers/cpu/cpu-uclass.c
index 16f8f2e5219..2c8e46c05e3 100644
--- a/drivers/cpu/cpu-uclass.c
+++ b/drivers/cpu/cpu-uclass.c
@@ -104,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 e65e1bdc51b..b1527957831 100644
--- a/drivers/cpu/cpu_sandbox.c
+++ b/drivers/cpu/cpu_sandbox.c
@@ -44,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))
@@ -58,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 4781a565547..60deca963a6 100644
--- a/drivers/cpu/imx8_cpu.c
+++ b/drivers/cpu/imx8_cpu.c
@@ -1,12 +1,13 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * Copyright 2019 NXP
+ * Copyright 2019, 2024 NXP
*/
#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>
@@ -15,6 +16,7 @@
#include <imx_thermal.h>
#include <linux/bitops.h>
#include <linux/clk-provider.h>
+#include <linux/psci.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -31,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";
@@ -184,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;
}
@@ -193,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;
}
@@ -236,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(&regs);
+ 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[] = {
@@ -287,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) {