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 <[email protected]>
+ *
+ * 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 <[email protected]>
+.\"
+.\" 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;