Skip to content

Commit 9bbc2e5

Browse files
committed
drivers: cache: Introduce xtheadcmo cache driver
Introduce xtheadcmo risc-v extenstion cache management functions Signed-off-by: Camille BAUD <[email protected]>
1 parent 6b2c47a commit 9bbc2e5

File tree

4 files changed

+262
-0
lines changed

4 files changed

+262
-0
lines changed

drivers/cache/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ zephyr_library_sources_ifdef(CONFIG_USERSPACE cache_handlers.c)
1111
zephyr_library_sources_ifdef(CONFIG_CACHE_NRF_CACHE cache_nrf.c)
1212
zephyr_library_sources_ifdef(CONFIG_CACHE_NXP_XCACHE cache_nxp_xcache.c)
1313
zephyr_library_sources_ifdef(CONFIG_CACHE_STM32 cache_stm32.c)
14+
zephyr_library_sources_ifdef(CONFIG_CACHE_XTHEADCMO cache_xtheadcmo.c)

drivers/cache/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,6 @@ source "drivers/cache/Kconfig.nrf"
2323
source "drivers/cache/Kconfig.andes"
2424
source "drivers/cache/Kconfig.nxp_xcache"
2525
source "drivers/cache/Kconfig.stm32"
26+
source "drivers/cache/Kconfig.xuantie"
2627

2728
endif # CACHE

drivers/cache/Kconfig.xuantie

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Copyright (c) 2025 MASSDRIVER EI <massdriver.space>
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config CACHE_XTHEADCMO
5+
bool "Xuantie T-HEAD xtheadcmo extension cache control driver"
6+
default y
7+
select CACHE_HAS_DRIVER
8+
depends on DT_HAS_XUANTIE_XTHEADCMO_ENABLED
9+
help
10+
This option enables the CACHE driver for xuantie cores using the xtheadcmo extension

