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