1 /* 2 * File : cache.c 3 * This file is part of RT-Thread RTOS 4 * COPYRIGHT (C) 2006 - 2011, RT-Thread Development Team 5 * 6 * The license and distribution terms for this file may be 7 * found in the file LICENSE in this distribution or at 8 * http://www.rt-thread.org/license/LICENSE 9 * 10 * Change Logs: 11 * Date Author Notes 12 * 2010-07-09 Bernard first version 13 * 2011-08-08 lgnq modified for LS1B 14 */ 15 16 #include <rtthread.h> 17 #include "../common/mipsregs.h" 18 19 #define K0BASE 0x80000000 20 #define PRID_LS1B 0x4220 21 22 extern void Clear_TagLo (void); 23 extern void Invalidate_Icache_Ls1b(unsigned int); 24 extern void Invalidate_Dcache_ClearTag_Ls1b(unsigned int); 25 extern void Invalidate_Dcache_Fill_Ls1b(unsigned int); 26 extern void Writeback_Invalidate_Dcache(unsigned int); 27 extern void enable_cpu_cache(void); 28 29 typedef struct cacheinfo_t 30 { 31 unsigned int icache_size; 32 unsigned int dcache_size; 33 unsigned int icacheline_size; 34 unsigned int dcacheline_size; 35 } cacheinfo_t ; 36 37 typedef struct cacheop_t 38 { 39 void (*Clear_TagLo) (void); 40 void (*Invalidate_Icache) (unsigned int); 41 void (*Invalidate_Dcache_Fill) (unsigned int); 42 void (*Invalidate_Dcache_ClearTag) (unsigned int); 43 void (*Init_Cache)(void); 44 } cacheop_t ; 45 46 static cacheop_t cacheop, *pcacheop; 47 static cacheinfo_t cacheinfo, *pcacheinfo; 48 49 int identify_cpu(void) 50 { 51 unsigned int cpu_id; 52 53 pcacheop = &cacheop; 54 pcacheinfo = &cacheinfo; 55 56 rt_kprintf("CPU configure: 0x%08x\n", read_c0_config()); 57 cpu_id = read_c0_prid(); 58 switch (cpu_id) 59 { 60 case PRID_LS1B: 61 rt_kprintf("CPU:LS1B\n"); 62 pcacheop->Clear_TagLo = Clear_TagLo; 63 pcacheop->Invalidate_Icache = Invalidate_Icache_Ls1b; 64 pcacheop->Invalidate_Dcache_Fill = Invalidate_Dcache_Fill_Ls1b; 65 pcacheop->Invalidate_Dcache_ClearTag = Invalidate_Dcache_ClearTag_Ls1b; 66 break; 67 default: 68 rt_kprintf("Unknown CPU type, system halted!\n"); 69 while (1) 70 { 71 ; 72 } 73 break; 74 } 75 76 return 0; 77 } 78 79 void probe_cache(void) 80 { 81 unsigned int config1 = read_c0_config1(); 82 unsigned int icache_size, icache_line_size, icache_sets, icache_ways; 83 unsigned int dcache_size, dcache_line_size, dcache_sets, dcache_ways; 84 85 if ((icache_line_size = ((config1 >> 19) & 7))) 86 icache_line_size = 2 << icache_line_size; 87 else 88 icache_line_size = icache_line_size; 89 icache_sets = 64 << ((config1 >> 22) & 7); 90 icache_ways = 1 + ((config1 >> 16) & 7); 91 icache_size = icache_sets * icache_ways * icache_line_size; 92 93 if ((dcache_line_size = ((config1 >> 10) & 7))) 94 dcache_line_size = 2 << dcache_line_size; 95 else 96 dcache_line_size = dcache_line_size; 97 dcache_sets = 64 << ((config1 >> 13) & 7); 98 dcache_ways = 1 + ((config1 >> 7) & 7); 99 dcache_size = dcache_sets * dcache_ways * dcache_line_size; 100 101 rt_kprintf("DCache %2dkb, linesize %d bytes.\n", dcache_size >> 10, dcache_line_size); 102 rt_kprintf("ICache %2dkb, linesize %d bytes.\n", icache_size >> 10, icache_line_size); 103 104 pcacheinfo->icache_size = icache_size; 105 pcacheinfo->dcache_size = dcache_size; 106 pcacheinfo->icacheline_size = icache_line_size; 107 pcacheinfo->dcacheline_size = dcache_line_size; 108 109 return ; 110 } 111 112 void invalidate_writeback_dcache_all(void) 113 { 114 unsigned int start = K0BASE; 115 unsigned int end = (start + pcacheinfo->dcache_size); 116 117 while (start < end) 118 { 119 Writeback_Invalidate_Dcache(start); //hit writeback invalidate 120 start += pcacheinfo->dcacheline_size; 121 } 122 } 123 124 void invalidate_writeback_dcache(unsigned long addr, int size) 125 { 126 unsigned long start, end; 127 128 start = (addr +pcacheinfo->dcacheline_size -1) & (- pcacheinfo->dcacheline_size); 129 end = (end + size + pcacheinfo->dcacheline_size -1) & ( -pcacheinfo->dcacheline_size); 130 131 while (start <end) 132 { 133 Writeback_Invalidate_Dcache(start); 134 start += pcacheinfo->dcacheline_size; 135 } 136 } 137 138 void invalidate_icache_all(void) 139 { 140 unsigned int start = K0BASE; 141 unsigned int end = (start + pcacheinfo->icache_size); 142 143 while (start < end) 144 { 145 pcacheop->Invalidate_Icache(start); 146 start += pcacheinfo->icacheline_size; 147 } 148 } 149 150 void invalidate_dcache_all(void) 151 { 152 unsigned int start = K0BASE; 153 unsigned int end = (start + pcacheinfo->dcache_size); 154 while (start <end) 155 { 156 Invalidate_Dcache_Fill_Ls1b(start); 157 start += pcacheinfo->icacheline_size; 158 } 159 } 160 161 //with cache disabled 162 void init_dcache(void) 163 { 164 unsigned int start = K0BASE; 165 unsigned int end = (start + pcacheinfo->dcache_size); 166 167 while (start < end) 168 { 169 pcacheop->Invalidate_Dcache_ClearTag(start); 170 start += pcacheinfo->dcacheline_size; 171 } 172 173 } 174 175 void rt_hw_cache_init(void) 176 { 177 unsigned int start, end; 178 179 /* 1. identify cpu and probe cache */ 180 identify_cpu(); 181 probe_cache(); 182 183 start = K0BASE; 184 end = (start + pcacheinfo->icache_size); 185 186 /* 187 * 2. clear CP0 taglo/taghi register; 188 */ 189 pcacheop->Clear_TagLo(); 190 191 /* 192 * 3. invalidate instruction cache; 193 */ 194 while (start < end) 195 { 196 pcacheop->Invalidate_Icache(start); //index invalidate icache 197 start += pcacheinfo->icacheline_size; 198 } 199 200 /* 201 * 4. invalidate data cache; 202 */ 203 start = K0BASE; 204 end = (start + pcacheinfo->dcache_size); 205 while(start < end) 206 { 207 pcacheop->Invalidate_Dcache_ClearTag(start); 208 start += pcacheinfo->dcacheline_size; 209 } 210 211 start = K0BASE; 212 while(start < end) 213 { 214 pcacheop->Invalidate_Dcache_Fill(start); //index invalidate dcache 215 start += pcacheinfo->dcacheline_size; 216 } 217 218 start = K0BASE; 219 while(start < end) 220 { 221 pcacheop->Invalidate_Dcache_ClearTag(start); 222 start += pcacheinfo->dcacheline_size; 223 } 224 225 /* enable cache */ 226 enable_cpu_cache(); 227 rt_kprintf("enable cpu cache done\n"); 228 229 return ; 230 } 231