drivers/cache/cache_xtheadcmo.c

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
/*
2+
* Copyright (c) 2025 MASSDRIVER EI (massdriver.space)
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/init.h>
8+
#include <zephyr/kernel.h>
9+
#include <zephyr/drivers/cache.h>
10+
#include <zephyr/logging/log.h>
11+
12+
#define DT_DRV_COMPAT xuantie_xtheadcmo
13+
14+
/* This driver defines a driver to access the xtheadcmo RISC-V extension's
15+
* cache management functionalities.
16+
* Some functions are defined as weak symbol to enable overwriting them with functions defined
17+
* for the specific core and setup of the platform it is used with, as the bits used to enable
18+
* and disable functionalities may be different for each implementation.
19+
*/
20+
21+
LOG_MODULE_REGISTER(cache_xtheadcmo, CONFIG_CACHE_LOG_LEVEL);
22+
23+
struct cache_config {
24+
uint32_t icache_line_size;
25+
uint32_t dcache_line_size;
26+
};
27+
28+
static struct cache_config cache_cfg = {
29+
.icache_line_size = DT_INST_PROP(0, icache_line_size),
30+
.dcache_line_size = DT_INST_PROP(0, dcache_line_size),
31+
};
32+
33+
void __weak cache_data_enable(void)
34+
{
35+
/* Platform specific */
36+
}
37+
38+
void __weak cache_data_disable(void)
39+
{
40+
/* Platform specific */
41+
}
42+
43+
void __weak cache_instr_enable(void)
44+
{
45+
/* Platform specific */
46+
}
47+
48+
void __weak cache_instr_disable(void)
49+
{
50+
/* Platform specific */
51+
}
52+
53+
int cache_data_invd_all(void)
54+
{
55+
__asm__ volatile (
56+
"fence\n"
57+
/* th.dcache.iall */
58+
".insn 0x20000B\n"
59+
"fence\n"
60+
);
61+
62+
return 0;
63+
}
64+
65+
static void cache_invalidate_dcache_line(uintptr_t address_in)
66+
{
67+
register uintptr_t address __asm__("a3") = address_in;
68+
69+
__asm__ volatile (
70+
/* th.dcache.ipa a3*/
71+
".insn 0x2A6800B\n"
72+
:
73+
: "r"(address)
74+
);
75+
}
76+
77+
int cache_data_invd_range(void *addr_in, size_t size)
78+
{
79+
uintptr_t addr = (uintptr_t)addr_in;
80+
81+
__asm__ volatile (
82+
"fence\n"
83+
);
84+
for (uintptr_t i = addr; i < addr + size; i += cache_cfg.dcache_line_size) {
85+
cache_invalidate_dcache_line(i);
86+
}
87+
__asm__ volatile (
88+
"fence\n"
89+
);
90+
91+
return 0;
92+
}
93+
94+
int cache_instr_invd_all(void)
95+
{
96+
__asm__ volatile (
97+
"fence\n"
98+
"fence.i\n"
99+
/* th.icache.iall */
100+
".insn 0x100000B\n"
101+
"fence\n"
102+
"fence.i\n"
103+
);
104+
105+
return 0;
106+
}
107+
108+
static void cache_invalidate_icache_line(uintptr_t address_in)
109+
{
110+
register uintptr_t address __asm__("a3") = address_in;
111+
112+
__asm__ volatile (
113+
/* th.icache.ipa a3*/
114+
".insn 0x386800B\n"
115+
:
116+
: "r"(address)
117+
);
118+
}
119+
120+
int cache_instr_invd_range(void *addr_in, size_t size)
121+
{
122+
uintptr_t addr = (uintptr_t)addr_in;
123+
124+
__asm__ volatile (
125+
"fence\n"
126+
"fence.i\n"
127+
);
128+
for (uintptr_t i = addr; i < addr + size; i += cache_cfg.icache_line_size) {
129+
cache_invalidate_icache_line(i);
130+
}
131+
__asm__ volatile (
132+
"fence\n"
133+
"fence.i\n"
134+
);
135+
136+
return 0;
137+
}
138+
139+
int cache_data_flush_all(void)
140+
{
141+
__asm__ volatile (
142+
"fence\n"
143+
/* th.dcache.call */
144+
".insn 0x10000B\n"
145+
"fence\n"
146+
);
147+
148+
return 0;
149+
}
150+
151+
static void cache_clean_dcache_line(uintptr_t address_in)
152+
{
153+
register uintptr_t address __asm__("a3") = address_in;
154+
155+
__asm__ volatile (
156+
/* th.dcache.cpa a3*/
157+
".insn 0x296800B\n"
158+
:
159+
: "r"(address)
160+
);
161+
}
162+
163+
int cache_data_flush_range(void *addr_in, size_t size)
164+
{
165+
uintptr_t addr = (uintptr_t)addr_in;
166+
167+
__asm__ volatile (
168+
"fence\n"
169+
);
170+
for (uintptr_t i = addr; i < addr + size; i += cache_cfg.dcache_line_size) {
171+
cache_clean_dcache_line(i);
172+
}
173+
__asm__ volatile (
174+
"fence\n"
175+
);
176+
177+
return 0;
178+
}
179+
180+
int cache_data_flush_and_invd_all(void)
181+
{
182+
__asm__ volatile (
183+
"fence\n"
184+
/* th.dcache.ciall */
185+
".insn 0x30000B\n"
186+
"fence\n"
187+
);
188+
189+
return 0;
190+
}
191+
192+
static void cache_clean_invalidate_dcache_line(uintptr_t address_in)
193+
{
194+
register uintptr_t address __asm__("a3") = address_in;
195+
196+
__asm__ volatile (
197+
/* th.dcache.cipa a3*/
198+
".insn 0x2B6800B\n"
199+
:
200+
: "r"(address)
201+
);
202+
}
203+
204+
int cache_data_flush_and_invd_range(void *addr_in, size_t size)
205+
{
206+
uintptr_t addr = (uintptr_t)addr_in;
207+
208+
__asm__ volatile (
209+
"fence\n"
210+
);
211+
for (uintptr_t i = addr; i < addr + size; i += cache_cfg.dcache_line_size) {
212+
cache_clean_invalidate_dcache_line(i);
213+
}
214+
__asm__ volatile (
215+
"fence\n"
216+
);
217+
218+
return 0;
219+
}
220+
221+
int cache_instr_flush_all(void)
222+
{
223+
return -ENOTSUP;
224+
}
225+
226+
int cache_instr_flush_and_invd_all(void)
227+
{
228+
return -ENOTSUP;
229+
}
230+
231+
int cache_instr_flush_range(void *addr, size_t size)
232+
{
233+
ARG_UNUSED(addr);
234+
ARG_UNUSED(size);
235+
236+
return -ENOTSUP;
237+
}
238+
239+
int cache_instr_flush_and_invd_range(void *addr, size_t size)
240+
{
241+
ARG_UNUSED(addr);
242+
ARG_UNUSED(size);
243+
244+
return -ENOTSUP;
245+
}
246+
247+
void __weak arch_cache_init(void)
248+
{
249+
/* Platform specific */
250+
}

0 commit comments

Comments
 (0)