[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>
This commit is contained in:
parent
8279d2e606
commit
e272a28534
2 changed files with 50 additions and 30 deletions
|
@ -504,7 +504,7 @@ config CPU_FREQ_PMAC
|
|||
|
||||
config CPU_FREQ_PMAC64
|
||||
bool "Support for some Apple G5s"
|
||||
depends on CPU_FREQ && PMAC_SMU && PPC64
|
||||
depends on CPU_FREQ && PPC64
|
||||
select CPU_FREQ_TABLE
|
||||
help
|
||||
This adds support for frequency switching on Apple iMac G5,
|
||||
|
|
|
@ -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_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 int g5_fvt_count; /* number of op. points */
|
||||
static int g5_fvt_cur; /* current op. point */
|
||||
|
@ -209,6 +208,16 @@ static int g5_scom_query_freq(void)
|
|||
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
|
||||
*/
|
||||
|
@ -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_PMAC_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_PMAC_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_PMAC_SMU
|
||||
else
|
||||
rc = g5_neo2_cpufreq_init(cpus);
|
||||
#endif /* CONFIG_PMAC_SMU */
|
||||
|
||||
of_node_put(cpus);
|
||||
return rc;
|
||||
|
|
Loading…
Reference in a new issue