linux/drivers/macintosh/windfarm_cpufreq_clamp.c
Benjamin Herrenschmidt b55fafc5a8 [PATCH] powerpc: Fix old g5 issues with windfarm
Some of the windfarm sensor modules can initialize on old machines that
don't have full windfarm support like non-dual core desktop G5s.
Unfortunately, by doing so, they would trigger a bug in their matching
algorithm causing them to attach to the wrong bus, thus triggering
issues with the i2c core and breaking the thermal driver.

This patch fixes the probing issue (so that they will work when a
windfarm port is done to these machines) and also prevents for now
windfarm to load at all on these machines that still use therm_pm72 to
avoid wasting resources.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
2006-03-03 21:43:53 +11:00

113 lines
2.4 KiB
C

#include <linux/config.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/wait.h>
#include <linux/cpufreq.h>
#include <asm/prom.h>
#include "windfarm.h"
#define VERSION "0.3"
static int clamped;
static struct wf_control *clamp_control;
static int clamp_notifier_call(struct notifier_block *self,
unsigned long event, void *data)
{
struct cpufreq_policy *p = data;
unsigned long max_freq;
if (event != CPUFREQ_ADJUST)
return 0;
max_freq = clamped ? (p->cpuinfo.min_freq) : (p->cpuinfo.max_freq);
cpufreq_verify_within_limits(p, 0, max_freq);
return 0;
}
static struct notifier_block clamp_notifier = {
.notifier_call = clamp_notifier_call,
};
static int clamp_set(struct wf_control *ct, s32 value)
{
if (value)
printk(KERN_INFO "windfarm: Clamping CPU frequency to "
"minimum !\n");
else
printk(KERN_INFO "windfarm: CPU frequency unclamped !\n");
clamped = value;
cpufreq_update_policy(0);
return 0;
}
static int clamp_get(struct wf_control *ct, s32 *value)
{
*value = clamped;
return 0;
}
static s32 clamp_min(struct wf_control *ct)
{
return 0;
}
static s32 clamp_max(struct wf_control *ct)
{
return 1;
}
static struct wf_control_ops clamp_ops = {
.set_value = clamp_set,
.get_value = clamp_get,
.get_min = clamp_min,
.get_max = clamp_max,
.owner = THIS_MODULE,
};
static int __init wf_cpufreq_clamp_init(void)
{
struct wf_control *clamp;
/* Don't register on old machines that use therm_pm72 for now */
if (machine_is_compatible("PowerMac7,2") ||
machine_is_compatible("PowerMac7,3") ||
machine_is_compatible("RackMac3,1"))
return -ENODEV;
clamp = kmalloc(sizeof(struct wf_control), GFP_KERNEL);
if (clamp == NULL)
return -ENOMEM;
cpufreq_register_notifier(&clamp_notifier, CPUFREQ_POLICY_NOTIFIER);
clamp->ops = &clamp_ops;
clamp->name = "cpufreq-clamp";
if (wf_register_control(clamp))
goto fail;
clamp_control = clamp;
return 0;
fail:
kfree(clamp);
return -ENODEV;
}
static void __exit wf_cpufreq_clamp_exit(void)
{
if (clamp_control)
wf_unregister_control(clamp_control);
}
module_init(wf_cpufreq_clamp_init);
module_exit(wf_cpufreq_clamp_exit);
MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
MODULE_DESCRIPTION("CPU frequency clamp for PowerMacs thermal control");
MODULE_LICENSE("GPL");