summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorGordon Willem Klok <gwk@cvs.openbsd.org>2007-05-31 17:49:17 +0000
committerGordon Willem Klok <gwk@cvs.openbsd.org>2007-05-31 17:49:17 +0000
commit2ff1e8275d4f73445fd38ed3b6ae0767fd684746 (patch)
treea7bcd3fc6eae5f19e8d0cbf9fc15c99ea13f9d88 /sys/arch
parent7a4d4259325b6c7e8c397b1542f832df8e736a9a (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.c127
-rw-r--r--sys/arch/i386/i386/powernow-k8.c107
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);