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", &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;

Reply via email to