2013-01-08 21:05:02 +08:00
|
|
|
#include "../common/mipsregs.h"
|
|
|
|
#include "cache.h"
|
|
|
|
|
|
|
|
#define K0BASE 0x80000000
|
|
|
|
#define PRID_3210I 0x4200
|
|
|
|
|
|
|
|
typedef struct cacheinfo_t {
|
|
|
|
unsigned int icache_size;
|
|
|
|
unsigned int dcache_size;
|
|
|
|
unsigned int icacheline_size;
|
|
|
|
unsigned int dcacheline_size;
|
|
|
|
} cacheinfo_t ;
|
|
|
|
|
|
|
|
typedef struct cacheop_t {
|
|
|
|
void (*Clear_TagLo) (void);
|
|
|
|
void (*Invalidate_Icache) (unsigned int);
|
|
|
|
void (*Invalidate_Dcache_Fill) (unsigned int);
|
|
|
|
void (*Invalidate_Dcache_ClearTag) (unsigned int);
|
|
|
|
void (*Init_Cache)(void);
|
|
|
|
} cacheop_t ;
|
|
|
|
|
|
|
|
static cacheop_t cacheop, *pcacheop;
|
|
|
|
static cacheinfo_t cacheinfo, *pcacheinfo;
|
|
|
|
|
|
|
|
int identify_cpu (void)
|
|
|
|
{
|
|
|
|
unsigned int cpu_id;
|
|
|
|
void invalidate_cache (void);
|
|
|
|
|
|
|
|
pcacheop = &cacheop;
|
|
|
|
pcacheinfo = &cacheinfo;
|
|
|
|
|
|
|
|
rt_kprintf("CPU configure: 0x%08x\n", read_c0_config());
|
|
|
|
cpu_id = read_c0_prid();
|
|
|
|
switch (cpu_id)
|
|
|
|
{
|
|
|
|
case PRID_3210I:
|
|
|
|
rt_kprintf ("CPU:SoC3210\n");
|
|
|
|
pcacheop->Clear_TagLo = Clear_TagLo;
|
|
|
|
pcacheop->Invalidate_Icache = Invalidate_Icache_Gc3210I;
|
|
|
|
pcacheop->Invalidate_Dcache_Fill = Invalidate_Dcache_Fill_Gc3210I;
|
|
|
|
pcacheop->Invalidate_Dcache_ClearTag = Invalidate_Dcache_ClearTag_Gc3210I;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
rt_kprintf ("Unknown CPU type, system halted!\n");
|
|
|
|
while (1) {}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void probe_cache(void)
|
|
|
|
{
|
|
|
|
unsigned int config = read_c0_config ();
|
|
|
|
unsigned int icache_size, ic_lsize;
|
|
|
|
unsigned int dcache_size, dc_lsize;
|
|
|
|
|
|
|
|
icache_size = 1 << (12 + ((config >> 9) & 7));
|
|
|
|
dcache_size = 1 << (12 + ((config >> 6) & 7));
|
|
|
|
ic_lsize = 16 << ((config >> 5) & 1);
|
|
|
|
dc_lsize = 16 << ((config >> 4) & 1);
|
|
|
|
|
|
|
|
rt_kprintf("DCache %2dkb, linesize %d bytes.\n",
|
|
|
|
dcache_size >> 10, dc_lsize);
|
|
|
|
rt_kprintf("ICache %2dkb, linesize %d bytes.\n",
|
|
|
|
icache_size >> 10, ic_lsize);
|
|
|
|
|
|
|
|
pcacheinfo->icache_size = icache_size;
|
|
|
|
pcacheinfo->dcache_size = dcache_size;
|
|
|
|
pcacheinfo->icacheline_size = ic_lsize;
|
|
|
|
pcacheinfo->dcacheline_size = dc_lsize;
|
|
|
|
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
void invalidate_writeback_dcache_all(void)
|
|
|
|
{
|
|
|
|
unsigned int start = K0BASE;
|
|
|
|
unsigned int end = (start + pcacheinfo->dcache_size);
|
|
|
|
|
|
|
|
start = K0BASE;
|
|
|
|
while(start < end) {
|
|
|
|
Writeback_Invalidate_Dcache(start); //hit writeback invalidate
|
|
|
|
start += pcacheinfo->dcacheline_size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void invalidate_writeback_dcache(unsigned long addr, int size)
|
|
|
|
{
|
|
|
|
unsigned long start, end;
|
|
|
|
|
|
|
|
start = (addr +pcacheinfo->dcacheline_size -1) & (- pcacheinfo->dcacheline_size);
|
|
|
|
end = (end + size + pcacheinfo->dcacheline_size -1) & ( -pcacheinfo->dcacheline_size);
|
|
|
|
|
|
|
|
while(start <end){
|
|
|
|
Writeback_Invalidate_Dcache(start);
|
|
|
|
start += pcacheinfo->dcacheline_size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void invalidate_icache_all(void)
|
|
|
|
{
|
|
|
|
unsigned int start = K0BASE;
|
|
|
|
unsigned int end = (start + pcacheinfo->icache_size);
|
|
|
|
|
|
|
|
while(start < end) {
|
|
|
|
pcacheop->Invalidate_Icache(start);
|
|
|
|
start += pcacheinfo->icacheline_size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void invalidate_dcache_all()
|
|
|
|
{
|
|
|
|
unsigned int start = K0BASE;
|
|
|
|
unsigned int end = (start + pcacheinfo->dcache_size);
|
|
|
|
while(start <end){
|
|
|
|
Invalidate_Dcache_Fill_Gc3210I(start);
|
|
|
|
start += pcacheinfo->icacheline_size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//with cache disabled
|
|
|
|
void init_dcache(void)
|
|
|
|
{
|
|
|
|
unsigned int start = K0BASE;
|
|
|
|
unsigned int end = (start + pcacheinfo->dcache_size);
|
|
|
|
|
|
|
|
while(start < end){
|
|
|
|
pcacheop->Invalidate_Dcache_ClearTag(start);
|
|
|
|
start += pcacheinfo->dcacheline_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void rt_hw_cache_init(void)
|
|
|
|
{
|
|
|
|
unsigned int start, end;
|
|
|
|
|
|
|
|
/* 1. identify cpu and probe cache */
|
|
|
|
identify_cpu();
|
|
|
|
probe_cache();
|
|
|
|
|
|
|
|
start = K0BASE;
|
|
|
|
end = (start + pcacheinfo->icache_size);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 2. clear CP0 taglo/taghi register;
|
|
|
|
*/
|
|
|
|
pcacheop->Clear_TagLo();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 3. invalidate instruction cache;
|
|
|
|
*/
|
|
|
|
while(start < end) {
|
|
|
|
pcacheop->Invalidate_Icache(start); //index invalidate icache
|
|
|
|
start += pcacheinfo->icacheline_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 4. invalidate data cache;
|
|
|
|
*/
|
|
|
|
start = K0BASE;
|
|
|
|
end = (start + pcacheinfo->dcache_size);
|
|
|
|
while(start < end) {
|
|
|
|
pcacheop->Invalidate_Dcache_ClearTag(start);
|
|
|
|
start += pcacheinfo->dcacheline_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
start = K0BASE;
|
|
|
|
while(start < end) {
|
|
|
|
pcacheop->Invalidate_Dcache_Fill(start); //index invalidate dcache
|
|
|
|
start += pcacheinfo->dcacheline_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
start = K0BASE;
|
|
|
|
while(start < end) {
|
|
|
|
pcacheop->Invalidate_Dcache_ClearTag(start);
|
|
|
|
start += pcacheinfo->dcacheline_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* enable cache */
|
|
|
|
enable_cpu_cache();
|
|
|
|
rt_kprintf("enable cpu cache done\n");
|
|
|
|
|
|
|
|
return ;
|
|
|
|
}
|