intel_tcc_cooling.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * cooling device driver that activates the processor throttling by
  4. * programming the TCC Offset register.
  5. * Copyright (c) 2021, Intel Corporation.
  6. */
  7. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  8. #include <linux/device.h>
  9. #include <linux/module.h>
  10. #include <linux/thermal.h>
  11. #include <asm/cpu_device_id.h>
  12. #define TCC_SHIFT 24
  13. #define TCC_MASK (0x3fULL<<24)
  14. #define TCC_PROGRAMMABLE BIT(30)
  15. static struct thermal_cooling_device *tcc_cdev;
  16. static int tcc_get_max_state(struct thermal_cooling_device *cdev, unsigned long
  17. *state)
  18. {
  19. *state = TCC_MASK >> TCC_SHIFT;
  20. return 0;
  21. }
  22. static int tcc_offset_update(int tcc)
  23. {
  24. u64 val;
  25. int err;
  26. err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val);
  27. if (err)
  28. return err;
  29. val &= ~TCC_MASK;
  30. val |= tcc << TCC_SHIFT;
  31. err = wrmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, val);
  32. if (err)
  33. return err;
  34. return 0;
  35. }
  36. static int tcc_get_cur_state(struct thermal_cooling_device *cdev, unsigned long
  37. *state)
  38. {
  39. u64 val;
  40. int err;
  41. err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val);
  42. if (err)
  43. return err;
  44. *state = (val & TCC_MASK) >> TCC_SHIFT;
  45. return 0;
  46. }
  47. static int tcc_set_cur_state(struct thermal_cooling_device *cdev, unsigned long
  48. state)
  49. {
  50. return tcc_offset_update(state);
  51. }
  52. static const struct thermal_cooling_device_ops tcc_cooling_ops = {
  53. .get_max_state = tcc_get_max_state,
  54. .get_cur_state = tcc_get_cur_state,
  55. .set_cur_state = tcc_set_cur_state,
  56. };
  57. static const struct x86_cpu_id tcc_ids[] __initconst = {
  58. X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE, NULL),
  59. X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_L, NULL),
  60. X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE, NULL),
  61. X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE_L, NULL),
  62. X86_MATCH_INTEL_FAM6_MODEL(ICELAKE, NULL),
  63. X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_L, NULL),
  64. X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE, NULL),
  65. X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L, NULL),
  66. X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE, NULL),
  67. X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, NULL),
  68. X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, NULL),
  69. X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N, NULL),
  70. X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, NULL),
  71. X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P, NULL),
  72. {}
  73. };
  74. MODULE_DEVICE_TABLE(x86cpu, tcc_ids);
  75. static int __init tcc_cooling_init(void)
  76. {
  77. int ret;
  78. u64 val;
  79. const struct x86_cpu_id *id;
  80. int err;
  81. id = x86_match_cpu(tcc_ids);
  82. if (!id)
  83. return -ENODEV;
  84. err = rdmsrl_safe(MSR_PLATFORM_INFO, &val);
  85. if (err)
  86. return err;
  87. if (!(val & TCC_PROGRAMMABLE))
  88. return -ENODEV;
  89. pr_info("Programmable TCC Offset detected\n");
  90. tcc_cdev =
  91. thermal_cooling_device_register("TCC Offset", NULL,
  92. &tcc_cooling_ops);
  93. if (IS_ERR(tcc_cdev)) {
  94. ret = PTR_ERR(tcc_cdev);
  95. return ret;
  96. }
  97. return 0;
  98. }
  99. module_init(tcc_cooling_init)
  100. static void __exit tcc_cooling_exit(void)
  101. {
  102. thermal_cooling_device_unregister(tcc_cdev);
  103. }
  104. module_exit(tcc_cooling_exit)
  105. MODULE_DESCRIPTION("TCC offset cooling device Driver");
  106. MODULE_AUTHOR("Zhang Rui <[email protected]>");
  107. MODULE_LICENSE("GPL v2");