arc: cache.h support added for em7d and em11d SOC
An implementation to flush multiple d-cache lines has been added per the top-level cache.h API. ZEP-1153 was opened to express the need for MORE i-cache and d-cache APIs. For example, the current cache.h API doesn't provide a means to invalidate d-cache lines and has nothing for i-cache. I've also modified some of the i-cache related aux registers to have better names so that they won't be confused with d-cache. These changes are for ZEP-1176. Change-Id: If4c5410451cc40dcd5618fc871093c8febf7e061 Signed-off-by: Chuck Jordan <cjordan@synopsys.com>
This commit is contained in:
parent
22ea605eab
commit
381cb25f63
6 changed files with 240 additions and 15 deletions
|
@ -269,8 +269,42 @@ config ARCH_HAS_NANO_FIBER_ABORT
|
||||||
# omit prompt to signify a "hidden" option
|
# omit prompt to signify a "hidden" option
|
||||||
default n
|
default n
|
||||||
|
|
||||||
endmenu
|
config CACHE_LINE_SIZE_DETECT
|
||||||
|
bool
|
||||||
|
prompt "Detect d-cache line size at runtime"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
This option enables querying the d-cache build register for finding
|
||||||
|
the d-cache line size at the expense of taking more memory and code
|
||||||
|
and a slightly increased boot time.
|
||||||
|
|
||||||
|
If the CPU's d-cache line size is known in advance, disable this
|
||||||
|
option and manually enter the value for CACHE_LINE_SIZE.
|
||||||
|
|
||||||
|
config CACHE_LINE_SIZE
|
||||||
|
int
|
||||||
|
prompt "Cache line size" if !CACHE_LINE_SIZE_DETECT
|
||||||
|
default 32
|
||||||
|
help
|
||||||
|
Size in bytes of a CPU d-cache line.
|
||||||
|
|
||||||
|
Detect automatically at runtime by selecting CACHE_LINE_SIZE_DETECT.
|
||||||
|
|
||||||
|
config ARCH_CACHE_FLUSH_DETECT
|
||||||
|
bool
|
||||||
|
default n
|
||||||
|
|
||||||
|
config CACHE_FLUSHING
|
||||||
|
bool
|
||||||
|
default n
|
||||||
|
prompt "Enable d-cache flushing mechanism"
|
||||||
|
help
|
||||||
|
This links in the sys_cache_flush() function, which provides a
|
||||||
|
way to flush multiple lines of the d-cache.
|
||||||
|
If the d-cache is present, set this to y.
|
||||||
|
If the d-cache is NOT present, set this to n.
|
||||||
|
|
||||||
|
endmenu
|
||||||
|
|
||||||
source "arch/arc/soc/*/Kconfig"
|
source "arch/arc/soc/*/Kconfig"
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ ccflags-y +=-I$(srctree)/arch/$(ARCH)/include
|
||||||
|
|
||||||
obj-y += thread.o thread_entry_wrapper.o \
|
obj-y += thread.o thread_entry_wrapper.o \
|
||||||
cpu_idle.o fast_irq.o fatal.o fault.o \
|
cpu_idle.o fast_irq.o fatal.o fault.o \
|
||||||
fault_s.o irq_manage.o \
|
fault_s.o irq_manage.o cache.o \
|
||||||
isr_wrapper.o regular_irq.o swap_macros.h swap.o \
|
isr_wrapper.o regular_irq.o swap_macros.h swap.o \
|
||||||
sys_fatal_error_handler.o
|
sys_fatal_error_handler.o
|
||||||
|
|
||||||
|
|
184
arch/arc/core/cache.c
Normal file
184
arch/arc/core/cache.c
Normal file
|
@ -0,0 +1,184 @@
|
||||||
|
/* cache.c - d-cache support for ARC CPUs */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Synopsys, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief d-cache manipulation
|
||||||
|
*
|
||||||
|
* This module contains functions for manipulation of the d-cache.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <nanokernel.h>
|
||||||
|
#include <arch/cpu.h>
|
||||||
|
#include <misc/util.h>
|
||||||
|
#include <toolchain.h>
|
||||||
|
#include <cache.h>
|
||||||
|
#include <linker-defs.h>
|
||||||
|
#include <arch/arc/v2/aux_regs.h>
|
||||||
|
#include <nano_internal.h>
|
||||||
|
#include <misc/__assert.h>
|
||||||
|
#include <init.h>
|
||||||
|
|
||||||
|
#if defined(CONFIG_CACHE_FLUSHING)
|
||||||
|
|
||||||
|
#if (CONFIG_CACHE_LINE_SIZE == 0) && !defined(CONFIG_CACHE_LINE_SIZE_DETECT)
|
||||||
|
#error Cannot use this implementation with a cache line size of 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_CACHE_LINE_SIZE_DETECT)
|
||||||
|
#define DCACHE_LINE_SIZE sys_cache_line_size
|
||||||
|
#else
|
||||||
|
#define DCACHE_LINE_SIZE CONFIG_CACHE_LINE_SIZE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DC_CTRL_DC_ENABLE 0x0 /* enable d-cache */
|
||||||
|
#define DC_CTRL_DC_DISABLE 0x1 /* disable d-cache */
|
||||||
|
#define DC_CTRL_INVALID_ONLY 0x0 /* invalid d-cache only */
|
||||||
|
#define DC_CTRL_INVALID_FLUSH 0x40 /* invalid and flush d-cache */
|
||||||
|
#define DC_CTRL_ENABLE_FLUSH_LOCKED 0x80 /* locked d-cache can be flushed */
|
||||||
|
#define DC_CTRL_DISABLE_FLUSH_LOCKED 0x0 /* locked d-cache cannot be flushed */
|
||||||
|
#define DC_CTRL_FLUSH_STATUS 0x100/* flush status */
|
||||||
|
#define DC_CTRL_DIRECT_ACCESS 0x0 /* direct access mode */
|
||||||
|
#define DC_CTRL_INDIRECT_ACCESS 0x20 /* indirect access mode */
|
||||||
|
#define DC_CTRL_OP_SUCCEEDED 0x4 /* d-cache operation succeeded */
|
||||||
|
|
||||||
|
|
||||||
|
static int dcache_available(void)
|
||||||
|
{
|
||||||
|
unsigned long val = _arc_v2_aux_reg_read(_ARC_V2_D_CACHE_BUILD);
|
||||||
|
|
||||||
|
val &= 0xff; /* extract version */
|
||||||
|
return (val == 0)?0:1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dcache_dc_ctrl(uint32_t dcache_en_mask)
|
||||||
|
{
|
||||||
|
if (!dcache_available())
|
||||||
|
return;
|
||||||
|
_arc_v2_aux_reg_write(_ARC_V2_DC_CTRL, dcache_en_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
uint32_t end_addr;
|
||||||
|
unsigned int key;
|
||||||
|
|
||||||
|
if (!dcache_available() || (size == 0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
end_addr = start_addr + size - 1;
|
||||||
|
start_addr &= (uint32_t)(~(DCACHE_LINE_SIZE - 1));
|
||||||
|
|
||||||
|
key = irq_lock(); /* --enter critical section-- */
|
||||||
|
|
||||||
|
do {
|
||||||
|
_arc_v2_aux_reg_write(_ARC_V2_DC_FLDL, start_addr);
|
||||||
|
__asm__ volatile("nop_s");
|
||||||
|
__asm__ volatile("nop_s");
|
||||||
|
__asm__ volatile("nop_s");
|
||||||
|
/* wait for flush completion */
|
||||||
|
do {
|
||||||
|
if ((_arc_v2_aux_reg_read(_ARC_V2_DC_CTRL) &
|
||||||
|
DC_CTRL_FLUSH_STATUS) == 0)
|
||||||
|
break;
|
||||||
|
} while (1);
|
||||||
|
start_addr += DCACHE_LINE_SIZE;
|
||||||
|
} while (start_addr <= end_addr);
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
dcache_flush_mlines((uint32_t)start_addr, (uint32_t)size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(CONFIG_CACHE_LINE_SIZE_DETECT)
|
||||||
|
size_t sys_cache_line_size;
|
||||||
|
static void init_dcache_line_size(void)
|
||||||
|
{
|
||||||
|
uint32_t val;
|
||||||
|
|
||||||
|
val = _arc_v2_aux_reg_read(_ARC_V2_D_CACHE_BUILD);
|
||||||
|
__ASSERT((val&0xff) != 0, "d-cache is not present");
|
||||||
|
val = ((val>>16) & 0xf) + 1;
|
||||||
|
val *= 16;
|
||||||
|
sys_cache_line_size = (size_t) val;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int init_dcache(struct device *unused)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(unused);
|
||||||
|
|
||||||
|
dcache_enable();
|
||||||
|
|
||||||
|
#if defined(CONFIG_CACHE_LINE_SIZE_DETECT)
|
||||||
|
init_dcache_line_size();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_INIT(init_dcache, PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||||
|
|
||||||
|
#endif /* CONFIG_CACHE_FLUSHING */
|
||||||
|
|
|
@ -16,10 +16,10 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
* @brief Cache helper functions (ARC)
|
* @brief Cache helper functions and defines (ARC)
|
||||||
*
|
*
|
||||||
* This file contains private nanokernel structures definitions and various
|
* This file contains cache related functions and definitions for the
|
||||||
* other definitions for the ARCv2 processor architecture.
|
* ARCv2 processor architecture.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _ARCV2_CACHE__H_
|
#ifndef _ARCV2_CACHE__H_
|
||||||
|
@ -33,28 +33,29 @@ extern "C" {
|
||||||
|
|
||||||
#ifndef _ASMLANGUAGE
|
#ifndef _ASMLANGUAGE
|
||||||
|
|
||||||
#define CACHE_ENABLE 0x00
|
/* i-cache defines for IC_CTRL register */
|
||||||
#define CACHE_DISABLE 0x01
|
#define IC_CACHE_ENABLE 0x00
|
||||||
#define CACHE_DIRECT 0x00
|
#define IC_CACHE_DISABLE 0x01
|
||||||
#define CACHE_CACHE_CONTROLLED 0x20
|
#define IC_CACHE_DIRECT 0x00
|
||||||
|
#define IC_CACHE_INDIRECT 0x20
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @brief Sets the I-cache
|
* @brief Initialize the I-cache
|
||||||
*
|
*
|
||||||
* Enables cache and sets the direct access.
|
* Enables the i-cache and sets it to direct access mode.
|
||||||
*/
|
*/
|
||||||
static ALWAYS_INLINE void _icache_setup(void)
|
static ALWAYS_INLINE void _icache_setup(void)
|
||||||
{
|
{
|
||||||
uint32_t icache_config = (
|
uint32_t icache_config = (
|
||||||
CACHE_DIRECT | /* direct mapping (one-way assoc.) */
|
IC_CACHE_DIRECT | /* direct mapping (one-way assoc.) */
|
||||||
CACHE_ENABLE /* i-cache enabled */
|
IC_CACHE_ENABLE /* i-cache enabled */
|
||||||
);
|
);
|
||||||
uint32_t val;
|
uint32_t val;
|
||||||
|
|
||||||
val = _arc_v2_aux_reg_read(_ARC_V2_I_CACHE_BUILD);
|
val = _arc_v2_aux_reg_read(_ARC_V2_I_CACHE_BUILD);
|
||||||
val &= 0xff;
|
val &= 0xff;
|
||||||
if (val != 0) {
|
if (val != 0) { /* is i-cache present? */
|
||||||
/* configure i-cache if present */
|
/* configure i-cache */
|
||||||
_arc_v2_aux_reg_write(_ARC_V2_IC_CTRL, icache_config);
|
_arc_v2_aux_reg_write(_ARC_V2_IC_CTRL, icache_config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,9 @@ config DCCM_BASE_ADDRESS
|
||||||
config DCCM_SIZE
|
config DCCM_SIZE
|
||||||
default 64
|
default 64
|
||||||
|
|
||||||
|
config CACHE_FLUSHING
|
||||||
|
def_bool y
|
||||||
|
|
||||||
if GPIO
|
if GPIO
|
||||||
|
|
||||||
config GPIO_DW
|
config GPIO_DW
|
||||||
|
|
|
@ -65,6 +65,9 @@ config DCCM_BASE_ADDRESS
|
||||||
config DCCM_SIZE
|
config DCCM_SIZE
|
||||||
default 128
|
default 128
|
||||||
|
|
||||||
|
config CACHE_FLUSHING
|
||||||
|
def_bool y
|
||||||
|
|
||||||
if GPIO
|
if GPIO
|
||||||
|
|
||||||
config GPIO_DW
|
config GPIO_DW
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue