static int ichss_probe(device_t dev) { device_t est_dev, perf_dev; int error, type; /* * If the ACPI perf driver has attached and is not just offering * info, let it manage things. Also, if Enhanced SpeedStep is * available, don't attach. */ perf_dev = device_find_child(device_get_parent(dev), "acpi_perf", -1); if (perf_dev && device_is_attached(perf_dev)) { error = CPUFREQ_DRV_TYPE(perf_dev, &type); if (error == 0 && (type & CPUFREQ_FLAG_INFO_ONLY) == 0) return (ENXIO); } est_dev = device_find_child(device_get_parent(dev), "est", -1); if (est_dev && device_is_attached(est_dev)) return (ENXIO); device_set_desc(dev, "SpeedStep ICH"); return (-1000); }
static int hwpstate_probe(device_t dev) { struct hwpstate_softc *sc; device_t perf_dev; uint64_t msr; int error, type; /* * Only hwpstate0. * It goes well with acpi_throttle. */ if (device_get_unit(dev) != 0) return (ENXIO); sc = device_get_softc(dev); sc->dev = dev; /* * Check if acpi_perf has INFO only flag. */ perf_dev = device_find_child(device_get_parent(dev), "acpi_perf", -1); error = TRUE; if (perf_dev && device_is_attached(perf_dev)) { error = CPUFREQ_DRV_TYPE(perf_dev, &type); if (error == 0) { if ((type & CPUFREQ_FLAG_INFO_ONLY) == 0) { /* * If acpi_perf doesn't have INFO_ONLY flag, * it will take care of pstate transitions. */ HWPSTATE_DEBUG(dev, "acpi_perf will take care of pstate transitions.\n"); return (ENXIO); } else { /* * If acpi_perf has INFO_ONLY flag, (_PCT has FFixedHW) * we can get _PSS info from acpi_perf * without going into ACPI. */ HWPSTATE_DEBUG(dev, "going to fetch info from acpi_perf\n"); error = hwpstate_get_info_from_acpi_perf(dev, perf_dev); } } } if (error == 0) { /* * Now we get _PSS info from acpi_perf without error. * Let's check it. */ msr = rdmsr(MSR_AMD_10H_11H_LIMIT); if (sc->cfnum != 1 + AMD_10H_11H_GET_PSTATE_MAX_VAL(msr)) { HWPSTATE_DEBUG(dev, "msr and acpi _PSS count mismatch.\n"); error = TRUE; } } /* * If we cannot get info from acpi_perf, * Let's get info from MSRs. */ if (error) error = hwpstate_get_info_from_msr(dev); if (error) return (error); device_set_desc(dev, "Cool`n'Quiet 2.0"); return (0); }
static int pn_decode_acpi(device_t dev, device_t perf_dev) { int i, j, n; uint64_t status; uint32_t ctrl; u_int cpuid; u_int regs[4]; struct pn_softc *sc; struct powernow_state state; struct cf_setting sets[POWERNOW_MAX_STATES]; int count = POWERNOW_MAX_STATES; int type; int rv; if (perf_dev == NULL) return (ENXIO); rv = CPUFREQ_DRV_SETTINGS(perf_dev, sets, &count); if (rv) return (ENXIO); rv = CPUFREQ_DRV_TYPE(perf_dev, &type); if (rv || (type & CPUFREQ_FLAG_INFO_ONLY) == 0) return (ENXIO); sc = device_get_softc(dev); do_cpuid(0x80000001, regs); cpuid = regs[0]; if ((cpuid & 0xfff) == 0x760) sc->errata |= A0_ERRATA; ctrl = 0; sc->sgtc = 0; for (n = 0, i = 0; i < count; ++i) { ctrl = sets[i].spec[PX_SPEC_CONTROL]; switch (sc->pn_type) { case PN7_TYPE: state.fid = ACPI_PN7_CTRL_TO_FID(ctrl); state.vid = ACPI_PN7_CTRL_TO_VID(ctrl); if ((sc->errata & A0_ERRATA) && (pn7_fid_to_mult[state.fid] % 10) == 5) continue; state.freq = 100 * pn7_fid_to_mult[state.fid] * sc->fsb; break; case PN8_TYPE: state.fid = ACPI_PN8_CTRL_TO_FID(ctrl); state.vid = ACPI_PN8_CTRL_TO_VID(ctrl); state.freq = 100 * pn8_fid_to_mult[state.fid] * sc->fsb; break; } state.power = sets[i].power; j = n; while (j > 0 && sc->powernow_states[j - 1].freq < state.freq) { memcpy(&sc->powernow_states[j], &sc->powernow_states[j - 1], sizeof(struct powernow_state)); --j; } memcpy(&sc->powernow_states[j], &state, sizeof(struct powernow_state)); ++n; } sc->powernow_max_states = n; state = sc->powernow_states[0]; status = rdmsr(MSR_AMDK7_FIDVID_STATUS); switch (sc->pn_type) { case PN7_TYPE: sc->sgtc = ACPI_PN7_CTRL_TO_SGTC(ctrl); /* * XXX Some bios forget the max frequency! * This maybe indicates we have the wrong tables. Therefore, * don't implement a quirk, but fallback to BIOS legacy * tables instead. */ if (PN7_STA_MFID(status) != state.fid) { device_printf(dev, "ACPI MAX frequency not found\n"); return (EINVAL); } break; case PN8_TYPE: sc->vst = ACPI_PN8_CTRL_TO_VST(ctrl), sc->mvs = ACPI_PN8_CTRL_TO_MVS(ctrl), sc->pll = ACPI_PN8_CTRL_TO_PLL(ctrl), sc->rvo = ACPI_PN8_CTRL_TO_RVO(ctrl), sc->irt = ACPI_PN8_CTRL_TO_IRT(ctrl); sc->low = 0; /* XXX */ /* * powernow k8 supports only one low frequency. */ if (sc->powernow_max_states >= 2 && (sc->powernow_states[sc->powernow_max_states - 2].fid < 8)) return (EINVAL); break; } return (0); }