On 26/04/11(Tue) 18:29, Martin Pieuchot wrote:
> 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.

Updated diff, correct the voltage offset in case the value of the reg
property is relative to the gpio controller offset.


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   27 Apr 2011 07:06:17 -0000
@@ -0,0 +1,160 @@
+/*     $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;
+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, 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])
+               voltage = reg + ca->ca_reg[0];
+       else
+               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        27 Apr 2011 07:06:17 -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: 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   27 Apr 2011 07:06:17 -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: 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       27 Apr 2011 07:06:17 -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: 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        27 Apr 2011 07:06:17 -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