[PATCH 5/6] lib: utils/reset: Add syscon based reboot and poweroff
Xiang W
wxjstz at 126.com
Fri Jul 28 06:42:37 PDT 2023
在 2023-07-21星期五的 22:40 +0530,Anup Patel写道:
> Let us have common FDT based reset driver for syscon reboot and
> poweroff. The device tree bindings for syscon reboot and poweroff
> are already available in the Linux kernel sources.
>
> Signed-off-by: Anup Patel <apatel at ventanamicro.com>
Look good to me.
Reviewed-by: Xiang W <wxjstz at 126.com>
> ---
> lib/utils/reset/Kconfig | 5 +
> lib/utils/reset/fdt_reset_syscon.c | 167 +++++++++++++++++++++++++++++
> lib/utils/reset/objects.mk | 4 +
> platform/generic/configs/defconfig | 1 +
> 4 files changed, 177 insertions(+)
> create mode 100644 lib/utils/reset/fdt_reset_syscon.c
>
> diff --git a/lib/utils/reset/Kconfig b/lib/utils/reset/Kconfig
> index 4748cc8..c0b9640 100644
> --- a/lib/utils/reset/Kconfig
> +++ b/lib/utils/reset/Kconfig
> @@ -33,6 +33,11 @@ config FDT_RESET_SUNXI_WDT
> bool "Sunxi WDT FDT reset driver"
> default n
>
> +config FDT_RESET_SYSCON
> + bool "Syscon FDT reset driver"
> + depends on FDT_REGMAP
> + default n
> +
> config FDT_RESET_THEAD
> bool "T-HEAD FDT reset driver"
> default n
> diff --git a/lib/utils/reset/fdt_reset_syscon.c b/lib/utils/reset/fdt_reset_syscon.c
> new file mode 100644
> index 0000000..bae9ec5
> --- /dev/null
> +++ b/lib/utils/reset/fdt_reset_syscon.c
> @@ -0,0 +1,167 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2023 Ventana Micro Systems Inc.
> + *
> + * Authors:
> + * Anup Patel <apatel at ventanamicro.com>
> + */
> +
> +#include <libfdt.h>
> +#include <sbi/sbi_ecall_interface.h>
> +#include <sbi/sbi_error.h>
> +#include <sbi/sbi_hart.h>
> +#include <sbi/sbi_system.h>
> +#include <sbi_utils/fdt/fdt_helper.h>
> +#include <sbi_utils/regmap/fdt_regmap.h>
> +#include <sbi_utils/reset/fdt_reset.h>
> +
> +struct syscon_reset {
> + struct regmap *rmap;
> + u32 priority;
> + u32 offset;
> + u32 value;
> + u32 mask;
> +};
> +
> +static struct syscon_reset poweroff;
> +static struct syscon_reset reboot;
> +
> +static struct syscon_reset *syscon_reset_get(bool is_reboot, u32 type)
> +{
> + struct syscon_reset *reset = NULL;
> +
> + switch (type) {
> + case SBI_SRST_RESET_TYPE_SHUTDOWN:
> + if (!is_reboot)
> + reset = &poweroff;
> + break;
> + case SBI_SRST_RESET_TYPE_COLD_REBOOT:
> + case SBI_SRST_RESET_TYPE_WARM_REBOOT:
> + if (is_reboot)
> + reset = &reboot;
> + break;
> + }
> +
> + if (reset && !reset->rmap)
> + reset = NULL;
> +
> + return reset;
> +}
> +
> +static void syscon_reset_exec(struct syscon_reset *reset)
> +{
> + /* Issue the reset through regmap */
> + if (reset)
> + regmap_update_bits(reset->rmap, reset->offset,
> + reset->mask, reset->value);
> +
> + /* hang !!! */
> + sbi_hart_hang();
> +}
> +
> +static int syscon_poweroff_check(u32 type, u32 reason)
> +{
> + struct syscon_reset *reset = syscon_reset_get(false, type);
> +
> + return (reset) ? reset->priority : 0;
> +}
> +
> +static void syscon_do_poweroff(u32 type, u32 reason)
> +{
> + syscon_reset_exec(syscon_reset_get(false, type));
> +}
> +
> +static struct sbi_system_reset_device syscon_poweroff = {
> + .name = "syscon-poweroff",
> + .system_reset_check = syscon_poweroff_check,
> + .system_reset = syscon_do_poweroff
> +};
> +
> +static int syscon_reboot_check(u32 type, u32 reason)
> +{
> + struct syscon_reset *reset = syscon_reset_get(true, type);
> +
> + return (reset) ? reset->priority : 0;
> +}
> +
> +static void syscon_do_reboot(u32 type, u32 reason)
> +{
> + syscon_reset_exec(syscon_reset_get(true, type));
> +}
> +
> +static struct sbi_system_reset_device syscon_reboot = {
> + .name = "syscon-reboot",
> + .system_reset_check = syscon_reboot_check,
> + .system_reset = syscon_do_reboot
> +};
> +
> +static int syscon_reset_init(void *fdt, int nodeoff,
> + const struct fdt_match *match)
> +{
> + int rc, len;
> + const fdt32_t *val, *mask;
> + bool is_reboot = (ulong)match->data;
> + struct syscon_reset *reset = (is_reboot) ? &reboot : &poweroff;
> +
> + if (reset->rmap)
> + return SBI_EALREADY;
> +
> + rc = fdt_regmap_get(fdt, nodeoff, &reset->rmap);
> + if (rc)
> + return rc;
> +
> + val = fdt_getprop(fdt, nodeoff, "priority", &len);
> + reset->priority = (val && len > 0) ? fdt32_to_cpu(*val) : 192;
> +
> + val = fdt_getprop(fdt, nodeoff, "offset", &len);
> + if (val && len > 0)
> + reset->offset = fdt32_to_cpu(*val);
> + else
> + return SBI_EINVAL;
> +
> + val = fdt_getprop(fdt, nodeoff, "value", &len);
> + mask = fdt_getprop(fdt, nodeoff, "mask", &len);
> + if (!val && !mask)
> + return SBI_EINVAL;
> +
> + if (!val) {
> + /* support old binding */
> + reset->value = fdt32_to_cpu(*mask);
> + reset->mask = 0xFFFFFFFF;
> + } else if (!mask) {
> + /* support value without mask */
> + reset->value = fdt32_to_cpu(*val);
> + reset->mask = 0xFFFFFFFF;
> + } else {
> + reset->value = fdt32_to_cpu(*val);
> + reset->mask = fdt32_to_cpu(*mask);
> + }
> +
> + if (is_reboot)
> + sbi_system_reset_add_device(&syscon_reboot);
> + else
> + sbi_system_reset_add_device(&syscon_poweroff);
> +
> + return 0;
> +}
> +
> +static const struct fdt_match syscon_poweroff_match[] = {
> + { .compatible = "syscon-poweroff", .data = (const void *)false },
> + { },
> +};
> +
> +struct fdt_reset fdt_syscon_poweroff = {
> + .match_table = syscon_poweroff_match,
> + .init = syscon_reset_init,
> +};
> +
> +static const struct fdt_match syscon_reboot_match[] = {
> + { .compatible = "syscon-reboot", .data = (const void *)true },
> + { },
> +};
> +
> +struct fdt_reset fdt_syscon_reboot = {
> + .match_table = syscon_reboot_match,
> + .init = syscon_reset_init,
> +};
> diff --git a/lib/utils/reset/objects.mk b/lib/utils/reset/objects.mk
> index c9f851c..17287a5 100644
> --- a/lib/utils/reset/objects.mk
> +++ b/lib/utils/reset/objects.mk
> @@ -26,6 +26,10 @@ libsbiutils-objs-$(CONFIG_FDT_RESET_SIFIVE_TEST) += reset/fdt_reset_sifive_test.
> carray-fdt_reset_drivers-$(CONFIG_FDT_RESET_SUNXI_WDT) += fdt_reset_sunxi_wdt
> libsbiutils-objs-$(CONFIG_FDT_RESET_SUNXI_WDT) += reset/fdt_reset_sunxi_wdt.o
>
> +carray-fdt_reset_drivers-$(CONFIG_FDT_RESET_SYSCON) += fdt_syscon_poweroff
> +carray-fdt_reset_drivers-$(CONFIG_FDT_RESET_SYSCON) += fdt_syscon_reboot
> +libsbiutils-objs-$(CONFIG_FDT_RESET_SYSCON) += reset/fdt_reset_syscon.o
> +
> carray-fdt_reset_drivers-$(CONFIG_FDT_RESET_THEAD) += fdt_reset_thead
> libsbiutils-objs-$(CONFIG_FDT_RESET_THEAD) += reset/fdt_reset_thead.o
> libsbiutils-objs-$(CONFIG_FDT_RESET_THEAD) += reset/fdt_reset_thead_asm.o
> diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
> index b767290..5008c7e 100644
> --- a/platform/generic/configs/defconfig
> +++ b/platform/generic/configs/defconfig
> @@ -26,6 +26,7 @@ CONFIG_FDT_RESET_GPIO=y
> CONFIG_FDT_RESET_HTIF=y
> CONFIG_FDT_RESET_SIFIVE_TEST=y
> CONFIG_FDT_RESET_SUNXI_WDT=y
> +CONFIG_FDT_RESET_SYSCON=y
> CONFIG_FDT_RESET_THEAD=y
> CONFIG_FDT_SERIAL=y
> CONFIG_FDT_SERIAL_CADENCE=y
> --
> 2.34.1
>
>
More information about the opensbi
mailing list