xref: /nrf52832-nimble/rt-thread/libcpu/mips/loongson_1b/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  */
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