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); }
void k8_powernow_init(struct cpu_info *ci) { uint64_t status; u_int maxfid, maxvid, i; u_int32_t extcpuid, dummy; struct k8pnow_cpu_state *cstate; struct k8pnow_state *state; char * techname = NULL; if (setperf_prio > 1) return; cstate = malloc(sizeof(struct k8pnow_cpu_state), M_DEVBUF, M_NOWAIT); if (!cstate) return; cstate->n_states = 0; status = rdmsr(MSR_AMDK7_FIDVID_STATUS); maxfid = PN8_STA_MFID(status); maxvid = PN8_STA_MVID(status); /* * If start FID is different to max FID, then it is a * mobile processor. If not, it is a low powered desktop * processor. */ if (PN8_STA_SFID(status) != PN8_STA_MFID(status)) techname = "PowerNow! K8"; else techname = "Cool'n'Quiet K8"; #if NACPICPU > 0 /* If we have acpi check acpi first */ if (!k8pnow_acpi_init(cstate, status)) #endif { if (!k8pnow_states(cstate, ci->ci_signature, maxfid, maxvid)) { /* Extended CPUID signature value */ CPUID(0x80000001, extcpuid, dummy, dummy, dummy); k8pnow_states(cstate, extcpuid, maxfid, maxvid); } } if (cstate->n_states) { printf("%s: %s %d MHz: speeds:", ci->ci_dev->dv_xname, techname, cpuspeed); for (i = cstate->n_states; i > 0; i--) { state = &cstate->state_table[i-1]; printf(" %d", state->freq); } printf(" MHz\n"); k8pnow_current_state = cstate; cpu_setperf = k8_powernow_setperf; setperf_prio = 1; return; } free(cstate, M_DEVBUF, sizeof(*cstate)); }
static int powernow_init(void) { uint64_t status; size_t len , freq_len; uint32_t maxfid, maxvid, i; struct k8pnow_cpu_state *cstate; struct k8pnow_state *state; const char *techname; u_int32_t regs [4]; cpuspeed = 0; struct sysctl_oid *oid, *leaf; do_cpuid(0x80000000, regs); if (regs[0] < 0x80000007) return 1; do_cpuid(0x80000007, regs); if (!(regs[3] & AMD_PN_FID_VID)) return 2; /* Extended CPUID signature value */ do_cpuid(0x80000001, regs); cstate = kmalloc(sizeof(struct k8pnow_cpu_state), M_DEVBUF, M_WAITOK); cstate->n_states = 0; status = rdmsr(MSR_AMDK7_FIDVID_STATUS); maxfid = PN8_STA_MFID(status); maxvid = PN8_STA_MVID(status); if (PN8_STA_SFID(status) != PN8_STA_MFID(status)) techname = "PowerNow!"; else techname = "Cool`n'Quiet"; k8pnow_states(cstate, regs[0], maxfid, maxvid); len = 0; if (cstate->n_states) { freq_len = cstate->n_states * (sizeof("9999 ") - 1) + 1; kprintf("%s speeds:", techname); for (i = cstate->n_states; i > 0; i--) { state = &cstate->state_table[i - 1]; kprintf(" %d", state->freq); len += ksnprintf(freqs_available + len, freq_len - len, "%d%s", state->freq, i > 1 ? " " : ""); } kprintf(" MHz\n"); k8pnow_current_state = cstate; k8_powernow_setperf(k8_get_curfreq()); } else { kfree(cstate, M_DEVBUF); kprintf("powernow: no power states found\n"); return 3; } /* * Setup the sysctl sub-tree machdep.powernow.* */ oid = SYSCTL_ADD_NODE(&machdep_powernow_ctx, SYSCTL_STATIC_CHILDREN(_machdep), OID_AUTO, "powernow", CTLFLAG_RD, NULL, ""); if (oid == NULL) return (EOPNOTSUPP); oid = SYSCTL_ADD_NODE(&machdep_powernow_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "frequency", CTLFLAG_RD, NULL, ""); if (oid == NULL) return (EOPNOTSUPP); leaf = SYSCTL_ADD_PROC(&machdep_powernow_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "target", CTLTYPE_INT | CTLFLAG_RW, NULL, 0, powernow_sysctl_helper, "I", "Target CPU frequency for AMD PowerNow!"); if (leaf == NULL) return (EOPNOTSUPP); leaf = SYSCTL_ADD_PROC(&machdep_powernow_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "current", CTLTYPE_INT | CTLFLAG_RD, NULL, 0, powernow_sysctl_helper, "I", "Current CPU frequency for AMD PowerNow!"); if (leaf == NULL) return (EOPNOTSUPP); leaf = SYSCTL_ADD_STRING(&machdep_powernow_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "available", CTLFLAG_RD, freqs_available, sizeof(freqs_available), "CPU frequencies supported by AMD PowerNow!"); if (leaf == NULL) return (EOPNOTSUPP); return (0); }