1*10465441SEvalZero /*
2*10465441SEvalZero * File : mipscfg.c
3*10465441SEvalZero * COPYRIGHT (C) 2008 - 2016, RT-Thread Development Team
4*10465441SEvalZero *
5*10465441SEvalZero * This program is free software; you can redistribute it and/or modify
6*10465441SEvalZero * it under the terms of the GNU General Public License as published by
7*10465441SEvalZero * the Free Software Foundation; either version 2 of the License, or
8*10465441SEvalZero * (at your option) any later version.
9*10465441SEvalZero *
10*10465441SEvalZero * This program is distributed in the hope that it will be useful,
11*10465441SEvalZero * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*10465441SEvalZero * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13*10465441SEvalZero * GNU General Public License for more details.
14*10465441SEvalZero *
15*10465441SEvalZero * You should have received a copy of the GNU General Public License along
16*10465441SEvalZero * with this program; if not, write to the Free Software Foundation, Inc.,
17*10465441SEvalZero * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18*10465441SEvalZero *
19*10465441SEvalZero * Change Logs:
20*10465441SEvalZero * Date Author Notes
21*10465441SEvalZero * 2010-05-27 swkyer first version
22*10465441SEvalZero */
23*10465441SEvalZero #include <rtthread.h>
24*10465441SEvalZero #include "../common/mipsregs.h"
25*10465441SEvalZero #include "../common/mipscfg.h"
26*10465441SEvalZero
27*10465441SEvalZero mips32_core_cfg_t g_mips_core =
28*10465441SEvalZero {
29*10465441SEvalZero 16, /* icache_line_size */
30*10465441SEvalZero 256, /* icache_lines_per_way */
31*10465441SEvalZero 4, /* icache_ways */
32*10465441SEvalZero 16, /* dcache_line_size */
33*10465441SEvalZero 256, /* dcache_lines_per_way */
34*10465441SEvalZero 4, /* dcache_ways */
35*10465441SEvalZero 16, /* max_tlb_entries */
36*10465441SEvalZero };
37*10465441SEvalZero
m_pow(rt_uint16_t b,rt_uint16_t n)38*10465441SEvalZero static rt_uint16_t m_pow(rt_uint16_t b, rt_uint16_t n)
39*10465441SEvalZero {
40*10465441SEvalZero rt_uint16_t rets = 1;
41*10465441SEvalZero
42*10465441SEvalZero while (n--)
43*10465441SEvalZero rets *= b;
44*10465441SEvalZero
45*10465441SEvalZero return rets;
46*10465441SEvalZero }
47*10465441SEvalZero
48*10465441SEvalZero /**
49*10465441SEvalZero * read core attribute
50*10465441SEvalZero */
mips32_cfg_init(void)51*10465441SEvalZero void mips32_cfg_init(void)
52*10465441SEvalZero {
53*10465441SEvalZero rt_uint16_t val;
54*10465441SEvalZero rt_uint32_t cp0_config1;
55*10465441SEvalZero
56*10465441SEvalZero cp0_config1 = read_c0_config();
57*10465441SEvalZero if (cp0_config1 & 0x80000000)
58*10465441SEvalZero {
59*10465441SEvalZero cp0_config1 = read_c0_config1();
60*10465441SEvalZero
61*10465441SEvalZero val = (cp0_config1 & (7<<22))>>22;
62*10465441SEvalZero g_mips_core.icache_lines_per_way = 64 * m_pow(2, val);
63*10465441SEvalZero val = (cp0_config1 & (7<<19))>>19;
64*10465441SEvalZero g_mips_core.icache_line_size = 2 * m_pow(2, val);
65*10465441SEvalZero val = (cp0_config1 & (7<<16))>>16;
66*10465441SEvalZero g_mips_core.icache_ways = val + 1;
67*10465441SEvalZero
68*10465441SEvalZero val = (cp0_config1 & (7<<13))>>13;
69*10465441SEvalZero g_mips_core.dcache_lines_per_way = 64 * m_pow(2, val);
70*10465441SEvalZero val = (cp0_config1 & (7<<10))>>10;
71*10465441SEvalZero g_mips_core.dcache_line_size = 2 * m_pow(2, val);
72*10465441SEvalZero val = (cp0_config1 & (7<<7))>>7;
73*10465441SEvalZero g_mips_core.dcache_ways = val + 1;
74*10465441SEvalZero
75*10465441SEvalZero val = (cp0_config1 & (0x3F<<25))>>25;
76*10465441SEvalZero g_mips_core.max_tlb_entries = val + 1;
77*10465441SEvalZero }
78*10465441SEvalZero }
79*10465441SEvalZero
80*10465441SEvalZero #ifdef RT_USING_FINSH
81*10465441SEvalZero #include <finsh.h>
CP0_status_analyze(unsigned long value)82*10465441SEvalZero static void CP0_status_analyze(unsigned long value)
83*10465441SEvalZero {
84*10465441SEvalZero if(value & (1<<26))
85*10465441SEvalZero rt_kprintf(" FR");
86*10465441SEvalZero if(value & (1<<23))
87*10465441SEvalZero rt_kprintf(" PX");
88*10465441SEvalZero if(value & (1<<22))
89*10465441SEvalZero rt_kprintf(" BEV");
90*10465441SEvalZero if(value & (1<<20))
91*10465441SEvalZero rt_kprintf(" SR");
92*10465441SEvalZero if(value & (1<<19))
93*10465441SEvalZero rt_kprintf(" NMI");
94*10465441SEvalZero if(value & (1<<20))
95*10465441SEvalZero rt_kprintf(" SR");
96*10465441SEvalZero if(value & (0xFF<<8))
97*10465441SEvalZero rt_kprintf(" IM:0x%02X", (value >> 8) & 0xFF);
98*10465441SEvalZero if(value & (1<<7))
99*10465441SEvalZero rt_kprintf(" KX");
100*10465441SEvalZero if(value & (1<<6))
101*10465441SEvalZero rt_kprintf(" SX");
102*10465441SEvalZero if(value & (1<<5))
103*10465441SEvalZero rt_kprintf(" UX");
104*10465441SEvalZero if(value & (0x03<<3))
105*10465441SEvalZero rt_kprintf(" KSU:0x%02X", (value >> 3) & 0x03);
106*10465441SEvalZero if(value & (1<<2))
107*10465441SEvalZero rt_kprintf(" ERL");
108*10465441SEvalZero if(value & (1<<1))
109*10465441SEvalZero rt_kprintf(" EXL");
110*10465441SEvalZero if(value & (1<<0))
111*10465441SEvalZero rt_kprintf(" IE");
112*10465441SEvalZero }
113*10465441SEvalZero
CP0_config0_analyze(unsigned long value)114*10465441SEvalZero static void CP0_config0_analyze(unsigned long value)
115*10465441SEvalZero {
116*10465441SEvalZero /* [31] M */
117*10465441SEvalZero if(value & (1UL<<31))
118*10465441SEvalZero rt_kprintf(" M");
119*10465441SEvalZero
120*10465441SEvalZero /* [15] BE */
121*10465441SEvalZero if(value & (1<<15))
122*10465441SEvalZero rt_kprintf(" big-endian");
123*10465441SEvalZero else
124*10465441SEvalZero rt_kprintf(" little-endian");
125*10465441SEvalZero
126*10465441SEvalZero /* [14:13] AT */
127*10465441SEvalZero {
128*10465441SEvalZero int AT = (value >> 13) & 0x03;
129*10465441SEvalZero
130*10465441SEvalZero if(AT == 0)
131*10465441SEvalZero {
132*10465441SEvalZero rt_kprintf(" MIPS32");
133*10465441SEvalZero }
134*10465441SEvalZero else if(AT == 1)
135*10465441SEvalZero {
136*10465441SEvalZero rt_kprintf(" MIPS64/A32");
137*10465441SEvalZero }
138*10465441SEvalZero else if(AT == 2)
139*10465441SEvalZero {
140*10465441SEvalZero rt_kprintf(" MIPS64/A64");
141*10465441SEvalZero }
142*10465441SEvalZero else
143*10465441SEvalZero {
144*10465441SEvalZero rt_kprintf(" unkown");
145*10465441SEvalZero }
146*10465441SEvalZero }
147*10465441SEvalZero
148*10465441SEvalZero /* [12:10] AR */
149*10465441SEvalZero {
150*10465441SEvalZero int AR = (value >> 10) & 0x07;
151*10465441SEvalZero
152*10465441SEvalZero if(AR == 0)
153*10465441SEvalZero {
154*10465441SEvalZero rt_kprintf(" R1");
155*10465441SEvalZero }
156*10465441SEvalZero else if(AR == 1)
157*10465441SEvalZero {
158*10465441SEvalZero rt_kprintf(" R2");
159*10465441SEvalZero }
160*10465441SEvalZero else
161*10465441SEvalZero {
162*10465441SEvalZero rt_kprintf(" reserve");
163*10465441SEvalZero }
164*10465441SEvalZero }
165*10465441SEvalZero
166*10465441SEvalZero /* [3] VI */
167*10465441SEvalZero if(value & (1UL<<31))
168*10465441SEvalZero rt_kprintf(" VI");
169*10465441SEvalZero
170*10465441SEvalZero /* [2:0] K0 */
171*10465441SEvalZero {
172*10465441SEvalZero int K0 = value & 0x07;
173*10465441SEvalZero
174*10465441SEvalZero if(K0 == 2)
175*10465441SEvalZero {
176*10465441SEvalZero rt_kprintf(" uncached");
177*10465441SEvalZero }
178*10465441SEvalZero else if(K0 == 3)
179*10465441SEvalZero {
180*10465441SEvalZero rt_kprintf(" cacheable");
181*10465441SEvalZero }
182*10465441SEvalZero else
183*10465441SEvalZero {
184*10465441SEvalZero rt_kprintf(" K0:reserve");
185*10465441SEvalZero }
186*10465441SEvalZero }
187*10465441SEvalZero }
188*10465441SEvalZero
CP0_config1_analyze(unsigned long value)189*10465441SEvalZero static void CP0_config1_analyze(unsigned long value)
190*10465441SEvalZero {
191*10465441SEvalZero /* [31] M */
192*10465441SEvalZero if(value & (1UL<<31))
193*10465441SEvalZero rt_kprintf(" M");
194*10465441SEvalZero
195*10465441SEvalZero /* [30:25] MMU size */
196*10465441SEvalZero {
197*10465441SEvalZero int MMU_size = (value >> 25) & 0x3F;
198*10465441SEvalZero rt_kprintf(" TLB:%d", MMU_size + 1);
199*10465441SEvalZero }
200*10465441SEvalZero
201*10465441SEvalZero /* [24:22] IS, [21:19] IL, [18:16] IA */
202*10465441SEvalZero {
203*10465441SEvalZero int IS = (value >> 22) & 0x07;
204*10465441SEvalZero int IL = (value >> 19) & 0x07;
205*10465441SEvalZero int IA = (value >> 16) & 0x07;
206*10465441SEvalZero
207*10465441SEvalZero IA = IA + 1;
208*10465441SEvalZero IS = 64 << IS;
209*10465441SEvalZero IL = 2 << IL;
210*10465441SEvalZero rt_kprintf(" Icache-%dKB:%dway*%dset*%dbyte",
211*10465441SEvalZero (IA*IS*IL) >> 10, IA, IS, IL);
212*10465441SEvalZero }
213*10465441SEvalZero
214*10465441SEvalZero /* [15:13] DS, [12:10] DL, [9:7] DA */
215*10465441SEvalZero {
216*10465441SEvalZero int DS = (value >> 13) & 0x07;
217*10465441SEvalZero int DL = (value >> 10) & 0x07;
218*10465441SEvalZero int DA = (value >> 7) & 0x07;
219*10465441SEvalZero
220*10465441SEvalZero DA = DA + 1;
221*10465441SEvalZero DS = 64 << DS;
222*10465441SEvalZero DL = 2 << DL;
223*10465441SEvalZero rt_kprintf(" Dcache-%dKB:%dway*%dset*%dbyte",
224*10465441SEvalZero (DA*DS*DL) >> 10, DA, DS, DL);
225*10465441SEvalZero }
226*10465441SEvalZero
227*10465441SEvalZero /* [6] C2 */
228*10465441SEvalZero if(value & (1UL<<6))
229*10465441SEvalZero rt_kprintf(" CP2");
230*10465441SEvalZero
231*10465441SEvalZero /* [5] MD */
232*10465441SEvalZero if(value & (1UL<<5))
233*10465441SEvalZero rt_kprintf(" MDMX-ASE");
234*10465441SEvalZero
235*10465441SEvalZero /* [4] PC */
236*10465441SEvalZero if(value & (1UL<<4))
237*10465441SEvalZero rt_kprintf(" performa-count");
238*10465441SEvalZero
239*10465441SEvalZero /* [3] WR */
240*10465441SEvalZero if(value & (1UL<<3))
241*10465441SEvalZero rt_kprintf(" Watch");
242*10465441SEvalZero
243*10465441SEvalZero /* [2] CA */
244*10465441SEvalZero if(value & (1UL<<2))
245*10465441SEvalZero rt_kprintf(" MIPS16e");
246*10465441SEvalZero
247*10465441SEvalZero /* [1] EP */
248*10465441SEvalZero if(value & (1UL<<1))
249*10465441SEvalZero rt_kprintf(" EJTAG");
250*10465441SEvalZero
251*10465441SEvalZero /* [0] FP */
252*10465441SEvalZero if(value & (1UL<<0))
253*10465441SEvalZero rt_kprintf(" FPU");
254*10465441SEvalZero }
255*10465441SEvalZero
CP0_config2_analyze(unsigned long value)256*10465441SEvalZero static void CP0_config2_analyze(unsigned long value)
257*10465441SEvalZero {
258*10465441SEvalZero /* [31] M */
259*10465441SEvalZero if(value & (1UL<<31))
260*10465441SEvalZero rt_kprintf(" M");
261*10465441SEvalZero }
262*10465441SEvalZero
CP0_config3_analyze(unsigned long value)263*10465441SEvalZero static void CP0_config3_analyze(unsigned long value)
264*10465441SEvalZero {
265*10465441SEvalZero /* [31] M */
266*10465441SEvalZero if(value & (1UL<<31))
267*10465441SEvalZero rt_kprintf(" M");
268*10465441SEvalZero }
269*10465441SEvalZero
list_mips(void)270*10465441SEvalZero static void list_mips(void)
271*10465441SEvalZero {
272*10465441SEvalZero unsigned long value;
273*10465441SEvalZero unsigned long num = 0;
274*10465441SEvalZero
275*10465441SEvalZero rt_kprintf("MIPS coprocessor register:\r\n");
276*10465441SEvalZero
277*10465441SEvalZero rt_kprintf("( 0,0) INDEX : 0x%08X\r\n", read_c0_index());
278*10465441SEvalZero rt_kprintf("( 1,0) RANDOM : 0x%08X\r\n", read_c0_random());
279*10465441SEvalZero rt_kprintf("( 2,0) ENTRYLO0 : 0x%08X\r\n", read_c0_entrylo0());
280*10465441SEvalZero rt_kprintf("( 3,0) ENTRYLO1 : 0x%08X\r\n", read_c0_entrylo1());
281*10465441SEvalZero rt_kprintf("( 4,0) CONTEXT : 0x%08X\r\n", read_c0_context());
282*10465441SEvalZero rt_kprintf("( 5,0) PAGEMASK : 0x%08X\r\n", read_c0_pagemask());
283*10465441SEvalZero rt_kprintf("( 6,0) WIRED : 0x%08X\r\n", read_c0_wired());
284*10465441SEvalZero rt_kprintf("( 7,0) INFO : 0x%08X\r\n", read_c0_info());
285*10465441SEvalZero rt_kprintf("( 8,0) BADVADDR : 0x%08X\r\n", read_c0_badvaddr());
286*10465441SEvalZero rt_kprintf("( 9,0) COUNT : 0x%08X\r\n", read_c0_count());
287*10465441SEvalZero rt_kprintf("(10,0) ENTRYHI : 0x%08X\r\n", read_c0_entryhi());
288*10465441SEvalZero rt_kprintf("(11,0) COMPARE : 0x%08X\r\n", read_c0_compare());
289*10465441SEvalZero
290*10465441SEvalZero value = read_c0_status();
291*10465441SEvalZero rt_kprintf("(12,0) STATUS : 0x%08X", value);
292*10465441SEvalZero CP0_status_analyze(value);
293*10465441SEvalZero rt_kprintf("\r\n");
294*10465441SEvalZero
295*10465441SEvalZero /*
296*10465441SEvalZero rt_kprintf("(12,1) INTCTL : 0x%08X\r\n", __read_32bit_c0_register(12, 1));
297*10465441SEvalZero rt_kprintf("(12,2) SRSCTL : 0x%08X\r\n", __read_32bit_c0_register(12, 2));
298*10465441SEvalZero */
299*10465441SEvalZero
300*10465441SEvalZero rt_kprintf("(13,0) CAUSE : 0x%08X\r\n", read_c0_cause());
301*10465441SEvalZero rt_kprintf("(14,0) EPC : 0x%08X\r\n", read_c0_epc());
302*10465441SEvalZero rt_kprintf("(15,0) PRID : 0x%08X\r\n", read_c0_prid());
303*10465441SEvalZero rt_kprintf("(15,1) EBASE : 0x%08X\r\n", read_c0_ebase());
304*10465441SEvalZero
305*10465441SEvalZero value = read_c0_config();
306*10465441SEvalZero rt_kprintf("(16,0) CONFIG : 0x%08X", value);
307*10465441SEvalZero CP0_config0_analyze(value);
308*10465441SEvalZero rt_kprintf("\r\n");
309*10465441SEvalZero if(value & (1UL << 31))
310*10465441SEvalZero {
311*10465441SEvalZero value = read_c0_config1();
312*10465441SEvalZero rt_kprintf("(16,1) CONFIG1 : 0x%08X", value);
313*10465441SEvalZero CP0_config1_analyze(value);
314*10465441SEvalZero rt_kprintf("\r\n");
315*10465441SEvalZero
316*10465441SEvalZero if(value & (1UL << 31))
317*10465441SEvalZero {
318*10465441SEvalZero value = read_c0_config2();
319*10465441SEvalZero rt_kprintf("(16,2) CONFIG2 : 0x%08X\r\n", value);
320*10465441SEvalZero CP0_config2_analyze(value);
321*10465441SEvalZero rt_kprintf("\r\n");
322*10465441SEvalZero
323*10465441SEvalZero if(value & (1UL << 31))
324*10465441SEvalZero {
325*10465441SEvalZero value = read_c0_config3();
326*10465441SEvalZero rt_kprintf("(16,3) CONFIG3 : 0x%08X\r\n", value);
327*10465441SEvalZero CP0_config3_analyze(value);
328*10465441SEvalZero rt_kprintf("\r\n");
329*10465441SEvalZero }
330*10465441SEvalZero }
331*10465441SEvalZero }
332*10465441SEvalZero
333*10465441SEvalZero rt_kprintf("(17,0) LLADDR : 0x%08X\r\n", __read_32bit_c0_register($17, 0));
334*10465441SEvalZero rt_kprintf("(18,0) WATCHLO : 0x%08X\r\n", __read_32bit_c0_register($18, 0));
335*10465441SEvalZero rt_kprintf("(19,0) WATCHHI : 0x%08X\r\n", __read_32bit_c0_register($19, 0));
336*10465441SEvalZero rt_kprintf("(20,0) XCONTEXT : 0x%08X\r\n", __read_32bit_c0_register($20, 0));
337*10465441SEvalZero rt_kprintf("(21,0) FRAMEMASK : 0x%08X\r\n", __read_32bit_c0_register($21, 0));
338*10465441SEvalZero rt_kprintf("(22,0) DIAGNOSTIC: 0x%08X\r\n", __read_32bit_c0_register($22, 0));
339*10465441SEvalZero rt_kprintf("(23,0) DEBUG : 0x%08X\r\n", __read_32bit_c0_register($23, 0));
340*10465441SEvalZero rt_kprintf("(24,0) DEPC : 0x%08X\r\n", __read_32bit_c0_register($24, 0));
341*10465441SEvalZero
342*10465441SEvalZero rt_kprintf("(25,0) PERFCTL0 : 0x%08X\r\n", __read_32bit_c0_register($25, 0));
343*10465441SEvalZero rt_kprintf("(26,0) ECC : 0x%08X\r\n", __read_32bit_c0_register($26, 0));
344*10465441SEvalZero rt_kprintf("(27,0) CACHEERR : 0x%08X\r\n", __read_32bit_c0_register($27, 0));
345*10465441SEvalZero rt_kprintf("(28,0) TAGLO : 0x%08X\r\n", __read_32bit_c0_register($28, 0));
346*10465441SEvalZero rt_kprintf("(29,0) TAGHI : 0x%08X\r\n", __read_32bit_c0_register($29, 0));
347*10465441SEvalZero
348*10465441SEvalZero /*
349*10465441SEvalZero rt_kprintf("(30,0) ERROREPC : 0x%08X\r\n", __read_32bit_c0_register($30, 0));
350*10465441SEvalZero rt_kprintf("(31,0) DESAVE : 0x%08X\r\n", __read_32bit_c0_register($31, 0));
351*10465441SEvalZero */
352*10465441SEvalZero
353*10465441SEvalZero
354*10465441SEvalZero rt_kprintf("\r\n");
355*10465441SEvalZero }
356*10465441SEvalZero FINSH_FUNCTION_EXPORT(list_mips, list CPU info)
357*10465441SEvalZero #endif /* RT_USING_FINSH */
358*10465441SEvalZero
359