xref: /nrf52832-nimble/rt-thread/libcpu/mips/loongson_1c/cache.c (revision 104654410c56c573564690304ae786df310c91fc)
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