diff options
author | Gordon Willem Klok <gwk@cvs.openbsd.org> | 2007-05-31 17:49:17 +0000 |
---|---|---|
committer | Gordon Willem Klok <gwk@cvs.openbsd.org> | 2007-05-31 17:49:17 +0000 |
commit | 2ff1e8275d4f73445fd38ed3b6ae0767fd684746 (patch) | |
tree | a7bcd3fc6eae5f19e8d0cbf9fc15c99ea13f9d88 /sys/arch | |
parent | 7a4d4259325b6c7e8c397b1542f832df8e736a9a (diff) |
Make powernow-k8 on amd64 and i386 use the _PSS object from acpi to
retreive p_state data as spelled out in the amd64 bios and kernel
developers guide. This code is still a little rough around the edges but
has been tested by myself on a tyan machine and by phessler at theapt
dot org on an HP DL145. This diff also takes a first stab and cleaning up
the acpicpu dmesg spam.
ok tedu, marco
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/amd64/amd64/powernow-k8.c | 127 | ||||
-rw-r--r-- | sys/arch/i386/i386/powernow-k8.c | 107 |
2 files changed, 218 insertions, 16 deletions
diff --git a/sys/arch/amd64/amd64/powernow-k8.c b/sys/arch/amd64/amd64/powernow-k8.c index 81674890924..6409218e574 100644 --- a/sys/arch/amd64/amd64/powernow-k8.c +++ b/sys/arch/amd64/amd64/powernow-k8.c @@ -1,4 +1,4 @@ -/* $OpenBSD: powernow-k8.c,v 1.18 2007/05/06 03:37:08 gwk Exp $ */ +/* $OpenBSD: powernow-k8.c,v 1.19 2007/05/31 17:49:15 gwk Exp $ */ /* * Copyright (c) 2004 Martin Végiard. * Copyright (c) 2004-2005 Bruno Ducrot @@ -39,6 +39,13 @@ #include <machine/cpufunc.h> #include <machine/bus.h> +#include "acpicpu.h" + +#if NACPICPU > 0 +#include <dev/acpi/acpidev.h> +#include <dev/acpi/acpivar.h> +#endif + #define BIOS_START 0xe0000 #define BIOS_LEN 0x20000 @@ -71,13 +78,13 @@ extern int setperf_prio; #define PN8_PSB_TO_BATT(x) (((x) >> 6) & 0x03) /* ACPI ctr_val status register to PowerNow K8 configuration */ -#define ACPI_PN8_CTRL_TO_FID(x) ((x) & 0x3f) -#define ACPI_PN8_CTRL_TO_VID(x) (((x) >> 6) & 0x1f) -#define ACPI_PN8_CTRL_TO_VST(x) (((x) >> 11) & 0x1f) -#define ACPI_PN8_CTRL_TO_MVS(x) (((x) >> 18) & 0x03) -#define ACPI_PN8_CTRL_TO_PLL(x) (((x) >> 20) & 0x7f) -#define ACPI_PN8_CTRL_TO_RVO(x) (((x) >> 28) & 0x03) -#define ACPI_PN8_CTRL_TO_IRT(x) (((x) >> 30) & 0x03) +#define PN8_ACPI_CTRL_TO_FID(x) ((x) & 0x3f) +#define PN8_ACPI_CTRL_TO_VID(x) (((x) >> 6) & 0x1f) +#define PN8_ACPI_CTRL_TO_VST(x) (((x) >> 11) & 0x1f) +#define PN8_ACPI_CTRL_TO_MVS(x) (((x) >> 18) & 0x03) +#define PN8_ACPI_CTRL_TO_PLL(x) (((x) >> 20) & 0x7f) +#define PN8_ACPI_CTRL_TO_RVO(x) (((x) >> 28) & 0x03) +#define PN8_ACPI_CTRL_TO_IRT(x) (((x) >> 30) & 0x03) #define WRITE_FIDVID(fid, vid, ctrl) \ wrmsr(MSR_AMDK7_FIDVID_CTL, \ @@ -134,6 +141,13 @@ int k8pnow_decode_pst(struct k8pnow_cpu_state *, uint8_t *); int k8pnow_states(struct k8pnow_cpu_state *, uint32_t, unsigned int, unsigned int); +#if NACPICPU > 0 +int k8pnow_acpi_init(struct k8pnow_cpu_state *, uint64_t); +void k8pnow_acpi_pss_changed(struct acpicpu_pss *, int); +int k8pnow_acpi_states(struct k8pnow_cpu_state *, struct acpicpu_pss *, int, + uint64_t); +#endif + int k8pnow_read_pending_wait(uint64_t *status) { @@ -283,6 +297,87 @@ k8pnow_decode_pst(struct k8pnow_cpu_state *cstate, uint8_t *p) return 1; } +#if NACPICPU > 0 + +int +k8pnow_acpi_states(struct k8pnow_cpu_state * cstate, struct acpicpu_pss * pss, + int nstates, uint64_t status) +{ + struct k8pnow_state state; + int j, k, n; + uint32_t ctrl; + + k = -1; + + for (n = 0; n < cstate->n_states; n++) { + if (status == pss[n].pss_status) + k = n; + ctrl = pss[n].pss_ctrl; + state.fid = PN8_ACPI_CTRL_TO_FID(ctrl); + state.vid = PN8_ACPI_CTRL_TO_VID(ctrl); + + state.freq = pss[n].pss_core_freq; + j = n; + while (j > 0 && cstate->state_table[j - 1].freq > state.freq) { + memcpy(&cstate->state_table[j], + &cstate->state_table[j - 1], + sizeof(struct k8pnow_state)); + --j; + } + memcpy(&cstate->state_table[j], &state, + sizeof(struct k8pnow_state)); + } + + return k; +} + +void +k8pnow_acpi_pss_changed(struct acpicpu_pss * pss, int npss) +{ + int curs; + struct k8pnow_cpu_state * cstate; + uint32_t ctrl; + uint64_t status; + + status = rdmsr(MSR_AMDK7_FIDVID_STATUS); + cstate = k8pnow_current_state; + + curs = k8pnow_acpi_states(cstate, pss, npss, status); + ctrl = pss[curs].pss_ctrl; + cstate->vst = PN8_ACPI_CTRL_TO_VST(ctrl); + cstate->mvs = PN8_ACPI_CTRL_TO_MVS(ctrl); + cstate->pll = PN8_ACPI_CTRL_TO_PLL(ctrl); + cstate->irt = PN8_ACPI_CTRL_TO_IRT(ctrl); + cstate->low = 0; + cstate->n_states = npss; +} + +int +k8pnow_acpi_init(struct k8pnow_cpu_state * cstate, uint64_t status) +{ + int curs; + uint32_t ctrl; + struct acpicpu_pss *pss; + + cstate->n_states = acpicpu_fetch_pss(&pss); + if (cstate->n_states == 0) + return 0; + acpicpu_set_notify(k8pnow_acpi_pss_changed); + + curs = k8pnow_acpi_states(cstate, pss, cstate->n_states, status); + ctrl = pss[curs].pss_ctrl; + + cstate->vst = PN8_ACPI_CTRL_TO_VST(ctrl); + cstate->mvs = PN8_ACPI_CTRL_TO_MVS(ctrl); + cstate->pll = PN8_ACPI_CTRL_TO_PLL(ctrl); + cstate->irt = PN8_ACPI_CTRL_TO_IRT(ctrl); + cstate->low = 0; + + return 1; +} + +#endif /* NACPICPU */ + int k8pnow_states(struct k8pnow_cpu_state *cstate, uint32_t cpusig, unsigned int fid, unsigned int vid) @@ -358,11 +453,17 @@ k8_powernow_init(struct cpu_info *ci) else techname = "Cool'n'Quiet K8"; - /* Extended CPUID signature value */ - CPUID(0x80000001, extcpuid, dummy, dummy, dummy); - - if (!k8pnow_states(cstate, ci->ci_signature, maxfid, maxvid)) - k8pnow_states(cstate, extcpuid, maxfid, maxvid); +#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); diff --git a/sys/arch/i386/i386/powernow-k8.c b/sys/arch/i386/i386/powernow-k8.c index a59fb1810de..8e4e2204fe8 100644 --- a/sys/arch/i386/i386/powernow-k8.c +++ b/sys/arch/i386/i386/powernow-k8.c @@ -1,4 +1,4 @@ -/* $OpenBSD: powernow-k8.c,v 1.22 2007/04/24 17:12:26 gwk Exp $ */ +/* $OpenBSD: powernow-k8.c,v 1.23 2007/05/31 17:49:16 gwk Exp $ */ /* * Copyright (c) 2004 Martin Végiard. @@ -40,6 +40,13 @@ #include <machine/cpufunc.h> #include <machine/bus.h> +#include "acpicpu.h" + +#if NACPICPU > 0 +#include <dev/acpi/acpidev.h> +#include <dev/acpi/acpivar.h> +#endif + #define BIOS_START 0xe0000 #define BIOS_LEN 0x20000 #define BIOS_STEP 16 @@ -137,6 +144,13 @@ int k8pnow_decode_pst(struct k8pnow_cpu_state *, uint8_t *); int k8pnow_states(struct k8pnow_cpu_state *, uint32_t, unsigned int, unsigned int); +#if NACPICPU > 0 +int k8pnow_acpi_init(struct k8pnow_cpu_state *, uint64_t); +void k8pnow_acpi_pss_changed(struct acpicpu_pss *, int); +int k8pnow_acpi_states(struct k8pnow_cpu_state *, struct acpicpu_pss *, int, + uint64_t); +#endif + int k8pnow_read_pending_wait(uint64_t *status) { @@ -330,6 +344,87 @@ k8pnow_states(struct k8pnow_cpu_state *cstate, uint32_t cpusig, } +#if NACPICPU > 0 + +int +k8pnow_acpi_states(struct k8pnow_cpu_state * cstate, struct acpicpu_pss * pss, + int nstates, uint64_t status) +{ + struct k8pnow_state state; + int j, k, n; + uint32_t ctrl; + + k = -1; + + for (n = 0; n < cstate->n_states; n++) { + if (status == pss[n].pss_status) + k = n; + ctrl = pss[n].pss_ctrl; + state.fid = PN8_ACPI_CTRL_TO_FID(ctrl); + state.vid = PN8_ACPI_CTRL_TO_VID(ctrl); + + state.freq = pss[n].pss_core_freq; + j = n; + while (j > 0 && cstate->state_table[j - 1].freq > state.freq) { + memcpy(&cstate->state_table[j], + &cstate->state_table[j - 1], + sizeof(struct k8pnow_state)); + --j; + } + memcpy(&cstate->state_table[j], &state, + sizeof(struct k8pnow_state)); + } + + return k; +} + +void +k8pnow_acpi_pss_changed(struct acpicpu_pss * pss, int npss) +{ + int curs; + struct k8pnow_cpu_state * cstate; + uint32_t ctrl; + uint64_t status; + + status = rdmsr(MSR_AMDK7_FIDVID_STATUS); + cstate = k8pnow_current_state; + + curs = k8pnow_acpi_states(cstate, pss, npss, status); + ctrl = pss[curs].pss_ctrl; + cstate->vst = PN8_ACPI_CTRL_TO_VST(ctrl); + cstate->mvs = PN8_ACPI_CTRL_TO_MVS(ctrl); + cstate->pll = PN8_ACPI_CTRL_TO_PLL(ctrl); + cstate->irt = PN8_ACPI_CTRL_TO_IRT(ctrl); + cstate->low = 0; + cstate->n_states = npss; +} + +int +k8pnow_acpi_init(struct k8pnow_cpu_state * cstate, uint64_t status) +{ + int curs; + uint32_t ctrl; + struct acpicpu_pss *pss; + + cstate->n_states = acpicpu_fetch_pss(&pss); + if (cstate->n_states == 0) + return 0; + acpicpu_set_notify(k8pnow_acpi_pss_changed); + + curs = k8pnow_acpi_states(cstate, pss, cstate->n_states, status); + ctrl = pss[curs].pss_ctrl; + + cstate->vst = PN8_ACPI_CTRL_TO_VST(ctrl); + cstate->mvs = PN8_ACPI_CTRL_TO_MVS(ctrl); + cstate->pll = PN8_ACPI_CTRL_TO_PLL(ctrl); + cstate->irt = PN8_ACPI_CTRL_TO_IRT(ctrl); + cstate->low = 0; + + return 1; +} + +#endif /* NACPICPU */ + void k8_powernow_init(void) { @@ -379,8 +474,14 @@ k8_powernow_init(void) else techname = "Cool'n'Quiet K8"; - if (!k8pnow_states(cstate, ci->ci_signature, maxfid, maxvid)) - k8pnow_states(cstate, regs[0], maxfid, maxvid); +#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)) + k8pnow_states(cstate, regs[0], maxfid, maxvid); + } if (cstate->n_states) { printf("%s: %s %d MHz: speeds:", ci->ci_dev.dv_xname, techname, cpuspeed); |