[PATCHv1 0/5] Add a subcommand 'release' to cmd/cpu.c

From: Hou Zhiqiang Zhiqiang.Hou@nxp.com
This patch set is to add a subcommand 'release' to the 'cpu' command in cmd/cpu.c, making the command is able to release a core to run baremetal and RTOS applications.
And enabled the 'cpu' command and imx CPU driver for i.MX 8M series EVK boards and i.MX 93 EVK board.
Hou Zhiqiang (5): cpu: add release_core callback cpu: imx: implement release_core callback cmd: cpu: add release subcommand configs: imx8m: enable the 'cpu' command configs: imx93: enable the 'cpu' command
cmd/cpu.c | 44 +++++++++++++++++++++++++++++-- configs/imx8mm_evk_defconfig | 3 +++ configs/imx8mn_evk_defconfig | 3 +++ configs/imx8mp_evk_defconfig | 3 +++ configs/imx93_11x11_evk_defconfig | 1 + drivers/cpu/cpu-uclass.c | 10 +++++++ drivers/cpu/imx8_cpu.c | 26 +++++++++++++++++- include/cpu.h | 15 +++++++++++ 8 files changed, 102 insertions(+), 3 deletions(-)

From: Hou Zhiqiang Zhiqiang.Hou@nxp.com
Add a new callback release_core to the cpu_ops, which is used to release a CPU core to run baremetal or RTOS application on a SoC with multiple CPU cores.
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com --- drivers/cpu/cpu-uclass.c | 10 ++++++++++ include/cpu.h | 15 +++++++++++++++ 2 files changed, 25 insertions(+)
diff --git a/drivers/cpu/cpu-uclass.c b/drivers/cpu/cpu-uclass.c index 16f8f2e521..2c8e46c05e 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/include/cpu.h b/include/cpu.h index 2077ff3063..0018910d61 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -102,6 +102,15 @@ struct cpu_ops { * if not. */ int (*is_current)(struct udevice *dev); + + /** + * release_core() - Relase a CPU core to the given address to run application + * + * @dev: Device to check (UCLASS_CPU) + * @addr: Address to relese the CPU core + * @return 0 if OK, -ve on error + */ + int (*release_core)(const struct udevice *dev, phys_addr_t addr); };
#define cpu_get_ops(dev) ((struct cpu_ops *)(dev)->driver->ops) @@ -164,4 +173,10 @@ int cpu_is_current(struct udevice *cpu); */ struct udevice *cpu_get_current_dev(void);
+/** + * cpu_release_core() - Relase a CPU core to the given address to run application + * + * @return 0 if OK, -ve on error + */ +int cpu_release_core(const struct udevice *dev, phys_addr_t addr); #endif

Hi Zhiqiang,
On Tue, 23 Jul 2024 at 08:43, Zhiqiang Hou Zhiqiang.Hou@nxp.com wrote:
From: Hou Zhiqiang Zhiqiang.Hou@nxp.com
Add a new callback release_core to the cpu_ops, which is used to release a CPU core to run baremetal or RTOS application on a SoC with multiple CPU cores.
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com
drivers/cpu/cpu-uclass.c | 10 ++++++++++ include/cpu.h | 15 +++++++++++++++ 2 files changed, 25 insertions(+)
diff --git a/drivers/cpu/cpu-uclass.c b/drivers/cpu/cpu-uclass.c index 16f8f2e521..2c8e46c05e 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/include/cpu.h b/include/cpu.h index 2077ff3063..0018910d61 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -102,6 +102,15 @@ struct cpu_ops { * if not. */ int (*is_current)(struct udevice *dev);
/**
* release_core() - Relase a CPU core to the given address to run application
*
* @dev: Device to check (UCLASS_CPU)
* @addr: Address to relese the CPU core
* @return 0 if OK, -ve on error
*/
int (*release_core)(const struct udevice *dev, phys_addr_t addr);
};
#define cpu_get_ops(dev) ((struct cpu_ops *)(dev)->driver->ops) @@ -164,4 +173,10 @@ int cpu_is_current(struct udevice *cpu); */ struct udevice *cpu_get_current_dev(void);
+/**
- cpu_release_core() - Relase a CPU core to the given address to run application
- @return 0 if OK, -ve on error
- */
+int cpu_release_core(const struct udevice *dev, phys_addr_t addr);
#endif
2.17.1
Please also add a test for this callback to test/dm/cpu.c
Regards, Simon

