lib: sbi: Add system suspend skeleton
authorAndrew Jones <ajones@ventanamicro.com>
Mon, 27 Feb 2023 10:31:02 +0000 (11:31 +0100)
committerAnup Patel <anup@brainfault.org>
Mon, 27 Feb 2023 14:13:52 +0000 (19:43 +0530)
Add the SUSP extension probe and ecall support, but for now the
system suspend function is just a stub.

Signed-off-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
include/sbi/sbi_ecall_interface.h
include/sbi/sbi_system.h
lib/sbi/Kconfig
lib/sbi/objects.mk
lib/sbi/sbi_ecall_susp.c [new file with mode: 0644]
lib/sbi/sbi_init.c
lib/sbi/sbi_system.c

index 9d6f4743651d8132dff7c43ca2649043ba6439cc..4c378c3e7c309c78819d8de6ed816e35d6e9a3a7 100644 (file)
@@ -30,6 +30,7 @@
 #define SBI_EXT_SRST                           0x53525354
 #define SBI_EXT_PMU                            0x504D55
 #define SBI_EXT_DBCN                           0x4442434E
+#define SBI_EXT_SUSP                           0x53555350
 
 /* SBI function IDs for BASE extension*/
 #define SBI_EXT_BASE_GET_SPEC_VERSION          0x0
@@ -236,6 +237,13 @@ enum sbi_pmu_ctr_type {
 #define SBI_EXT_DBCN_CONSOLE_READ              0x1
 #define SBI_EXT_DBCN_CONSOLE_WRITE_BYTE                0x2
 
+/* SBI function IDs for SUSP extension */
+#define SBI_EXT_SUSP_SUSPEND                   0x0
+
+#define SBI_SUSP_SLEEP_TYPE_SUSPEND            0x0
+#define SBI_SUSP_SLEEP_TYPE_LAST               SBI_SUSP_SLEEP_TYPE_SUSPEND
+#define SBI_SUSP_PLATFORM_SLEEP_START          0x80000000
+
 /* SBI base specification related macros */
 #define SBI_SPEC_VERSION_MAJOR_OFFSET          24
 #define SBI_SPEC_VERSION_MAJOR_MASK            0x7f
index 84c281383d8cf66f8b7880b38e50ac007b721bea..11d3d6fd9a68ba06f7061de06eaa8343fc51e85d 100644 (file)
@@ -43,4 +43,30 @@ bool sbi_system_reset_supported(u32 reset_type, u32 reset_reason);
 
 void __noreturn sbi_system_reset(u32 reset_type, u32 reset_reason);
 
+/** System suspend device */
+struct sbi_system_suspend_device {
+       /** Name of the system suspend device */
+       char name[32];
+
+       /* Check whether sleep type is supported by the device */
+       int (*system_suspend_check)(u32 sleep_type);
+
+       /**
+        * Suspend the system
+        *
+        * @sleep_type: The sleep type identifier passed to the SBI call.
+        * @mmode_resume_addr:
+        *     This is the same as sbi_scratch.warmboot_addr. Some platforms
+        *     may not be able to return from system_suspend(), so they will
+        *     jump directly to this address instead. Platforms which can
+        *     return from system_suspend() may ignore this parameter.
+        */
+       int (*system_suspend)(u32 sleep_type, unsigned long mmode_resume_addr);
+};
+
+const struct sbi_system_suspend_device *sbi_system_suspend_get_device(void);
+void sbi_system_suspend_set_device(struct sbi_system_suspend_device *dev);
+bool sbi_system_suspend_supported(u32 sleep_type);
+int sbi_system_suspend(u32 sleep_type, ulong resume_addr, ulong opaque);
+
 #endif
index ef6728bab3eaec58173486a793a0e10cc0f26013..7eb3273d546ea8cb36ba8fffcfedb0dc1ff8a720 100644 (file)
@@ -22,6 +22,10 @@ config SBI_ECALL_SRST
        bool "System Reset extension"
        default y
 
+config SBI_ECALL_SUSP
+       bool "System Suspend extension"
+       default y
+
 config SBI_ECALL_PMU
        bool "Performance Monitoring Unit extension"
        default y
index 319f38dce7023d00c28a1345ac5d4ebcdca49d2b..770238b25fa62eb1bd432145051c97c5db4d5372 100644 (file)
@@ -34,6 +34,9 @@ libsbi-objs-$(CONFIG_SBI_ECALL_HSM) += sbi_ecall_hsm.o
 carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_SRST) += ecall_srst
 libsbi-objs-$(CONFIG_SBI_ECALL_SRST) += sbi_ecall_srst.o
 
+carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_SUSP) += ecall_susp
+libsbi-objs-$(CONFIG_SBI_ECALL_SUSP) += sbi_ecall_susp.o
+
 carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_PMU) += ecall_pmu
 libsbi-objs-$(CONFIG_SBI_ECALL_PMU) += sbi_ecall_pmu.o
 
diff --git a/lib/sbi/sbi_ecall_susp.c b/lib/sbi/sbi_ecall_susp.c
new file mode 100644 (file)
index 0000000..f20126c
--- /dev/null
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: BSD-2-Clause
+#include <sbi/sbi_ecall.h>
+#include <sbi/sbi_ecall_interface.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_trap.h>
+#include <sbi/sbi_system.h>
+
+static int sbi_ecall_susp_handler(unsigned long extid, unsigned long funcid,
+                                 const struct sbi_trap_regs *regs,
+                                 unsigned long *out_val,
+                                 struct sbi_trap_info *out_trap)
+{
+       int ret = SBI_ENOTSUPP;
+
+       if (funcid == SBI_EXT_SUSP_SUSPEND)
+               ret = sbi_system_suspend(regs->a0, regs->a1, regs->a2);
+
+       if (ret >= 0) {
+               *out_val = ret;
+               ret = 0;
+       }
+
+       return ret;
+}
+
+static int sbi_ecall_susp_probe(unsigned long extid, unsigned long *out_val)
+{
+       u32 type, count = 0;
+
+       /*
+        * At least one suspend type should be supported by the
+        * platform for the SBI SUSP extension to be usable.
+        */
+       for (type = 0; type <= SBI_SUSP_SLEEP_TYPE_LAST; type++) {
+               if (sbi_system_suspend_supported(type))
+                       count++;
+       }
+
+       *out_val = count ? 1 : 0;
+       return 0;
+}
+
+struct sbi_ecall_extension ecall_susp = {
+       .extid_start = SBI_EXT_SUSP,
+       .extid_end = SBI_EXT_SUSP,
+       .handle = sbi_ecall_susp_handler,
+       .probe = sbi_ecall_susp_probe,
+};
index e353c3348303e03552c5050404763496e23b325c..bc60a4279354985a8ea6c8eceba70555a0d00eea 100644 (file)
@@ -69,6 +69,7 @@ static void sbi_boot_print_general(struct sbi_scratch *scratch)
        const struct sbi_timer_device *tdev;
        const struct sbi_console_device *cdev;
        const struct sbi_system_reset_device *srdev;
+       const struct sbi_system_suspend_device *susp_dev;
        const struct sbi_platform *plat = sbi_platform_ptr(scratch);
 
        if (scratch->options & SBI_SCRATCH_NO_BOOT_PRINTS)
@@ -103,6 +104,9 @@ static void sbi_boot_print_general(struct sbi_scratch *scratch)
        srdev = sbi_system_reset_get_device(SBI_SRST_RESET_TYPE_SHUTDOWN, 0);
        sbi_printf("Platform Shutdown Device  : %s\n",
                   (srdev) ? srdev->name : "---");
+       susp_dev = sbi_system_suspend_get_device();
+       sbi_printf("Platform Suspend Device   : %s\n",
+                  (susp_dev) ? susp_dev->name : "---");
 
        /* Firmware details */
        sbi_printf("Firmware Base             : 0x%lx\n", scratch->fw_start);
index f37c811d0bf31530a644da13bf2a1a1e8be9da70..5c123a6c9d8dded56ad4024f104dad5b08bd61be 100644 (file)
@@ -92,3 +92,29 @@ void __noreturn sbi_system_reset(u32 reset_type, u32 reset_reason)
        /* If platform specific reset did not work then do sbi_exit() */
        sbi_exit(scratch);
 }
+
+static const struct sbi_system_suspend_device *suspend_dev = NULL;
+
+const struct sbi_system_suspend_device *sbi_system_suspend_get_device(void)
+{
+       return suspend_dev;
+}
+
+void sbi_system_suspend_set_device(struct sbi_system_suspend_device *dev)
+{
+       if (!dev || suspend_dev)
+               return;
+
+       suspend_dev = dev;
+}
+
+bool sbi_system_suspend_supported(u32 sleep_type)
+{
+       return suspend_dev && suspend_dev->system_suspend_check &&
+              suspend_dev->system_suspend_check(sleep_type);
+}
+
+int sbi_system_suspend(u32 sleep_type, ulong resume_addr, ulong opaque)
+{
+       return 0;
+}