Skip to content

Commit

Permalink
[POWERPC] Add cpufreq support for Xserve G5
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Benjamin Herrenschmidt authored and Paul Mackerras committed Jul 7, 2006
1 parent 861fa77 commit 7ed14c2
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 30 deletions.
2 changes: 1 addition & 1 deletion arch/powerpc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
78 changes: 49 additions & 29 deletions arch/powerpc/platforms/powermac/cpufreq_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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 */

Expand Down Expand Up @@ -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);
Expand All @@ -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 */
Expand Down Expand Up @@ -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_PPC_SMU */

/*
* Platform function based voltage switching for PowerMac7,2 & 7,3
*/
Expand Down Expand Up @@ -248,16 +257,22 @@ 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)
g5_switch_volt(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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;) {
Expand Down Expand Up @@ -636,14 +652,23 @@ 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;

/* 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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
Expand Down

0 comments on commit 7ed14c2

Please sign in to comment.