summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorYu Chien Peter Lin <peterlin@andestech.com>2023-01-20 06:05:10 +0300
committerAnup Patel <anup@brainfault.org>2023-01-22 15:02:50 +0300
commit9c4eb3521e515603671198295f2c7d5114e4c601 (patch)
treeaad9bfd5515d8281d791104769b7deabfe2d4329 /lib
parentb1818ee244adae3c07fcd4494873a74f7aaeb21a (diff)
downloadopensbi-9c4eb3521e515603671198295f2c7d5114e4c601.tar.xz
lib: utils: atcsmu: Add Andes System Management Unit support
This patch adds atcsmu support for Andes AE350 platforms. The SMU provides system management capabilities, including clock, reset and power control based on power domain partitions. Signed-off-by: Yu Chien Peter Lin <peterlin@andestech.com> Reviewed-by: Anup Patel <anup@brainfault.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/utils/sys/Kconfig4
-rw-r--r--lib/utils/sys/atcsmu.c92
-rw-r--r--lib/utils/sys/objects.mk1
3 files changed, 97 insertions, 0 deletions
diff --git a/lib/utils/sys/Kconfig b/lib/utils/sys/Kconfig
index ee85b1a..76190f8 100644
--- a/lib/utils/sys/Kconfig
+++ b/lib/utils/sys/Kconfig
@@ -2,6 +2,10 @@
menu "System Device Support"
+config SYS_ATCSMU
+ bool "Andes System Management Unit (SMU) support"
+ default n
+
config SYS_HTIF
bool "Host transfere interface (HTIF) support"
default n
diff --git a/lib/utils/sys/atcsmu.c b/lib/utils/sys/atcsmu.c
new file mode 100644
index 0000000..8ddd88d
--- /dev/null
+++ b/lib/utils/sys/atcsmu.c
@@ -0,0 +1,92 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Andes Technology Corporation
+ *
+ * Authors:
+ * Yu Chien Peter Lin <peterlin@andestech.com>
+ */
+
+#include <sbi_utils/sys/atcsmu.h>
+#include <sbi/riscv_io.h>
+#include <sbi/sbi_console.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_bitops.h>
+
+inline int smu_set_wakeup_events(struct smu_data *smu, u32 events, u32 hartid)
+{
+ if (smu) {
+ writel(events, (void *)(smu->addr + PCSm_WE_OFFSET(hartid)));
+ return 0;
+ } else
+ return SBI_EINVAL;
+}
+
+inline bool smu_support_sleep_mode(struct smu_data *smu, u32 sleep_mode,
+ u32 hartid)
+{
+ u32 pcs_cfg;
+
+ if (!smu) {
+ sbi_printf("%s(): Failed to access smu_data\n", __func__);
+ return false;
+ }
+
+ pcs_cfg = readl((void *)(smu->addr + PCSm_CFG_OFFSET(hartid)));
+
+ switch (sleep_mode) {
+ case LIGHTSLEEP_MODE:
+ if (EXTRACT_FIELD(pcs_cfg, PCS_CFG_LIGHT_SLEEP) == 0) {
+ sbi_printf(
+ "SMU: hart%d (PCS%d) does not support light sleep mode\n",
+ hartid, hartid + 3);
+ return false;
+ }
+ break;
+ case DEEPSLEEP_MODE:
+ if (EXTRACT_FIELD(pcs_cfg, PCS_CFG_DEEP_SLEEP) == 0) {
+ sbi_printf(
+ "SMU: hart%d (PCS%d) does not support deep sleep mode\n",
+ hartid, hartid + 3);
+ return false;
+ }
+ break;
+ }
+
+ return true;
+}
+
+inline int smu_set_command(struct smu_data *smu, u32 pcs_ctl, u32 hartid)
+{
+ if (smu) {
+ writel(pcs_ctl, (void *)(smu->addr + PCSm_CTL_OFFSET(hartid)));
+ return 0;
+ } else
+ return SBI_EINVAL;
+}
+
+inline int smu_set_reset_vector(struct smu_data *smu, ulong wakeup_addr,
+ u32 hartid)
+{
+ u32 vec_lo, vec_hi;
+ u64 reset_vector;
+
+ if (!smu)
+ return SBI_EINVAL;
+
+ writel(wakeup_addr, (void *)(smu->addr + HARTn_RESET_VEC_LO(hartid)));
+ writel((u64)wakeup_addr >> 32,
+ (void *)(smu->addr + HARTn_RESET_VEC_HI(hartid)));
+
+ vec_lo = readl((void *)(smu->addr + HARTn_RESET_VEC_LO(hartid)));
+ vec_hi = readl((void *)(smu->addr + HARTn_RESET_VEC_HI(hartid)));
+ reset_vector = ((u64)vec_hi << 32) | vec_lo;
+
+ if (reset_vector != (u64)wakeup_addr) {
+ sbi_printf(
+ "hard%d (PCS%d): Failed to program the reset vector.\n",
+ hartid, hartid + 3);
+ return SBI_EFAIL;
+ } else
+ return 0;
+}
diff --git a/lib/utils/sys/objects.mk b/lib/utils/sys/objects.mk
index 9f67aee..03d6740 100644
--- a/lib/utils/sys/objects.mk
+++ b/lib/utils/sys/objects.mk
@@ -9,3 +9,4 @@
libsbiutils-objs-$(CONFIG_SYS_HTIF) += sys/htif.o
libsbiutils-objs-$(CONFIG_SYS_SIFIVE_TEST) += sys/sifive_test.o
+libsbiutils-objs-$(CONFIG_SYS_ATCSMU) += sys/atcsmu.o