power_domain.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. // SPDX-License-Identifier: BSD-3-Clause
  2. /*
  3. * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved.
  4. * Copyright (c) 2019-2020, Linaro Limited
  5. */
  6. #include <cdefs.h>
  7. #include <string.h>
  8. #include <drivers/scmi-msg.h>
  9. #include <drivers/scmi.h>
  10. #include <lib/utils_def.h>
  11. #include "common.h"
  12. #pragma weak plat_scmi_pd_count
  13. #pragma weak plat_scmi_pd_get_name
  14. #pragma weak plat_scmi_pd_get_state
  15. #pragma weak plat_scmi_pd_set_state
  16. #pragma weak plat_scmi_pd_statistics
  17. #pragma weak plat_scmi_pd_get_attributes
  18. static bool message_id_is_supported(unsigned int message_id);
  19. size_t plat_scmi_pd_count(unsigned int agent_id __unused)
  20. {
  21. return 0U;
  22. }
  23. const char *plat_scmi_pd_get_name(unsigned int agent_id __unused,
  24. unsigned int pd_id __unused)
  25. {
  26. return NULL;
  27. }
  28. unsigned int plat_scmi_pd_statistics(unsigned int agent_id __unused,
  29. unsigned long *pd_id __unused)
  30. {
  31. return 0U;
  32. }
  33. unsigned int plat_scmi_pd_get_attributes(unsigned int agent_id __unused,
  34. unsigned int pd_id __unused)
  35. {
  36. return 0U;
  37. }
  38. unsigned int plat_scmi_pd_get_state(unsigned int agent_id __unused,
  39. unsigned int pd_id __unused)
  40. {
  41. return 0U;
  42. }
  43. int32_t plat_scmi_pd_set_state(unsigned int agent_id __unused,
  44. unsigned int flags __unused,
  45. unsigned int pd_id __unused,
  46. unsigned int state __unused)
  47. {
  48. return SCMI_NOT_SUPPORTED;
  49. }
  50. static void report_version(struct scmi_msg *msg)
  51. {
  52. struct scmi_protocol_version_p2a return_values = {
  53. .status = SCMI_SUCCESS,
  54. .version = SCMI_PROTOCOL_VERSION_PD,
  55. };
  56. if (msg->in_size != 0) {
  57. scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
  58. return;
  59. }
  60. scmi_write_response(msg, &return_values, sizeof(return_values));
  61. }
  62. static void report_attributes(struct scmi_msg *msg)
  63. {
  64. unsigned long addr = 0UL;
  65. unsigned int len;
  66. struct scmi_protocol_attributes_p2a_pd return_values = {
  67. .status = SCMI_SUCCESS,
  68. };
  69. if (msg->in_size != 0) {
  70. scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
  71. return;
  72. }
  73. return_values.attributes = plat_scmi_pd_count(msg->agent_id);
  74. len = plat_scmi_pd_statistics(msg->agent_id, &addr);
  75. if (len != 0U) {
  76. return_values.statistics_addr_low = (unsigned int)addr;
  77. return_values.statistics_addr_high = (uint32_t)(addr >> 32);
  78. return_values.statistics_len = len;
  79. }
  80. scmi_write_response(msg, &return_values, sizeof(return_values));
  81. }
  82. static void report_message_attributes(struct scmi_msg *msg)
  83. {
  84. struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in;
  85. struct scmi_protocol_message_attributes_p2a return_values = {
  86. .status = SCMI_SUCCESS,
  87. /* For this protocol, attributes shall be zero */
  88. .attributes = 0U,
  89. };
  90. if (msg->in_size != sizeof(*in_args)) {
  91. scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
  92. return;
  93. }
  94. if (!message_id_is_supported(in_args->message_id)) {
  95. scmi_status_response(msg, SCMI_NOT_FOUND);
  96. return;
  97. }
  98. scmi_write_response(msg, &return_values, sizeof(return_values));
  99. }
  100. static void scmi_pd_attributes(struct scmi_msg *msg)
  101. {
  102. const struct scmi_pd_attributes_a2p *in_args = (void *)msg->in;
  103. struct scmi_pd_attributes_p2a return_values = {
  104. .status = SCMI_SUCCESS,
  105. };
  106. const char *name = NULL;
  107. unsigned int pd_id = 0U;
  108. if (msg->in_size != sizeof(*in_args)) {
  109. scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
  110. return;
  111. }
  112. pd_id = SPECULATION_SAFE_VALUE(in_args->pd_id);
  113. if (pd_id >= plat_scmi_pd_count(msg->agent_id)) {
  114. scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
  115. return;
  116. }
  117. name = plat_scmi_pd_get_name(msg->agent_id, pd_id);
  118. if (name == NULL) {
  119. scmi_status_response(msg, SCMI_NOT_FOUND);
  120. return;
  121. }
  122. COPY_NAME_IDENTIFIER(return_values.pd_name, name);
  123. return_values.attributes = plat_scmi_pd_get_attributes(msg->agent_id, pd_id);
  124. scmi_write_response(msg, &return_values, sizeof(return_values));
  125. }
  126. static void scmi_pd_state_get(struct scmi_msg *msg)
  127. {
  128. const struct scmi_pd_state_get_a2p *in_args = (void *)msg->in;
  129. unsigned int state = 0U;
  130. struct scmi_pd_state_get_p2a return_values = {
  131. .status = SCMI_SUCCESS,
  132. };
  133. unsigned int pd_id = 0U;
  134. if (msg->in_size != sizeof(*in_args)) {
  135. scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
  136. return;
  137. }
  138. pd_id = SPECULATION_SAFE_VALUE(in_args->pd_id);
  139. if (pd_id >= plat_scmi_pd_count(msg->agent_id)) {
  140. scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
  141. return;
  142. }
  143. state = plat_scmi_pd_get_state(msg->agent_id, pd_id);
  144. return_values.power_state = state;
  145. scmi_write_response(msg, &return_values, sizeof(return_values));
  146. }
  147. static void scmi_pd_state_set(struct scmi_msg *msg)
  148. {
  149. const struct scmi_pd_state_set_a2p *in_args = (void *)msg->in;
  150. unsigned int flags = 0U;
  151. int32_t status = 0;
  152. unsigned int pd_id = 0U;
  153. unsigned int state = 0U;
  154. if (msg->in_size != sizeof(*in_args)) {
  155. scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
  156. return;
  157. }
  158. pd_id = SPECULATION_SAFE_VALUE(in_args->pd_id);
  159. if (pd_id >= plat_scmi_pd_count(msg->agent_id)) {
  160. scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
  161. return;
  162. }
  163. flags = SPECULATION_SAFE_VALUE(in_args->flags);
  164. state = SPECULATION_SAFE_VALUE(in_args->power_state);
  165. status = plat_scmi_pd_set_state(msg->agent_id, flags, pd_id, state);
  166. scmi_status_response(msg, status);
  167. }
  168. static const scmi_msg_handler_t scmi_pd_handler_table[] = {
  169. [SCMI_PROTOCOL_VERSION] = report_version,
  170. [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes,
  171. [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes,
  172. [SCMI_PD_ATTRIBUTES] = scmi_pd_attributes,
  173. [SCMI_PD_STATE_SET] = scmi_pd_state_set,
  174. [SCMI_PD_STATE_GET] = scmi_pd_state_get,
  175. };
  176. static bool message_id_is_supported(unsigned int message_id)
  177. {
  178. return (message_id < ARRAY_SIZE(scmi_pd_handler_table)) &&
  179. (scmi_pd_handler_table[message_id] != NULL);
  180. }
  181. scmi_msg_handler_t scmi_msg_get_pd_handler(struct scmi_msg *msg)
  182. {
  183. const size_t array_size = ARRAY_SIZE(scmi_pd_handler_table);
  184. unsigned int message_id = SPECULATION_SAFE_VALUE(msg->message_id);
  185. if (message_id >= array_size) {
  186. VERBOSE("pd handle not found %u", msg->message_id);
  187. return NULL;
  188. }
  189. return scmi_pd_handler_table[message_id];
  190. }