dpu_power_handle.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. */
  13. #define pr_fmt(fmt) "[drm:%s:%d]: " fmt, __func__, __LINE__
  14. #include <linux/kernel.h>
  15. #include <linux/of.h>
  16. #include <linux/string.h>
  17. #include <linux/of_address.h>
  18. #include <linux/slab.h>
  19. #include <linux/mutex.h>
  20. #include <linux/of_platform.h>
  21. #include "dpu_power_handle.h"
  22. #include "dpu_trace.h"
  23. static const char *data_bus_name[DPU_POWER_HANDLE_DBUS_ID_MAX] = {
  24. [DPU_POWER_HANDLE_DBUS_ID_MNOC] = "qcom,dpu-data-bus",
  25. [DPU_POWER_HANDLE_DBUS_ID_LLCC] = "qcom,dpu-llcc-bus",
  26. [DPU_POWER_HANDLE_DBUS_ID_EBI] = "qcom,dpu-ebi-bus",
  27. };
  28. const char *dpu_power_handle_get_dbus_name(u32 bus_id)
  29. {
  30. if (bus_id < DPU_POWER_HANDLE_DBUS_ID_MAX)
  31. return data_bus_name[bus_id];
  32. return NULL;
  33. }
  34. static void dpu_power_event_trigger_locked(struct dpu_power_handle *phandle,
  35. u32 event_type)
  36. {
  37. struct dpu_power_event *event;
  38. list_for_each_entry(event, &phandle->event_list, list) {
  39. if (event->event_type & event_type)
  40. event->cb_fnc(event_type, event->usr);
  41. }
  42. }
  43. struct dpu_power_client *dpu_power_client_create(
  44. struct dpu_power_handle *phandle, char *client_name)
  45. {
  46. struct dpu_power_client *client;
  47. static u32 id;
  48. if (!client_name || !phandle) {
  49. pr_err("client name is null or invalid power data\n");
  50. return ERR_PTR(-EINVAL);
  51. }
  52. client = kzalloc(sizeof(struct dpu_power_client), GFP_KERNEL);
  53. if (!client)
  54. return ERR_PTR(-ENOMEM);
  55. mutex_lock(&phandle->phandle_lock);
  56. strlcpy(client->name, client_name, MAX_CLIENT_NAME_LEN);
  57. client->usecase_ndx = VOTE_INDEX_DISABLE;
  58. client->id = id;
  59. client->active = true;
  60. pr_debug("client %s created:%pK id :%d\n", client_name,
  61. client, id);
  62. id++;
  63. list_add(&client->list, &phandle->power_client_clist);
  64. mutex_unlock(&phandle->phandle_lock);
  65. return client;
  66. }
  67. void dpu_power_client_destroy(struct dpu_power_handle *phandle,
  68. struct dpu_power_client *client)
  69. {
  70. if (!client || !phandle) {
  71. pr_err("reg bus vote: invalid client handle\n");
  72. } else if (!client->active) {
  73. pr_err("dpu power deinit already done\n");
  74. kfree(client);
  75. } else {
  76. pr_debug("bus vote client %s destroyed:%pK id:%u\n",
  77. client->name, client, client->id);
  78. mutex_lock(&phandle->phandle_lock);
  79. list_del_init(&client->list);
  80. mutex_unlock(&phandle->phandle_lock);
  81. kfree(client);
  82. }
  83. }
  84. void dpu_power_resource_init(struct platform_device *pdev,
  85. struct dpu_power_handle *phandle)
  86. {
  87. phandle->dev = &pdev->dev;
  88. INIT_LIST_HEAD(&phandle->power_client_clist);
  89. INIT_LIST_HEAD(&phandle->event_list);
  90. mutex_init(&phandle->phandle_lock);
  91. }
  92. void dpu_power_resource_deinit(struct platform_device *pdev,
  93. struct dpu_power_handle *phandle)
  94. {
  95. struct dpu_power_client *curr_client, *next_client;
  96. struct dpu_power_event *curr_event, *next_event;
  97. if (!phandle || !pdev) {
  98. pr_err("invalid input param\n");
  99. return;
  100. }
  101. mutex_lock(&phandle->phandle_lock);
  102. list_for_each_entry_safe(curr_client, next_client,
  103. &phandle->power_client_clist, list) {
  104. pr_err("client:%s-%d still registered with refcount:%d\n",
  105. curr_client->name, curr_client->id,
  106. curr_client->refcount);
  107. curr_client->active = false;
  108. list_del(&curr_client->list);
  109. }
  110. list_for_each_entry_safe(curr_event, next_event,
  111. &phandle->event_list, list) {
  112. pr_err("event:%d, client:%s still registered\n",
  113. curr_event->event_type,
  114. curr_event->client_name);
  115. curr_event->active = false;
  116. list_del(&curr_event->list);
  117. }
  118. mutex_unlock(&phandle->phandle_lock);
  119. }
  120. int dpu_power_resource_enable(struct dpu_power_handle *phandle,
  121. struct dpu_power_client *pclient, bool enable)
  122. {
  123. bool changed = false;
  124. u32 max_usecase_ndx = VOTE_INDEX_DISABLE, prev_usecase_ndx;
  125. struct dpu_power_client *client;
  126. u32 event_type;
  127. if (!phandle || !pclient) {
  128. pr_err("invalid input argument\n");
  129. return -EINVAL;
  130. }
  131. mutex_lock(&phandle->phandle_lock);
  132. if (enable)
  133. pclient->refcount++;
  134. else if (pclient->refcount)
  135. pclient->refcount--;
  136. if (pclient->refcount)
  137. pclient->usecase_ndx = VOTE_INDEX_LOW;
  138. else
  139. pclient->usecase_ndx = VOTE_INDEX_DISABLE;
  140. list_for_each_entry(client, &phandle->power_client_clist, list) {
  141. if (client->usecase_ndx < VOTE_INDEX_MAX &&
  142. client->usecase_ndx > max_usecase_ndx)
  143. max_usecase_ndx = client->usecase_ndx;
  144. }
  145. if (phandle->current_usecase_ndx != max_usecase_ndx) {
  146. changed = true;
  147. prev_usecase_ndx = phandle->current_usecase_ndx;
  148. phandle->current_usecase_ndx = max_usecase_ndx;
  149. }
  150. pr_debug("%pS: changed=%d current idx=%d request client %s id:%u enable:%d refcount:%d\n",
  151. __builtin_return_address(0), changed, max_usecase_ndx,
  152. pclient->name, pclient->id, enable, pclient->refcount);
  153. if (!changed)
  154. goto end;
  155. event_type = enable ? DPU_POWER_EVENT_ENABLE : DPU_POWER_EVENT_DISABLE;
  156. dpu_power_event_trigger_locked(phandle, event_type);
  157. end:
  158. mutex_unlock(&phandle->phandle_lock);
  159. return 0;
  160. }
  161. struct dpu_power_event *dpu_power_handle_register_event(
  162. struct dpu_power_handle *phandle,
  163. u32 event_type, void (*cb_fnc)(u32 event_type, void *usr),
  164. void *usr, char *client_name)
  165. {
  166. struct dpu_power_event *event;
  167. if (!phandle) {
  168. pr_err("invalid power handle\n");
  169. return ERR_PTR(-EINVAL);
  170. } else if (!cb_fnc || !event_type) {
  171. pr_err("no callback fnc or event type\n");
  172. return ERR_PTR(-EINVAL);
  173. }
  174. event = kzalloc(sizeof(struct dpu_power_event), GFP_KERNEL);
  175. if (!event)
  176. return ERR_PTR(-ENOMEM);
  177. event->event_type = event_type;
  178. event->cb_fnc = cb_fnc;
  179. event->usr = usr;
  180. strlcpy(event->client_name, client_name, MAX_CLIENT_NAME_LEN);
  181. event->active = true;
  182. mutex_lock(&phandle->phandle_lock);
  183. list_add(&event->list, &phandle->event_list);
  184. mutex_unlock(&phandle->phandle_lock);
  185. return event;
  186. }
  187. void dpu_power_handle_unregister_event(
  188. struct dpu_power_handle *phandle,
  189. struct dpu_power_event *event)
  190. {
  191. if (!phandle || !event) {
  192. pr_err("invalid phandle or event\n");
  193. } else if (!event->active) {
  194. pr_err("power handle deinit already done\n");
  195. kfree(event);
  196. } else {
  197. mutex_lock(&phandle->phandle_lock);
  198. list_del_init(&event->list);
  199. mutex_unlock(&phandle->phandle_lock);
  200. kfree(event);
  201. }
  202. }