Commit e272a285 authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by Paul Mackerras

[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: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 8279d2e6
...@@ -504,7 +504,7 @@ config CPU_FREQ_PMAC ...@@ -504,7 +504,7 @@ config CPU_FREQ_PMAC
config CPU_FREQ_PMAC64 config CPU_FREQ_PMAC64
bool "Support for some Apple G5s" bool "Support for some Apple G5s"
depends on CPU_FREQ && PMAC_SMU && PPC64 depends on CPU_FREQ && PPC64
select CPU_FREQ_TABLE select CPU_FREQ_TABLE
help help
This adds support for frequency switching on Apple iMac G5, This adds support for frequency switching on Apple iMac G5,
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
* that is iMac G5 and latest single CPU desktop. * that is iMac G5 and latest single CPU desktop.
*/ */
#undef DEBUG
#include <linux/module.h> #include <linux/module.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -30,13 +32,7 @@ ...@@ -30,13 +32,7 @@
#include <asm/smu.h> #include <asm/smu.h>
#include <asm/pmac_pfunc.h> #include <asm/pmac_pfunc.h>
#undef DEBUG #define DBG(fmt...) pr_debug(fmt)
#ifdef DEBUG
#define DBG(fmt...) printk(fmt)
#else
#define DBG(fmt...)
#endif
/* see 970FX user manual */ /* see 970FX user manual */
...@@ -82,8 +78,6 @@ static struct freq_attr* g5_cpu_freqs_attr[] = { ...@@ -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 /* Power mode data is an array of the 32 bits PCR values to use for
* the various frequencies, retrieved from the device-tree * the various frequencies, retrieved from the device-tree
*/ */
static u32 *g5_pmode_data;
static int g5_pmode_max;
static int g5_pmode_cur; static int g5_pmode_cur;
static void (*g5_switch_volt)(int speed_mode); static void (*g5_switch_volt)(int speed_mode);
...@@ -93,6 +87,11 @@ static int (*g5_query_freq)(void); ...@@ -93,6 +87,11 @@ static int (*g5_query_freq)(void);
static DEFINE_MUTEX(g5_switch_mutex); static DEFINE_MUTEX(g5_switch_mutex);
#ifdef CONFIG_PMAC_SMU
static u32 *g5_pmode_data;
static int g5_pmode_max;
static struct smu_sdbp_fvt *g5_fvt_table; /* table of op. points */ 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_count; /* number of op. points */
static int g5_fvt_cur; /* current op. point */ static int g5_fvt_cur; /* current op. point */
...@@ -209,6 +208,16 @@ static int g5_scom_query_freq(void) ...@@ -209,6 +208,16 @@ static int g5_scom_query_freq(void)
return i; return i;
} }
/*
* Fake voltage switching for platforms with missing support
*/
static void g5_dummy_switch_volt(int speed_mode)
{
}
#endif /* CONFIG_PMAC_SMU */
/* /*
* Platform function based voltage switching for PowerMac7,2 & 7,3 * Platform function based voltage switching for PowerMac7,2 & 7,3
*/ */
...@@ -248,6 +257,9 @@ static int g5_pfunc_switch_freq(int speed_mode) ...@@ -248,6 +257,9 @@ static int g5_pfunc_switch_freq(int speed_mode)
struct pmf_args args; struct pmf_args args;
u32 done = 0; u32 done = 0;
unsigned long timeout; 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 frequency is going up, first ramp up the voltage */
if (speed_mode < g5_pmode_cur) if (speed_mode < g5_pmode_cur)
...@@ -255,9 +267,12 @@ static int g5_pfunc_switch_freq(int speed_mode) ...@@ -255,9 +267,12 @@ static int g5_pfunc_switch_freq(int speed_mode)
/* Do it */ /* Do it */
if (speed_mode == CPUFREQ_HIGH) if (speed_mode == CPUFREQ_HIGH)
pmf_call_one(pfunc_cpu_setfreq_high, NULL); rc = pmf_call_one(pfunc_cpu_setfreq_high, NULL);
else 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, /* 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 * 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) ...@@ -296,13 +311,6 @@ static int g5_pfunc_query_freq(void)
return val ? CPUFREQ_HIGH : CPUFREQ_LOW; 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 * Common interface to the cpufreq core
...@@ -375,6 +383,8 @@ static struct cpufreq_driver g5_cpufreq_driver = { ...@@ -375,6 +383,8 @@ static struct cpufreq_driver g5_cpufreq_driver = {
}; };
#ifdef CONFIG_PMAC_SMU
static int __init g5_neo2_cpufreq_init(struct device_node *cpus) static int __init g5_neo2_cpufreq_init(struct device_node *cpus)
{ {
struct device_node *cpunode; struct device_node *cpunode;
...@@ -525,6 +535,9 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpus) ...@@ -525,6 +535,9 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpus)
return rc; return rc;
} }
#endif /* CONFIG_PMAC_SMU */
static int __init g5_pm72_cpufreq_init(struct device_node *cpus) static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
{ {
struct device_node *cpuid = NULL, *hwclock = NULL, *cpunode = NULL; struct device_node *cpuid = NULL, *hwclock = NULL, *cpunode = NULL;
...@@ -533,6 +546,9 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus) ...@@ -533,6 +546,9 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
u64 max_freq, min_freq, ih, il; u64 max_freq, min_freq, ih, il;
int has_volt = 1, rc = 0; int has_volt = 1, rc = 0;
DBG("cpufreq: Initializing for PowerMac7,2, PowerMac7,3 and"
" RackMac3,1...\n");
/* Get first CPU node */ /* Get first CPU node */
for (cpunode = NULL; for (cpunode = NULL;
(cpunode = of_get_next_child(cpus, 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) ...@@ -636,6 +652,15 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
*/ */
ih = *((u32 *)(eeprom + 0x10)); ih = *((u32 *)(eeprom + 0x10));
il = *((u32 *)(eeprom + 0x20)); 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; min_freq = 0;
if (ih != 0 && il != 0) if (ih != 0 && il != 0)
min_freq = (max_freq * il) / ih; min_freq = (max_freq * il) / ih;
...@@ -643,7 +668,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus) ...@@ -643,7 +668,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
/* Sanity check */ /* Sanity check */
if (min_freq >= max_freq || min_freq < 1000) { if (min_freq >= max_freq || min_freq < 1000) {
printk(KERN_ERR "cpufreq: Can't calculate low frequency !\n"); printk(KERN_ERR "cpufreq: Can't calculate low frequency !\n");
rc = -ENODEV; rc = -ENXIO;
goto bail; goto bail;
} }
g5_cpu_freqs[0].frequency = max_freq; g5_cpu_freqs[0].frequency = max_freq;
...@@ -690,16 +715,10 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus) ...@@ -690,16 +715,10 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
return rc; return rc;
} }
static int __init g5_rm31_cpufreq_init(struct device_node *cpus)
{
/* NYI */
return 0;
}
static int __init g5_cpufreq_init(void) static int __init g5_cpufreq_init(void)
{ {
struct device_node *cpus; struct device_node *cpus;
int rc; int rc = 0;
cpus = of_find_node_by_path("/cpus"); cpus = of_find_node_by_path("/cpus");
if (cpus == NULL) { if (cpus == NULL) {
...@@ -708,12 +727,13 @@ static int __init g5_cpufreq_init(void) ...@@ -708,12 +727,13 @@ static int __init g5_cpufreq_init(void)
} }
if (machine_is_compatible("PowerMac7,2") || 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); rc = g5_pm72_cpufreq_init(cpus);
else if (machine_is_compatible("RackMac3,1")) #ifdef CONFIG_PMAC_SMU
rc = g5_rm31_cpufreq_init(cpus);
else else
rc = g5_neo2_cpufreq_init(cpus); rc = g5_neo2_cpufreq_init(cpus);
#endif /* CONFIG_PMAC_SMU */
of_node_put(cpus); of_node_put(cpus);
return rc; return rc;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment