Lines Matching +full:opp +full:- +full:level
1 // SPDX-License-Identifier: GPL-2.0
8 #define pr_fmt(fmt) "SCMI Notifications PERF - " fmt
13 #include <linux/io-64-nonatomic-hi-lo.h>
80 __le32 level; member
109 } opp[]; member
160 struct scmi_opp opp[MAX_OPPS]; member
190 attr = t->rx.buf; in scmi_perf_attributes_get()
194 u16 flags = le16_to_cpu(attr->flags); in scmi_perf_attributes_get()
196 pi->num_domains = le16_to_cpu(attr->num_domains); in scmi_perf_attributes_get()
197 pi->power_scale_mw = POWER_SCALE_IN_MILLIWATT(flags); in scmi_perf_attributes_get()
198 pi->stats_addr = le32_to_cpu(attr->stats_addr_low) | in scmi_perf_attributes_get()
199 (u64)le32_to_cpu(attr->stats_addr_high) << 32; in scmi_perf_attributes_get()
200 pi->stats_size = le32_to_cpu(attr->stats_size); in scmi_perf_attributes_get()
221 put_unaligned_le32(domain, t->tx.buf); in scmi_perf_domain_attributes_get()
222 attr = t->rx.buf; in scmi_perf_domain_attributes_get()
226 u32 flags = le32_to_cpu(attr->flags); in scmi_perf_domain_attributes_get()
228 dom_info->set_limits = SUPPORTS_SET_LIMITS(flags); in scmi_perf_domain_attributes_get()
229 dom_info->set_perf = SUPPORTS_SET_PERF_LVL(flags); in scmi_perf_domain_attributes_get()
230 dom_info->perf_limit_notify = SUPPORTS_PERF_LIMIT_NOTIFY(flags); in scmi_perf_domain_attributes_get()
231 dom_info->perf_level_notify = SUPPORTS_PERF_LEVEL_NOTIFY(flags); in scmi_perf_domain_attributes_get()
232 dom_info->perf_fastchannels = SUPPORTS_PERF_FASTCHANNELS(flags); in scmi_perf_domain_attributes_get()
233 dom_info->sustained_freq_khz = in scmi_perf_domain_attributes_get()
234 le32_to_cpu(attr->sustained_freq_khz); in scmi_perf_domain_attributes_get()
235 dom_info->sustained_perf_level = in scmi_perf_domain_attributes_get()
236 le32_to_cpu(attr->sustained_perf_level); in scmi_perf_domain_attributes_get()
237 if (!dom_info->sustained_freq_khz || in scmi_perf_domain_attributes_get()
238 !dom_info->sustained_perf_level) in scmi_perf_domain_attributes_get()
240 dom_info->mult_factor = 1000; in scmi_perf_domain_attributes_get()
242 dom_info->mult_factor = in scmi_perf_domain_attributes_get()
243 (dom_info->sustained_freq_khz * 1000) / in scmi_perf_domain_attributes_get()
244 dom_info->sustained_perf_level; in scmi_perf_domain_attributes_get()
245 strlcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE); in scmi_perf_domain_attributes_get()
256 return t1->perf - t2->perf; in opp_cmp_func()
267 struct scmi_opp *opp; in scmi_perf_describe_levels_get() local
276 dom_info = t->tx.buf; in scmi_perf_describe_levels_get()
277 level_info = t->rx.buf; in scmi_perf_describe_levels_get()
280 dom_info->domain = cpu_to_le32(domain); in scmi_perf_describe_levels_get()
282 dom_info->level_index = cpu_to_le32(tot_opp_cnt); in scmi_perf_describe_levels_get()
288 num_returned = le16_to_cpu(level_info->num_returned); in scmi_perf_describe_levels_get()
289 num_remaining = le16_to_cpu(level_info->num_remaining); in scmi_perf_describe_levels_get()
291 dev_err(handle->dev, "No. of OPPs exceeded MAX_OPPS"); in scmi_perf_describe_levels_get()
295 opp = &perf_dom->opp[tot_opp_cnt]; in scmi_perf_describe_levels_get()
296 for (cnt = 0; cnt < num_returned; cnt++, opp++) { in scmi_perf_describe_levels_get()
297 opp->perf = le32_to_cpu(level_info->opp[cnt].perf_val); in scmi_perf_describe_levels_get()
298 opp->power = le32_to_cpu(level_info->opp[cnt].power); in scmi_perf_describe_levels_get()
299 opp->trans_latency_us = le16_to_cpu in scmi_perf_describe_levels_get()
300 (level_info->opp[cnt].transition_latency_us); in scmi_perf_describe_levels_get()
302 dev_dbg(handle->dev, "Level %d Power %d Latency %dus\n", in scmi_perf_describe_levels_get()
303 opp->perf, opp->power, opp->trans_latency_us); in scmi_perf_describe_levels_get()
315 perf_dom->opp_count = tot_opp_cnt; in scmi_perf_describe_levels_get()
318 sort(perf_dom->opp, tot_opp_cnt, sizeof(*opp), opp_cmp_func, NULL); in scmi_perf_describe_levels_get()
326 if (db->mask) \
327 val = ioread##w(db->addr) & db->mask; \
328 iowrite##w((u##w)db->set | val, db->addr); \
333 if (!db || !db->addr) in scmi_perf_fc_ring_db()
336 if (db->width == 1) in scmi_perf_fc_ring_db()
338 else if (db->width == 2) in scmi_perf_fc_ring_db()
340 else if (db->width == 4) in scmi_perf_fc_ring_db()
342 else /* db->width == 8 */ in scmi_perf_fc_ring_db()
349 if (db->mask) in scmi_perf_fc_ring_db()
350 val = ioread64_hi_lo(db->addr) & db->mask; in scmi_perf_fc_ring_db()
351 iowrite64_hi_lo(db->set | val, db->addr); in scmi_perf_fc_ring_db()
368 limits = t->tx.buf; in scmi_perf_mb_limits_set()
369 limits->domain = cpu_to_le32(domain); in scmi_perf_mb_limits_set()
370 limits->max_level = cpu_to_le32(max_perf); in scmi_perf_mb_limits_set()
371 limits->min_level = cpu_to_le32(min_perf); in scmi_perf_mb_limits_set()
382 struct scmi_perf_info *pi = handle->perf_priv; in scmi_perf_limits_set()
383 struct perf_dom_info *dom = pi->dom_info + domain; in scmi_perf_limits_set()
385 if (dom->fc_info && dom->fc_info->limit_set_addr) { in scmi_perf_limits_set()
386 iowrite32(max_perf, dom->fc_info->limit_set_addr); in scmi_perf_limits_set()
387 iowrite32(min_perf, dom->fc_info->limit_set_addr + 4); in scmi_perf_limits_set()
388 scmi_perf_fc_ring_db(dom->fc_info->limit_set_db); in scmi_perf_limits_set()
407 put_unaligned_le32(domain, t->tx.buf); in scmi_perf_mb_limits_get()
411 limits = t->rx.buf; in scmi_perf_mb_limits_get()
413 *max_perf = le32_to_cpu(limits->max_level); in scmi_perf_mb_limits_get()
414 *min_perf = le32_to_cpu(limits->min_level); in scmi_perf_mb_limits_get()
424 struct scmi_perf_info *pi = handle->perf_priv; in scmi_perf_limits_get()
425 struct perf_dom_info *dom = pi->dom_info + domain; in scmi_perf_limits_get()
427 if (dom->fc_info && dom->fc_info->limit_get_addr) { in scmi_perf_limits_get()
428 *max_perf = ioread32(dom->fc_info->limit_get_addr); in scmi_perf_limits_get()
429 *min_perf = ioread32(dom->fc_info->limit_get_addr + 4); in scmi_perf_limits_get()
437 u32 level, bool poll) in scmi_perf_mb_level_set() argument
448 t->hdr.poll_completion = poll; in scmi_perf_mb_level_set()
449 lvl = t->tx.buf; in scmi_perf_mb_level_set()
450 lvl->domain = cpu_to_le32(domain); in scmi_perf_mb_level_set()
451 lvl->level = cpu_to_le32(level); in scmi_perf_mb_level_set()
460 u32 level, bool poll) in scmi_perf_level_set() argument
462 struct scmi_perf_info *pi = handle->perf_priv; in scmi_perf_level_set()
463 struct perf_dom_info *dom = pi->dom_info + domain; in scmi_perf_level_set()
465 if (dom->fc_info && dom->fc_info->level_set_addr) { in scmi_perf_level_set()
466 iowrite32(level, dom->fc_info->level_set_addr); in scmi_perf_level_set()
467 scmi_perf_fc_ring_db(dom->fc_info->level_set_db); in scmi_perf_level_set()
471 return scmi_perf_mb_level_set(handle, domain, level, poll); in scmi_perf_level_set()
475 u32 *level, bool poll) in scmi_perf_mb_level_get() argument
485 t->hdr.poll_completion = poll; in scmi_perf_mb_level_get()
486 put_unaligned_le32(domain, t->tx.buf); in scmi_perf_mb_level_get()
490 *level = get_unaligned_le32(t->rx.buf); in scmi_perf_mb_level_get()
497 u32 *level, bool poll) in scmi_perf_level_get() argument
499 struct scmi_perf_info *pi = handle->perf_priv; in scmi_perf_level_get()
500 struct perf_dom_info *dom = pi->dom_info + domain; in scmi_perf_level_get()
502 if (dom->fc_info && dom->fc_info->level_get_addr) { in scmi_perf_level_get()
503 *level = ioread32(dom->fc_info->level_get_addr); in scmi_perf_level_get()
507 return scmi_perf_mb_level_get(handle, domain, level, poll); in scmi_perf_level_get()
523 notify = t->tx.buf; in scmi_perf_level_limits_notify()
524 notify->domain = cpu_to_le32(domain); in scmi_perf_level_limits_notify()
525 notify->notify_enable = enable ? cpu_to_le32(BIT(0)) : 0; in scmi_perf_level_limits_notify()
566 info = t->tx.buf; in scmi_perf_domain_desc_fc()
567 info->domain = cpu_to_le32(domain); in scmi_perf_domain_desc_fc()
568 info->message_id = cpu_to_le32(message_id); in scmi_perf_domain_desc_fc()
574 resp = t->rx.buf; in scmi_perf_domain_desc_fc()
575 flags = le32_to_cpu(resp->attr); in scmi_perf_domain_desc_fc()
576 size = le32_to_cpu(resp->chan_size); in scmi_perf_domain_desc_fc()
580 phys_addr = le32_to_cpu(resp->chan_addr_low); in scmi_perf_domain_desc_fc()
581 phys_addr |= (u64)le32_to_cpu(resp->chan_addr_high) << 32; in scmi_perf_domain_desc_fc()
582 addr = devm_ioremap(handle->dev, phys_addr, size); in scmi_perf_domain_desc_fc()
588 db = devm_kzalloc(handle->dev, sizeof(*db), GFP_KERNEL); in scmi_perf_domain_desc_fc()
593 phys_addr = le32_to_cpu(resp->db_addr_low); in scmi_perf_domain_desc_fc()
594 phys_addr |= (u64)le32_to_cpu(resp->db_addr_high) << 32; in scmi_perf_domain_desc_fc()
595 addr = devm_ioremap(handle->dev, phys_addr, size); in scmi_perf_domain_desc_fc()
599 db->addr = addr; in scmi_perf_domain_desc_fc()
600 db->width = size; in scmi_perf_domain_desc_fc()
601 db->set = le32_to_cpu(resp->db_set_lmask); in scmi_perf_domain_desc_fc()
602 db->set |= (u64)le32_to_cpu(resp->db_set_hmask) << 32; in scmi_perf_domain_desc_fc()
603 db->mask = le32_to_cpu(resp->db_preserve_lmask); in scmi_perf_domain_desc_fc()
604 db->mask |= (u64)le32_to_cpu(resp->db_preserve_hmask) << 32; in scmi_perf_domain_desc_fc()
616 fc = devm_kzalloc(handle->dev, sizeof(*fc), GFP_KERNEL); in scmi_perf_domain_init_fc()
621 &fc->level_set_addr, &fc->level_set_db); in scmi_perf_domain_init_fc()
623 &fc->level_get_addr, NULL); in scmi_perf_domain_init_fc()
625 &fc->limit_set_addr, &fc->limit_set_db); in scmi_perf_domain_init_fc()
627 &fc->limit_get_addr, NULL); in scmi_perf_domain_init_fc()
636 if (of_parse_phandle_with_args(dev->of_node, "clocks", "#clock-cells", in scmi_dev_domain_id()
638 return -EINVAL; in scmi_dev_domain_id()
648 struct scmi_opp *opp; in scmi_dvfs_device_opps_add() local
650 struct scmi_perf_info *pi = handle->perf_priv; in scmi_dvfs_device_opps_add()
656 dom = pi->dom_info + domain; in scmi_dvfs_device_opps_add()
658 for (opp = dom->opp, idx = 0; idx < dom->opp_count; idx++, opp++) { in scmi_dvfs_device_opps_add()
659 freq = opp->perf * dom->mult_factor; in scmi_dvfs_device_opps_add()
663 dev_warn(dev, "failed to add opp %luHz\n", freq); in scmi_dvfs_device_opps_add()
665 while (idx-- > 0) { in scmi_dvfs_device_opps_add()
666 freq = (--opp)->perf * dom->mult_factor; in scmi_dvfs_device_opps_add()
679 struct scmi_perf_info *pi = handle->perf_priv; in scmi_dvfs_transition_latency_get()
685 dom = pi->dom_info + domain; in scmi_dvfs_transition_latency_get()
687 return dom->opp[dom->opp_count - 1].trans_latency_us * 1000; in scmi_dvfs_transition_latency_get()
693 struct scmi_perf_info *pi = handle->perf_priv; in scmi_dvfs_freq_set()
694 struct perf_dom_info *dom = pi->dom_info + domain; in scmi_dvfs_freq_set()
696 return scmi_perf_level_set(handle, domain, freq / dom->mult_factor, in scmi_dvfs_freq_set()
704 u32 level; in scmi_dvfs_freq_get() local
705 struct scmi_perf_info *pi = handle->perf_priv; in scmi_dvfs_freq_get()
706 struct perf_dom_info *dom = pi->dom_info + domain; in scmi_dvfs_freq_get()
708 ret = scmi_perf_level_get(handle, domain, &level, poll); in scmi_dvfs_freq_get()
710 *freq = level * dom->mult_factor; in scmi_dvfs_freq_get()
718 struct scmi_perf_info *pi = handle->perf_priv; in scmi_dvfs_est_power_get()
721 int idx, ret = -EINVAL; in scmi_dvfs_est_power_get()
722 struct scmi_opp *opp; in scmi_dvfs_est_power_get() local
724 dom = pi->dom_info + domain; in scmi_dvfs_est_power_get()
726 return -EIO; in scmi_dvfs_est_power_get()
728 for (opp = dom->opp, idx = 0; idx < dom->opp_count; idx++, opp++) { in scmi_dvfs_est_power_get()
729 opp_freq = opp->perf * dom->mult_factor; in scmi_dvfs_est_power_get()
734 *power = opp->power; in scmi_dvfs_est_power_get()
746 struct scmi_perf_info *pi = handle->perf_priv; in scmi_fast_switch_possible()
748 dom = pi->dom_info + scmi_dev_domain_id(dev); in scmi_fast_switch_possible()
750 return dom->fc_info && dom->fc_info->level_set_addr; in scmi_fast_switch_possible()
773 return -EINVAL; in scmi_perf_set_notify_enabled()
778 pr_debug("FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n", in scmi_perf_set_notify_enabled()
800 r->timestamp = timestamp; in scmi_perf_fill_custom_report()
801 r->agent_id = le32_to_cpu(p->agent_id); in scmi_perf_fill_custom_report()
802 r->domain_id = le32_to_cpu(p->domain_id); in scmi_perf_fill_custom_report()
803 r->range_max = le32_to_cpu(p->range_max); in scmi_perf_fill_custom_report()
804 r->range_min = le32_to_cpu(p->range_min); in scmi_perf_fill_custom_report()
805 *src_id = r->domain_id; in scmi_perf_fill_custom_report()
817 r->timestamp = timestamp; in scmi_perf_fill_custom_report()
818 r->agent_id = le32_to_cpu(p->agent_id); in scmi_perf_fill_custom_report()
819 r->domain_id = le32_to_cpu(p->domain_id); in scmi_perf_fill_custom_report()
820 r->performance_level = le32_to_cpu(p->performance_level); in scmi_perf_fill_custom_report()
821 *src_id = r->domain_id; in scmi_perf_fill_custom_report()
858 dev_dbg(handle->dev, "Performance Version %d.%d\n", in scmi_perf_protocol_init()
861 pinfo = devm_kzalloc(handle->dev, sizeof(*pinfo), GFP_KERNEL); in scmi_perf_protocol_init()
863 return -ENOMEM; in scmi_perf_protocol_init()
867 pinfo->dom_info = devm_kcalloc(handle->dev, pinfo->num_domains, in scmi_perf_protocol_init()
868 sizeof(*pinfo->dom_info), GFP_KERNEL); in scmi_perf_protocol_init()
869 if (!pinfo->dom_info) in scmi_perf_protocol_init()
870 return -ENOMEM; in scmi_perf_protocol_init()
872 for (domain = 0; domain < pinfo->num_domains; domain++) { in scmi_perf_protocol_init()
873 struct perf_dom_info *dom = pinfo->dom_info + domain; in scmi_perf_protocol_init()
878 if (dom->perf_fastchannels) in scmi_perf_protocol_init()
879 scmi_perf_domain_init_fc(handle, domain, &dom->fc_info); in scmi_perf_protocol_init()
886 pinfo->num_domains); in scmi_perf_protocol_init()
888 pinfo->version = version; in scmi_perf_protocol_init()
889 handle->perf_ops = &perf_ops; in scmi_perf_protocol_init()
890 handle->perf_priv = pinfo; in scmi_perf_protocol_init()