static int amdsbwd_attach(device_t dev) { struct amdsbwd_softc *sc; int rc; sc = &amdsbwd_sc; sc->dev = dev; rc = amdsbwd_attach_sb(dev, sc); if (rc != 0) goto fail; #ifdef AMDSBWD_DEBUG device_printf(dev, "wd ctrl = %#04x\n", wdctrl_read(sc)); device_printf(dev, "wd count = %#04x\n", wdcount_read(sc)); #endif /* Setup initial state of Watchdog Control. */ wdctrl_write(sc, AMDSB_WD_FIRED); if (wdctrl_read(sc) & AMDSB_WD_DISABLE) { device_printf(dev, "watchdog hardware is disabled\n"); goto fail; } wdog_register(&amdsb_wdog); return (0); fail: amdsbwd_detach(dev); return (ENXIO); }
void pmc_attach(struct device *parent, struct device *self, void *aux) { struct pmc_softc *sc = (void *)self; struct ebus_attach_args *ea = aux; /* Use prom address if available, otherwise map it. */ if (ea->ea_nvaddrs) { if (bus_space_map(ea->ea_memtag, ea->ea_vaddrs[0], 0, BUS_SPACE_MAP_PROMADDRESS, &sc->sc_ioh)) { printf(": can't map PROM register space\n"); return; } sc->sc_iot = ea->ea_memtag; } else if (ebus_bus_map(ea->ea_iotag, 0, EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) { sc->sc_iot = ea->ea_iotag; } else if (ebus_bus_map(ea->ea_memtag, 0, EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) { sc->sc_iot = ea->ea_memtag; } else { printf("%s: can't map register space\n", self->dv_xname); return; } printf("\n"); wdog_register(sc, pmc_wdog_cb); }
void wdt_attach(struct device *parent, struct device *self, void *aux) { struct wdt_softc *wdt = (struct wdt_softc *)self; struct pci_attach_args *const pa = (struct pci_attach_args *)aux; bus_size_t iosize; /* retrieve the I/O region (BAR2) */ if (pci_mapreg_map(pa, 0x18, PCI_MAPREG_TYPE_IO, 0, &wdt->sc_iot, &wdt->sc_ioh, NULL, &iosize, 0) != 0) { printf("%s: couldn't find PCI I/O region\n", wdt->sc_dev.dv_xname); return; } /* sanity check I/O size */ if (iosize != (bus_size_t)16) { printf("%s: invalid I/O region size\n", wdt->sc_dev.dv_xname); return; } /* initialize the watchdog timer structure */ /* check the feature set available */ if (wdt_is501(wdt)) wdt->sc_features = 1; else wdt->sc_features = 0; if (wdt->sc_features) { /* * turn off the buzzer, it may have been activated * by a previous timeout */ wdt_buzzer_off(wdt); wdt_buzzer_enable(wdt); } /* initialize the timer modes and the lower 16-bit counter */ wdt_init_timer(wdt); /* * ensure that the watchdog is disabled */ wdt_timer_disable(wdt); /* * register with the watchdog framework */ wdog_register(wdt_set_timeout, wdt); }
void viasio_wdg_init(struct viasio_softc *sc) { u_int8_t reg0, reg1; u_int16_t iobase; printf(" WDG"); /* Select WDG logical device */ viasio_conf_write(sc->sc_iot, sc->sc_ioh, VT1211_LDN, VT1211_LDN_WDG); /* * Check if logical device is activated by firmware. If not * try to activate it only if requested. */ reg0 = viasio_conf_read(sc->sc_iot, sc->sc_ioh, VT1211_WDG_ACT); DPRINTF((": ACT 0x%02x", reg0)); if ((reg0 & VT1211_WDG_ACT_EN) == 0) { if ((sc->sc_dev.dv_cfdata->cf_flags & VIASIO_CFFLAGS_WDG_ENABLE) != 0) { reg0 |= VT1211_WDG_ACT_EN; viasio_conf_write(sc->sc_iot, sc->sc_ioh, VT1211_WDG_ACT, reg0); reg0 = viasio_conf_read(sc->sc_iot, sc->sc_ioh, VT1211_WDG_ACT); DPRINTF((", new ACT 0x%02x", reg0)); if ((reg0 & VT1211_WDG_ACT_EN) == 0) { printf(": failed to activate"); return; } } else { printf(": not activated"); return; } } /* Read WDG I/O space address */ reg0 = viasio_conf_read(sc->sc_iot, sc->sc_ioh, VT1211_WDG_ADDR_LSB); reg1 = viasio_conf_read(sc->sc_iot, sc->sc_ioh, VT1211_WDG_ADDR_MSB); iobase = (reg1 << 8) | reg0; DPRINTF((", addr 0x%04x", iobase)); /* Map WDG I/O space */ if (bus_space_map(sc->sc_iot, iobase, VT1211_WDG_IOSIZE, 0, &sc->sc_wdg_ioh)) { printf(": can't map I/O space"); return; } /* Register new watchdog */ wdog_register(sc, viasio_wdg_cb); }
void geodesc_attach(struct device *parent, struct device *self, void *aux) { struct geodesc_softc *sc = (void *) self; struct pci_attach_args *pa = aux; uint16_t cnfg, cba; uint8_t sts, rev, iid; pcireg_t reg; extern void (*cpuresetfn)(void); reg = pci_conf_read(pa->pa_pc, pa->pa_tag, SC1100_F5_SCRATCHPAD); sc->sc_iot = pa->pa_iot; if (reg == 0 || bus_space_map(sc->sc_iot, reg, 64, 0, &sc->sc_ioh)) { printf(": unable to map registers at 0x%x\n", reg); return; } cba = bus_space_read_2(sc->sc_iot, sc->sc_ioh, GCB_CBA); if (cba != reg) { printf(": cba mismatch: cba 0x%x != reg 0x%x\n", cba, reg); bus_space_unmap(sc->sc_iot, sc->sc_ioh, 64); return; } sts = bus_space_read_1(sc->sc_iot, sc->sc_ioh, GCB_WDSTS); cnfg = bus_space_read_2(sc->sc_iot, sc->sc_ioh, GCB_WDCNFG); iid = bus_space_read_1(sc->sc_iot, sc->sc_ioh, GCB_IID); rev = bus_space_read_1(sc->sc_iot, sc->sc_ioh, GCB_REV); printf(": iid %d revision %d wdstatus %b\n", iid, rev, sts, WDSTSBITS); #ifndef SMALL_KERNEL /* setup and register watchdog */ bus_space_write_2(sc->sc_iot, sc->sc_ioh, GCB_WDTO, 0); sts |= WDOVF_CLEAR; bus_space_write_1(sc->sc_iot, sc->sc_ioh, GCB_WDSTS, sts); cnfg &= ~WDCNFG_MASK; cnfg |= WDTYPE1_RESET|WDPRES_DIV_512; bus_space_write_2(sc->sc_iot, sc->sc_ioh, GCB_WDCNFG, cnfg); wdog_register(sc, geodesc_wdogctl_cb); #endif /* SMALL_KERNEL */ #ifdef __HAVE_TIMECOUNTER bus_space_write_4(sc->sc_iot, sc->sc_ioh, GCB_TSCNFG, TSC_ENABLE); /* Hook into the kern_tc */ geodesc_timecounter.tc_priv = sc; tc_init(&geodesc_timecounter); #endif /* __HAVE_TIMECOUNTER */ /* We have a special way to reset the CPU on the SC1100 */ cpuresetfn = sc1100_sysreset; }
static int geode_attach(device_t self) { u_int32_t reg; u_int16_t cnfg, cba; u_int8_t sts, rev, iid; /* * The address of the CBA is written to this register * by the bios, see p161 in data sheet. */ reg = pci_read_config(self, SC1100_F5_SCRATCHPAD, 4); if (reg == 0) return ENODEV; /* bus_space_map(sc->sc_iot, reg, 64, 0, &sc->sc_ioh)) */ geode_sc.sc_iot = I386_BUS_SPACE_IO; geode_sc.sc_ioh = reg; cba = bus_space_read_2(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_CBA); if (cba != reg) { kprintf("Geode LX: cba mismatch: cba 0x%x != reg 0x%x\n", cba, reg); return ENODEV; } /* outl(cba + 0x0d, 2); ??? */ sts = bus_space_read_1(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_WDSTS); cnfg = bus_space_read_2(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_WDCNFG); iid = bus_space_read_1(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_IID); rev = bus_space_read_1(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_REV); #define WDSTSBITS "\20\x04WDRST\x03WDSMI\x02WDINT\x01WDOVF" kprintf("Geode LX: iid %d revision %d wdstatus %b\n", iid, rev, sts, WDSTSBITS); /* enable timer */ bus_space_write_4(geode_sc.sc_iot, geode_sc.sc_iot, GCB_TSCNFG, TSC_ENABLE); cputimer_register(&geode_timer); cputimer_select(&geode_timer, 0); /* enable watchdog and configure */ bus_space_write_2(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_WDTO, 0); sts |= WDOVF_CLEAR; bus_space_write_1(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_WDSTS, sts); cnfg &= ~WDCNFG_MASK; cnfg |= WDTYPE1_RESET | WDPRES_DIV_512; bus_space_write_2(geode_sc.sc_iot, geode_sc.sc_ioh, GCB_WDCNFG, cnfg); wdog_register(&geode_wdog); return 0; }
void pwdog_attach(struct device *parent, struct device *self, void *aux) { struct pwdog_softc *pwdog = (struct pwdog_softc *)self; struct pci_attach_args *const pa = (struct pci_attach_args *)aux; pcireg_t memtype; bus_size_t iosize; memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, PCI_MAPREG_START); if (pci_mapreg_map(pa, PCI_MAPREG_START, memtype, 0, &pwdog->iot, &pwdog->ioh, NULL, &iosize, 0)) { printf("\n%s: PCI %s region not found\n", pwdog->pwdog_dev.dv_xname, memtype == PCI_MAPREG_TYPE_IO ? "I/O" : "memory"); return; } printf("\n"); bus_space_write_1(pwdog->iot, pwdog->ioh, PWDOG_DISABLE, 0); wdog_register(pwdog_set_timeout, pwdog); }
void schsio_wdt_init(struct schsio_softc *sc) { u_int8_t reg; reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_GPIO); if ((reg & SCHSIO_WDT_GPIO_MASK) != SCHSIO_WDT_GPIO_OUT) { if (sc->sc_dev.dv_cfdata->cf_flags & SCHSIO_CFFLAGS_WDTEN) { reg &= ~0x0f; reg |= SCHSIO_WDT_GPIO_OUT; bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_GPIO, reg); } else { printf(", watchdog disabled"); return; } } /* First of all, make sure the wdt is disabled */ bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_VAL, 0); /* Clear triggered status */ reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_CTRL); if (reg & SCHSIO_WDT_CTRL_TRIGGERED) { printf(", warning: watchdog triggered"); reg &= ~SCHSIO_WDT_CTRL_TRIGGERED; bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_CTRL, reg); } /* Disable wdt reset by mouse and kbd */ reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_CFG); reg &= ~(SCHSIO_WDT_CFG_MSEN | SCHSIO_WDT_CFG_MSEN); bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_CFG, reg); wdog_register(schsio_wdt_cb, sc); }
void berkwdt_attach(struct device *parent, struct device *self, void *aux) { struct berkwdt_softc *sc = (struct berkwdt_softc *)self; struct pci_attach_args *const pa = (struct pci_attach_args *)aux; bus_size_t iosize; u_int8_t reg; /* retrieve the I/O region (BAR 0) */ if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, &sc->sc_iot, &sc->sc_ioh, NULL, &iosize, 0) != 0) { printf(": couldn't find PCI I/O region\n"); return; } /* Check for reboot by the card */ reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh, PCWD_PCI_CS1); if (reg & WD_PCI_WTRP) { printf(", warning: watchdog triggered"); if (reg & WD_PCI_TTRP) printf(", overheat detected"); /* clear trip status & LED and keep mode of relay 2 */ reg &= WD_PCI_R2DS; reg |= WD_PCI_WTRP; bus_space_write_1(sc->sc_iot, sc->sc_ioh, PCWD_PCI_CS1, reg); } printf("\n"); /* ensure that the watchdog is disabled */ berkwdt_stop(sc); sc->sc_period = 0; /* register with the watchdog framework */ wdog_register(berkwdt_set_timeout, sc); }
void bcmpm_attach(struct device *parent, struct device *self, void *args) { struct bcmpm_softc *sc = (struct bcmpm_softc *)self; struct armv7_attach_args *aa = args; struct fdt_memory mem; sc->sc_iot = aa->aa_iot; if (fdt_get_memory_address(aa->aa_node, 0, &mem)) panic("%s: could not extract memory data from FDT", __func__); if (bus_space_map(sc->sc_iot, mem.addr, mem.size, 0, &sc->sc_ioh)) panic("%s: bus_space_map failed!", __func__); printf("\n"); bcmpm_sc = sc; extern void (*fdt_platform_watchdog_reset_fn)(void); fdt_platform_watchdog_reset_fn = bcmpm_wdog_reset; wdog_register(bcmpm_wdog_cb, sc); }
void tcpcib_attach(struct device *parent, struct device *self, void *aux) { struct tcpcib_softc *sc = (struct tcpcib_softc *)self; struct pci_attach_args *pa = aux; struct timecounter *tc = &sc->sc_hpet_timecounter; u_int32_t reg, wdtbase; sc->sc_active = 0; /* High Precision Event Timer */ sc->sc_hpet_iot = pa->pa_memt; if (bus_space_map(sc->sc_hpet_iot, E600_HPET_BASE, E600_HPET_SIZE, 0, &sc->sc_hpet_ioh) == 0) { tc->tc_get_timecount = tcpcib_hpet_get_timecount; /* XXX 64-bit counter is not supported! */ tc->tc_counter_mask = 0xffffffff; reg = bus_space_read_4(sc->sc_hpet_iot, sc->sc_hpet_ioh, E600_HPET_PERIOD); /* femtosecs -> Hz */ tc->tc_frequency = 1000000000000000ULL / reg; tc->tc_name = sc->sc_dev.dv_xname; tc->tc_quality = 2000; tc->tc_priv = sc; tc_init(tc); /* Enable counting */ bus_space_write_4(sc->sc_hpet_iot, sc->sc_hpet_ioh, E600_HPET_GC, E600_HPET_GC_ENABLE); sc->sc_active |= E600_HPET_ACTIVE; printf(": %llu Hz timer", tc->tc_frequency); } /* Map Watchdog I/O space */ reg = pci_conf_read(pa->pa_pc, pa->pa_tag, E600_LPC_WDTBA); wdtbase = reg & 0xffff; sc->sc_wdt_iot = pa->pa_iot; if (reg & (1U << 31) && wdtbase) { if (PCI_MAPREG_IO_ADDR(wdtbase) == 0 || bus_space_map(sc->sc_wdt_iot, PCI_MAPREG_IO_ADDR(wdtbase), E600_WDT_SIZE, 0, &sc->sc_wdt_ioh)) { printf("%c can't map watchdog I/O space", sc->sc_active ? ',' : ':'); goto corepcib; } printf("%c watchdog", sc->sc_active ? ',' : ':'); /* Check for reboot on timeout */ reg = bus_space_read_1(sc->sc_wdt_iot, sc->sc_wdt_ioh, E600_WDT_RR1); if (reg & E600_WDT_RR1_TIMEOUT) { printf(", reboot on timeout"); /* Clear timeout bit */ tcpcib_wdt_unlock(sc); bus_space_write_1(sc->sc_wdt_iot, sc->sc_wdt_ioh, E600_WDT_RR1, E600_WDT_RR1_TIMEOUT); } /* Check it's not locked already */ reg = bus_space_read_1(sc->sc_wdt_iot, sc->sc_wdt_ioh, E600_WDT_WDTLR); if (reg & E600_WDT_WDTLR_LOCK) { printf(", locked"); goto corepcib; } /* Disable watchdog */ tcpcib_wdt_stop(sc); sc->sc_wdt_period = 0; sc->sc_active |= E600_WDT_ACTIVE; /* Register new watchdog */ wdog_register(tcpcib_wdt_cb, sc); } corepcib: /* Provide core pcib(4) functionality */ pcibattach(parent, self, aux); }
void glxpcib_attach(struct device *parent, struct device *self, void *aux) { struct glxpcib_softc *sc = (struct glxpcib_softc *)self; struct timecounter *tc = &sc->sc_timecounter; #ifndef SMALL_KERNEL struct pci_attach_args *pa = (struct pci_attach_args *)aux; u_int64_t wa; #if NGPIO > 0 u_int64_t ga; struct gpiobus_attach_args gba; int i, gpio = 0; #endif u_int64_t sa; struct i2cbus_attach_args iba; int i2c = 0; bus_space_handle_t tmpioh; #endif tc->tc_get_timecount = glxpcib_get_timecount; tc->tc_counter_mask = 0xffffffff; tc->tc_frequency = 3579545; tc->tc_name = "CS5536"; tc->tc_quality = 1000; tc->tc_priv = sc; tc_init(tc); printf(": rev %d, 32-bit %lluHz timer", (int)rdmsr(AMD5536_REV) & AMD5536_REV_MASK, tc->tc_frequency); #ifndef SMALL_KERNEL /* Attach the watchdog timer */ sc->sc_iot = pa->pa_iot; wa = rdmsr(MSR_LBAR_MFGPT); if (wa & MSR_LBAR_ENABLE && !bus_space_map(sc->sc_iot, wa & MSR_MFGPT_ADDR_MASK, MSR_MFGPT_SIZE, 0, &sc->sc_ioh)) { /* count in seconds (as upper level desires) */ bus_space_write_2(sc->sc_iot, sc->sc_ioh, AMD5536_MFGPT0_SETUP, AMD5536_MFGPT_CNT_EN | AMD5536_MFGPT_CMP2EV | AMD5536_MFGPT_CMP2 | AMD5536_MFGPT_DIV_MASK | AMD5536_MFGPT_STOP_EN); wdog_register(glxpcib_wdogctl_cb, sc); sc->sc_wdog = 1; printf(", watchdog"); } #if NGPIO > 0 /* map GPIO I/O space */ sc->sc_gpio_iot = pa->pa_iot; ga = rdmsr(MSR_LBAR_GPIO); if (ga & MSR_LBAR_ENABLE && !bus_space_map(sc->sc_gpio_iot, ga & MSR_GPIO_ADDR_MASK, MSR_GPIO_SIZE, 0, &sc->sc_gpio_ioh)) { printf(", gpio"); /* initialize pin array */ for (i = 0; i < AMD5536_GPIO_NPINS; i++) { sc->sc_gpio_pins[i].pin_num = i; sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN | GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN | GPIO_PIN_INVIN | GPIO_PIN_INVOUT; /* read initial state */ sc->sc_gpio_pins[i].pin_state = glxpcib_gpio_pin_read(sc, i); } /* create controller tag */ sc->sc_gpio_gc.gp_cookie = sc; sc->sc_gpio_gc.gp_pin_read = glxpcib_gpio_pin_read; sc->sc_gpio_gc.gp_pin_write = glxpcib_gpio_pin_write; sc->sc_gpio_gc.gp_pin_ctl = glxpcib_gpio_pin_ctl; gba.gba_name = "gpio"; gba.gba_gc = &sc->sc_gpio_gc; gba.gba_pins = sc->sc_gpio_pins; gba.gba_npins = AMD5536_GPIO_NPINS; gpio = 1; } #endif /* NGPIO */ /* Map SMB I/O space */ sc->sc_smb_iot = pa->pa_iot; sa = rdmsr(MSR_LBAR_SMB); if (sa & MSR_LBAR_ENABLE && !bus_space_map(sc->sc_smb_iot, sa & MSR_SMB_ADDR_MASK, MSR_SMB_SIZE, 0, &sc->sc_smb_ioh)) { printf(", i2c"); /* Enable controller */ bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, AMD5536_SMB_CTL2, AMD5536_SMB_CTL2_EN | AMD5536_SMB_CTL2_FREQ); /* Disable interrupts */ bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, AMD5536_SMB_CTL1, 0); /* Disable slave address */ bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, AMD5536_SMB_ADDR, 0); /* Stall the bus after start */ bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, AMD5536_SMB_CTL1, AMD5536_SMB_CTL1_STASTRE); /* Attach I2C framework */ sc->sc_smb_ic.ic_cookie = sc; sc->sc_smb_ic.ic_acquire_bus = glxpcib_smb_acquire_bus; sc->sc_smb_ic.ic_release_bus = glxpcib_smb_release_bus; sc->sc_smb_ic.ic_send_start = glxpcib_smb_send_start; sc->sc_smb_ic.ic_send_stop = glxpcib_smb_send_stop; sc->sc_smb_ic.ic_initiate_xfer = glxpcib_smb_initiate_xfer; sc->sc_smb_ic.ic_read_byte = glxpcib_smb_read_byte; sc->sc_smb_ic.ic_write_byte = glxpcib_smb_write_byte; rw_init(&sc->sc_smb_lck, "iiclk"); bzero(&iba, sizeof(iba)); iba.iba_name = "iic"; iba.iba_tag = &sc->sc_smb_ic; i2c = 1; } /* Map PMS I/O space and enable the ``Power Immediate'' feature */ sa = rdmsr(MSR_LBAR_PMS); if (sa & MSR_LBAR_ENABLE && !bus_space_map(pa->pa_iot, sa & MSR_PMS_ADDR_MASK, MSR_PMS_SIZE, 0, &tmpioh)) { bus_space_write_4(pa->pa_iot, tmpioh, AMD5536_PMS_SSC, AMD5536_PMS_SSC_SET_PI); bus_space_barrier(pa->pa_iot, tmpioh, AMD5536_PMS_SSC, 4, BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); bus_space_unmap(pa->pa_iot, tmpioh, MSR_PMS_SIZE); } #endif /* SMALL_KERNEL */ pcibattach(parent, self, aux); #ifndef SMALL_KERNEL #if NGPIO > 0 if (gpio) config_found(&sc->sc_dev, &gba, gpiobus_print); #endif if (i2c) config_found(&sc->sc_dev, &iba, iicbus_print); config_search(glxpcib_search, self, pa); #endif }
void imc_attach(struct device *parent, struct device *self, void *aux) { struct imc_attach_args iaa; #if NEISA > 0 struct eisabus_attach_args eba; #endif uint32_t reg, lastreg; uint32_t id, rev; int have_eisa; id = imc_read(IMC_SYSID); rev = id & IMC_SYSID_REVMASK; /* EISA exists on Indigo2 only */ if (sys_config.system_type != SGI_IP20 && sys_config.system_subtype == IP22_INDIGO2) have_eisa = (id & IMC_SYSID_HAVEISA) != 0; else have_eisa = 0; printf(": revision %d\n", rev); /* Clear CPU/GIO error status registers to clear any leftover bits. */ imc_bus_reset(); /* Disable watchdog if leftover from previous reboot */ imc_watchdog_cb(self, 0); /* Hook the bus error handler into the ISR */ set_intr(INTPRI_BUSERR, CR_INT_4, imc_bus_error); /* * Enable parity reporting on GIO/main memory transactions, except * on systems with the ECC memory controller, where enabling parity * interferes with regular operation and causes sticky false errors. * * Disable parity checking on CPU bus transactions (as turning * it on seems to cause spurious bus errors), but enable parity * checking on CPU reads from main memory (note that this bit * has the opposite sense... Turning it on turns the checks off!). * * Finally, turn on interrupt writes to the CPU from the MC. */ reg = imc_read(IMC_CPUCTRL0); if (ip22_ecc) reg &= ~(IMC_CPUCTRL0_GPR | IMC_CPUCTRL0_MPR); else reg |= IMC_CPUCTRL0_GPR | IMC_CPUCTRL0_MPR; reg &= ~IMC_CPUCTRL0_NCHKMEMPAR; reg |= IMC_CPUCTRL0_INTENA; imc_write(IMC_CPUCTRL0, reg); /* Setup the MC write buffer depth */ /* * XXX This hardcoded value is not documented anywhere, and can be * XXX traced back to DaveM's internship at SGI in 1996, so it can * XXX be considered correct at least for IP24 (and, to a lesser * XXX extent, IP22). IP20 and IP28 systems seem to run happy with * XXX this value as well. */ reg = imc_read(IMC_CPUCTRL1); reg = (reg & ~IMC_CPUCTRL1_MCHWMSK) | 13; /* * Force endianness on the onboard HPC and both slots. * This should be safe for Fullhouse, but leave it conditional * for now. */ switch (sys_config.system_type) { case SGI_IP22: if (sys_config.system_subtype == IP22_INDIGO2) break; /* FALLTHROUGH */ case SGI_IP20: reg |= IMC_CPUCTRL1_HPCFX; reg |= IMC_CPUCTRL1_EXP0FX; reg |= IMC_CPUCTRL1_EXP1FX; reg &= ~IMC_CPUCTRL1_HPCLITTLE; reg &= ~IMC_CPUCTRL1_EXP0LITTLE; reg &= ~IMC_CPUCTRL1_EXP1LITTLE; break; } imc_write(IMC_CPUCTRL1, reg); /* * Try and read the GIO64 arbitrator configuration register value. * See comments above the declaration of imc_arb_value for why we * are doing this. */ reg = 0; lastreg = ~reg; while (reg != lastreg || (reg & ~0xffff) != 0) { lastreg = reg; reg = imc_read(IMC_GIO64ARB); /* read another harmless register */ (void)imc_read(IMC_CPUCTRL0); } /* * Set GIO64 arbitrator configuration register: * * Preserve PROM-set graphics-related bits, as they seem to depend * on the graphics variant present and I'm not sure how to figure * that out or 100% sure what the correct settings are for each. */ reg &= (IMC_GIO64ARB_GRX64 | IMC_GIO64ARB_GRXRT | IMC_GIO64ARB_GRXMST); /* * Rest of settings are machine/board dependent */ switch (sys_config.system_type) { case SGI_IP20: reg |= IMC_GIO64ARB_ONEGIO; reg |= IMC_GIO64ARB_EXP0RT | IMC_GIO64ARB_EXP1RT; reg |= IMC_GIO64ARB_EXP0MST | IMC_GIO64ARB_EXP1MST; reg &= ~(IMC_GIO64ARB_HPC64 | IMC_GIO64ARB_HPCEXP64 | IMC_GIO64ARB_EISA64 | IMC_GIO64ARB_EXP064 | IMC_GIO64ARB_EXP164 | IMC_GIO64ARB_EXP0PIPE | IMC_GIO64ARB_EXP1PIPE); break; default: /* * GIO64 invariant for all IP22 platforms: one GIO bus, * HPC1 @ 64 */ reg |= IMC_GIO64ARB_ONEGIO | IMC_GIO64ARB_HPC64; switch (sys_config.system_subtype) { default: case IP22_INDY: case IP22_CHALLS: /* XXX is MST mutually exclusive? */ reg |= IMC_GIO64ARB_EXP0RT | IMC_GIO64ARB_EXP1RT; reg |= IMC_GIO64ARB_EXP0MST | IMC_GIO64ARB_EXP1MST; /* EISA (VINO, really) can bus-master, is 64-bit */ reg |= IMC_GIO64ARB_EISAMST | IMC_GIO64ARB_EISA64; break; case IP22_INDIGO2: /* * All Fullhouse boards have a 64-bit HPC2 and pipelined * EXP0 slot. */ reg |= IMC_GIO64ARB_HPCEXP64 | IMC_GIO64ARB_EXP0PIPE; /* * The EISA bus is the real thing, and is a 32-bit bus. */ reg &= ~IMC_GIO64ARB_EISA64; if (rev < 2) { /* EXP0 realtime, EXP1 can master */ reg |= IMC_GIO64ARB_EXP0RT | IMC_GIO64ARB_EXP1MST; } else { /* EXP1 pipelined as well, EISA masters */ reg |= IMC_GIO64ARB_EXP1PIPE | IMC_GIO64ARB_EISAMST; } break; } } imc_write(IMC_GIO64ARB, reg); imc_arb_value = reg; memset(&iaa, 0, sizeof(iaa)); iaa.iaa_name = "gio"; iaa.iaa_st = &imcbus_tag; iaa.iaa_dmat = &imc_bus_dma_tag; config_found(self, &iaa, imc_print); #if NEISA > 0 if (have_eisa) { memset(&eba, 0, sizeof(eba)); eba.eba_busname = "eisa"; eba.eba_iot = &imcbus_eisa_io_tag; eba.eba_memt = &imcbus_eisa_mem_tag; eba.eba_dmat = &imc_bus_dma_tag; eba.eba_ec = NULL; config_found(self, &eba, imc_print); } #endif /* Register watchdog */ wdog_register(imc_watchdog_cb, self); }
void elansc_attach(struct device *parent, struct device *self, void *aux) { struct elansc_softc *sc = (void *) self; struct pci_attach_args *pa = aux; struct gpiobus_attach_args gba; struct timecounter *tc; uint16_t rev, data; uint8_t ressta, cpuctl, tmr; int pin, reg, shift; sc->sc_memt = pa->pa_memt; if (bus_space_map(sc->sc_memt, MMCR_BASE_ADDR, NBPG, 0, &sc->sc_memh) != 0) { printf(": unable to map registers\n"); return; } rev = bus_space_read_2(sc->sc_memt, sc->sc_memh, MMCR_REVID); cpuctl = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_CPUCTL); ressta = bus_space_read_1(sc->sc_memt, sc->sc_memh, MMCR_RESSTA); printf(": product %d stepping %d.%d, CPU clock %s, reset %b\n", (rev & REVID_PRODID) >> REVID_PRODID_SHIFT, (rev & REVID_MAJSTEP) >> REVID_MAJSTEP_SHIFT, (rev & REVID_MINSTEP), elansc_speeds[cpuctl & CPUCTL_CPU_CLK_SPD_MASK], ressta, RSTBITS); /* * Determine cause of the last reset, and issue a warning if it * was due to watchdog expiry. */ if (ressta & RESSTA_WDT_RST_DET) printf("%s: WARNING: LAST RESET DUE TO WATCHDOG EXPIRATION!\n", sc->sc_dev.dv_xname); bus_space_write_1(sc->sc_memt, sc->sc_memh, MMCR_RESSTA, ressta); /* Set up the watchdog registers with some defaults. */ elansc_wdogctl_write(sc, WDTMRCTL_WRST_ENB | WDTMRCTL_EXP_SEL30); /* ...and clear it. */ elansc_wdogctl_reset(sc); wdog_register(elansc_wdogctl_cb, sc); elansc = sc; cpu_setperf = elansc_setperf; cpu_cpuspeed = elansc_cpuspeed; elansc_update_cpuspeed(); /* Initialize GPIO pins array */ for (pin = 0; pin < ELANSC_PIO_NPINS; pin++) { sc->sc_gpio_pins[pin].pin_num = pin; sc->sc_gpio_pins[pin].pin_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT; /* Read initial state */ reg = (pin < 16 ? MMCR_PIODIR15_0 : MMCR_PIODIR31_16); shift = pin % 16; data = bus_space_read_2(sc->sc_memt, sc->sc_memh, reg); if ((data & (1 << shift)) == 0) sc->sc_gpio_pins[pin].pin_flags = GPIO_PIN_INPUT; else sc->sc_gpio_pins[pin].pin_flags = GPIO_PIN_OUTPUT; if (elansc_gpio_pin_read(sc, pin) == 0) sc->sc_gpio_pins[pin].pin_state = GPIO_PIN_LOW; else sc->sc_gpio_pins[pin].pin_state = GPIO_PIN_HIGH; } /* Create controller tag */ sc->sc_gpio_gc.gp_cookie = sc; sc->sc_gpio_gc.gp_pin_read = elansc_gpio_pin_read; sc->sc_gpio_gc.gp_pin_write = elansc_gpio_pin_write; sc->sc_gpio_gc.gp_pin_ctl = elansc_gpio_pin_ctl; gba.gba_name = "gpio"; gba.gba_gc = &sc->sc_gpio_gc; gba.gba_pins = sc->sc_gpio_pins; gba.gba_npins = ELANSC_PIO_NPINS; /* Attach GPIO framework */ config_found(&sc->sc_dev, &gba, gpiobus_print); /* Disable GP1/2, clear the current count, and set the period to max */ bus_space_write_2(sc->sc_memt, sc->sc_memh, GPTMR1CTL, GPTMRCTL_ENB_WR | GPTMRCTL_CONT_CMP | GPTMRCTL_PSC_SEL | GPTMRCTL_RTG); bus_space_write_2(sc->sc_memt, sc->sc_memh, GPTMR1CNT, 0); bus_space_write_2(sc->sc_memt, sc->sc_memh, GPTMR1MAXCMPA, 0); bus_space_write_2(sc->sc_memt, sc->sc_memh, GPTMR2CTL, GPTMRCTL_ENB_WR | GPTMRCTL_CONT_CMP); bus_space_write_2(sc->sc_memt, sc->sc_memh, GPTMR2CNT, 0); bus_space_write_2(sc->sc_memt, sc->sc_memh, GPTMR2MAXCMPA, 0); tmr = bus_space_read_1(sc->sc_memt, sc->sc_memh, SWTMRCFG); /* Enable GP1/2 */ bus_space_write_2(sc->sc_memt, sc->sc_memh, GPTMR1CTL, GPTMRCTL_ENB | GPTMRCTL_ENB_WR | GPTMRCTL_CONT_CMP | GPTMRCTL_PSC_SEL | GPTMRCTL_RTG); bus_space_write_2(sc->sc_memt, sc->sc_memh, GPTMR2CTL, GPTMRCTL_ENB | GPTMRCTL_ENB_WR | GPTMRCTL_CONT_CMP); /* Attach timer */ tc = &sc->sc_tc; tc->tc_get_timecount = elansc_tc_read; tc->tc_poll_pps = NULL; tc->tc_counter_mask = ~0; tc->tc_frequency = (tmr & 1) ? (33000000 / 4) : (33333333 / 4); tc->tc_name = sc->sc_dev.dv_xname; tc->tc_quality = 1000; tc->tc_priv = sc; tc_init(tc); }