From: Chao-ying Fu <c...@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 <c...@mips.com>
Signed-off-by: Uros Stajic <uros.sta...@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 3be6459acf6..3cfc6bcc7e7 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2334,6 +2334,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 e1bdb7f05e8..afe10e92291 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, w...@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

Reply via email to