-
Notifications
You must be signed in to change notification settings - Fork 6.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
arch: arm: cortex_a_r: implement cache API
Implement cache management APIs for Cortex-A/R AArch32 L1 caches. Signed-off-by: Manuel Argüelles <[email protected]>
- Loading branch information
Showing
3 changed files
with
212 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,210 @@ | ||
/* | ||
* Copyright 2023 NXP | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
/** | ||
* @file | ||
* @brief Cortex-A/R AArch32 L1-cache maintenance operations. | ||
* | ||
* This module implement the cache API for Cortex-A/R AArch32 cores using CMSIS. | ||
* Only L1-cache maintenance operations is supported. | ||
*/ | ||
|
||
#include <zephyr/kernel.h> | ||
#include <zephyr/cache.h> | ||
#include <zephyr/arch/arm/aarch32/cortex_a_r/cmsis.h> | ||
|
||
/* Cache Type Register */ | ||
#define CTR_DMINLINE_SHIFT 16 | ||
#define CTR_DMINLINE_MASK BIT_MASK(4) | ||
|
||
static size_t dcache_line_size; | ||
|
||
/** | ||
* @brief Get the smallest D-cache line size. | ||
* | ||
* Get the smallest D-cache line size of all the data and unified caches that | ||
* the processor controls. | ||
*/ | ||
size_t arch_dcache_line_size_get(void) | ||
{ | ||
uint32_t val; | ||
uint32_t dminline; | ||
|
||
if (!dcache_line_size) { | ||
val = read_sysreg(ctr); | ||
dminline = (val >> CTR_DMINLINE_SHIFT) & CTR_DMINLINE_MASK; | ||
/* Log2 of the number of words */ | ||
dcache_line_size = 2 << dminline; | ||
} | ||
|
||
return dcache_line_size; | ||
} | ||
|
||
void arch_dcache_enable(void) | ||
{ | ||
uint32_t val; | ||
|
||
arch_dcache_invd_all(); | ||
|
||
val = __get_SCTLR(); | ||
val |= SCTLR_C_Msk; | ||
__DSB(); | ||
__set_SCTLR(val); | ||
__ISB(); | ||
} | ||
|
||
void arch_dcache_disable(void) | ||
{ | ||
uint32_t val; | ||
|
||
val = __get_SCTLR(); | ||
val &= ~SCTLR_C_Msk; | ||
__DSB(); | ||
__set_SCTLR(val); | ||
__ISB(); | ||
|
||
arch_dcache_flush_and_invd_all(); | ||
} | ||
|
||
int arch_dcache_flush_all(void) | ||
{ | ||
L1C_CleanDCacheAll(); | ||
|
||
return 0; | ||
} | ||
|
||
int arch_dcache_invd_all(void) | ||
{ | ||
L1C_InvalidateDCacheAll(); | ||
|
||
return 0; | ||
} | ||
|
||
int arch_dcache_flush_and_invd_all(void) | ||
{ | ||
L1C_CleanInvalidateDCacheAll(); | ||
|
||
return 0; | ||
} | ||
|
||
int arch_dcache_flush_range(void *start_addr, size_t size) | ||
{ | ||
size_t line_size; | ||
uintptr_t addr = (uintptr_t)start_addr; | ||
uintptr_t end_addr = addr + size; | ||
|
||
/* Align address to line size */ | ||
line_size = arch_dcache_line_size_get(); | ||
addr &= ~(line_size - 1); | ||
|
||
while (addr < end_addr) { | ||
L1C_CleanDCacheMVA((void *)addr); | ||
addr += line_size; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
int arch_dcache_invd_range(void *start_addr, size_t size) | ||
{ | ||
size_t line_size; | ||
uintptr_t addr = (uintptr_t)start_addr; | ||
uintptr_t end_addr = addr + size; | ||
|
||
line_size = arch_dcache_line_size_get(); | ||
|
||
/* | ||
* Clean and invalidate the partial cache lines at both ends of the | ||
* given range to prevent data corruption | ||
*/ | ||
if (end_addr & (line_size - 1)) { | ||
end_addr &= ~(line_size - 1); | ||
L1C_CleanInvalidateDCacheMVA((void *)end_addr); | ||
} | ||
|
||
if (addr & (line_size - 1)) { | ||
addr &= ~(line_size - 1); | ||
if (addr == end_addr) { | ||
goto done; | ||
} | ||
L1C_CleanInvalidateDCacheMVA((void *)addr); | ||
addr += line_size; | ||
} | ||
|
||
/* Align address to line size */ | ||
addr &= ~(line_size - 1); | ||
|
||
while (addr < end_addr) { | ||
L1C_InvalidateDCacheMVA((void *)addr); | ||
addr += line_size; | ||
} | ||
|
||
done: | ||
return 0; | ||
} | ||
|
||
int arch_dcache_flush_and_invd_range(void *start_addr, size_t size) | ||
{ | ||
size_t line_size; | ||
uintptr_t addr = (uintptr_t)start_addr; | ||
uintptr_t end_addr = addr + size; | ||
|
||
/* Align address to line size */ | ||
line_size = arch_dcache_line_size_get(); | ||
addr &= ~(line_size - 1); | ||
|
||
while (addr < end_addr) { | ||
L1C_CleanInvalidateDCacheMVA((void *)addr); | ||
addr += line_size; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
void arch_icache_enable(void) | ||
{ | ||
arch_icache_invd_all(); | ||
__set_SCTLR(__get_SCTLR() | SCTLR_I_Msk); | ||
__ISB(); | ||
} | ||
|
||
void arch_icache_disable(void) | ||
{ | ||
__set_SCTLR(__get_SCTLR() & ~SCTLR_I_Msk); | ||
__ISB(); | ||
} | ||
|
||
int arch_icache_flush_all(void) | ||
{ | ||
return -ENOTSUP; | ||
} | ||
|
||
int arch_icache_invd_all(void) | ||
{ | ||
L1C_InvalidateICacheAll(); | ||
|
||
return 0; | ||
} | ||
|
||
int arch_icache_flush_and_invd_all(void) | ||
{ | ||
return -ENOTSUP; | ||
} | ||
|
||
int arch_icache_flush_range(void *start_addr, size_t size) | ||
{ | ||
return -ENOTSUP; | ||
} | ||
|
||
int arch_icache_invd_range(void *start_addr, size_t size) | ||
{ | ||
return -ENOTSUP; | ||
} | ||
|
||
int arch_icache_flush_and_invd_range(void *start_addr, size_t size) | ||
{ | ||
return -ENOTSUP; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters