Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v6.13 1337 lines 32 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * System Control and Management Interface (SCMI) Performance Protocol 4 * 5 * Copyright (C) 2018-2023 ARM Ltd. 6 */ 7 8#define pr_fmt(fmt) "SCMI Notifications PERF - " fmt 9 10#include <linux/bits.h> 11#include <linux/hashtable.h> 12#include <linux/io.h> 13#include <linux/log2.h> 14#include <linux/module.h> 15#include <linux/of.h> 16#include <linux/platform_device.h> 17#include <linux/pm_opp.h> 18#include <linux/scmi_protocol.h> 19#include <linux/sort.h> 20#include <linux/xarray.h> 21 22#include <trace/events/scmi.h> 23 24#include "protocols.h" 25#include "notify.h" 26 27/* Updated only after ALL the mandatory features for that version are merged */ 28#define SCMI_PROTOCOL_SUPPORTED_VERSION 0x40000 29 30#define MAX_OPPS 32 31 32enum scmi_performance_protocol_cmd { 33 PERF_DOMAIN_ATTRIBUTES = 0x3, 34 PERF_DESCRIBE_LEVELS = 0x4, 35 PERF_LIMITS_SET = 0x5, 36 PERF_LIMITS_GET = 0x6, 37 PERF_LEVEL_SET = 0x7, 38 PERF_LEVEL_GET = 0x8, 39 PERF_NOTIFY_LIMITS = 0x9, 40 PERF_NOTIFY_LEVEL = 0xa, 41 PERF_DESCRIBE_FASTCHANNEL = 0xb, 42 PERF_DOMAIN_NAME_GET = 0xc, 43}; 44 45enum { 46 PERF_FC_LEVEL, 47 PERF_FC_LIMIT, 48 PERF_FC_MAX, 49}; 50 51struct scmi_opp { 52 u32 perf; 53 u32 power; 54 u32 trans_latency_us; 55 u32 indicative_freq; 56 u32 level_index; 57 struct hlist_node hash; 58}; 59 60struct scmi_msg_resp_perf_attributes { 61 __le16 num_domains; 62 __le16 flags; 63#define POWER_SCALE_IN_MILLIWATT(x) ((x) & BIT(0)) 64#define POWER_SCALE_IN_MICROWATT(x) ((x) & BIT(1)) 65 __le32 stats_addr_low; 66 __le32 stats_addr_high; 67 __le32 stats_size; 68}; 69 70struct scmi_msg_resp_perf_domain_attributes { 71 __le32 flags; 72#define SUPPORTS_SET_LIMITS(x) ((x) & BIT(31)) 73#define SUPPORTS_SET_PERF_LVL(x) ((x) & BIT(30)) 74#define SUPPORTS_PERF_LIMIT_NOTIFY(x) ((x) & BIT(29)) 75#define SUPPORTS_PERF_LEVEL_NOTIFY(x) ((x) & BIT(28)) 76#define SUPPORTS_PERF_FASTCHANNELS(x) ((x) & BIT(27)) 77#define SUPPORTS_EXTENDED_NAMES(x) ((x) & BIT(26)) 78#define SUPPORTS_LEVEL_INDEXING(x) ((x) & BIT(25)) 79 __le32 rate_limit_us; 80 __le32 sustained_freq_khz; 81 __le32 sustained_perf_level; 82 u8 name[SCMI_SHORT_NAME_MAX_SIZE]; 83}; 84 85struct scmi_msg_perf_describe_levels { 86 __le32 domain; 87 __le32 level_index; 88}; 89 90struct scmi_perf_set_limits { 91 __le32 domain; 92 __le32 max_level; 93 __le32 min_level; 94}; 95 96struct scmi_perf_get_limits { 97 __le32 max_level; 98 __le32 min_level; 99}; 100 101struct scmi_perf_set_level { 102 __le32 domain; 103 __le32 level; 104}; 105 106struct scmi_perf_notify_level_or_limits { 107 __le32 domain; 108 __le32 notify_enable; 109}; 110 111struct scmi_perf_limits_notify_payld { 112 __le32 agent_id; 113 __le32 domain_id; 114 __le32 range_max; 115 __le32 range_min; 116}; 117 118struct scmi_perf_level_notify_payld { 119 __le32 agent_id; 120 __le32 domain_id; 121 __le32 performance_level; 122}; 123 124struct scmi_msg_resp_perf_describe_levels { 125 __le16 num_returned; 126 __le16 num_remaining; 127 struct { 128 __le32 perf_val; 129 __le32 power; 130 __le16 transition_latency_us; 131 __le16 reserved; 132 } opp[]; 133}; 134 135struct scmi_msg_resp_perf_describe_levels_v4 { 136 __le16 num_returned; 137 __le16 num_remaining; 138 struct { 139 __le32 perf_val; 140 __le32 power; 141 __le16 transition_latency_us; 142 __le16 reserved; 143 __le32 indicative_freq; 144 __le32 level_index; 145 } opp[]; 146}; 147 148struct perf_dom_info { 149 u32 id; 150 bool set_limits; 151 bool perf_limit_notify; 152 bool perf_level_notify; 153 bool perf_fastchannels; 154 bool level_indexing_mode; 155 u32 opp_count; 156 u32 rate_limit_us; 157 u32 sustained_freq_khz; 158 u32 sustained_perf_level; 159 unsigned long mult_factor; 160 struct scmi_perf_domain_info info; 161 struct scmi_opp opp[MAX_OPPS]; 162 struct scmi_fc_info *fc_info; 163 struct xarray opps_by_idx; 164 struct xarray opps_by_lvl; 165 DECLARE_HASHTABLE(opps_by_freq, ilog2(MAX_OPPS)); 166}; 167 168#define LOOKUP_BY_FREQ(__htp, __freq) \ 169({ \ 170 /* u32 cast is needed to pick right hash func */ \ 171 u32 f_ = (u32)(__freq); \ 172 struct scmi_opp *_opp; \ 173 \ 174 hash_for_each_possible((__htp), _opp, hash, f_) \ 175 if (_opp->indicative_freq == f_) \ 176 break; \ 177 _opp; \ 178}) 179 180struct scmi_perf_info { 181 u32 version; 182 u16 num_domains; 183 enum scmi_power_scale power_scale; 184 u64 stats_addr; 185 u32 stats_size; 186 bool notify_lvl_cmd; 187 bool notify_lim_cmd; 188 struct perf_dom_info *dom_info; 189}; 190 191static enum scmi_performance_protocol_cmd evt_2_cmd[] = { 192 PERF_NOTIFY_LIMITS, 193 PERF_NOTIFY_LEVEL, 194}; 195 196static int scmi_perf_attributes_get(const struct scmi_protocol_handle *ph, 197 struct scmi_perf_info *pi) 198{ 199 int ret; 200 struct scmi_xfer *t; 201 struct scmi_msg_resp_perf_attributes *attr; 202 203 ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, 0, 204 sizeof(*attr), &t); 205 if (ret) 206 return ret; 207 208 attr = t->rx.buf; 209 210 ret = ph->xops->do_xfer(ph, t); 211 if (!ret) { 212 u16 flags = le16_to_cpu(attr->flags); 213 214 pi->num_domains = le16_to_cpu(attr->num_domains); 215 216 if (POWER_SCALE_IN_MILLIWATT(flags)) 217 pi->power_scale = SCMI_POWER_MILLIWATTS; 218 if (PROTOCOL_REV_MAJOR(pi->version) >= 0x3) 219 if (POWER_SCALE_IN_MICROWATT(flags)) 220 pi->power_scale = SCMI_POWER_MICROWATTS; 221 222 pi->stats_addr = le32_to_cpu(attr->stats_addr_low) | 223 (u64)le32_to_cpu(attr->stats_addr_high) << 32; 224 pi->stats_size = le32_to_cpu(attr->stats_size); 225 } 226 227 ph->xops->xfer_put(ph, t); 228 229 if (!ret) { 230 if (!ph->hops->protocol_msg_check(ph, PERF_NOTIFY_LEVEL, NULL)) 231 pi->notify_lvl_cmd = true; 232 233 if (!ph->hops->protocol_msg_check(ph, PERF_NOTIFY_LIMITS, NULL)) 234 pi->notify_lim_cmd = true; 235 } 236 237 return ret; 238} 239 240static void scmi_perf_xa_destroy(void *data) 241{ 242 int domain; 243 struct scmi_perf_info *pinfo = data; 244 245 for (domain = 0; domain < pinfo->num_domains; domain++) { 246 xa_destroy(&((pinfo->dom_info + domain)->opps_by_idx)); 247 xa_destroy(&((pinfo->dom_info + domain)->opps_by_lvl)); 248 } 249} 250 251static int 252scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph, 253 struct perf_dom_info *dom_info, 254 bool notify_lim_cmd, bool notify_lvl_cmd, 255 u32 version) 256{ 257 int ret; 258 u32 flags; 259 struct scmi_xfer *t; 260 struct scmi_msg_resp_perf_domain_attributes *attr; 261 262 ret = ph->xops->xfer_get_init(ph, PERF_DOMAIN_ATTRIBUTES, 263 sizeof(dom_info->id), sizeof(*attr), &t); 264 if (ret) 265 return ret; 266 267 put_unaligned_le32(dom_info->id, t->tx.buf); 268 attr = t->rx.buf; 269 270 ret = ph->xops->do_xfer(ph, t); 271 if (!ret) { 272 flags = le32_to_cpu(attr->flags); 273 274 dom_info->set_limits = SUPPORTS_SET_LIMITS(flags); 275 dom_info->info.set_perf = SUPPORTS_SET_PERF_LVL(flags); 276 if (notify_lim_cmd) 277 dom_info->perf_limit_notify = 278 SUPPORTS_PERF_LIMIT_NOTIFY(flags); 279 if (notify_lvl_cmd) 280 dom_info->perf_level_notify = 281 SUPPORTS_PERF_LEVEL_NOTIFY(flags); 282 dom_info->perf_fastchannels = SUPPORTS_PERF_FASTCHANNELS(flags); 283 if (PROTOCOL_REV_MAJOR(version) >= 0x4) 284 dom_info->level_indexing_mode = 285 SUPPORTS_LEVEL_INDEXING(flags); 286 dom_info->rate_limit_us = le32_to_cpu(attr->rate_limit_us) & 287 GENMASK(19, 0); 288 dom_info->sustained_freq_khz = 289 le32_to_cpu(attr->sustained_freq_khz); 290 dom_info->sustained_perf_level = 291 le32_to_cpu(attr->sustained_perf_level); 292 /* 293 * sustained_freq_khz = mult_factor * sustained_perf_level 294 * mult_factor must be non zero positive integer(not fraction) 295 */ 296 if (!dom_info->sustained_freq_khz || 297 !dom_info->sustained_perf_level || 298 dom_info->level_indexing_mode) { 299 /* CPUFreq converts to kHz, hence default 1000 */ 300 dom_info->mult_factor = 1000; 301 } else { 302 dom_info->mult_factor = 303 (dom_info->sustained_freq_khz * 1000UL) 304 / dom_info->sustained_perf_level; 305 if ((dom_info->sustained_freq_khz * 1000UL) % 306 dom_info->sustained_perf_level) 307 dev_warn(ph->dev, 308 "multiplier for domain %d rounded\n", 309 dom_info->id); 310 } 311 if (!dom_info->mult_factor) 312 dev_warn(ph->dev, 313 "Wrong sustained perf/frequency(domain %d)\n", 314 dom_info->id); 315 316 strscpy(dom_info->info.name, attr->name, 317 SCMI_SHORT_NAME_MAX_SIZE); 318 } 319 320 ph->xops->xfer_put(ph, t); 321 322 /* 323 * If supported overwrite short name with the extended one; 324 * on error just carry on and use already provided short name. 325 */ 326 if (!ret && PROTOCOL_REV_MAJOR(version) >= 0x3 && 327 SUPPORTS_EXTENDED_NAMES(flags)) 328 ph->hops->extended_name_get(ph, PERF_DOMAIN_NAME_GET, 329 dom_info->id, NULL, dom_info->info.name, 330 SCMI_MAX_STR_SIZE); 331 332 xa_init(&dom_info->opps_by_lvl); 333 if (dom_info->level_indexing_mode) { 334 xa_init(&dom_info->opps_by_idx); 335 hash_init(dom_info->opps_by_freq); 336 } 337 338 return ret; 339} 340 341static int opp_cmp_func(const void *opp1, const void *opp2) 342{ 343 const struct scmi_opp *t1 = opp1, *t2 = opp2; 344 345 return t1->perf - t2->perf; 346} 347 348struct scmi_perf_ipriv { 349 u32 version; 350 struct perf_dom_info *perf_dom; 351}; 352 353static void iter_perf_levels_prepare_message(void *message, 354 unsigned int desc_index, 355 const void *priv) 356{ 357 struct scmi_msg_perf_describe_levels *msg = message; 358 const struct scmi_perf_ipriv *p = priv; 359 360 msg->domain = cpu_to_le32(p->perf_dom->id); 361 /* Set the number of OPPs to be skipped/already read */ 362 msg->level_index = cpu_to_le32(desc_index); 363} 364 365static int iter_perf_levels_update_state(struct scmi_iterator_state *st, 366 const void *response, void *priv) 367{ 368 const struct scmi_msg_resp_perf_describe_levels *r = response; 369 370 st->num_returned = le16_to_cpu(r->num_returned); 371 st->num_remaining = le16_to_cpu(r->num_remaining); 372 373 return 0; 374} 375 376static inline int 377process_response_opp(struct device *dev, struct perf_dom_info *dom, 378 struct scmi_opp *opp, unsigned int loop_idx, 379 const struct scmi_msg_resp_perf_describe_levels *r) 380{ 381 int ret; 382 383 opp->perf = le32_to_cpu(r->opp[loop_idx].perf_val); 384 opp->power = le32_to_cpu(r->opp[loop_idx].power); 385 opp->trans_latency_us = 386 le16_to_cpu(r->opp[loop_idx].transition_latency_us); 387 388 ret = xa_insert(&dom->opps_by_lvl, opp->perf, opp, GFP_KERNEL); 389 if (ret) { 390 dev_info(dev, FW_BUG "Failed to add opps_by_lvl at %d for %s - ret:%d\n", 391 opp->perf, dom->info.name, ret); 392 return ret; 393 } 394 395 return 0; 396} 397 398static inline int 399process_response_opp_v4(struct device *dev, struct perf_dom_info *dom, 400 struct scmi_opp *opp, unsigned int loop_idx, 401 const struct scmi_msg_resp_perf_describe_levels_v4 *r) 402{ 403 int ret; 404 405 opp->perf = le32_to_cpu(r->opp[loop_idx].perf_val); 406 opp->power = le32_to_cpu(r->opp[loop_idx].power); 407 opp->trans_latency_us = 408 le16_to_cpu(r->opp[loop_idx].transition_latency_us); 409 410 ret = xa_insert(&dom->opps_by_lvl, opp->perf, opp, GFP_KERNEL); 411 if (ret) { 412 dev_info(dev, FW_BUG "Failed to add opps_by_lvl at %d for %s - ret:%d\n", 413 opp->perf, dom->info.name, ret); 414 return ret; 415 } 416 417 /* Note that PERF v4 reports always five 32-bit words */ 418 opp->indicative_freq = le32_to_cpu(r->opp[loop_idx].indicative_freq); 419 if (dom->level_indexing_mode) { 420 opp->level_index = le32_to_cpu(r->opp[loop_idx].level_index); 421 422 ret = xa_insert(&dom->opps_by_idx, opp->level_index, opp, 423 GFP_KERNEL); 424 if (ret) { 425 dev_warn(dev, 426 "Failed to add opps_by_idx at %d for %s - ret:%d\n", 427 opp->level_index, dom->info.name, ret); 428 429 /* Cleanup by_lvl too */ 430 xa_erase(&dom->opps_by_lvl, opp->perf); 431 432 return ret; 433 } 434 435 hash_add(dom->opps_by_freq, &opp->hash, opp->indicative_freq); 436 } 437 438 return 0; 439} 440 441static int 442iter_perf_levels_process_response(const struct scmi_protocol_handle *ph, 443 const void *response, 444 struct scmi_iterator_state *st, void *priv) 445{ 446 int ret; 447 struct scmi_opp *opp; 448 struct scmi_perf_ipriv *p = priv; 449 450 opp = &p->perf_dom->opp[p->perf_dom->opp_count]; 451 if (PROTOCOL_REV_MAJOR(p->version) <= 0x3) 452 ret = process_response_opp(ph->dev, p->perf_dom, opp, 453 st->loop_idx, response); 454 else 455 ret = process_response_opp_v4(ph->dev, p->perf_dom, opp, 456 st->loop_idx, response); 457 458 /* Skip BAD duplicates received from firmware */ 459 if (ret) 460 return ret == -EBUSY ? 0 : ret; 461 462 p->perf_dom->opp_count++; 463 464 dev_dbg(ph->dev, "Level %d Power %d Latency %dus Ifreq %d Index %d\n", 465 opp->perf, opp->power, opp->trans_latency_us, 466 opp->indicative_freq, opp->level_index); 467 468 return 0; 469} 470 471static int 472scmi_perf_describe_levels_get(const struct scmi_protocol_handle *ph, 473 struct perf_dom_info *perf_dom, u32 version) 474{ 475 int ret; 476 void *iter; 477 struct scmi_iterator_ops ops = { 478 .prepare_message = iter_perf_levels_prepare_message, 479 .update_state = iter_perf_levels_update_state, 480 .process_response = iter_perf_levels_process_response, 481 }; 482 struct scmi_perf_ipriv ppriv = { 483 .version = version, 484 .perf_dom = perf_dom, 485 }; 486 487 iter = ph->hops->iter_response_init(ph, &ops, MAX_OPPS, 488 PERF_DESCRIBE_LEVELS, 489 sizeof(struct scmi_msg_perf_describe_levels), 490 &ppriv); 491 if (IS_ERR(iter)) 492 return PTR_ERR(iter); 493 494 ret = ph->hops->iter_response_run(iter); 495 if (ret) 496 return ret; 497 498 if (perf_dom->opp_count) 499 sort(perf_dom->opp, perf_dom->opp_count, 500 sizeof(struct scmi_opp), opp_cmp_func, NULL); 501 502 return ret; 503} 504 505static int scmi_perf_num_domains_get(const struct scmi_protocol_handle *ph) 506{ 507 struct scmi_perf_info *pi = ph->get_priv(ph); 508 509 return pi->num_domains; 510} 511 512static inline struct perf_dom_info * 513scmi_perf_domain_lookup(const struct scmi_protocol_handle *ph, u32 domain) 514{ 515 struct scmi_perf_info *pi = ph->get_priv(ph); 516 517 if (domain >= pi->num_domains) 518 return ERR_PTR(-EINVAL); 519 520 return pi->dom_info + domain; 521} 522 523static const struct scmi_perf_domain_info * 524scmi_perf_info_get(const struct scmi_protocol_handle *ph, u32 domain) 525{ 526 struct perf_dom_info *dom; 527 528 dom = scmi_perf_domain_lookup(ph, domain); 529 if (IS_ERR(dom)) 530 return ERR_PTR(-EINVAL); 531 532 return &dom->info; 533} 534 535static int scmi_perf_msg_limits_set(const struct scmi_protocol_handle *ph, 536 u32 domain, u32 max_perf, u32 min_perf) 537{ 538 int ret; 539 struct scmi_xfer *t; 540 struct scmi_perf_set_limits *limits; 541 542 ret = ph->xops->xfer_get_init(ph, PERF_LIMITS_SET, 543 sizeof(*limits), 0, &t); 544 if (ret) 545 return ret; 546 547 limits = t->tx.buf; 548 limits->domain = cpu_to_le32(domain); 549 limits->max_level = cpu_to_le32(max_perf); 550 limits->min_level = cpu_to_le32(min_perf); 551 552 ret = ph->xops->do_xfer(ph, t); 553 554 ph->xops->xfer_put(ph, t); 555 return ret; 556} 557 558static int __scmi_perf_limits_set(const struct scmi_protocol_handle *ph, 559 struct perf_dom_info *dom, u32 max_perf, 560 u32 min_perf) 561{ 562 if (dom->fc_info && dom->fc_info[PERF_FC_LIMIT].set_addr) { 563 struct scmi_fc_info *fci = &dom->fc_info[PERF_FC_LIMIT]; 564 565 trace_scmi_fc_call(SCMI_PROTOCOL_PERF, PERF_LIMITS_SET, 566 dom->id, min_perf, max_perf); 567 iowrite32(max_perf, fci->set_addr); 568 iowrite32(min_perf, fci->set_addr + 4); 569 ph->hops->fastchannel_db_ring(fci->set_db); 570 return 0; 571 } 572 573 return scmi_perf_msg_limits_set(ph, dom->id, max_perf, min_perf); 574} 575 576static int scmi_perf_limits_set(const struct scmi_protocol_handle *ph, 577 u32 domain, u32 max_perf, u32 min_perf) 578{ 579 struct scmi_perf_info *pi = ph->get_priv(ph); 580 struct perf_dom_info *dom; 581 582 dom = scmi_perf_domain_lookup(ph, domain); 583 if (IS_ERR(dom)) 584 return PTR_ERR(dom); 585 586 if (!dom->set_limits) 587 return -EOPNOTSUPP; 588 589 if (PROTOCOL_REV_MAJOR(pi->version) >= 0x3 && !max_perf && !min_perf) 590 return -EINVAL; 591 592 if (dom->level_indexing_mode) { 593 struct scmi_opp *opp; 594 595 if (min_perf) { 596 opp = xa_load(&dom->opps_by_lvl, min_perf); 597 if (!opp) 598 return -EIO; 599 600 min_perf = opp->level_index; 601 } 602 603 if (max_perf) { 604 opp = xa_load(&dom->opps_by_lvl, max_perf); 605 if (!opp) 606 return -EIO; 607 608 max_perf = opp->level_index; 609 } 610 } 611 612 return __scmi_perf_limits_set(ph, dom, max_perf, min_perf); 613} 614 615static int scmi_perf_msg_limits_get(const struct scmi_protocol_handle *ph, 616 u32 domain, u32 *max_perf, u32 *min_perf) 617{ 618 int ret; 619 struct scmi_xfer *t; 620 struct scmi_perf_get_limits *limits; 621 622 ret = ph->xops->xfer_get_init(ph, PERF_LIMITS_GET, 623 sizeof(__le32), 0, &t); 624 if (ret) 625 return ret; 626 627 put_unaligned_le32(domain, t->tx.buf); 628 629 ret = ph->xops->do_xfer(ph, t); 630 if (!ret) { 631 limits = t->rx.buf; 632 633 *max_perf = le32_to_cpu(limits->max_level); 634 *min_perf = le32_to_cpu(limits->min_level); 635 } 636 637 ph->xops->xfer_put(ph, t); 638 return ret; 639} 640 641static int __scmi_perf_limits_get(const struct scmi_protocol_handle *ph, 642 struct perf_dom_info *dom, u32 *max_perf, 643 u32 *min_perf) 644{ 645 if (dom->fc_info && dom->fc_info[PERF_FC_LIMIT].get_addr) { 646 struct scmi_fc_info *fci = &dom->fc_info[PERF_FC_LIMIT]; 647 648 *max_perf = ioread32(fci->get_addr); 649 *min_perf = ioread32(fci->get_addr + 4); 650 trace_scmi_fc_call(SCMI_PROTOCOL_PERF, PERF_LIMITS_GET, 651 dom->id, *min_perf, *max_perf); 652 return 0; 653 } 654 655 return scmi_perf_msg_limits_get(ph, dom->id, max_perf, min_perf); 656} 657 658static int scmi_perf_limits_get(const struct scmi_protocol_handle *ph, 659 u32 domain, u32 *max_perf, u32 *min_perf) 660{ 661 int ret; 662 struct perf_dom_info *dom; 663 664 dom = scmi_perf_domain_lookup(ph, domain); 665 if (IS_ERR(dom)) 666 return PTR_ERR(dom); 667 668 ret = __scmi_perf_limits_get(ph, dom, max_perf, min_perf); 669 if (ret) 670 return ret; 671 672 if (dom->level_indexing_mode) { 673 struct scmi_opp *opp; 674 675 opp = xa_load(&dom->opps_by_idx, *min_perf); 676 if (!opp) 677 return -EIO; 678 679 *min_perf = opp->perf; 680 681 opp = xa_load(&dom->opps_by_idx, *max_perf); 682 if (!opp) 683 return -EIO; 684 685 *max_perf = opp->perf; 686 } 687 688 return 0; 689} 690 691static int scmi_perf_msg_level_set(const struct scmi_protocol_handle *ph, 692 u32 domain, u32 level, bool poll) 693{ 694 int ret; 695 struct scmi_xfer *t; 696 struct scmi_perf_set_level *lvl; 697 698 ret = ph->xops->xfer_get_init(ph, PERF_LEVEL_SET, sizeof(*lvl), 0, &t); 699 if (ret) 700 return ret; 701 702 t->hdr.poll_completion = poll; 703 lvl = t->tx.buf; 704 lvl->domain = cpu_to_le32(domain); 705 lvl->level = cpu_to_le32(level); 706 707 ret = ph->xops->do_xfer(ph, t); 708 709 ph->xops->xfer_put(ph, t); 710 return ret; 711} 712 713static int __scmi_perf_level_set(const struct scmi_protocol_handle *ph, 714 struct perf_dom_info *dom, u32 level, 715 bool poll) 716{ 717 if (dom->fc_info && dom->fc_info[PERF_FC_LEVEL].set_addr) { 718 struct scmi_fc_info *fci = &dom->fc_info[PERF_FC_LEVEL]; 719 720 trace_scmi_fc_call(SCMI_PROTOCOL_PERF, PERF_LEVEL_SET, 721 dom->id, level, 0); 722 iowrite32(level, fci->set_addr); 723 ph->hops->fastchannel_db_ring(fci->set_db); 724 return 0; 725 } 726 727 return scmi_perf_msg_level_set(ph, dom->id, level, poll); 728} 729 730static int scmi_perf_level_set(const struct scmi_protocol_handle *ph, 731 u32 domain, u32 level, bool poll) 732{ 733 struct perf_dom_info *dom; 734 735 dom = scmi_perf_domain_lookup(ph, domain); 736 if (IS_ERR(dom)) 737 return PTR_ERR(dom); 738 739 if (!dom->info.set_perf) 740 return -EOPNOTSUPP; 741 742 if (dom->level_indexing_mode) { 743 struct scmi_opp *opp; 744 745 opp = xa_load(&dom->opps_by_lvl, level); 746 if (!opp) 747 return -EIO; 748 749 level = opp->level_index; 750 } 751 752 return __scmi_perf_level_set(ph, dom, level, poll); 753} 754 755static int scmi_perf_msg_level_get(const struct scmi_protocol_handle *ph, 756 u32 domain, u32 *level, bool poll) 757{ 758 int ret; 759 struct scmi_xfer *t; 760 761 ret = ph->xops->xfer_get_init(ph, PERF_LEVEL_GET, 762 sizeof(u32), sizeof(u32), &t); 763 if (ret) 764 return ret; 765 766 t->hdr.poll_completion = poll; 767 put_unaligned_le32(domain, t->tx.buf); 768 769 ret = ph->xops->do_xfer(ph, t); 770 if (!ret) 771 *level = get_unaligned_le32(t->rx.buf); 772 773 ph->xops->xfer_put(ph, t); 774 return ret; 775} 776 777static int __scmi_perf_level_get(const struct scmi_protocol_handle *ph, 778 struct perf_dom_info *dom, u32 *level, 779 bool poll) 780{ 781 if (dom->fc_info && dom->fc_info[PERF_FC_LEVEL].get_addr) { 782 *level = ioread32(dom->fc_info[PERF_FC_LEVEL].get_addr); 783 trace_scmi_fc_call(SCMI_PROTOCOL_PERF, PERF_LEVEL_GET, 784 dom->id, *level, 0); 785 return 0; 786 } 787 788 return scmi_perf_msg_level_get(ph, dom->id, level, poll); 789} 790 791static int scmi_perf_level_get(const struct scmi_protocol_handle *ph, 792 u32 domain, u32 *level, bool poll) 793{ 794 int ret; 795 struct perf_dom_info *dom; 796 797 dom = scmi_perf_domain_lookup(ph, domain); 798 if (IS_ERR(dom)) 799 return PTR_ERR(dom); 800 801 ret = __scmi_perf_level_get(ph, dom, level, poll); 802 if (ret) 803 return ret; 804 805 if (dom->level_indexing_mode) { 806 struct scmi_opp *opp; 807 808 opp = xa_load(&dom->opps_by_idx, *level); 809 if (!opp) 810 return -EIO; 811 812 *level = opp->perf; 813 } 814 815 return 0; 816} 817 818static int scmi_perf_level_limits_notify(const struct scmi_protocol_handle *ph, 819 u32 domain, int message_id, 820 bool enable) 821{ 822 int ret; 823 struct scmi_xfer *t; 824 struct scmi_perf_notify_level_or_limits *notify; 825 826 ret = ph->xops->xfer_get_init(ph, message_id, sizeof(*notify), 0, &t); 827 if (ret) 828 return ret; 829 830 notify = t->tx.buf; 831 notify->domain = cpu_to_le32(domain); 832 notify->notify_enable = enable ? cpu_to_le32(BIT(0)) : 0; 833 834 ret = ph->xops->do_xfer(ph, t); 835 836 ph->xops->xfer_put(ph, t); 837 return ret; 838} 839 840static void scmi_perf_domain_init_fc(const struct scmi_protocol_handle *ph, 841 struct perf_dom_info *dom) 842{ 843 struct scmi_fc_info *fc; 844 845 fc = devm_kcalloc(ph->dev, PERF_FC_MAX, sizeof(*fc), GFP_KERNEL); 846 if (!fc) 847 return; 848 849 ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL, 850 PERF_LEVEL_GET, 4, dom->id, 851 &fc[PERF_FC_LEVEL].get_addr, NULL, 852 &fc[PERF_FC_LEVEL].rate_limit); 853 854 ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL, 855 PERF_LIMITS_GET, 8, dom->id, 856 &fc[PERF_FC_LIMIT].get_addr, NULL, 857 &fc[PERF_FC_LIMIT].rate_limit); 858 859 if (dom->info.set_perf) 860 ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL, 861 PERF_LEVEL_SET, 4, dom->id, 862 &fc[PERF_FC_LEVEL].set_addr, 863 &fc[PERF_FC_LEVEL].set_db, 864 &fc[PERF_FC_LEVEL].rate_limit); 865 866 if (dom->set_limits) 867 ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL, 868 PERF_LIMITS_SET, 8, dom->id, 869 &fc[PERF_FC_LIMIT].set_addr, 870 &fc[PERF_FC_LIMIT].set_db, 871 &fc[PERF_FC_LIMIT].rate_limit); 872 873 dom->fc_info = fc; 874} 875 876static int scmi_dvfs_device_opps_add(const struct scmi_protocol_handle *ph, 877 struct device *dev, u32 domain) 878{ 879 int idx, ret; 880 unsigned long freq; 881 struct dev_pm_opp_data data = {}; 882 struct perf_dom_info *dom; 883 884 dom = scmi_perf_domain_lookup(ph, domain); 885 if (IS_ERR(dom)) 886 return PTR_ERR(dom); 887 888 for (idx = 0; idx < dom->opp_count; idx++) { 889 if (!dom->level_indexing_mode) 890 freq = dom->opp[idx].perf * dom->mult_factor; 891 else 892 freq = dom->opp[idx].indicative_freq * dom->mult_factor; 893 894 /* All OPPs above the sustained frequency are treated as turbo */ 895 data.turbo = freq > dom->sustained_freq_khz * 1000; 896 897 data.level = dom->opp[idx].perf; 898 data.freq = freq; 899 900 ret = dev_pm_opp_add_dynamic(dev, &data); 901 if (ret) { 902 dev_warn(dev, "[%d][%s]: Failed to add OPP[%d] %lu\n", 903 domain, dom->info.name, idx, freq); 904 dev_pm_opp_remove_all_dynamic(dev); 905 return ret; 906 } 907 908 dev_dbg(dev, "[%d][%s]:: Registered OPP[%d] %lu\n", 909 domain, dom->info.name, idx, freq); 910 } 911 return 0; 912} 913 914static int 915scmi_dvfs_transition_latency_get(const struct scmi_protocol_handle *ph, 916 u32 domain) 917{ 918 struct perf_dom_info *dom; 919 920 dom = scmi_perf_domain_lookup(ph, domain); 921 if (IS_ERR(dom)) 922 return PTR_ERR(dom); 923 924 /* uS to nS */ 925 return dom->opp[dom->opp_count - 1].trans_latency_us * 1000; 926} 927 928static int 929scmi_dvfs_rate_limit_get(const struct scmi_protocol_handle *ph, 930 u32 domain, u32 *rate_limit) 931{ 932 struct perf_dom_info *dom; 933 934 if (!rate_limit) 935 return -EINVAL; 936 937 dom = scmi_perf_domain_lookup(ph, domain); 938 if (IS_ERR(dom)) 939 return PTR_ERR(dom); 940 941 *rate_limit = dom->rate_limit_us; 942 return 0; 943} 944 945static int scmi_dvfs_freq_set(const struct scmi_protocol_handle *ph, u32 domain, 946 unsigned long freq, bool poll) 947{ 948 unsigned int level; 949 struct perf_dom_info *dom; 950 951 dom = scmi_perf_domain_lookup(ph, domain); 952 if (IS_ERR(dom)) 953 return PTR_ERR(dom); 954 955 if (!dom->level_indexing_mode) { 956 level = freq / dom->mult_factor; 957 } else { 958 struct scmi_opp *opp; 959 960 opp = LOOKUP_BY_FREQ(dom->opps_by_freq, 961 freq / dom->mult_factor); 962 if (!opp) 963 return -EIO; 964 965 level = opp->level_index; 966 } 967 968 return __scmi_perf_level_set(ph, dom, level, poll); 969} 970 971static int scmi_dvfs_freq_get(const struct scmi_protocol_handle *ph, u32 domain, 972 unsigned long *freq, bool poll) 973{ 974 int ret; 975 u32 level; 976 struct perf_dom_info *dom; 977 978 dom = scmi_perf_domain_lookup(ph, domain); 979 if (IS_ERR(dom)) 980 return PTR_ERR(dom); 981 982 ret = __scmi_perf_level_get(ph, dom, &level, poll); 983 if (ret) 984 return ret; 985 986 if (!dom->level_indexing_mode) { 987 *freq = level * dom->mult_factor; 988 } else { 989 struct scmi_opp *opp; 990 991 opp = xa_load(&dom->opps_by_idx, level); 992 if (!opp) 993 return -EIO; 994 995 *freq = opp->indicative_freq * dom->mult_factor; 996 } 997 998 return ret; 999} 1000 1001static int scmi_dvfs_est_power_get(const struct scmi_protocol_handle *ph, 1002 u32 domain, unsigned long *freq, 1003 unsigned long *power) 1004{ 1005 struct perf_dom_info *dom; 1006 unsigned long opp_freq; 1007 int idx, ret = -EINVAL; 1008 struct scmi_opp *opp; 1009 1010 dom = scmi_perf_domain_lookup(ph, domain); 1011 if (IS_ERR(dom)) 1012 return PTR_ERR(dom); 1013 1014 for (opp = dom->opp, idx = 0; idx < dom->opp_count; idx++, opp++) { 1015 if (!dom->level_indexing_mode) 1016 opp_freq = opp->perf * dom->mult_factor; 1017 else 1018 opp_freq = opp->indicative_freq * dom->mult_factor; 1019 1020 if (opp_freq < *freq) 1021 continue; 1022 1023 *freq = opp_freq; 1024 *power = opp->power; 1025 ret = 0; 1026 break; 1027 } 1028 1029 return ret; 1030} 1031 1032static bool scmi_fast_switch_possible(const struct scmi_protocol_handle *ph, 1033 u32 domain) 1034{ 1035 struct perf_dom_info *dom; 1036 1037 dom = scmi_perf_domain_lookup(ph, domain); 1038 if (IS_ERR(dom)) 1039 return false; 1040 1041 return dom->fc_info && dom->fc_info[PERF_FC_LEVEL].set_addr; 1042} 1043 1044static int scmi_fast_switch_rate_limit(const struct scmi_protocol_handle *ph, 1045 u32 domain, u32 *rate_limit) 1046{ 1047 struct perf_dom_info *dom; 1048 1049 if (!rate_limit) 1050 return -EINVAL; 1051 1052 dom = scmi_perf_domain_lookup(ph, domain); 1053 if (IS_ERR(dom)) 1054 return PTR_ERR(dom); 1055 1056 if (!dom->fc_info) 1057 return -EINVAL; 1058 1059 *rate_limit = dom->fc_info[PERF_FC_LEVEL].rate_limit; 1060 return 0; 1061} 1062 1063static enum scmi_power_scale 1064scmi_power_scale_get(const struct scmi_protocol_handle *ph) 1065{ 1066 struct scmi_perf_info *pi = ph->get_priv(ph); 1067 1068 return pi->power_scale; 1069} 1070 1071static const struct scmi_perf_proto_ops perf_proto_ops = { 1072 .num_domains_get = scmi_perf_num_domains_get, 1073 .info_get = scmi_perf_info_get, 1074 .limits_set = scmi_perf_limits_set, 1075 .limits_get = scmi_perf_limits_get, 1076 .level_set = scmi_perf_level_set, 1077 .level_get = scmi_perf_level_get, 1078 .transition_latency_get = scmi_dvfs_transition_latency_get, 1079 .rate_limit_get = scmi_dvfs_rate_limit_get, 1080 .device_opps_add = scmi_dvfs_device_opps_add, 1081 .freq_set = scmi_dvfs_freq_set, 1082 .freq_get = scmi_dvfs_freq_get, 1083 .est_power_get = scmi_dvfs_est_power_get, 1084 .fast_switch_possible = scmi_fast_switch_possible, 1085 .fast_switch_rate_limit = scmi_fast_switch_rate_limit, 1086 .power_scale_get = scmi_power_scale_get, 1087}; 1088 1089static bool scmi_perf_notify_supported(const struct scmi_protocol_handle *ph, 1090 u8 evt_id, u32 src_id) 1091{ 1092 bool supported; 1093 struct perf_dom_info *dom; 1094 1095 if (evt_id >= ARRAY_SIZE(evt_2_cmd)) 1096 return false; 1097 1098 dom = scmi_perf_domain_lookup(ph, src_id); 1099 if (IS_ERR(dom)) 1100 return false; 1101 1102 if (evt_id == SCMI_EVENT_PERFORMANCE_LIMITS_CHANGED) 1103 supported = dom->perf_limit_notify; 1104 else 1105 supported = dom->perf_level_notify; 1106 1107 return supported; 1108} 1109 1110static int scmi_perf_set_notify_enabled(const struct scmi_protocol_handle *ph, 1111 u8 evt_id, u32 src_id, bool enable) 1112{ 1113 int ret, cmd_id; 1114 1115 if (evt_id >= ARRAY_SIZE(evt_2_cmd)) 1116 return -EINVAL; 1117 1118 cmd_id = evt_2_cmd[evt_id]; 1119 ret = scmi_perf_level_limits_notify(ph, src_id, cmd_id, enable); 1120 if (ret) 1121 pr_debug("FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n", 1122 evt_id, src_id, ret); 1123 1124 return ret; 1125} 1126 1127static int 1128scmi_perf_xlate_opp_to_freq(struct perf_dom_info *dom, 1129 unsigned int index, unsigned long *freq) 1130{ 1131 struct scmi_opp *opp; 1132 1133 if (!dom || !freq) 1134 return -EINVAL; 1135 1136 if (!dom->level_indexing_mode) { 1137 opp = xa_load(&dom->opps_by_lvl, index); 1138 if (!opp) 1139 return -ENODEV; 1140 1141 *freq = opp->perf * dom->mult_factor; 1142 } else { 1143 opp = xa_load(&dom->opps_by_idx, index); 1144 if (!opp) 1145 return -ENODEV; 1146 1147 *freq = opp->indicative_freq * dom->mult_factor; 1148 } 1149 1150 return 0; 1151} 1152 1153static void *scmi_perf_fill_custom_report(const struct scmi_protocol_handle *ph, 1154 u8 evt_id, ktime_t timestamp, 1155 const void *payld, size_t payld_sz, 1156 void *report, u32 *src_id) 1157{ 1158 int ret; 1159 void *rep = NULL; 1160 struct perf_dom_info *dom; 1161 1162 switch (evt_id) { 1163 case SCMI_EVENT_PERFORMANCE_LIMITS_CHANGED: 1164 { 1165 const struct scmi_perf_limits_notify_payld *p = payld; 1166 struct scmi_perf_limits_report *r = report; 1167 unsigned long freq_min, freq_max; 1168 1169 if (sizeof(*p) != payld_sz) 1170 break; 1171 1172 r->timestamp = timestamp; 1173 r->agent_id = le32_to_cpu(p->agent_id); 1174 r->domain_id = le32_to_cpu(p->domain_id); 1175 r->range_max = le32_to_cpu(p->range_max); 1176 r->range_min = le32_to_cpu(p->range_min); 1177 /* Check if the reported domain exist at all */ 1178 dom = scmi_perf_domain_lookup(ph, r->domain_id); 1179 if (IS_ERR(dom)) 1180 break; 1181 /* 1182 * Event will be reported from this point on... 1183 * ...even if, later, xlated frequencies were not retrieved. 1184 */ 1185 *src_id = r->domain_id; 1186 rep = r; 1187 1188 ret = scmi_perf_xlate_opp_to_freq(dom, r->range_max, &freq_max); 1189 if (ret) 1190 break; 1191 1192 ret = scmi_perf_xlate_opp_to_freq(dom, r->range_min, &freq_min); 1193 if (ret) 1194 break; 1195 1196 /* Report translated freqs ONLY if both available */ 1197 r->range_max_freq = freq_max; 1198 r->range_min_freq = freq_min; 1199 1200 break; 1201 } 1202 case SCMI_EVENT_PERFORMANCE_LEVEL_CHANGED: 1203 { 1204 const struct scmi_perf_level_notify_payld *p = payld; 1205 struct scmi_perf_level_report *r = report; 1206 unsigned long freq; 1207 1208 if (sizeof(*p) != payld_sz) 1209 break; 1210 1211 r->timestamp = timestamp; 1212 r->agent_id = le32_to_cpu(p->agent_id); 1213 r->domain_id = le32_to_cpu(p->domain_id); 1214 /* Report translated freqs ONLY if available */ 1215 r->performance_level = le32_to_cpu(p->performance_level); 1216 /* Check if the reported domain exist at all */ 1217 dom = scmi_perf_domain_lookup(ph, r->domain_id); 1218 if (IS_ERR(dom)) 1219 break; 1220 /* 1221 * Event will be reported from this point on... 1222 * ...even if, later, xlated frequencies were not retrieved. 1223 */ 1224 *src_id = r->domain_id; 1225 rep = r; 1226 1227 /* Report translated freqs ONLY if available */ 1228 ret = scmi_perf_xlate_opp_to_freq(dom, r->performance_level, 1229 &freq); 1230 if (ret) 1231 break; 1232 1233 r->performance_level_freq = freq; 1234 1235 break; 1236 } 1237 default: 1238 break; 1239 } 1240 1241 return rep; 1242} 1243 1244static int scmi_perf_get_num_sources(const struct scmi_protocol_handle *ph) 1245{ 1246 struct scmi_perf_info *pi = ph->get_priv(ph); 1247 1248 if (!pi) 1249 return -EINVAL; 1250 1251 return pi->num_domains; 1252} 1253 1254static const struct scmi_event perf_events[] = { 1255 { 1256 .id = SCMI_EVENT_PERFORMANCE_LIMITS_CHANGED, 1257 .max_payld_sz = sizeof(struct scmi_perf_limits_notify_payld), 1258 .max_report_sz = sizeof(struct scmi_perf_limits_report), 1259 }, 1260 { 1261 .id = SCMI_EVENT_PERFORMANCE_LEVEL_CHANGED, 1262 .max_payld_sz = sizeof(struct scmi_perf_level_notify_payld), 1263 .max_report_sz = sizeof(struct scmi_perf_level_report), 1264 }, 1265}; 1266 1267static const struct scmi_event_ops perf_event_ops = { 1268 .is_notify_supported = scmi_perf_notify_supported, 1269 .get_num_sources = scmi_perf_get_num_sources, 1270 .set_notify_enabled = scmi_perf_set_notify_enabled, 1271 .fill_custom_report = scmi_perf_fill_custom_report, 1272}; 1273 1274static const struct scmi_protocol_events perf_protocol_events = { 1275 .queue_sz = SCMI_PROTO_QUEUE_SZ, 1276 .ops = &perf_event_ops, 1277 .evts = perf_events, 1278 .num_events = ARRAY_SIZE(perf_events), 1279}; 1280 1281static int scmi_perf_protocol_init(const struct scmi_protocol_handle *ph) 1282{ 1283 int domain, ret; 1284 u32 version; 1285 struct scmi_perf_info *pinfo; 1286 1287 ret = ph->xops->version_get(ph, &version); 1288 if (ret) 1289 return ret; 1290 1291 dev_dbg(ph->dev, "Performance Version %d.%d\n", 1292 PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); 1293 1294 pinfo = devm_kzalloc(ph->dev, sizeof(*pinfo), GFP_KERNEL); 1295 if (!pinfo) 1296 return -ENOMEM; 1297 1298 pinfo->version = version; 1299 1300 ret = scmi_perf_attributes_get(ph, pinfo); 1301 if (ret) 1302 return ret; 1303 1304 pinfo->dom_info = devm_kcalloc(ph->dev, pinfo->num_domains, 1305 sizeof(*pinfo->dom_info), GFP_KERNEL); 1306 if (!pinfo->dom_info) 1307 return -ENOMEM; 1308 1309 for (domain = 0; domain < pinfo->num_domains; domain++) { 1310 struct perf_dom_info *dom = pinfo->dom_info + domain; 1311 1312 dom->id = domain; 1313 scmi_perf_domain_attributes_get(ph, dom, pinfo->notify_lim_cmd, 1314 pinfo->notify_lvl_cmd, version); 1315 scmi_perf_describe_levels_get(ph, dom, version); 1316 1317 if (dom->perf_fastchannels) 1318 scmi_perf_domain_init_fc(ph, dom); 1319 } 1320 1321 ret = devm_add_action_or_reset(ph->dev, scmi_perf_xa_destroy, pinfo); 1322 if (ret) 1323 return ret; 1324 1325 return ph->set_priv(ph, pinfo, version); 1326} 1327 1328static const struct scmi_protocol scmi_perf = { 1329 .id = SCMI_PROTOCOL_PERF, 1330 .owner = THIS_MODULE, 1331 .instance_init = &scmi_perf_protocol_init, 1332 .ops = &perf_proto_ops, 1333 .events = &perf_protocol_events, 1334 .supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION, 1335}; 1336 1337DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(perf, scmi_perf)