Skip to content

Commit

Permalink
arch: arm: cortex_a_r: implement cache API
Browse files Browse the repository at this point in the history
Implement cache management APIs for Cortex-A/R AArch32 L1 caches.

Signed-off-by: Manuel Argüelles <[email protected]>
  • Loading branch information
manuargue committed Mar 28, 2023
1 parent 955acbd commit bbf3756
Show file tree
Hide file tree
Showing 3 changed files with 212 additions and 0 deletions.
1 change: 1 addition & 0 deletions arch/arm/core/aarch32/cortex_a_r/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ zephyr_library_sources(
zephyr_library_sources_ifdef(CONFIG_USERSPACE thread.c)
zephyr_library_sources_ifdef(CONFIG_SEMIHOST semihost.c)
zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE __aeabi_read_tp.S)
zephyr_library_sources_ifdef(CONFIG_ARCH_CACHE cache.c)
210 changes: 210 additions & 0 deletions arch/arm/core/aarch32/cortex_a_r/cache.c
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;
}
1 change: 1 addition & 0 deletions include/zephyr/arch/arm/aarch32/cortex_a_r/lib_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ MAKE_REG_HELPER(prlar, 0, 6, 3, 1);
MAKE_REG_HELPER(mair0, 0, 10, 2, 0);
MAKE_REG_HELPER(vbar, 0, 12, 0, 0);
MAKE_REG_HELPER(cntv_ctl, 0, 14, 3, 1);
MAKE_REG_HELPER(ctr, 0, 0, 0, 1);
MAKE_REG64_HELPER(ICC_SGI1R, 0, 12);
MAKE_REG64_HELPER(cntvct, 1, 14);
MAKE_REG64_HELPER(cntv_cval, 3, 14);
Expand Down

0 comments on commit bbf3756

Please sign in to comment.