diff options
author | Rahul Pathak <rpathak@ventanamicro.com> | 2024-08-06 10:24:19 +0530 |
---|---|---|
committer | Anup Patel <anup@brainfault.org> | 2024-12-06 09:26:27 +0530 |
commit | 6a26726e08e4d1e23b2e6cce073689ecdabf9291 (patch) | |
tree | 86fa158485a31bf094264bf04c9e16ed602b55a9 | |
parent | 91f46fb47eefb872a7981935fbcc125226e93eca (diff) | |
download | opensbi-6a26726e08e4d1e23b2e6cce073689ecdabf9291.zip opensbi-6a26726e08e4d1e23b2e6cce073689ecdabf9291.tar.gz opensbi-6a26726e08e4d1e23b2e6cce073689ecdabf9291.tar.bz2 |
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 <rpathak@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
-rw-r--r-- | include/sbi_utils/mailbox/rpmi_msgprot.h | 27 | ||||
-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 | ||||
-rw-r--r-- | platform/generic/configs/defconfig | 1 |
5 files changed, 177 insertions, 0 deletions
diff --git a/include/sbi_utils/mailbox/rpmi_msgprot.h b/include/sbi_utils/mailbox/rpmi_msgprot.h index f9f6544..31c3034 100644 --- a/include/sbi_utils/mailbox/rpmi_msgprot.h +++ b/include/sbi_utils/mailbox/rpmi_msgprot.h @@ -196,6 +196,7 @@ struct rpmi_message_args { enum rpmi_servicegroup_id { RPMI_SRVGRP_ID_MIN = 0, RPMI_SRVGRP_BASE = 0x0001, + RPMI_SRVGRP_SYSTEM_RESET = 0x0002, RPMI_SRVGRP_ID_MAX_COUNT, /* Reserved range for service groups */ @@ -252,4 +253,30 @@ struct rpmi_base_get_platform_info_resp { char plat_info[]; }; +/** RPMI System Reset ServiceGroup Service IDs */ +enum rpmi_system_reset_service_id { + RPMI_SYSRST_SRV_ENABLE_NOTIFICATION = 0x01, + RPMI_SYSRST_SRV_GET_ATTRIBUTES = 0x02, + RPMI_SYSRST_SRV_SYSTEM_RESET = 0x03, + RPMI_SYSRST_SRV_ID_MAX_COUNT, +}; + +/** RPMI System Reset types */ +enum rpmi_sysrst_reset_type { + RPMI_SYSRST_TYPE_SHUTDOWN = 0x0, + RPMI_SYSRST_TYPE_COLD_REBOOT = 0x1, + RPMI_SYSRST_TYPE_WARM_REBOOT = 0x2, + RPMI_SYSRST_TYPE_MAX, +}; + +#define RPMI_SYSRST_ATTRS_FLAGS_RESETTYPE_POS (1) +#define RPMI_SYSRST_ATTRS_FLAGS_RESETTYPE_MASK \ + (1U << RPMI_SYSRST_ATTRS_FLAGS_RESETTYPE_POS) + +/** Response for system reset attributes */ +struct rpmi_sysrst_get_reset_attributes_resp { + s32 status; + u32 flags; +}; + #endif /* !__RPMI_MSGPROT_H__ */ diff --git a/lib/utils/reset/Kconfig b/lib/utils/reset/Kconfig index 6c077fe..68e6671 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 0000000..1ec4396 --- /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 <rpathak@ventanamicro.com> + */ + +#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 a84336c..8f3774c 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 diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig index 233a9a8..48f8df4 100644 --- a/platform/generic/configs/defconfig +++ b/platform/generic/configs/defconfig @@ -29,6 +29,7 @@ CONFIG_FDT_RESET=y CONFIG_FDT_RESET_ATCWDT200=y CONFIG_FDT_RESET_GPIO=y CONFIG_FDT_RESET_HTIF=y +CONFIG_FDT_RESET_RPMI=y CONFIG_FDT_RESET_SUNXI_WDT=y CONFIG_FDT_RESET_SG2042_HWMON_MCU=y CONFIG_FDT_RESET_SYSCON=y |