[PATCH v3 3/3] sysreset: provide SBI based sysreset driver

Bin Meng bmeng.cn at gmail.com
Sun Sep 5 13:59:41 CEST 2021


On Sun, Sep 5, 2021 at 4:38 PM Heinrich Schuchardt <xypron.glpk at 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.glpk at 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.glpk at 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?

> +
> +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


More information about the U-Boot mailing list