powercap.c 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * System Control and Management Interface (SCMI) Powercap Protocol
  4. *
  5. * Copyright (C) 2022 ARM Ltd.
  6. */
  7. #define pr_fmt(fmt) "SCMI Notifications POWERCAP - " fmt
  8. #include <linux/bitfield.h>
  9. #include <linux/io.h>
  10. #include <linux/module.h>
  11. #include <linux/scmi_protocol.h>
  12. #include <trace/events/scmi.h>
  13. #include "protocols.h"
  14. #include "notify.h"
  15. /* Updated only after ALL the mandatory features for that version are merged */
  16. #define SCMI_PROTOCOL_SUPPORTED_VERSION 0x20000
  17. enum scmi_powercap_protocol_cmd {
  18. POWERCAP_DOMAIN_ATTRIBUTES = 0x3,
  19. POWERCAP_CAP_GET = 0x4,
  20. POWERCAP_CAP_SET = 0x5,
  21. POWERCAP_PAI_GET = 0x6,
  22. POWERCAP_PAI_SET = 0x7,
  23. POWERCAP_DOMAIN_NAME_GET = 0x8,
  24. POWERCAP_MEASUREMENTS_GET = 0x9,
  25. POWERCAP_CAP_NOTIFY = 0xa,
  26. POWERCAP_MEASUREMENTS_NOTIFY = 0xb,
  27. POWERCAP_DESCRIBE_FASTCHANNEL = 0xc,
  28. };
  29. enum {
  30. POWERCAP_FC_CAP,
  31. POWERCAP_FC_PAI,
  32. POWERCAP_FC_MAX,
  33. };
  34. struct scmi_msg_resp_powercap_domain_attributes {
  35. __le32 attributes;
  36. #define SUPPORTS_POWERCAP_CAP_CHANGE_NOTIFY(x) ((x) & BIT(31))
  37. #define SUPPORTS_POWERCAP_MEASUREMENTS_CHANGE_NOTIFY(x) ((x) & BIT(30))
  38. #define SUPPORTS_ASYNC_POWERCAP_CAP_SET(x) ((x) & BIT(29))
  39. #define SUPPORTS_EXTENDED_NAMES(x) ((x) & BIT(28))
  40. #define SUPPORTS_POWERCAP_CAP_CONFIGURATION(x) ((x) & BIT(27))
  41. #define SUPPORTS_POWERCAP_MONITORING(x) ((x) & BIT(26))
  42. #define SUPPORTS_POWERCAP_PAI_CONFIGURATION(x) ((x) & BIT(25))
  43. #define SUPPORTS_POWERCAP_FASTCHANNELS(x) ((x) & BIT(22))
  44. #define POWERCAP_POWER_UNIT(x) \
  45. (FIELD_GET(GENMASK(24, 23), (x)))
  46. #define SUPPORTS_POWER_UNITS_MW(x) \
  47. (POWERCAP_POWER_UNIT(x) == 0x2)
  48. #define SUPPORTS_POWER_UNITS_UW(x) \
  49. (POWERCAP_POWER_UNIT(x) == 0x1)
  50. u8 name[SCMI_SHORT_NAME_MAX_SIZE];
  51. __le32 min_pai;
  52. __le32 max_pai;
  53. __le32 pai_step;
  54. __le32 min_power_cap;
  55. __le32 max_power_cap;
  56. __le32 power_cap_step;
  57. __le32 sustainable_power;
  58. __le32 accuracy;
  59. __le32 parent_id;
  60. };
  61. struct scmi_msg_powercap_set_cap_or_pai {
  62. __le32 domain;
  63. __le32 flags;
  64. #define CAP_SET_ASYNC BIT(1)
  65. #define CAP_SET_IGNORE_DRESP BIT(0)
  66. __le32 value;
  67. };
  68. struct scmi_msg_resp_powercap_cap_set_complete {
  69. __le32 domain;
  70. __le32 power_cap;
  71. };
  72. struct scmi_msg_resp_powercap_meas_get {
  73. __le32 power;
  74. __le32 pai;
  75. };
  76. struct scmi_msg_powercap_notify_cap {
  77. __le32 domain;
  78. __le32 notify_enable;
  79. };
  80. struct scmi_msg_powercap_notify_thresh {
  81. __le32 domain;
  82. __le32 notify_enable;
  83. __le32 power_thresh_low;
  84. __le32 power_thresh_high;
  85. };
  86. struct scmi_powercap_cap_changed_notify_payld {
  87. __le32 agent_id;
  88. __le32 domain_id;
  89. __le32 power_cap;
  90. __le32 pai;
  91. };
  92. struct scmi_powercap_meas_changed_notify_payld {
  93. __le32 agent_id;
  94. __le32 domain_id;
  95. __le32 power;
  96. };
  97. struct scmi_powercap_state {
  98. bool enabled;
  99. u32 last_pcap;
  100. bool meas_notif_enabled;
  101. u64 thresholds;
  102. #define THRESH_LOW(p, id) \
  103. (lower_32_bits((p)->states[(id)].thresholds))
  104. #define THRESH_HIGH(p, id) \
  105. (upper_32_bits((p)->states[(id)].thresholds))
  106. };
  107. struct powercap_info {
  108. u32 version;
  109. int num_domains;
  110. bool notify_cap_cmd;
  111. bool notify_measurements_cmd;
  112. struct scmi_powercap_state *states;
  113. struct scmi_powercap_info *powercaps;
  114. };
  115. static enum scmi_powercap_protocol_cmd evt_2_cmd[] = {
  116. POWERCAP_CAP_NOTIFY,
  117. POWERCAP_MEASUREMENTS_NOTIFY,
  118. };
  119. static int scmi_powercap_notify(const struct scmi_protocol_handle *ph,
  120. u32 domain, int message_id, bool enable);
  121. static int
  122. scmi_powercap_attributes_get(const struct scmi_protocol_handle *ph,
  123. struct powercap_info *pi)
  124. {
  125. int ret;
  126. struct scmi_xfer *t;
  127. ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, 0,
  128. sizeof(u32), &t);
  129. if (ret)
  130. return ret;
  131. ret = ph->xops->do_xfer(ph, t);
  132. if (!ret) {
  133. u32 attributes;
  134. attributes = get_unaligned_le32(t->rx.buf);
  135. pi->num_domains = FIELD_GET(GENMASK(15, 0), attributes);
  136. }
  137. ph->xops->xfer_put(ph, t);
  138. if (!ret) {
  139. if (!ph->hops->protocol_msg_check(ph,
  140. POWERCAP_CAP_NOTIFY, NULL))
  141. pi->notify_cap_cmd = true;
  142. if (!ph->hops->protocol_msg_check(ph,
  143. POWERCAP_MEASUREMENTS_NOTIFY,
  144. NULL))
  145. pi->notify_measurements_cmd = true;
  146. }
  147. return ret;
  148. }
  149. static inline int
  150. scmi_powercap_validate(unsigned int min_val, unsigned int max_val,
  151. unsigned int step_val, bool configurable)
  152. {
  153. if (!min_val || !max_val)
  154. return -EPROTO;
  155. if ((configurable && min_val == max_val) ||
  156. (!configurable && min_val != max_val))
  157. return -EPROTO;
  158. if (min_val != max_val && !step_val)
  159. return -EPROTO;
  160. return 0;
  161. }
  162. static int
  163. scmi_powercap_domain_attributes_get(const struct scmi_protocol_handle *ph,
  164. struct powercap_info *pinfo, u32 domain)
  165. {
  166. int ret;
  167. u32 flags;
  168. struct scmi_xfer *t;
  169. struct scmi_powercap_info *dom_info = pinfo->powercaps + domain;
  170. struct scmi_msg_resp_powercap_domain_attributes *resp;
  171. ret = ph->xops->xfer_get_init(ph, POWERCAP_DOMAIN_ATTRIBUTES,
  172. sizeof(domain), sizeof(*resp), &t);
  173. if (ret)
  174. return ret;
  175. put_unaligned_le32(domain, t->tx.buf);
  176. resp = t->rx.buf;
  177. ret = ph->xops->do_xfer(ph, t);
  178. if (!ret) {
  179. flags = le32_to_cpu(resp->attributes);
  180. dom_info->id = domain;
  181. if (pinfo->notify_cap_cmd)
  182. dom_info->notify_powercap_cap_change =
  183. SUPPORTS_POWERCAP_CAP_CHANGE_NOTIFY(flags);
  184. if (pinfo->notify_measurements_cmd)
  185. dom_info->notify_powercap_measurement_change =
  186. SUPPORTS_POWERCAP_MEASUREMENTS_CHANGE_NOTIFY(flags);
  187. dom_info->async_powercap_cap_set =
  188. SUPPORTS_ASYNC_POWERCAP_CAP_SET(flags);
  189. dom_info->powercap_cap_config =
  190. SUPPORTS_POWERCAP_CAP_CONFIGURATION(flags);
  191. dom_info->powercap_monitoring =
  192. SUPPORTS_POWERCAP_MONITORING(flags);
  193. dom_info->powercap_pai_config =
  194. SUPPORTS_POWERCAP_PAI_CONFIGURATION(flags);
  195. dom_info->powercap_scale_mw =
  196. SUPPORTS_POWER_UNITS_MW(flags);
  197. dom_info->powercap_scale_uw =
  198. SUPPORTS_POWER_UNITS_UW(flags);
  199. dom_info->fastchannels =
  200. SUPPORTS_POWERCAP_FASTCHANNELS(flags);
  201. strscpy(dom_info->name, resp->name, SCMI_SHORT_NAME_MAX_SIZE);
  202. dom_info->min_pai = le32_to_cpu(resp->min_pai);
  203. dom_info->max_pai = le32_to_cpu(resp->max_pai);
  204. dom_info->pai_step = le32_to_cpu(resp->pai_step);
  205. ret = scmi_powercap_validate(dom_info->min_pai,
  206. dom_info->max_pai,
  207. dom_info->pai_step,
  208. dom_info->powercap_pai_config);
  209. if (ret) {
  210. dev_err(ph->dev,
  211. "Platform reported inconsistent PAI config for domain %d - %s\n",
  212. dom_info->id, dom_info->name);
  213. goto clean;
  214. }
  215. dom_info->min_power_cap = le32_to_cpu(resp->min_power_cap);
  216. dom_info->max_power_cap = le32_to_cpu(resp->max_power_cap);
  217. dom_info->power_cap_step = le32_to_cpu(resp->power_cap_step);
  218. ret = scmi_powercap_validate(dom_info->min_power_cap,
  219. dom_info->max_power_cap,
  220. dom_info->power_cap_step,
  221. dom_info->powercap_cap_config);
  222. if (ret) {
  223. dev_err(ph->dev,
  224. "Platform reported inconsistent CAP config for domain %d - %s\n",
  225. dom_info->id, dom_info->name);
  226. goto clean;
  227. }
  228. dom_info->sustainable_power =
  229. le32_to_cpu(resp->sustainable_power);
  230. dom_info->accuracy = le32_to_cpu(resp->accuracy);
  231. dom_info->parent_id = le32_to_cpu(resp->parent_id);
  232. if (dom_info->parent_id != SCMI_POWERCAP_ROOT_ZONE_ID &&
  233. (dom_info->parent_id >= pinfo->num_domains ||
  234. dom_info->parent_id == dom_info->id)) {
  235. dev_err(ph->dev,
  236. "Platform reported inconsistent parent ID for domain %d - %s\n",
  237. dom_info->id, dom_info->name);
  238. ret = -ENODEV;
  239. }
  240. }
  241. clean:
  242. ph->xops->xfer_put(ph, t);
  243. /*
  244. * If supported overwrite short name with the extended one;
  245. * on error just carry on and use already provided short name.
  246. */
  247. if (!ret && SUPPORTS_EXTENDED_NAMES(flags))
  248. ph->hops->extended_name_get(ph, POWERCAP_DOMAIN_NAME_GET,
  249. domain, NULL, dom_info->name,
  250. SCMI_MAX_STR_SIZE);
  251. return ret;
  252. }
  253. static int scmi_powercap_num_domains_get(const struct scmi_protocol_handle *ph)
  254. {
  255. struct powercap_info *pi = ph->get_priv(ph);
  256. return pi->num_domains;
  257. }
  258. static const struct scmi_powercap_info *
  259. scmi_powercap_dom_info_get(const struct scmi_protocol_handle *ph, u32 domain_id)
  260. {
  261. struct powercap_info *pi = ph->get_priv(ph);
  262. if (domain_id >= pi->num_domains)
  263. return NULL;
  264. return pi->powercaps + domain_id;
  265. }
  266. static int scmi_powercap_xfer_cap_get(const struct scmi_protocol_handle *ph,
  267. u32 domain_id, u32 *power_cap)
  268. {
  269. int ret;
  270. struct scmi_xfer *t;
  271. ret = ph->xops->xfer_get_init(ph, POWERCAP_CAP_GET, sizeof(u32),
  272. sizeof(u32), &t);
  273. if (ret)
  274. return ret;
  275. put_unaligned_le32(domain_id, t->tx.buf);
  276. ret = ph->xops->do_xfer(ph, t);
  277. if (!ret)
  278. *power_cap = get_unaligned_le32(t->rx.buf);
  279. ph->xops->xfer_put(ph, t);
  280. return ret;
  281. }
  282. static int __scmi_powercap_cap_get(const struct scmi_protocol_handle *ph,
  283. const struct scmi_powercap_info *dom,
  284. u32 *power_cap)
  285. {
  286. if (dom->fc_info && dom->fc_info[POWERCAP_FC_CAP].get_addr) {
  287. *power_cap = ioread32(dom->fc_info[POWERCAP_FC_CAP].get_addr);
  288. trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_CAP_GET,
  289. dom->id, *power_cap, 0);
  290. return 0;
  291. }
  292. return scmi_powercap_xfer_cap_get(ph, dom->id, power_cap);
  293. }
  294. static int scmi_powercap_cap_get(const struct scmi_protocol_handle *ph,
  295. u32 domain_id, u32 *power_cap)
  296. {
  297. const struct scmi_powercap_info *dom;
  298. if (!power_cap)
  299. return -EINVAL;
  300. dom = scmi_powercap_dom_info_get(ph, domain_id);
  301. if (!dom)
  302. return -EINVAL;
  303. return __scmi_powercap_cap_get(ph, dom, power_cap);
  304. }
  305. static int scmi_powercap_xfer_cap_set(const struct scmi_protocol_handle *ph,
  306. const struct scmi_powercap_info *pc,
  307. u32 power_cap, bool ignore_dresp)
  308. {
  309. int ret;
  310. struct scmi_xfer *t;
  311. struct scmi_msg_powercap_set_cap_or_pai *msg;
  312. ret = ph->xops->xfer_get_init(ph, POWERCAP_CAP_SET,
  313. sizeof(*msg), 0, &t);
  314. if (ret)
  315. return ret;
  316. msg = t->tx.buf;
  317. msg->domain = cpu_to_le32(pc->id);
  318. msg->flags =
  319. cpu_to_le32(FIELD_PREP(CAP_SET_ASYNC, pc->async_powercap_cap_set) |
  320. FIELD_PREP(CAP_SET_IGNORE_DRESP, ignore_dresp));
  321. msg->value = cpu_to_le32(power_cap);
  322. if (!pc->async_powercap_cap_set || ignore_dresp) {
  323. ret = ph->xops->do_xfer(ph, t);
  324. } else {
  325. ret = ph->xops->do_xfer_with_response(ph, t);
  326. if (!ret) {
  327. struct scmi_msg_resp_powercap_cap_set_complete *resp;
  328. resp = t->rx.buf;
  329. if (le32_to_cpu(resp->domain) == pc->id)
  330. dev_dbg(ph->dev,
  331. "Powercap ID %d CAP set async to %u\n",
  332. pc->id,
  333. get_unaligned_le32(&resp->power_cap));
  334. else
  335. ret = -EPROTO;
  336. }
  337. }
  338. ph->xops->xfer_put(ph, t);
  339. return ret;
  340. }
  341. static int __scmi_powercap_cap_set(const struct scmi_protocol_handle *ph,
  342. struct powercap_info *pi, u32 domain_id,
  343. u32 power_cap, bool ignore_dresp)
  344. {
  345. int ret = -EINVAL;
  346. const struct scmi_powercap_info *pc;
  347. pc = scmi_powercap_dom_info_get(ph, domain_id);
  348. if (!pc || !pc->powercap_cap_config)
  349. return ret;
  350. if (power_cap &&
  351. (power_cap < pc->min_power_cap || power_cap > pc->max_power_cap))
  352. return ret;
  353. if (pc->fc_info && pc->fc_info[POWERCAP_FC_CAP].set_addr) {
  354. struct scmi_fc_info *fci = &pc->fc_info[POWERCAP_FC_CAP];
  355. iowrite32(power_cap, fci->set_addr);
  356. ph->hops->fastchannel_db_ring(fci->set_db);
  357. trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_CAP_SET,
  358. domain_id, power_cap, 0);
  359. ret = 0;
  360. } else {
  361. ret = scmi_powercap_xfer_cap_set(ph, pc, power_cap,
  362. ignore_dresp);
  363. }
  364. /* Save the last explicitly set non-zero powercap value */
  365. if (PROTOCOL_REV_MAJOR(pi->version) >= 0x2 && !ret && power_cap)
  366. pi->states[domain_id].last_pcap = power_cap;
  367. return ret;
  368. }
  369. static int scmi_powercap_cap_set(const struct scmi_protocol_handle *ph,
  370. u32 domain_id, u32 power_cap,
  371. bool ignore_dresp)
  372. {
  373. struct powercap_info *pi = ph->get_priv(ph);
  374. /*
  375. * Disallow zero as a possible explicitly requested powercap:
  376. * there are enable/disable operations for this.
  377. */
  378. if (!power_cap)
  379. return -EINVAL;
  380. /* Just log the last set request if acting on a disabled domain */
  381. if (PROTOCOL_REV_MAJOR(pi->version) >= 0x2 &&
  382. !pi->states[domain_id].enabled) {
  383. pi->states[domain_id].last_pcap = power_cap;
  384. return 0;
  385. }
  386. return __scmi_powercap_cap_set(ph, pi, domain_id,
  387. power_cap, ignore_dresp);
  388. }
  389. static int scmi_powercap_xfer_pai_get(const struct scmi_protocol_handle *ph,
  390. u32 domain_id, u32 *pai)
  391. {
  392. int ret;
  393. struct scmi_xfer *t;
  394. ret = ph->xops->xfer_get_init(ph, POWERCAP_PAI_GET, sizeof(u32),
  395. sizeof(u32), &t);
  396. if (ret)
  397. return ret;
  398. put_unaligned_le32(domain_id, t->tx.buf);
  399. ret = ph->xops->do_xfer(ph, t);
  400. if (!ret)
  401. *pai = get_unaligned_le32(t->rx.buf);
  402. ph->xops->xfer_put(ph, t);
  403. return ret;
  404. }
  405. static int scmi_powercap_pai_get(const struct scmi_protocol_handle *ph,
  406. u32 domain_id, u32 *pai)
  407. {
  408. struct scmi_powercap_info *dom;
  409. struct powercap_info *pi = ph->get_priv(ph);
  410. if (!pai || domain_id >= pi->num_domains)
  411. return -EINVAL;
  412. dom = pi->powercaps + domain_id;
  413. if (dom->fc_info && dom->fc_info[POWERCAP_FC_PAI].get_addr) {
  414. *pai = ioread32(dom->fc_info[POWERCAP_FC_PAI].get_addr);
  415. trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_PAI_GET,
  416. domain_id, *pai, 0);
  417. return 0;
  418. }
  419. return scmi_powercap_xfer_pai_get(ph, domain_id, pai);
  420. }
  421. static int scmi_powercap_xfer_pai_set(const struct scmi_protocol_handle *ph,
  422. u32 domain_id, u32 pai)
  423. {
  424. int ret;
  425. struct scmi_xfer *t;
  426. struct scmi_msg_powercap_set_cap_or_pai *msg;
  427. ret = ph->xops->xfer_get_init(ph, POWERCAP_PAI_SET,
  428. sizeof(*msg), 0, &t);
  429. if (ret)
  430. return ret;
  431. msg = t->tx.buf;
  432. msg->domain = cpu_to_le32(domain_id);
  433. msg->flags = cpu_to_le32(0);
  434. msg->value = cpu_to_le32(pai);
  435. ret = ph->xops->do_xfer(ph, t);
  436. ph->xops->xfer_put(ph, t);
  437. return ret;
  438. }
  439. static int scmi_powercap_pai_set(const struct scmi_protocol_handle *ph,
  440. u32 domain_id, u32 pai)
  441. {
  442. const struct scmi_powercap_info *pc;
  443. pc = scmi_powercap_dom_info_get(ph, domain_id);
  444. if (!pc || !pc->powercap_pai_config || !pai ||
  445. pai < pc->min_pai || pai > pc->max_pai)
  446. return -EINVAL;
  447. if (pc->fc_info && pc->fc_info[POWERCAP_FC_PAI].set_addr) {
  448. struct scmi_fc_info *fci = &pc->fc_info[POWERCAP_FC_PAI];
  449. trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_PAI_SET,
  450. domain_id, pai, 0);
  451. iowrite32(pai, fci->set_addr);
  452. ph->hops->fastchannel_db_ring(fci->set_db);
  453. return 0;
  454. }
  455. return scmi_powercap_xfer_pai_set(ph, domain_id, pai);
  456. }
  457. static int scmi_powercap_measurements_get(const struct scmi_protocol_handle *ph,
  458. u32 domain_id, u32 *average_power,
  459. u32 *pai)
  460. {
  461. int ret;
  462. struct scmi_xfer *t;
  463. struct scmi_msg_resp_powercap_meas_get *resp;
  464. const struct scmi_powercap_info *pc;
  465. pc = scmi_powercap_dom_info_get(ph, domain_id);
  466. if (!pc || !pc->powercap_monitoring || !pai || !average_power)
  467. return -EINVAL;
  468. ret = ph->xops->xfer_get_init(ph, POWERCAP_MEASUREMENTS_GET,
  469. sizeof(u32), sizeof(*resp), &t);
  470. if (ret)
  471. return ret;
  472. resp = t->rx.buf;
  473. put_unaligned_le32(domain_id, t->tx.buf);
  474. ret = ph->xops->do_xfer(ph, t);
  475. if (!ret) {
  476. *average_power = le32_to_cpu(resp->power);
  477. *pai = le32_to_cpu(resp->pai);
  478. }
  479. ph->xops->xfer_put(ph, t);
  480. return ret;
  481. }
  482. static int
  483. scmi_powercap_measurements_threshold_get(const struct scmi_protocol_handle *ph,
  484. u32 domain_id, u32 *power_thresh_low,
  485. u32 *power_thresh_high)
  486. {
  487. struct powercap_info *pi = ph->get_priv(ph);
  488. if (!power_thresh_low || !power_thresh_high ||
  489. domain_id >= pi->num_domains)
  490. return -EINVAL;
  491. *power_thresh_low = THRESH_LOW(pi, domain_id);
  492. *power_thresh_high = THRESH_HIGH(pi, domain_id);
  493. return 0;
  494. }
  495. static int
  496. scmi_powercap_measurements_threshold_set(const struct scmi_protocol_handle *ph,
  497. u32 domain_id, u32 power_thresh_low,
  498. u32 power_thresh_high)
  499. {
  500. int ret = 0;
  501. struct powercap_info *pi = ph->get_priv(ph);
  502. if (domain_id >= pi->num_domains ||
  503. power_thresh_low > power_thresh_high)
  504. return -EINVAL;
  505. /* Anything to do ? */
  506. if (THRESH_LOW(pi, domain_id) == power_thresh_low &&
  507. THRESH_HIGH(pi, domain_id) == power_thresh_high)
  508. return ret;
  509. pi->states[domain_id].thresholds =
  510. (FIELD_PREP(GENMASK_ULL(31, 0), power_thresh_low) |
  511. FIELD_PREP(GENMASK_ULL(63, 32), power_thresh_high));
  512. /* Update thresholds if notification already enabled */
  513. if (pi->states[domain_id].meas_notif_enabled)
  514. ret = scmi_powercap_notify(ph, domain_id,
  515. POWERCAP_MEASUREMENTS_NOTIFY,
  516. true);
  517. return ret;
  518. }
  519. static int scmi_powercap_cap_enable_set(const struct scmi_protocol_handle *ph,
  520. u32 domain_id, bool enable)
  521. {
  522. int ret;
  523. u32 power_cap;
  524. struct powercap_info *pi = ph->get_priv(ph);
  525. if (PROTOCOL_REV_MAJOR(pi->version) < 0x2)
  526. return -EINVAL;
  527. if (enable == pi->states[domain_id].enabled)
  528. return 0;
  529. if (enable) {
  530. /* Cannot enable with a zero powercap. */
  531. if (!pi->states[domain_id].last_pcap)
  532. return -EINVAL;
  533. ret = __scmi_powercap_cap_set(ph, pi, domain_id,
  534. pi->states[domain_id].last_pcap,
  535. true);
  536. } else {
  537. ret = __scmi_powercap_cap_set(ph, pi, domain_id, 0, true);
  538. }
  539. if (ret)
  540. return ret;
  541. /*
  542. * Update our internal state to reflect final platform state: the SCMI
  543. * server could have ignored a disable request and kept enforcing some
  544. * powercap limit requested by other agents.
  545. */
  546. ret = scmi_powercap_cap_get(ph, domain_id, &power_cap);
  547. if (!ret)
  548. pi->states[domain_id].enabled = !!power_cap;
  549. return ret;
  550. }
  551. static int scmi_powercap_cap_enable_get(const struct scmi_protocol_handle *ph,
  552. u32 domain_id, bool *enable)
  553. {
  554. int ret;
  555. u32 power_cap;
  556. struct powercap_info *pi = ph->get_priv(ph);
  557. *enable = true;
  558. if (PROTOCOL_REV_MAJOR(pi->version) < 0x2)
  559. return 0;
  560. /*
  561. * Report always real platform state; platform could have ignored
  562. * a previous disable request. Default true on any error.
  563. */
  564. ret = scmi_powercap_cap_get(ph, domain_id, &power_cap);
  565. if (!ret)
  566. *enable = !!power_cap;
  567. /* Update internal state with current real platform state */
  568. pi->states[domain_id].enabled = *enable;
  569. return 0;
  570. }
  571. static const struct scmi_powercap_proto_ops powercap_proto_ops = {
  572. .num_domains_get = scmi_powercap_num_domains_get,
  573. .info_get = scmi_powercap_dom_info_get,
  574. .cap_get = scmi_powercap_cap_get,
  575. .cap_set = scmi_powercap_cap_set,
  576. .cap_enable_set = scmi_powercap_cap_enable_set,
  577. .cap_enable_get = scmi_powercap_cap_enable_get,
  578. .pai_get = scmi_powercap_pai_get,
  579. .pai_set = scmi_powercap_pai_set,
  580. .measurements_get = scmi_powercap_measurements_get,
  581. .measurements_threshold_set = scmi_powercap_measurements_threshold_set,
  582. .measurements_threshold_get = scmi_powercap_measurements_threshold_get,
  583. };
  584. static void scmi_powercap_domain_init_fc(const struct scmi_protocol_handle *ph,
  585. u32 domain, struct scmi_fc_info **p_fc)
  586. {
  587. struct scmi_fc_info *fc;
  588. fc = devm_kcalloc(ph->dev, POWERCAP_FC_MAX, sizeof(*fc), GFP_KERNEL);
  589. if (!fc)
  590. return;
  591. ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
  592. POWERCAP_CAP_SET, 4, domain,
  593. &fc[POWERCAP_FC_CAP].set_addr,
  594. &fc[POWERCAP_FC_CAP].set_db,
  595. &fc[POWERCAP_FC_CAP].rate_limit);
  596. ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
  597. POWERCAP_CAP_GET, 4, domain,
  598. &fc[POWERCAP_FC_CAP].get_addr, NULL,
  599. &fc[POWERCAP_FC_CAP].rate_limit);
  600. ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
  601. POWERCAP_PAI_SET, 4, domain,
  602. &fc[POWERCAP_FC_PAI].set_addr,
  603. &fc[POWERCAP_FC_PAI].set_db,
  604. &fc[POWERCAP_FC_PAI].rate_limit);
  605. ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
  606. POWERCAP_PAI_GET, 4, domain,
  607. &fc[POWERCAP_FC_PAI].get_addr, NULL,
  608. &fc[POWERCAP_FC_PAI].rate_limit);
  609. *p_fc = fc;
  610. }
  611. static int scmi_powercap_notify(const struct scmi_protocol_handle *ph,
  612. u32 domain, int message_id, bool enable)
  613. {
  614. int ret;
  615. struct scmi_xfer *t;
  616. switch (message_id) {
  617. case POWERCAP_CAP_NOTIFY:
  618. {
  619. struct scmi_msg_powercap_notify_cap *notify;
  620. ret = ph->xops->xfer_get_init(ph, message_id,
  621. sizeof(*notify), 0, &t);
  622. if (ret)
  623. return ret;
  624. notify = t->tx.buf;
  625. notify->domain = cpu_to_le32(domain);
  626. notify->notify_enable = cpu_to_le32(enable ? BIT(0) : 0);
  627. break;
  628. }
  629. case POWERCAP_MEASUREMENTS_NOTIFY:
  630. {
  631. u32 low, high;
  632. struct scmi_msg_powercap_notify_thresh *notify;
  633. /*
  634. * Note that we have to pick the most recently configured
  635. * thresholds to build a proper POWERCAP_MEASUREMENTS_NOTIFY
  636. * enable request and we fail, complaining, if no thresholds
  637. * were ever set, since this is an indication the API has been
  638. * used wrongly.
  639. */
  640. ret = scmi_powercap_measurements_threshold_get(ph, domain,
  641. &low, &high);
  642. if (ret)
  643. return ret;
  644. if (enable && !low && !high) {
  645. dev_err(ph->dev,
  646. "Invalid Measurements Notify thresholds: %u/%u\n",
  647. low, high);
  648. return -EINVAL;
  649. }
  650. ret = ph->xops->xfer_get_init(ph, message_id,
  651. sizeof(*notify), 0, &t);
  652. if (ret)
  653. return ret;
  654. notify = t->tx.buf;
  655. notify->domain = cpu_to_le32(domain);
  656. notify->notify_enable = cpu_to_le32(enable ? BIT(0) : 0);
  657. notify->power_thresh_low = cpu_to_le32(low);
  658. notify->power_thresh_high = cpu_to_le32(high);
  659. break;
  660. }
  661. default:
  662. return -EINVAL;
  663. }
  664. ret = ph->xops->do_xfer(ph, t);
  665. ph->xops->xfer_put(ph, t);
  666. return ret;
  667. }
  668. static bool
  669. scmi_powercap_notify_supported(const struct scmi_protocol_handle *ph,
  670. u8 evt_id, u32 src_id)
  671. {
  672. bool supported = false;
  673. const struct scmi_powercap_info *dom_info;
  674. struct powercap_info *pi = ph->get_priv(ph);
  675. if (evt_id >= ARRAY_SIZE(evt_2_cmd) || src_id >= pi->num_domains)
  676. return false;
  677. dom_info = pi->powercaps + src_id;
  678. if (evt_id == SCMI_EVENT_POWERCAP_CAP_CHANGED)
  679. supported = dom_info->notify_powercap_cap_change;
  680. else if (evt_id == SCMI_EVENT_POWERCAP_MEASUREMENTS_CHANGED)
  681. supported = dom_info->notify_powercap_measurement_change;
  682. return supported;
  683. }
  684. static int
  685. scmi_powercap_set_notify_enabled(const struct scmi_protocol_handle *ph,
  686. u8 evt_id, u32 src_id, bool enable)
  687. {
  688. int ret, cmd_id;
  689. struct powercap_info *pi = ph->get_priv(ph);
  690. if (evt_id >= ARRAY_SIZE(evt_2_cmd) || src_id >= pi->num_domains)
  691. return -EINVAL;
  692. cmd_id = evt_2_cmd[evt_id];
  693. ret = scmi_powercap_notify(ph, src_id, cmd_id, enable);
  694. if (ret)
  695. pr_debug("FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n",
  696. evt_id, src_id, ret);
  697. else if (cmd_id == POWERCAP_MEASUREMENTS_NOTIFY)
  698. /*
  699. * On success save the current notification enabled state, so
  700. * as to be able to properly update the notification thresholds
  701. * when they are modified on a domain for which measurement
  702. * notifications were currently enabled.
  703. *
  704. * This is needed because the SCMI Notification core machinery
  705. * and API does not support passing per-notification custom
  706. * arguments at callback registration time.
  707. *
  708. * Note that this can be done here with a simple flag since the
  709. * SCMI core Notifications code takes care of keeping proper
  710. * per-domain enables refcounting, so that this helper function
  711. * will be called only once (for enables) when the first user
  712. * registers a callback on this domain and once more (disable)
  713. * when the last user de-registers its callback.
  714. */
  715. pi->states[src_id].meas_notif_enabled = enable;
  716. return ret;
  717. }
  718. static void *
  719. scmi_powercap_fill_custom_report(const struct scmi_protocol_handle *ph,
  720. u8 evt_id, ktime_t timestamp,
  721. const void *payld, size_t payld_sz,
  722. void *report, u32 *src_id)
  723. {
  724. void *rep = NULL;
  725. switch (evt_id) {
  726. case SCMI_EVENT_POWERCAP_CAP_CHANGED:
  727. {
  728. const struct scmi_powercap_cap_changed_notify_payld *p = payld;
  729. struct scmi_powercap_cap_changed_report *r = report;
  730. if (sizeof(*p) != payld_sz)
  731. break;
  732. r->timestamp = timestamp;
  733. r->agent_id = le32_to_cpu(p->agent_id);
  734. r->domain_id = le32_to_cpu(p->domain_id);
  735. r->power_cap = le32_to_cpu(p->power_cap);
  736. r->pai = le32_to_cpu(p->pai);
  737. *src_id = r->domain_id;
  738. rep = r;
  739. break;
  740. }
  741. case SCMI_EVENT_POWERCAP_MEASUREMENTS_CHANGED:
  742. {
  743. const struct scmi_powercap_meas_changed_notify_payld *p = payld;
  744. struct scmi_powercap_meas_changed_report *r = report;
  745. if (sizeof(*p) != payld_sz)
  746. break;
  747. r->timestamp = timestamp;
  748. r->agent_id = le32_to_cpu(p->agent_id);
  749. r->domain_id = le32_to_cpu(p->domain_id);
  750. r->power = le32_to_cpu(p->power);
  751. *src_id = r->domain_id;
  752. rep = r;
  753. break;
  754. }
  755. default:
  756. break;
  757. }
  758. return rep;
  759. }
  760. static int
  761. scmi_powercap_get_num_sources(const struct scmi_protocol_handle *ph)
  762. {
  763. struct powercap_info *pi = ph->get_priv(ph);
  764. if (!pi)
  765. return -EINVAL;
  766. return pi->num_domains;
  767. }
  768. static const struct scmi_event powercap_events[] = {
  769. {
  770. .id = SCMI_EVENT_POWERCAP_CAP_CHANGED,
  771. .max_payld_sz =
  772. sizeof(struct scmi_powercap_cap_changed_notify_payld),
  773. .max_report_sz =
  774. sizeof(struct scmi_powercap_cap_changed_report),
  775. },
  776. {
  777. .id = SCMI_EVENT_POWERCAP_MEASUREMENTS_CHANGED,
  778. .max_payld_sz =
  779. sizeof(struct scmi_powercap_meas_changed_notify_payld),
  780. .max_report_sz =
  781. sizeof(struct scmi_powercap_meas_changed_report),
  782. },
  783. };
  784. static const struct scmi_event_ops powercap_event_ops = {
  785. .is_notify_supported = scmi_powercap_notify_supported,
  786. .get_num_sources = scmi_powercap_get_num_sources,
  787. .set_notify_enabled = scmi_powercap_set_notify_enabled,
  788. .fill_custom_report = scmi_powercap_fill_custom_report,
  789. };
  790. static const struct scmi_protocol_events powercap_protocol_events = {
  791. .queue_sz = SCMI_PROTO_QUEUE_SZ,
  792. .ops = &powercap_event_ops,
  793. .evts = powercap_events,
  794. .num_events = ARRAY_SIZE(powercap_events),
  795. };
  796. static int
  797. scmi_powercap_protocol_init(const struct scmi_protocol_handle *ph)
  798. {
  799. int domain, ret;
  800. u32 version;
  801. struct powercap_info *pinfo;
  802. ret = ph->xops->version_get(ph, &version);
  803. if (ret)
  804. return ret;
  805. dev_dbg(ph->dev, "Powercap Version %d.%d\n",
  806. PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
  807. pinfo = devm_kzalloc(ph->dev, sizeof(*pinfo), GFP_KERNEL);
  808. if (!pinfo)
  809. return -ENOMEM;
  810. ret = scmi_powercap_attributes_get(ph, pinfo);
  811. if (ret)
  812. return ret;
  813. pinfo->powercaps = devm_kcalloc(ph->dev, pinfo->num_domains,
  814. sizeof(*pinfo->powercaps),
  815. GFP_KERNEL);
  816. if (!pinfo->powercaps)
  817. return -ENOMEM;
  818. pinfo->states = devm_kcalloc(ph->dev, pinfo->num_domains,
  819. sizeof(*pinfo->states), GFP_KERNEL);
  820. if (!pinfo->states)
  821. return -ENOMEM;
  822. /*
  823. * Note that any failure in retrieving any domain attribute leads to
  824. * the whole Powercap protocol initialization failure: this way the
  825. * reported Powercap domains are all assured, when accessed, to be well
  826. * formed and correlated by sane parent-child relationship (if any).
  827. */
  828. for (domain = 0; domain < pinfo->num_domains; domain++) {
  829. ret = scmi_powercap_domain_attributes_get(ph, pinfo, domain);
  830. if (ret)
  831. return ret;
  832. if (pinfo->powercaps[domain].fastchannels)
  833. scmi_powercap_domain_init_fc(ph, domain,
  834. &pinfo->powercaps[domain].fc_info);
  835. /* Grab initial state when disable is supported. */
  836. if (PROTOCOL_REV_MAJOR(version) >= 0x2) {
  837. ret = __scmi_powercap_cap_get(ph,
  838. &pinfo->powercaps[domain],
  839. &pinfo->states[domain].last_pcap);
  840. if (ret)
  841. return ret;
  842. pinfo->states[domain].enabled =
  843. !!pinfo->states[domain].last_pcap;
  844. }
  845. }
  846. pinfo->version = version;
  847. return ph->set_priv(ph, pinfo, version);
  848. }
  849. static const struct scmi_protocol scmi_powercap = {
  850. .id = SCMI_PROTOCOL_POWERCAP,
  851. .owner = THIS_MODULE,
  852. .instance_init = &scmi_powercap_protocol_init,
  853. .ops = &powercap_proto_ops,
  854. .events = &powercap_protocol_events,
  855. .supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION,
  856. };
  857. DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(powercap, scmi_powercap)