setup.c 5.9 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
18
#include <linux/export.h>
19
#include <linux/init.h>
L
Linus Torvalds 已提交
20 21 22 23 24
#include <linux/kernel.h>
#include <linux/reboot.h>
#include <linux/string.h>

#include <asm/bootinfo.h>
25
#include <asm/cpu.h>
L
Linus Torvalds 已提交
26 27 28 29 30 31 32 33 34
#include <asm/mipsregs.h>
#include <asm/io.h>
#include <asm/sibyte/sb1250.h>
#include <asm/sibyte/sb1250_regs.h>
#include <asm/sibyte/sb1250_scd.h>

unsigned int sb1_pass;
unsigned int soc_pass;
unsigned int soc_type;
35
EXPORT_SYMBOL(soc_type);
L
Linus Torvalds 已提交
36 37
unsigned int periph_rev;
unsigned int zbbus_mhz;
R
Ralf Baechle 已提交
38
EXPORT_SYMBOL(zbbus_mhz);
L
Linus Torvalds 已提交
39 40 41 42 43

static char *soc_str;
static char *pass_str;
static unsigned int war_pass;	/* XXXKW don't overload PASS defines? */

44
static int __init setup_bcm1250(void)
L
Linus Torvalds 已提交
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
{
	int ret = 0;

	switch (soc_pass) {
	case K_SYS_REVISION_BCM1250_PASS1:
		periph_rev = 1;
		pass_str = "Pass 1";
		break;
	case K_SYS_REVISION_BCM1250_A10:
		periph_rev = 2;
		pass_str = "A8/A10";
		/* XXXKW different war_pass? */
		war_pass = K_SYS_REVISION_BCM1250_PASS2;
		break;
	case K_SYS_REVISION_BCM1250_PASS2_2:
		periph_rev = 2;
		pass_str = "B1";
		break;
	case K_SYS_REVISION_BCM1250_B2:
		periph_rev = 2;
		pass_str = "B2";
		war_pass = K_SYS_REVISION_BCM1250_PASS2_2;
		break;
	case K_SYS_REVISION_BCM1250_PASS3:
		periph_rev = 3;
		pass_str = "C0";
		break;
	case K_SYS_REVISION_BCM1250_C1:
		periph_rev = 3;
		pass_str = "C1";
		break;
	default:
		if (soc_pass < K_SYS_REVISION_BCM1250_PASS2_2) {
			periph_rev = 2;
			pass_str = "A0-A6";
			war_pass = K_SYS_REVISION_BCM1250_PASS2;
		} else {
82
			printk("Unknown BCM1250 rev %x\n", soc_pass);
L
Linus Torvalds 已提交
83 84 85 86
			ret = 1;
		}
		break;
	}
87

L
Linus Torvalds 已提交
88 89 90
	return ret;
}

91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
int sb1250_m3_workaround_needed(void)
{
	switch (soc_type) {
	case K_SYS_SOC_TYPE_BCM1250:
	case K_SYS_SOC_TYPE_BCM1250_ALT:
	case K_SYS_SOC_TYPE_BCM1250_ALT2:
	case K_SYS_SOC_TYPE_BCM1125:
	case K_SYS_SOC_TYPE_BCM1125H:
		return soc_pass < K_SYS_REVISION_BCM1250_C0;

	default:
		return 0;
	}
}

106
static int __init setup_bcm112x(void)
L
Linus Torvalds 已提交
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
{
	int ret = 0;

	switch (soc_pass) {
	case 0:
		/* Early build didn't have revid set */
		periph_rev = 3;
		pass_str = "A1";
		war_pass = K_SYS_REVISION_BCM112x_A1;
		break;
	case K_SYS_REVISION_BCM112x_A1:
		periph_rev = 3;
		pass_str = "A1";
		break;
	case K_SYS_REVISION_BCM112x_A2:
		periph_rev = 3;
		pass_str = "A2";
		break;
125 126 127 128 129 130 131 132 133 134 135 136
	case K_SYS_REVISION_BCM112x_A3:
		periph_rev = 3;
		pass_str = "A3";
		break;
	case K_SYS_REVISION_BCM112x_A4:
		periph_rev = 3;
		pass_str = "A4";
		break;
	case K_SYS_REVISION_BCM112x_B0:
		periph_rev = 3;
		pass_str = "B0";
		break;
L
Linus Torvalds 已提交
137
	default:
138
		printk("Unknown %s rev %x\n", soc_str, soc_pass);
L
Linus Torvalds 已提交
139 140
		ret = 1;
	}
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176

	return ret;
}

/* Setup code likely to be common to all SiByte platforms */

