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);