mirror of
https://github.com/u-boot/u-boot.git
synced 2024-11-28 15:13:31 +08:00
arc: cache - accommodate different L1 cache line lengths
ARC core could be configured with different L1 and L2 (AKA SLC) cache line lengths. At least these values are possible and were really used: 32, 64 or 128 bytes. Current implementation requires cache line to be selected upon U-Boot configuration and then it will only work on matching hardware. Indeed this is quite efficient because cache line length gets hardcoded during code compilation. But OTOH it makes binary less portable. With this commit we allow U-Boot to determine real L1 cache line length early in runtime and use this value later on. This extends portability of U-Boot binary a lot. Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
This commit is contained in:
parent
86a0df7328
commit
379b3280b3
@ -116,17 +116,6 @@ config SYS_DCACHE_OFF
|
||||
bool "Do not use Data Cache"
|
||||
default n
|
||||
|
||||
config ARC_CACHE_LINE_SHIFT
|
||||
int "Cache Line Length (as power of 2)"
|
||||
range 5 7
|
||||
default "6"
|
||||
depends on !SYS_DCACHE_OFF || !SYS_ICACHE_OFF
|
||||
help
|
||||
Starting with ARC700 4.9, Cache line length is configurable,
|
||||
This option specifies "N", with Line-len = 2 power N
|
||||
So line lengths of 32, 64, 128 are specified by 5,6,7, respectively
|
||||
Linux only supports same line lengths for I and D caches.
|
||||
|
||||
choice
|
||||
prompt "Target select"
|
||||
default TARGET_AXS101
|
||||
|
@ -9,13 +9,13 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#ifdef CONFIG_ARC_CACHE_LINE_SHIFT
|
||||
#define CONFIG_SYS_CACHELINE_SIZE (1 << CONFIG_ARC_CACHE_LINE_SHIFT)
|
||||
#define ARCH_DMA_MINALIGN CONFIG_SYS_CACHELINE_SIZE
|
||||
#else
|
||||
/* Satisfy users of ARCH_DMA_MINALIGN */
|
||||
/*
|
||||
* As of today we may handle any L1 cache line length right in software.
|
||||
* For that essentially cache line length is a variable not constant.
|
||||
* And to satisfy users of ARCH_DMA_MINALIGN we just use largest line length
|
||||
* that may exist in either L1 or L2 (AKA SLC) caches on ARC.
|
||||
*/
|
||||
#define ARCH_DMA_MINALIGN 128
|
||||
#endif
|
||||
|
||||
#if defined(ARC_MMU_ABSENT)
|
||||
#define CONFIG_ARC_MMU_VER 0
|
||||
|
@ -5,13 +5,12 @@
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/arcregs.h>
|
||||
#include <asm/cache.h>
|
||||
|
||||
#define CACHE_LINE_MASK (~(CONFIG_SYS_CACHELINE_SIZE - 1))
|
||||
|
||||
/* Bit values in IC_CTRL */
|
||||
#define IC_CTRL_CACHE_DISABLE (1 << 0)
|
||||
|
||||
@ -26,12 +25,18 @@
|
||||
#define OP_FLUSH 0x2
|
||||
#define OP_INV_IC 0x3
|
||||
|
||||
#ifdef CONFIG_ISA_ARCV2
|
||||
/*
|
||||
* By default that variable will fall into .bss section.
|
||||
* But .bss section is not relocated and so it will be initilized before
|
||||
* relocation but will be used after being zeroed.
|
||||
*/
|
||||
int l1_line_sz __section(".data");
|
||||
int dcache_exists __section(".data");
|
||||
int icache_exists __section(".data");
|
||||
|
||||
#define CACHE_LINE_MASK (~(l1_line_sz - 1))
|
||||
|
||||
#ifdef CONFIG_ISA_ARCV2
|
||||
int slc_line_sz __section(".data");
|
||||
int slc_exists __section(".data");
|
||||
|
||||
@ -111,46 +116,87 @@ static inline void __slc_line_op(unsigned long paddr, unsigned long sz,
|
||||
#define __slc_line_op(paddr, sz, cacheop)
|
||||
#endif
|
||||
|
||||
static inline int icache_exists(void)
|
||||
#ifdef CONFIG_ISA_ARCV2
|
||||
static void read_decode_cache_bcr_arcv2(void)
|
||||
{
|
||||
/* Check if Instruction Cache is available */
|
||||
if (read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
union {
|
||||
struct {
|
||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
unsigned int pad:24, way:2, lsz:2, sz:4;
|
||||
#else
|
||||
unsigned int sz:4, lsz:2, way:2, pad:24;
|
||||
#endif
|
||||
} fields;
|
||||
unsigned int word;
|
||||
} slc_cfg;
|
||||
|
||||
static inline int dcache_exists(void)
|
||||
union {
|
||||
struct {
|
||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
unsigned int pad:24, ver:8;
|
||||
#else
|
||||
unsigned int ver:8, pad:24;
|
||||
#endif
|
||||
} fields;
|
||||
unsigned int word;
|
||||
} sbcr;
|
||||
|
||||
sbcr.word = read_aux_reg(ARC_BCR_SLC);
|
||||
if (sbcr.fields.ver) {
|
||||
slc_cfg.word = read_aux_reg(ARC_AUX_SLC_CONFIG);
|
||||
slc_exists = 1;
|
||||
slc_line_sz = (slc_cfg.fields.lsz == 0) ? 128 : 64;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void read_decode_cache_bcr(void)
|
||||
{
|
||||
/* Check if Data Cache is available */
|
||||
if (read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
int dc_line_sz = 0, ic_line_sz = 0;
|
||||
|
||||
union {
|
||||
struct {
|
||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
unsigned int pad:12, line_len:4, sz:4, config:4, ver:8;
|
||||
#else
|
||||
unsigned int ver:8, config:4, sz:4, line_len:4, pad:12;
|
||||
#endif
|
||||
} fields;
|
||||
unsigned int word;
|
||||
} ibcr, dbcr;
|
||||
|
||||
ibcr.word = read_aux_reg(ARC_BCR_IC_BUILD);
|
||||
if (ibcr.fields.ver) {
|
||||
icache_exists = 1;
|
||||
l1_line_sz = ic_line_sz = 8 << ibcr.fields.line_len;
|
||||
if (!ic_line_sz)
|
||||
panic("Instruction exists but line length is 0\n");
|
||||
}
|
||||
|
||||
dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD);
|
||||
if (dbcr.fields.ver){
|
||||
dcache_exists = 1;
|
||||
l1_line_sz = dc_line_sz = 16 << dbcr.fields.line_len;
|
||||
if (!dc_line_sz)
|
||||
panic("Data cache exists but line length is 0\n");
|
||||
}
|
||||
|
||||
if (ic_line_sz && dc_line_sz && (ic_line_sz != dc_line_sz))
|
||||
panic("Instruction and data cache line lengths differ\n");
|
||||
}
|
||||
|
||||
void cache_init(void)
|
||||
{
|
||||
read_decode_cache_bcr();
|
||||
|
||||
#ifdef CONFIG_ISA_ARCV2
|
||||
/* Check if System-Level Cache (SLC) is available */
|
||||
if (read_aux_reg(ARC_BCR_SLC) & CACHE_VER_NUM_MASK) {
|
||||
#define LSIZE_OFFSET 4
|
||||
#define LSIZE_MASK 3
|
||||
if (read_aux_reg(ARC_AUX_SLC_CONFIG) &
|
||||
(LSIZE_MASK << LSIZE_OFFSET))
|
||||
slc_line_sz = 64;
|
||||
else
|
||||
slc_line_sz = 128;
|
||||
slc_exists = 1;
|
||||
} else {
|
||||
slc_exists = 0;
|
||||
}
|
||||
read_decode_cache_bcr_arcv2();
|
||||
#endif
|
||||
}
|
||||
|
||||
int icache_status(void)
|
||||
{
|
||||
if (!icache_exists())
|
||||
if (!icache_exists)
|
||||
return 0;
|
||||
|
||||
if (read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE)
|
||||
@ -161,14 +207,14 @@ int icache_status(void)
|
||||
|
||||
void icache_enable(void)
|
||||
{
|
||||
if (icache_exists())
|
||||
if (icache_exists)
|
||||
write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) &
|
||||
~IC_CTRL_CACHE_DISABLE);
|
||||
}
|
||||
|
||||
void icache_disable(void)
|
||||
{
|
||||
if (icache_exists())
|
||||
if (icache_exists)
|
||||
write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) |
|
||||
IC_CTRL_CACHE_DISABLE);
|
||||
}
|
||||
@ -190,7 +236,7 @@ void invalidate_icache_all(void)
|
||||
|
||||
int dcache_status(void)
|
||||
{
|
||||
if (!dcache_exists())
|
||||
if (!dcache_exists)
|
||||
return 0;
|
||||
|
||||
if (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE)
|
||||
@ -201,7 +247,7 @@ int dcache_status(void)
|
||||
|
||||
void dcache_enable(void)
|
||||
{
|
||||
if (!dcache_exists())
|
||||
if (!dcache_exists)
|
||||
return;
|
||||
|
||||
write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) &
|
||||
@ -210,7 +256,7 @@ void dcache_enable(void)
|
||||
|
||||
void dcache_disable(void)
|
||||
{
|
||||
if (!dcache_exists())
|
||||
if (!dcache_exists)
|
||||
return;
|
||||
|
||||
write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) |
|
||||
@ -246,14 +292,14 @@ static inline void __cache_line_loop(unsigned long paddr, unsigned long sz,
|
||||
sz += paddr & ~CACHE_LINE_MASK;
|
||||
paddr &= CACHE_LINE_MASK;
|
||||
|
||||
num_lines = DIV_ROUND_UP(sz, CONFIG_SYS_CACHELINE_SIZE);
|
||||
num_lines = DIV_ROUND_UP(sz, l1_line_sz);
|
||||
|
||||
while (num_lines-- > 0) {
|
||||
#if (CONFIG_ARC_MMU_VER == 3)
|
||||
write_aux_reg(aux_tag, paddr);
|
||||
#endif
|
||||
write_aux_reg(aux_cmd, paddr);
|
||||
paddr += CONFIG_SYS_CACHELINE_SIZE;
|
||||
paddr += l1_line_sz;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
CONFIG_ARC=y
|
||||
CONFIG_SYS_DCACHE_OFF=y
|
||||
CONFIG_ARC_CACHE_LINE_SHIFT=5
|
||||
CONFIG_DM_SERIAL=y
|
||||
CONFIG_SYS_CLK_FREQ=750000000
|
||||
CONFIG_SYS_TEXT_BASE=0x81000000
|
||||
|
@ -1,5 +1,4 @@
|
||||
CONFIG_ARC=y
|
||||
CONFIG_ARC_CACHE_LINE_SHIFT=5
|
||||
CONFIG_TARGET_TB100=y
|
||||
CONFIG_DM_SERIAL=y
|
||||
CONFIG_SYS_CLK_FREQ=500000000
|
||||
|
Loading…
Reference in New Issue
Block a user