On 03/05/11(Tue) 20:37, Miod Vallat wrote: > > Index: dev/dfs.c > > > +static int voltage; > > There is no reason for this variable to be global. You should put it in > your device' softc instead.
Ok, new diff below. > > +int > > +dfs_match(struct device *parent, void *arg, void *aux) > > +{ > > + struct confargs *ca = aux; > > + uint16_t cpu; > > + > > + if (strcmp(ca->ca_name, "cpu-vcore-select") != 0) > > + return (0); > > + > > + cpu = ppc_mfpvr() >> 16; > > Is there any possibility for this device to attach to multiprocessor > machines? If so, what if there are multiple cpu-vcore-select nodes, one > per processor? Oh well, I suppose there won't be multiprocessor systems > with different cpu models... at least not on macppc. I'm not aware of such machine but for what I understand the cpu-vcore-select node shouldn't be per processor. > > + cpu = ppc_mfpvr() >> 16; > > + if (cpu == PPC_CPU_MPC7448) > > + printf(", %d MHz\n", ppc_maxfreq / 4); > > + else > > + printf(" MHz\n"); > > Nitpicking, but I'd rather see the optional /4 freq be printed as ", %d" > and an unconditional " MHz\n" in all cases. See below. > > +void > > +dfs_setperf(int perflevel) > > +{ > > + if (perflevel > 50) { > > + if (ppc_curfreq != ppc_maxfreq) { > > + macobio_write(voltage, GPIO_DDR_OUTPUT | 1); > > + DELAY(1000); > > Speaking of DELAY()... it is implemented using the processor internal > counter register. Is this register impacted by frequency changes? If so, > shouldn't you update the computed ns_per_tick delay() constant? Reading the doc again, it's said that the time base register is clocked at one-fourth of the bus clock. But the DFS feature divides the processor to system bus ratio. So, if I understand well there is no impact on the time base counter frequency. > Also, this register is used to feed the timecounter. Is the clock still > accurate after running for a while at a lower frequency? Is there any > other, fixed, clock source which can be used as a safe monotonic clock > source? I don't know for an other clock source but for the accuracy of the time base register, like I just said if I understand well, there should be no impact. New diff, manpage included with some tweaks by jmc@ . Martin Index: sys/arch/macppc/dev/dfs.c =================================================================== RCS file: sys/arch/macppc/dev/dfs.c diff -N sys/arch/macppc/dev/dfs.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/arch/macppc/dev/dfs.c 4 May 2011 12:40:54 -0000 @@ -0,0 +1,167 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2011 Martin Pieuchot <m...@nolizard.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/filedesc.h> +#include <sys/sysctl.h> + +#include <dev/ofw/openfirm.h> + +#include <machine/cpu.h> +#include <machine/autoconf.h> +#include <macppc/pci/macobio.h> + +#define DFS2 (1 << 22) /* Divide-by-Two */ +#define DFS4 (1 << 23) /* Divide-by-Four (MPC7448 Specific) */ + +extern int perflevel; + +struct dfs_softc { + struct device sc_dev; + int sc_voltage; +}; + +int dfs_match(struct device *, void *, void *); +void dfs_attach(struct device *, struct device *, void *); +void dfs_setperf(int); +void dfs_scale_frequency(u_int); + +struct cfattach dfs_ca = { + sizeof(struct device), dfs_match, dfs_attach +}; + +struct cfdriver dfs_cd = { + NULL, "dfs", DV_DULL +}; + +int +dfs_match(struct device *parent, void *arg, void *aux) +{ + struct confargs *ca = aux; + uint16_t cpu; + + if (strcmp(ca->ca_name, "cpu-vcore-select") != 0) + return (0); + + cpu = ppc_mfpvr() >> 16; + if (cpu == PPC_CPU_MPC7447A || cpu == PPC_CPU_MPC7448) + return (1); + + return (0); +} + +void +dfs_attach(struct device *parent, struct device *self, void *aux) +{ + struct dfs_softc *sc = (struct dfs_softc *)self; + struct confargs *ca = aux; + uint32_t hid1, reg; + uint16_t cpu; + + /* + * On some models the vcore-select offset is relative to + * its parent offset and not to the bus base address. + */ + OF_getprop(OF_parent(ca->ca_node), "reg", ®, sizeof(reg)); + if (reg > ca->ca_reg[0]) + sc->sc_voltage = reg + ca->ca_reg[0]; + else + sc->sc_voltage = ca->ca_reg[0]; + + hid1 = ppc_mfhid1(); + + if (hid1 & DFS4) { + ppc_curfreq = ppc_maxfreq / 4; + perflevel = 25; + } else if (hid1 & DFS2) { + ppc_curfreq = ppc_maxfreq / 2; + perflevel = 50; + } + + cpu_setperf = dfs_setperf; + + printf(": speeds: %d, %d", ppc_maxfreq, ppc_maxfreq / 2); + + cpu = ppc_mfpvr() >> 16; + if (cpu == PPC_CPU_MPC7448) + printf(", %d", ppc_maxfreq / 4); + printf(" MHz\n"); +} + +void +dfs_setperf(int perflevel) +{ + struct dfs_softc *sc = dfs_cd.cd_devs[0]; + + if (perflevel > 50) { + if (ppc_curfreq != ppc_maxfreq) { + macobio_write(sc->sc_voltage, GPIO_DDR_OUTPUT | 1); + delay(1000); + dfs_scale_frequency(FREQ_FULL); + } + } else { + uint16_t cpu; + + cpu = ppc_mfpvr() >> 16; + if (cpu == PPC_CPU_MPC7448 && perflevel <= 25) { + if (ppc_curfreq != ppc_maxfreq / 4) { + dfs_scale_frequency(FREQ_QUARTER); + macobio_write(sc->sc_voltage, + GPIO_DDR_OUTPUT | 0); + delay(1000); + } + } else { + if (ppc_curfreq != ppc_maxfreq / 2) { + dfs_scale_frequency(FREQ_HALF); + macobio_write(sc->sc_voltage, + GPIO_DDR_OUTPUT | 0); + delay(1000); + } + } + } +} + +void +dfs_scale_frequency(u_int freq_scale) +{ + uint32_t hid1; + int s; + + s = splhigh(); + hid1 = ppc_mfhid1(); + + hid1 &= ~(DFS2 | DFS4); + switch (freq_scale) { + case FREQ_QUARTER: + hid1 |= DFS4; + ppc_curfreq = ppc_maxfreq / 4; + break; + case FREQ_HALF: + hid1 |= DFS2; + ppc_curfreq = ppc_maxfreq / 2; + break; + case FREQ_FULL: /* FALLTHROUGH */ + default: + ppc_curfreq = ppc_maxfreq; + } + + asm volatile ("sync"); + ppc_mthid1(hid1); + asm volatile ("sync; isync"); + + splx(s); +} Index: share/man/man4/man4.macppc/dfs.4 =================================================================== RCS file: share/man/man4/man4.macppc/dfs.4 diff -N share/man/man4/man4.macppc/dfs.4 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ share/man/man4/man4.macppc/dfs.4 4 May 2011 12:40:54 -0000 @@ -0,0 +1,53 @@ +.\" $OpenBSD$ +.\" +.\" Copyright (c) 2011 Martin Pieuchot <m...@nolizard.org> +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd $Mdocdate: April 27 2011 $ +.Dt DFS 4 macppc +.Os +.Sh NAME +.Nm dfs +.Nd Dynamic Frequence Switching +.Sh SYNOPSIS +.Cd "dfs* at macgpio?" +.Sh DESCRIPTION +The +.Nm +driver provides support for the Dynamic Frequence Switching +feature found on some PowerPC microprocessors. +.Pp +It conserves power by lowering the processor operating frequency. +Depending on the processor model, the processor-to-system bus ratio can +be divided by two or four. +.Sh HARDWARE +Processors supported by the +.Nm +driver are part of the PowerPC G4 family and are found on various iBook +and PowerBook machines: +.Bd -literal -offset indent +MPC7447A PowerPC 7447 "Apollo 7" +MPC7448 PowerPC 7448 "Apollo 8" +.Ed +.Sh SEE ALSO +.Xr macgpio 4 , +.Xr sysctl 8 , +.Rs +.%T MPC7450 RISC Microprocessor Family Reference Manual +.Re +.Sh HISTORY +Support for the +.Nm +driver first appeared in +.Ox 5.0 . Index: sys/arch/macppc/conf/GENERIC =================================================================== RCS file: /cvs/src/sys/arch/macppc/conf/GENERIC,v retrieving revision 1.207 diff -u -p -r1.207 GENERIC --- sys/arch/macppc/conf/GENERIC 19 Apr 2011 23:07:54 -0000 1.207 +++ sys/arch/macppc/conf/GENERIC 4 May 2011 12:40:54 -0000 @@ -155,6 +155,7 @@ macgpio* at macobio? # GPIO, PMU interru macgpio* at macgpio? # GPIO, PMU interrupt router. sysbutton* at macgpio? # Xserve system id button. pgs* at macgpio? # Programmer Switch. +dfs* at macgpio? # Dynamic Frequence Switching. akbd* at adb? # ADB keyboard wskbd* at akbd? mux 1 ams* at adb? # ADB mouse Index: sys/arch/macppc/conf/files.macppc =================================================================== RCS file: /cvs/src/sys/arch/macppc/conf/files.macppc,v retrieving revision 1.63 diff -u -p -r1.63 files.macppc --- sys/arch/macppc/conf/files.macppc 6 Dec 2010 20:10:18 -0000 1.63 +++ sys/arch/macppc/conf/files.macppc 4 May 2011 12:40:54 -0000 @@ -237,6 +237,10 @@ device pgs {} attach pgs at macgpio file arch/macppc/dev/pgs.c +device dfs {} +attach dfs at macgpio +file arch/macppc/dev/dfs.c + attach wdc at mediabay, macobio, kauaiata with wdc_obio file arch/macppc/dev/wdc_obio.c wdc_obio Index: sys/arch/macppc/include/cpu.h =================================================================== RCS file: /cvs/src/sys/arch/macppc/include/cpu.h,v retrieving revision 1.9 diff -u -p -r1.9 cpu.h --- sys/arch/macppc/include/cpu.h 9 Dec 2005 22:54:15 -0000 1.9 +++ sys/arch/macppc/include/cpu.h 4 May 2011 12:40:54 -0000 @@ -49,7 +49,14 @@ { "altivec", CTLTYPE_INT }, \ } -extern int ppc_altivec; +/* Frequency scaling */ +#define FREQ_FULL 0 +#define FREQ_HALF 1 +#define FREQ_QUARTER 2 /* Not supported on IBM 970FX */ + +extern u_int32_t ppc_curfreq; +extern u_int32_t ppc_maxfreq; +extern int ppc_altivec; extern void (*ppc64_slew_voltage)(u_int); Index: sys/arch/macppc/macppc/cpu.c =================================================================== RCS file: /cvs/src/sys/arch/macppc/macppc/cpu.c,v retrieving revision 1.66 diff -u -p -r1.66 cpu.c --- sys/arch/macppc/macppc/cpu.c 26 Jun 2010 23:24:43 -0000 1.66 +++ sys/arch/macppc/macppc/cpu.c 4 May 2011 12:40:54 -0000 @@ -68,11 +68,6 @@ extern u_int32_t hid0_idle; #define SCOMC_ADDR_MASK 0xffff0000 #define SCOMC_READ 0x00008000 -/* Frequency scaling */ -#define FREQ_FULL 0 -#define FREQ_HALF 1 -#define FREQ_QUARTER 2 /* Not supported on IBM 970FX */ - /* Power (Tuning) Status Register */ #define PSR_CMD_RECEIVED 0x2000000000000000LL #define PSR_CMD_COMPLETED 0x1000000000000000LL @@ -118,8 +113,8 @@ cpumatch(struct device *parent, void *cf return (1); } -static u_int32_t ppc_curfreq; -static u_int32_t ppc_maxfreq; +u_int32_t ppc_curfreq; +u_int32_t ppc_maxfreq; int ppc_altivec;