From bad5062f7bcbb21be735ee9b372f179915ae1f93 Mon Sep 17 00:00:00 2001 From: Gordon Willem Klok Date: Tue, 19 Dec 2006 16:20:02 +0000 Subject: 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 --- sys/dev/acpi/acpicpu.c | 101 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 70 insertions(+), 31 deletions(-) (limited to 'sys/dev/acpi') 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 * @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -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; +} -- cgit v1.2.3