panfrost_devfreq.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Copyright 2019 Collabora ltd. */
  3. #include <linux/clk.h>
  4. #include <linux/devfreq.h>
  5. #include <linux/devfreq_cooling.h>
  6. #include <linux/platform_device.h>
  7. #include <linux/pm_opp.h>
  8. #include "panfrost_device.h"
  9. #include "panfrost_devfreq.h"
  10. static void panfrost_devfreq_update_utilization(struct panfrost_devfreq *pfdevfreq)
  11. {
  12. ktime_t now, last;
  13. now = ktime_get();
  14. last = pfdevfreq->time_last_update;
  15. if (pfdevfreq->busy_count > 0)
  16. pfdevfreq->busy_time += ktime_sub(now, last);
  17. else
  18. pfdevfreq->idle_time += ktime_sub(now, last);
  19. pfdevfreq->time_last_update = now;
  20. }
  21. static int panfrost_devfreq_target(struct device *dev, unsigned long *freq,
  22. u32 flags)
  23. {
  24. struct dev_pm_opp *opp;
  25. opp = devfreq_recommended_opp(dev, freq, flags);
  26. if (IS_ERR(opp))
  27. return PTR_ERR(opp);
  28. dev_pm_opp_put(opp);
  29. return dev_pm_opp_set_rate(dev, *freq);
  30. }
  31. static void panfrost_devfreq_reset(struct panfrost_devfreq *pfdevfreq)
  32. {
  33. pfdevfreq->busy_time = 0;
  34. pfdevfreq->idle_time = 0;
  35. pfdevfreq->time_last_update = ktime_get();
  36. }
  37. static int panfrost_devfreq_get_dev_status(struct device *dev,
  38. struct devfreq_dev_status *status)
  39. {
  40. struct panfrost_device *pfdev = dev_get_drvdata(dev);
  41. struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq;
  42. unsigned long irqflags;
  43. status->current_frequency = clk_get_rate(pfdev->clock);
  44. spin_lock_irqsave(&pfdevfreq->lock, irqflags);
  45. panfrost_devfreq_update_utilization(pfdevfreq);
  46. status->total_time = ktime_to_ns(ktime_add(pfdevfreq->busy_time,
  47. pfdevfreq->idle_time));
  48. status->busy_time = ktime_to_ns(pfdevfreq->busy_time);
  49. panfrost_devfreq_reset(pfdevfreq);
  50. spin_unlock_irqrestore(&pfdevfreq->lock, irqflags);
  51. dev_dbg(pfdev->dev, "busy %lu total %lu %lu %% freq %lu MHz\n",
  52. status->busy_time, status->total_time,
  53. status->busy_time / (status->total_time / 100),
  54. status->current_frequency / 1000 / 1000);
  55. return 0;
  56. }
  57. static struct devfreq_dev_profile panfrost_devfreq_profile = {
  58. .timer = DEVFREQ_TIMER_DELAYED,
  59. .polling_ms = 50, /* ~3 frames */
  60. .target = panfrost_devfreq_target,
  61. .get_dev_status = panfrost_devfreq_get_dev_status,
  62. };
  63. int panfrost_devfreq_init(struct panfrost_device *pfdev)
  64. {
  65. int ret;
  66. struct dev_pm_opp *opp;
  67. unsigned long cur_freq;
  68. struct device *dev = &pfdev->pdev->dev;
  69. struct devfreq *devfreq;
  70. struct thermal_cooling_device *cooling;
  71. struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq;
  72. if (pfdev->comp->num_supplies > 1) {
  73. /*
  74. * GPUs with more than 1 supply require platform-specific handling:
  75. * continue without devfreq
  76. */
  77. DRM_DEV_INFO(dev, "More than 1 supply is not supported yet\n");
  78. return 0;
  79. }
  80. ret = devm_pm_opp_set_regulators(dev, pfdev->comp->supply_names);
  81. if (ret) {
  82. /* Continue if the optional regulator is missing */
  83. if (ret != -ENODEV) {
  84. if (ret != -EPROBE_DEFER)
  85. DRM_DEV_ERROR(dev, "Couldn't set OPP regulators\n");
  86. return ret;
  87. }
  88. }
  89. ret = devm_pm_opp_of_add_table(dev);
  90. if (ret) {
  91. /* Optional, continue without devfreq */
  92. if (ret == -ENODEV)
  93. ret = 0;
  94. return ret;
  95. }
  96. pfdevfreq->opp_of_table_added = true;
  97. spin_lock_init(&pfdevfreq->lock);
  98. panfrost_devfreq_reset(pfdevfreq);
  99. cur_freq = clk_get_rate(pfdev->clock);
  100. opp = devfreq_recommended_opp(dev, &cur_freq, 0);
  101. if (IS_ERR(opp))
  102. return PTR_ERR(opp);
  103. panfrost_devfreq_profile.initial_freq = cur_freq;
  104. /*
  105. * Set the recommend OPP this will enable and configure the regulator
  106. * if any and will avoid a switch off by regulator_late_cleanup()
  107. */
  108. ret = dev_pm_opp_set_opp(dev, opp);
  109. if (ret) {
  110. DRM_DEV_ERROR(dev, "Couldn't set recommended OPP\n");
  111. return ret;
  112. }
  113. dev_pm_opp_put(opp);
  114. /*
  115. * Setup default thresholds for the simple_ondemand governor.
  116. * The values are chosen based on experiments.
  117. */
  118. pfdevfreq->gov_data.upthreshold = 45;
  119. pfdevfreq->gov_data.downdifferential = 5;
  120. devfreq = devm_devfreq_add_device(dev, &panfrost_devfreq_profile,
  121. DEVFREQ_GOV_SIMPLE_ONDEMAND,
  122. &pfdevfreq->gov_data);
  123. if (IS_ERR(devfreq)) {
  124. DRM_DEV_ERROR(dev, "Couldn't initialize GPU devfreq\n");
  125. return PTR_ERR(devfreq);
  126. }
  127. pfdevfreq->devfreq = devfreq;
  128. cooling = devfreq_cooling_em_register(devfreq, NULL);
  129. if (IS_ERR(cooling))
  130. DRM_DEV_INFO(dev, "Failed to register cooling device\n");
  131. else
  132. pfdevfreq->cooling = cooling;
  133. return 0;
  134. }
  135. void panfrost_devfreq_fini(struct panfrost_device *pfdev)
  136. {
  137. struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq;
  138. if (pfdevfreq->cooling) {
  139. devfreq_cooling_unregister(pfdevfreq->cooling);
  140. pfdevfreq->cooling = NULL;
  141. }
  142. }
  143. void panfrost_devfreq_resume(struct panfrost_device *pfdev)
  144. {
  145. struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq;
  146. if (!pfdevfreq->devfreq)
  147. return;
  148. panfrost_devfreq_reset(pfdevfreq);
  149. devfreq_resume_device(pfdevfreq->devfreq);
  150. }
  151. void panfrost_devfreq_suspend(struct panfrost_device *pfdev)
  152. {
  153. struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq;
  154. if (!pfdevfreq->devfreq)
  155. return;
  156. devfreq_suspend_device(pfdevfreq->devfreq);
  157. }
  158. void panfrost_devfreq_record_busy(struct panfrost_devfreq *pfdevfreq)
  159. {
  160. unsigned long irqflags;
  161. if (!pfdevfreq->devfreq)
  162. return;
  163. spin_lock_irqsave(&pfdevfreq->lock, irqflags);
  164. panfrost_devfreq_update_utilization(pfdevfreq);
  165. pfdevfreq->busy_count++;
  166. spin_unlock_irqrestore(&pfdevfreq->lock, irqflags);
  167. }
  168. void panfrost_devfreq_record_idle(struct panfrost_devfreq *pfdevfreq)
  169. {
  170. unsigned long irqflags;
  171. if (!pfdevfreq->devfreq)
  172. return;
  173. spin_lock_irqsave(&pfdevfreq->lock, irqflags);
  174. panfrost_devfreq_update_utilization(pfdevfreq);
  175. WARN_ON(--pfdevfreq->busy_count < 0);
  176. spin_unlock_irqrestore(&pfdevfreq->lock, irqflags);
  177. }