Lines Matching +full:opp +full:- +full:level
1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright (C) 2018-2022 ARM Ltd.
8 #define pr_fmt(fmt) "SCMI Notifications PERF - " fmt
93 __le32 level; member
122 } opp[]; member
136 struct scmi_opp opp[MAX_OPPS]; member
161 ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, 0, in scmi_perf_attributes_get()
166 attr = t->rx.buf; in scmi_perf_attributes_get()
168 ret = ph->xops->do_xfer(ph, t); in scmi_perf_attributes_get()
170 u16 flags = le16_to_cpu(attr->flags); in scmi_perf_attributes_get()
172 pi->num_domains = le16_to_cpu(attr->num_domains); in scmi_perf_attributes_get()
175 pi->power_scale = SCMI_POWER_MILLIWATTS; in scmi_perf_attributes_get()
176 if (PROTOCOL_REV_MAJOR(pi->version) >= 0x3) in scmi_perf_attributes_get()
178 pi->power_scale = SCMI_POWER_MICROWATTS; in scmi_perf_attributes_get()
180 pi->stats_addr = le32_to_cpu(attr->stats_addr_low) | in scmi_perf_attributes_get()
181 (u64)le32_to_cpu(attr->stats_addr_high) << 32; in scmi_perf_attributes_get()
182 pi->stats_size = le32_to_cpu(attr->stats_size); in scmi_perf_attributes_get()
185 ph->xops->xfer_put(ph, t); in scmi_perf_attributes_get()
199 ret = ph->xops->xfer_get_init(ph, PERF_DOMAIN_ATTRIBUTES, in scmi_perf_domain_attributes_get()
204 put_unaligned_le32(domain, t->tx.buf); in scmi_perf_domain_attributes_get()
205 attr = t->rx.buf; in scmi_perf_domain_attributes_get()
207 ret = ph->xops->do_xfer(ph, t); in scmi_perf_domain_attributes_get()
209 flags = le32_to_cpu(attr->flags); in scmi_perf_domain_attributes_get()
211 dom_info->set_limits = SUPPORTS_SET_LIMITS(flags); in scmi_perf_domain_attributes_get()
212 dom_info->set_perf = SUPPORTS_SET_PERF_LVL(flags); in scmi_perf_domain_attributes_get()
213 dom_info->perf_limit_notify = SUPPORTS_PERF_LIMIT_NOTIFY(flags); in scmi_perf_domain_attributes_get()
214 dom_info->perf_level_notify = SUPPORTS_PERF_LEVEL_NOTIFY(flags); in scmi_perf_domain_attributes_get()
215 dom_info->perf_fastchannels = SUPPORTS_PERF_FASTCHANNELS(flags); in scmi_perf_domain_attributes_get()
216 dom_info->sustained_freq_khz = in scmi_perf_domain_attributes_get()
217 le32_to_cpu(attr->sustained_freq_khz); in scmi_perf_domain_attributes_get()
218 dom_info->sustained_perf_level = in scmi_perf_domain_attributes_get()
219 le32_to_cpu(attr->sustained_perf_level); in scmi_perf_domain_attributes_get()
220 if (!dom_info->sustained_freq_khz || in scmi_perf_domain_attributes_get()
221 !dom_info->sustained_perf_level) in scmi_perf_domain_attributes_get()
223 dom_info->mult_factor = 1000; in scmi_perf_domain_attributes_get()
225 dom_info->mult_factor = in scmi_perf_domain_attributes_get()
226 (dom_info->sustained_freq_khz * 1000) / in scmi_perf_domain_attributes_get()
227 dom_info->sustained_perf_level; in scmi_perf_domain_attributes_get()
228 strscpy(dom_info->name, attr->name, SCMI_SHORT_NAME_MAX_SIZE); in scmi_perf_domain_attributes_get()
231 ph->xops->xfer_put(ph, t); in scmi_perf_domain_attributes_get()
239 ph->hops->extended_name_get(ph, PERF_DOMAIN_NAME_GET, domain, in scmi_perf_domain_attributes_get()
240 dom_info->name, SCMI_MAX_STR_SIZE); in scmi_perf_domain_attributes_get()
249 return t1->perf - t2->perf; in opp_cmp_func()
264 msg->domain = cpu_to_le32(p->domain); in iter_perf_levels_prepare_message()
266 msg->level_index = cpu_to_le32(desc_index); in iter_perf_levels_prepare_message()
274 st->num_returned = le16_to_cpu(r->num_returned); in iter_perf_levels_update_state()
275 st->num_remaining = le16_to_cpu(r->num_remaining); in iter_perf_levels_update_state()
285 struct scmi_opp *opp; in iter_perf_levels_process_response() local
289 opp = &p->perf_dom->opp[st->desc_index + st->loop_idx]; in iter_perf_levels_process_response()
290 opp->perf = le32_to_cpu(r->opp[st->loop_idx].perf_val); in iter_perf_levels_process_response()
291 opp->power = le32_to_cpu(r->opp[st->loop_idx].power); in iter_perf_levels_process_response()
292 opp->trans_latency_us = in iter_perf_levels_process_response()
293 le16_to_cpu(r->opp[st->loop_idx].transition_latency_us); in iter_perf_levels_process_response()
294 p->perf_dom->opp_count++; in iter_perf_levels_process_response()
296 dev_dbg(ph->dev, "Level %d Power %d Latency %dus\n", in iter_perf_levels_process_response()
297 opp->perf, opp->power, opp->trans_latency_us); in iter_perf_levels_process_response()
318 iter = ph->hops->iter_response_init(ph, &ops, MAX_OPPS, in scmi_perf_describe_levels_get()
325 ret = ph->hops->iter_response_run(iter); in scmi_perf_describe_levels_get()
329 if (perf_dom->opp_count) in scmi_perf_describe_levels_get()
330 sort(perf_dom->opp, perf_dom->opp_count, in scmi_perf_describe_levels_get()
343 ret = ph->xops->xfer_get_init(ph, PERF_LIMITS_SET, in scmi_perf_mb_limits_set()
348 limits = t->tx.buf; in scmi_perf_mb_limits_set()
349 limits->domain = cpu_to_le32(domain); in scmi_perf_mb_limits_set()
350 limits->max_level = cpu_to_le32(max_perf); in scmi_perf_mb_limits_set()
351 limits->min_level = cpu_to_le32(min_perf); in scmi_perf_mb_limits_set()
353 ret = ph->xops->do_xfer(ph, t); in scmi_perf_mb_limits_set()
355 ph->xops->xfer_put(ph, t); in scmi_perf_mb_limits_set()
362 struct scmi_perf_info *pi = ph->get_priv(ph); in scmi_perf_limits_set()
363 struct perf_dom_info *dom = pi->dom_info + domain; in scmi_perf_limits_set()
365 if (PROTOCOL_REV_MAJOR(pi->version) >= 0x3 && !max_perf && !min_perf) in scmi_perf_limits_set()
366 return -EINVAL; in scmi_perf_limits_set()
368 if (dom->fc_info && dom->fc_info[PERF_FC_LIMIT].set_addr) { in scmi_perf_limits_set()
369 struct scmi_fc_info *fci = &dom->fc_info[PERF_FC_LIMIT]; in scmi_perf_limits_set()
373 iowrite32(max_perf, fci->set_addr); in scmi_perf_limits_set()
374 iowrite32(min_perf, fci->set_addr + 4); in scmi_perf_limits_set()
375 ph->hops->fastchannel_db_ring(fci->set_db); in scmi_perf_limits_set()
389 ret = ph->xops->xfer_get_init(ph, PERF_LIMITS_GET, in scmi_perf_mb_limits_get()
394 put_unaligned_le32(domain, t->tx.buf); in scmi_perf_mb_limits_get()
396 ret = ph->xops->do_xfer(ph, t); in scmi_perf_mb_limits_get()
398 limits = t->rx.buf; in scmi_perf_mb_limits_get()
400 *max_perf = le32_to_cpu(limits->max_level); in scmi_perf_mb_limits_get()
401 *min_perf = le32_to_cpu(limits->min_level); in scmi_perf_mb_limits_get()
404 ph->xops->xfer_put(ph, t); in scmi_perf_mb_limits_get()
411 struct scmi_perf_info *pi = ph->get_priv(ph); in scmi_perf_limits_get()
412 struct perf_dom_info *dom = pi->dom_info + domain; in scmi_perf_limits_get()
414 if (dom->fc_info && dom->fc_info[PERF_FC_LIMIT].get_addr) { in scmi_perf_limits_get()
415 struct scmi_fc_info *fci = &dom->fc_info[PERF_FC_LIMIT]; in scmi_perf_limits_get()
417 *max_perf = ioread32(fci->get_addr); in scmi_perf_limits_get()
418 *min_perf = ioread32(fci->get_addr + 4); in scmi_perf_limits_get()
428 u32 domain, u32 level, bool poll) in scmi_perf_mb_level_set() argument
434 ret = ph->xops->xfer_get_init(ph, PERF_LEVEL_SET, sizeof(*lvl), 0, &t); in scmi_perf_mb_level_set()
438 t->hdr.poll_completion = poll; in scmi_perf_mb_level_set()
439 lvl = t->tx.buf; in scmi_perf_mb_level_set()
440 lvl->domain = cpu_to_le32(domain); in scmi_perf_mb_level_set()
441 lvl->level = cpu_to_le32(level); in scmi_perf_mb_level_set()
443 ret = ph->xops->do_xfer(ph, t); in scmi_perf_mb_level_set()
445 ph->xops->xfer_put(ph, t); in scmi_perf_mb_level_set()
450 u32 domain, u32 level, bool poll) in scmi_perf_level_set() argument
452 struct scmi_perf_info *pi = ph->get_priv(ph); in scmi_perf_level_set()
453 struct perf_dom_info *dom = pi->dom_info + domain; in scmi_perf_level_set()
455 if (dom->fc_info && dom->fc_info[PERF_FC_LEVEL].set_addr) { in scmi_perf_level_set()
456 struct scmi_fc_info *fci = &dom->fc_info[PERF_FC_LEVEL]; in scmi_perf_level_set()
459 domain, level, 0); in scmi_perf_level_set()
460 iowrite32(level, fci->set_addr); in scmi_perf_level_set()
461 ph->hops->fastchannel_db_ring(fci->set_db); in scmi_perf_level_set()
465 return scmi_perf_mb_level_set(ph, domain, level, poll); in scmi_perf_level_set()
469 u32 domain, u32 *level, bool poll) in scmi_perf_mb_level_get() argument
474 ret = ph->xops->xfer_get_init(ph, PERF_LEVEL_GET, in scmi_perf_mb_level_get()
479 t->hdr.poll_completion = poll; in scmi_perf_mb_level_get()
480 put_unaligned_le32(domain, t->tx.buf); in scmi_perf_mb_level_get()
482 ret = ph->xops->do_xfer(ph, t); in scmi_perf_mb_level_get()
484 *level = get_unaligned_le32(t->rx.buf); in scmi_perf_mb_level_get()
486 ph->xops->xfer_put(ph, t); in scmi_perf_mb_level_get()
491 u32 domain, u32 *level, bool poll) in scmi_perf_level_get() argument
493 struct scmi_perf_info *pi = ph->get_priv(ph); in scmi_perf_level_get()
494 struct perf_dom_info *dom = pi->dom_info + domain; in scmi_perf_level_get()
496 if (dom->fc_info && dom->fc_info[PERF_FC_LEVEL].get_addr) { in scmi_perf_level_get()
497 *level = ioread32(dom->fc_info[PERF_FC_LEVEL].get_addr); in scmi_perf_level_get()
499 domain, *level, 0); in scmi_perf_level_get()
503 return scmi_perf_mb_level_get(ph, domain, level, poll); in scmi_perf_level_get()
514 ret = ph->xops->xfer_get_init(ph, message_id, sizeof(*notify), 0, &t); in scmi_perf_level_limits_notify()
518 notify = t->tx.buf; in scmi_perf_level_limits_notify()
519 notify->domain = cpu_to_le32(domain); in scmi_perf_level_limits_notify()
520 notify->notify_enable = enable ? cpu_to_le32(BIT(0)) : 0; in scmi_perf_level_limits_notify()
522 ret = ph->xops->do_xfer(ph, t); in scmi_perf_level_limits_notify()
524 ph->xops->xfer_put(ph, t); in scmi_perf_level_limits_notify()
533 fc = devm_kcalloc(ph->dev, PERF_FC_MAX, sizeof(*fc), GFP_KERNEL); in scmi_perf_domain_init_fc()
537 ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL, in scmi_perf_domain_init_fc()
542 ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL, in scmi_perf_domain_init_fc()
546 ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL, in scmi_perf_domain_init_fc()
551 ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL, in scmi_perf_domain_init_fc()
563 if (of_parse_phandle_with_args(dev->of_node, "clocks", "#clock-cells", in scmi_dev_domain_id()
565 return -EINVAL; in scmi_dev_domain_id()
575 struct scmi_opp *opp; in scmi_dvfs_device_opps_add() local
577 struct scmi_perf_info *pi = ph->get_priv(ph); in scmi_dvfs_device_opps_add()
583 dom = pi->dom_info + domain; in scmi_dvfs_device_opps_add()
585 for (opp = dom->opp, idx = 0; idx < dom->opp_count; idx++, opp++) { in scmi_dvfs_device_opps_add()
586 freq = opp->perf * dom->mult_factor; in scmi_dvfs_device_opps_add()
590 dev_warn(dev, "failed to add opp %luHz\n", freq); in scmi_dvfs_device_opps_add()
592 while (idx-- > 0) { in scmi_dvfs_device_opps_add()
593 freq = (--opp)->perf * dom->mult_factor; in scmi_dvfs_device_opps_add()
607 struct scmi_perf_info *pi = ph->get_priv(ph); in scmi_dvfs_transition_latency_get()
613 dom = pi->dom_info + domain; in scmi_dvfs_transition_latency_get()
615 return dom->opp[dom->opp_count - 1].trans_latency_us * 1000; in scmi_dvfs_transition_latency_get()
621 struct scmi_perf_info *pi = ph->get_priv(ph); in scmi_dvfs_freq_set()
622 struct perf_dom_info *dom = pi->dom_info + domain; in scmi_dvfs_freq_set()
624 return scmi_perf_level_set(ph, domain, freq / dom->mult_factor, poll); in scmi_dvfs_freq_set()
631 u32 level; in scmi_dvfs_freq_get() local
632 struct scmi_perf_info *pi = ph->get_priv(ph); in scmi_dvfs_freq_get()
633 struct perf_dom_info *dom = pi->dom_info + domain; in scmi_dvfs_freq_get()
635 ret = scmi_perf_level_get(ph, domain, &level, poll); in scmi_dvfs_freq_get()
637 *freq = level * dom->mult_factor; in scmi_dvfs_freq_get()
646 struct scmi_perf_info *pi = ph->get_priv(ph); in scmi_dvfs_est_power_get()
649 int idx, ret = -EINVAL; in scmi_dvfs_est_power_get()
650 struct scmi_opp *opp; in scmi_dvfs_est_power_get() local
652 dom = pi->dom_info + domain; in scmi_dvfs_est_power_get()
654 return -EIO; in scmi_dvfs_est_power_get()
656 for (opp = dom->opp, idx = 0; idx < dom->opp_count; idx++, opp++) { in scmi_dvfs_est_power_get()
657 opp_freq = opp->perf * dom->mult_factor; in scmi_dvfs_est_power_get()
662 *power = opp->power; in scmi_dvfs_est_power_get()
674 struct scmi_perf_info *pi = ph->get_priv(ph); in scmi_fast_switch_possible()
676 dom = pi->dom_info + scmi_dev_domain_id(dev); in scmi_fast_switch_possible()
678 return dom->fc_info && dom->fc_info[PERF_FC_LEVEL].set_addr; in scmi_fast_switch_possible()
684 struct scmi_perf_info *pi = ph->get_priv(ph); in scmi_power_scale_get()
686 return pi->power_scale; in scmi_power_scale_get()
710 return -EINVAL; in scmi_perf_set_notify_enabled()
715 pr_debug("FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n", in scmi_perf_set_notify_enabled()
737 r->timestamp = timestamp; in scmi_perf_fill_custom_report()
738 r->agent_id = le32_to_cpu(p->agent_id); in scmi_perf_fill_custom_report()
739 r->domain_id = le32_to_cpu(p->domain_id); in scmi_perf_fill_custom_report()
740 r->range_max = le32_to_cpu(p->range_max); in scmi_perf_fill_custom_report()
741 r->range_min = le32_to_cpu(p->range_min); in scmi_perf_fill_custom_report()
742 *src_id = r->domain_id; in scmi_perf_fill_custom_report()
754 r->timestamp = timestamp; in scmi_perf_fill_custom_report()
755 r->agent_id = le32_to_cpu(p->agent_id); in scmi_perf_fill_custom_report()
756 r->domain_id = le32_to_cpu(p->domain_id); in scmi_perf_fill_custom_report()
757 r->performance_level = le32_to_cpu(p->performance_level); in scmi_perf_fill_custom_report()
758 *src_id = r->domain_id; in scmi_perf_fill_custom_report()
771 struct scmi_perf_info *pi = ph->get_priv(ph); in scmi_perf_get_num_sources()
774 return -EINVAL; in scmi_perf_get_num_sources()
776 return pi->num_domains; in scmi_perf_get_num_sources()
811 ret = ph->xops->version_get(ph, &version); in scmi_perf_protocol_init()
815 dev_dbg(ph->dev, "Performance Version %d.%d\n", in scmi_perf_protocol_init()
818 pinfo = devm_kzalloc(ph->dev, sizeof(*pinfo), GFP_KERNEL); in scmi_perf_protocol_init()
820 return -ENOMEM; in scmi_perf_protocol_init()
826 pinfo->dom_info = devm_kcalloc(ph->dev, pinfo->num_domains, in scmi_perf_protocol_init()
827 sizeof(*pinfo->dom_info), GFP_KERNEL); in scmi_perf_protocol_init()
828 if (!pinfo->dom_info) in scmi_perf_protocol_init()
829 return -ENOMEM; in scmi_perf_protocol_init()
831 for (domain = 0; domain < pinfo->num_domains; domain++) { in scmi_perf_protocol_init()
832 struct perf_dom_info *dom = pinfo->dom_info + domain; in scmi_perf_protocol_init()
837 if (dom->perf_fastchannels) in scmi_perf_protocol_init()
838 scmi_perf_domain_init_fc(ph, domain, &dom->fc_info); in scmi_perf_protocol_init()
841 pinfo->version = version; in scmi_perf_protocol_init()
843 return ph->set_priv(ph, pinfo); in scmi_perf_protocol_init()