xref: /OK3568_Linux_fs/kernel/arch/sh/kernel/cpu/sh4/probe.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * arch/sh/kernel/cpu/sh4/probe.c
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * CPU Subtype Probing for SH-4.
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Copyright (C) 2001 - 2007  Paul Mundt
8*4882a593Smuzhiyun  * Copyright (C) 2003  Richard Curnow
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun #include <linux/init.h>
11*4882a593Smuzhiyun #include <linux/io.h>
12*4882a593Smuzhiyun #include <asm/processor.h>
13*4882a593Smuzhiyun #include <asm/cache.h>
14*4882a593Smuzhiyun 
cpu_probe(void)15*4882a593Smuzhiyun void cpu_probe(void)
16*4882a593Smuzhiyun {
17*4882a593Smuzhiyun 	unsigned long pvr, prr, cvr;
18*4882a593Smuzhiyun 	unsigned long size;
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun 	static unsigned long sizes[16] = {
21*4882a593Smuzhiyun 		[1] = (1 << 12),
22*4882a593Smuzhiyun 		[2] = (1 << 13),
23*4882a593Smuzhiyun 		[4] = (1 << 14),
24*4882a593Smuzhiyun 		[8] = (1 << 15),
25*4882a593Smuzhiyun 		[9] = (1 << 16)
26*4882a593Smuzhiyun 	};
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun 	pvr = (__raw_readl(CCN_PVR) >> 8) & 0xffffff;
29*4882a593Smuzhiyun 	prr = (__raw_readl(CCN_PRR) >> 4) & 0xff;
30*4882a593Smuzhiyun 	cvr = (__raw_readl(CCN_CVR));
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun 	/*
33*4882a593Smuzhiyun 	 * Setup some sane SH-4 defaults for the icache
34*4882a593Smuzhiyun 	 */
35*4882a593Smuzhiyun 	boot_cpu_data.icache.way_incr		= (1 << 13);
36*4882a593Smuzhiyun 	boot_cpu_data.icache.entry_shift	= 5;
37*4882a593Smuzhiyun 	boot_cpu_data.icache.sets		= 256;
38*4882a593Smuzhiyun 	boot_cpu_data.icache.ways		= 1;
39*4882a593Smuzhiyun 	boot_cpu_data.icache.linesz		= L1_CACHE_BYTES;
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun 	/*
42*4882a593Smuzhiyun 	 * And again for the dcache ..
43*4882a593Smuzhiyun 	 */
44*4882a593Smuzhiyun 	boot_cpu_data.dcache.way_incr		= (1 << 14);
45*4882a593Smuzhiyun 	boot_cpu_data.dcache.entry_shift	= 5;
46*4882a593Smuzhiyun 	boot_cpu_data.dcache.sets		= 512;
47*4882a593Smuzhiyun 	boot_cpu_data.dcache.ways		= 1;
48*4882a593Smuzhiyun 	boot_cpu_data.dcache.linesz		= L1_CACHE_BYTES;
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	/* We don't know the chip cut */
51*4882a593Smuzhiyun 	boot_cpu_data.cut_major = boot_cpu_data.cut_minor = -1;
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 	/*
54*4882a593Smuzhiyun 	 * Setup some generic flags we can probe on SH-4A parts
55*4882a593Smuzhiyun 	 */
56*4882a593Smuzhiyun 	if (((pvr >> 16) & 0xff) == 0x10) {
57*4882a593Smuzhiyun 		boot_cpu_data.family = CPU_FAMILY_SH4A;
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 		if ((cvr & 0x10000000) == 0) {
60*4882a593Smuzhiyun 			boot_cpu_data.flags |= CPU_HAS_DSP;
61*4882a593Smuzhiyun 			boot_cpu_data.family = CPU_FAMILY_SH4AL_DSP;
62*4882a593Smuzhiyun 		}
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 		boot_cpu_data.flags |= CPU_HAS_LLSC | CPU_HAS_PERF_COUNTER;
65*4882a593Smuzhiyun 		boot_cpu_data.cut_major = pvr & 0x7f;
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 		boot_cpu_data.icache.ways = 4;
68*4882a593Smuzhiyun 		boot_cpu_data.dcache.ways = 4;
69*4882a593Smuzhiyun 	} else {
70*4882a593Smuzhiyun 		/* And some SH-4 defaults.. */
71*4882a593Smuzhiyun 		boot_cpu_data.flags |= CPU_HAS_PTEA | CPU_HAS_FPU;
72*4882a593Smuzhiyun 		boot_cpu_data.family = CPU_FAMILY_SH4;
73*4882a593Smuzhiyun 	}
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	/* FPU detection works for almost everyone */
76*4882a593Smuzhiyun 	if ((cvr & 0x20000000))
77*4882a593Smuzhiyun 		boot_cpu_data.flags |= CPU_HAS_FPU;
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	/* Mask off the upper chip ID */
80*4882a593Smuzhiyun 	pvr &= 0xffff;
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 	/*
83*4882a593Smuzhiyun 	 * Probe the underlying processor version/revision and
84*4882a593Smuzhiyun 	 * adjust cpu_data setup accordingly.
85*4882a593Smuzhiyun 	 */
86*4882a593Smuzhiyun 	switch (pvr) {
87*4882a593Smuzhiyun 	case 0x205:
88*4882a593Smuzhiyun 		boot_cpu_data.type = CPU_SH7750;
89*4882a593Smuzhiyun 		boot_cpu_data.flags |= CPU_HAS_P2_FLUSH_BUG |
90*4882a593Smuzhiyun 				       CPU_HAS_PERF_COUNTER;
91*4882a593Smuzhiyun 		break;
92*4882a593Smuzhiyun 	case 0x206:
93*4882a593Smuzhiyun 		boot_cpu_data.type = CPU_SH7750S;
94*4882a593Smuzhiyun 		boot_cpu_data.flags |= CPU_HAS_P2_FLUSH_BUG |
95*4882a593Smuzhiyun 				       CPU_HAS_PERF_COUNTER;
96*4882a593Smuzhiyun 		break;
97*4882a593Smuzhiyun 	case 0x1100:
98*4882a593Smuzhiyun 		boot_cpu_data.type = CPU_SH7751;
99*4882a593Smuzhiyun 		break;
100*4882a593Smuzhiyun 	case 0x2001:
101*4882a593Smuzhiyun 	case 0x2004:
102*4882a593Smuzhiyun 		boot_cpu_data.type = CPU_SH7770;
103*4882a593Smuzhiyun 		break;
104*4882a593Smuzhiyun 	case 0x2006:
105*4882a593Smuzhiyun 	case 0x200A:
106*4882a593Smuzhiyun 		if (prr == 0x61)
107*4882a593Smuzhiyun 			boot_cpu_data.type = CPU_SH7781;
108*4882a593Smuzhiyun 		else if (prr == 0xa1)
109*4882a593Smuzhiyun 			boot_cpu_data.type = CPU_SH7763;
110*4882a593Smuzhiyun 		else
111*4882a593Smuzhiyun 			boot_cpu_data.type = CPU_SH7780;
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 		break;
114*4882a593Smuzhiyun 	case 0x3000:
115*4882a593Smuzhiyun 	case 0x3003:
116*4882a593Smuzhiyun 	case 0x3009:
117*4882a593Smuzhiyun 		boot_cpu_data.type = CPU_SH7343;
118*4882a593Smuzhiyun 		break;
119*4882a593Smuzhiyun 	case 0x3004:
120*4882a593Smuzhiyun 	case 0x3007:
121*4882a593Smuzhiyun 		boot_cpu_data.type = CPU_SH7785;
122*4882a593Smuzhiyun 		break;
123*4882a593Smuzhiyun 	case 0x4004:
124*4882a593Smuzhiyun 	case 0x4005:
125*4882a593Smuzhiyun 		boot_cpu_data.type = CPU_SH7786;
126*4882a593Smuzhiyun 		boot_cpu_data.flags |= CPU_HAS_PTEAEX | CPU_HAS_L2_CACHE;
127*4882a593Smuzhiyun 		break;
128*4882a593Smuzhiyun 	case 0x3008:
129*4882a593Smuzhiyun 		switch (prr) {
130*4882a593Smuzhiyun 		case 0x50:
131*4882a593Smuzhiyun 		case 0x51:
132*4882a593Smuzhiyun 			boot_cpu_data.type = CPU_SH7723;
133*4882a593Smuzhiyun 			boot_cpu_data.flags |= CPU_HAS_L2_CACHE;
134*4882a593Smuzhiyun 			break;
135*4882a593Smuzhiyun 		case 0x70:
136*4882a593Smuzhiyun 			boot_cpu_data.type = CPU_SH7366;
137*4882a593Smuzhiyun 			break;
138*4882a593Smuzhiyun 		case 0xa0:
139*4882a593Smuzhiyun 		case 0xa1:
140*4882a593Smuzhiyun 			boot_cpu_data.type = CPU_SH7722;
141*4882a593Smuzhiyun 			break;
142*4882a593Smuzhiyun 		}
143*4882a593Smuzhiyun 		break;
144*4882a593Smuzhiyun 	case 0x300b:
145*4882a593Smuzhiyun 		switch (prr) {
146*4882a593Smuzhiyun 		case 0x20:
147*4882a593Smuzhiyun 			boot_cpu_data.type = CPU_SH7724;
148*4882a593Smuzhiyun 			boot_cpu_data.flags |= CPU_HAS_L2_CACHE;
149*4882a593Smuzhiyun 			break;
150*4882a593Smuzhiyun 		case 0x10:
151*4882a593Smuzhiyun 		case 0x11:
152*4882a593Smuzhiyun 			boot_cpu_data.type = CPU_SH7757;
153*4882a593Smuzhiyun 			break;
154*4882a593Smuzhiyun 		case 0xd0:
155*4882a593Smuzhiyun 		case 0x40: /* yon-ten-go */
156*4882a593Smuzhiyun 			boot_cpu_data.type = CPU_SH7372;
157*4882a593Smuzhiyun 			break;
158*4882a593Smuzhiyun 		case 0xE0: /* 0x4E0 */
159*4882a593Smuzhiyun 			boot_cpu_data.type = CPU_SH7734; /* SH7733/SH7734 */
160*4882a593Smuzhiyun 			break;
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 		}
163*4882a593Smuzhiyun 		break;
164*4882a593Smuzhiyun 	case 0x4000:	/* 1st cut */
165*4882a593Smuzhiyun 	case 0x4001:	/* 2nd cut */
166*4882a593Smuzhiyun 		boot_cpu_data.type = CPU_SHX3;
167*4882a593Smuzhiyun 		break;
168*4882a593Smuzhiyun 	case 0x700:
169*4882a593Smuzhiyun 		boot_cpu_data.type = CPU_SH4_501;
170*4882a593Smuzhiyun 		boot_cpu_data.flags &= ~CPU_HAS_FPU;
171*4882a593Smuzhiyun 		boot_cpu_data.icache.ways = 2;
172*4882a593Smuzhiyun 		boot_cpu_data.dcache.ways = 2;
173*4882a593Smuzhiyun 		break;
174*4882a593Smuzhiyun 	case 0x600:
175*4882a593Smuzhiyun 		boot_cpu_data.type = CPU_SH4_202;
176*4882a593Smuzhiyun 		boot_cpu_data.icache.ways = 2;
177*4882a593Smuzhiyun 		boot_cpu_data.dcache.ways = 2;
178*4882a593Smuzhiyun 		break;
179*4882a593Smuzhiyun 	case 0x500 ... 0x501:
180*4882a593Smuzhiyun 		switch (prr) {
181*4882a593Smuzhiyun 		case 0x10:
182*4882a593Smuzhiyun 			boot_cpu_data.type = CPU_SH7750R;
183*4882a593Smuzhiyun 			break;
184*4882a593Smuzhiyun 		case 0x11:
185*4882a593Smuzhiyun 			boot_cpu_data.type = CPU_SH7751R;
186*4882a593Smuzhiyun 			break;
187*4882a593Smuzhiyun 		case 0x50 ... 0x5f:
188*4882a593Smuzhiyun 			boot_cpu_data.type = CPU_SH7760;
189*4882a593Smuzhiyun 			break;
190*4882a593Smuzhiyun 		}
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 		boot_cpu_data.icache.ways = 2;
193*4882a593Smuzhiyun 		boot_cpu_data.dcache.ways = 2;
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun 		break;
196*4882a593Smuzhiyun 	}
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	/*
199*4882a593Smuzhiyun 	 * On anything that's not a direct-mapped cache, look to the CVR
200*4882a593Smuzhiyun 	 * for I/D-cache specifics.
201*4882a593Smuzhiyun 	 */
202*4882a593Smuzhiyun 	if (boot_cpu_data.icache.ways > 1) {
203*4882a593Smuzhiyun 		size = sizes[(cvr >> 20) & 0xf];
204*4882a593Smuzhiyun 		boot_cpu_data.icache.way_incr	= (size >> 1);
205*4882a593Smuzhiyun 		boot_cpu_data.icache.sets	= (size >> 6);
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun 	}
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	/* And the rest of the D-cache */
210*4882a593Smuzhiyun 	if (boot_cpu_data.dcache.ways > 1) {
211*4882a593Smuzhiyun 		size = sizes[(cvr >> 16) & 0xf];
212*4882a593Smuzhiyun 		boot_cpu_data.dcache.way_incr	= (size >> 1);
213*4882a593Smuzhiyun 		boot_cpu_data.dcache.sets	= (size >> 6);
214*4882a593Smuzhiyun 	}
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	/*
217*4882a593Smuzhiyun 	 * SH-4A's have an optional PIPT L2.
218*4882a593Smuzhiyun 	 */
219*4882a593Smuzhiyun 	if (boot_cpu_data.flags & CPU_HAS_L2_CACHE) {
220*4882a593Smuzhiyun 		/*
221*4882a593Smuzhiyun 		 * Verify that it really has something hooked up, this
222*4882a593Smuzhiyun 		 * is the safety net for CPUs that have optional L2
223*4882a593Smuzhiyun 		 * support yet do not implement it.
224*4882a593Smuzhiyun 		 */
225*4882a593Smuzhiyun 		if ((cvr & 0xf) == 0)
226*4882a593Smuzhiyun 			boot_cpu_data.flags &= ~CPU_HAS_L2_CACHE;
227*4882a593Smuzhiyun 		else {
228*4882a593Smuzhiyun 			/*
229*4882a593Smuzhiyun 			 * Silicon and specifications have clearly never
230*4882a593Smuzhiyun 			 * met..
231*4882a593Smuzhiyun 			 */
232*4882a593Smuzhiyun 			cvr ^= 0xf;
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 			/*
235*4882a593Smuzhiyun 			 * Size calculation is much more sensible
236*4882a593Smuzhiyun 			 * than it is for the L1.
237*4882a593Smuzhiyun 			 *
238*4882a593Smuzhiyun 			 * Sizes are 128KB, 256KB, 512KB, and 1MB.
239*4882a593Smuzhiyun 			 */
240*4882a593Smuzhiyun 			size = (cvr & 0xf) << 17;
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 			boot_cpu_data.scache.way_incr		= (1 << 16);
243*4882a593Smuzhiyun 			boot_cpu_data.scache.entry_shift	= 5;
244*4882a593Smuzhiyun 			boot_cpu_data.scache.ways		= 4;
245*4882a593Smuzhiyun 			boot_cpu_data.scache.linesz		= L1_CACHE_BYTES;
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 			boot_cpu_data.scache.entry_mask	=
248*4882a593Smuzhiyun 				(boot_cpu_data.scache.way_incr -
249*4882a593Smuzhiyun 				 boot_cpu_data.scache.linesz);
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 			boot_cpu_data.scache.sets	= size /
252*4882a593Smuzhiyun 				(boot_cpu_data.scache.linesz *
253*4882a593Smuzhiyun 				 boot_cpu_data.scache.ways);
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 			boot_cpu_data.scache.way_size	=
256*4882a593Smuzhiyun 				(boot_cpu_data.scache.sets *
257*4882a593Smuzhiyun 				 boot_cpu_data.scache.linesz);
258*4882a593Smuzhiyun 		}
259*4882a593Smuzhiyun 	}
260*4882a593Smuzhiyun }
261