diff options
-rw-r--r-- | sys/i386/i386/geode.c | 87 |
1 files changed, 84 insertions, 3 deletions
diff --git a/sys/i386/i386/geode.c b/sys/i386/i386/geode.c index 650dcba..c178d8b 100644 --- a/sys/i386/i386/geode.c +++ b/sys/i386/i386/geode.c @@ -49,6 +49,16 @@ static struct bios_oem bios_soekris = { } }; +static struct bios_oem bios_soekris_55 = { + { 0xf0000, 0xf1000 }, + { + { "Soekris", 0, 8 }, /* Soekris Engineering. */ + { "net5", 0, 8 }, /* net5xxx */ + { "comBIOS", 0, 54 }, /* comBIOS ver. 1.26a 20040819 ... */ + { NULL, 0, 0 }, + } +}; + static struct bios_oem bios_pcengines = { { 0xf9000, 0xfa000 }, { @@ -94,6 +104,25 @@ led_func(void *ptr, int onoff) outl(gpio, u); } +static void +cs5536_led_func(void *ptr, int onoff) +{ + int bit; + uint16_t a; + + bit = *(int *)ptr; + if (bit < 0) { + bit = -bit; + onoff = !onoff; + } + + a = rdmsr(0x5140000c); + if (onoff) + outl(a, 1 << bit); + else + outl(a, 1 << (bit + 16)); +} + static unsigned geode_get_timecount(struct timecounter *tc) @@ -158,6 +187,43 @@ geode_watchdog(void *foo __unused, u_int cmd, int *error) } /* + * We run MFGPT0 off the 32kHz frequency and prescale by 16384 giving a + * period of half a second. + * Range becomes 2^30 (= 1 sec) to 2^44 (almost 5 hours) + */ +static void +cs5536_watchdog(void *foo __unused, u_int cmd, int *error) +{ + u_int u, p; + uint16_t a; + uint32_t m; + + a = rdmsr(0x5140000d); + m = rdmsr(0x51400029); + m &= ~(1 << 24); + wrmsr(0x51400029, m); + + u = cmd & WD_INTERVAL; + if (u >= 30 && u <= 44) { + p = 1 << (u - 29); + + /* Set up MFGPT0, 32khz, prescaler 16k, C2 event */ + outw(a + 6, 0x030e); + /* set comparator 2 */ + outw(a + 2, p); + /* reset counter */ + outw(a + 4, 0); + /* Arm reset mechanism */ + m |= (1 << 24); + wrmsr(0x51400029, m); + /* Start counter */ + outw(a + 6, 0x8000); + + *error = 0; + } +} + +/* * The Advantech PCM-582x watchdog expects 0x1 at I/O port 0x0443 * every 1.6 secs +/- 30%. Writing 0x0 disables the watchdog * NB: reading the I/O port enables the timer as well @@ -182,7 +248,8 @@ geode_probe(device_t self) #define BIOS_OEM_MAXLEN 80 static u_char bios_oem[BIOS_OEM_MAXLEN] = "\0"; - if (pci_get_devid(self) == 0x0515100b) { + switch (pci_get_devid(self)) { + case 0x0515100b: if (geode_counter == 0) { /* * The address of the CBA is written to this register @@ -199,7 +266,8 @@ geode_probe(device_t self) NULL, 0); set_cputicker(geode_cputicks, 27000000, 0); } - } else if (pci_get_devid(self) == 0x0510100b) { + break; + case 0x0510100b: gpio = pci_read_config(self, PCIR_BAR(0), 4); gpio &= ~0x1f; printf("Geode GPIO@ = %x\n", gpio); @@ -223,13 +291,26 @@ geode_probe(device_t self) } if ( strlen(bios_oem) ) printf("Geode %s\n", bios_oem); - } else if (pci_get_devid(self) == 0x01011078) { + break; + case 0x01011078: if ( bios_oem_strings(&bios_advantech, bios_oem, BIOS_OEM_MAXLEN) > 0 ) { printf("Geode %s\n", bios_oem); EVENTHANDLER_REGISTER(watchdog_list, advantech_watchdog, NULL, 0); } + break; + case 0x20801022: + if ( bios_oem_strings(&bios_soekris_55, + bios_oem, BIOS_OEM_MAXLEN) > 0 ) { + printf("Geode LX: %s\n", bios_oem); + led1b = 6; + led1 = led_create(cs5536_led_func, &led1b, "error"); + } + printf("MFGPT bar: %jx\n", rdmsr(0x5140000d)); + EVENTHANDLER_REGISTER(watchdog_list, cs5536_watchdog, + NULL, 0); + break; } return (ENXIO); } |