Commit | Line | Data |
---|---|---|
1a59d1b8 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
1da177e4 LT |
2 | /* |
3 | * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation | |
1da177e4 | 4 | */ |
26dd3e4f | 5 | #include <linux/export.h> |
5ac71fd1 | 6 | #include <linux/init.h> |
1da177e4 LT |
7 | #include <linux/kernel.h> |
8 | #include <linux/reboot.h> | |
9 | #include <linux/string.h> | |
10 | ||
11 | #include <asm/bootinfo.h> | |
8ff374b9 | 12 | #include <asm/cpu.h> |
1da177e4 LT |
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 | ||
19 | unsigned int sb1_pass; | |
20 | unsigned int soc_pass; | |
21 | unsigned int soc_type; | |
b45d5279 | 22 | EXPORT_SYMBOL(soc_type); |
1da177e4 | 23 | unsigned int periph_rev; |
c1d59008 | 24 | EXPORT_SYMBOL_GPL(periph_rev); |
1da177e4 | 25 | unsigned int zbbus_mhz; |
bb9b813b | 26 | EXPORT_SYMBOL(zbbus_mhz); |
1da177e4 LT |
27 | |
28 | static char *soc_str; | |
29 | static char *pass_str; | |
30 | static unsigned int war_pass; /* XXXKW don't overload PASS defines? */ | |
31 | ||
5ac71fd1 | 32 | static int __init setup_bcm1250(void) |
1da177e4 LT |
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 { | |
36a88530 | 70 | printk("Unknown BCM1250 rev %x\n", soc_pass); |
1da177e4 LT |
71 | ret = 1; |
72 | } | |
73 | break; | |
74 | } | |
7c4b4773 | 75 | |
1da177e4 LT |
76 | return ret; |
77 | } | |
78 | ||
8d9df29d RB |
79 | int 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 | ||
5ac71fd1 | 94 | static int __init setup_bcm112x(void) |
1da177e4 LT |
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; | |
9a994357 MM |
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; | |
1da177e4 | 125 | default: |
36a88530 | 126 | printk("Unknown %s rev %x\n", soc_str, soc_pass); |
1da177e4 LT |
127 | ret = 1; |
128 | } | |
7c4b4773 RB |
129 | |
130 | return ret; | |
131 | } | |
132 | ||
133 | /* Setup code likely to be common to all SiByte platforms */ | |
134 | ||
135 | static 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 | ||
1da177e4 LT |
165 | return ret; |
166 | } | |
167 | ||
5ac71fd1 | 168 | void __init sb1250_setup(void) |
1da177e4 LT |
169 | { |
170 | uint64_t sys_rev; | |
171 | int plldiv; | |
172 | int bad_config = 0; | |
173 | ||
8ff374b9 | 174 | sb1_pass = read_c0_prid() & PRID_REV_MASK; |
65bda1a9 | 175 | sys_rev = __raw_readq(IOADDR(A_SCD_SYSTEM_REVISION)); |
1da177e4 LT |
176 | soc_type = SYS_SOC_TYPE(sys_rev); |
177 | soc_pass = G_SYS_REVISION(sys_rev); | |
178 | ||
179 | if (sys_rev_decode()) { | |
36a88530 | 180 | printk("Restart after failure to identify SiByte chip\n"); |
1da177e4 LT |
181 | machine_restart(NULL); |
182 | } | |
183 | ||
65bda1a9 | 184 | plldiv = G_SYS_PLL_DIV(__raw_readq(IOADDR(A_SCD_SYSTEM_CFG))); |
1da177e4 LT |
185 | zbbus_mhz = ((plldiv >> 1) * 50) + ((plldiv & 1) * 25); |
186 | ||
36a88530 | 187 | printk("Broadcom SiByte %s %s @ %d MHz (SB1 rev %d)\n", |
1da177e4 | 188 | soc_str, pass_str, zbbus_mhz * 2, sb1_pass); |
36a88530 | 189 | printk("Board type: %s\n", get_system_type()); |
1da177e4 | 190 | |
b6f7880b | 191 | switch (war_pass) { |
1da177e4 | 192 | case K_SYS_REVISION_BCM1250_PASS1: |
36a88530 | 193 | printk("@@@@ This is a BCM1250 A0-A2 (Pass 1) board, " |
70342287 RB |
194 | "and the kernel doesn't have the proper " |
195 | "workarounds compiled in. @@@@\n"); | |
1da177e4 | 196 | bad_config = 1; |
1da177e4 LT |
197 | break; |
198 | case K_SYS_REVISION_BCM1250_PASS2: | |
199 | /* Pass 2 - easiest as default for now - so many numbers */ | |
b6f7880b RB |
200 | #if !defined(CONFIG_SB1_PASS_2_WORKAROUNDS) || \ |
201 | !defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS) | |
36a88530 | 202 | printk("@@@@ This is a BCM1250 A3-A10 board, and the " |
70342287 RB |
203 | "kernel doesn't have the proper workarounds " |
204 | "compiled in. @@@@\n"); | |
1da177e4 LT |
205 | bad_config = 1; |
206 | #endif | |
207 | #ifdef CONFIG_CPU_HAS_PREFETCH | |
36a88530 | 208 | printk("@@@@ Prefetches may be enabled in this kernel, " |
70342287 | 209 | "but are buggy on this board. @@@@\n"); |
1da177e4 LT |
210 | bad_config = 1; |
211 | #endif | |
212 | break; | |
213 | case K_SYS_REVISION_BCM1250_PASS2_2: | |
214 | #ifndef CONFIG_SB1_PASS_2_WORKAROUNDS | |
36a88530 | 215 | printk("@@@@ This is a BCM1250 B1/B2. board, and the " |
70342287 RB |
216 | "kernel doesn't have the proper workarounds " |
217 | "compiled in. @@@@\n"); | |
1da177e4 LT |
218 | bad_config = 1; |
219 | #endif | |
b6f7880b RB |
220 | #if defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS) || \ |
221 | !defined(CONFIG_CPU_HAS_PREFETCH) | |
36a88530 | 222 | printk("@@@@ This is a BCM1250 B1/B2, but the kernel is " |
70342287 RB |
223 | "conservatively configured for an 'A' stepping. " |
224 | "@@@@\n"); | |
1da177e4 LT |
225 | #endif |
226 | break; | |
227 | default: | |
228 | break; | |
229 | } | |
230 | if (bad_config) { | |
36a88530 | 231 | printk("Invalid configuration for this chip.\n"); |
1da177e4 LT |
232 | machine_restart(NULL); |
233 | } | |
234 | } |