1 #include <linux/config.h> 2 #include <linux/types.h> 3 #include <linux/errno.h> 4 #include <linux/kernel.h> 5 #include <linux/delay.h> 6 #include <linux/slab.h> 7 #include <linux/init.h> 8 #include <linux/wait.h> 9 #include <linux/cpufreq.h> 10 11 #include <asm/prom.h> 12 13 #include "windfarm.h" 14 15 #define VERSION "0.3" 16 17 static int clamped; 18 static struct wf_control *clamp_control; 19 20 static int clamp_notifier_call(struct notifier_block *self, 21 unsigned long event, void *data) 22 { 23 struct cpufreq_policy *p = data; 24 unsigned long max_freq; 25 26 if (event != CPUFREQ_ADJUST) 27 return 0; 28 29 max_freq = clamped ? (p->cpuinfo.min_freq) : (p->cpuinfo.max_freq); 30 cpufreq_verify_within_limits(p, 0, max_freq); 31 32 return 0; 33 } 34 35 static struct notifier_block clamp_notifier = { 36 .notifier_call = clamp_notifier_call, 37 }; 38 39 static int clamp_set(struct wf_control *ct, s32 value) 40 { 41 if (value) 42 printk(KERN_INFO "windfarm: Clamping CPU frequency to " 43 "minimum !\n"); 44 else 45 printk(KERN_INFO "windfarm: CPU frequency unclamped !\n"); 46 clamped = value; 47 cpufreq_update_policy(0); 48 return 0; 49 } 50 51 static int clamp_get(struct wf_control *ct, s32 *value) 52 { 53 *value = clamped; 54 return 0; 55 } 56 57 static s32 clamp_min(struct wf_control *ct) 58 { 59 return 0; 60 } 61 62 static s32 clamp_max(struct wf_control *ct) 63 { 64 return 1; 65 } 66 67 static struct wf_control_ops clamp_ops = { 68 .set_value = clamp_set, 69 .get_value = clamp_get, 70 .get_min = clamp_min, 71 .get_max = clamp_max, 72 .owner = THIS_MODULE, 73 }; 74 75 static int __init wf_cpufreq_clamp_init(void) 76 { 77 struct wf_control *clamp; 78 79 /* Don't register on old machines that use therm_pm72 for now */ 80 if (machine_is_compatible("PowerMac7,2") || 81 machine_is_compatible("PowerMac7,3") || 82 machine_is_compatible("RackMac3,1")) 83 return -ENODEV; 84 85 clamp = kmalloc(sizeof(struct wf_control), GFP_KERNEL); 86 if (clamp == NULL) 87 return -ENOMEM; 88 cpufreq_register_notifier(&clamp_notifier, CPUFREQ_POLICY_NOTIFIER); 89 clamp->ops = &clamp_ops; 90 clamp->name = "cpufreq-clamp"; 91 if (wf_register_control(clamp)) 92 goto fail; 93 clamp_control = clamp; 94 return 0; 95 fail: 96 kfree(clamp); 97 return -ENODEV; 98 } 99 100 static void __exit wf_cpufreq_clamp_exit(void) 101 { 102 if (clamp_control) 103 wf_unregister_control(clamp_control); 104 } 105 106 107 module_init(wf_cpufreq_clamp_init); 108 module_exit(wf_cpufreq_clamp_exit); 109 110 MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>"); 111 MODULE_DESCRIPTION("CPU frequency clamp for PowerMacs thermal control"); 112 MODULE_LICENSE("GPL"); 113 114