windfarm_cpufreq_clamp.c 2.4 KB

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