示例#1
0
void
k7_powernow_setperf(int level)
{
	unsigned int i;
	int cvid, cfid, vid = 0, fid = 0;
	uint64_t status, ctl;
	struct k7pnow_cpu_state * cstate;

	cstate = k7pnow_current_state;

	i = ((level * cstate->n_states) + 1) / 101;
	if (i >= cstate->n_states)
		i = cstate->n_states - 1;
	fid = cstate->state_table[i].fid;
	vid = cstate->state_table[i].vid;

	if (fid == 0 || vid == 0)
		return;

	status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
	cfid = PN7_STA_CFID(status);
	cvid = PN7_STA_CVID(status);

	/*
	 * We're already at the requested level.
	 */
	if (fid == cfid && vid == cvid)
		return;

	ctl = rdmsr(MSR_AMDK7_FIDVID_CTL) & PN7_CTR_FIDCHRATIO;

	ctl |= PN7_CTR_FID(fid);
	ctl |= PN7_CTR_VID(vid);
	ctl |= PN7_CTR_SGTC(cstate->sgtc);

	if (cstate->flags & PN7_FLAG_ERRATA_A0)
		disable_intr();

	if (k7pnow_fid_to_mult[fid] < k7pnow_fid_to_mult[cfid]) {
		wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_FIDC);
		if (vid != cvid)
			wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_VIDC);
	} else {
		wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_VIDC);
		if (fid != cfid)
			wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_FIDC);
	}

	if (cstate->flags & PN7_FLAG_ERRATA_A0)
		enable_intr();

	status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
	cfid = PN7_STA_CFID(status);
	cvid = PN7_STA_CVID(status);
	if (cfid == fid || cvid == vid)
		cpuspeed = cstate->state_table[i].freq;
}
示例#2
0
static int
pn_get(device_t dev, struct cf_setting *cf)
{
	struct pn_softc *sc;
	u_int cfid = 0, cvid = 0;
	int i;
	uint64_t status;

	if (cf == NULL)
		return (EINVAL);
	sc = device_get_softc(dev);
	if (sc->errata & PENDING_STUCK)
		return (ENXIO);

	status = rdmsr(MSR_AMDK7_FIDVID_STATUS);

	switch (sc->pn_type) {
	case PN7_TYPE:
		cfid = PN7_STA_CFID(status);
		cvid = PN7_STA_CVID(status);
		break;
	case PN8_TYPE:
		cfid = PN8_STA_CFID(status);
		cvid = PN8_STA_CVID(status);
		break;
	}
	for (i = 0; i < sc->powernow_max_states; ++i)
		if (cfid == sc->powernow_states[i].fid &&
		    cvid == sc->powernow_states[i].vid)
			break;

	if (i < sc->powernow_max_states) {
		cf->freq = sc->powernow_states[i].freq / 1000;
		cf->power = sc->powernow_states[i].power;
		cf->lat = 200;
		cf->volts = sc->vid_to_volts[cvid];
		cf->dev = dev;
	} else {
		memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf));
		cf->dev = NULL;
	}

	return (0);
}