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
|
||||
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"
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ ccflags-y +=-I$(srctree)/arch/$(ARCH)/include
|
|||
|
||||
obj-y += thread.o thread_entry_wrapper.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 \
|
||||
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
|
||||
* @brief Cache helper functions (ARC)
|
||||
* @brief Cache helper functions and defines (ARC)
|
||||
*
|
||||
* This file contains private nanokernel structures definitions and various
|
||||
* other definitions for the ARCv2 processor architecture.
|
||||
* This file contains cache related functions and definitions for the
|
||||
* ARCv2 processor architecture.
|
||||
*/
|
||||
|
||||
#ifndef _ARCV2_CACHE__H_
|
||||
|
@ -33,28 +33,29 @@ extern "C" {
|
|||
|
||||
#ifndef _ASMLANGUAGE
|
||||
|
||||
#define CACHE_ENABLE 0x00
|
||||
#define CACHE_DISABLE 0x01
|
||||
#define CACHE_DIRECT 0x00
|
||||
#define CACHE_CACHE_CONTROLLED 0x20
|
||||
/* i-cache defines for IC_CTRL register */
|
||||
#define IC_CACHE_ENABLE 0x00
|
||||
#define IC_CACHE_DISABLE 0x01
|
||||
#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)
|
||||
{
|
||||
uint32_t icache_config = (
|
||||
CACHE_DIRECT | /* direct mapping (one-way assoc.) */
|
||||
CACHE_ENABLE /* i-cache enabled */
|
||||
IC_CACHE_DIRECT | /* direct mapping (one-way assoc.) */
|
||||
IC_CACHE_ENABLE /* i-cache enabled */
|
||||
);
|
||||
uint32_t val;
|
||||
|
||||
val = _arc_v2_aux_reg_read(_ARC_V2_I_CACHE_BUILD);
|
||||
val &= 0xff;
|
||||
if (val != 0) {
|
||||
/* configure i-cache if present */
|
||||
if (val != 0) { /* is i-cache present? */
|
||||
/* configure i-cache */
|
||||
_arc_v2_aux_reg_write(_ARC_V2_IC_CTRL, icache_config);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,6 +65,9 @@ config DCCM_BASE_ADDRESS
|
|||
config DCCM_SIZE
|
||||
default 64
|
||||
|
||||
config CACHE_FLUSHING
|
||||
def_bool y
|
||||
|
||||
if GPIO
|
||||
|
||||
config GPIO_DW
|
||||
|
|
|
@ -65,6 +65,9 @@ config DCCM_BASE_ADDRESS
|
|||
config DCCM_SIZE
|
||||
default 128
|
||||
|
||||
config CACHE_FLUSHING
|
||||
def_bool y
|
||||
|
||||
if GPIO
|
||||
|
||||
config GPIO_DW
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue