VisionFive2 U-Boot

StarFive Tech U-Boot for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   15 Branches   51 Tags
author: andy.hu <andy.hu@starfivetech.com> 2023-02-03 11:26:19 +0000 committer: andy.hu <andy.hu@starfivetech.com> 2023-02-03 11:26:19 +0000 commit: ec041f706042d7e09e92c84b06180bcb4700ac88 parent: 8571717e560a7033a644f84d8182714ed26fdbf5
Commit Summary:
Merge branch 'CR_1432_add_sbi_reset_patch_minda' into 'jh7110-master'
Diffstat:
7 files changed, 108 insertions, 3 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 5370b55064..cd5b92fcce 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1010,6 +1010,7 @@ T:	git https://source.denx.de/u-boot/custodians/u-boot-riscv.git
 F:	arch/riscv/
 F:	cmd/riscv/
 F:	doc/usage/sbi.rst
+F:	drivers/sysreset/sysreset_sbi.c
 F:	drivers/timer/andes_plmt_timer.c
 F:	drivers/timer/sifive_clint_timer.c
 F:	tools/prelink-riscv.c
diff --git a/arch/riscv/cpu/cpu.c b/arch/riscv/cpu/cpu.c
index c894ac10b5..8e49b6d736 100644
--- a/arch/riscv/cpu/cpu.c
+++ b/arch/riscv/cpu/cpu.c
@@ -6,6 +6,7 @@
 #include <common.h>
 #include <cpu.h>
 #include <dm.h>
+#include <dm/lists.h>
 #include <init.h>
 #include <log.h>
 #include <asm/encoding.h>
