qcom-simple-cluster-lpm.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  4. */
  5. #include <linux/kernel.h>
  6. #include <linux/ktime.h>
  7. #include <linux/module.h>
  8. #include <linux/platform_device.h>
  9. #include <linux/pm_domain.h>
  10. #include <linux/pm_runtime.h>
  11. #include <linux/slab.h>
  12. #include <linux/spinlock.h>
  13. #if defined(_TRACE_HOOK_PM_DOMAIN_H)
  14. #include <trace/hooks/pm_domain.h>
  15. #endif
  16. #define CREATE_TRACE_POINTS
  17. #include "qcom-simple-lpm.h"
  18. LIST_HEAD(cluster_dev_list);
  19. u64 cluster_cur_div = 500;
  20. static struct simple_lpm_cluster *to_cluster(struct generic_pm_domain *genpd)
  21. {
  22. struct simple_lpm_cluster *cluster_simple_gov;
  23. list_for_each_entry(cluster_simple_gov, &cluster_dev_list, list)
  24. if (cluster_simple_gov->genpd == genpd)
  25. return cluster_simple_gov;
  26. return NULL;
  27. }
  28. void update_cluster_select(struct simple_lpm_cpu *cpu_gov)
  29. {
  30. }
  31. #if defined(_TRACE_HOOK_PM_DOMAIN_H)
  32. static void android_vh_allow_domain_state(void *unused,
  33. struct generic_pm_domain *genpd,
  34. uint32_t idx, bool *allow)
  35. {
  36. struct simple_lpm_cluster *cluster_simple_gov = to_cluster(genpd);
  37. if (!cluster_simple_gov)
  38. return;
  39. *allow = cluster_simple_gov->state_allowed[idx];
  40. }
  41. #endif
  42. static int simple_lpm_cluster_simple_gov_remove(struct platform_device *pdev)
  43. {
  44. int i;
  45. struct generic_pm_domain *genpd = pd_to_genpd(pdev->dev.pm_domain);
  46. struct simple_lpm_cluster *cluster_simple_gov = to_cluster(genpd);
  47. if (!cluster_simple_gov)
  48. return -ENODEV;
  49. pm_runtime_disable(&pdev->dev);
  50. cluster_simple_gov->genpd->flags &= ~GENPD_FLAG_MIN_RESIDENCY;
  51. remove_simple_cluster_sysfs_nodes(cluster_simple_gov);
  52. for (i = 0; i < genpd->state_count; i++) {
  53. struct genpd_power_state *states = &genpd->states[i];
  54. states->residency_ns = states->residency_ns * cluster_cur_div;
  55. states->power_on_latency_ns = states->power_on_latency_ns * cluster_cur_div;
  56. states->power_off_latency_ns = states->power_off_latency_ns * cluster_cur_div;
  57. }
  58. list_del(&cluster_simple_gov->list);
  59. return 0;
  60. }
  61. static int simple_lpm_cluster_simple_gov_probe(struct platform_device *pdev)
  62. {
  63. int i, ret;
  64. struct simple_lpm_cluster *cluster_simple_gov;
  65. cluster_simple_gov = devm_kzalloc(&pdev->dev,
  66. sizeof(struct simple_lpm_cluster),
  67. GFP_KERNEL);
  68. if (!cluster_simple_gov)
  69. return -ENOMEM;
  70. spin_lock_init(&cluster_simple_gov->lock);
  71. cluster_simple_gov->dev = &pdev->dev;
  72. pm_runtime_enable(&pdev->dev);
  73. cluster_simple_gov->genpd = pd_to_genpd(cluster_simple_gov->dev->pm_domain);
  74. dev_pm_genpd_set_next_wakeup(cluster_simple_gov->dev, KTIME_MAX - 1);
  75. cluster_simple_gov->genpd->flags |= GENPD_FLAG_MIN_RESIDENCY;
  76. ret = create_simple_cluster_sysfs_nodes(cluster_simple_gov);
  77. if (ret < 0) {
  78. pm_runtime_disable(&pdev->dev);
  79. cluster_simple_gov->genpd->flags &= ~GENPD_FLAG_MIN_RESIDENCY;
  80. return ret;
  81. }
  82. list_add_tail(&cluster_simple_gov->list, &cluster_dev_list);
  83. cluster_simple_gov->initialized = true;
  84. for (i = 0; i < cluster_simple_gov->genpd->state_count; i++) {
  85. struct generic_pm_domain *genpd = cluster_simple_gov->genpd;
  86. struct genpd_power_state *states = &genpd->states[i];
  87. do_div(states->residency_ns, cluster_cur_div);
  88. do_div(states->power_on_latency_ns, cluster_cur_div);
  89. do_div(states->power_off_latency_ns, cluster_cur_div);
  90. cluster_simple_gov->state_allowed[i] = true;
  91. }
  92. return 0;
  93. }
  94. static const struct of_device_id qcom_cluster_simple_lpm[] = {
  95. { .compatible = "qcom,lpm-cluster-dev" },
  96. { }
  97. };
  98. static struct platform_driver qcom_cluster_simple_lpm_driver = {
  99. .probe = simple_lpm_cluster_simple_gov_probe,
  100. .remove = simple_lpm_cluster_simple_gov_remove,
  101. .driver = {
  102. .name = "qcom-simple-gov",
  103. .of_match_table = qcom_cluster_simple_lpm,
  104. .suppress_bind_attrs = true,
  105. },
  106. };
  107. static void cluster_simple_gov_disable(void)
  108. {
  109. #if defined(_TRACE_HOOK_PM_DOMAIN_H)
  110. unregister_trace_android_vh_allow_domain_state(android_vh_allow_domain_state, NULL);
  111. #endif
  112. platform_driver_unregister(&qcom_cluster_simple_lpm_driver);
  113. }
  114. static void cluster_simple_gov_enable(void)
  115. {
  116. #if defined(_TRACE_HOOK_PM_DOMAIN_H)
  117. register_trace_android_vh_allow_domain_state(android_vh_allow_domain_state, NULL);
  118. #endif
  119. platform_driver_register(&qcom_cluster_simple_lpm_driver);
  120. }
  121. struct simple_cluster_governor gov_ops = {
  122. .select = update_cluster_select,
  123. .enable = cluster_simple_gov_enable,
  124. .disable = cluster_simple_gov_disable,
  125. };
  126. void qcom_cluster_lpm_simple_governor_deinit(void)
  127. {
  128. unregister_cluster_simple_governor_ops(&gov_ops);
  129. }
  130. int qcom_cluster_lpm_simple_governor_init(void)
  131. {
  132. register_cluster_simple_governor_ops(&gov_ops);
  133. return 0;
  134. }