aboutsummaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
authorBen Zong-You Xie <ben717@andestech.com>2025-12-29 15:19:10 +0800
committerAnup Patel <anup@brainfault.org>2026-02-11 12:03:50 +0530
commit9ffacc8ae1ca07ed36d57f887d62a65ae7a44223 (patch)
tree5afcb8ec6848672d817dffc27462c5f6f8429357 /platform
parent74434f255873d74e56cc50aa762d1caf24c099f8 (diff)
downloadopensbi-9ffacc8ae1ca07ed36d57f887d62a65ae7a44223.tar.gz
opensbi-9ffacc8ae1ca07ed36d57f887d62a65ae7a44223.tar.bz2
opensbi-9ffacc8ae1ca07ed36d57f887d62a65ae7a44223.zip
lib: utils/hsm: factor out ATCSMU code into an HSM driver
Refactor ATCSMU (System Management Unit) support by moving it from a system utility into a dedicated FDT-based HSM driver. Key changes include: - Moving the functions in lib/utils/sys/atcsmu.c into the new HSM driver - Moving hart start and stop operations on AE350 platform into the new HSM driver - Converting the assembly-based functions in sleep.S to C code for the readability - Updating the ATCWDT200 driver Signed-off-by: Ben Zong-You Xie <ben717@andestech.com> Signed-off-by: Leo Yu-Chi Liang <ycliang@andestech.com> Link: https://lore.kernel.org/r/20251229071914.1451587-2-ben717@andestech.com Signed-off-by: Anup Patel <anup@brainfault.org>
Diffstat (limited to 'platform')
-rw-r--r--platform/generic/Kconfig1
-rw-r--r--platform/generic/andes/ae350.c112
-rw-r--r--platform/generic/andes/objects.mk2
-rw-r--r--platform/generic/andes/sleep.S70
-rw-r--r--platform/generic/configs/defconfig1
-rw-r--r--platform/generic/include/andes/andes.h62
6 files changed, 72 insertions, 176 deletions
diff --git a/platform/generic/Kconfig b/platform/generic/Kconfig
index 716fab42..0c11fbd2 100644
--- a/platform/generic/Kconfig
+++ b/platform/generic/Kconfig
@@ -36,7 +36,6 @@ config PLATFORM_ALLWINNER_D1
config PLATFORM_ANDES_AE350
bool "Andes AE350 support"
- select SYS_ATCSMU
select ANDES_PMU
select ANDES_PMA
default n
diff --git a/platform/generic/andes/ae350.c b/platform/generic/andes/ae350.c
index 08080657..fa3f0368 100644
--- a/platform/generic/andes/ae350.c
+++ b/platform/generic/andes/ae350.c
@@ -1,121 +1,25 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
- * Copyright (c) 2022 Andes Technology Corporation
- *
- * Authors:
- * Yu Chien Peter Lin <peterlin@andestech.com>
+ * Copyright (c) 2025 Andes Technology Corporation
*/
-#include <platform_override.h>
-#include <andes/andes_pmu.h>
-#include <sbi_utils/fdt/fdt_helper.h>
-#include <sbi_utils/fdt/fdt_fixup.h>
-#include <sbi_utils/sys/atcsmu.h>
-#include <sbi/riscv_asm.h>
-#include <sbi/sbi_bitops.h>
-#include <sbi/sbi_error.h>
-#include <sbi/sbi_hsm.h>
-#include <sbi/sbi_ipi.h>
-#include <sbi/sbi_init.h>
#include <andes/andes.h>
+#include <andes/andes_pmu.h>
#include <andes/andes_sbi.h>
+#include <platform_override.h>
+#include <sbi_utils/fdt/fdt_helper.h>
-static struct smu_data smu = { 0 };
-extern void __ae350_enable_coherency_warmboot(void);
-extern void __ae350_disable_coherency(void);
-
-static int ae350_hart_start(u32 hartid, ulong saddr)
-{
- u32 hartindex = sbi_hartid_to_hartindex(hartid);
-
- /*
- * Don't send wakeup command when:
- * 1) boot-time
- * 2) the target hart is non-sleepable 25-series hart0
- */
- if (!sbi_init_count(hartindex) || (is_andes(25) && hartid == 0))
- return sbi_ipi_raw_send(hartindex, false);
-
- /* Write wakeup command to the sleep hart */
- smu_set_command(&smu, WAKEUP_CMD, hartid);
-
- return 0;
-}
-
-static int ae350_hart_stop(void)
-{
- int rc;
- u32 hartid = current_hartid();
-
- /**
- * For Andes AX25MP, the hart0 shares power domain with
- * L2-cache, instead of turning it off, it should fall
- * through and jump to warmboot_addr.
- */
- if (is_andes(25) && hartid == 0)
- return SBI_ENOTSUPP;
-
- if (!smu_support_sleep_mode(&smu, DEEPSLEEP_MODE, hartid))
- return SBI_ENOTSUPP;
-
- /**
- * disable all events, the current hart will be
- * woken up from reset vector when other hart
- * writes its PCS (power control slot) control
- * register
- */
- smu_set_wakeup_events(&smu, 0x0, hartid);
- smu_set_command(&smu, DEEP_SLEEP_CMD, hartid);
-
- rc = smu_set_reset_vector(&smu,
- (ulong)__ae350_enable_coherency_warmboot,
- hartid);
- if (rc)
- goto fail;
-
- __ae350_disable_coherency();
-
- wfi();
-
-fail:
- /* It should never reach here */
- sbi_hart_hang();
- return 0;
-}
-
-static const struct sbi_hsm_device andes_smu = {
- .name = "andes_smu",
- .hart_start = ae350_hart_start,
- .hart_stop = ae350_hart_stop,
-};
-
-static void ae350_hsm_device_init(const void *fdt)
-{
- int rc;
-
- rc = fdt_parse_compat_addr(fdt, (uint64_t *)&smu.addr,
- "andestech,atcsmu");
-
- if (!rc) {
- sbi_hsm_set_device(&andes_smu);
- }
-}
+extern void _start_warm(void);
-static int ae350_final_init(bool cold_boot)
+void ae350_enable_coherency_warmboot(void)
{
- if (cold_boot) {
- const void *fdt = fdt_get_address();
-
- ae350_hsm_device_init(fdt);
- }
-
- return generic_final_init(cold_boot);
+ ae350_enable_coherency();
+ _start_warm();
}
static int ae350_platform_init(const void *fdt, int nodeoff, const struct fdt_match *match)
{
- generic_platform_ops.final_init = ae350_final_init;
generic_platform_ops.extensions_init = andes_pmu_extensions_init;
generic_platform_ops.pmu_init = andes_pmu_init;
generic_platform_ops.vendor_ext_provider = andes_sbi_vendor_ext_provider;
diff --git a/platform/generic/andes/objects.mk b/platform/generic/andes/objects.mk
index f85ad481..660546c3 100644
--- a/platform/generic/andes/objects.mk
+++ b/platform/generic/andes/objects.mk
@@ -3,7 +3,7 @@
#
carray-platform_override_modules-$(CONFIG_PLATFORM_ANDES_AE350) += andes_ae350
-platform-objs-$(CONFIG_PLATFORM_ANDES_AE350) += andes/ae350.o andes/sleep.o
+platform-objs-$(CONFIG_PLATFORM_ANDES_AE350) += andes/ae350.o
carray-platform_override_modules-$(CONFIG_PLATFORM_ANDES_QILAI) += andes_qilai
platform-objs-$(CONFIG_PLATFORM_ANDES_QILAI) += andes/qilai.o
diff --git a/platform/generic/andes/sleep.S b/platform/generic/andes/sleep.S
deleted file mode 100644
index 361aff3a..00000000
--- a/platform/generic/andes/sleep.S
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2023 Andes Technology Corporation
- *
- * Authors:
- * Yu Chien Peter Lin <peterlin@andestech.com>
- */
-
-#include <sbi/riscv_encoding.h>
-#include <sbi/riscv_asm.h>
-#include <andes/andes.h>
-
- .section .text, "ax", %progbits
- .align 3
- .global __ae350_disable_coherency
-__ae350_disable_coherency:
- /* flush d-cache */
- csrw CSR_MCCTLCOMMAND, 0x6
- /* disable i/d-cache */
- csrc CSR_MCACHE_CTL, 0x3
- /* disable d-cache coherency */
- lui t1, 0x80
- csrc CSR_MCACHE_CTL, t1
- /*
- * wait for mcache_ctl.DC_COHSTA to be cleared,
- * the bit is hard-wired 0 on platforms w/o CM
- * (Coherence Manager)
- */
-check_cm_disabled:
- csrr t1, CSR_MCACHE_CTL
- srli t1, t1, 20
- andi t1, t1, 0x1
- bnez t1, check_cm_disabled
-
- ret
-
- .section .text, "ax", %progbits
- .align 3
- .global __ae350_enable_coherency
-__ae350_enable_coherency:
- /* enable d-cache coherency */
- lui t1, 0x80
- csrs CSR_MCACHE_CTL, t1
- /*
- * mcache_ctl.DC_COHEN is hard-wired 0 on platforms
- * w/o CM support
- */
- csrr t1, CSR_MCACHE_CTL
- srli t1, t1, 19
- andi t1, t1, 0x1
- beqz t1, enable_L1_cache
- /* wait for mcache_ctl.DC_COHSTA to be set */
-check_cm_enabled:
- csrr t1, CSR_MCACHE_CTL
- srli t1, t1, 20
- andi t1, t1, 0x1
- beqz t1, check_cm_enabled
-enable_L1_cache:
- /* enable i/d-cache */
- csrs CSR_MCACHE_CTL, 0x3
-
- ret
-
- .section .text, "ax", %progbits
- .align 3
- .global __ae350_enable_coherency_warmboot
-__ae350_enable_coherency_warmboot:
- call ra, __ae350_enable_coherency
- j _start_warm
diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
index aab1560f..d85da930 100644
--- a/platform/generic/configs/defconfig
+++ b/platform/generic/configs/defconfig
@@ -23,6 +23,7 @@ CONFIG_FDT_GPIO_DESIGNWARE=y
CONFIG_FDT_GPIO_SIFIVE=y
CONFIG_FDT_GPIO_STARFIVE=y
CONFIG_FDT_HSM=y
+CONFIG_FDT_HSM_ANDES_ATCSMU=y
CONFIG_FDT_HSM_RPMI=y
CONFIG_FDT_HSM_SIFIVE_TMC0=y
CONFIG_FDT_I2C=y
diff --git a/platform/generic/include/andes/andes.h b/platform/generic/include/andes/andes.h
index bfedf034..1b589392 100644
--- a/platform/generic/include/andes/andes.h
+++ b/platform/generic/include/andes/andes.h
@@ -6,6 +6,9 @@
#ifndef _RISCV_ANDES_H
#define _RISCV_ANDES_H
+#include <sbi/sbi_bitops.h>
+#include <sbi/sbi_scratch.h>
+
/* Memory and Miscellaneous Registers */
#define CSR_MCACHE_CTL 0x7ca
#define CSR_MCCTLCOMMAND 0x7cc
@@ -43,13 +46,23 @@
#define MMSC_IOCP_OFFSET 47
#define MMSC_IOCP_MASK (1ULL << MMSC_IOCP_OFFSET)
+#define MCACHE_CTL_IC_EN_MASK BIT(0)
+#define MCACHE_CTL_DC_EN_MASK BIT(1)
#define MCACHE_CTL_CCTL_SUEN_OFFSET 8
#define MCACHE_CTL_CCTL_SUEN_MASK (1 << MCACHE_CTL_CCTL_SUEN_OFFSET)
+#define MCACHE_CTL_DC_COHEN_MASK BIT(19)
+#define MCACHE_CTL_DC_COHSTA_MASK BIT(20)
/* Performance monitor */
#define MMSC_CFG_PMNDS_MASK (1 << 15)
#define MIP_PMOVI (1 << 18)
+/* Cache control commands */
+#define MCCTLCOMMAND_L1D_WBINVAL_ALL 6
+
+/* AE350 platform specific sleep types */
+#define SBI_SUSP_AE350_LIGHT_SLEEP SBI_SUSP_PLATFORM_SLEEP_START
+
#ifndef __ASSEMBLER__
#define is_andes(series) \
@@ -67,4 +80,53 @@
#endif /* __ASSEMBLER__ */
+void ae350_enable_coherency_warmboot(void);
+
+/*
+ * On Andes 4X-series CPUs, disabling the L1 data cache causes the CPU to fetch
+ * data directly from RAM. However, L1 cache flushes write data back to the
+ * Last Level Cache (LLC). This discrepancy can lead to return address
+ * corruption on the stack. To prevent this, the following functions must
+ * be inlined.
+ */
+static inline void ae350_disable_coherency(void)
+{
+ /*
+ * To disable cache coherency of a core in AE350 platform, follow below steps:
+ *
+ * 1) Disable I/D-Cache
+ * 2) Write back and invalidate D-Cache
+ * 3) Disable D-Cache coherency
+ * 4) Wait for D-Cache disengaged from the coherence management
+ */
+ csr_clear(CSR_MCACHE_CTL, MCACHE_CTL_IC_EN_MASK | MCACHE_CTL_DC_EN_MASK);
+ csr_write(CSR_MCCTLCOMMAND, MCCTLCOMMAND_L1D_WBINVAL_ALL);
+ csr_clear(CSR_MCACHE_CTL, MCACHE_CTL_DC_COHEN_MASK);
+ while (csr_read(CSR_MCACHE_CTL) & MCACHE_CTL_DC_COHSTA_MASK)
+ ;
+}
+
+static inline void ae350_enable_coherency(void)
+{
+ /*
+ * To enable cache coherency of a core in AE350 platform, follow below steps:
+ *
+ * 1) Enable D-Cache coherency
+ * 2) Wait for D-Cache engaging in the coherence management
+ * 3) Enable I/D-Cache
+ */
+ csr_set(CSR_MCACHE_CTL, MCACHE_CTL_DC_COHEN_MASK);
+
+ /*
+ * mcache_ctl.DC_COHEN is hardwired to 0 if there is no coherence
+ * manager. In such situation, just enable the I/D-Cache to prevent
+ * permanently being stuck in the while loop.
+ */
+ if (csr_read(CSR_MCACHE_CTL) & MCACHE_CTL_DC_COHEN_MASK)
+ while (!(csr_read(CSR_MCACHE_CTL) & MCACHE_CTL_DC_COHSTA_MASK))
+ ;
+
+ csr_set(CSR_MCACHE_CTL, MCACHE_CTL_IC_EN_MASK | MCACHE_CTL_DC_EN_MASK);
+}
+
#endif /* _RISCV_ANDES_H */