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