Module Name: src Committed By: macallan Date: Fri Jun 1 18:06:58 UTC 2018
Modified Files: src/sys/arch/powerpc/conf: files.powerpc src/sys/arch/powerpc/oea: cpu_subr.c Added Files: src/sys/arch/powerpc/oea: cpu_speedctl.c Log Message: add clock speed control for 970MP CPUs To generate a diff of this commit: cvs rdiff -u -r1.89 -r1.90 src/sys/arch/powerpc/conf/files.powerpc cvs rdiff -u -r0 -r1.1 src/sys/arch/powerpc/oea/cpu_speedctl.c cvs rdiff -u -r1.94 -r1.95 src/sys/arch/powerpc/oea/cpu_subr.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/powerpc/conf/files.powerpc diff -u src/sys/arch/powerpc/conf/files.powerpc:1.89 src/sys/arch/powerpc/conf/files.powerpc:1.90 --- src/sys/arch/powerpc/conf/files.powerpc:1.89 Tue Mar 4 08:25:11 2014 +++ src/sys/arch/powerpc/conf/files.powerpc Fri Jun 1 18:06:58 2018 @@ -1,4 +1,4 @@ -# $NetBSD: files.powerpc,v 1.89 2014/03/04 08:25:11 matt Exp $ +# $NetBSD: files.powerpc,v 1.90 2018/06/01 18:06:58 macallan Exp $ defflag opt_altivec.h ALTIVEC K_ALTIVEC PPC_HAVE_SPE defflag opt_openpic.h OPENPIC_DISTRIBUTE @@ -51,6 +51,7 @@ file arch/powerpc/ibm4xx/copyoutstr.c p defparam opt_oea.h EXTMAP_RANGES=20 file arch/powerpc/oea/altivec.c (ppc_oea |ppc_oea64 | ppc_oea64_bridge) & altivec file arch/powerpc/oea/cpu_subr.c ppc_oea | ppc_oea64 | ppc_oea64_bridge | ppc_oea601 +file arch/powerpc/oea/cpu_speedctl.c ppc_oea64 | ppc_oea64_bridge file arch/powerpc/oea/oea_machdep.c ppc_oea | ppc_oea64 | ppc_oea64_bridge | ppc_oea601 file arch/powerpc/oea/pmap.c ppc_oea | ppc_oea601 file arch/powerpc/oea/pmap64.c ppc_oea64 Index: src/sys/arch/powerpc/oea/cpu_subr.c diff -u src/sys/arch/powerpc/oea/cpu_subr.c:1.94 src/sys/arch/powerpc/oea/cpu_subr.c:1.95 --- src/sys/arch/powerpc/oea/cpu_subr.c:1.94 Fri May 25 23:00:34 2018 +++ src/sys/arch/powerpc/oea/cpu_subr.c Fri Jun 1 18:06:58 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu_subr.c,v 1.94 2018/05/25 23:00:34 macallan Exp $ */ +/* $NetBSD: cpu_subr.c,v 1.95 2018/06/01 18:06:58 macallan Exp $ */ /*- * Copyright (c) 2001 Matt Thomas. @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cpu_subr.c,v 1.94 2018/05/25 23:00:34 macallan Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cpu_subr.c,v 1.95 2018/06/01 18:06:58 macallan Exp $"); #include "opt_ppcparam.h" #include "opt_ppccache.h" @@ -73,6 +73,8 @@ static void cpu_tau_setup(struct cpu_inf static void cpu_tau_refresh(struct sysmon_envsys *, envsys_data_t *); #endif +extern void init_scom_speedctl(void); + int cpu = -1; int ncpus; @@ -757,6 +759,11 @@ cpu_setup(device_t self, struct cpu_info cpu_tau_setup(ci); #endif +#if defined(PPC_OEA64) || defined(PPC_OEA64_BRIDGE) + if (vers == IBM970MP) + init_scom_speedctl(); +#endif + evcnt_attach_dynamic(&ci->ci_ev_clock, EVCNT_TYPE_INTR, NULL, xname, "clock"); evcnt_attach_dynamic(&ci->ci_ev_traps, EVCNT_TYPE_TRAP, @@ -1319,7 +1326,6 @@ cpu_spinup(device_t self, struct cpu_inf h->hatch_hid1 = mfspr(SPR_HID1); h->hatch_hid4 = mfspr(SPR_HID4); h->hatch_hid5 = mfspr(SPR_HID5); - printf("HIDs: %016llx %016llx\n", h->hatch_hid4, h->hatch_hid5); #endif __asm volatile ("mfsdr1 %0" : "=r"(h->hatch_sdr1)); Added files: Index: src/sys/arch/powerpc/oea/cpu_speedctl.c diff -u /dev/null src/sys/arch/powerpc/oea/cpu_speedctl.c:1.1 --- /dev/null Fri Jun 1 18:06:58 2018 +++ src/sys/arch/powerpc/oea/cpu_speedctl.c Fri Jun 1 18:06:58 2018 @@ -0,0 +1,183 @@ +/* $NetBSD: cpu_speedctl.c,v 1.1 2018/06/01 18:06:58 macallan Exp $ */ + +/*- + * Copyright (c) 2006 Michael Lorenz + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: cpu_speedctl.c,v 1.1 2018/06/01 18:06:58 macallan Exp $"); + +#include "opt_ppcparam.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/types.h> + +#include <powerpc/psl.h> +#include <powerpc/spr.h> +#include <powerpc/oea/cpufeat.h> +#include <powerpc/oea/spr.h> + +#include <sys/sysctl.h> +#include <dev/ofw/openfirm.h> + +void init_scom_speedctl(void); +static int scom_speedctl = 0; +static uint32_t scom_speeds[2]; +static uint32_t scom_reg[2]; +static int sysctl_cpuspeed_temp(SYSCTLFN_ARGS); +static int sysctl_cpuspeed_cur(SYSCTLFN_ARGS); +static int sysctl_cpuspeed_available(SYSCTLFN_ARGS); + +void +init_scom_speedctl(void) +{ + int node; + const struct sysctlnode *sysctl_node, *me, *freq; + + /* do this only once */ + if (scom_speedctl != 0) return; + scom_speedctl = 1; + + node = OF_finddevice("/cpus/@0"); + if (OF_getprop(node, "power-mode-data", scom_reg, 8) != 8) + return; + if (OF_getprop(node, "clock-frequency", scom_speeds, 4) != 4) + return; + scom_speeds[0] = scom_speeds[0] / 1000000; /* Hz -> MHz */ + scom_speeds[1] = scom_speeds[0] / 2; + + sysctl_node = NULL; + + if (sysctl_createv(NULL, 0, NULL, + &me, + CTLFLAG_READWRITE, CTLTYPE_NODE, "cpu", NULL, NULL, + 0, NULL, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL) != 0) + printf("couldn't create 'cpu' node\n"); + + if (sysctl_createv(NULL, 0, NULL, + &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, + &sysctl_node, + CTLFLAG_READWRITE | CTLFLAG_OWNDESC, + CTLTYPE_INT, "target", "CPU speed", sysctl_cpuspeed_temp, + 0, NULL, 0, CTL_MACHDEP, me->sysctl_num, freq->sysctl_num, + CTL_CREATE, CTL_EOL) == 0) { + } else + printf("couldn't create 'target' node\n"); + + if (sysctl_createv(NULL, 0, NULL, + &sysctl_node, + CTLFLAG_READWRITE, + CTLTYPE_INT, "current", NULL, sysctl_cpuspeed_cur, + 1, NULL, 0, CTL_MACHDEP, me->sysctl_num, freq->sysctl_num, + CTL_CREATE, CTL_EOL) == 0) { + } else + printf("couldn't create 'current' node\n"); + + if (sysctl_createv(NULL, 0, NULL, + &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) { + } else + printf("couldn't create 'available' node\n"); +} + +static int +sysctl_cpuspeed_temp(SYSCTLFN_ARGS) +{ + struct sysctlnode node = *rnode; + int speed, nspeed = -1, mhz; + + speed = (scom_read(SCOM_PSR) >> 56) & 3; + if (speed > 1) speed = 1; + mhz = scom_speeds[speed]; + node.sysctl_data = &mhz; + + if (sysctl_lookup(SYSCTLFN_CALL(&node)) == 0) { + int new_reg; + + new_reg = *(int *)node.sysctl_data; + if (new_reg == scom_speeds[0]) { + nspeed = 0; + } else if (new_reg == scom_speeds[1]) { + nspeed = 1; + } else { + printf("%s: new_reg %d\n", __func__, new_reg); + return EINVAL; + } + if (nspeed != speed) { + volatile uint64_t junk; + scom_write(SCOM_PCR, 0x80000000); + scom_write(SCOM_PCR, scom_reg[nspeed]); + junk = scom_read(SCOM_PSR); + __USE(junk); + } + return 0; + } + return EINVAL; +} + +static int +sysctl_cpuspeed_cur(SYSCTLFN_ARGS) +{ + struct sysctlnode node = *rnode; + uint64_t speed; + int mhz; + + speed = (scom_read(SCOM_PSR) >> 56) & 3; + if (speed > 1) speed = 1; + + mhz = scom_speeds[speed]; + node.sysctl_data = &mhz; + return sysctl_lookup(SYSCTLFN_CALL(&node)); +} + +static int +sysctl_cpuspeed_available(SYSCTLFN_ARGS) +{ + struct sysctlnode node = *rnode; + char buf[128]; + + snprintf(buf, 128, "%d %d", scom_speeds[0], scom_speeds[1]); + 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); +}