@@ -138,7 +139,17 @@ int arch_cpu_init_dm(void)
 
 int arch_early_init_r(void)
 {
-	return riscv_cpu_probe();
+	int ret;
+
+	ret = riscv_cpu_probe();
+	if (ret)
+		return ret;
+
+	if (IS_ENABLED(CONFIG_SYSRESET_SBI))
+		device_bind_driver(gd->dm_root, "sbi-sysreset",
+				   "sbi-sysreset", NULL);
+
+	return 0;
 }
 
 /**
diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h
index 53ca316180..5030892b47 100644
--- a/arch/riscv/include/asm/sbi.h
+++ b/arch/riscv/include/asm/sbi.h
@@ -12,7 +12,6 @@
 #include <linux/types.h>
 
 enum sbi_ext_id {
-#ifdef CONFIG_SBI_V01
 	SBI_EXT_0_1_SET_TIMER = 0x0,
 	SBI_EXT_0_1_CONSOLE_PUTCHAR = 0x1,
 	SBI_EXT_0_1_CONSOLE_GETCHAR = 0x2,
@@ -22,11 +21,12 @@ enum sbi_ext_id {
 	SBI_EXT_0_1_REMOTE_SFENCE_VMA = 0x6,
 	SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID = 0x7,
 	SBI_EXT_0_1_SHUTDOWN = 0x8,
-#endif
 	SBI_EXT_BASE = 0x10,
 	SBI_EXT_TIME = 0x54494D45,
 	SBI_EXT_IPI = 0x735049,
 	SBI_EXT_RFENCE = 0x52464E43,
+	SBI_EXT_HSM = 0x48534D,
+	SBI_EXT_SRST = 0x53525354,
 };
 
 enum sbi_ext_base_fid {
@@ -51,6 +51,41 @@ enum sbi_ext_rfence_fid {
 	SBI_EXT_RFENCE_REMOTE_FENCE_I = 0,
 	SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,
 	SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,
+	SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID,
+	SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA,
+	SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID,
+	SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA,
+};
+
+enum sbi_ext_hsm_fid {
+	SBI_EXT_HSM_HART_START = 0,
+	SBI_EXT_HSM_HART_STOP,
+	SBI_EXT_HSM_HART_STATUS,
+	SBI_EXT_HSM_HART_SUSPEND,
+};
+
+enum sbi_hsm_hart_status {
+	SBI_HSM_HART_STATUS_STARTED = 0,
+	SBI_HSM_HART_STATUS_STOPPED,
+	SBI_HSM_HART_STATUS_START_PENDING,
+	SBI_HSM_HART_STATUS_STOP_PENDING,
+	SBI_HSM_HART_STATUS_SUSPEND_PENDING,
+	SBI_HSM_HART_STATUS_RESUME_PENDING,
+};
+
+enum sbi_ext_srst_fid {
+	SBI_EXT_SRST_RESET = 0,
+};
+
+enum sbi_srst_reset_type {
+	SBI_SRST_RESET_TYPE_SHUTDOWN = 0,
+	SBI_SRST_RESET_TYPE_COLD_REBOOT,
+	SBI_SRST_RESET_TYPE_WARM_REBOOT,
+};
+
+enum sbi_srst_reset_reason {
+	SBI_SRST_RESET_REASON_NONE = 0,
+	SBI_SRST_RESET_REASON_SYS_FAILURE,
 };
 
 #ifdef CONFIG_SBI_V01
@@ -118,5 +153,6 @@ void sbi_set_timer(uint64_t stime_value);
 long sbi_get_spec_version(void);
 int sbi_get_impl_id(void);
 int sbi_probe_extension(int ext);
+void sbi_srst_reset(unsigned long type, unsigned long reason);
 
 #endif
diff --git a/arch/riscv/lib/sbi.c b/arch/riscv/lib/sbi.c
index 77845a73ca..2b53896b8a 100644
--- a/arch/riscv/lib/sbi.c
+++ b/arch/riscv/lib/sbi.c
@@ -108,6 +108,18 @@ int sbi_probe_extension(int extid)
 	return -ENOTSUPP;
 }
 
+/**
+ * sbi_srst_reset() - invoke system reset extension
+ *
+ * @type:	type of reset
+ * @reason:	reason for reset
+ */
+void sbi_srst_reset(unsigned long type, unsigned long reason)
+{
+	sbi_ecall(SBI_EXT_SRST, SBI_EXT_SRST_RESET, type, reason,
+		  0, 0, 0, 0);
+}
+
 #ifdef CONFIG_SBI_V01
 
 /**
diff --git a/drivers/sysreset/Kconfig b/drivers/sysreset/Kconfig
index ac77ffbc8b..43a948cfcd 100644
--- a/drivers/sysreset/Kconfig
+++ b/drivers/sysreset/Kconfig
@@ -85,6 +85,18 @@ config SYSRESET_PSCI
 	  Enable PSCI SYSTEM_RESET function call.  To use this, PSCI firmware
 	  must be running on your system.
 
+config SYSRESET_SBI
+	bool "Enable support for SBI System Reset"
+	depends on RISCV_SMODE && SBI_V02
+	select SYSRESET_CMD_POWEROFF if CMD_POWEROFF
+	help
+	  Enable system reset and poweroff via the SBI system reset extension.
+	  The extension was introduced in version 0.3 of the SBI specification.
+
+	  If the SBI implementation provides the extension, is board specific.
+	  The RISC-V platform specification mandates the extension for rich
+	  operating system platforms.
+
 config SYSRESET_SOCFPGA
 	bool "Enable support for Intel SOCFPGA family"
 	depends on ARCH_SOCFPGA && (TARGET_SOCFPGA_GEN5 || TARGET_SOCFPGA_ARRIA10)
diff --git a/drivers/sysreset/Makefile b/drivers/sysreset/Makefile
index de81c399d7..8e00be0779 100644
--- a/drivers/sysreset/Makefile
+++ b/drivers/sysreset/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_SYSRESET_MPC83XX) += sysreset_mpc83xx.o
 obj-$(CONFIG_SYSRESET_MICROBLAZE) += sysreset_microblaze.o
 obj-$(CONFIG_SYSRESET_OCTEON) += sysreset_octeon.o
 obj-$(CONFIG_SYSRESET_PSCI) += sysreset_psci.o
+obj-$(CONFIG_SYSRESET_SBI) += sysreset_sbi.o
 obj-$(CONFIG_SYSRESET_SOCFPGA) += sysreset_socfpga.o
 obj-$(CONFIG_SYSRESET_SOCFPGA_SOC64) += sysreset_socfpga_soc64.o
 obj-$(CONFIG_SYSRESET_TI_SCI) += sysreset-ti-sci.o
diff --git a/drivers/sysreset/sysreset_sbi.c b/drivers/sysreset/sysreset_sbi.c
new file mode 100644
index 0000000000..5e8090d62b
--- /dev/null
+++ b/drivers/sysreset/sysreset_sbi.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021, Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <log.h>
+#include <sysreset.h>
+#include <asm/sbi.h>
+
+static enum sbi_srst_reset_type reset_type_map[SYSRESET_COUNT] = {
+	[SYSRESET_WARM] = SBI_SRST_RESET_TYPE_WARM_REBOOT,
+	[SYSRESET_COLD] = SBI_SRST_RESET_TYPE_COLD_REBOOT,
+	[SYSRESET_POWER] = SBI_SRST_RESET_TYPE_COLD_REBOOT,
+	[SYSRESET_POWER_OFF] = SBI_SRST_RESET_TYPE_SHUTDOWN,
+};
+
+static int sbi_sysreset_request(struct udevice *dev, enum sysreset_t type)
+{
+	enum sbi_srst_reset_type reset_type;
+
+	reset_type = reset_type_map[type];
+	sbi_srst_reset(reset_type, SBI_SRST_RESET_REASON_NONE);
+
+	return -EINPROGRESS;
+}
+
+static int sbi_sysreset_probe(struct udevice *dev)
+{
+	long have_reset;
+
+	have_reset = sbi_probe_extension(SBI_EXT_SRST);
+	if (have_reset)
+		return 0;
+
+	log_warning("SBI has no system reset extension\n");
+	return -ENOENT;
+}
+
+static struct sysreset_ops sbi_sysreset_ops = {
+	.request = sbi_sysreset_request,
+};
+
+U_BOOT_DRIVER(sbi_sysreset) = {
+	.name = "sbi-sysreset",
+	.id = UCLASS_SYSRESET,
+	.ops = &sbi_sysreset_ops,
+	.probe = sbi_sysreset_probe,
+};