Hi Simon,
-----Original Message----- From: Simon Glass sjg@chromium.org Sent: Wednesday, July 24, 2024 10:37 PM To: Z.Q. Hou zhiqiang.hou@nxp.com Cc: u-boot@lists.denx.de; trini@konsulko.com; Peng Fan peng.fan@nxp.com; festevam@gmail.com Subject: Re: [PATCHv1 1/5] cpu: add release_core callback
Hi Zhiqiang,
On Tue, 23 Jul 2024 at 08:43, Zhiqiang Hou Zhiqiang.Hou@nxp.com wrote:
From: Hou Zhiqiang Zhiqiang.Hou@nxp.com
Add a new callback release_core to the cpu_ops, which is used to release a CPU core to run baremetal or RTOS application on a SoC with multiple CPU cores.
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com
drivers/cpu/cpu-uclass.c | 10 ++++++++++ include/cpu.h | 15 +++++++++++++++ 2 files changed, 25 insertions(+)
diff --git a/drivers/cpu/cpu-uclass.c b/drivers/cpu/cpu-uclass.c index 16f8f2e521..2c8e46c05e 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/include/cpu.h b/include/cpu.h index 2077ff3063..0018910d61 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -102,6 +102,15 @@ struct cpu_ops { * if not. */ int (*is_current)(struct udevice *dev);
/**
* release_core() - Relase a CPU core to the given address to run
application
*
* @dev: Device to check (UCLASS_CPU)
* @addr: Address to relese the CPU core
* @return 0 if OK, -ve on error
*/
int (*release_core)(const struct udevice *dev, phys_addr_t
- addr);
};
#define cpu_get_ops(dev) ((struct cpu_ops *)(dev)->driver->ops) @@ -164,4 +173,10 @@ int cpu_is_current(struct udevice *cpu); */ struct udevice *cpu_get_current_dev(void);
+/**
- cpu_release_core() - Relase a CPU core to the given address to run
+application
- @return 0 if OK, -ve on error
- */
+int cpu_release_core(const struct udevice *dev, phys_addr_t addr);
#endif
2.17.1
Please also add a test for this callback to test/dm/cpu.c
will add. Thanks!
- Zhiqiang

