windfarm_cpufreq_clamp.c 2.4 KB

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