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