xref: /OK3568_Linux_fs/kernel/arch/mips/sibyte/sb1250/setup.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun #include <linux/export.h>
6*4882a593Smuzhiyun #include <linux/init.h>
7*4882a593Smuzhiyun #include <linux/kernel.h>
8*4882a593Smuzhiyun #include <linux/reboot.h>
9*4882a593Smuzhiyun #include <linux/string.h>
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <asm/bootinfo.h>
12*4882a593Smuzhiyun #include <asm/cpu.h>
13*4882a593Smuzhiyun #include <asm/mipsregs.h>
14*4882a593Smuzhiyun #include <asm/io.h>
15*4882a593Smuzhiyun #include <asm/sibyte/sb1250.h>
16*4882a593Smuzhiyun #include <asm/sibyte/sb1250_regs.h>
17*4882a593Smuzhiyun #include <asm/sibyte/sb1250_scd.h>
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun unsigned int sb1_pass;
20*4882a593Smuzhiyun unsigned int soc_pass;
21*4882a593Smuzhiyun unsigned int soc_type;
22*4882a593Smuzhiyun EXPORT_SYMBOL(soc_type);
23*4882a593Smuzhiyun unsigned int periph_rev;
24*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(periph_rev);
25*4882a593Smuzhiyun unsigned int zbbus_mhz;
26*4882a593Smuzhiyun EXPORT_SYMBOL(zbbus_mhz);
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun static char *soc_str;
29*4882a593Smuzhiyun static char *pass_str;
30*4882a593Smuzhiyun static unsigned int war_pass;	/* XXXKW don't overload PASS defines? */
31*4882a593Smuzhiyun 
setup_bcm1250(void)32*4882a593Smuzhiyun static int __init setup_bcm1250(void)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun 	int ret = 0;
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun 	switch (soc_pass) {
37*4882a593Smuzhiyun 	case K_SYS_REVISION_BCM1250_PASS1:
38*4882a593Smuzhiyun 		periph_rev = 1;
39*4882a593Smuzhiyun 		pass_str = "Pass 1";
40*4882a593Smuzhiyun 		break;
41*4882a593Smuzhiyun 	case K_SYS_REVISION_BCM1250_A10:
42*4882a593Smuzhiyun 		periph_rev = 2;
43*4882a593Smuzhiyun 		pass_str = "A8/A10";
44*4882a593Smuzhiyun 		/* XXXKW different war_pass? */
45*4882a593Smuzhiyun 		war_pass = K_SYS_REVISION_BCM1250_PASS2;
46*4882a593Smuzhiyun 		break;
47*4882a593Smuzhiyun 	case K_SYS_REVISION_BCM1250_PASS2_2:
48*4882a593Smuzhiyun 		periph_rev = 2;
49*4882a593Smuzhiyun 		pass_str = "B1";
50*4882a593Smuzhiyun 		break;
51*4882a593Smuzhiyun 	case K_SYS_REVISION_BCM1250_B2:
52*4882a593Smuzhiyun 		periph_rev = 2;
53*4882a593Smuzhiyun 		pass_str = "B2";
54*4882a593Smuzhiyun 		war_pass = K_SYS_REVISION_BCM1250_PASS2_2;
55*4882a593Smuzhiyun 		break;
56*4882a593Smuzhiyun 	case K_SYS_REVISION_BCM1250_PASS3:
57*4882a593Smuzhiyun 		periph_rev = 3;
58*4882a593Smuzhiyun 		pass_str = "C0";
59*4882a593Smuzhiyun 		break;
60*4882a593Smuzhiyun 	case K_SYS_REVISION_BCM1250_C1:
61*4882a593Smuzhiyun 		periph_rev = 3;
62*4882a593Smuzhiyun 		pass_str = "C1";
63*4882a593Smuzhiyun 		break;
64*4882a593Smuzhiyun 	default:
65*4882a593Smuzhiyun 		if (soc_pass < K_SYS_REVISION_BCM1250_PASS2_2) {
66*4882a593Smuzhiyun 			periph_rev = 2;
67*4882a593Smuzhiyun 			pass_str = "A0-A6";
68*4882a593Smuzhiyun 			war_pass = K_SYS_REVISION_BCM1250_PASS2;
69*4882a593Smuzhiyun 		} else {
70*4882a593Smuzhiyun 			printk("Unknown BCM1250 rev %x\n", soc_pass);
71*4882a593Smuzhiyun 			ret = 1;
72*4882a593Smuzhiyun 		}
73*4882a593Smuzhiyun 		break;
74*4882a593Smuzhiyun 	}
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	return ret;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun 
sb1250_m3_workaround_needed(void)79*4882a593Smuzhiyun int sb1250_m3_workaround_needed(void)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun 	switch (soc_type) {
82*4882a593Smuzhiyun 	case K_SYS_SOC_TYPE_BCM1250:
83*4882a593Smuzhiyun 	case K_SYS_SOC_TYPE_BCM1250_ALT:
84*4882a593Smuzhiyun 	case K_SYS_SOC_TYPE_BCM1250_ALT2:
85*4882a593Smuzhiyun 	case K_SYS_SOC_TYPE_BCM1125:
86*4882a593Smuzhiyun 	case K_SYS_SOC_TYPE_BCM1125H:
87*4882a593Smuzhiyun 		return soc_pass < K_SYS_REVISION_BCM1250_C0;
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	default:
90*4882a593Smuzhiyun 		return 0;
91*4882a593Smuzhiyun 	}
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun 
setup_bcm112x(void)94*4882a593Smuzhiyun static int __init setup_bcm112x(void)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun 	int ret = 0;
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	switch (soc_pass) {
99*4882a593Smuzhiyun 	case 0:
100*4882a593Smuzhiyun 		/* Early build didn't have revid set */
101*4882a593Smuzhiyun 		periph_rev = 3;
102*4882a593Smuzhiyun 		pass_str = "A1";
103*4882a593Smuzhiyun 		war_pass = K_SYS_REVISION_BCM112x_A1;
104*4882a593Smuzhiyun 		break;
105*4882a593Smuzhiyun 	case K_SYS_REVISION_BCM112x_A1:
106*4882a593Smuzhiyun 		periph_rev = 3;
107*4882a593Smuzhiyun 		pass_str = "A1";
108*4882a593Smuzhiyun 		break;
109*4882a593Smuzhiyun 	case K_SYS_REVISION_BCM112x_A2:
110*4882a593Smuzhiyun 		periph_rev = 3;
111*4882a593Smuzhiyun 		pass_str = "A2";
112*4882a593Smuzhiyun 		break;
113*4882a593Smuzhiyun 	case K_SYS_REVISION_BCM112x_A3:
114*4882a593Smuzhiyun 		periph_rev = 3;
115*4882a593Smuzhiyun 		pass_str = "A3";
116*4882a593Smuzhiyun 		break;
117*4882a593Smuzhiyun 	case K_SYS_REVISION_BCM112x_A4:
118*4882a593Smuzhiyun 		periph_rev = 3;
119*4882a593Smuzhiyun 		pass_str = "A4";
120*4882a593Smuzhiyun 		break;
121*4882a593Smuzhiyun 	case K_SYS_REVISION_BCM112x_B0:
122*4882a593Smuzhiyun 		periph_rev = 3;
123*4882a593Smuzhiyun 		pass_str = "B0";
124*4882a593Smuzhiyun 		break;
125*4882a593Smuzhiyun 	default:
126*4882a593Smuzhiyun 		printk("Unknown %s rev %x\n", soc_str, soc_pass);
127*4882a593Smuzhiyun 		ret = 1;
128*4882a593Smuzhiyun 	}
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	return ret;
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun /* Setup code likely to be common to all SiByte platforms */
134*4882a593Smuzhiyun 
sys_rev_decode(void)135*4882a593Smuzhiyun static int __init sys_rev_decode(void)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun 	int ret = 0;
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	war_pass = soc_pass;
140*4882a593Smuzhiyun 	switch (soc_type) {
141*4882a593Smuzhiyun 	case K_SYS_SOC_TYPE_BCM1250:
142*4882a593Smuzhiyun 	case K_SYS_SOC_TYPE_BCM1250_ALT:
143*4882a593Smuzhiyun 	case K_SYS_SOC_TYPE_BCM1250_ALT2:
144*4882a593Smuzhiyun 		soc_str = "BCM1250";
145*4882a593Smuzhiyun 		ret = setup_bcm1250();
146*4882a593Smuzhiyun 		break;
147*4882a593Smuzhiyun 	case K_SYS_SOC_TYPE_BCM1120:
148*4882a593Smuzhiyun 		soc_str = "BCM1120";
149*4882a593Smuzhiyun 		ret = setup_bcm112x();
150*4882a593Smuzhiyun 		break;
151*4882a593Smuzhiyun 	case K_SYS_SOC_TYPE_BCM1125:
152*4882a593Smuzhiyun 		soc_str = "BCM1125";
153*4882a593Smuzhiyun 		ret = setup_bcm112x();
154*4882a593Smuzhiyun 		break;
155*4882a593Smuzhiyun 	case K_SYS_SOC_TYPE_BCM1125H:
156*4882a593Smuzhiyun 		soc_str = "BCM1125H";
157*4882a593Smuzhiyun 		ret = setup_bcm112x();
158*4882a593Smuzhiyun 		break;
159*4882a593Smuzhiyun 	default:
160*4882a593Smuzhiyun 		printk("Unknown SOC type %x\n", soc_type);
161*4882a593Smuzhiyun 		ret = 1;
162*4882a593Smuzhiyun 		break;
163*4882a593Smuzhiyun 	}
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 	return ret;
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun 
sb1250_setup(void)168*4882a593Smuzhiyun void __init sb1250_setup(void)
169*4882a593Smuzhiyun {
170*4882a593Smuzhiyun 	uint64_t sys_rev;
171*4882a593Smuzhiyun 	int plldiv;
172*4882a593Smuzhiyun 	int bad_config = 0;
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	sb1_pass = read_c0_prid() & PRID_REV_MASK;
175*4882a593Smuzhiyun 	sys_rev = __raw_readq(IOADDR(A_SCD_SYSTEM_REVISION));
176*4882a593Smuzhiyun 	soc_type = SYS_SOC_TYPE(sys_rev);
177*4882a593Smuzhiyun 	soc_pass = G_SYS_REVISION(sys_rev);
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	if (sys_rev_decode()) {
180*4882a593Smuzhiyun 		printk("Restart after failure to identify SiByte chip\n");
181*4882a593Smuzhiyun 		machine_restart(NULL);
182*4882a593Smuzhiyun 	}
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	plldiv = G_SYS_PLL_DIV(__raw_readq(IOADDR(A_SCD_SYSTEM_CFG)));
185*4882a593Smuzhiyun 	zbbus_mhz = ((plldiv >> 1) * 50) + ((plldiv & 1) * 25);
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	printk("Broadcom SiByte %s %s @ %d MHz (SB1 rev %d)\n",
188*4882a593Smuzhiyun 		    soc_str, pass_str, zbbus_mhz * 2, sb1_pass);
189*4882a593Smuzhiyun 	printk("Board type: %s\n", get_system_type());
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	switch (war_pass) {
192*4882a593Smuzhiyun 	case K_SYS_REVISION_BCM1250_PASS1:
193*4882a593Smuzhiyun 		printk("@@@@ This is a BCM1250 A0-A2 (Pass 1) board, "
194*4882a593Smuzhiyun 			    "and the kernel doesn't have the proper "
195*4882a593Smuzhiyun 			    "workarounds compiled in. @@@@\n");
196*4882a593Smuzhiyun 		bad_config = 1;
197*4882a593Smuzhiyun 		break;
198*4882a593Smuzhiyun 	case K_SYS_REVISION_BCM1250_PASS2:
199*4882a593Smuzhiyun 		/* Pass 2 - easiest as default for now - so many numbers */
200*4882a593Smuzhiyun #if !defined(CONFIG_SB1_PASS_2_WORKAROUNDS) || \
201*4882a593Smuzhiyun     !defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS)
202*4882a593Smuzhiyun 		printk("@@@@ This is a BCM1250 A3-A10 board, and the "
203*4882a593Smuzhiyun 			    "kernel doesn't have the proper workarounds "
204*4882a593Smuzhiyun 			    "compiled in. @@@@\n");
205*4882a593Smuzhiyun 		bad_config = 1;
206*4882a593Smuzhiyun #endif
207*4882a593Smuzhiyun #ifdef CONFIG_CPU_HAS_PREFETCH
208*4882a593Smuzhiyun 		printk("@@@@ Prefetches may be enabled in this kernel, "
209*4882a593Smuzhiyun 			    "but are buggy on this board.  @@@@\n");
210*4882a593Smuzhiyun 		bad_config = 1;
211*4882a593Smuzhiyun #endif
212*4882a593Smuzhiyun 		break;
213*4882a593Smuzhiyun 	case K_SYS_REVISION_BCM1250_PASS2_2:
214*4882a593Smuzhiyun #ifndef CONFIG_SB1_PASS_2_WORKAROUNDS
215*4882a593Smuzhiyun 		printk("@@@@ This is a BCM1250 B1/B2. board, and the "
216*4882a593Smuzhiyun 			    "kernel doesn't have the proper workarounds "
217*4882a593Smuzhiyun 			    "compiled in. @@@@\n");
218*4882a593Smuzhiyun 		bad_config = 1;
219*4882a593Smuzhiyun #endif
220*4882a593Smuzhiyun #if defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS) || \
221*4882a593Smuzhiyun     !defined(CONFIG_CPU_HAS_PREFETCH)
222*4882a593Smuzhiyun 		printk("@@@@ This is a BCM1250 B1/B2, but the kernel is "
223*4882a593Smuzhiyun 			    "conservatively configured for an 'A' stepping. "
224*4882a593Smuzhiyun 			    "@@@@\n");
225*4882a593Smuzhiyun #endif
226*4882a593Smuzhiyun 		break;
227*4882a593Smuzhiyun 	default:
228*4882a593Smuzhiyun 		break;
229*4882a593Smuzhiyun 	}
230*4882a593Smuzhiyun 	if (bad_config) {
231*4882a593Smuzhiyun 		printk("Invalid configuration for this chip.\n");
232*4882a593Smuzhiyun 		machine_restart(NULL);
233*4882a593Smuzhiyun 	}
234*4882a593Smuzhiyun }
235