From: Hou Zhiqiang Zhiqiang.Hou@nxp.com
Release the secondary cores through the PSCI request.
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com --- drivers/cpu/imx8_cpu.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/drivers/cpu/imx8_cpu.c b/drivers/cpu/imx8_cpu.c index 4781a56554..5942a28be4 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;
@@ -236,12 +238,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[] = {

From: Hou Zhiqiang Zhiqiang.Hou@nxp.com
Add a new subcommand 'release' to bring up a core to run baremetal and RTOS applications.
For example on i.MX8M Plus EVK, release the LAST core to run a RTOS application, passing the sequence number of the CPU core to release, here it is 3: u-boot=> cpu list 0: cpu@0 NXP i.MX?? Rev1.1 A53 at 4154504685 MHz at 31C
1: cpu@1 NXP i.MX?? Rev1.1 A53 at 4154504685 MHz at 30C
2: cpu@2 NXP i.MX?? Rev1.1 A53 at 4154504685 MHz at 31C
3: cpu@3 NXP i.MX?? Rev1.1 A53 at 4154504685 MHz at 31C
u-boot=> load mmc 1:2 C0000000 /hello_world.bin 66008 bytes read in 5 ms (12.6 MiB/s) u-boot=> dcache flush; icache flush u-boot=> cpu release 3 C0000000 Released CPU core (mpidr: 0x3) to address 0xc0000000
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com --- cmd/cpu.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-)
diff --git a/cmd/cpu.c b/cmd/cpu.c index 9e323069b9..2755250756 100644 --- a/cmd/cpu.c +++ b/cmd/cpu.c @@ -3,6 +3,7 @@ * Copyright (c) 2015 Google, Inc * Written by Simon Glass sjg@chromium.org * Copyright (c) 2017 Álvaro Fernández Rojas noltari@gmail.com + * Copyright 2024 NXP */
#include <command.h> @@ -18,6 +19,19 @@ static const char *cpu_feature_name[CPU_FEAT_COUNT] = { "Device ID", };
+static struct udevice *cpu_find_device(unsigned long cpu_id) +{ + struct udevice *dev; + + for (uclass_first_device(UCLASS_CPU, &dev); dev; + uclass_next_device(&dev)) { + if (cpu_id == dev_seq(dev)) + return dev; + } + + return NULL; +} + static int print_cpu_list(bool detail) { struct udevice *dev; @@ -82,10 +96,36 @@ static int do_cpu_detail(struct cmd_tbl *cmdtp, int flag, int argc, return 0; }
+static int do_cpu_release(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct udevice *dev; + unsigned long cpu_id; + unsigned long long boot_addr; + + if (argc != 3) + return CMD_RET_USAGE; + + cpu_id = dectoul(argv[1], NULL); + dev = cpu_find_device(cpu_id); + if (!dev) + return CMD_RET_FAILURE; + + boot_addr = simple_strtoull(argv[2], NULL, 16); + + if (cpu_release_core(dev, boot_addr)) + return CMD_RET_FAILURE; + + return 0; +} + U_BOOT_LONGHELP(cpu, "list - list available CPUs\n" - "cpu detail - show CPU detail"); + "cpu detail - show CPU detail\n" + "cpu release <core ID> <addr> - Release CPU <core ID> at <addr>\n" + " <core ID>: the sequence number in list subcommand outputs");
U_BOOT_CMD_WITH_SUBCMDS(cpu, "display information about CPUs", cpu_help_text, U_BOOT_SUBCMD_MKENT(list, 1, 1, do_cpu_list), - U_BOOT_SUBCMD_MKENT(detail, 1, 0, do_cpu_detail)); + U_BOOT_SUBCMD_MKENT(detail, 1, 0, do_cpu_detail), + U_BOOT_SUBCMD_MKENT(release, 3, 0, do_cpu_release));

On Tue, Jul 23, 2024 at 11:43 AM Zhiqiang Hou Zhiqiang.Hou@nxp.com wrote:
From: Hou Zhiqiang Zhiqiang.Hou@nxp.com
Add a new subcommand 'release' to bring up a core to run baremetal and RTOS applications.
For example on i.MX8M Plus EVK, release the LAST core to run a RTOS application, passing the sequence number of the CPU core to release, here it is 3: u-boot=> cpu list 0: cpu@0 NXP i.MX?? Rev1.1 A53 at 4154504685 MHz at 31C
What is this ?? and this super high frequency?

Hi Fabio,
-----Original Message----- From: Fabio Estevam festevam@gmail.com Sent: Tuesday, July 23, 2024 10:51 PM To: Z.Q. Hou zhiqiang.hou@nxp.com Cc: u-boot@lists.denx.de; trini@konsulko.com; Peng Fan peng.fan@nxp.com; sjg@chromium.org Subject: Re: [PATCHv1 3/5] cmd: cpu: add release subcommand
On Tue, Jul 23, 2024 at 11:43 AM Zhiqiang Hou Zhiqiang.Hou@nxp.com wrote:
From: Hou Zhiqiang Zhiqiang.Hou@nxp.com
Add a new subcommand 'release' to bring up a core to run baremetal and RTOS applications.
For example on i.MX8M Plus EVK, release the LAST core to run a RTOS application, passing the sequence number of the CPU core to release, here it is 3: u-boot=> cpu list 0: cpu@0 NXP i.MX?? Rev1.1 A53 at 4154504685 MHz at
31C
What is this ?? and this super high frequency?
The i.MX8M Plus name isn't added to the imx8_cpu.c, will add the i.MX8M series names.
Thanks, Zhiqiang

Hi Zhiqiang,
On Tue, Jul 23, 2024 at 10:02 PM Z.Q. Hou zhiqiang.hou@nxp.com wrote:
The i.MX8M Plus name isn't added to the imx8_cpu.c, will add the i.MX8M series names.
Ok, thanks. Please also fix the CPU frequency.

