diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 05dcd84465380..5d3e85450f195 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -526,5 +526,6 @@ config RISCV_NO_MTVAL_ON_FP_TRAP to handle FP exceptions. rsource "Kconfig.isa" +rsource "core/Kconfig" endmenu diff --git a/arch/riscv/core/CMakeLists.txt b/arch/riscv/core/CMakeLists.txt index abd9d4504134c..b2bf26dbf39a9 100644 --- a/arch/riscv/core/CMakeLists.txt +++ b/arch/riscv/core/CMakeLists.txt @@ -42,3 +42,5 @@ if(CONFIG_GEN_SW_ISR_TABLE) zephyr_linker_sources(RODATA swi_tables.ld) endif() endif() + +add_subdirectory_ifdef(CONFIG_XUANTIE xuantie) diff --git a/arch/riscv/core/Kconfig b/arch/riscv/core/Kconfig new file mode 100644 index 0000000000000..c3bfe4158a5ac --- /dev/null +++ b/arch/riscv/core/Kconfig @@ -0,0 +1,11 @@ +# RISC-V cores configuration options + +# Copyright (c) 2025 MASSDRIVER EI (massdriver.space) +# SPDX-License-Identifier: Apache-2.0 + +config XUANTIE + bool + help + This option signifies the use of a CPU of the XuanTie RISC-V family + +rsource "xuantie/Kconfig" diff --git a/arch/riscv/core/xuantie/CMakeLists.txt b/arch/riscv/core/xuantie/CMakeLists.txt new file mode 100644 index 0000000000000..38a4c403765a5 --- /dev/null +++ b/arch/riscv/core/xuantie/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/cache.h) + +zephyr_library() + +zephyr_library_sources_ifdef(CONFIG_CACHE_XTHEADCMO cache_xtheadcmo.c) +zephyr_library_sources_ifdef(CONFIG_CACHE_XTHEADCMO_E907 cache_xtheadcmo_e907.c) diff --git a/arch/riscv/core/xuantie/Kconfig b/arch/riscv/core/xuantie/Kconfig new file mode 100644 index 0000000000000..bb0cf7b0b004c --- /dev/null +++ b/arch/riscv/core/xuantie/Kconfig @@ -0,0 +1,48 @@ +# Copyright (c) 2025 MASSDRIVER EI (massdriver.space) +# SPDX-License-Identifier: Apache-2.0 + +config XUANTIE_E907 + bool + select XUANTIE + select GEN_IRQ_VECTOR_TABLE + select INCLUDE_RESET_VECTOR + select RISCV_HAS_CLIC + select RISCV_MACHINE_TIMER + select RISCV_PRIVILEGED + select RISCV_ISA_RV32I + select RISCV_ISA_EXT_M + select RISCV_ISA_EXT_A + select RISCV_ISA_EXT_C + select RISCV_ISA_EXT_ZICSR + select RISCV_ISA_EXT_ZIFENCEI + select RISCV_VECTORED_MODE + +if XUANTIE + +config CACHE_XTHEADCMO + bool + default y + select CACHE_MANAGEMENT + select CPU_HAS_ICACHE + help + This option enables cache support for XuanTie family of CPUs using the XTHeadCmo extension + +if CACHE_XTHEADCMO + +config DCACHE_LINE_SIZE + default 32 + +config ICACHE_LINE_SIZE + default 32 + +config CACHE_XTHEADCMO_E907 + bool + default y + depends on XUANTIE_E907 + select CPU_HAS_DCACHE + help + This option enables the additional XTHeadCmo cache functions for the E907 cores + +endif # CACHE_XTHEADCMO + +endif # XUANTIE diff --git a/arch/riscv/core/xuantie/cache_xtheadcmo.c b/arch/riscv/core/xuantie/cache_xtheadcmo.c new file mode 100644 index 0000000000000..1a5cf7ecb2626 --- /dev/null +++ b/arch/riscv/core/xuantie/cache_xtheadcmo.c @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2025 MASSDRIVER EI (massdriver.space) + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +int arch_dcache_invd_all(void) +{ + __asm__ volatile ( + "fence\n" + /* th.dcache.iall */ + ".insn 0x20000B\n" + "fence\n" + ); + + return 0; +} + +static void arch_cache_invalidate_dcache_line(uintptr_t address_in) +{ + register uintptr_t address __asm__("a3") = address_in; + + __asm__ volatile ( + /* th.dcache.ipa a3*/ + ".insn 0x2A6800B\n" + : + : "r"(address) + ); +} + +int arch_dcache_invd_range(void *addr_in, size_t size) +{ + uintptr_t addr = (uintptr_t)addr_in; + + __asm__ volatile ( + "fence\n" + ); + for (uintptr_t i = addr; i < addr + size; i += CONFIG_DCACHE_LINE_SIZE) { + arch_cache_invalidate_dcache_line(i); + } + __asm__ volatile ( + "fence\n" + ); + + return 0; +} + +int arch_icache_invd_all(void) +{ + __asm__ volatile ( + "fence\n" + "fence.i\n" + /* th.icache.iall */ + ".insn 0x100000B\n" + "fence\n" + "fence.i\n" + ); + + return 0; +} + +static void arch_cache_invalidate_icache_line(uintptr_t address_in) +{ + register uintptr_t address __asm__("a3") = address_in; + + __asm__ volatile ( + /* th.icache.ipa a3*/ + ".insn 0x386800B\n" + : + : "r"(address) + ); +} + +int arch_icache_invd_range(void *addr_in, size_t size) +{ + uintptr_t addr = (uintptr_t)addr_in; + + __asm__ volatile ( + "fence\n" + "fence.i\n" + ); + for (uintptr_t i = addr; i < addr + size; i += CONFIG_ICACHE_LINE_SIZE) { + arch_cache_invalidate_icache_line(i); + } + __asm__ volatile ( + "fence\n" + "fence.i\n" + ); + + return 0; +} + +int arch_dcache_flush_all(void) +{ + __asm__ volatile ( + "fence\n" + /* th.dcache.call */ + ".insn 0x10000B\n" + "fence\n" + ); + + return 0; +} + +static void arch_cache_clean_dcache_line(uintptr_t address_in) +{ + register uintptr_t address __asm__("a3") = address_in; + + __asm__ volatile ( + /* th.dcache.cpa a3*/ + ".insn 0x296800B\n" + : + : "r"(address) + ); +} + +int arch_dcache_flush_range(void *addr_in, size_t size) +{ + uintptr_t addr = (uintptr_t)addr_in; + + __asm__ volatile ( + "fence\n" + ); + for (uintptr_t i = addr; i < addr + size; i += CONFIG_DCACHE_LINE_SIZE) { + arch_cache_clean_dcache_line(i); + } + __asm__ volatile ( + "fence\n" + ); + + return 0; +} + +int arch_dcache_flush_and_invd_all(void) +{ + __asm__ volatile ( + "fence\n" + /* th.dcache.ciall */ + ".insn 0x30000B\n" + "fence\n" + ); + + return 0; +} + +static void arch_cache_clean_invalidate_dcache_line(uintptr_t address_in) +{ + register uintptr_t address __asm__("a3") = address_in; + + __asm__ volatile ( + /* th.dcache.cipa a3*/ + ".insn 0x2B6800B\n" + : + : "r"(address) + ); +} + +int arch_dcache_flush_and_invd_range(void *addr_in, size_t size) +{ + uintptr_t addr = (uintptr_t)addr_in; + + __asm__ volatile ( + "fence\n" + ); + for (uintptr_t i = addr; i < addr + size; i += CONFIG_DCACHE_LINE_SIZE) { + arch_cache_clean_invalidate_dcache_line(i); + } + __asm__ volatile ( + "fence\n" + ); + + return 0; +} + +int arch_icache_flush_all(void) +{ + return -ENOTSUP; +} + +int arch_icache_flush_and_invd_all(void) +{ + return -ENOTSUP; +} + +int arch_icache_flush_range(void *addr, size_t size) +{ + ARG_UNUSED(addr); + ARG_UNUSED(size); + + return -ENOTSUP; +} + +int arch_icache_flush_and_invd_range(void *addr, size_t size) +{ + ARG_UNUSED(addr); + ARG_UNUSED(size); + + return -ENOTSUP; +} diff --git a/arch/riscv/core/xuantie/cache_xtheadcmo_e907.c b/arch/riscv/core/xuantie/cache_xtheadcmo_e907.c new file mode 100644 index 0000000000000..424d3003cddfc --- /dev/null +++ b/arch/riscv/core/xuantie/cache_xtheadcmo_e907.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2025 MASSDRIVER EI (massdriver.space) + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +/* "a Hardware CSR" */ +#define THEAD_MHCR "0x7C1" + +void arch_icache_enable(void) +{ + uint32_t tmp; + + __asm__ volatile ( + "fence\n" + "fence.i\n" + /* th.icache.iall */ + ".insn 0x100000B\n" + ); + __asm__ volatile( + "csrr %0, " THEAD_MHCR + : "=r"(tmp)); + tmp |= (1 << 0); + __asm__ volatile( + "csrw " THEAD_MHCR ", %0" + : + : "r"(tmp)); + __asm__ volatile ( + "fence\n" + "fence.i\n" + ); +} + +void arch_dcache_enable(void) +{ + uint32_t tmp; + + __asm__ volatile ( + "fence\n" + "fence.i\n" + /* th.dcache.iall */ + ".insn 0x20000B\n" + ); + __asm__ volatile( + "csrr %0, " THEAD_MHCR + : "=r"(tmp)); + tmp |= (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4); + __asm__ volatile( + "csrw " THEAD_MHCR ", %0" + : + : "r"(tmp)); + __asm__ volatile ( + "fence\n" + "fence.i\n" + ); +} + +void arch_icache_disable(void) +{ + uint32_t tmp; + + __asm__ volatile ( + "fence\n" + "fence.i\n" + /* th.icache.iall */ + ".insn 0x100000B\n" + ); + __asm__ volatile( + "csrr %0, " THEAD_MHCR + : "=r"(tmp)); + tmp &= ~(1 << 0); + __asm__ volatile( + "csrw " THEAD_MHCR ", %0" + : + : "r"(tmp)); + __asm__ volatile ( + "fence\n" + "fence.i\n" + ); +} + +void arch_dcache_disable(void) +{ + uint32_t tmp; + + __asm__ volatile ( + "fence\n" + "fence.i\n" + /* th.dcache.iall */ + ".insn 0x20000B\n" + ); + __asm__ volatile( + "csrr %0, " THEAD_MHCR + : "=r"(tmp)); + tmp &= ~((1 << 1) | (1 << 2) | (1 << 3) | (1 << 4)); + __asm__ volatile( + "csrw " THEAD_MHCR ", %0" + : + : "r"(tmp)); + __asm__ volatile ( + "fence\n" + "fence.i\n" + ); +} diff --git a/soc/bflb/bl61x/CMakeLists.txt b/soc/bflb/bl61x/CMakeLists.txt index 9760222051f90..73622c1849b4f 100644 --- a/soc/bflb/bl61x/CMakeLists.txt +++ b/soc/bflb/bl61x/CMakeLists.txt @@ -7,6 +7,9 @@ zephyr_sources(soc.c) set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/riscv/common/linker.ld CACHE INTERNAL "") +zephyr_code_relocate( + FILES ${ZEPHYR_BASE}/arch/riscv/core/xuantie/cache_xtheadcmo.c LOCATION ITCM NOKEEP) + zephyr_code_relocate_ifdef(CONFIG_UART_BFLB LIBRARY drivers__serial LOCATION ITCM NOKEEP) zephyr_code_relocate_ifdef(CONFIG_RISCV_MACHINE_TIMER LIBRARY drivers__timer LOCATION ITCM NOKEEP) zephyr_code_relocate_ifdef(CONFIG_PINCTRL_BFLB LIBRARY drivers__pinctrl LOCATION ITCM NOKEEP) diff --git a/soc/bflb/bl61x/Kconfig b/soc/bflb/bl61x/Kconfig index 6030a27709386..bf311619847fa 100644 --- a/soc/bflb/bl61x/Kconfig +++ b/soc/bflb/bl61x/Kconfig @@ -6,22 +6,13 @@ config SOC_SERIES_BL61X select CLOCK_CONTROL select CODE_DATA_RELOCATION select CPU_HAS_FPU + select DCACHE select FLOAT_HARD select FPU - select GEN_IRQ_VECTOR_TABLE - select INCLUDE_RESET_VECTOR + select ICACHE select RISCV - select RISCV_HAS_CLIC - select RISCV_MACHINE_TIMER - select RISCV_PRIVILEGED - select RISCV_ISA_RV32I - select RISCV_ISA_EXT_M - select RISCV_ISA_EXT_A select RISCV_ISA_EXT_F - select RISCV_ISA_EXT_C - select RISCV_ISA_EXT_ZICSR - select RISCV_ISA_EXT_ZIFENCEI - select RISCV_VECTORED_MODE select SOC_EARLY_INIT_HOOK select SYSCON select XIP + select XUANTIE_E907 diff --git a/soc/bflb/bl61x/soc.c b/soc/bflb/bl61x/soc.c index 3dbf109cbcf03..26a13bdb52e70 100644 --- a/soc/bflb/bl61x/soc.c +++ b/soc/bflb/bl61x/soc.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -107,76 +108,6 @@ void system_BOD_init(void) sys_write32(tmp, HBN_BASE + HBN_BOR_CFG_OFFSET); } -static void clean_dcache(void) -{ - __asm__ volatile ( - "fence\n" - /* th.dcache.call*/ - ".insn 0x10000B\n" - "fence\n" - ); -} - -static void clean_icache(void) -{ - __asm__ volatile ( - "fence\n" - "fence.i\n" - /* th.icache.iall */ - ".insn 0x100000B\n" - "fence\n" - "fence.i\n" - ); -} - -static void enable_icache(void) -{ - uint32_t tmp; - - __asm__ volatile ( - "fence\n" - "fence.i\n" - /* th.icache.iall */ - ".insn 0x100000B\n" - ); - __asm__ volatile( - "csrr %0, 0x7C1" - : "=r"(tmp)); - tmp |= (1 << 0); - __asm__ volatile( - "csrw 0x7C1, %0" - : - : "r"(tmp)); - __asm__ volatile ( - "fence\n" - "fence.i\n" - ); -} - -static void enable_dcache(void) -{ - uint32_t tmp; - - __asm__ volatile ( - "fence\n" - "fence.i\n" - /* th.dcache.iall */ - ".insn 0x20000B\n" - ); - __asm__ volatile( - "csrr %0, 0x7C1" - : "=r"(tmp)); - tmp |= (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4); - __asm__ volatile( - "csrw 0x7C1, %0" - : - : "r"(tmp)); - __asm__ volatile ( - "fence\n" - "fence.i\n" - ); -} - static void enable_branchpred(bool yes) { uint32_t tmp; @@ -249,6 +180,17 @@ static void disable_interrupt_autostacking(void) : "r"(tmp)); } +void arch_cache_init(void) +{ + enable_thead_isa_ext(); + set_thead_enforce_aligned(false); + sys_cache_data_enable(); + enable_branchpred(true); + sys_cache_instr_enable(); + disable_interrupt_autostacking(); + sys_cache_data_flush_and_invd_all(); + sys_cache_instr_invd_all(); +} void soc_early_init_hook(void) { @@ -263,18 +205,6 @@ void soc_early_init_hook(void) sys_write32((1 << 5), PDS_BASE + PDS_USB_CTL_OFFSET); sys_write32(0, PDS_BASE + PDS_USB_PHY_CTRL_OFFSET); - enable_thead_isa_ext(); - set_thead_enforce_aligned(false); - enable_dcache(); - /* branch prediction can cause major slowdowns (250ms -> 2 seconds) - * in some applications - */ - enable_branchpred(true); - enable_icache(); - disable_interrupt_autostacking(); - clean_dcache(); - clean_icache(); - /* reset uart signals */ sys_write32(0xffffffffU, GLB_BASE + GLB_UART_CFG1_OFFSET); sys_write32(0x0000ffffU, GLB_BASE + GLB_UART_CFG2_OFFSET);