diff options
| author | Rahul Pathak <[email protected]> | 2024-08-06 10:24:19 +0530 |
|---|---|---|
| committer | Anup Patel <[email protected]> | 2024-12-06 09:26:27 +0530 |
| commit | 6a26726e08e4d1e23b2e6cce073689ecdabf9291 (patch) | |
| tree | 86fa158485a31bf094264bf04c9e16ed602b55a9 /lib/utils | |
| parent | 91f46fb47eefb872a7981935fbcc125226e93eca (diff) | |
lib/utils: reset: Add RPMI System Reset driver
Add RPMI based driver for system reset and enable it in the generic
platform defconfig
Signed-off-by: Rahul Pathak <[email protected]>
Signed-off-by: Anup Patel <[email protected]>
Diffstat (limited to 'lib/utils')
| -rw-r--r-- | lib/utils/reset/Kconfig | 5 | ||||
| -rw-r--r-- | lib/utils/reset/fdt_reset_rpmi.c | 141 | ||||
| -rw-r--r-- | lib/utils/reset/objects.mk | 3 |
3 files changed, 149 insertions, 0 deletions
diff --git a/lib/utils/reset/Kconfig b/lib/utils/reset/Kconfig index 6c077fe7..68e66716 100644 --- a/lib/utils/reset/Kconfig +++ b/lib/utils/reset/Kconfig @@ -24,6 +24,11 @@ config FDT_RESET_HTIF select SYS_HTIF default n +config FDT_RESET_RPMI + bool "RPMI FDT reset driver" + depends on FDT_MAILBOX && RPMI_MAILBOX + default n + config FDT_RESET_SG2042_HWMON_MCU bool "Sophgo SG2042 hwmon MCU FDT reset driver" default n diff --git a/lib/utils/reset/fdt_reset_rpmi.c b/lib/utils/reset/fdt_reset_rpmi.c new file mode 100644 index 00000000..1ec4396b --- /dev/null +++ b/lib/utils/reset/fdt_reset_rpmi.c @@ -0,0 +1,141 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 Ventana Micro Systems Inc. + * + * Authors: + * Rahul Pathak <[email protected]> + */ + +#include <sbi/sbi_error.h> +#include <sbi/sbi_system.h> +#include <sbi/sbi_console.h> +#include <sbi_utils/fdt/fdt_helper.h> +#include <sbi_utils/reset/fdt_reset.h> +#include <sbi_utils/mailbox/fdt_mailbox.h> +#include <sbi_utils/mailbox/rpmi_msgprot.h> +#include <sbi_utils/mailbox/rpmi_mailbox.h> + +/* struct rpmi_sysreset: RPMI System Reset Context */ +struct rpmi_sysreset { + int warm_reset_support; + struct mbox_chan *chan; +}; + +static struct rpmi_sysreset sysreset_ctx; + +static int rpmi_system_reset_type_check(u32 reset_type) +{ + int ret; + struct rpmi_sysrst_get_reset_attributes_resp resp; + + ret = rpmi_normal_request_with_status(sysreset_ctx.chan, + RPMI_SYSRST_SRV_GET_ATTRIBUTES, &reset_type, + rpmi_u32_count(reset_type), rpmi_u32_count(reset_type), + &resp, rpmi_u32_count(resp), rpmi_u32_count(resp)); + if (ret) { + return 0; + } + + return (resp.flags & RPMI_SYSRST_ATTRS_FLAGS_RESETTYPE_MASK) ? 1 : 0; +} + +/** + * rpmi_do_system_reset: Do system reset + * + * @reset_type: RPMI System Reset Type + */ +static void rpmi_do_system_reset(u32 reset_type) +{ + int ret; + + ret = rpmi_posted_request(sysreset_ctx.chan, + RPMI_SYSRST_SRV_SYSTEM_RESET, + &reset_type, rpmi_u32_count(reset_type), + rpmi_u32_count(reset_type)); + if (ret) + sbi_printf("system reset failed [type: %d]: ret: %d\n", + reset_type, ret); +} + +/** + * rpmi_system_reset_check: Check the support for + * various reset types + * + * @type: SBI System Reset Type + * @reason: Reason for system reset + */ +static int rpmi_system_reset_check(u32 type, u32 reason) +{ + switch (type) { + case SBI_SRST_RESET_TYPE_SHUTDOWN: + case SBI_SRST_RESET_TYPE_COLD_REBOOT: + return 1; + case SBI_SRST_RESET_TYPE_WARM_REBOOT: + return sysreset_ctx.warm_reset_support; + default: + return 0; + } +} + +static void rpmi_system_reset(u32 type, u32 reason) +{ + u32 reset_type; + + switch (type) { + case SBI_SRST_RESET_TYPE_SHUTDOWN: + reset_type = RPMI_SYSRST_TYPE_SHUTDOWN; + break; + case SBI_SRST_RESET_TYPE_COLD_REBOOT: + reset_type = RPMI_SYSRST_TYPE_COLD_REBOOT; + break; + case SBI_SRST_RESET_TYPE_WARM_REBOOT: + reset_type = RPMI_SYSRST_TYPE_WARM_REBOOT; + break; + default: + return; + } + + rpmi_do_system_reset(reset_type); +} + +static struct sbi_system_reset_device rpmi_reset_dev = { + .name = "rpmi-system-reset", + .system_reset_check = rpmi_system_reset_check, + .system_reset = rpmi_system_reset, +}; + +static int rpmi_reset_init(const void *fdt, int nodeoff, + const struct fdt_match *match) +{ + int ret; + + /* If channel already available then do nothing. */ + if (sysreset_ctx.chan) + return 0; + + /* + * If channel request failed then other end does not support + * system reset group so do nothing. + */ + ret = fdt_mailbox_request_chan(fdt, nodeoff, 0, &sysreset_ctx.chan); + if (ret) + return SBI_ENODEV; + + sysreset_ctx.warm_reset_support = + rpmi_system_reset_type_check(RPMI_SYSRST_TYPE_WARM_REBOOT); + + sbi_system_reset_add_device(&rpmi_reset_dev); + + return SBI_OK; +} + +static const struct fdt_match rpmi_reset_match[] = { + { .compatible = "riscv,rpmi-system-reset" }, + {}, +}; + +struct fdt_driver fdt_reset_rpmi = { + .match_table = rpmi_reset_match, + .init = rpmi_reset_init, +}; diff --git a/lib/utils/reset/objects.mk b/lib/utils/reset/objects.mk index a84336cf..8f3774c5 100644 --- a/lib/utils/reset/objects.mk +++ b/lib/utils/reset/objects.mk @@ -29,3 +29,6 @@ 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_RPMI) += fdt_reset_rpmi +libsbiutils-objs-$(CONFIG_FDT_RESET_RPMI) += reset/fdt_reset_rpmi.o |
