summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnup Patel <anup.patel@wdc.com>2020-11-24 11:50:19 +0300
committerAnup Patel <anup@brainfault.org>2020-12-01 14:41:11 +0300
commit548d03e577490f74af8b57706655e5d81c9b94a1 (patch)
treef8854349e7f544d05886c38c18c320d0dafbc0da
parent5c429ae2133e1a82b81403146a3e38e2b4b8350e (diff)
downloadopensbi-548d03e577490f74af8b57706655e5d81c9b94a1.tar.xz
lib: sbi: Implement System Reset (SRST) SBI extension
The SBI SRST extension has been accepted and merged in the latest SBI v0.3-draft specification. (Refer, https://github.com/riscv/riscv-sbi-doc) It allows to S-mode software to request system shutdown, cold reboot, and warm reboot. This patch implements SBI SRST extension as a replacement of the legacy sbi_shutdown() call of SBI v0.1 specification. Signed-off-by: Anup Patel <anup.patel@wdc.com> Reviewed-by: Atish Patra <atish.patra@wdc.com>
-rw-r--r--include/sbi/sbi_ecall.h1
-rw-r--r--lib/sbi/sbi_ecall.c3
-rw-r--r--lib/sbi/sbi_ecall_replace.c60
3 files changed, 64 insertions, 0 deletions
diff --git a/include/sbi/sbi_ecall.h b/include/sbi/sbi_ecall.h
index 3273ba6..1ef86e2 100644
--- a/include/sbi/sbi_ecall.h
+++ b/include/sbi/sbi_ecall.h
@@ -37,6 +37,7 @@ extern struct sbi_ecall_extension ecall_rfence;
extern struct sbi_ecall_extension ecall_ipi;
extern struct sbi_ecall_extension ecall_vendor;
extern struct sbi_ecall_extension ecall_hsm;
+extern struct sbi_ecall_extension ecall_srst;
u16 sbi_ecall_version_major(void);
diff --git a/lib/sbi/sbi_ecall.c b/lib/sbi/sbi_ecall.c
index 64c9933..6d41cff 100644
--- a/lib/sbi/sbi_ecall.c
+++ b/lib/sbi/sbi_ecall.c
@@ -169,6 +169,9 @@ int sbi_ecall_init(void)
ret = sbi_ecall_register_extension(&ecall_hsm);
if (ret)
return ret;
+ ret = sbi_ecall_register_extension(&ecall_srst);
+ if (ret)
+ return ret;
ret = sbi_ecall_register_extension(&ecall_legacy);
if (ret)
return ret;
diff --git a/lib/sbi/sbi_ecall_replace.c b/lib/sbi/sbi_ecall_replace.c
index e460c30..d06dfa2 100644
--- a/lib/sbi/sbi_ecall_replace.c
+++ b/lib/sbi/sbi_ecall_replace.c
@@ -14,6 +14,7 @@
#include <sbi/sbi_error.h>
#include <sbi/sbi_hart.h>
#include <sbi/sbi_ipi.h>
+#include <sbi/sbi_system.h>
#include <sbi/sbi_timer.h>
#include <sbi/sbi_tlb.h>
@@ -127,3 +128,62 @@ struct sbi_ecall_extension ecall_ipi = {
.extid_end = SBI_EXT_IPI,
.handle = sbi_ecall_ipi_handler,
};
+
+static int sbi_ecall_srst_handler(unsigned long extid, unsigned long funcid,
+ unsigned long *args, unsigned long *out_val,
+ struct sbi_trap_info *out_trap)
+{
+ if (funcid == SBI_EXT_SRST_RESET) {
+ if ((((u32)-1U) <= ((u64)args[0])) ||
+ (((u32)-1U) <= ((u64)args[1])))
+ return SBI_EINVAL;
+
+ switch (args[0]) {
+ case SBI_SRST_RESET_TYPE_SHUTDOWN:
+ case SBI_SRST_RESET_TYPE_COLD_REBOOT:
+ case SBI_SRST_RESET_TYPE_WARM_REBOOT:
+ break;
+ default:
+ return SBI_ENOTSUPP;
+ }
+
+ switch (args[1]) {
+ case SBI_SRST_RESET_REASON_NONE:
+ case SBI_SRST_RESET_REASON_SYSFAIL:
+ break;
+ default:
+ return SBI_ENOTSUPP;
+ }
+
+ if (sbi_system_reset_supported(args[0], args[1]))
+ sbi_system_reset(args[0], args[1]);
+ }
+
+ return SBI_ENOTSUPP;
+}
+
+static int sbi_ecall_srst_probe(unsigned long extid, unsigned long *out_val)
+{
+ u32 type, count = 0;
+
+ /*
+ * At least one standard reset types should be supported by
+ * the platform for SBI SRST extension to be usable.
+ */
+
+ for (type = 0; type <= SBI_SRST_RESET_TYPE_LAST; type++) {
+ if (sbi_system_reset_supported(type,
+ SBI_SRST_RESET_REASON_NONE))
+ count++;
+ }
+
+ *out_val = (count) ? 1 : 0;
+ return 0;
+}
+
+struct sbi_ecall_extension ecall_srst = {
+ .extid_start = SBI_EXT_SRST,
+ .extid_end = SBI_EXT_SRST,
+ .handle = sbi_ecall_srst_handler,
+ .probe = sbi_ecall_srst_probe,
+};