On 9/5/21 1:59 PM, Bin Meng wrote:
On Sun, Sep 5, 2021 at 4:38 PM Heinrich Schuchardt <xypron.g...@gmx.de> wrote:

Provide sysreset driver using the SBI system reset extension.


This patch should be split into 2 patches, one for adding the sysreset
DM driver, and the other one for EFI support.

Signed-off-by: Heinrich Schuchardt <xypron.g...@gmx.de>
---
v3:
         no change
---
  MAINTAINERS                     |  1 +
  arch/riscv/cpu/cpu.c            | 13 ++++-
  arch/riscv/include/asm/sbi.h    |  1 +
  arch/riscv/lib/sbi.c            | 21 ++++++--
  drivers/sysreset/Kconfig        | 11 ++++
  drivers/sysreset/Makefile       |  1 +
  drivers/sysreset/sysreset_sbi.c | 96 +++++++++++++++++++++++++++++++++
  lib/efi_loader/Kconfig          |  2 +-
  8 files changed, 140 insertions(+), 6 deletions(-)
  create mode 100644 drivers/sysreset/sysreset_sbi.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 4cf0c33c5d..88d7aa2bc7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1017,6 +1017,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 e9caa78d17..69cddda245 100644
--- a/arch/riscv/include/asm/sbi.h
+++ b/arch/riscv/include/asm/sbi.h
@@ -154,5 +154,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..8508041f2a 100644
--- a/arch/riscv/lib/sbi.c
+++ b/arch/riscv/lib/sbi.c
@@ -8,13 +8,14 @@
   */

  #include <common.h>
+#include <efi_loader.h>
  #include <asm/encoding.h>
  #include <asm/sbi.h>

-struct sbiret sbi_ecall(int ext, int fid, unsigned long arg0,
-                       unsigned long arg1, unsigned long arg2,
-                       unsigned long arg3, unsigned long arg4,
-                       unsigned long arg5)
+struct sbiret __efi_runtime sbi_ecall(int ext, int fid, unsigned long arg0,
+                                     unsigned long arg1, unsigned long arg2,
+                                     unsigned long arg3, unsigned long arg4,
+                                     unsigned long arg5)
  {
         struct sbiret ret;

@@ -108,6 +109,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 __efi_runtime 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..6782331181 100644
--- a/drivers/sysreset/Kconfig
+++ b/drivers/sysreset/Kconfig
@@ -85,6 +85,17 @@ 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.
+         If the SBI implementation provides the extension, is board specific.
+         The extension was introduced in version 0.3 of the SBI specification.
+         The SBI system reset driver supports the UEFI ResetSystem() service
+         at runtime.
+
  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..fec5a66515
--- /dev/null
+++ b/drivers/sysreset/sysreset_sbi.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021, Heinrich Schuchardt <xypron.g...@gmx.de>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <efi_loader.h>
+#include <log.h>
+#include <sysreset.h>
+#include <asm/sbi.h>
+
+static long __efi_runtime_data have_reset;
+
+static int sbi_sysreset_request(struct udevice *dev, enum sysreset_t type)
+{
+       enum sbi_srst_reset_type reset_type;
+
+       switch (type) {
+       case SYSRESET_WARM:
+               reset_type = SBI_SRST_RESET_TYPE_WARM_REBOOT;
+               break;
+       case SYSRESET_COLD:
+               reset_type = SBI_SRST_RESET_TYPE_COLD_REBOOT;
+               break;
+       case SYSRESET_POWER_OFF:
+               reset_type = SBI_SRST_RESET_TYPE_SHUTDOWN;
+               break;
+       default:
+               log_err("SBI has no system reset extension\n");
+               return -ENOSYS;
+       }
+
+       sbi_srst_reset(reset_type, SBI_SRST_RESET_REASON_NONE);
+
+       return -EINPROGRESS;
+}
+
+efi_status_t efi_reset_system_init(void)
+{
+       return EFI_SUCCESS;
+}

Is there a better place for the EFI stuff?

Bin, thanks for reviewing the series.

This seems to be related to you comment above about splitting into two
patches. We put have the same set of EFI runtime functions for system
reset in:

drivers/sysreset/sysreset_x86.c
drivers/firmware/psci.c
arch/arm/mach-bcm283x/reset.c
arch/arm/cpu/armv8/fsl-layerscape/cpu.c

My idea was that all SBI system reset related things should be in the
same source file.

Where do you think would be the best place for RISC-V SBI calls at UEFI
runtime?

Best regards

Heinrich


+
+void __efi_runtime EFIAPI efi_reset_system(enum efi_reset_type type,
+                                          efi_status_t reset_status,
+                                          unsigned long data_size,
+                                          void *reset_data)
+{
+       enum sbi_srst_reset_type reset_type;
+       enum sbi_srst_reset_reason reset_reason;
+
+       if (have_reset)
+               switch (type) {
+               case SYSRESET_COLD:
+                       reset_type = SBI_SRST_RESET_TYPE_COLD_REBOOT;
+                       break;
+               case SYSRESET_POWER_OFF:
+                       reset_type = SBI_SRST_RESET_TYPE_SHUTDOWN;
+                       break;
+               default:
+                       reset_type = SBI_SRST_RESET_TYPE_WARM_REBOOT;
+                       break;
+       }
+
+       if (reset_status == EFI_SUCCESS)
+               reset_reason = SBI_SRST_RESET_REASON_NONE;
+       else
+               reset_reason = SBI_SRST_RESET_REASON_SYS_FAILURE;
+
+       sbi_srst_reset(reset_type, reset_reason);
+
+       while (1)
+               ;
+}
+
+static int sbi_sysreset_probe(struct udevice *dev)
+{
+       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,
+};
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index dacc3b5881..36985fce2c 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -297,7 +297,7 @@ config EFI_HAVE_RUNTIME_RESET
         bool
         default y
         depends on ARCH_BCM283X || FSL_LAYERSCAPE || PSCI_RESET || \
-                  SANDBOX || SYSRESET_X86
+                  SANDBOX || SYSRESET_SBI || SYSRESET_X86

  config EFI_GRUB_ARM32_WORKAROUND
         bool "Workaround for GRUB on 32bit ARM"
--

Regards,
Bin


Reply via email to