1 // SPDX-License-Identifier: GPL-2.0
3 * System Control and Management Interface (SCMI) Powercap Protocol
5 * Copyright (C) 2022 ARM Ltd.
8 #define pr_fmt(fmt) "SCMI Notifications POWERCAP - " fmt
10 #include <linux/bitfield.h>
12 #include <linux/module.h>
13 #include <linux/scmi_protocol.h>
15 #include <trace/events/scmi.h>
17 #include "protocols.h"
20 enum scmi_powercap_protocol_cmd {
21 POWERCAP_DOMAIN_ATTRIBUTES = 0x3,
22 POWERCAP_CAP_GET = 0x4,
23 POWERCAP_CAP_SET = 0x5,
24 POWERCAP_PAI_GET = 0x6,
25 POWERCAP_PAI_SET = 0x7,
26 POWERCAP_DOMAIN_NAME_GET = 0x8,
27 POWERCAP_MEASUREMENTS_GET = 0x9,
28 POWERCAP_CAP_NOTIFY = 0xa,
29 POWERCAP_MEASUREMENTS_NOTIFY = 0xb,
30 POWERCAP_DESCRIBE_FASTCHANNEL = 0xc,
39 struct scmi_msg_resp_powercap_domain_attributes {
41 #define SUPPORTS_POWERCAP_CAP_CHANGE_NOTIFY(x) ((x) & BIT(31))
42 #define SUPPORTS_POWERCAP_MEASUREMENTS_CHANGE_NOTIFY(x) ((x) & BIT(30))
43 #define SUPPORTS_ASYNC_POWERCAP_CAP_SET(x) ((x) & BIT(29))
44 #define SUPPORTS_EXTENDED_NAMES(x) ((x) & BIT(28))
45 #define SUPPORTS_POWERCAP_CAP_CONFIGURATION(x) ((x) & BIT(27))
46 #define SUPPORTS_POWERCAP_MONITORING(x) ((x) & BIT(26))
47 #define SUPPORTS_POWERCAP_PAI_CONFIGURATION(x) ((x) & BIT(25))
48 #define SUPPORTS_POWERCAP_FASTCHANNELS(x) ((x) & BIT(22))
49 #define POWERCAP_POWER_UNIT(x) \
50 (FIELD_GET(GENMASK(24, 23), (x)))
51 #define SUPPORTS_POWER_UNITS_MW(x) \
52 (POWERCAP_POWER_UNIT(x) == 0x2)
53 #define SUPPORTS_POWER_UNITS_UW(x) \
54 (POWERCAP_POWER_UNIT(x) == 0x1)
55 u8 name[SCMI_SHORT_NAME_MAX_SIZE];
61 __le32 power_cap_step;
62 __le32 sustainable_power;
67 struct scmi_msg_powercap_set_cap_or_pai {
70 #define CAP_SET_ASYNC BIT(1)
71 #define CAP_SET_IGNORE_DRESP BIT(0)
75 struct scmi_msg_resp_powercap_cap_set_complete {
80 struct scmi_msg_resp_powercap_meas_get {
85 struct scmi_msg_powercap_notify_cap {
90 struct scmi_msg_powercap_notify_thresh {
93 __le32 power_thresh_low;
94 __le32 power_thresh_high;
97 struct scmi_powercap_cap_changed_notify_payld {
104 struct scmi_powercap_meas_changed_notify_payld {
110 struct scmi_powercap_state {
111 bool meas_notif_enabled;
113 #define THRESH_LOW(p, id) \
114 (lower_32_bits((p)->states[(id)].thresholds))
115 #define THRESH_HIGH(p, id) \
116 (upper_32_bits((p)->states[(id)].thresholds))
119 struct powercap_info {
122 struct scmi_powercap_state *states;
123 struct scmi_powercap_info *powercaps;
126 static enum scmi_powercap_protocol_cmd evt_2_cmd[] = {
128 POWERCAP_MEASUREMENTS_NOTIFY,
131 static int scmi_powercap_notify(const struct scmi_protocol_handle *ph,
132 u32 domain, int message_id, bool enable);
135 scmi_powercap_attributes_get(const struct scmi_protocol_handle *ph,
136 struct powercap_info *pi)
141 ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, 0,
146 ret = ph->xops->do_xfer(ph, t);
150 attributes = get_unaligned_le32(t->rx.buf);
151 pi->num_domains = FIELD_GET(GENMASK(15, 0), attributes);
154 ph->xops->xfer_put(ph, t);
159 scmi_powercap_validate(unsigned int min_val, unsigned int max_val,
160 unsigned int step_val, bool configurable)
162 if (!min_val || !max_val)
165 if ((configurable && min_val == max_val) ||
166 (!configurable && min_val != max_val))
169 if (min_val != max_val && !step_val)
176 scmi_powercap_domain_attributes_get(const struct scmi_protocol_handle *ph,
177 struct powercap_info *pinfo, u32 domain)
182 struct scmi_powercap_info *dom_info = pinfo->powercaps + domain;
183 struct scmi_msg_resp_powercap_domain_attributes *resp;
185 ret = ph->xops->xfer_get_init(ph, POWERCAP_DOMAIN_ATTRIBUTES,
186 sizeof(domain), sizeof(*resp), &t);
190 put_unaligned_le32(domain, t->tx.buf);
193 ret = ph->xops->do_xfer(ph, t);
195 flags = le32_to_cpu(resp->attributes);
197 dom_info->id = domain;
198 dom_info->notify_powercap_cap_change =
199 SUPPORTS_POWERCAP_CAP_CHANGE_NOTIFY(flags);
200 dom_info->notify_powercap_measurement_change =
201 SUPPORTS_POWERCAP_MEASUREMENTS_CHANGE_NOTIFY(flags);
202 dom_info->async_powercap_cap_set =
203 SUPPORTS_ASYNC_POWERCAP_CAP_SET(flags);
204 dom_info->powercap_cap_config =
205 SUPPORTS_POWERCAP_CAP_CONFIGURATION(flags);
206 dom_info->powercap_monitoring =
207 SUPPORTS_POWERCAP_MONITORING(flags);
208 dom_info->powercap_pai_config =
209 SUPPORTS_POWERCAP_PAI_CONFIGURATION(flags);
210 dom_info->powercap_scale_mw =
211 SUPPORTS_POWER_UNITS_MW(flags);
212 dom_info->powercap_scale_uw =
213 SUPPORTS_POWER_UNITS_UW(flags);
214 dom_info->fastchannels =
215 SUPPORTS_POWERCAP_FASTCHANNELS(flags);
217 strscpy(dom_info->name, resp->name, SCMI_SHORT_NAME_MAX_SIZE);
219 dom_info->min_pai = le32_to_cpu(resp->min_pai);
220 dom_info->max_pai = le32_to_cpu(resp->max_pai);
221 dom_info->pai_step = le32_to_cpu(resp->pai_step);
222 ret = scmi_powercap_validate(dom_info->min_pai,
225 dom_info->powercap_pai_config);
228 "Platform reported inconsistent PAI config for domain %d - %s\n",
229 dom_info->id, dom_info->name);
233 dom_info->min_power_cap = le32_to_cpu(resp->min_power_cap);
234 dom_info->max_power_cap = le32_to_cpu(resp->max_power_cap);
235 dom_info->power_cap_step = le32_to_cpu(resp->power_cap_step);
236 ret = scmi_powercap_validate(dom_info->min_power_cap,
237 dom_info->max_power_cap,
238 dom_info->power_cap_step,
239 dom_info->powercap_cap_config);
242 "Platform reported inconsistent CAP config for domain %d - %s\n",
243 dom_info->id, dom_info->name);
247 dom_info->sustainable_power =
248 le32_to_cpu(resp->sustainable_power);
249 dom_info->accuracy = le32_to_cpu(resp->accuracy);
251 dom_info->parent_id = le32_to_cpu(resp->parent_id);
252 if (dom_info->parent_id != SCMI_POWERCAP_ROOT_ZONE_ID &&
253 (dom_info->parent_id >= pinfo->num_domains ||
254 dom_info->parent_id == dom_info->id)) {
256 "Platform reported inconsistent parent ID for domain %d - %s\n",
257 dom_info->id, dom_info->name);
263 ph->xops->xfer_put(ph, t);
266 * If supported overwrite short name with the extended one;
267 * on error just carry on and use already provided short name.
269 if (!ret && SUPPORTS_EXTENDED_NAMES(flags))
270 ph->hops->extended_name_get(ph, POWERCAP_DOMAIN_NAME_GET,
271 domain, dom_info->name,
277 static int scmi_powercap_num_domains_get(const struct scmi_protocol_handle *ph)
279 struct powercap_info *pi = ph->get_priv(ph);
281 return pi->num_domains;
284 static const struct scmi_powercap_info *
285 scmi_powercap_dom_info_get(const struct scmi_protocol_handle *ph, u32 domain_id)
287 struct powercap_info *pi = ph->get_priv(ph);
289 if (domain_id >= pi->num_domains)
292 return pi->powercaps + domain_id;
295 static int scmi_powercap_xfer_cap_get(const struct scmi_protocol_handle *ph,
296 u32 domain_id, u32 *power_cap)
301 ret = ph->xops->xfer_get_init(ph, POWERCAP_CAP_GET, sizeof(u32),
306 put_unaligned_le32(domain_id, t->tx.buf);
307 ret = ph->xops->do_xfer(ph, t);
309 *power_cap = get_unaligned_le32(t->rx.buf);
311 ph->xops->xfer_put(ph, t);
316 static int scmi_powercap_cap_get(const struct scmi_protocol_handle *ph,
317 u32 domain_id, u32 *power_cap)
319 struct scmi_powercap_info *dom;
320 struct powercap_info *pi = ph->get_priv(ph);
322 if (!power_cap || domain_id >= pi->num_domains)
325 dom = pi->powercaps + domain_id;
326 if (dom->fc_info && dom->fc_info[POWERCAP_FC_CAP].get_addr) {
327 *power_cap = ioread32(dom->fc_info[POWERCAP_FC_CAP].get_addr);
328 trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_CAP_GET,
329 domain_id, *power_cap, 0);
333 return scmi_powercap_xfer_cap_get(ph, domain_id, power_cap);
336 static int scmi_powercap_xfer_cap_set(const struct scmi_protocol_handle *ph,
337 const struct scmi_powercap_info *pc,
338 u32 power_cap, bool ignore_dresp)
342 struct scmi_msg_powercap_set_cap_or_pai *msg;
344 ret = ph->xops->xfer_get_init(ph, POWERCAP_CAP_SET,
345 sizeof(*msg), 0, &t);
350 msg->domain = cpu_to_le32(pc->id);
352 cpu_to_le32(FIELD_PREP(CAP_SET_ASYNC, !!pc->async_powercap_cap_set) |
353 FIELD_PREP(CAP_SET_IGNORE_DRESP, !!ignore_dresp));
354 msg->value = cpu_to_le32(power_cap);
356 if (!pc->async_powercap_cap_set || ignore_dresp) {
357 ret = ph->xops->do_xfer(ph, t);
359 ret = ph->xops->do_xfer_with_response(ph, t);
361 struct scmi_msg_resp_powercap_cap_set_complete *resp;
364 if (le32_to_cpu(resp->domain) == pc->id)
366 "Powercap ID %d CAP set async to %u\n",
368 get_unaligned_le32(&resp->power_cap));
374 ph->xops->xfer_put(ph, t);
378 static int scmi_powercap_cap_set(const struct scmi_protocol_handle *ph,
379 u32 domain_id, u32 power_cap,
382 const struct scmi_powercap_info *pc;
384 pc = scmi_powercap_dom_info_get(ph, domain_id);
385 if (!pc || !pc->powercap_cap_config || !power_cap ||
386 power_cap < pc->min_power_cap ||
387 power_cap > pc->max_power_cap)
390 if (pc->fc_info && pc->fc_info[POWERCAP_FC_CAP].set_addr) {
391 struct scmi_fc_info *fci = &pc->fc_info[POWERCAP_FC_CAP];
393 iowrite32(power_cap, fci->set_addr);
394 ph->hops->fastchannel_db_ring(fci->set_db);
395 trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_CAP_SET,
396 domain_id, power_cap, 0);
400 return scmi_powercap_xfer_cap_set(ph, pc, power_cap, ignore_dresp);
403 static int scmi_powercap_xfer_pai_get(const struct scmi_protocol_handle *ph,
404 u32 domain_id, u32 *pai)
409 ret = ph->xops->xfer_get_init(ph, POWERCAP_PAI_GET, sizeof(u32),
414 put_unaligned_le32(domain_id, t->tx.buf);
415 ret = ph->xops->do_xfer(ph, t);
417 *pai = get_unaligned_le32(t->rx.buf);
419 ph->xops->xfer_put(ph, t);
424 static int scmi_powercap_pai_get(const struct scmi_protocol_handle *ph,
425 u32 domain_id, u32 *pai)
427 struct scmi_powercap_info *dom;
428 struct powercap_info *pi = ph->get_priv(ph);
430 if (!pai || domain_id >= pi->num_domains)
433 dom = pi->powercaps + domain_id;
434 if (dom->fc_info && dom->fc_info[POWERCAP_FC_PAI].get_addr) {
435 *pai = ioread32(dom->fc_info[POWERCAP_FC_PAI].get_addr);
436 trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_PAI_GET,
441 return scmi_powercap_xfer_pai_get(ph, domain_id, pai);
444 static int scmi_powercap_xfer_pai_set(const struct scmi_protocol_handle *ph,
445 u32 domain_id, u32 pai)
449 struct scmi_msg_powercap_set_cap_or_pai *msg;
451 ret = ph->xops->xfer_get_init(ph, POWERCAP_PAI_SET,
452 sizeof(*msg), 0, &t);
457 msg->domain = cpu_to_le32(domain_id);
458 msg->flags = cpu_to_le32(0);
459 msg->value = cpu_to_le32(pai);
461 ret = ph->xops->do_xfer(ph, t);
463 ph->xops->xfer_put(ph, t);
467 static int scmi_powercap_pai_set(const struct scmi_protocol_handle *ph,
468 u32 domain_id, u32 pai)
470 const struct scmi_powercap_info *pc;
472 pc = scmi_powercap_dom_info_get(ph, domain_id);
473 if (!pc || !pc->powercap_pai_config || !pai ||
474 pai < pc->min_pai || pai > pc->max_pai)
477 if (pc->fc_info && pc->fc_info[POWERCAP_FC_PAI].set_addr) {
478 struct scmi_fc_info *fci = &pc->fc_info[POWERCAP_FC_PAI];
480 trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_PAI_SET,
482 iowrite32(pai, fci->set_addr);
483 ph->hops->fastchannel_db_ring(fci->set_db);
487 return scmi_powercap_xfer_pai_set(ph, domain_id, pai);
490 static int scmi_powercap_measurements_get(const struct scmi_protocol_handle *ph,
491 u32 domain_id, u32 *average_power,
496 struct scmi_msg_resp_powercap_meas_get *resp;
497 const struct scmi_powercap_info *pc;
499 pc = scmi_powercap_dom_info_get(ph, domain_id);
500 if (!pc || !pc->powercap_monitoring || !pai || !average_power)
503 ret = ph->xops->xfer_get_init(ph, POWERCAP_MEASUREMENTS_GET,
504 sizeof(u32), sizeof(*resp), &t);
509 put_unaligned_le32(domain_id, t->tx.buf);
510 ret = ph->xops->do_xfer(ph, t);
512 *average_power = le32_to_cpu(resp->power);
513 *pai = le32_to_cpu(resp->pai);
516 ph->xops->xfer_put(ph, t);
521 scmi_powercap_measurements_threshold_get(const struct scmi_protocol_handle *ph,
522 u32 domain_id, u32 *power_thresh_low,
523 u32 *power_thresh_high)
525 struct powercap_info *pi = ph->get_priv(ph);
527 if (!power_thresh_low || !power_thresh_high ||
528 domain_id >= pi->num_domains)
531 *power_thresh_low = THRESH_LOW(pi, domain_id);
532 *power_thresh_high = THRESH_HIGH(pi, domain_id);
538 scmi_powercap_measurements_threshold_set(const struct scmi_protocol_handle *ph,
539 u32 domain_id, u32 power_thresh_low,
540 u32 power_thresh_high)
543 struct powercap_info *pi = ph->get_priv(ph);
545 if (domain_id >= pi->num_domains ||
546 power_thresh_low > power_thresh_high)
549 /* Anything to do ? */
550 if (THRESH_LOW(pi, domain_id) == power_thresh_low &&
551 THRESH_HIGH(pi, domain_id) == power_thresh_high)
554 pi->states[domain_id].thresholds =
555 (FIELD_PREP(GENMASK_ULL(31, 0), power_thresh_low) |
556 FIELD_PREP(GENMASK_ULL(63, 32), power_thresh_high));
558 /* Update thresholds if notification already enabled */
559 if (pi->states[domain_id].meas_notif_enabled)
560 ret = scmi_powercap_notify(ph, domain_id,
561 POWERCAP_MEASUREMENTS_NOTIFY,
567 static const struct scmi_powercap_proto_ops powercap_proto_ops = {
568 .num_domains_get = scmi_powercap_num_domains_get,
569 .info_get = scmi_powercap_dom_info_get,
570 .cap_get = scmi_powercap_cap_get,
571 .cap_set = scmi_powercap_cap_set,
572 .pai_get = scmi_powercap_pai_get,
573 .pai_set = scmi_powercap_pai_set,
574 .measurements_get = scmi_powercap_measurements_get,
575 .measurements_threshold_set = scmi_powercap_measurements_threshold_set,
576 .measurements_threshold_get = scmi_powercap_measurements_threshold_get,
579 static void scmi_powercap_domain_init_fc(const struct scmi_protocol_handle *ph,
580 u32 domain, struct scmi_fc_info **p_fc)
582 struct scmi_fc_info *fc;
584 fc = devm_kcalloc(ph->dev, POWERCAP_FC_MAX, sizeof(*fc), GFP_KERNEL);
588 ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
589 POWERCAP_CAP_SET, 4, domain,
590 &fc[POWERCAP_FC_CAP].set_addr,
591 &fc[POWERCAP_FC_CAP].set_db);
593 ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
594 POWERCAP_CAP_GET, 4, domain,
595 &fc[POWERCAP_FC_CAP].get_addr, NULL);
597 ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
598 POWERCAP_PAI_SET, 4, domain,
599 &fc[POWERCAP_FC_PAI].set_addr,
600 &fc[POWERCAP_FC_PAI].set_db);
602 ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
603 POWERCAP_PAI_GET, 4, domain,
604 &fc[POWERCAP_FC_PAI].get_addr, NULL);
609 static int scmi_powercap_notify(const struct scmi_protocol_handle *ph,
610 u32 domain, int message_id, bool enable)
615 switch (message_id) {
616 case POWERCAP_CAP_NOTIFY:
618 struct scmi_msg_powercap_notify_cap *notify;
620 ret = ph->xops->xfer_get_init(ph, message_id,
621 sizeof(*notify), 0, &t);
626 notify->domain = cpu_to_le32(domain);
627 notify->notify_enable = cpu_to_le32(enable ? BIT(0) : 0);
630 case POWERCAP_MEASUREMENTS_NOTIFY:
633 struct scmi_msg_powercap_notify_thresh *notify;
636 * Note that we have to pick the most recently configured
637 * thresholds to build a proper POWERCAP_MEASUREMENTS_NOTIFY
638 * enable request and we fail, complaining, if no thresholds
639 * were ever set, since this is an indication the API has been
642 ret = scmi_powercap_measurements_threshold_get(ph, domain,
647 if (enable && !low && !high) {
649 "Invalid Measurements Notify thresholds: %u/%u\n",
654 ret = ph->xops->xfer_get_init(ph, message_id,
655 sizeof(*notify), 0, &t);
660 notify->domain = cpu_to_le32(domain);
661 notify->notify_enable = cpu_to_le32(enable ? BIT(0) : 0);
662 notify->power_thresh_low = cpu_to_le32(low);
663 notify->power_thresh_high = cpu_to_le32(high);
670 ret = ph->xops->do_xfer(ph, t);
672 ph->xops->xfer_put(ph, t);
677 scmi_powercap_set_notify_enabled(const struct scmi_protocol_handle *ph,
678 u8 evt_id, u32 src_id, bool enable)
681 struct powercap_info *pi = ph->get_priv(ph);
683 if (evt_id >= ARRAY_SIZE(evt_2_cmd) || src_id >= pi->num_domains)
686 cmd_id = evt_2_cmd[evt_id];
687 ret = scmi_powercap_notify(ph, src_id, cmd_id, enable);
689 pr_debug("FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n",
690 evt_id, src_id, ret);
691 else if (cmd_id == POWERCAP_MEASUREMENTS_NOTIFY)
693 * On success save the current notification enabled state, so
694 * as to be able to properly update the notification thresholds
695 * when they are modified on a domain for which measurement
696 * notifications were currently enabled.
698 * This is needed because the SCMI Notification core machinery
699 * and API does not support passing per-notification custom
700 * arguments at callback registration time.
702 * Note that this can be done here with a simple flag since the
703 * SCMI core Notifications code takes care of keeping proper
704 * per-domain enables refcounting, so that this helper function
705 * will be called only once (for enables) when the first user
706 * registers a callback on this domain and once more (disable)
707 * when the last user de-registers its callback.
709 pi->states[src_id].meas_notif_enabled = enable;
715 scmi_powercap_fill_custom_report(const struct scmi_protocol_handle *ph,
716 u8 evt_id, ktime_t timestamp,
717 const void *payld, size_t payld_sz,
718 void *report, u32 *src_id)
723 case SCMI_EVENT_POWERCAP_CAP_CHANGED:
725 const struct scmi_powercap_cap_changed_notify_payld *p = payld;
726 struct scmi_powercap_cap_changed_report *r = report;
728 if (sizeof(*p) != payld_sz)
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;
740 case SCMI_EVENT_POWERCAP_MEASUREMENTS_CHANGED:
742 const struct scmi_powercap_meas_changed_notify_payld *p = payld;
743 struct scmi_powercap_meas_changed_report *r = report;
745 if (sizeof(*p) != payld_sz)
748 r->timestamp = timestamp;
749 r->agent_id = le32_to_cpu(p->agent_id);
750 r->domain_id = le32_to_cpu(p->domain_id);
751 r->power = le32_to_cpu(p->power);
752 *src_id = r->domain_id;
764 scmi_powercap_get_num_sources(const struct scmi_protocol_handle *ph)
766 struct powercap_info *pi = ph->get_priv(ph);
771 return pi->num_domains;
774 static const struct scmi_event powercap_events[] = {
776 .id = SCMI_EVENT_POWERCAP_CAP_CHANGED,
778 sizeof(struct scmi_powercap_cap_changed_notify_payld),
780 sizeof(struct scmi_powercap_cap_changed_report),
783 .id = SCMI_EVENT_POWERCAP_MEASUREMENTS_CHANGED,
785 sizeof(struct scmi_powercap_meas_changed_notify_payld),
787 sizeof(struct scmi_powercap_meas_changed_report),
791 static const struct scmi_event_ops powercap_event_ops = {
792 .get_num_sources = scmi_powercap_get_num_sources,
793 .set_notify_enabled = scmi_powercap_set_notify_enabled,
794 .fill_custom_report = scmi_powercap_fill_custom_report,
797 static const struct scmi_protocol_events powercap_protocol_events = {
798 .queue_sz = SCMI_PROTO_QUEUE_SZ,
799 .ops = &powercap_event_ops,
800 .evts = powercap_events,
801 .num_events = ARRAY_SIZE(powercap_events),
805 scmi_powercap_protocol_init(const struct scmi_protocol_handle *ph)
809 struct powercap_info *pinfo;
811 ret = ph->xops->version_get(ph, &version);
815 dev_dbg(ph->dev, "Powercap Version %d.%d\n",
816 PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
818 pinfo = devm_kzalloc(ph->dev, sizeof(*pinfo), GFP_KERNEL);
822 ret = scmi_powercap_attributes_get(ph, pinfo);
826 pinfo->powercaps = devm_kcalloc(ph->dev, pinfo->num_domains,
827 sizeof(*pinfo->powercaps),
829 if (!pinfo->powercaps)
833 * Note that any failure in retrieving any domain attribute leads to
834 * the whole Powercap protocol initialization failure: this way the
835 * reported Powercap domains are all assured, when accessed, to be well
836 * formed and correlated by sane parent-child relationship (if any).
838 for (domain = 0; domain < pinfo->num_domains; domain++) {
839 ret = scmi_powercap_domain_attributes_get(ph, pinfo, domain);
843 if (pinfo->powercaps[domain].fastchannels)
844 scmi_powercap_domain_init_fc(ph, domain,
845 &pinfo->powercaps[domain].fc_info);
848 pinfo->states = devm_kcalloc(ph->dev, pinfo->num_domains,
849 sizeof(*pinfo->states), GFP_KERNEL);
853 pinfo->version = version;
855 return ph->set_priv(ph, pinfo);
858 static const struct scmi_protocol scmi_powercap = {
859 .id = SCMI_PROTOCOL_POWERCAP,
860 .owner = THIS_MODULE,
861 .instance_init = &scmi_powercap_protocol_init,
862 .ops = &powercap_proto_ops,
863 .events = &powercap_protocol_events,
866 DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(powercap, scmi_powercap)