Esempio n. 1
0
static int
pn_probe(device_t dev)
{
	struct pn_softc *sc;
	uint64_t status;
	uint64_t rate;
	struct pcpu *pc;
	u_int sfid, mfid, cfid;

	sc = device_get_softc(dev);
	sc->errata = 0;
	status = rdmsr(MSR_AMDK7_FIDVID_STATUS);

	pc = cpu_get_pcpu(dev);
	if (pc == NULL)
		return (ENODEV);

	cpu_est_clockrate(pc->pc_cpuid, &rate);

	switch (cpu_id & 0xf00) {
	case 0x600:
		sfid = PN7_STA_SFID(status);
		mfid = PN7_STA_MFID(status);
		cfid = PN7_STA_CFID(status);
		sc->pn_type = PN7_TYPE;
		sc->fsb = rate / 100000 / pn7_fid_to_mult[cfid];

		/*
		 * If start FID is different to max FID, then it is a
		 * mobile processor.  If not, it is a low powered desktop
		 * processor.
		 */
		if (PN7_STA_SFID(status) != PN7_STA_MFID(status)) {
			sc->vid_to_volts = pn7_mobile_vid_to_volts;
			device_set_desc(dev, "PowerNow! K7");
		} else {
			sc->vid_to_volts = pn7_desktop_vid_to_volts;
			device_set_desc(dev, "Cool`n'Quiet K7");
		}
		break;

	case 0xf00:
		sfid = PN8_STA_SFID(status);
		mfid = PN8_STA_MFID(status);
		cfid = PN8_STA_CFID(status);
		sc->pn_type = PN8_TYPE;
		sc->vid_to_volts = pn8_vid_to_volts;
		sc->fsb = rate / 100000 / pn8_fid_to_mult[cfid];

		if (PN8_STA_SFID(status) != PN8_STA_MFID(status))
			device_set_desc(dev, "PowerNow! K8");
		else
			device_set_desc(dev, "Cool`n'Quiet K8");
		break;
	default:
		return (ENODEV);
	}

	return (0);
}
Esempio n. 2
0
static int
ichss_set(device_t dev, const struct cf_setting *set)
{
	struct ichss_softc *sc;
	uint8_t bmval, new_val, old_val, req_val;
	uint64_t rate;
	register_t regs;

	/* Look up appropriate bit value based on frequency. */
	sc = device_get_softc(dev);
	if (CPUFREQ_CMP(set->freq, sc->sets[0].freq))
		req_val = 0;
	else if (CPUFREQ_CMP(set->freq, sc->sets[1].freq))
		req_val = ICHSS_CTRL_BIT;
	else
		return (EINVAL);
	DPRINT("ichss: requested setting %d\n", req_val);

	/* Disable interrupts and get the other register contents. */
	regs = intr_disable();
	old_val = ICH_GET_REG(sc->ctrl_reg) & ~ICHSS_CTRL_BIT;

	/*
	 * Disable bus master arbitration, write the new value to the control
	 * register, and then re-enable bus master arbitration.
	 */
	bmval = ICH_GET_REG(sc->bm_reg) | ICHSS_BM_DISABLE;
	ICH_SET_REG(sc->bm_reg, bmval);
	ICH_SET_REG(sc->ctrl_reg, old_val | req_val);
	ICH_SET_REG(sc->bm_reg, bmval & ~ICHSS_BM_DISABLE);

	/* Get the new value and re-enable interrupts. */
	new_val = ICH_GET_REG(sc->ctrl_reg);
	intr_restore(regs);

	/* Check if the desired state was indeed selected. */
	if (req_val != (new_val & ICHSS_CTRL_BIT)) {
	    device_printf(sc->dev, "transition to %d failed\n", req_val);
	    return (ENXIO);
	}

	/* Re-initialize our cycle counter if we don't know this new state. */
	if (sc->sets[req_val].freq == CPUFREQ_VAL_UNKNOWN) {
		cpu_est_clockrate(0, &rate);
		sc->sets[req_val].freq = rate / 1000000;
		DPRINT("ichss: set calibrated new rate of %d\n",
		    sc->sets[req_val].freq);
	}

	return (0);
}
Esempio n. 3
0
static int
acpi_px_get(device_t dev, struct cf_setting *set)
{
	struct acpi_perf_softc *sc;
	uint64_t rate;
	int i;
	struct pcpu *pc;

	if (set == NULL)
		return (EINVAL);
	sc = device_get_softc(dev);

	/* If we can't get new states, return immediately. */
	if (sc->info_only)
		return (ENXIO);

	/* If we've set the rate before, use the cached value. */
	if (sc->px_curr_state != CPUFREQ_VAL_UNKNOWN) {
		acpi_px_to_set(dev, &sc->px_states[sc->px_curr_state], set);
		return (0);
	}

	/* Otherwise, estimate and try to match against our settings. */
	pc = cpu_get_pcpu(dev);
	if (pc == NULL)
		return (ENXIO);
	cpu_est_clockrate(pc->pc_cpuid, &rate);
	rate /= 1000000;
	for (i = 0; i < sc->px_count; i++) {
		if (CPUFREQ_CMP(sc->px_states[i].core_freq, rate)) {
			sc->px_curr_state = i;
			acpi_px_to_set(dev, &sc->px_states[i], set);
			break;
		}
	}

	/* No match, give up. */
	if (i == sc->px_count) {
		sc->px_curr_state = CPUFREQ_VAL_UNKNOWN;
		set->freq = CPUFREQ_VAL_UNKNOWN;
	}

	return (0);
}
Esempio n. 4
0
static int
ichss_get(device_t dev, struct cf_setting *set)
{
	struct ichss_softc *sc;
	uint64_t rate;
	uint8_t state;

	sc = device_get_softc(dev);
	state = ICH_GET_REG(sc->ctrl_reg) & ICHSS_CTRL_BIT;

	/* If we haven't changed settings yet, estimate the current value. */
	if (sc->sets[state].freq == CPUFREQ_VAL_UNKNOWN) {
		cpu_est_clockrate(0, &rate);
		sc->sets[state].freq = rate / 1000000;
		DPRINT("ichss: get calibrated new rate of %d\n",
		    sc->sets[state].freq);
	}
	*set = sc->sets[state];

	return (0);
}