include: Implement API's for cache flush and cache invalidate
arch: arc: core: Add Cache Implementation function & prototype for arc Signed-off-by: Aastha Grover <aastha.grover@intel.com>
This commit is contained in:
parent
568211738d
commit
97ecad69f0
5 changed files with 144 additions and 76 deletions
|
@ -67,34 +67,19 @@ static void dcache_enable(void)
|
|||
dcache_dc_ctrl(DC_CTRL_DC_ENABLE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Flush multiple d-cache lines to memory
|
||||
*
|
||||
* No alignment is required for either <start_addr> or <size>, but since
|
||||
* dcache_flush_mlines() iterates on the d-cache lines, a cache line
|
||||
* alignment for both is optimal.
|
||||
*
|
||||
* The d-cache line size is specified either via the CONFIG_CACHE_LINE_SIZE
|
||||
* kconfig option or it is detected at runtime.
|
||||
*
|
||||
* @param start_addr the pointer to start the multi-line flush
|
||||
* @param size the number of bytes that are to be flushed
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
static void dcache_flush_mlines(uint32_t start_addr, uint32_t size)
|
||||
void arch_dcache_flush(void *start_addr_ptr, size_t size)
|
||||
{
|
||||
uint32_t end_addr;
|
||||
uintptr_t start_addr = (uintptr_t)start_addr_ptr;
|
||||
uintptr_t end_addr;
|
||||
unsigned int key;
|
||||
|
||||
if (!dcache_available() || (size == 0U)) {
|
||||
return;
|
||||
}
|
||||
|
||||
end_addr = start_addr + size - 1;
|
||||
start_addr &= (uint32_t)(~(DCACHE_LINE_SIZE - 1));
|
||||
end_addr = start_addr + size;
|
||||
|
||||
start_addr = ROUND_DOWN(start_addr, DCACHE_LINE_SIZE);
|
||||
|
||||
key = arch_irq_lock(); /* --enter critical section-- */
|
||||
|
||||
|
@ -111,35 +96,35 @@ static void dcache_flush_mlines(uint32_t start_addr, uint32_t size)
|
|||
}
|
||||
} while (1);
|
||||
start_addr += DCACHE_LINE_SIZE;
|
||||
} while (start_addr <= end_addr);
|
||||
} while (start_addr < end_addr);
|
||||
|
||||
arch_irq_unlock(key); /* --exit critical section-- */
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Flush d-cache lines to main memory
|
||||
*
|
||||
* No alignment is required for either <virt> or <size>, but since
|
||||
* sys_cache_flush() iterates on the d-cache lines, a d-cache line alignment for
|
||||
* both is optimal.
|
||||
*
|
||||
* The d-cache line size is specified either via the CONFIG_CACHE_LINE_SIZE
|
||||
* kconfig option or it is detected at runtime.
|
||||
*
|
||||
* @param start_addr the pointer to start the multi-line flush
|
||||
* @param size the number of bytes that are to be flushed
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void sys_cache_flush(vaddr_t start_addr, size_t size)
|
||||
void arch_dcache_invd(void *start_addr_ptr, size_t size)
|
||||
{
|
||||
dcache_flush_mlines((uint32_t)start_addr, (uint32_t)size);
|
||||
}
|
||||
uintptr_t start_addr = (uintptr_t)start_addr_ptr;
|
||||
uintptr_t end_addr;
|
||||
unsigned int key;
|
||||
|
||||
if (!dcache_available() || (size == 0U)) {
|
||||
return;
|
||||
}
|
||||
end_addr = start_addr + size;
|
||||
start_addr = ROUND_DOWN(start_addr, DCACHE_LINE_SIZE);
|
||||
|
||||
key = arch_irq_lock(); /* -enter critical section- */
|
||||
|
||||
do {
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_DC_IVDL, start_addr);
|
||||
__asm__ volatile("nop_s");
|
||||
__asm__ volatile("nop_s");
|
||||
__asm__ volatile("nop_s");
|
||||
start_addr += DCACHE_LINE_SIZE;
|
||||
} while (start_addr < end_addr);
|
||||
irq_unlock(key); /* -exit critical section- */
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CACHE_LINE_SIZE_DETECT)
|
||||
size_t sys_cache_line_size;
|
||||
|
@ -155,6 +140,15 @@ static void init_dcache_line_size(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
size_t arch_cache_line_size_get(void)
|
||||
{
|
||||
#if defined(CONFIG_CACHE_LINE_SIZE_DETECT)
|
||||
return sys_cache_line_size;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int init_dcache(struct device *unused)
|
||||
{
|
||||
ARG_UNUSED(unused);
|
||||
|
|
|
@ -97,6 +97,15 @@ static void init_cache_line_size(void)
|
|||
#define init_cache_line_size() do { } while ((0))
|
||||
#endif
|
||||
|
||||
size_t arch_cache_line_size_get(void)
|
||||
{
|
||||
#if defined(CONFIG_CACHE_LINE_SIZE_DETECT)
|
||||
return sys_cache_line_size;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int init_cache(struct device *unused)
|
||||
{
|
||||
ARG_UNUSED(unused);
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
#define ZEPHYR_INCLUDE_ARCH_X86_ADDR_TYPES_H_
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
typedef unsigned int paddr_t;
|
||||
typedef unsigned int vaddr_t;
|
||||
typedef uintptr_t paddr_t;
|
||||
typedef void *vaddr_t;
|
||||
#endif
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_ARCH_X86_ADDR_TYPES_H_ */
|
||||
|
|
|
@ -13,45 +13,75 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define _sys_cache_flush_sig(x) void (x)(vaddr_t virt, size_t size)
|
||||
void arch_dcache_flush(void *addr, size_t size);
|
||||
void arch_dcache_invd(void *addr, size_t size);
|
||||
|
||||
#if defined(CONFIG_CACHE_FLUSHING)
|
||||
|
||||
#if defined(CONFIG_ARCH_CACHE_FLUSH_DETECT)
|
||||
typedef _sys_cache_flush_sig(_sys_cache_flush_t);
|
||||
extern _sys_cache_flush_t *sys_cache_flush;
|
||||
#else
|
||||
extern _sys_cache_flush_sig(sys_cache_flush);
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Provide NOP APIs for systems that do not have caches.
|
||||
/**
|
||||
*
|
||||
* An example is the Cortex-M chips. However, the functions are provided so
|
||||
* that code that need to manipulate caches can be written in an
|
||||
* architecture-agnostic manner. The functions do nothing. The cache line size
|
||||
* value is always 0.
|
||||
* @brief Flush d-cache lines to main memory
|
||||
*
|
||||
* No alignment is required for either addr or size, but since
|
||||
* sys_cache_flush() iterates on the d-cache lines, a d-cache line alignment for
|
||||
* both is optimal.
|
||||
*
|
||||
* The d-cache line size is specified either via the CONFIG_CACHE_LINE_SIZE
|
||||
* kconfig option or it is detected at runtime.
|
||||
*
|
||||
* @param addr the pointer to start the multi-line flush
|
||||
* @param size the number of bytes that are to be flushed
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
static inline _sys_cache_flush_sig(sys_cache_flush)
|
||||
static inline void sys_cache_flush(void *addr, size_t size)
|
||||
{
|
||||
ARG_UNUSED(virt);
|
||||
ARG_UNUSED(size);
|
||||
|
||||
/* do nothing */
|
||||
if (IS_ENABLED(CONFIG_CACHE_FLUSHING)) {
|
||||
arch_dcache_flush(addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CACHE_FLUSHING */
|
||||
/**
|
||||
*
|
||||
* @brief Invalidate d-cache lines
|
||||
*
|
||||
* No alignment is required for either addr or size, but since
|
||||
* sys_cache_invd() iterates on the d-cache lines, a d-cache line alignment for
|
||||
* both is optimal.
|
||||
*
|
||||
* The d-cache line size is specified either via the CONFIG_CACHE_LINE_SIZE
|
||||
* kconfig option or it is detected at runtime.
|
||||
*
|
||||
* @param addr the pointer to start address
|
||||
* @param size the number of bytes that are to be invalidated
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
static inline void sys_cache_invd(void *addr, size_t size)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_CACHE_FLUSHING)) {
|
||||
arch_dcache_invd(addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CACHE_LINE_SIZE_DETECT)
|
||||
extern size_t sys_cache_line_size;
|
||||
#elif defined(CONFIG_CACHE_LINE_SIZE)
|
||||
#define sys_cache_line_size CONFIG_CACHE_LINE_SIZE
|
||||
/**
|
||||
*
|
||||
* @brief Get the d-cache line size.
|
||||
*
|
||||
* The API is provided to get the cache line size.
|
||||
*
|
||||
* @return size of the cache line or 0 if the cache is not enabled.
|
||||
*/
|
||||
static inline size_t sys_cache_line_size_get(void)
|
||||
{
|
||||
#ifdef CONFIG_CACHE_FLUSHING
|
||||
#ifdef CONFIG_CACHE_LINE_SIZE
|
||||
return CONFIG_CACHE_LINE_SIZE;
|
||||
#else
|
||||
#define sys_cache_line_size 0
|
||||
#endif
|
||||
return arch_cache_line_size_get();
|
||||
#endif /* CONFIG_CACHE_LINE_SIZE */
|
||||
#else
|
||||
return 0;
|
||||
#endif /* CONFIG_CACHE_FLUSHING */
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -675,6 +675,41 @@ extern uint64_t arch_timing_value_swap_temp;
|
|||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @defgroup arch_cache Architecture-specific cache functions
|
||||
* @ingroup arch-interface
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_CACHE_FLUSHING
|
||||
/**
|
||||
*
|
||||
* @brief Flush d-cache lines to main memory
|
||||
*
|
||||
* @see sys_cache_flush
|
||||
*/
|
||||
void arch_dcache_flush(void *addr, size_t size);
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Invalidate d-cache lines
|
||||
*
|
||||
* @see sys_cache_invd
|
||||
*/
|
||||
void arch_dcache_invd(void *addr, size_t size);
|
||||
|
||||
#ifndef CONFIG_CACHE_LINE_SIZE
|
||||
/**
|
||||
*
|
||||
* @brief Get d-cache line size
|
||||
*
|
||||
* @see sys_cache_line_size_get
|
||||
*/
|
||||
size_t arch_cache_line_size_get(void);
|
||||
#endif
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue