1*1a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
41da177e4SLinus Torvalds */
526dd3e4fSPaul Gortmaker #include <linux/export.h>
65ac71fd1SRalf Baechle #include <linux/init.h>
71da177e4SLinus Torvalds #include <linux/kernel.h>
81da177e4SLinus Torvalds #include <linux/reboot.h>
91da177e4SLinus Torvalds #include <linux/string.h>
101da177e4SLinus Torvalds
111da177e4SLinus Torvalds #include <asm/bootinfo.h>
128ff374b9SMaciej W. Rozycki #include <asm/cpu.h>
131da177e4SLinus Torvalds #include <asm/mipsregs.h>
141da177e4SLinus Torvalds #include <asm/io.h>
151da177e4SLinus Torvalds #include <asm/sibyte/sb1250.h>
161da177e4SLinus Torvalds #include <asm/sibyte/sb1250_regs.h>
171da177e4SLinus Torvalds #include <asm/sibyte/sb1250_scd.h>
181da177e4SLinus Torvalds
191da177e4SLinus Torvalds unsigned int sb1_pass;
201da177e4SLinus Torvalds unsigned int soc_pass;
211da177e4SLinus Torvalds unsigned int soc_type;
22b45d5279SMaciej W. Rozycki EXPORT_SYMBOL(soc_type);
231da177e4SLinus Torvalds unsigned int periph_rev;
24c1d59008SRalf Baechle EXPORT_SYMBOL_GPL(periph_rev);
251da177e4SLinus Torvalds unsigned int zbbus_mhz;
26bb9b813bSRalf Baechle EXPORT_SYMBOL(zbbus_mhz);
271da177e4SLinus Torvalds
281da177e4SLinus Torvalds static char *soc_str;
291da177e4SLinus Torvalds static char *pass_str;
301da177e4SLinus Torvalds static unsigned int war_pass; /* XXXKW don't overload PASS defines? */
311da177e4SLinus Torvalds
setup_bcm1250(void)325ac71fd1SRalf Baechle static int __init setup_bcm1250(void)
331da177e4SLinus Torvalds {
341da177e4SLinus Torvalds int ret = 0;
351da177e4SLinus Torvalds
361da177e4SLinus Torvalds switch (soc_pass) {
371da177e4SLinus Torvalds case K_SYS_REVISION_BCM1250_PASS1:
381da177e4SLinus Torvalds periph_rev = 1;
391da177e4SLinus Torvalds pass_str = "Pass 1";
401da177e4SLinus Torvalds break;
411da177e4SLinus Torvalds case K_SYS_REVISION_BCM1250_A10:
421da177e4SLinus Torvalds periph_rev = 2;
431da177e4SLinus Torvalds pass_str = "A8/A10";
441da177e4SLinus Torvalds /* XXXKW different war_pass? */
451da177e4SLinus Torvalds war_pass = K_SYS_REVISION_BCM1250_PASS2;
461da177e4SLinus Torvalds break;
471da177e4SLinus Torvalds case K_SYS_REVISION_BCM1250_PASS2_2:
481da177e4SLinus Torvalds periph_rev = 2;
491da177e4SLinus Torvalds pass_str = "B1";
501da177e4SLinus Torvalds break;
511da177e4SLinus Torvalds case K_SYS_REVISION_BCM1250_B2:
521da177e4SLinus Torvalds periph_rev = 2;
531da177e4SLinus Torvalds pass_str = "B2";
541da177e4SLinus Torvalds war_pass = K_SYS_REVISION_BCM1250_PASS2_2;
551da177e4SLinus Torvalds break;
561da177e4SLinus Torvalds case K_SYS_REVISION_BCM1250_PASS3:
571da177e4SLinus Torvalds periph_rev = 3;
581da177e4SLinus Torvalds pass_str = "C0";
591da177e4SLinus Torvalds break;
601da177e4SLinus Torvalds case K_SYS_REVISION_BCM1250_C1:
611da177e4SLinus Torvalds periph_rev = 3;
621da177e4SLinus Torvalds pass_str = "C1";
631da177e4SLinus Torvalds break;
641da177e4SLinus Torvalds default:
651da177e4SLinus Torvalds if (soc_pass < K_SYS_REVISION_BCM1250_PASS2_2) {
661da177e4SLinus Torvalds periph_rev = 2;
671da177e4SLinus Torvalds pass_str = "A0-A6";
681da177e4SLinus Torvalds war_pass = K_SYS_REVISION_BCM1250_PASS2;
691da177e4SLinus Torvalds } else {
7036a88530SRalf Baechle printk("Unknown BCM1250 rev %x\n", soc_pass);
711da177e4SLinus Torvalds ret = 1;
721da177e4SLinus Torvalds }
731da177e4SLinus Torvalds break;
741da177e4SLinus Torvalds }
757c4b4773SRalf Baechle
761da177e4SLinus Torvalds return ret;
771da177e4SLinus Torvalds }
781da177e4SLinus Torvalds
sb1250_m3_workaround_needed(void)798d9df29dSRalf Baechle int sb1250_m3_workaround_needed(void)
808d9df29dSRalf Baechle {
818d9df29dSRalf Baechle switch (soc_type) {
828d9df29dSRalf Baechle case K_SYS_SOC_TYPE_BCM1250:
838d9df29dSRalf Baechle case K_SYS_SOC_TYPE_BCM1250_ALT:
848d9df29dSRalf Baechle case K_SYS_SOC_TYPE_BCM1250_ALT2:
858d9df29dSRalf Baechle case K_SYS_SOC_TYPE_BCM1125:
868d9df29dSRalf Baechle case K_SYS_SOC_TYPE_BCM1125H:
878d9df29dSRalf Baechle return soc_pass < K_SYS_REVISION_BCM1250_C0;
888d9df29dSRalf Baechle
898d9df29dSRalf Baechle default:
908d9df29dSRalf Baechle return 0;
918d9df29dSRalf Baechle }
928d9df29dSRalf Baechle }
938d9df29dSRalf Baechle
setup_bcm112x(void)945ac71fd1SRalf Baechle static int __init setup_bcm112x(void)
951da177e4SLinus Torvalds {
961da177e4SLinus Torvalds int ret = 0;
971da177e4SLinus Torvalds
981da177e4SLinus Torvalds switch (soc_pass) {
991da177e4SLinus Torvalds case 0:
1001da177e4SLinus Torvalds /* Early build didn't have revid set */
1011da177e4SLinus Torvalds periph_rev = 3;
1021da177e4SLinus Torvalds pass_str = "A1";
1031da177e4SLinus Torvalds war_pass = K_SYS_REVISION_BCM112x_A1;
1041da177e4SLinus Torvalds break;
1051da177e4SLinus Torvalds case K_SYS_REVISION_BCM112x_A1:
1061da177e4SLinus Torvalds periph_rev = 3;
1071da177e4SLinus Torvalds pass_str = "A1";
1081da177e4SLinus Torvalds break;
1091da177e4SLinus Torvalds case K_SYS_REVISION_BCM112x_A2:
1101da177e4SLinus Torvalds periph_rev = 3;
1111da177e4SLinus Torvalds pass_str = "A2";
1121da177e4SLinus Torvalds break;
1139a994357SMark Mason case K_SYS_REVISION_BCM112x_A3:
1149a994357SMark Mason periph_rev = 3;
1159a994357SMark Mason pass_str = "A3";
1169a994357SMark Mason break;
1179a994357SMark Mason case K_SYS_REVISION_BCM112x_A4:
1189a994357SMark Mason periph_rev = 3;
1199a994357SMark Mason pass_str = "A4";
1209a994357SMark Mason break;
1219a994357SMark Mason case K_SYS_REVISION_BCM112x_B0:
1229a994357SMark Mason periph_rev = 3;
1239a994357SMark Mason pass_str = "B0";
1249a994357SMark Mason break;
1251da177e4SLinus Torvalds default:
12636a88530SRalf Baechle printk("Unknown %s rev %x\n", soc_str, soc_pass);
1271da177e4SLinus Torvalds ret = 1;
1281da177e4SLinus Torvalds }
1297c4b4773SRalf Baechle
1307c4b4773SRalf Baechle return ret;
1317c4b4773SRalf Baechle }
1327c4b4773SRalf Baechle
1337c4b4773SRalf Baechle /* Setup code likely to be common to all SiByte platforms */
1347c4b4773SRalf Baechle
sys_rev_decode(void)1357c4b4773SRalf Baechle static int __init sys_rev_decode(void)
1367c4b4773SRalf Baechle {
1377c4b4773SRalf Baechle int ret = 0;
1387c4b4773SRalf Baechle
1397c4b4773SRalf Baechle war_pass = soc_pass;
1407c4b4773SRalf Baechle switch (soc_type) {
1417c4b4773SRalf Baechle case K_SYS_SOC_TYPE_BCM1250:
1427c4b4773SRalf Baechle case K_SYS_SOC_TYPE_BCM1250_ALT:
1437c4b4773SRalf Baechle case K_SYS_SOC_TYPE_BCM1250_ALT2:
1447c4b4773SRalf Baechle soc_str = "BCM1250";
1457c4b4773SRalf Baechle ret = setup_bcm1250();
1467c4b4773SRalf Baechle break;
1477c4b4773SRalf Baechle case K_SYS_SOC_TYPE_BCM1120:
1487c4b4773SRalf Baechle soc_str = "BCM1120";
1497c4b4773SRalf Baechle ret = setup_bcm112x();
1507c4b4773SRalf Baechle break;
1517c4b4773SRalf Baechle case K_SYS_SOC_TYPE_BCM1125:
1527c4b4773SRalf Baechle soc_str = "BCM1125";
1537c4b4773SRalf Baechle ret = setup_bcm112x();
1547c4b4773SRalf Baechle break;
1557c4b4773SRalf Baechle case K_SYS_SOC_TYPE_BCM1125H:
1567c4b4773SRalf Baechle soc_str = "BCM1125H";
1577c4b4773SRalf Baechle ret = setup_bcm112x();
1587c4b4773SRalf Baechle break;
1597c4b4773SRalf Baechle default:
1607c4b4773SRalf Baechle printk("Unknown SOC type %x\n", soc_type);
1617c4b4773SRalf Baechle ret = 1;
1627c4b4773SRalf Baechle break;
1637c4b4773SRalf Baechle }
1647c4b4773SRalf Baechle
1651da177e4SLinus Torvalds return ret;
1661da177e4SLinus Torvalds }
1671da177e4SLinus Torvalds
sb1250_setup(void)1685ac71fd1SRalf Baechle void __init sb1250_setup(void)
1691da177e4SLinus Torvalds {
1701da177e4SLinus Torvalds uint64_t sys_rev;
1711da177e4SLinus Torvalds int plldiv;
1721da177e4SLinus Torvalds int bad_config = 0;
1731da177e4SLinus Torvalds
1748ff374b9SMaciej W. Rozycki sb1_pass = read_c0_prid() & PRID_REV_MASK;
17565bda1a9SMaciej W. Rozycki sys_rev = __raw_readq(IOADDR(A_SCD_SYSTEM_REVISION));
1761da177e4SLinus Torvalds soc_type = SYS_SOC_TYPE(sys_rev);
1771da177e4SLinus Torvalds soc_pass = G_SYS_REVISION(sys_rev);
1781da177e4SLinus Torvalds
1791da177e4SLinus Torvalds if (sys_rev_decode()) {
18036a88530SRalf Baechle printk("Restart after failure to identify SiByte chip\n");
1811da177e4SLinus Torvalds machine_restart(NULL);
1821da177e4SLinus Torvalds }
1831da177e4SLinus Torvalds
18465bda1a9SMaciej W. Rozycki plldiv = G_SYS_PLL_DIV(__raw_readq(IOADDR(A_SCD_SYSTEM_CFG)));
1851da177e4SLinus Torvalds zbbus_mhz = ((plldiv >> 1) * 50) + ((plldiv & 1) * 25);
1861da177e4SLinus Torvalds
18736a88530SRalf Baechle printk("Broadcom SiByte %s %s @ %d MHz (SB1 rev %d)\n",
1881da177e4SLinus Torvalds soc_str, pass_str, zbbus_mhz * 2, sb1_pass);
18936a88530SRalf Baechle printk("Board type: %s\n", get_system_type());
1901da177e4SLinus Torvalds
1911da177e4SLinus Torvalds switch (war_pass) {
1921da177e4SLinus Torvalds case K_SYS_REVISION_BCM1250_PASS1:
19336a88530SRalf Baechle printk("@@@@ This is a BCM1250 A0-A2 (Pass 1) board, "
194b6f7880bSRalf Baechle "and the kernel doesn't have the proper "
195b6f7880bSRalf Baechle "workarounds compiled in. @@@@\n");
1961da177e4SLinus Torvalds bad_config = 1;
1971da177e4SLinus Torvalds break;
1981da177e4SLinus Torvalds case K_SYS_REVISION_BCM1250_PASS2:
1991da177e4SLinus Torvalds /* Pass 2 - easiest as default for now - so many numbers */
200b6f7880bSRalf Baechle #if !defined(CONFIG_SB1_PASS_2_WORKAROUNDS) || \
201b6f7880bSRalf Baechle !defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS)
20236a88530SRalf Baechle printk("@@@@ This is a BCM1250 A3-A10 board, and the "
203b6f7880bSRalf Baechle "kernel doesn't have the proper workarounds "
204b6f7880bSRalf Baechle "compiled in. @@@@\n");
2051da177e4SLinus Torvalds bad_config = 1;
2061da177e4SLinus Torvalds #endif
2071da177e4SLinus Torvalds #ifdef CONFIG_CPU_HAS_PREFETCH
20836a88530SRalf Baechle printk("@@@@ Prefetches may be enabled in this kernel, "
209b6f7880bSRalf Baechle "but are buggy on this board. @@@@\n");
2101da177e4SLinus Torvalds bad_config = 1;
2111da177e4SLinus Torvalds #endif
2121da177e4SLinus Torvalds break;
2131da177e4SLinus Torvalds case K_SYS_REVISION_BCM1250_PASS2_2:
2141da177e4SLinus Torvalds #ifndef CONFIG_SB1_PASS_2_WORKAROUNDS
21536a88530SRalf Baechle printk("@@@@ This is a BCM1250 B1/B2. board, and the "
216b6f7880bSRalf Baechle "kernel doesn't have the proper workarounds "
217b6f7880bSRalf Baechle "compiled in. @@@@\n");
2181da177e4SLinus Torvalds bad_config = 1;
2191da177e4SLinus Torvalds #endif
220b6f7880bSRalf Baechle #if defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS) || \
221b6f7880bSRalf Baechle !defined(CONFIG_CPU_HAS_PREFETCH)
22236a88530SRalf Baechle printk("@@@@ This is a BCM1250 B1/B2, but the kernel is "
223b6f7880bSRalf Baechle "conservatively configured for an 'A' stepping. "
224b6f7880bSRalf Baechle "@@@@\n");
2251da177e4SLinus Torvalds #endif
2261da177e4SLinus Torvalds break;
2271da177e4SLinus Torvalds default:
2281da177e4SLinus Torvalds break;
2291da177e4SLinus Torvalds }
2301da177e4SLinus Torvalds if (bad_config) {
23136a88530SRalf Baechle printk("Invalid configuration for this chip.\n");
2321da177e4SLinus Torvalds machine_restart(NULL);
2331da177e4SLinus Torvalds }
2341da177e4SLinus Torvalds }
235