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