powercap.c 27 KB

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