Lines Matching +full:p +full:- +full:states
1 // SPDX-License-Identifier: GPL-2.0
8 #define pr_fmt(fmt) "SCMI Notifications POWERCAP - " fmt
115 #define THRESH_LOW(p, id) \ argument
116 (lower_32_bits((p)->states[(id)].thresholds))
117 #define THRESH_HIGH(p, id) \ argument
118 (upper_32_bits((p)->states[(id)].thresholds))
124 struct scmi_powercap_state *states; member
143 ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, 0, in scmi_powercap_attributes_get()
148 ret = ph->xops->do_xfer(ph, t); in scmi_powercap_attributes_get()
152 attributes = get_unaligned_le32(t->rx.buf); in scmi_powercap_attributes_get()
153 pi->num_domains = FIELD_GET(GENMASK(15, 0), attributes); in scmi_powercap_attributes_get()
156 ph->xops->xfer_put(ph, t); in scmi_powercap_attributes_get()
165 return -EPROTO; in scmi_powercap_validate()
169 return -EPROTO; in scmi_powercap_validate()
172 return -EPROTO; in scmi_powercap_validate()
184 struct scmi_powercap_info *dom_info = pinfo->powercaps + domain; in scmi_powercap_domain_attributes_get()
187 ret = ph->xops->xfer_get_init(ph, POWERCAP_DOMAIN_ATTRIBUTES, in scmi_powercap_domain_attributes_get()
192 put_unaligned_le32(domain, t->tx.buf); in scmi_powercap_domain_attributes_get()
193 resp = t->rx.buf; in scmi_powercap_domain_attributes_get()
195 ret = ph->xops->do_xfer(ph, t); in scmi_powercap_domain_attributes_get()
197 flags = le32_to_cpu(resp->attributes); in scmi_powercap_domain_attributes_get()
199 dom_info->id = domain; in scmi_powercap_domain_attributes_get()
200 dom_info->notify_powercap_cap_change = in scmi_powercap_domain_attributes_get()
202 dom_info->notify_powercap_measurement_change = in scmi_powercap_domain_attributes_get()
204 dom_info->async_powercap_cap_set = in scmi_powercap_domain_attributes_get()
206 dom_info->powercap_cap_config = in scmi_powercap_domain_attributes_get()
208 dom_info->powercap_monitoring = in scmi_powercap_domain_attributes_get()
210 dom_info->powercap_pai_config = in scmi_powercap_domain_attributes_get()
212 dom_info->powercap_scale_mw = in scmi_powercap_domain_attributes_get()
214 dom_info->powercap_scale_uw = in scmi_powercap_domain_attributes_get()
216 dom_info->fastchannels = in scmi_powercap_domain_attributes_get()
219 strscpy(dom_info->name, resp->name, SCMI_SHORT_NAME_MAX_SIZE); in scmi_powercap_domain_attributes_get()
221 dom_info->min_pai = le32_to_cpu(resp->min_pai); in scmi_powercap_domain_attributes_get()
222 dom_info->max_pai = le32_to_cpu(resp->max_pai); in scmi_powercap_domain_attributes_get()
223 dom_info->pai_step = le32_to_cpu(resp->pai_step); in scmi_powercap_domain_attributes_get()
224 ret = scmi_powercap_validate(dom_info->min_pai, in scmi_powercap_domain_attributes_get()
225 dom_info->max_pai, in scmi_powercap_domain_attributes_get()
226 dom_info->pai_step, in scmi_powercap_domain_attributes_get()
227 dom_info->powercap_pai_config); in scmi_powercap_domain_attributes_get()
229 dev_err(ph->dev, in scmi_powercap_domain_attributes_get()
230 "Platform reported inconsistent PAI config for domain %d - %s\n", in scmi_powercap_domain_attributes_get()
231 dom_info->id, dom_info->name); in scmi_powercap_domain_attributes_get()
235 dom_info->min_power_cap = le32_to_cpu(resp->min_power_cap); in scmi_powercap_domain_attributes_get()
236 dom_info->max_power_cap = le32_to_cpu(resp->max_power_cap); in scmi_powercap_domain_attributes_get()
237 dom_info->power_cap_step = le32_to_cpu(resp->power_cap_step); in scmi_powercap_domain_attributes_get()
238 ret = scmi_powercap_validate(dom_info->min_power_cap, in scmi_powercap_domain_attributes_get()
239 dom_info->max_power_cap, in scmi_powercap_domain_attributes_get()
240 dom_info->power_cap_step, in scmi_powercap_domain_attributes_get()
241 dom_info->powercap_cap_config); in scmi_powercap_domain_attributes_get()
243 dev_err(ph->dev, in scmi_powercap_domain_attributes_get()
244 "Platform reported inconsistent CAP config for domain %d - %s\n", in scmi_powercap_domain_attributes_get()
245 dom_info->id, dom_info->name); in scmi_powercap_domain_attributes_get()
249 dom_info->sustainable_power = in scmi_powercap_domain_attributes_get()
250 le32_to_cpu(resp->sustainable_power); in scmi_powercap_domain_attributes_get()
251 dom_info->accuracy = le32_to_cpu(resp->accuracy); in scmi_powercap_domain_attributes_get()
253 dom_info->parent_id = le32_to_cpu(resp->parent_id); in scmi_powercap_domain_attributes_get()
254 if (dom_info->parent_id != SCMI_POWERCAP_ROOT_ZONE_ID && in scmi_powercap_domain_attributes_get()
255 (dom_info->parent_id >= pinfo->num_domains || in scmi_powercap_domain_attributes_get()
256 dom_info->parent_id == dom_info->id)) { in scmi_powercap_domain_attributes_get()
257 dev_err(ph->dev, in scmi_powercap_domain_attributes_get()
258 "Platform reported inconsistent parent ID for domain %d - %s\n", in scmi_powercap_domain_attributes_get()
259 dom_info->id, dom_info->name); in scmi_powercap_domain_attributes_get()
260 ret = -ENODEV; in scmi_powercap_domain_attributes_get()
265 ph->xops->xfer_put(ph, t); in scmi_powercap_domain_attributes_get()
272 ph->hops->extended_name_get(ph, POWERCAP_DOMAIN_NAME_GET, in scmi_powercap_domain_attributes_get()
273 domain, dom_info->name, in scmi_powercap_domain_attributes_get()
281 struct powercap_info *pi = ph->get_priv(ph); in scmi_powercap_num_domains_get()
283 return pi->num_domains; in scmi_powercap_num_domains_get()
289 struct powercap_info *pi = ph->get_priv(ph); in scmi_powercap_dom_info_get()
291 if (domain_id >= pi->num_domains) in scmi_powercap_dom_info_get()
294 return pi->powercaps + domain_id; in scmi_powercap_dom_info_get()
303 ret = ph->xops->xfer_get_init(ph, POWERCAP_CAP_GET, sizeof(u32), in scmi_powercap_xfer_cap_get()
308 put_unaligned_le32(domain_id, t->tx.buf); in scmi_powercap_xfer_cap_get()
309 ret = ph->xops->do_xfer(ph, t); in scmi_powercap_xfer_cap_get()
311 *power_cap = get_unaligned_le32(t->rx.buf); in scmi_powercap_xfer_cap_get()
313 ph->xops->xfer_put(ph, t); in scmi_powercap_xfer_cap_get()
322 if (dom->fc_info && dom->fc_info[POWERCAP_FC_CAP].get_addr) { in __scmi_powercap_cap_get()
323 *power_cap = ioread32(dom->fc_info[POWERCAP_FC_CAP].get_addr); in __scmi_powercap_cap_get()
325 dom->id, *power_cap, 0); in __scmi_powercap_cap_get()
329 return scmi_powercap_xfer_cap_get(ph, dom->id, power_cap); in __scmi_powercap_cap_get()
338 return -EINVAL; in scmi_powercap_cap_get()
342 return -EINVAL; in scmi_powercap_cap_get()
355 ret = ph->xops->xfer_get_init(ph, POWERCAP_CAP_SET, in scmi_powercap_xfer_cap_set()
360 msg = t->tx.buf; in scmi_powercap_xfer_cap_set()
361 msg->domain = cpu_to_le32(pc->id); in scmi_powercap_xfer_cap_set()
362 msg->flags = in scmi_powercap_xfer_cap_set()
363 cpu_to_le32(FIELD_PREP(CAP_SET_ASYNC, !!pc->async_powercap_cap_set) | in scmi_powercap_xfer_cap_set()
365 msg->value = cpu_to_le32(power_cap); in scmi_powercap_xfer_cap_set()
367 if (!pc->async_powercap_cap_set || ignore_dresp) { in scmi_powercap_xfer_cap_set()
368 ret = ph->xops->do_xfer(ph, t); in scmi_powercap_xfer_cap_set()
370 ret = ph->xops->do_xfer_with_response(ph, t); in scmi_powercap_xfer_cap_set()
374 resp = t->rx.buf; in scmi_powercap_xfer_cap_set()
375 if (le32_to_cpu(resp->domain) == pc->id) in scmi_powercap_xfer_cap_set()
376 dev_dbg(ph->dev, in scmi_powercap_xfer_cap_set()
378 pc->id, in scmi_powercap_xfer_cap_set()
379 get_unaligned_le32(&resp->power_cap)); in scmi_powercap_xfer_cap_set()
381 ret = -EPROTO; in scmi_powercap_xfer_cap_set()
385 ph->xops->xfer_put(ph, t); in scmi_powercap_xfer_cap_set()
393 int ret = -EINVAL; in __scmi_powercap_cap_set()
397 if (!pc || !pc->powercap_cap_config) in __scmi_powercap_cap_set()
401 (power_cap < pc->min_power_cap || power_cap > pc->max_power_cap)) in __scmi_powercap_cap_set()
404 if (pc->fc_info && pc->fc_info[POWERCAP_FC_CAP].set_addr) { in __scmi_powercap_cap_set()
405 struct scmi_fc_info *fci = &pc->fc_info[POWERCAP_FC_CAP]; in __scmi_powercap_cap_set()
407 iowrite32(power_cap, fci->set_addr); in __scmi_powercap_cap_set()
408 ph->hops->fastchannel_db_ring(fci->set_db); in __scmi_powercap_cap_set()
417 /* Save the last explicitly set non-zero powercap value */ in __scmi_powercap_cap_set()
418 if (PROTOCOL_REV_MAJOR(pi->version) >= 0x2 && !ret && power_cap) in __scmi_powercap_cap_set()
419 pi->states[domain_id].last_pcap = power_cap; in __scmi_powercap_cap_set()
428 struct powercap_info *pi = ph->get_priv(ph); in scmi_powercap_cap_set()
435 return -EINVAL; in scmi_powercap_cap_set()
438 if (PROTOCOL_REV_MAJOR(pi->version) >= 0x2 && in scmi_powercap_cap_set()
439 !pi->states[domain_id].enabled) { in scmi_powercap_cap_set()
440 pi->states[domain_id].last_pcap = power_cap; in scmi_powercap_cap_set()
454 ret = ph->xops->xfer_get_init(ph, POWERCAP_PAI_GET, sizeof(u32), in scmi_powercap_xfer_pai_get()
459 put_unaligned_le32(domain_id, t->tx.buf); in scmi_powercap_xfer_pai_get()
460 ret = ph->xops->do_xfer(ph, t); in scmi_powercap_xfer_pai_get()
462 *pai = get_unaligned_le32(t->rx.buf); in scmi_powercap_xfer_pai_get()
464 ph->xops->xfer_put(ph, t); in scmi_powercap_xfer_pai_get()
473 struct powercap_info *pi = ph->get_priv(ph); in scmi_powercap_pai_get()
475 if (!pai || domain_id >= pi->num_domains) in scmi_powercap_pai_get()
476 return -EINVAL; in scmi_powercap_pai_get()
478 dom = pi->powercaps + domain_id; in scmi_powercap_pai_get()
479 if (dom->fc_info && dom->fc_info[POWERCAP_FC_PAI].get_addr) { in scmi_powercap_pai_get()
480 *pai = ioread32(dom->fc_info[POWERCAP_FC_PAI].get_addr); in scmi_powercap_pai_get()
496 ret = ph->xops->xfer_get_init(ph, POWERCAP_PAI_SET, in scmi_powercap_xfer_pai_set()
501 msg = t->tx.buf; in scmi_powercap_xfer_pai_set()
502 msg->domain = cpu_to_le32(domain_id); in scmi_powercap_xfer_pai_set()
503 msg->flags = cpu_to_le32(0); in scmi_powercap_xfer_pai_set()
504 msg->value = cpu_to_le32(pai); in scmi_powercap_xfer_pai_set()
506 ret = ph->xops->do_xfer(ph, t); in scmi_powercap_xfer_pai_set()
508 ph->xops->xfer_put(ph, t); in scmi_powercap_xfer_pai_set()
518 if (!pc || !pc->powercap_pai_config || !pai || in scmi_powercap_pai_set()
519 pai < pc->min_pai || pai > pc->max_pai) in scmi_powercap_pai_set()
520 return -EINVAL; in scmi_powercap_pai_set()
522 if (pc->fc_info && pc->fc_info[POWERCAP_FC_PAI].set_addr) { in scmi_powercap_pai_set()
523 struct scmi_fc_info *fci = &pc->fc_info[POWERCAP_FC_PAI]; in scmi_powercap_pai_set()
527 iowrite32(pai, fci->set_addr); in scmi_powercap_pai_set()
528 ph->hops->fastchannel_db_ring(fci->set_db); in scmi_powercap_pai_set()
545 if (!pc || !pc->powercap_monitoring || !pai || !average_power) in scmi_powercap_measurements_get()
546 return -EINVAL; in scmi_powercap_measurements_get()
548 ret = ph->xops->xfer_get_init(ph, POWERCAP_MEASUREMENTS_GET, in scmi_powercap_measurements_get()
553 resp = t->rx.buf; in scmi_powercap_measurements_get()
554 put_unaligned_le32(domain_id, t->tx.buf); in scmi_powercap_measurements_get()
555 ret = ph->xops->do_xfer(ph, t); in scmi_powercap_measurements_get()
557 *average_power = le32_to_cpu(resp->power); in scmi_powercap_measurements_get()
558 *pai = le32_to_cpu(resp->pai); in scmi_powercap_measurements_get()
561 ph->xops->xfer_put(ph, t); in scmi_powercap_measurements_get()
570 struct powercap_info *pi = ph->get_priv(ph); in scmi_powercap_measurements_threshold_get()
573 domain_id >= pi->num_domains) in scmi_powercap_measurements_threshold_get()
574 return -EINVAL; in scmi_powercap_measurements_threshold_get()
588 struct powercap_info *pi = ph->get_priv(ph); in scmi_powercap_measurements_threshold_set()
590 if (domain_id >= pi->num_domains || in scmi_powercap_measurements_threshold_set()
592 return -EINVAL; in scmi_powercap_measurements_threshold_set()
599 pi->states[domain_id].thresholds = in scmi_powercap_measurements_threshold_set()
604 if (pi->states[domain_id].meas_notif_enabled) in scmi_powercap_measurements_threshold_set()
617 struct powercap_info *pi = ph->get_priv(ph); in scmi_powercap_cap_enable_set()
619 if (PROTOCOL_REV_MAJOR(pi->version) < 0x2) in scmi_powercap_cap_enable_set()
620 return -EINVAL; in scmi_powercap_cap_enable_set()
622 if (enable == pi->states[domain_id].enabled) in scmi_powercap_cap_enable_set()
627 if (!pi->states[domain_id].last_pcap) in scmi_powercap_cap_enable_set()
628 return -EINVAL; in scmi_powercap_cap_enable_set()
631 pi->states[domain_id].last_pcap, in scmi_powercap_cap_enable_set()
647 pi->states[domain_id].enabled = !!power_cap; in scmi_powercap_cap_enable_set()
657 struct powercap_info *pi = ph->get_priv(ph); in scmi_powercap_cap_enable_get()
660 if (PROTOCOL_REV_MAJOR(pi->version) < 0x2) in scmi_powercap_cap_enable_get()
672 pi->states[domain_id].enabled = *enable; in scmi_powercap_cap_enable_get()
696 fc = devm_kcalloc(ph->dev, POWERCAP_FC_MAX, sizeof(*fc), GFP_KERNEL); in scmi_powercap_domain_init_fc()
700 ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL, in scmi_powercap_domain_init_fc()
705 ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL, in scmi_powercap_domain_init_fc()
709 ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL, in scmi_powercap_domain_init_fc()
714 ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL, in scmi_powercap_domain_init_fc()
732 ret = ph->xops->xfer_get_init(ph, message_id, in scmi_powercap_notify()
737 notify = t->tx.buf; in scmi_powercap_notify()
738 notify->domain = cpu_to_le32(domain); in scmi_powercap_notify()
739 notify->notify_enable = cpu_to_le32(enable ? BIT(0) : 0); in scmi_powercap_notify()
760 dev_err(ph->dev, in scmi_powercap_notify()
763 return -EINVAL; in scmi_powercap_notify()
766 ret = ph->xops->xfer_get_init(ph, message_id, in scmi_powercap_notify()
771 notify = t->tx.buf; in scmi_powercap_notify()
772 notify->domain = cpu_to_le32(domain); in scmi_powercap_notify()
773 notify->notify_enable = cpu_to_le32(enable ? BIT(0) : 0); in scmi_powercap_notify()
774 notify->power_thresh_low = cpu_to_le32(low); in scmi_powercap_notify()
775 notify->power_thresh_high = cpu_to_le32(high); in scmi_powercap_notify()
779 return -EINVAL; in scmi_powercap_notify()
782 ret = ph->xops->do_xfer(ph, t); in scmi_powercap_notify()
784 ph->xops->xfer_put(ph, t); in scmi_powercap_notify()
793 struct powercap_info *pi = ph->get_priv(ph); in scmi_powercap_set_notify_enabled()
795 if (evt_id >= ARRAY_SIZE(evt_2_cmd) || src_id >= pi->num_domains) in scmi_powercap_set_notify_enabled()
796 return -EINVAL; in scmi_powercap_set_notify_enabled()
801 pr_debug("FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n", in scmi_powercap_set_notify_enabled()
811 * and API does not support passing per-notification custom in scmi_powercap_set_notify_enabled()
816 * per-domain enables refcounting, so that this helper function in scmi_powercap_set_notify_enabled()
819 * when the last user de-registers its callback. in scmi_powercap_set_notify_enabled()
821 pi->states[src_id].meas_notif_enabled = enable; in scmi_powercap_set_notify_enabled()
837 const struct scmi_powercap_cap_changed_notify_payld *p = payld; in scmi_powercap_fill_custom_report() local
840 if (sizeof(*p) != payld_sz) in scmi_powercap_fill_custom_report()
843 r->timestamp = timestamp; in scmi_powercap_fill_custom_report()
844 r->agent_id = le32_to_cpu(p->agent_id); in scmi_powercap_fill_custom_report()
845 r->domain_id = le32_to_cpu(p->domain_id); in scmi_powercap_fill_custom_report()
846 r->power_cap = le32_to_cpu(p->power_cap); in scmi_powercap_fill_custom_report()
847 r->pai = le32_to_cpu(p->pai); in scmi_powercap_fill_custom_report()
848 *src_id = r->domain_id; in scmi_powercap_fill_custom_report()
854 const struct scmi_powercap_meas_changed_notify_payld *p = payld; in scmi_powercap_fill_custom_report() local
857 if (sizeof(*p) != payld_sz) in scmi_powercap_fill_custom_report()
860 r->timestamp = timestamp; in scmi_powercap_fill_custom_report()
861 r->agent_id = le32_to_cpu(p->agent_id); in scmi_powercap_fill_custom_report()
862 r->domain_id = le32_to_cpu(p->domain_id); in scmi_powercap_fill_custom_report()
863 r->power = le32_to_cpu(p->power); in scmi_powercap_fill_custom_report()
864 *src_id = r->domain_id; in scmi_powercap_fill_custom_report()
878 struct powercap_info *pi = ph->get_priv(ph); in scmi_powercap_get_num_sources()
881 return -EINVAL; in scmi_powercap_get_num_sources()
883 return pi->num_domains; in scmi_powercap_get_num_sources()
923 ret = ph->xops->version_get(ph, &version); in scmi_powercap_protocol_init()
927 dev_dbg(ph->dev, "Powercap Version %d.%d\n", in scmi_powercap_protocol_init()
930 pinfo = devm_kzalloc(ph->dev, sizeof(*pinfo), GFP_KERNEL); in scmi_powercap_protocol_init()
932 return -ENOMEM; in scmi_powercap_protocol_init()
938 pinfo->powercaps = devm_kcalloc(ph->dev, pinfo->num_domains, in scmi_powercap_protocol_init()
939 sizeof(*pinfo->powercaps), in scmi_powercap_protocol_init()
941 if (!pinfo->powercaps) in scmi_powercap_protocol_init()
942 return -ENOMEM; in scmi_powercap_protocol_init()
944 pinfo->states = devm_kcalloc(ph->dev, pinfo->num_domains, in scmi_powercap_protocol_init()
945 sizeof(*pinfo->states), GFP_KERNEL); in scmi_powercap_protocol_init()
946 if (!pinfo->states) in scmi_powercap_protocol_init()
947 return -ENOMEM; in scmi_powercap_protocol_init()
953 * formed and correlated by sane parent-child relationship (if any). in scmi_powercap_protocol_init()
955 for (domain = 0; domain < pinfo->num_domains; domain++) { in scmi_powercap_protocol_init()
960 if (pinfo->powercaps[domain].fastchannels) in scmi_powercap_protocol_init()
962 &pinfo->powercaps[domain].fc_info); in scmi_powercap_protocol_init()
967 &pinfo->powercaps[domain], in scmi_powercap_protocol_init()
968 &pinfo->states[domain].last_pcap); in scmi_powercap_protocol_init()
972 pinfo->states[domain].enabled = in scmi_powercap_protocol_init()
973 !!pinfo->states[domain].last_pcap; in scmi_powercap_protocol_init()
977 pinfo->version = version; in scmi_powercap_protocol_init()
978 return ph->set_priv(ph, pinfo); in scmi_powercap_protocol_init()