The following diff adds support for dfs. It requires my precedent patch
about GPIOs. I don't have a machine with a MPC7448 so it's only tested
with a MPC7447A.

I'm also interested in various device-tree dumps for further development.
If you can send me yours, contact me off list.

Comments ?

Index: dev/dfs.c
===================================================================
RCS file: dev/dfs.c
diff -N dev/dfs.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dev/dfs.c   26 Apr 2011 12:13:22 -0000
@@ -0,0 +1,150 @@
+/*     $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 <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;
+static int 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 confargs *ca = aux;
+       uint32_t hid1;
+       uint16_t cpu;
+
+       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(": Dynamic Frequency Switching, speeds: ");
+       printf("%d, %d", ppc_maxfreq, ppc_maxfreq / 2);
+
+       cpu = ppc_mfpvr() >> 16;
+       if (cpu == PPC_CPU_MPC7448)
+               printf(", %d MHz\n", ppc_maxfreq / 4);
+       else
+               printf(" MHz\n");
+}
+
+void
+dfs_setperf(int perflevel)
+{
+       if (perflevel > 50) {
+               if (ppc_curfreq != ppc_maxfreq) {
+                       macobio_write(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(voltage, GPIO_DDR_OUTPUT | 0);
+                               DELAY(1000);
+                       }
+               } else { 
+                       if (ppc_curfreq != ppc_maxfreq / 2) {
+                               dfs_scale_frequency(FREQ_HALF);
+                               macobio_write(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: conf/GENERIC
===================================================================
RCS file: /cvs/src/sys/arch/macppc/conf/GENERIC,v
retrieving revision 1.207
diff -u -p -r1.207 GENERIC
--- conf/GENERIC        19 Apr 2011 23:07:54 -0000      1.207
+++ conf/GENERIC        26 Apr 2011 12:13:22 -0000
@@ -155,6 +156,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: 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
--- conf/files.macppc   6 Dec 2010 20:10:18 -0000       1.63
+++ conf/files.macppc   26 Apr 2011 12:13:22 -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: 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
--- macppc/cpu.c        26 Jun 2010 23:24:43 -0000      1.66
+++ macppc/cpu.c        26 Apr 2011 12:13:22 -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;
 
 
Index: 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
--- include/cpu.h       9 Dec 2005 22:54:15 -0000       1.9
+++ include/cpu.h       26 Apr 2011 12:13:22 -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);

Reply via email to