static int __init sys_rev_decode(void)
{
	int ret = 0;

	war_pass = soc_pass;
	switch (soc_type) {
	case K_SYS_SOC_TYPE_BCM1250:
	case K_SYS_SOC_TYPE_BCM1250_ALT:
	case K_SYS_SOC_TYPE_BCM1250_ALT2:
		soc_str = "BCM1250";
		ret = setup_bcm1250();
		break;
	case K_SYS_SOC_TYPE_BCM1120:
		soc_str = "BCM1120";
		ret = setup_bcm112x();
		break;
	case K_SYS_SOC_TYPE_BCM1125:
		soc_str = "BCM1125";
		ret = setup_bcm112x();
		break;
	case K_SYS_SOC_TYPE_BCM1125H:
		soc_str = "BCM1125H";
		ret = setup_bcm112x();
		break;
	default:
		printk("Unknown SOC type %x\n", soc_type);
		ret = 1;
		break;
	}

L
Linus Torvalds 已提交
177 178 179
	return ret;
}

180
void __init sb1250_setup(void)
L
Linus Torvalds 已提交
181 182 183 184 185
{
	uint64_t sys_rev;
	int plldiv;
	int bad_config = 0;

186
	sb1_pass = read_c0_prid() & PRID_REV_MASK;
187
	sys_rev = __raw_readq(IOADDR(A_SCD_SYSTEM_REVISION));
L
Linus Torvalds 已提交
188 189 190 191
	soc_type = SYS_SOC_TYPE(sys_rev);
	soc_pass = G_SYS_REVISION(sys_rev);

	if (sys_rev_decode()) {
192
		printk("Restart after failure to identify SiByte chip\n");
L
Linus Torvalds 已提交
193 194 195
		machine_restart(NULL);
	}

196
	plldiv = G_SYS_PLL_DIV(__raw_readq(IOADDR(A_SCD_SYSTEM_CFG)));
L
Linus Torvalds 已提交
197 198
	zbbus_mhz = ((plldiv >> 1) * 50) + ((plldiv & 1) * 25);

199
	printk("Broadcom SiByte %s %s @ %d MHz (SB1 rev %d)\n",
L
Linus Torvalds 已提交
200
		    soc_str, pass_str, zbbus_mhz * 2, sb1_pass);
201
	printk("Board type: %s\n", get_system_type());
L
Linus Torvalds 已提交
202

R
Ralf Baechle 已提交
203
	switch (war_pass) {
L
Linus Torvalds 已提交
204
	case K_SYS_REVISION_BCM1250_PASS1:
205
		printk("@@@@ This is a BCM1250 A0-A2 (Pass 1) board, "
R
Ralf Baechle 已提交
206 207
			    "and the kernel doesn't have the proper "
			    "workarounds compiled in. @@@@\n");
L
Linus Torvalds 已提交
208 209 210 211
		bad_config = 1;
		break;
	case K_SYS_REVISION_BCM1250_PASS2:
		/* Pass 2 - easiest as default for now - so many numbers */
R
Ralf Baechle 已提交
212 213
#if !defined(CONFIG_SB1_PASS_2_WORKAROUNDS) || \
    !defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS)
214
		printk("@@@@ This is a BCM1250 A3-A10 board, and the "
R
Ralf Baechle 已提交
215 216
			    "kernel doesn't have the proper workarounds "
			    "compiled in. @@@@\n");
L
Linus Torvalds 已提交
217 218 219
		bad_config = 1;
#endif
#ifdef CONFIG_CPU_HAS_PREFETCH
220
		printk("@@@@ Prefetches may be enabled in this kernel, "
R
Ralf Baechle 已提交
221
			    "but are buggy on this board.  @@@@\n");
L
Linus Torvalds 已提交
222 223 224 225 226
		bad_config = 1;
#endif
		break;
	case K_SYS_REVISION_BCM1250_PASS2_2:
#ifndef CONFIG_SB1_PASS_2_WORKAROUNDS
227
		printk("@@@@ This is a BCM1250 B1/B2. board, and the "
R
Ralf Baechle 已提交
228 229
			    "kernel doesn't have the proper workarounds "
			    "compiled in. @@@@\n");
L
Linus Torvalds 已提交
230 231
		bad_config = 1;
#endif
R
Ralf Baechle 已提交
232 233
#if defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS) || \
    !defined(CONFIG_CPU_HAS_PREFETCH)
234
		printk("@@@@ This is a BCM1250 B1/B2, but the kernel is "
R
Ralf Baechle 已提交
235 236
			    "conservatively configured for an 'A' stepping. "
			    "@@@@\n");
L
Linus Torvalds 已提交
237 238 239 240 241 242
#endif
		break;
	default:
		break;
	}
	if (bad_config) {
243
		printk("Invalid configuration for this chip.\n");
L
Linus Torvalds 已提交
244 245 246
		machine_restart(NULL);
	}
}