void amdpm_attach(struct device *parent, struct device *self, void *aux) { struct amdpm_softc *sc = (struct amdpm_softc *) self; struct pci_attach_args *pa = aux; struct i2cbus_attach_args iba; pcireg_t cfg_reg, reg; int i; sc->sc_pc = pa->pa_pc; sc->sc_tag = pa->pa_tag; sc->sc_iot = pa->pa_iot; sc->sc_poll = 1; /* XXX */ if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_AMD) { cfg_reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AMDPM_CONFREG); if ((cfg_reg & AMDPM_PMIOEN) == 0) { printf(": PMxx space isn't enabled\n"); return; } reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AMDPM_PMPTR); if (AMDPM_PMBASE(reg) == 0 || bus_space_map(sc->sc_iot, AMDPM_PMBASE(reg), AMDPM_PMSIZE, 0, &sc->sc_ioh)) { printf("\n"); return; } if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, AMDPM_SMB_REGS, AMDPM_SMB_SIZE, &sc->sc_i2c_ioh)) { printf(": failed to map I2C subregion\n"); return; } if ((cfg_reg & AMDPM_TMRRST) == 0 && (cfg_reg & AMDPM_STOPTMR) == 0 && (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_PBC768_PMC || PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_8111_PMC)) { printf(": %d-bit timer at %lluHz", (cfg_reg & AMDPM_TMR32) ? 32 : 24, amdpm_timecounter.tc_frequency); amdpm_timecounter.tc_priv = sc; if (cfg_reg & AMDPM_TMR32) amdpm_timecounter.tc_counter_mask = 0xffffffffu; tc_init(&amdpm_timecounter); } if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_PBC768_PMC || PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_8111_PMC) { if ((cfg_reg & AMDPM_RNGEN) ==0) { pci_conf_write(pa->pa_pc, pa->pa_tag, AMDPM_CONFREG, cfg_reg | AMDPM_RNGEN); cfg_reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AMDPM_CONFREG); } if (cfg_reg & AMDPM_RNGEN) { /* Check to see if we can read data from the RNG. */ (void) bus_space_read_4(sc->sc_iot, sc->sc_ioh, AMDPM_RNGDATA); for (i = 1000; i--; ) { if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, AMDPM_RNGSTAT) & AMDPM_RNGDONE) break; DELAY(10); } if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, AMDPM_RNGSTAT) & AMDPM_RNGDONE) { printf(": rng active"); timeout_set(&sc->sc_rnd_ch, amdpm_rnd_callout, sc); amdpm_rnd_callout(sc); } } } } else if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NVIDIA) { reg = pci_conf_read(pa->pa_pc, pa->pa_tag, NFPM_PMPTR); if (AMDPM_PMBASE(reg) == 0 || bus_space_map(sc->sc_iot, AMDPM_PMBASE(reg), AMDPM_SMB_SIZE, 0, &sc->sc_i2c_ioh)) { printf(": failed to map I2C subregion\n"); return; } } printf("\n"); /* Attach I2C bus */ rw_init(&sc->sc_i2c_lock, "iiclk"); sc->sc_i2c_tag.ic_cookie = sc; sc->sc_i2c_tag.ic_acquire_bus = amdpm_i2c_acquire_bus; sc->sc_i2c_tag.ic_release_bus = amdpm_i2c_release_bus; sc->sc_i2c_tag.ic_exec = amdpm_i2c_exec; bzero(&iba, sizeof(iba)); iba.iba_name = "iic"; iba.iba_tag = &sc->sc_i2c_tag; config_found(self, &iba, iicbus_print); }
void amdpm_attach(struct device *parent, struct device *self, void *aux) { struct amdpm_softc *sc = (struct amdpm_softc *) self; struct pci_attach_args *pa = aux; struct timeval tv1, tv2; pcireg_t reg; int i; sc->sc_pc = pa->pa_pc; sc->sc_tag = pa->pa_tag; sc->sc_iot = pa->pa_iot; reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AMDPM_CONFREG); if ((reg & AMDPM_PMIOEN) == 0) { printf(": PMxx space isn't enabled\n"); return; } reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AMDPM_PMPTR); if (bus_space_map(sc->sc_iot, AMDPM_PMBASE(reg), AMDPM_PMSIZE, 0, &sc->sc_ioh)) { printf(": failed to map PMxx space\n"); return; } reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AMDPM_CONFREG); if (reg & AMDPM_RNGEN) { /* Check to see if we can read data from the RNG. */ (void) bus_space_read_4(sc->sc_iot, sc->sc_ioh, AMDPM_RNGDATA); /* benchmark the RNG */ microtime(&tv1); for (i = 2 * 1024; i--; ) { while(!(bus_space_read_1(sc->sc_iot, sc->sc_ioh, AMDPM_RNGSTAT) & AMDPM_RNGDONE)) ; (void) bus_space_read_4(sc->sc_iot, sc->sc_ioh, AMDPM_RNGDATA); } microtime(&tv2); timersub(&tv2, &tv1, &tv1); if (tv1.tv_sec) tv1.tv_usec += 1000000 * tv1.tv_sec; printf(": rng active, %dKb/sec", 8 * 1000000 / tv1.tv_usec); #ifdef AMDPM_RND_COUNTERS evcnt_attach_dynamic(&sc->sc_rnd_hits, EVCNT_TYPE_MISC, NULL, sc->sc_dev.dv_xname, "rnd hits"); evcnt_attach_dynamic(&sc->sc_rnd_miss, EVCNT_TYPE_MISC, NULL, sc->sc_dev.dv_xname, "rnd miss"); for (i = 0; i < 256; i++) { evcnt_attach_dynamic(&sc->sc_rnd_data[i], EVCNT_TYPE_MISC, NULL, sc->sc_dev.dv_xname, "rnd data"); } #endif timeout_set(&sc->sc_rnd_ch, amdpm_rnd_callout, sc); amdpm_rnd_callout(sc); } }