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