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