diff options
author | Gordon Willem Klok <gwk@cvs.openbsd.org> | 2006-12-19 16:20:02 +0000 |
---|---|---|
committer | Gordon Willem Klok <gwk@cvs.openbsd.org> | 2006-12-19 16:20:02 +0000 |
commit | bad5062f7bcbb21be735ee9b372f179915ae1f93 (patch) | |
tree | bd705f6eeaff18e0bf98070fefefb460d7a736ef /sys/dev/acpi | |
parent | dfe85635a5050b621b50bf50a389b4399cea4312 (diff) |
Hook up acpicpu to the hw.setperf mechanism, this allows people running
ACPI kernels built with the acpicpu diff to scale processor and frequency
voltage, various incarnations tested by brad, thib, johan m:son lindman.
ok marco
Diffstat (limited to 'sys/dev/acpi')
-rw-r--r-- | sys/dev/acpi/acpicpu.c | 101 |
1 files changed, 70 insertions, 31 deletions
diff --git a/sys/dev/acpi/acpicpu.c b/sys/dev/acpi/acpicpu.c index 5bb492448f0..e871cade899 100644 --- a/sys/dev/acpi/acpicpu.c +++ b/sys/dev/acpi/acpicpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpicpu.c,v 1.10 2006/10/12 16:38:21 jordan Exp $ */ +/* $OpenBSD: acpicpu.c,v 1.11 2006/12/19 16:20:01 gwk Exp $ */ /* * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org> * @@ -18,6 +18,7 @@ #include <sys/param.h> #include <sys/proc.h> #include <sys/signalvar.h> +#include <sys/sysctl.h> #include <sys/systm.h> #include <sys/device.h> #include <sys/malloc.h> @@ -38,6 +39,7 @@ int acpicpu_match(struct device *, void *, void *); void acpicpu_attach(struct device *, struct device *, void *); int acpicpu_notify(struct aml_node *, int, void *); +void acpicpu_setperf(int); struct acpicpu_softc { struct device sc_dev; @@ -65,6 +67,15 @@ struct cfdriver acpicpu_cd = { NULL, "acpicpu", DV_DULL }; +extern int setperf_prio; + +#ifdef __i386__ +struct acpicpu_softc *acpicpu_sc[I386_MAXPROCS]; +#elif __amd64__ +extern int cpuspeed; +struct acpicpu_softc *acpicpu_sc[X86_MAXPROCS]; +#endif + int acpicpu_match(struct device *parent, void *match, void *aux) { @@ -119,6 +130,13 @@ acpicpu_attach(struct device *parent, struct device *self, void *aux) aml_register_notify(sc->sc_devnode->parent, NULL, acpicpu_notify, sc); + + if (setperf_prio < 30) { + cpu_setperf = acpicpu_setperf; + setperf_prio = 30; + } + acpicpu_sc[sc->sc_dev.dv_unit] = sc; + } int @@ -171,35 +189,6 @@ acpicpu_getpct(struct acpicpu_softc *sc) sc->sc_pct.pct_status.grd_gas.access_size, sc->sc_pct.pct_status.grd_gas.address); -#if 0 - char pb[8]; - - acpi_gasio(sc->sc_acpi, ACPI_IOREAD, - sc->sc_pct.pct_ctrl.grd_gas.address_space_id, - sc->sc_pct.pct_ctrl.grd_gas.address, - 1, - 4, - //sc->sc_pct.pct_ctrl.grd_gas.register_bit_width >> 3, - pb); - - acpi_gasio(sc->sc_acpi, ACPI_IOWRITE, - sc->sc_pct.pct_ctrl.grd_gas.address_space_id, - sc->sc_pct.pct_ctrl.grd_gas.address, - 1, - 4, - //sc->sc_pct.pct_ctrl.grd_gas.register_bit_width >> 3, - &sc->sc_pss[3].pss_ctrl); - - acpi_gasio(sc->sc_acpi, ACPI_IOREAD, - sc->sc_pct.pct_ctrl.grd_gas.address_space_id, - sc->sc_pct.pct_ctrl.grd_gas.address, - 1, - 4, - //sc->sc_pct.pct_ctrl.grd_gas.register_bit_width >> 3, - pb); - printf("acpicpu: %02x %02x %02x %02x\n", pb[0], pb[1], pb[2], pb[3]); -#endif - return (0); } @@ -262,6 +251,56 @@ acpicpu_notify(struct aml_node *node, int notify_type, void *arg) break; } - return (0); } + +void +acpicpu_setperf(int level) { + struct acpicpu_softc *sc; + struct acpicpu_pss *pss = NULL; + int high, low, freq, i; + u_int32_t status; + + sc = acpicpu_sc[cpu_number()]; + high = sc->sc_pss[0].pss_core_freq; + low = sc->sc_pss[sc->sc_pss_len - 1].pss_core_freq; + freq = low + (high - low) * level / 100; + + for (i = 0; i < sc->sc_pss_len; i++) { + if (sc->sc_pss[i].pss_core_freq <= freq) { + pss = &sc->sc_pss[i]; + break; + } + } + + if (pss == NULL) + return; + + acpi_gasio(sc->sc_acpi, ACPI_IOREAD, + sc->sc_pct.pct_status.grd_gas.address_space_id, + sc->sc_pct.pct_status.grd_gas.address, 1, 4, + &status); + + /* Are we already at the requested frequency? */ + if (status == pss->pss_status) + return; + + acpi_gasio(sc->sc_acpi, ACPI_IOWRITE, + sc->sc_pct.pct_ctrl.grd_gas.address_space_id, + sc->sc_pct.pct_ctrl.grd_gas.address, 1, 4, + &pss->pss_ctrl); + + acpi_gasio(sc->sc_acpi, ACPI_IOREAD, + sc->sc_pct.pct_status.grd_gas.address_space_id, + sc->sc_pct.pct_status.grd_gas.address, 1, 4, + &status); + + /* Did the transition succeed? */ + if (status == pss->pss_status) +#ifdef __i386__ + pentium_mhz = pss->pss_core_freq; +#elif __amd64__ + cpuspeed = pss->pss_core_freq; +#endif + return; +} |