[PATCH 10/11] cmd: riscv: Add 'startharts' command to start multiple harts
Uros Stajic
uros.stajic at htecgroup.com
Tue Jun 3 15:41:08 CEST 2025
From: Chao-ying Fu <cfu at mips.com>
Introduce the 'startharts' command for RISC-V targets, which prints
or executes commands to power up and reset all harts and jump to
0x80000000. The command supports optional cluster/core count and
immediate execution via the 'g' argument.
Signed-off-by: Chao-ying Fu <cfu at mips.com>
Signed-off-by: Uros Stajic <uros.stajic at htecgroup.com>
---
arch/riscv/include/asm/arch-p8700/p8700.h | 3 +
board/mips/boston-riscv/MAINTAINERS | 1 +
cmd/Kconfig | 6 ++
cmd/Makefile | 1 +
cmd/start_harts.c | 103 ++++++++++++++++++++++
configs/boston-p8700_defconfig | 1 +
6 files changed, 115 insertions(+)
create mode 100644 cmd/start_harts.c
diff --git a/arch/riscv/include/asm/arch-p8700/p8700.h b/arch/riscv/include/asm/arch-p8700/p8700.h
index 6c47de9a633..20868eee419 100644
--- a/arch/riscv/include/asm/arch-p8700/p8700.h
+++ b/arch/riscv/include/asm/arch-p8700/p8700.h
@@ -77,8 +77,11 @@
#define CPC_SYS_CONFIG 0x0140
#define CPC_Cx_CMD 0x0000
+#define CPC_Cx_CMD_PWRUP 0x3
#define CPC_Cx_CMD_RESET 0x4
+#define CPC_Cx_VP_RUN 0x0028
+
/* GCR_CONFIG */
#define GCR_CONFIG 0x0000
#define GCR_REV 0x0030
diff --git a/board/mips/boston-riscv/MAINTAINERS b/board/mips/boston-riscv/MAINTAINERS
index b04dcde943a..0e2f4c277d3 100644
--- a/board/mips/boston-riscv/MAINTAINERS
+++ b/board/mips/boston-riscv/MAINTAINERS
@@ -12,3 +12,4 @@ F: arch/riscv/lib/mips_gic.c
F: cmd/display.c
F: include/led-display.h
F: doc/README.LED_display
+F: cmd/start_harts.c
diff --git a/cmd/Kconfig b/cmd/Kconfig
index e40fbded3e3..eda2e5b8306 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2321,6 +2321,12 @@ config CMD_DISPLAY
displayed on a simple board-specific display. Implement
display_putc() to use it.
+config CMD_START_HARTS
+ bool "Start harts"
+ depends on RISCV
+ help
+ This prints commands to start all harts and go 0x80000000.
+
config CMD_EFIDEBUG
bool "efidebug - display/configure UEFI environment"
depends on EFI_LOADER
diff --git a/cmd/Makefile b/cmd/Makefile
index e1ce7bbaff9..e3d7e944715 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -59,6 +59,7 @@ obj-$(CONFIG_CMD_SOUND) += sound.o
ifdef CONFIG_POST
obj-$(CONFIG_CMD_DIAG) += diag.o
endif
+obj-$(CONFIG_CMD_START_HARTS) += start_harts.o
obj-$(CONFIG_CMD_DISPLAY) += display.o
obj-$(CONFIG_CMD_ADTIMG) += adtimg.o
obj-$(CONFIG_CMD_ABOOTIMG) += abootimg.o
diff --git a/cmd/start_harts.c b/cmd/start_harts.c
new file mode 100644
index 00000000000..0d074778b6d
--- /dev/null
+++ b/cmd/start_harts.c
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2005
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ */
+
+#include <command.h>
+#include <asm/arch-p8700/p8700.h>
+
+int start_harts(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
+{
+ int n_cluster = 1;
+ int n_core = 1;
+ int run = 0;
+ int cl, co;
+ long cmd_reg;
+
+ if (argc > 1 && argv[1][0] > '0' && argv[1][0] <= '9')
+ n_cluster = argv[1][0] - '0';
+ if (argc > 2 && argv[2][0] > '0' && argv[2][0] <= '9')
+ n_core = argv[2][0] - '0';
+ if (argc > 3)
+ run = (argv[3][0] == 'g');
+
+ for (cl = 1; cl < n_cluster; cl++) {
+ cmd_reg = CPC_BASE + (cl << CM_BASE_CLUSTER_SHIFT) +
+ CPC_OFF_LOCAL + CPC_Cx_CMD;
+ printf("# Start cluster %d core 0 hart 0\n", cl);
+ printf("mw.q 0x%lx %d\n", cmd_reg, CPC_Cx_CMD_PWRUP);
+ if (run == 1) {
+ asm volatile("sd %0, 0(%1)"::"r"(CPC_Cx_CMD_PWRUP), "r"(cmd_reg));
+ asm volatile("fence");
+ }
+
+ printf("mw.q 0x%lx %d\n", cmd_reg, CPC_Cx_CMD_RESET);
+ if (run == 1) {
+ asm volatile("sd %0, 0(%1)"::"r"(CPC_Cx_CMD_RESET), "r"(cmd_reg));
+ asm volatile("fence");
+ }
+
+ cmd_reg = CPC_BASE + (cl << CM_BASE_CLUSTER_SHIFT) + CPC_OFF_LOCAL + CPC_Cx_VP_RUN;
+ printf("mw.q 0x%lx 1\n", cmd_reg);
+
+ if (run == 1) {
+ asm volatile("sd %0, 0(%1)"::"r"(1), "r"(cmd_reg));
+ asm volatile("fence");
+ }
+ }
+
+ for (cl = 0; cl < n_cluster; cl++) {
+ for (co = 1; co < n_core; co++) {
+ cmd_reg = CPC_BASE + (cl << CM_BASE_CLUSTER_SHIFT) +
+ (co << CM_BASE_CORE_SHIFT) +
+ CPC_OFF_LOCAL + CPC_Cx_CMD;
+ printf("# Start cluster %d core %d hart 0\n", cl, co);
+ printf("mw.q 0x%lx %d\n", cmd_reg, CPC_Cx_CMD_RESET);
+ if (run == 1) {
+ asm volatile("sd %0, 0(%1)"::"r"(CPC_Cx_CMD_RESET), "r"(cmd_reg));
+ asm volatile("fence");
+ }
+
+ cmd_reg = CPC_BASE + (cl << CM_BASE_CLUSTER_SHIFT) +
+ (co << CM_BASE_CORE_SHIFT) +
+ CPC_OFF_LOCAL + CPC_Cx_VP_RUN;
+ printf("mw.q 0x%lx 1\n", cmd_reg);
+ if (run == 1) {
+ asm volatile("sd %0, 0(%1)"::"r"(1), "r"(cmd_reg));
+ asm volatile("fence");
+ }
+ }
+ }
+
+ for (cl = 0; cl < n_cluster; cl++) {
+ for (co = 0; co < n_core; co++) {
+ printf("# Start cluster %d core %d all harts\n", cl, co);
+ cmd_reg = CPC_BASE + (cl << CM_BASE_CLUSTER_SHIFT) +
+ (co << CM_BASE_CORE_SHIFT) +
+ CPC_OFF_LOCAL + CPC_Cx_VP_RUN;
+ printf("mw.q 0x%lx 0xff\n", cmd_reg);
+ if (run == 1) {
+ asm volatile("sd %0, 0(%1)"::"r"(0xff), "r"(cmd_reg));
+ asm volatile("fence");
+ }
+ }
+ }
+
+ printf("go 0x80000000\n");
+ if (run == 1) {
+ void (*addr)(void) = (void (*)(void))0x80000000;
+ (*addr)();
+ }
+
+ return 0;
+}
+
+/***************************************************/
+
+U_BOOT_CMD(startharts, CONFIG_SYS_MAXARGS, 1, start_harts,
+ "print commands to start all harts and go 0x80000000",
+ "[<#clusters:1-9>] [<#cores_per_cluster:1-9>] [g]\n"
+ " - print commands to start all harts and go 0x80000000\n"
+ " If the 3rd parameter is 'g', execute all comamnds."
+);
diff --git a/configs/boston-p8700_defconfig b/configs/boston-p8700_defconfig
index 3df7ffe50b3..85ed687107e 100644
--- a/configs/boston-p8700_defconfig
+++ b/configs/boston-p8700_defconfig
@@ -72,6 +72,7 @@ CONFIG_OF_EMBED=y
CONFIG_CPU=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_PCI=y
+CONFIG_CMD_START_HARTS=y
CONFIG_UNIT_TEST=y
CONFIG_UT_LIB=n
--
2.34.1
More information about the U-Boot
mailing list