diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2006-07-06 15:09:19 +1000 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-07-07 20:19:16 +1000 |
commit | 7ed14c2177694ce086180eb9ca9ca4c6cd72c7ef (patch) | |
tree | 3ae86ab89905167c8fdc9f220524d4d693895108 /arch/powerpc/platforms/powermac/cpufreq_64.c | |
parent | 861fa7737db889ae1701ba58c083d4a7bd8705d3 (diff) | |
download | blackbird-op-linux-7ed14c2177694ce086180eb9ca9ca4c6cd72c7ef.tar.gz blackbird-op-linux-7ed14c2177694ce086180eb9ca9ca4c6cd72c7ef.zip |
[POWERPC] Add cpufreq support for Xserve G5
The Xserve G5 are capable of frequency switching like other desktop G5s.
This enables it. It also fix a Kconfig issue which prevented from
building the G5 cpufreq support if CONFIG_PMAC_SMU was not set (the
first version of that driver only worked with SMU based macs, but this
isn't the case anymore).
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms/powermac/cpufreq_64.c')
-rw-r--r-- | arch/powerpc/platforms/powermac/cpufreq_64.c | 78 |
1 files changed, 49 insertions, 29 deletions
diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c index f08a14516139..a6a84ac5433e 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_64.c +++ b/arch/powerpc/platforms/powermac/cpufreq_64.c @@ -10,6 +10,8 @@ * that is iMac G5 and latest single CPU desktop. */ +#undef DEBUG + #include <linux/module.h> #include <linux/types.h> #include <linux/errno.h> @@ -30,13 +32,7 @@ #include <asm/smu.h> #include <asm/pmac_pfunc.h> -#undef DEBUG - -#ifdef DEBUG -#define DBG(fmt...) printk(fmt) -#else -#define DBG(fmt...) -#endif +#define DBG(fmt...) pr_debug(fmt) /* see 970FX user manual */ @@ -82,8 +78,6 @@ static struct freq_attr* g5_cpu_freqs_attr[] = { /* Power mode data is an array of the 32 bits PCR values to use for * the various frequencies, retrieved from the device-tree */ -static u32 *g5_pmode_data; -static int g5_pmode_max; static int g5_pmode_cur; static void (*g5_switch_volt)(int speed_mode); @@ -93,6 +87,11 @@ static int (*g5_query_freq)(void); static DEFINE_MUTEX(g5_switch_mutex); +#ifdef CONFIG_PPC_SMU + +static u32 *g5_pmode_data; +static int g5_pmode_max; + static struct smu_sdbp_fvt *g5_fvt_table; /* table of op. points */ static int g5_fvt_count; /* number of op. points */ static int g5_fvt_cur; /* current op. point */ @@ -210,6 +209,16 @@ static int g5_scom_query_freq(void) } /* + * Fake voltage switching for platforms with missing support + */ + +static void g5_dummy_switch_volt(int speed_mode) +{ +} + +#endif /* CONFIG_PPC_SMU */ + +/* * Platform function based voltage switching for PowerMac7,2 & 7,3 */ @@ -248,6 +257,9 @@ static int g5_pfunc_switch_freq(int speed_mode) struct pmf_args args; u32 done = 0; unsigned long timeout; + int rc; + + DBG("g5_pfunc_switch_freq(%d)\n", speed_mode); /* If frequency is going up, first ramp up the voltage */ if (speed_mode < g5_pmode_cur) @@ -255,9 +267,12 @@ static int g5_pfunc_switch_freq(int speed_mode) /* Do it */ if (speed_mode == CPUFREQ_HIGH) - pmf_call_one(pfunc_cpu_setfreq_high, NULL); + rc = pmf_call_one(pfunc_cpu_setfreq_high, NULL); else - pmf_call_one(pfunc_cpu_setfreq_low, NULL); + rc = pmf_call_one(pfunc_cpu_setfreq_low, NULL); + + if (rc) + printk(KERN_WARNING "cpufreq: pfunc switch error %d\n", rc); /* It's an irq GPIO so we should be able to just block here, * I'll do that later after I've properly tested the IRQ code for @@ -296,13 +311,6 @@ static int g5_pfunc_query_freq(void) return val ? CPUFREQ_HIGH : CPUFREQ_LOW; } -/* - * Fake voltage switching for platforms with missing support - */ - -static void g5_dummy_switch_volt(int speed_mode) -{ -} /* * Common interface to the cpufreq core @@ -375,6 +383,8 @@ static struct cpufreq_driver g5_cpufreq_driver = { }; +#ifdef CONFIG_PPC_SMU + static int __init g5_neo2_cpufreq_init(struct device_node *cpus) { struct device_node *cpunode; @@ -525,6 +535,9 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpus) return rc; } +#endif /* CONFIG_PPC_SMU */ + + static int __init g5_pm72_cpufreq_init(struct device_node *cpus) { struct device_node *cpuid = NULL, *hwclock = NULL, *cpunode = NULL; @@ -533,6 +546,9 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus) u64 max_freq, min_freq, ih, il; int has_volt = 1, rc = 0; + DBG("cpufreq: Initializing for PowerMac7,2, PowerMac7,3 and" + " RackMac3,1...\n"); + /* Get first CPU node */ for (cpunode = NULL; (cpunode = of_get_next_child(cpus, cpunode)) != NULL;) { @@ -636,6 +652,15 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus) */ ih = *((u32 *)(eeprom + 0x10)); il = *((u32 *)(eeprom + 0x20)); + + /* Check for machines with no useful settings */ + if (il == ih) { + printk(KERN_WARNING "cpufreq: No low frequency mode available" + " on this model !\n"); + rc = -ENODEV; + goto bail; + } + min_freq = 0; if (ih != 0 && il != 0) min_freq = (max_freq * il) / ih; @@ -643,7 +668,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus) /* Sanity check */ if (min_freq >= max_freq || min_freq < 1000) { printk(KERN_ERR "cpufreq: Can't calculate low frequency !\n"); - rc = -ENODEV; + rc = -ENXIO; goto bail; } g5_cpu_freqs[0].frequency = max_freq; @@ -690,16 +715,10 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus) return rc; } -static int __init g5_rm31_cpufreq_init(struct device_node *cpus) -{ - /* NYI */ - return 0; -} - static int __init g5_cpufreq_init(void) { struct device_node *cpus; - int rc; + int rc = 0; cpus = of_find_node_by_path("/cpus"); if (cpus == NULL) { @@ -708,12 +727,13 @@ static int __init g5_cpufreq_init(void) } if (machine_is_compatible("PowerMac7,2") || - machine_is_compatible("PowerMac7,3")) + machine_is_compatible("PowerMac7,3") || + machine_is_compatible("RackMac3,1")) rc = g5_pm72_cpufreq_init(cpus); - else if (machine_is_compatible("RackMac3,1")) - rc = g5_rm31_cpufreq_init(cpus); +#ifdef CONFIG_PPC_SMU else rc = g5_neo2_cpufreq_init(cpus); +#endif /* CONFIG_PPC_SMU */ of_node_put(cpus); return rc; |