113 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			113 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #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");
 | |
| 
 |