@ -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 ;
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
static inline int dcache_exists ( void )
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 ;
}
}