Lines Matching +full:p +full:- +full:states

1 // SPDX-License-Identifier: GPL-2.0
8 #define pr_fmt(fmt) "SCMI Notifications POWERCAP - " fmt
118 #define THRESH_LOW(p, id) \ argument
119 (lower_32_bits((p)->states[(id)].thresholds))
120 #define THRESH_HIGH(p, id) \ argument
121 (upper_32_bits((p)->states[(id)].thresholds))
129 struct scmi_powercap_state *states; member
148 ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, 0, in scmi_powercap_attributes_get()
153 ret = ph->xops->do_xfer(ph, t); in scmi_powercap_attributes_get()
157 attributes = get_unaligned_le32(t->rx.buf); in scmi_powercap_attributes_get()
158 pi->num_domains = FIELD_GET(GENMASK(15, 0), attributes); in scmi_powercap_attributes_get()
161 ph->xops->xfer_put(ph, t); in scmi_powercap_attributes_get()
164 if (!ph->hops->protocol_msg_check(ph, in scmi_powercap_attributes_get()
166 pi->notify_cap_cmd = true; in scmi_powercap_attributes_get()
168 if (!ph->hops->protocol_msg_check(ph, in scmi_powercap_attributes_get()
171 pi->notify_measurements_cmd = true; in scmi_powercap_attributes_get()
182 return -EPROTO; in scmi_powercap_validate()
186 return -EPROTO; in scmi_powercap_validate()
189 return -EPROTO; in scmi_powercap_validate()
201 struct scmi_powercap_info *dom_info = pinfo->powercaps + domain; in scmi_powercap_domain_attributes_get()
204 ret = ph->xops->xfer_get_init(ph, POWERCAP_DOMAIN_ATTRIBUTES, in scmi_powercap_domain_attributes_get()
209 put_unaligned_le32(domain, t->tx.buf); in scmi_powercap_domain_attributes_get()
210 resp = t->rx.buf; in scmi_powercap_domain_attributes_get()
212 ret = ph->xops->do_xfer(ph, t); in scmi_powercap_domain_attributes_get()
214 flags = le32_to_cpu(resp->attributes); in scmi_powercap_domain_attributes_get()
216 dom_info->id = domain; in scmi_powercap_domain_attributes_get()
217 if (pinfo->notify_cap_cmd) in scmi_powercap_domain_attributes_get()
218 dom_info->notify_powercap_cap_change = in scmi_powercap_domain_attributes_get()
220 if (pinfo->notify_measurements_cmd) in scmi_powercap_domain_attributes_get()
221 dom_info->notify_powercap_measurement_change = in scmi_powercap_domain_attributes_get()
223 dom_info->async_powercap_cap_set = in scmi_powercap_domain_attributes_get()
225 dom_info->powercap_cap_config = in scmi_powercap_domain_attributes_get()
227 dom_info->powercap_monitoring = in scmi_powercap_domain_attributes_get()
229 dom_info->powercap_pai_config = in scmi_powercap_domain_attributes_get()
231 dom_info->powercap_scale_mw = in scmi_powercap_domain_attributes_get()
233 dom_info->powercap_scale_uw = in scmi_powercap_domain_attributes_get()
235 dom_info->fastchannels = in scmi_powercap_domain_attributes_get()
238 strscpy(dom_info->name, resp->name, SCMI_SHORT_NAME_MAX_SIZE); in scmi_powercap_domain_attributes_get()
240 dom_info->min_pai = le32_to_cpu(resp->min_pai); in scmi_powercap_domain_attributes_get()
241 dom_info->max_pai = le32_to_cpu(resp->max_pai); in scmi_powercap_domain_attributes_get()
242 dom_info->pai_step = le32_to_cpu(resp->pai_step); in scmi_powercap_domain_attributes_get()
243 ret = scmi_powercap_validate(dom_info->min_pai, in scmi_powercap_domain_attributes_get()
244 dom_info->max_pai, in scmi_powercap_domain_attributes_get()
245 dom_info->pai_step, in scmi_powercap_domain_attributes_get()
246 dom_info->powercap_pai_config); in scmi_powercap_domain_attributes_get()
248 dev_err(ph->dev, in scmi_powercap_domain_attributes_get()
249 "Platform reported inconsistent PAI config for domain %d - %s\n", in scmi_powercap_domain_attributes_get()
250 dom_info->id, dom_info->name); in scmi_powercap_domain_attributes_get()
254 dom_info->min_power_cap = le32_to_cpu(resp->min_power_cap); in scmi_powercap_domain_attributes_get()
255 dom_info->max_power_cap = le32_to_cpu(resp->max_power_cap); in scmi_powercap_domain_attributes_get()
256 dom_info->power_cap_step = le32_to_cpu(resp->power_cap_step); in scmi_powercap_domain_attributes_get()
257 ret = scmi_powercap_validate(dom_info->min_power_cap, in scmi_powercap_domain_attributes_get()
258 dom_info->max_power_cap, in scmi_powercap_domain_attributes_get()
259 dom_info->power_cap_step, in scmi_powercap_domain_attributes_get()
260 dom_info->powercap_cap_config); in scmi_powercap_domain_attributes_get()
262 dev_err(ph->dev, in scmi_powercap_domain_attributes_get()
263 "Platform reported inconsistent CAP config for domain %d - %s\n", in scmi_powercap_domain_attributes_get()
264 dom_info->id, dom_info->name); in scmi_powercap_domain_attributes_get()
268 dom_info->sustainable_power = in scmi_powercap_domain_attributes_get()
269 le32_to_cpu(resp->sustainable_power); in scmi_powercap_domain_attributes_get()
270 dom_info->accuracy = le32_to_cpu(resp->accuracy); in scmi_powercap_domain_attributes_get()
272 dom_info->parent_id = le32_to_cpu(resp->parent_id); in scmi_powercap_domain_attributes_get()
273 if (dom_info->parent_id != SCMI_POWERCAP_ROOT_ZONE_ID && in scmi_powercap_domain_attributes_get()
274 (dom_info->parent_id >= pinfo->num_domains || in scmi_powercap_domain_attributes_get()
275 dom_info->parent_id == dom_info->id)) { in scmi_powercap_domain_attributes_get()
276 dev_err(ph->dev, in scmi_powercap_domain_attributes_get()
277 "Platform reported inconsistent parent ID for domain %d - %s\n", in scmi_powercap_domain_attributes_get()
278 dom_info->id, dom_info->name); in scmi_powercap_domain_attributes_get()
279 ret = -ENODEV; in scmi_powercap_domain_attributes_get()
284 ph->xops->xfer_put(ph, t); in scmi_powercap_domain_attributes_get()
291 ph->hops->extended_name_get(ph, POWERCAP_DOMAIN_NAME_GET, in scmi_powercap_domain_attributes_get()
292 domain, NULL, dom_info->name, in scmi_powercap_domain_attributes_get()
300 struct powercap_info *pi = ph->get_priv(ph); in scmi_powercap_num_domains_get()
302 return pi->num_domains; in scmi_powercap_num_domains_get()
308 struct powercap_info *pi = ph->get_priv(ph); in scmi_powercap_dom_info_get()
310 if (domain_id >= pi->num_domains) in scmi_powercap_dom_info_get()
313 return pi->powercaps + domain_id; in scmi_powercap_dom_info_get()
322 ret = ph->xops->xfer_get_init(ph, POWERCAP_CAP_GET, sizeof(u32), in scmi_powercap_xfer_cap_get()
327 put_unaligned_le32(domain_id, t->tx.buf); in scmi_powercap_xfer_cap_get()
328 ret = ph->xops->do_xfer(ph, t); in scmi_powercap_xfer_cap_get()
330 *power_cap = get_unaligned_le32(t->rx.buf); in scmi_powercap_xfer_cap_get()
332 ph->xops->xfer_put(ph, t); in scmi_powercap_xfer_cap_get()
341 if (dom->fc_info && dom->fc_info[POWERCAP_FC_CAP].get_addr) { in __scmi_powercap_cap_get()
342 *power_cap = ioread32(dom->fc_info[POWERCAP_FC_CAP].get_addr); in __scmi_powercap_cap_get()
344 dom->id, *power_cap, 0); in __scmi_powercap_cap_get()
348 return scmi_powercap_xfer_cap_get(ph, dom->id, power_cap); in __scmi_powercap_cap_get()
357 return -EINVAL; in scmi_powercap_cap_get()
361 return -EINVAL; in scmi_powercap_cap_get()
374 ret = ph->xops->xfer_get_init(ph, POWERCAP_CAP_SET, in scmi_powercap_xfer_cap_set()
379 msg = t->tx.buf; in scmi_powercap_xfer_cap_set()
380 msg->domain = cpu_to_le32(pc->id); in scmi_powercap_xfer_cap_set()
381 msg->flags = in scmi_powercap_xfer_cap_set()
382 cpu_to_le32(FIELD_PREP(CAP_SET_ASYNC, pc->async_powercap_cap_set) | in scmi_powercap_xfer_cap_set()
384 msg->value = cpu_to_le32(power_cap); in scmi_powercap_xfer_cap_set()
386 if (!pc->async_powercap_cap_set || ignore_dresp) { in scmi_powercap_xfer_cap_set()
387 ret = ph->xops->do_xfer(ph, t); in scmi_powercap_xfer_cap_set()
389 ret = ph->xops->do_xfer_with_response(ph, t); in scmi_powercap_xfer_cap_set()
393 resp = t->rx.buf; in scmi_powercap_xfer_cap_set()
394 if (le32_to_cpu(resp->domain) == pc->id) in scmi_powercap_xfer_cap_set()
395 dev_dbg(ph->dev, in scmi_powercap_xfer_cap_set()
397 pc->id, in scmi_powercap_xfer_cap_set()
398 get_unaligned_le32(&resp->power_cap)); in scmi_powercap_xfer_cap_set()
400 ret = -EPROTO; in scmi_powercap_xfer_cap_set()
404 ph->xops->xfer_put(ph, t); in scmi_powercap_xfer_cap_set()
412 int ret = -EINVAL; in __scmi_powercap_cap_set()
416 if (!pc || !pc->powercap_cap_config) in __scmi_powercap_cap_set()
420 (power_cap < pc->min_power_cap || power_cap > pc->max_power_cap)) in __scmi_powercap_cap_set()
423 if (pc->fc_info && pc->fc_info[POWERCAP_FC_CAP].set_addr) { in __scmi_powercap_cap_set()
424 struct scmi_fc_info *fci = &pc->fc_info[POWERCAP_FC_CAP]; in __scmi_powercap_cap_set()
426 iowrite32(power_cap, fci->set_addr); in __scmi_powercap_cap_set()
427 ph->hops->fastchannel_db_ring(fci->set_db); in __scmi_powercap_cap_set()
436 /* Save the last explicitly set non-zero powercap value */ in __scmi_powercap_cap_set()
437 if (PROTOCOL_REV_MAJOR(pi->version) >= 0x2 && !ret && power_cap) in __scmi_powercap_cap_set()
438 pi->states[domain_id].last_pcap = power_cap; in __scmi_powercap_cap_set()
447 struct powercap_info *pi = ph->get_priv(ph); in scmi_powercap_cap_set()
454 return -EINVAL; in scmi_powercap_cap_set()
457 if (PROTOCOL_REV_MAJOR(pi->version) >= 0x2 && in scmi_powercap_cap_set()
458 !pi->states[domain_id].enabled) { in scmi_powercap_cap_set()
459 pi->states[domain_id].last_pcap = power_cap; in scmi_powercap_cap_set()
473 ret = ph->xops->xfer_get_init(ph, POWERCAP_PAI_GET, sizeof(u32), in scmi_powercap_xfer_pai_get()
478 put_unaligned_le32(domain_id, t->tx.buf); in scmi_powercap_xfer_pai_get()
479 ret = ph->xops->do_xfer(ph, t); in scmi_powercap_xfer_pai_get()
481 *pai = get_unaligned_le32(t->rx.buf); in scmi_powercap_xfer_pai_get()
483 ph->xops->xfer_put(ph, t); in scmi_powercap_xfer_pai_get()
492 struct powercap_info *pi = ph->get_priv(ph); in scmi_powercap_pai_get()
494 if (!pai || domain_id >= pi->num_domains) in scmi_powercap_pai_get()
495 return -EINVAL; in scmi_powercap_pai_get()
497 dom = pi->powercaps + domain_id; in scmi_powercap_pai_get()
498 if (dom->fc_info && dom->fc_info[POWERCAP_FC_PAI].get_addr) { in scmi_powercap_pai_get()
499 *pai = ioread32(dom->fc_info[POWERCAP_FC_PAI].get_addr); in scmi_powercap_pai_get()
515 ret = ph->xops->xfer_get_init(ph, POWERCAP_PAI_SET, in scmi_powercap_xfer_pai_set()
520 msg = t->tx.buf; in scmi_powercap_xfer_pai_set()
521 msg->domain = cpu_to_le32(domain_id); in scmi_powercap_xfer_pai_set()
522 msg->flags = cpu_to_le32(0); in scmi_powercap_xfer_pai_set()
523 msg->value = cpu_to_le32(pai); in scmi_powercap_xfer_pai_set()
525 ret = ph->xops->do_xfer(ph, t); in scmi_powercap_xfer_pai_set()
527 ph->xops->xfer_put(ph, t); in scmi_powercap_xfer_pai_set()
537 if (!pc || !pc->powercap_pai_config || !pai || in scmi_powercap_pai_set()
538 pai < pc->min_pai || pai > pc->max_pai) in scmi_powercap_pai_set()
539 return -EINVAL; in scmi_powercap_pai_set()
541 if (pc->fc_info && pc->fc_info[POWERCAP_FC_PAI].set_addr) { in scmi_powercap_pai_set()
542 struct scmi_fc_info *fci = &pc->fc_info[POWERCAP_FC_PAI]; in scmi_powercap_pai_set()
546 iowrite32(pai, fci->set_addr); in scmi_powercap_pai_set()
547 ph->hops->fastchannel_db_ring(fci->set_db); in scmi_powercap_pai_set()
564 if (!pc || !pc->powercap_monitoring || !pai || !average_power) in scmi_powercap_measurements_get()
565 return -EINVAL; in scmi_powercap_measurements_get()
567 ret = ph->xops->xfer_get_init(ph, POWERCAP_MEASUREMENTS_GET, in scmi_powercap_measurements_get()
572 resp = t->rx.buf; in scmi_powercap_measurements_get()
573 put_unaligned_le32(domain_id, t->tx.buf); in scmi_powercap_measurements_get()
574 ret = ph->xops->do_xfer(ph, t); in scmi_powercap_measurements_get()
576 *average_power = le32_to_cpu(resp->power); in scmi_powercap_measurements_get()
577 *pai = le32_to_cpu(resp->pai); in scmi_powercap_measurements_get()
580 ph->xops->xfer_put(ph, t); in scmi_powercap_measurements_get()
589 struct powercap_info *pi = ph->get_priv(ph); in scmi_powercap_measurements_threshold_get()
592 domain_id >= pi->num_domains) in scmi_powercap_measurements_threshold_get()
593 return -EINVAL; in scmi_powercap_measurements_threshold_get()
607 struct powercap_info *pi = ph->get_priv(ph); in scmi_powercap_measurements_threshold_set()
609 if (domain_id >= pi->num_domains || in scmi_powercap_measurements_threshold_set()
611 return -EINVAL; in scmi_powercap_measurements_threshold_set()
618 pi->states[domain_id].thresholds = in scmi_powercap_measurements_threshold_set()
623 if (pi->states[domain_id].meas_notif_enabled) in scmi_powercap_measurements_threshold_set()
636 struct powercap_info *pi = ph->get_priv(ph); in scmi_powercap_cap_enable_set()
638 if (PROTOCOL_REV_MAJOR(pi->version) < 0x2) in scmi_powercap_cap_enable_set()
639 return -EINVAL; in scmi_powercap_cap_enable_set()
641 if (enable == pi->states[domain_id].enabled) in scmi_powercap_cap_enable_set()
646 if (!pi->states[domain_id].last_pcap) in scmi_powercap_cap_enable_set()
647 return -EINVAL; in scmi_powercap_cap_enable_set()
650 pi->states[domain_id].last_pcap, in scmi_powercap_cap_enable_set()
666 pi->states[domain_id].enabled = !!power_cap; in scmi_powercap_cap_enable_set()
676 struct powercap_info *pi = ph->get_priv(ph); in scmi_powercap_cap_enable_get()
679 if (PROTOCOL_REV_MAJOR(pi->version) < 0x2) in scmi_powercap_cap_enable_get()
691 pi->states[domain_id].enabled = *enable; in scmi_powercap_cap_enable_get()
715 fc = devm_kcalloc(ph->dev, POWERCAP_FC_MAX, sizeof(*fc), GFP_KERNEL); in scmi_powercap_domain_init_fc()
719 ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL, in scmi_powercap_domain_init_fc()
725 ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL, in scmi_powercap_domain_init_fc()
730 ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL, in scmi_powercap_domain_init_fc()
736 ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL, in scmi_powercap_domain_init_fc()
755 ret = ph->xops->xfer_get_init(ph, message_id, in scmi_powercap_notify()
760 notify = t->tx.buf; in scmi_powercap_notify()
761 notify->domain = cpu_to_le32(domain); in scmi_powercap_notify()
762 notify->notify_enable = cpu_to_le32(enable ? BIT(0) : 0); in scmi_powercap_notify()
783 dev_err(ph->dev, in scmi_powercap_notify()
786 return -EINVAL; in scmi_powercap_notify()
789 ret = ph->xops->xfer_get_init(ph, message_id, in scmi_powercap_notify()
794 notify = t->tx.buf; in scmi_powercap_notify()
795 notify->domain = cpu_to_le32(domain); in scmi_powercap_notify()
796 notify->notify_enable = cpu_to_le32(enable ? BIT(0) : 0); in scmi_powercap_notify()
797 notify->power_thresh_low = cpu_to_le32(low); in scmi_powercap_notify()
798 notify->power_thresh_high = cpu_to_le32(high); in scmi_powercap_notify()
802 return -EINVAL; in scmi_powercap_notify()
805 ret = ph->xops->do_xfer(ph, t); in scmi_powercap_notify()
807 ph->xops->xfer_put(ph, t); in scmi_powercap_notify()
817 struct powercap_info *pi = ph->get_priv(ph); in scmi_powercap_notify_supported()
819 if (evt_id >= ARRAY_SIZE(evt_2_cmd) || src_id >= pi->num_domains) in scmi_powercap_notify_supported()
822 dom_info = pi->powercaps + src_id; in scmi_powercap_notify_supported()
824 supported = dom_info->notify_powercap_cap_change; in scmi_powercap_notify_supported()
826 supported = dom_info->notify_powercap_measurement_change; in scmi_powercap_notify_supported()
836 struct powercap_info *pi = ph->get_priv(ph); in scmi_powercap_set_notify_enabled()
838 if (evt_id >= ARRAY_SIZE(evt_2_cmd) || src_id >= pi->num_domains) in scmi_powercap_set_notify_enabled()
839 return -EINVAL; in scmi_powercap_set_notify_enabled()
844 pr_debug("FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n", in scmi_powercap_set_notify_enabled()
854 * and API does not support passing per-notification custom in scmi_powercap_set_notify_enabled()
859 * per-domain enables refcounting, so that this helper function in scmi_powercap_set_notify_enabled()
862 * when the last user de-registers its callback. in scmi_powercap_set_notify_enabled()
864 pi->states[src_id].meas_notif_enabled = enable; in scmi_powercap_set_notify_enabled()
880 const struct scmi_powercap_cap_changed_notify_payld *p = payld; in scmi_powercap_fill_custom_report() local
883 if (sizeof(*p) != payld_sz) in scmi_powercap_fill_custom_report()
886 r->timestamp = timestamp; in scmi_powercap_fill_custom_report()
887 r->agent_id = le32_to_cpu(p->agent_id); in scmi_powercap_fill_custom_report()
888 r->domain_id = le32_to_cpu(p->domain_id); in scmi_powercap_fill_custom_report()
889 r->power_cap = le32_to_cpu(p->power_cap); in scmi_powercap_fill_custom_report()
890 r->pai = le32_to_cpu(p->pai); in scmi_powercap_fill_custom_report()
891 *src_id = r->domain_id; in scmi_powercap_fill_custom_report()
897 const struct scmi_powercap_meas_changed_notify_payld *p = payld; in scmi_powercap_fill_custom_report() local
900 if (sizeof(*p) != payld_sz) in scmi_powercap_fill_custom_report()
903 r->timestamp = timestamp; in scmi_powercap_fill_custom_report()
904 r->agent_id = le32_to_cpu(p->agent_id); in scmi_powercap_fill_custom_report()
905 r->domain_id = le32_to_cpu(p->domain_id); in scmi_powercap_fill_custom_report()
906 r->power = le32_to_cpu(p->power); in scmi_powercap_fill_custom_report()
907 *src_id = r->domain_id; in scmi_powercap_fill_custom_report()
921 struct powercap_info *pi = ph->get_priv(ph); in scmi_powercap_get_num_sources()
924 return -EINVAL; in scmi_powercap_get_num_sources()
926 return pi->num_domains; in scmi_powercap_get_num_sources()
967 ret = ph->xops->version_get(ph, &version); in scmi_powercap_protocol_init()
971 dev_dbg(ph->dev, "Powercap Version %d.%d\n", in scmi_powercap_protocol_init()
974 pinfo = devm_kzalloc(ph->dev, sizeof(*pinfo), GFP_KERNEL); in scmi_powercap_protocol_init()
976 return -ENOMEM; in scmi_powercap_protocol_init()
982 pinfo->powercaps = devm_kcalloc(ph->dev, pinfo->num_domains, in scmi_powercap_protocol_init()
983 sizeof(*pinfo->powercaps), in scmi_powercap_protocol_init()
985 if (!pinfo->powercaps) in scmi_powercap_protocol_init()
986 return -ENOMEM; in scmi_powercap_protocol_init()
988 pinfo->states = devm_kcalloc(ph->dev, pinfo->num_domains, in scmi_powercap_protocol_init()
989 sizeof(*pinfo->states), GFP_KERNEL); in scmi_powercap_protocol_init()
990 if (!pinfo->states) in scmi_powercap_protocol_init()
991 return -ENOMEM; in scmi_powercap_protocol_init()
997 * formed and correlated by sane parent-child relationship (if any). in scmi_powercap_protocol_init()
999 for (domain = 0; domain < pinfo->num_domains; domain++) { in scmi_powercap_protocol_init()
1004 if (pinfo->powercaps[domain].fastchannels) in scmi_powercap_protocol_init()
1006 &pinfo->powercaps[domain].fc_info); in scmi_powercap_protocol_init()
1011 &pinfo->powercaps[domain], in scmi_powercap_protocol_init()
1012 &pinfo->states[domain].last_pcap); in scmi_powercap_protocol_init()
1016 pinfo->states[domain].enabled = in scmi_powercap_protocol_init()
1017 !!pinfo->states[domain].last_pcap; in scmi_powercap_protocol_init()
1021 pinfo->version = version; in scmi_powercap_protocol_init()
1022 return ph->set_priv(ph, pinfo, version); in scmi_powercap_protocol_init()