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
identify_cpu(void)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
probe_cache(void)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
invalidate_writeback_dcache_all(void)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
invalidate_writeback_dcache(unsigned long addr,int size)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
invalidate_icache_all(void)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
invalidate_dcache_all(void)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
init_dcache(void)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
rt_hw_cache_init(void)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