setup.c 5.4 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/init.h>
L
Linus Torvalds 已提交
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
#include <linux/kernel.h>
#include <linux/reboot.h>
#include <linux/string.h>

#include <asm/bootinfo.h>
#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;
unsigned int periph_rev;
unsigned int zbbus_mhz;

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

static inline int setup_bcm1250(void);
static inline int setup_bcm112x(void);

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

45
static int __init sys_rev_decode(void)
L
Linus Torvalds 已提交
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
{
	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:
70
		printk("Unknown SOC type %x\n", soc_type);
L
Linus Torvalds 已提交
71 72 73 74 75 76
		ret = 1;
		break;
	}
	return ret;
}

77
static int __init setup_bcm1250(void)
L
Linus Torvalds 已提交
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
{
	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 {
115
			printk("Unknown BCM1250 rev %x\n", soc_pass);
L
Linus Torvalds 已提交
116 117 118 119 120 121 122
			ret = 1;
		}
		break;
	}
	return ret;
}

123
static int __init setup_bcm112x(void)
L
Linus Torvalds 已提交
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
{
	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;
	default:
143
		printk("Unknown %s rev %x\n", soc_str, soc_pass);
L
Linus Torvalds 已提交
144 145 146 147 148
		ret = 1;
	}
	return ret;
}

149
void __init sb1250_setup(void)
L
Linus Torvalds 已提交
150 151 152 153 154 155
{
	uint64_t sys_rev;
	int plldiv;
	int bad_config = 0;

	sb1_pass = read_c0_prid() & 0xff;
156
	sys_rev = __raw_readq(IOADDR(A_SCD_SYSTEM_REVISION));
L
Linus Torvalds 已提交
157 158 159 160
	soc_type = SYS_SOC_TYPE(sys_rev);
	soc_pass = G_SYS_REVISION(sys_rev);

	if (sys_rev_decode()) {
161
		printk("Restart after failure to identify SiByte chip\n");
L
Linus Torvalds 已提交
162 163 164
		machine_restart(NULL);
	}

165
	plldiv = G_SYS_PLL_DIV(__raw_readq(IOADDR(A_SCD_SYSTEM_CFG)));
L
Linus Torvalds 已提交
166 167
	zbbus_mhz = ((plldiv >> 1) * 50) + ((plldiv & 1) * 25);

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

R
Ralf Baechle 已提交
172
	switch (war_pass) {
L
Linus Torvalds 已提交
173 174
	case K_SYS_REVISION_BCM1250_PASS1:
#ifndef CONFIG_SB1_PASS_1_WORKAROUNDS
175
		printk("@@@@ This is a BCM1250 A0-A2 (Pass 1) board, "
R
Ralf Baechle 已提交
176 177
		            "and the kernel doesn't have the proper "
		            "workarounds compiled in. @@@@\n");
L
Linus Torvalds 已提交
178 179 180 181 182
		bad_config = 1;
#endif
		break;
	case K_SYS_REVISION_BCM1250_PASS2:
		/* Pass 2 - easiest as default for now - so many numbers */
R
Ralf Baechle 已提交
183 184
#if !defined(CONFIG_SB1_PASS_2_WORKAROUNDS) || \
    !defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS)
185
		printk("@@@@ This is a BCM1250 A3-A10 board, and the "
R
Ralf Baechle 已提交
186 187
		            "kernel doesn't have the proper workarounds "
		            "compiled in. @@@@\n");
L
Linus Torvalds 已提交
188 189 190
		bad_config = 1;
#endif
#ifdef CONFIG_CPU_HAS_PREFETCH
191
		printk("@@@@ Prefetches may be enabled in this kernel, "
R
Ralf Baechle 已提交
192
		            "but are buggy on this board.  @@@@\n");
L
Linus Torvalds 已提交
193 194 195 196 197
		bad_config = 1;
#endif
		break;
	case K_SYS_REVISION_BCM1250_PASS2_2:
#ifndef CONFIG_SB1_PASS_2_WORKAROUNDS
198
		printk("@@@@ This is a BCM1250 B1/B2. board, and the "
R
Ralf Baechle 已提交
199 200
		            "kernel doesn't have the proper workarounds "
		            "compiled in. @@@@\n");
L
Linus Torvalds 已提交
201 202
		bad_config = 1;
#endif
R
Ralf Baechle 已提交
203 204
#if defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS) || \
    !defined(CONFIG_CPU_HAS_PREFETCH)
205
		printk("@@@@ This is a BCM1250 B1/B2, but the kernel is "
R
Ralf Baechle 已提交
206 207
		            "conservatively configured for an 'A' stepping. "
		            "@@@@\n");
L
Linus Torvalds 已提交
208 209 210 211 212 213
#endif
		break;
	default:
		break;
	}
	if (bad_config) {
214
		printk("Invalid configuration for this chip.\n");
L
Linus Torvalds 已提交
215 216 217
		machine_restart(NULL);
	}
}