Module Name: src Committed By: macallan Date: Wed Oct 19 21:12:51 UTC 2011
Modified Files: src/sys/arch/macppc/dev: obio.c Log Message: add cpufreq support To generate a diff of this commit: cvs rdiff -u -r1.35 -r1.36 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.35 src/sys/arch/macppc/dev/obio.c:1.36 --- src/sys/arch/macppc/dev/obio.c:1.35 Mon Aug 1 22:40:21 2011 +++ src/sys/arch/macppc/dev/obio.c Wed Oct 19 21:12:50 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: obio.c,v 1.35 2011/08/01 22:40:21 macallan Exp $ */ +/* $NetBSD: obio.c,v 1.36 2011/10/19 21:12:50 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.35 2011/08/01 22:40:21 macallan Exp $"); +__KERNEL_RCSID(0, "$NetBSD: obio.c,v 1.36 2011/10/19 21:12:50 macallan Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -50,6 +50,7 @@ __KERNEL_RCSID(0, "$NetBSD: obio.c,v 1.3 #include <macppc/dev/obiovar.h> #include <powerpc/cpu.h> +#include <sys/cpufreq.h> #include "opt_obio.h" @@ -72,6 +73,7 @@ struct obio_softc { int sc_voltage; int sc_busspeed; int sc_spd_hi, sc_spd_lo; + struct cpufreq sc_cf; #endif }; @@ -84,7 +86,8 @@ static int obio_get_cpu_speed(struct ob static int sysctl_cpuspeed_temp(SYSCTLFN_ARGS); static int sysctl_cpuspeed_cur(SYSCTLFN_ARGS); static int sysctl_cpuspeed_available(SYSCTLFN_ARGS); - +static void obio_get_freq(void *, void *); +static void obio_set_freq(void *, void *); static const char *keylargo[] = {"Keylargo", "AAPL,Keylargo", NULL}; @@ -333,10 +336,22 @@ uint8_t obio_read_1(int offset) #ifdef OBIO_SPEED_CONTROL static void +obio_setup_cpufreq(device_t dev) +{ + struct obio_softc *sc = device_private(dev); + int ret; + + ret = cpufreq_register(&sc->sc_cf); + if (ret != 0) + aprint_error_dev(sc->sc_dev, "cpufreq_register() failed, error %d\n", ret); +} + +static void obio_setup_gpios(struct obio_softc *sc, int node) { uint32_t gpio_base, reg[6]; const struct sysctlnode *sysctl_node, *me, *freq; + struct cpufreq *cf = &sc->sc_cf; char name[32]; int child, use_dfs, cpunode, hiclock; @@ -394,7 +409,10 @@ obio_setup_gpios(struct obio_softc *sc, hiclock = 0; cpunode = OF_finddevice("/cpus/@0"); OF_getprop(cpunode, "clock-frequency", &hiclock, 4); - printf("hiclock: %d\n", (hiclock + 500000) / 1000000); + if (hiclock != 0) + sc->sc_spd_hi = (hiclock + 500000) / 1000000; + printf("hiclock: %d\n", sc->sc_spd_hi); + sysctl_node = NULL; if (sysctl_createv(NULL, 0, NULL, @@ -436,6 +454,22 @@ obio_setup_gpios(struct obio_softc *sc, } else printf("couldn't create 'available' node\n"); printf("speed: %d\n", curcpu()->ci_khz); + + /* support cpufreq */ + snprintf(cf->cf_name, CPUFREQ_NAME_MAX, "Intrepid"); + cf->cf_state[0].cfs_freq = sc->sc_spd_hi; + cf->cf_state[1].cfs_freq = sc->sc_spd_lo; + cf->cf_state_count = 2; + cf->cf_mp = FALSE; + cf->cf_cookie = sc; + cf->cf_get_freq = obio_get_freq; + cf->cf_set_freq = obio_set_freq; + /* + * XXX + * cpufreq_register() calls xc_broadcast() which relies on kthreads + * running so we need to postpone it + */ + config_interrupts(sc->sc_dev, obio_setup_cpufreq); } static void @@ -497,6 +531,34 @@ obio_get_cpu_speed(struct obio_softc *sc return 0; } +static void +obio_get_freq(void *cookie, void *spd) +{ + struct obio_softc *sc = cookie; + uint32_t *freq; + + freq = spd; + if (obio_get_cpu_speed(sc) == 0) { + *freq = sc->sc_spd_lo; + } else + *freq = sc->sc_spd_hi; +} + +static void +obio_set_freq(void *cookie, void *spd) +{ + struct obio_softc *sc = cookie; + uint32_t *freq; + + freq = spd; + if (*freq == sc->sc_spd_lo) { + obio_set_cpu_speed(sc, 0); + } else if (*freq == sc->sc_spd_hi) { + obio_set_cpu_speed(sc, 1); + } else + aprint_error_dev(sc->sc_dev, "%s(%d) bogus CPU speed\n", __func__, *freq); +} + static int sysctl_cpuspeed_temp(SYSCTLFN_ARGS) {