summaryrefslogtreecommitdiff
path: root/lib/utils
diff options
context:
space:
mode:
authorRahul Pathak <[email protected]>2024-08-06 10:24:19 +0530
committerAnup Patel <[email protected]>2024-12-06 09:26:27 +0530
commit6a26726e08e4d1e23b2e6cce073689ecdabf9291 (patch)
tree86fa158485a31bf094264bf04c9e16ed602b55a9 /lib/utils
parent91f46fb47eefb872a7981935fbcc125226e93eca (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/Kconfig5
-rw-r--r--lib/utils/reset/fdt_reset_rpmi.c141
-rw-r--r--lib/utils/reset/objects.mk3
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