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