Module Name: src Committed By: macallan Date: Wed Mar 16 05:08:29 UTC 2011
Modified Files: src/sys/arch/macppc/dev: obio.c Log Message: change the CPU speed sysctl to look more like the ACPI ones, as in machdep.<name>.frequency.available etc. so estd can work with minimal changes To generate a diff of this commit: cvs rdiff -u -r1.31 -r1.32 src/sys/arch/macppc/dev/obio.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/macppc/dev/obio.c diff -u src/sys/arch/macppc/dev/obio.c:1.31 src/sys/arch/macppc/dev/obio.c:1.32 --- src/sys/arch/macppc/dev/obio.c:1.31 Sun Dec 5 13:33:50 2010 +++ src/sys/arch/macppc/dev/obio.c Wed Mar 16 05:08:29 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: obio.c,v 1.31 2010/12/05 13:33:50 phx Exp $ */ +/* $NetBSD: obio.c,v 1.32 2011/03/16 05:08:29 macallan Exp $ */ /*- * Copyright (C) 1998 Internet Research Institute, Inc. @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: obio.c,v 1.31 2010/12/05 13:33:50 phx Exp $"); +__KERNEL_RCSID(0, "$NetBSD: obio.c,v 1.32 2011/03/16 05:08:29 macallan Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -71,6 +71,7 @@ #ifdef OBIO_SPEED_CONTROL int sc_voltage; int sc_busspeed; + int sc_spd_hi, sc_spd_lo; #endif }; @@ -81,6 +82,8 @@ static void obio_set_cpu_speed(struct obio_softc *, int); static int obio_get_cpu_speed(struct obio_softc *); static int sysctl_cpuspeed_temp(SYSCTLFN_ARGS); +static int sysctl_cpuspeed_cur(SYSCTLFN_ARGS); +static int sysctl_cpuspeed_available(SYSCTLFN_ARGS); static const char *keylargo[] = {"Keylargo", "AAPL,Keylargo", @@ -131,6 +134,8 @@ #ifdef OBIO_SPEED_CONTROL sc->sc_voltage = -1; sc->sc_busspeed = -1; + sc->sc_spd_lo = 600; + sc->sc_spd_hi = 800; #endif switch (PCI_PRODUCT(pa->pa_id)) { @@ -330,9 +335,9 @@ obio_setup_gpios(struct obio_softc *sc, int node) { uint32_t gpio_base, reg[6]; - struct sysctlnode *sysctl_node; + struct sysctlnode *sysctl_node, *me, *freq; char name[32]; - int child, use_dfs; + int child, use_dfs, cpunode, hiclock; if (of_compatible(sc->sc_node, keylargo) == -1) return; @@ -384,14 +389,55 @@ printf("%s: enabling Intrepid CPU speed control\n", sc->sc_dev.dv_xname); + sc->sc_spd_lo = curcpu()->ci_khz / 1000; + hiclock = 0; + cpunode = OF_finddevice("/cpus/@0"); + OF_getprop(cpunode, "clock-frequency", &hiclock, 4); + printf("hiclock: %d\n", (hiclock + 500000) / 1000000); sysctl_node = NULL; - sysctl_createv(NULL, 0, NULL, + + if (sysctl_createv(NULL, 0, NULL, + (const struct sysctlnode **)&me, + CTLFLAG_READWRITE, CTLTYPE_NODE, "intrepid", NULL, NULL, + 0, NULL, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL) != 0) + printf("couldn't create 'interpid' node\n"); + + if (sysctl_createv(NULL, 0, NULL, + (const struct sysctlnode **)&freq, + CTLFLAG_READWRITE, CTLTYPE_NODE, "frequency", NULL, NULL, + 0, NULL, 0, CTL_MACHDEP, me->sysctl_num, CTL_CREATE, CTL_EOL) != 0) + printf("couldn't create 'frequency' node\n"); + + if (sysctl_createv(NULL, 0, NULL, (const struct sysctlnode **)&sysctl_node, CTLFLAG_READWRITE | CTLFLAG_OWNDESC | CTLFLAG_IMMEDIATE, - CTLTYPE_INT, "cpu_speed", "CPU speed", sysctl_cpuspeed_temp, - (unsigned long)sc, NULL, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL); - if (sysctl_node != NULL) + CTLTYPE_INT, "target", "CPU speed", sysctl_cpuspeed_temp, + 0, NULL, 0, CTL_MACHDEP, me->sysctl_num, freq->sysctl_num, + CTL_CREATE, CTL_EOL) == 0) { + sysctl_node->sysctl_data = (void *)sc; + } else + printf("couldn't create 'target' node\n"); + + if (sysctl_createv(NULL, 0, NULL, + (const struct sysctlnode **)&sysctl_node, + CTLFLAG_READWRITE | CTLFLAG_IMMEDIATE, + CTLTYPE_INT, "current", NULL, sysctl_cpuspeed_cur, + 1, NULL, 0, CTL_MACHDEP, me->sysctl_num, freq->sysctl_num, + CTL_CREATE, CTL_EOL) == 0) { sysctl_node->sysctl_data = (void *)sc; + } else + printf("couldn't create 'current' node\n"); + + if (sysctl_createv(NULL, 0, NULL, + (const struct sysctlnode **)&sysctl_node, + CTLFLAG_READWRITE, + CTLTYPE_STRING, "available", NULL, sysctl_cpuspeed_available, + 2, NULL, 0, CTL_MACHDEP, me->sysctl_num, freq->sysctl_num, + CTL_CREATE, CTL_EOL) == 0) { + sysctl_node->sysctl_data = (void *)sc; + } else + printf("couldn't create 'available' node\n"); + printf("speed: %d\n", curcpu()->ci_khz); } static void @@ -458,27 +504,83 @@ { struct sysctlnode node = *rnode; struct obio_softc *sc = node.sysctl_data; - const int *np = newp; - int speed, nd = 0; + int speed, mhz; speed = obio_get_cpu_speed(sc); - node.sysctl_idata = speed; - if (np) { - /* we're asked to write */ - nd = *np; - node.sysctl_data = &speed; - if (sysctl_lookup(SYSCTLFN_CALL(&node)) == 0) { - int new_reg; - - new_reg = (max(0, min(1, node.sysctl_idata))); - obio_set_cpu_speed(sc, new_reg); - return 0; + switch (speed) { + case 0: + mhz = sc->sc_spd_lo; + break; + case 1: + mhz = sc->sc_spd_hi; + break; + default: + speed = -1; + } + node.sysctl_idata = mhz; + node.sysctl_data = &mhz; + if (sysctl_lookup(SYSCTLFN_CALL(&node)) == 0) { + int new_reg; + + new_reg = node.sysctl_idata; + if (new_reg == sc->sc_spd_lo) { + obio_set_cpu_speed(sc, 0); + } else if (new_reg == sc->sc_spd_hi) { + obio_set_cpu_speed(sc, 1); + } else { + printf("%s: new_reg %d\n", __func__, new_reg); + return EINVAL; } - return EINVAL; - } else { - node.sysctl_size = 4; - return(sysctl_lookup(SYSCTLFN_CALL(&node))); + return 0; } + return EINVAL; +} + +static int +sysctl_cpuspeed_cur(SYSCTLFN_ARGS) +{ + struct sysctlnode node = *rnode; + struct obio_softc *sc = node.sysctl_data; + int speed, mhz; + + speed = obio_get_cpu_speed(sc); + switch (speed) { + case 0: + mhz = sc->sc_spd_lo; + break; + case 1: + mhz = sc->sc_spd_hi; + break; + default: + speed = -1; + } + node.sysctl_idata = mhz; + node.sysctl_data = &mhz; + return sysctl_lookup(SYSCTLFN_CALL(&node)); +} + +static int +sysctl_cpuspeed_available(SYSCTLFN_ARGS) +{ + struct sysctlnode node = *rnode; + struct obio_softc *sc = node.sysctl_data; + char buf[128]; + int speed; + + speed = obio_get_cpu_speed(sc); + snprintf(buf, 128, "%d %d", sc->sc_spd_lo, sc->sc_spd_hi); + node.sysctl_data = buf; + return(sysctl_lookup(SYSCTLFN_CALL(&node))); +} + +SYSCTL_SETUP(sysctl_ams_setup, "sysctl obio subtree setup") +{ + + sysctl_createv(NULL, 0, NULL, NULL, + CTLFLAG_PERMANENT, + CTLTYPE_NODE, "machdep", NULL, + NULL, 0, NULL, 0, + CTL_MACHDEP, CTL_EOL); } #endif /* OBIO_SPEEDCONTROL */