diff options
Diffstat (limited to 'arch/i386/kernel/setup.c')
-rw-r--r-- | arch/i386/kernel/setup.c | 325 |
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 && |