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