voltage.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * System Control and Management Interface (SCMI) Voltage Protocol
  4. *
  5. * Copyright (C) 2020 ARM Ltd.
  6. */
  7. #include <linux/scmi_protocol.h>
  8. #include "common.h"
  9. #define VOLTAGE_DOMS_NUM_MASK GENMASK(15, 0)
  10. #define REMAINING_LEVELS_MASK GENMASK(31, 16)
  11. #define RETURNED_LEVELS_MASK GENMASK(11, 0)
  12. enum scmi_voltage_protocol_cmd {
  13. VOLTAGE_DOMAIN_ATTRIBUTES = 0x3,
  14. VOLTAGE_DESCRIBE_LEVELS = 0x4,
  15. VOLTAGE_CONFIG_SET = 0x5,
  16. VOLTAGE_CONFIG_GET = 0x6,
  17. VOLTAGE_LEVEL_SET = 0x7,
  18. VOLTAGE_LEVEL_GET = 0x8,
  19. };
  20. #define NUM_VOLTAGE_DOMAINS(x) ((u16)(FIELD_GET(VOLTAGE_DOMS_NUM_MASK, (x))))
  21. struct scmi_msg_resp_domain_attributes {
  22. __le32 attr;
  23. u8 name[SCMI_MAX_STR_SIZE];
  24. };
  25. struct scmi_msg_cmd_describe_levels {
  26. __le32 domain_id;
  27. __le32 level_index;
  28. };
  29. struct scmi_msg_resp_describe_levels {
  30. __le32 flags;
  31. #define NUM_REMAINING_LEVELS(f) ((u16)(FIELD_GET(REMAINING_LEVELS_MASK, (f))))
  32. #define NUM_RETURNED_LEVELS(f) ((u16)(FIELD_GET(RETURNED_LEVELS_MASK, (f))))
  33. #define SUPPORTS_SEGMENTED_LEVELS(f) ((f) & BIT(12))
  34. __le32 voltage[];
  35. };
  36. struct scmi_msg_cmd_config_set {
  37. __le32 domain_id;
  38. __le32 config;
  39. };
  40. struct scmi_msg_cmd_level_set {
  41. __le32 domain_id;
  42. __le32 flags;
  43. __le32 voltage_level;
  44. };
  45. struct voltage_info {
  46. unsigned int version;
  47. unsigned int num_domains;
  48. struct scmi_voltage_info *domains;
  49. };
  50. static int scmi_protocol_attributes_get(const struct scmi_protocol_handle *ph,
  51. struct voltage_info *vinfo)
  52. {
  53. int ret;
  54. struct scmi_xfer *t;
  55. ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, 0,
  56. sizeof(__le32), &t);
  57. if (ret)
  58. return ret;
  59. ret = ph->xops->do_xfer(ph, t);
  60. if (!ret)
  61. vinfo->num_domains =
  62. NUM_VOLTAGE_DOMAINS(get_unaligned_le32(t->rx.buf));
  63. ph->xops->xfer_put(ph, t);
  64. return ret;
  65. }
  66. static int scmi_init_voltage_levels(struct device *dev,
  67. struct scmi_voltage_info *v,
  68. u32 num_returned, u32 num_remaining,
  69. bool segmented)
  70. {
  71. u32 num_levels;
  72. num_levels = num_returned + num_remaining;
  73. /*
  74. * segmented levels entries are represented by a single triplet
  75. * returned all in one go.
  76. */
  77. if (!num_levels ||
  78. (segmented && (num_remaining || num_returned != 3))) {
  79. dev_err(dev,
  80. "Invalid level descriptor(%d/%d/%d) for voltage dom %d\n",
  81. num_levels, num_returned, num_remaining, v->id);
  82. return -EINVAL;
  83. }
  84. v->levels_uv = devm_kcalloc(dev, num_levels, sizeof(u32), GFP_KERNEL);
  85. if (!v->levels_uv)
  86. return -ENOMEM;
  87. v->num_levels = num_levels;
  88. v->segmented = segmented;
  89. return 0;
  90. }
  91. static int scmi_voltage_descriptors_get(const struct scmi_protocol_handle *ph,
  92. struct voltage_info *vinfo)
  93. {
  94. int ret, dom;
  95. struct scmi_xfer *td, *tl;
  96. struct device *dev = ph->dev;
  97. struct scmi_msg_resp_domain_attributes *resp_dom;
  98. struct scmi_msg_resp_describe_levels *resp_levels;
  99. ret = ph->xops->xfer_get_init(ph, VOLTAGE_DOMAIN_ATTRIBUTES,
  100. sizeof(__le32), sizeof(*resp_dom), &td);
  101. if (ret)
  102. return ret;
  103. resp_dom = td->rx.buf;
  104. ret = ph->xops->xfer_get_init(ph, VOLTAGE_DESCRIBE_LEVELS,
  105. sizeof(__le64), 0, &tl);
  106. if (ret)
  107. goto outd;
  108. resp_levels = tl->rx.buf;
  109. for (dom = 0; dom < vinfo->num_domains; dom++) {
  110. u32 desc_index = 0;
  111. u16 num_returned = 0, num_remaining = 0;
  112. struct scmi_msg_cmd_describe_levels *cmd;
  113. struct scmi_voltage_info *v;
  114. /* Retrieve domain attributes at first ... */
  115. put_unaligned_le32(dom, td->tx.buf);
  116. ret = ph->xops->do_xfer(ph, td);
  117. /* Skip domain on comms error */
  118. if (ret)
  119. continue;
  120. v = vinfo->domains + dom;
  121. v->id = dom;
  122. v->attributes = le32_to_cpu(resp_dom->attr);
  123. strlcpy(v->name, resp_dom->name, SCMI_MAX_STR_SIZE);
  124. cmd = tl->tx.buf;
  125. /* ...then retrieve domain levels descriptions */
  126. do {
  127. u32 flags;
  128. int cnt;
  129. cmd->domain_id = cpu_to_le32(v->id);
  130. cmd->level_index = cpu_to_le32(desc_index);
  131. ret = ph->xops->do_xfer(ph, tl);
  132. if (ret)
  133. break;
  134. flags = le32_to_cpu(resp_levels->flags);
  135. num_returned = NUM_RETURNED_LEVELS(flags);
  136. num_remaining = NUM_REMAINING_LEVELS(flags);
  137. /* Allocate space for num_levels if not already done */
  138. if (!v->num_levels) {
  139. ret = scmi_init_voltage_levels(dev, v,
  140. num_returned,
  141. num_remaining,
  142. SUPPORTS_SEGMENTED_LEVELS(flags));
  143. if (ret)
  144. break;
  145. }
  146. if (desc_index + num_returned > v->num_levels) {
  147. dev_err(ph->dev,
  148. "No. of voltage levels can't exceed %d\n",
  149. v->num_levels);
  150. ret = -EINVAL;
  151. break;
  152. }
  153. for (cnt = 0; cnt < num_returned; cnt++) {
  154. s32 val;
  155. val =
  156. (s32)le32_to_cpu(resp_levels->voltage[cnt]);
  157. v->levels_uv[desc_index + cnt] = val;
  158. if (val < 0)
  159. v->negative_volts_allowed = true;
  160. }
  161. desc_index += num_returned;
  162. ph->xops->reset_rx_to_maxsz(ph, tl);
  163. /* check both to avoid infinite loop due to buggy fw */
  164. } while (num_returned && num_remaining);
  165. if (ret) {
  166. v->num_levels = 0;
  167. devm_kfree(dev, v->levels_uv);
  168. }
  169. ph->xops->reset_rx_to_maxsz(ph, td);
  170. }
  171. ph->xops->xfer_put(ph, tl);
  172. outd:
  173. ph->xops->xfer_put(ph, td);
  174. return ret;
  175. }
  176. static int __scmi_voltage_get_u32(const struct scmi_protocol_handle *ph,
  177. u8 cmd_id, u32 domain_id, u32 *value)
  178. {
  179. int ret;
  180. struct scmi_xfer *t;
  181. struct voltage_info *vinfo = ph->get_priv(ph);
  182. if (domain_id >= vinfo->num_domains)
  183. return -EINVAL;
  184. ret = ph->xops->xfer_get_init(ph, cmd_id, sizeof(__le32), 0, &t);
  185. if (ret)
  186. return ret;
  187. put_unaligned_le32(domain_id, t->tx.buf);
  188. ret = ph->xops->do_xfer(ph, t);
  189. if (!ret)
  190. *value = get_unaligned_le32(t->rx.buf);
  191. ph->xops->xfer_put(ph, t);
  192. return ret;
  193. }
  194. static int scmi_voltage_config_set(const struct scmi_protocol_handle *ph,
  195. u32 domain_id, u32 config)
  196. {
  197. int ret;
  198. struct scmi_xfer *t;
  199. struct voltage_info *vinfo = ph->get_priv(ph);
  200. struct scmi_msg_cmd_config_set *cmd;
  201. if (domain_id >= vinfo->num_domains)
  202. return -EINVAL;
  203. ret = ph->xops->xfer_get_init(ph, VOLTAGE_CONFIG_SET,
  204. sizeof(*cmd), 0, &t);
  205. if (ret)
  206. return ret;
  207. cmd = t->tx.buf;
  208. cmd->domain_id = cpu_to_le32(domain_id);
  209. cmd->config = cpu_to_le32(config & GENMASK(3, 0));
  210. ret = ph->xops->do_xfer(ph, t);
  211. ph->xops->xfer_put(ph, t);
  212. return ret;
  213. }
  214. static int scmi_voltage_config_get(const struct scmi_protocol_handle *ph,
  215. u32 domain_id, u32 *config)
  216. {
  217. return __scmi_voltage_get_u32(ph, VOLTAGE_CONFIG_GET,
  218. domain_id, config);
  219. }
  220. static int scmi_voltage_level_set(const struct scmi_protocol_handle *ph,
  221. u32 domain_id, u32 flags, s32 volt_uV)
  222. {
  223. int ret;
  224. struct scmi_xfer *t;
  225. struct voltage_info *vinfo = ph->get_priv(ph);
  226. struct scmi_msg_cmd_level_set *cmd;
  227. if (domain_id >= vinfo->num_domains)
  228. return -EINVAL;
  229. ret = ph->xops->xfer_get_init(ph, VOLTAGE_LEVEL_SET,
  230. sizeof(*cmd), 0, &t);
  231. if (ret)
  232. return ret;
  233. cmd = t->tx.buf;
  234. cmd->domain_id = cpu_to_le32(domain_id);
  235. cmd->flags = cpu_to_le32(flags);
  236. cmd->voltage_level = cpu_to_le32(volt_uV);
  237. ret = ph->xops->do_xfer(ph, t);
  238. ph->xops->xfer_put(ph, t);
  239. return ret;
  240. }
  241. static int scmi_voltage_level_get(const struct scmi_protocol_handle *ph,
  242. u32 domain_id, s32 *volt_uV)
  243. {
  244. return __scmi_voltage_get_u32(ph, VOLTAGE_LEVEL_GET,
  245. domain_id, (u32 *)volt_uV);
  246. }
  247. static const struct scmi_voltage_info * __must_check
  248. scmi_voltage_info_get(const struct scmi_protocol_handle *ph, u32 domain_id)
  249. {
  250. struct voltage_info *vinfo = ph->get_priv(ph);
  251. if (domain_id >= vinfo->num_domains ||
  252. !vinfo->domains[domain_id].num_levels)
  253. return NULL;
  254. return vinfo->domains + domain_id;
  255. }
  256. static int scmi_voltage_domains_num_get(const struct scmi_protocol_handle *ph)
  257. {
  258. struct voltage_info *vinfo = ph->get_priv(ph);
  259. return vinfo->num_domains;
  260. }
  261. static struct scmi_voltage_proto_ops voltage_proto_ops = {
  262. .num_domains_get = scmi_voltage_domains_num_get,
  263. .info_get = scmi_voltage_info_get,
  264. .config_set = scmi_voltage_config_set,
  265. .config_get = scmi_voltage_config_get,
  266. .level_set = scmi_voltage_level_set,
  267. .level_get = scmi_voltage_level_get,
  268. };
  269. static int scmi_voltage_protocol_init(const struct scmi_protocol_handle *ph)
  270. {
  271. int ret;
  272. u32 version;
  273. struct voltage_info *vinfo;
  274. ret = ph->xops->version_get(ph, &version);
  275. if (ret)
  276. return ret;
  277. dev_dbg(ph->dev, "Voltage Version %d.%d\n",
  278. PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
  279. vinfo = devm_kzalloc(ph->dev, sizeof(*vinfo), GFP_KERNEL);
  280. if (!vinfo)
  281. return -ENOMEM;
  282. vinfo->version = version;
  283. ret = scmi_protocol_attributes_get(ph, vinfo);
  284. if (ret)
  285. return ret;
  286. if (vinfo->num_domains) {
  287. vinfo->domains = devm_kcalloc(ph->dev, vinfo->num_domains,
  288. sizeof(*vinfo->domains),
  289. GFP_KERNEL);
  290. if (!vinfo->domains)
  291. return -ENOMEM;
  292. ret = scmi_voltage_descriptors_get(ph, vinfo);
  293. if (ret)
  294. return ret;
  295. } else {
  296. dev_warn(ph->dev, "No Voltage domains found.\n");
  297. }
  298. return ph->set_priv(ph, vinfo);
  299. }
  300. static const struct scmi_protocol scmi_voltage = {
  301. .id = SCMI_PROTOCOL_VOLTAGE,
  302. .init_instance = &scmi_voltage_protocol_init,
  303. .ops = &voltage_proto_ops,
  304. };
  305. DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(voltage, scmi_voltage)