Hi Fabio,
-----Original Message----- From: Fabio Estevam festevam@gmail.com Sent: Wednesday, July 24, 2024 9:38 AM To: Z.Q. Hou zhiqiang.hou@nxp.com Cc: u-boot@lists.denx.de; trini@konsulko.com; Peng Fan peng.fan@nxp.com; sjg@chromium.org Subject: Re: [PATCHv1 3/5] cmd: cpu: add release subcommand
Hi Zhiqiang,
On Tue, Jul 23, 2024 at 10:02 PM Z.Q. Hou zhiqiang.hou@nxp.com wrote:
The i.MX8M Plus name isn't added to the imx8_cpu.c, will add the i.MX8M
series names.
Ok, thanks. Please also fix the CPU frequency.
Yes, the CPU frequency is not correct, will have a look. Thanks!
- Zhiqiang

From: Hou Zhiqiang Zhiqiang.Hou@nxp.com
Enable the 'cpu' command and the depended imx CPU driver to display the CPU info and release CPU core to run baremetal or RTOS applications.
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com --- configs/imx8mm_evk_defconfig | 3 +++ configs/imx8mn_evk_defconfig | 3 +++ configs/imx8mp_evk_defconfig | 3 +++ 3 files changed, 9 insertions(+)
diff --git a/configs/imx8mm_evk_defconfig b/configs/imx8mm_evk_defconfig index ff33d1532a..8b04586f86 100644 --- a/configs/imx8mm_evk_defconfig +++ b/configs/imx8mm_evk_defconfig @@ -118,3 +118,6 @@ CONFIG_SDP_LOADADDR=0x40400000 CONFIG_USB_GADGET_DOWNLOAD=y CONFIG_SPL_USB_SDP_SUPPORT=y CONFIG_IMX_WATCHDOG=y +CONFIG_CPU=y +CONFIG_CPU_IMX=y +CONFIG_CMD_CPU=y diff --git a/configs/imx8mn_evk_defconfig b/configs/imx8mn_evk_defconfig index 2402e9e8bf..ee7a5e9088 100644 --- a/configs/imx8mn_evk_defconfig +++ b/configs/imx8mn_evk_defconfig @@ -105,3 +105,6 @@ CONFIG_SYSRESET_PSCI=y CONFIG_SYSRESET_WATCHDOG=y CONFIG_DM_THERMAL=y CONFIG_IMX_WATCHDOG=y +CONFIG_CPU=y +CONFIG_CPU_IMX=y +CONFIG_CMD_CPU=y diff --git a/configs/imx8mp_evk_defconfig b/configs/imx8mp_evk_defconfig index f5ba022b07..3176069991 100644 --- a/configs/imx8mp_evk_defconfig +++ b/configs/imx8mp_evk_defconfig @@ -137,3 +137,6 @@ CONFIG_USB_GADGET_MANUFACTURER="FSL" CONFIG_USB_GADGET_VENDOR_NUM=0x0525 CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5 CONFIG_IMX_WATCHDOG=y +CONFIG_CPU=y +CONFIG_CPU_IMX=y +CONFIG_CMD_CPU=y

From: Hou Zhiqiang Zhiqiang.Hou@nxp.com
Enable the 'cpu' command to display the CPU info and release CPU core to run baremetal or RTOS applications.
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com --- configs/imx93_11x11_evk_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/configs/imx93_11x11_evk_defconfig b/configs/imx93_11x11_evk_defconfig index 2246715d82..93ab0b9aa3 100644 --- a/configs/imx93_11x11_evk_defconfig +++ b/configs/imx93_11x11_evk_defconfig @@ -52,6 +52,7 @@ CONFIG_CMD_ERASEENV=y # CONFIG_CMD_CRC32 is not set CONFIG_CMD_MEMTEST=y CONFIG_CMD_CLK=y +CONFIG_CMD_CPU=y CONFIG_CMD_DFU=y CONFIG_CMD_FUSE=y CONFIG_CMD_GPIO=y
participants (4)
-
Fabio Estevam
-
Simon Glass
-
Z.Q. Hou
-
Zhiqiang Hou