dtpm_devfreq.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright 2021 Linaro Limited
  4. *
  5. * Author: Daniel Lezcano <[email protected]>
  6. *
  7. * The devfreq device combined with the energy model and the load can
  8. * give an estimation of the power consumption as well as limiting the
  9. * power.
  10. *
  11. */
  12. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  13. #include <linux/cpumask.h>
  14. #include <linux/devfreq.h>
  15. #include <linux/dtpm.h>
  16. #include <linux/energy_model.h>
  17. #include <linux/of.h>
  18. #include <linux/pm_qos.h>
  19. #include <linux/slab.h>
  20. #include <linux/units.h>
  21. struct dtpm_devfreq {
  22. struct dtpm dtpm;
  23. struct dev_pm_qos_request qos_req;
  24. struct devfreq *devfreq;
  25. };
  26. static struct dtpm_devfreq *to_dtpm_devfreq(struct dtpm *dtpm)
  27. {
  28. return container_of(dtpm, struct dtpm_devfreq, dtpm);
  29. }
  30. static int update_pd_power_uw(struct dtpm *dtpm)
  31. {
  32. struct dtpm_devfreq *dtpm_devfreq = to_dtpm_devfreq(dtpm);
  33. struct devfreq *devfreq = dtpm_devfreq->devfreq;
  34. struct device *dev = devfreq->dev.parent;
  35. struct em_perf_domain *pd = em_pd_get(dev);
  36. dtpm->power_min = pd->table[0].power;
  37. dtpm->power_max = pd->table[pd->nr_perf_states - 1].power;
  38. return 0;
  39. }
  40. static u64 set_pd_power_limit(struct dtpm *dtpm, u64 power_limit)
  41. {
  42. struct dtpm_devfreq *dtpm_devfreq = to_dtpm_devfreq(dtpm);
  43. struct devfreq *devfreq = dtpm_devfreq->devfreq;
  44. struct device *dev = devfreq->dev.parent;
  45. struct em_perf_domain *pd = em_pd_get(dev);
  46. unsigned long freq;
  47. int i;
  48. for (i = 0; i < pd->nr_perf_states; i++) {
  49. if (pd->table[i].power > power_limit)
  50. break;
  51. }
  52. freq = pd->table[i - 1].frequency;
  53. dev_pm_qos_update_request(&dtpm_devfreq->qos_req, freq);
  54. power_limit = pd->table[i - 1].power;
  55. return power_limit;
  56. }
  57. static void _normalize_load(struct devfreq_dev_status *status)
  58. {
  59. if (status->total_time > 0xfffff) {
  60. status->total_time >>= 10;
  61. status->busy_time >>= 10;
  62. }
  63. status->busy_time <<= 10;
  64. status->busy_time /= status->total_time ? : 1;
  65. status->busy_time = status->busy_time ? : 1;
  66. status->total_time = 1024;
  67. }
  68. static u64 get_pd_power_uw(struct dtpm *dtpm)
  69. {
  70. struct dtpm_devfreq *dtpm_devfreq = to_dtpm_devfreq(dtpm);
  71. struct devfreq *devfreq = dtpm_devfreq->devfreq;
  72. struct device *dev = devfreq->dev.parent;
  73. struct em_perf_domain *pd = em_pd_get(dev);
  74. struct devfreq_dev_status status;
  75. unsigned long freq;
  76. u64 power;
  77. int i;
  78. mutex_lock(&devfreq->lock);
  79. status = devfreq->last_status;
  80. mutex_unlock(&devfreq->lock);
  81. freq = DIV_ROUND_UP(status.current_frequency, HZ_PER_KHZ);
  82. _normalize_load(&status);
  83. for (i = 0; i < pd->nr_perf_states; i++) {
  84. if (pd->table[i].frequency < freq)
  85. continue;
  86. power = pd->table[i].power;
  87. power *= status.busy_time;
  88. power >>= 10;
  89. return power;
  90. }
  91. return 0;
  92. }
  93. static void pd_release(struct dtpm *dtpm)
  94. {
  95. struct dtpm_devfreq *dtpm_devfreq = to_dtpm_devfreq(dtpm);
  96. if (dev_pm_qos_request_active(&dtpm_devfreq->qos_req))
  97. dev_pm_qos_remove_request(&dtpm_devfreq->qos_req);
  98. kfree(dtpm_devfreq);
  99. }
  100. static struct dtpm_ops dtpm_ops = {
  101. .set_power_uw = set_pd_power_limit,
  102. .get_power_uw = get_pd_power_uw,
  103. .update_power_uw = update_pd_power_uw,
  104. .release = pd_release,
  105. };
  106. static int __dtpm_devfreq_setup(struct devfreq *devfreq, struct dtpm *parent)
  107. {
  108. struct device *dev = devfreq->dev.parent;
  109. struct dtpm_devfreq *dtpm_devfreq;
  110. struct em_perf_domain *pd;
  111. int ret = -ENOMEM;
  112. pd = em_pd_get(dev);
  113. if (!pd) {
  114. ret = dev_pm_opp_of_register_em(dev, NULL);
  115. if (ret) {
  116. pr_err("No energy model available for '%s'\n", dev_name(dev));
  117. return -EINVAL;
  118. }
  119. }
  120. dtpm_devfreq = kzalloc(sizeof(*dtpm_devfreq), GFP_KERNEL);
  121. if (!dtpm_devfreq)
  122. return -ENOMEM;
  123. dtpm_init(&dtpm_devfreq->dtpm, &dtpm_ops);
  124. dtpm_devfreq->devfreq = devfreq;
  125. ret = dtpm_register(dev_name(dev), &dtpm_devfreq->dtpm, parent);
  126. if (ret) {
  127. pr_err("Failed to register '%s': %d\n", dev_name(dev), ret);
  128. kfree(dtpm_devfreq);
  129. return ret;
  130. }
  131. ret = dev_pm_qos_add_request(dev, &dtpm_devfreq->qos_req,
  132. DEV_PM_QOS_MAX_FREQUENCY,
  133. PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE);
  134. if (ret) {
  135. pr_err("Failed to add QoS request: %d\n", ret);
  136. goto out_dtpm_unregister;
  137. }
  138. dtpm_update_power(&dtpm_devfreq->dtpm);
  139. return 0;
  140. out_dtpm_unregister:
  141. dtpm_unregister(&dtpm_devfreq->dtpm);
  142. return ret;
  143. }
  144. static int dtpm_devfreq_setup(struct dtpm *dtpm, struct device_node *np)
  145. {
  146. struct devfreq *devfreq;
  147. devfreq = devfreq_get_devfreq_by_node(np);
  148. if (IS_ERR(devfreq))
  149. return 0;
  150. return __dtpm_devfreq_setup(devfreq, dtpm);
  151. }
  152. struct dtpm_subsys_ops dtpm_devfreq_ops = {
  153. .name = KBUILD_MODNAME,
  154. .setup = dtpm_devfreq_setup,
  155. };