diff options
| author | Ben Zong-You Xie <ben717@andestech.com> | 2025-12-29 15:19:10 +0800 |
|---|---|---|
| committer | Anup Patel <anup@brainfault.org> | 2026-02-11 12:03:50 +0530 |
| commit | 9ffacc8ae1ca07ed36d57f887d62a65ae7a44223 (patch) | |
| tree | 5afcb8ec6848672d817dffc27462c5f6f8429357 /platform | |
| parent | 74434f255873d74e56cc50aa762d1caf24c099f8 (diff) | |
| download | opensbi-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/Kconfig | 1 | ||||
| -rw-r--r-- | platform/generic/andes/ae350.c | 112 | ||||
| -rw-r--r-- | platform/generic/andes/objects.mk | 2 | ||||
| -rw-r--r-- | platform/generic/andes/sleep.S | 70 | ||||
| -rw-r--r-- | platform/generic/configs/defconfig | 1 | ||||
| -rw-r--r-- | platform/generic/include/andes/andes.h | 62 |
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 */ |
