summaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/setup.c')
-rw-r--r--arch/i386/kernel/setup.c325
1 files changed, 259 insertions, 66 deletions
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 490c4db82..c3f34270a 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -38,6 +38,7 @@
#include <asm/system.h>
#include <asm/io.h>
#include <asm/smp.h>
+#include <asm/cobalt.h>
/*
* Machine setup..
@@ -45,7 +46,6 @@
char ignore_irq13 = 0; /* set if exception 16 works */
struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
-static char Cx86_step[8]; /* decoded Cyrix step number */
/*
* Bus types ..
@@ -108,6 +108,133 @@ extern unsigned long cpu_hz;
#define RAMDISK_PROMPT_FLAG 0x8000
#define RAMDISK_LOAD_FLAG 0x4000
+#ifdef CONFIG_VISWS
+char visws_board_type = -1;
+char visws_board_rev = -1;
+
+#define PIIX_PM_START 0x0F80
+
+#define SIO_GPIO_START 0x0FC0
+
+#define SIO_PM_START 0x0FC8
+
+#define PMBASE PIIX_PM_START
+#define GPIREG0 (PMBASE+0x30)
+#define GPIREG(x) (GPIREG0+((x)/8))
+#define PIIX_GPI_BD_ID1 18
+#define PIIX_GPI_BD_REG GPIREG(PIIX_GPI_BD_ID1)
+
+#define PIIX_GPI_BD_SHIFT (PIIX_GPI_BD_ID1 % 8)
+
+#define SIO_INDEX 0x2e
+#define SIO_DATA 0x2f
+
+#define SIO_DEV_SEL 0x7
+#define SIO_DEV_ENB 0x30
+#define SIO_DEV_MSB 0x60
+#define SIO_DEV_LSB 0x61
+
+#define SIO_GP_DEV 0x7
+
+#define SIO_GP_BASE SIO_GPIO_START
+#define SIO_GP_MSB (SIO_GP_BASE>>8)
+#define SIO_GP_LSB (SIO_GP_BASE&0xff)
+
+#define SIO_GP_DATA1 (SIO_GP_BASE+0)
+
+#define SIO_PM_DEV 0x8
+
+#define SIO_PM_BASE SIO_PM_START
+#define SIO_PM_MSB (SIO_PM_BASE>>8)
+#define SIO_PM_LSB (SIO_PM_BASE&0xff)
+#define SIO_PM_INDEX (SIO_PM_BASE+0)
+#define SIO_PM_DATA (SIO_PM_BASE+1)
+
+#define SIO_PM_FER2 0x1
+
+#define SIO_PM_GP_EN 0x80
+
+static void
+visws_get_board_type_and_rev(void)
+{
+ int raw;
+
+ visws_board_type = (char)(inb_p(PIIX_GPI_BD_REG) & PIIX_GPI_BD_REG)
+ >> PIIX_GPI_BD_SHIFT;
+/*
+ * Get Board rev.
+ * First, we have to initialize the 307 part to allow us access
+ * to the GPIO registers. Let's map them at 0x0fc0 which is right
+ * after the PIIX4 PM section.
+ */
+ outb_p(SIO_DEV_SEL, SIO_INDEX);
+ outb_p(SIO_GP_DEV, SIO_DATA); /* Talk to GPIO regs. */
+
+ outb_p(SIO_DEV_MSB, SIO_INDEX);
+ outb_p(SIO_GP_MSB, SIO_DATA); /* MSB of GPIO base address */
+
+ outb_p(SIO_DEV_LSB, SIO_INDEX);
+ outb_p(SIO_GP_LSB, SIO_DATA); /* LSB of GPIO base address */
+
+ outb_p(SIO_DEV_ENB, SIO_INDEX);
+ outb_p(1, SIO_DATA); /* Enable GPIO registers. */
+
+/*
+ * Now, we have to map the power management section to write
+ * a bit which enables access to the GPIO registers.
+ * What lunatic came up with this shit?
+ */
+ outb_p(SIO_DEV_SEL, SIO_INDEX);
+ outb_p(SIO_PM_DEV, SIO_DATA); /* Talk to GPIO regs. */
+
+ outb_p(SIO_DEV_MSB, SIO_INDEX);
+ outb_p(SIO_PM_MSB, SIO_DATA); /* MSB of PM base address */
+
+ outb_p(SIO_DEV_LSB, SIO_INDEX);
+ outb_p(SIO_PM_LSB, SIO_DATA); /* LSB of PM base address */
+
+ outb_p(SIO_DEV_ENB, SIO_INDEX);
+ outb_p(1, SIO_DATA); /* Enable PM registers. */
+
+/*
+ * Now, write the PM register which enables the GPIO registers.
+ */
+ outb_p(SIO_PM_FER2, SIO_PM_INDEX);
+ outb_p(SIO_PM_GP_EN, SIO_PM_DATA);
+
+/*
+ * Now, initialize the GPIO registers.
+ * We want them all to be inputs which is the
+ * power on default, so let's leave them alone.
+ * So, let's just read the board rev!
+ */
+ raw = inb_p(SIO_GP_DATA1);
+ raw &= 0x7f; /* 7 bits of valid board revision ID. */
+
+ if (visws_board_type == VISWS_320) {
+ if (raw < 0x6) {
+ visws_board_rev = 4;
+ } else if (raw < 0xc) {
+ visws_board_rev = 5;
+ } else {
+ visws_board_rev = 6;
+
+ }
+ } else if (visws_board_type == VISWS_540) {
+ visws_board_rev = 2;
+ } else {
+ visws_board_rev = raw;
+ }
+
+ printk("Silicon Graphics %s (rev %d)\n",
+ visws_board_type == VISWS_320 ? "320" :
+ (visws_board_type == VISWS_540 ? "540" :
+ "unknown"),
+ visws_board_rev);
+ }
+#endif
+
+
static char command_line[COMMAND_LINE_SIZE] = { 0, };
char saved_command_line[COMMAND_LINE_SIZE];
@@ -123,6 +250,10 @@ __initfunc(void setup_arch(char **cmdline_p,
return;
smptrap=1;
+#ifdef CONFIG_VISWS
+ visws_get_board_type_and_rev();
+#endif
+
ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
drive_info = DRIVE_INFO;
screen_info = SCREEN_INFO;
@@ -146,12 +277,6 @@ __initfunc(void setup_arch(char **cmdline_p,
}
#endif
-#define VMALLOC_RESERVE (64 << 20) /* 64MB for vmalloc */
-#define MAXMEM ((unsigned long)(-PAGE_OFFSET-VMALLOC_RESERVE))
-
- if (memory_end > MAXMEM)
- memory_end = MAXMEM;
-
memory_end &= PAGE_MASK;
#ifdef CONFIG_BLK_DEV_RAM
rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
@@ -201,10 +326,28 @@ __initfunc(void setup_arch(char **cmdline_p,
}
*to = '\0';
*cmdline_p = command_line;
+
+#define VMALLOC_RESERVE (64 << 20) /* 64MB for vmalloc */
+#define MAXMEM ((unsigned long)(-PAGE_OFFSET-VMALLOC_RESERVE))
+
+ if (memory_end > MAXMEM)
+ {
+ memory_end = MAXMEM;
+ printk(KERN_WARNING "Warning only %ldMB will be used.\n",
+ MAXMEM>>20);
+ }
+
memory_end += PAGE_OFFSET;
*memory_start_p = memory_start;
*memory_end_p = memory_end;
+#ifdef __SMP__
+ /*
+ * Save possible boot-time SMP configuration:
+ */
+ init_smp_config();
+#endif
+
#ifdef CONFIG_BLK_DEV_INITRD
if (LOADER_TYPE) {
initrd_start = INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
@@ -232,6 +375,10 @@ __initfunc(void setup_arch(char **cmdline_p,
conswitchp = &dummy_con;
#endif
#endif
+ /*
+ * Check the bugs that will bite us before we get booting
+ */
+
}
__initfunc(static int amd_model(struct cpuinfo_x86 *c))
@@ -245,6 +392,7 @@ __initfunc(static int amd_model(struct cpuinfo_x86 *c))
cpuid(0x80000000, &n, &dummy, &dummy, &dummy);
if (n < 4)
return 0;
+ cpuid(0x80000001, &dummy, &dummy, &dummy, &(c->x86_capability));
v = (unsigned int *) c->x86_model_id;
cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
@@ -254,9 +402,9 @@ __initfunc(static int amd_model(struct cpuinfo_x86 *c))
}
/*
- * Use the Cyrix DEVID CPU registers if avail. to get more detailed info.
+ * Read Cyrix DEVID registers (DIR) to get more detailed info. about the CPU
*/
-__initfunc(static void do_cyrix_devid(struct cpuinfo_x86 *c))
+static inline void do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
{
unsigned char ccr2, ccr3;
@@ -272,22 +420,28 @@ __initfunc(static void do_cyrix_devid(struct cpuinfo_x86 *c))
getCx86(0xc0); /* dummy */
if (getCx86(CX86_CCR2) == ccr2) /* old Cx486SLC/DLC */
- c->x86_model = 0xfd;
+ *dir0 = 0xfd;
else { /* Cx486S A step */
setCx86(CX86_CCR2, ccr2);
- c->x86_model = 0xfe;
+ *dir0 = 0xfe;
}
}
else {
setCx86(CX86_CCR3, ccr3); /* restore CCR3 */
/* read DIR0 and DIR1 CPU registers */
- c->x86_model = getCx86(CX86_DIR0);
- c->x86_mask = getCx86(CX86_DIR1);
+ *dir0 = getCx86(CX86_DIR0);
+ *dir1 = getCx86(CX86_DIR1);
}
sti();
}
+/*
+ * Cx86_dir0_msb is a HACK needed by check_cx686_cpuid/slop in bugs.h in
+ * order to identify the Cyrix CPU model after we're out of setup.c
+ */
+unsigned char Cx86_dir0_msb __initdata = 0;
+
static char Cx86_model[][9] __initdata = {
"Cx486", "Cx486", "5x86 ", "6x86", "MediaGX ", "6x86MX ",
"M II ", "Unknown"
@@ -305,27 +459,28 @@ static char Cx486D_name[][4] __initdata = {
static char Cx86_cb[] __initdata = "?.5x Core/Bus Clock";
static char cyrix_model_mult1[] __initdata = "12??43";
static char cyrix_model_mult2[] __initdata = "12233445";
-static char cyrix_model_oldstep[] __initdata = "A step";
__initfunc(static void cyrix_model(struct cpuinfo_x86 *c))
{
- unsigned char dir0_msn, dir0_lsn, dir1;
+ unsigned char dir0, dir0_msn, dir0_lsn, dir1 = 0;
char *buf = c->x86_model_id;
const char *p = NULL;
- do_cyrix_devid(c);
+ do_cyrix_devid(&dir0, &dir1);
- dir0_msn = c->x86_model >> 4;
- dir0_lsn = c->x86_model & 0xf;
- dir1 = c->x86_mask;
+ Cx86_dir0_msb = dir0_msn = dir0 >> 4; /* identifies CPU "family" */
+ dir0_lsn = dir0 & 0xf; /* model or clock multiplier */
- /* common case stepping number -- exceptions handled below */
- sprintf(Cx86_step, "%d.%d", (dir1 >> 4) + 1, dir1 & 0x0f);
+ /* common case step number/rev -- exceptions handled below */
+ c->x86_model = (dir1 >> 4) + 1;
+ c->x86_mask = dir1 & 0xf;
/* Now cook; the original recipe is by Channing Corn, from Cyrix.
* We do the same thing for each generation: we work out
- * the model, multiplier and stepping.
+ * the model, multiplier and stepping. Black magic included,
+ * to make the silicon step/rev numbers match the printed ones.
*/
+
switch (dir0_msn) {
unsigned char tmp;
@@ -349,37 +504,41 @@ __initfunc(static void cyrix_model(struct cpuinfo_x86 *c))
if (dir1 > 0x21) { /* 686L */
Cx86_cb[0] = 'L';
p = Cx86_cb;
- Cx86_step[0]++;
+ (c->x86_model)++;
} else /* 686 */
p = Cx86_cb+1;
break;
case 4: /* MediaGX/GXm */
+ /*
+ * Life sometimes gets weiiiiiiiird if we use this
+ * on the MediaGX. So we turn it off for now.
+ */
+
/* GXm supports extended cpuid levels 'ala' AMD */
if (c->cpuid_level == 2) {
amd_model(c); /* get CPU marketing name */
+ c->x86_capability&=~X86_FEATURE_TSC;
return;
}
else { /* MediaGX */
Cx86_cb[2] = (dir0_lsn & 1) ? '3' : '4';
p = Cx86_cb+2;
- Cx86_step[0] = (dir1 & 0x20) ? '1' : '2';
+ c->x86_model = (dir1 & 0x20) ? 1 : 2;
+ c->x86_capability&=~X86_FEATURE_TSC;
}
break;
case 5: /* 6x86MX/M II */
- /* the TSC is broken (for now) */
- c->x86_capability &= ~16;
-
if (dir1 > 7) dir0_msn++; /* M II */
tmp = (!(dir0_lsn & 7) || dir0_lsn & 1) ? 2 : 0;
Cx86_cb[tmp] = cyrix_model_mult2[dir0_lsn & 7];
p = Cx86_cb+tmp;
if (((dir1 & 0x0f) > 4) || ((dir1 & 0xf0) == 0x20))
- Cx86_step[0]++;
+ (c->x86_model)++;
break;
- case 0xf: /* Cyrix 486 without DIR registers */
+ case 0xf: /* Cyrix 486 without DEVID registers */
switch (dir0_lsn) {
case 0xd: /* either a 486SLC or DLC w/o DEVID */
dir0_msn = 0;
@@ -389,11 +548,13 @@ __initfunc(static void cyrix_model(struct cpuinfo_x86 *c))
case 0xe: /* a 486S A step */
dir0_msn = 0;
p = Cx486S_name[0];
- strcpy(Cx86_step, cyrix_model_oldstep);
- c->x86_mask = 1; /* must != 0 to print */
break;
break;
}
+
+ default: /* unknown (shouldn't happen, we know everyone ;-) */
+ dir0_msn = 7;
+ break;
}
strcpy(buf, Cx86_model[dir0_msn & 7]);
if (p) strcat(buf, p);
@@ -445,15 +606,15 @@ static struct cpu_model_info cpu_models[] __initdata = {
"486 DX/4", "486 DX/4-WB", NULL, NULL, NULL, NULL, "Am5x86-WT",
"Am5x86-WB" }},
{ X86_VENDOR_AMD, 5,
- { "K5/SSA5 (PR75, PR90, PR100)", "K5 (PR120, PR133)",
- "K5 (PR166)", "K5 (PR200)", NULL, NULL,
- "K6 (PR166 - PR266)", "K6 (PR166 - PR300)", "K6-2 (PR233 - PR333)",
- "K6-3 (PR300 - PR450)", NULL, NULL, NULL, NULL, NULL, NULL }},
+ { "K5/SSA5", "K5",
+ "K5", "K5", NULL, NULL,
+ "K6", "K6", "K6-2",
+ "K6-3", NULL, NULL, NULL, NULL, NULL, NULL }},
{ X86_VENDOR_UMC, 4,
{ NULL, "U5D", "U5S", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL }},
{ X86_VENDOR_CENTAUR, 5,
- { NULL, NULL, NULL, NULL, "C6", NULL, NULL, NULL, NULL, NULL, NULL,
+ { NULL, NULL, NULL, NULL, "C6", NULL, NULL, NULL, "C6-2", NULL, NULL,
NULL, NULL, NULL, NULL, NULL }},
{ X86_VENDOR_NEXGEN, 5,
{ "Nx586", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -479,6 +640,9 @@ __initfunc(void identify_cpu(struct cpuinfo_x86 *c))
return;
}
+ if (c->x86_vendor == X86_VENDOR_AMD && amd_model(c))
+ return;
+
for (i = 0; i < sizeof(cpu_models)/sizeof(struct cpu_model_info); i++) {
if (c->cpuid_level > 1) {
/* supports eax=2 call */
@@ -543,15 +707,39 @@ __initfunc(void identify_cpu(struct cpuinfo_x86 *c))
return;
}
- if (c->x86_vendor == X86_VENDOR_AMD && amd_model(c))
- return;
-
sprintf(c->x86_model_id, "%02x/%02x", c->x86_vendor, c->x86_model);
}
+/*
+ * Perform early boot up checks for a valid TSC. See arch/i386/kernel/time.c
+ */
+
+__initfunc(void dodgy_tsc(void))
+{
+ get_cpu_vendor(&boot_cpu_data);
+
+ if(boot_cpu_data.x86_vendor != X86_VENDOR_CYRIX)
+ {
+ return;
+ }
+ cyrix_model(&boot_cpu_data);
+}
+
+
+#define rdmsr(msr,val1,val2) \
+ __asm__ __volatile__("rdmsr" \
+ : "=a" (val1), "=d" (val2) \
+ : "c" (msr))
+
+#define wrmsr(msr,val1,val2) \
+ __asm__ __volatile__("wrmsr" \
+ : /* no outputs */ \
+ : "c" (msr), "a" (val1), "d" (val2))
+
static char *cpu_vendor_names[] __initdata = {
"Intel", "Cyrix", "AMD", "UMC", "NexGen", "Centaur" };
+
__initfunc(void print_cpu_info(struct cpuinfo_x86 *c))
{
char *vendor = NULL;
@@ -569,11 +757,19 @@ __initfunc(void print_cpu_info(struct cpuinfo_x86 *c))
else
printk("%s", c->x86_model_id);
- if (c->x86_mask) {
- if (c->x86_vendor == X86_VENDOR_CYRIX)
- printk(" stepping %s", Cx86_step);
- else
- printk(" stepping %02x", c->x86_mask);
+ if (c->x86_mask || c->cpuid_level>=0)
+ printk(" stepping %02x", c->x86_mask);
+
+ if(c->x86_vendor == X86_VENDOR_CENTAUR)
+ {
+ u32 hv,lv;
+ rdmsr(0x107, lv, hv);
+ printk("\nCentaur FSR was 0x%X ",lv);
+ lv|=(1<<8);
+ lv|=(1<<7);
+ /* lv|=(1<<6); - may help too if the board can cope */
+ printk("now 0x%X", lv);
+ wrmsr(0x107, lv, hv);
}
printk("\n");
}
@@ -597,7 +793,7 @@ int get_cpuinfo(char * buffer)
for(n=0; n<NR_CPUS; n++, c++) {
#ifdef __SMP__
- if (!(cpu_present_map & (1<<n)))
+ if (!(cpu_online_map & (1<<n)))
continue;
#endif
p += sprintf(p,"processor\t: %d\n"
@@ -611,12 +807,9 @@ int get_cpuinfo(char * buffer)
c->x86_model,
c->x86_model_id[0] ? c->x86_model_id : "unknown");
- if (c->x86_mask) {
- if (c->x86_vendor == X86_VENDOR_CYRIX)
- p += sprintf(p, "stepping\t: %s\n", Cx86_step);
- else
- p += sprintf(p, "stepping\t: %d\n", c->x86_mask);
- } else
+ if (c->x86_mask)
+ p += sprintf(p, "stepping\t: %d\n", c->x86_mask);
+ else
p += sprintf(p, "stepping\t: unknown\n");
if (c->x86_capability & X86_FEATURE_TSC) {
@@ -629,21 +822,21 @@ int get_cpuinfo(char * buffer)
p += sprintf(p, "cache size\t: %d KB\n", c->x86_cache_size);
/* Modify the capabilities according to chip type */
- if (c->x86_mask) {
- if (c->x86_vendor == X86_VENDOR_CYRIX) {
- x86_cap_flags[24] = "cxmmx";
- } else if (c->x86_vendor == X86_VENDOR_AMD) {
- x86_cap_flags[16] = "fcmov";
- x86_cap_flags[31] = "amd3d";
- } else if (c->x86_vendor == X86_VENDOR_INTEL) {
- x86_cap_flags[6] = "pae";
- x86_cap_flags[9] = "apic";
- x86_cap_flags[12] = "mtrr";
- x86_cap_flags[14] = "mca";
- x86_cap_flags[16] = "pat";
- x86_cap_flags[17] = "pse36";
- x86_cap_flags[24] = "osfxsr";
- }
+ if (c->x86_vendor == X86_VENDOR_CYRIX) {
+ x86_cap_flags[24] = "cxmmx";
+ } else if (c->x86_vendor == X86_VENDOR_AMD) {
+ x86_cap_flags[16] = "fcmov";
+ x86_cap_flags[31] = "3dnow";
+ if (c->x86 == 5 && c->x86_model == 6)
+ x86_cap_flags[10] = "sep";
+ } else if (c->x86_vendor == X86_VENDOR_INTEL) {
+ x86_cap_flags[6] = "pae";
+ x86_cap_flags[9] = "apic";
+ x86_cap_flags[12] = "mtrr";
+ x86_cap_flags[14] = "mca";
+ x86_cap_flags[16] = "pat";
+ x86_cap_flags[17] = "pse36";
+ x86_cap_flags[24] = "osfxsr";
}
sep_bug = c->x86_vendor == X86_VENDOR_INTEL &&