perf.c (23892B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * System Control and Management Interface (SCMI) Performance Protocol 4 * 5 * Copyright (C) 2018-2022 ARM Ltd. 6 */ 7 8#define pr_fmt(fmt) "SCMI Notifications PERF - " fmt 9 10#include <linux/bits.h> 11#include <linux/of.h> 12#include <linux/io.h> 13#include <linux/io-64-nonatomic-hi-lo.h> 14#include <linux/module.h> 15#include <linux/platform_device.h> 16#include <linux/pm_opp.h> 17#include <linux/scmi_protocol.h> 18#include <linux/sort.h> 19 20#include "protocols.h" 21#include "notify.h" 22 23#define MAX_OPPS 16 24 25enum scmi_performance_protocol_cmd { 26 PERF_DOMAIN_ATTRIBUTES = 0x3, 27 PERF_DESCRIBE_LEVELS = 0x4, 28 PERF_LIMITS_SET = 0x5, 29 PERF_LIMITS_GET = 0x6, 30 PERF_LEVEL_SET = 0x7, 31 PERF_LEVEL_GET = 0x8, 32 PERF_NOTIFY_LIMITS = 0x9, 33 PERF_NOTIFY_LEVEL = 0xa, 34 PERF_DESCRIBE_FASTCHANNEL = 0xb, 35 PERF_DOMAIN_NAME_GET = 0xc, 36}; 37 38struct scmi_opp { 39 u32 perf; 40 u32 power; 41 u32 trans_latency_us; 42}; 43 44struct scmi_msg_resp_perf_attributes { 45 __le16 num_domains; 46 __le16 flags; 47#define POWER_SCALE_IN_MILLIWATT(x) ((x) & BIT(0)) 48#define POWER_SCALE_IN_MICROWATT(x) ((x) & BIT(1)) 49 __le32 stats_addr_low; 50 __le32 stats_addr_high; 51 __le32 stats_size; 52}; 53 54struct scmi_msg_resp_perf_domain_attributes { 55 __le32 flags; 56#define SUPPORTS_SET_LIMITS(x) ((x) & BIT(31)) 57#define SUPPORTS_SET_PERF_LVL(x) ((x) & BIT(30)) 58#define SUPPORTS_PERF_LIMIT_NOTIFY(x) ((x) & BIT(29)) 59#define SUPPORTS_PERF_LEVEL_NOTIFY(x) ((x) & BIT(28)) 60#define SUPPORTS_PERF_FASTCHANNELS(x) ((x) & BIT(27)) 61#define SUPPORTS_EXTENDED_NAMES(x) ((x) & BIT(26)) 62 __le32 rate_limit_us; 63 __le32 sustained_freq_khz; 64 __le32 sustained_perf_level; 65 u8 name[SCMI_SHORT_NAME_MAX_SIZE]; 66}; 67 68struct scmi_msg_perf_describe_levels { 69 __le32 domain; 70 __le32 level_index; 71}; 72 73struct scmi_perf_set_limits { 74 __le32 domain; 75 __le32 max_level; 76 __le32 min_level; 77}; 78 79struct scmi_perf_get_limits { 80 __le32 max_level; 81 __le32 min_level; 82}; 83 84struct scmi_perf_set_level { 85 __le32 domain; 86 __le32 level; 87}; 88 89struct scmi_perf_notify_level_or_limits { 90 __le32 domain; 91 __le32 notify_enable; 92}; 93 94struct scmi_perf_limits_notify_payld { 95 __le32 agent_id; 96 __le32 domain_id; 97 __le32 range_max; 98 __le32 range_min; 99}; 100 101struct scmi_perf_level_notify_payld { 102 __le32 agent_id; 103 __le32 domain_id; 104 __le32 performance_level; 105}; 106 107struct scmi_msg_resp_perf_describe_levels { 108 __le16 num_returned; 109 __le16 num_remaining; 110 struct { 111 __le32 perf_val; 112 __le32 power; 113 __le16 transition_latency_us; 114 __le16 reserved; 115 } opp[]; 116}; 117 118struct scmi_perf_get_fc_info { 119 __le32 domain; 120 __le32 message_id; 121}; 122 123struct scmi_msg_resp_perf_desc_fc { 124 __le32 attr; 125#define SUPPORTS_DOORBELL(x) ((x) & BIT(0)) 126#define DOORBELL_REG_WIDTH(x) FIELD_GET(GENMASK(2, 1), (x)) 127 __le32 rate_limit; 128 __le32 chan_addr_low; 129 __le32 chan_addr_high; 130 __le32 chan_size; 131 __le32 db_addr_low; 132 __le32 db_addr_high; 133 __le32 db_set_lmask; 134 __le32 db_set_hmask; 135 __le32 db_preserve_lmask; 136 __le32 db_preserve_hmask; 137}; 138 139struct scmi_fc_db_info { 140 int width; 141 u64 set; 142 u64 mask; 143 void __iomem *addr; 144}; 145 146struct scmi_fc_info { 147 void __iomem *level_set_addr; 148 void __iomem *limit_set_addr; 149 void __iomem *level_get_addr; 150 void __iomem *limit_get_addr; 151 struct scmi_fc_db_info *level_set_db; 152 struct scmi_fc_db_info *limit_set_db; 153}; 154 155struct perf_dom_info { 156 bool set_limits; 157 bool set_perf; 158 bool perf_limit_notify; 159 bool perf_level_notify; 160 bool perf_fastchannels; 161 u32 opp_count; 162 u32 sustained_freq_khz; 163 u32 sustained_perf_level; 164 u32 mult_factor; 165 char name[SCMI_MAX_STR_SIZE]; 166 struct scmi_opp opp[MAX_OPPS]; 167 struct scmi_fc_info *fc_info; 168}; 169 170struct scmi_perf_info { 171 u32 version; 172 int num_domains; 173 bool power_scale_mw; 174 bool power_scale_uw; 175 u64 stats_addr; 176 u32 stats_size; 177 struct perf_dom_info *dom_info; 178}; 179 180static enum scmi_performance_protocol_cmd evt_2_cmd[] = { 181 PERF_NOTIFY_LIMITS, 182 PERF_NOTIFY_LEVEL, 183}; 184 185static int scmi_perf_attributes_get(const struct scmi_protocol_handle *ph, 186 struct scmi_perf_info *pi) 187{ 188 int ret; 189 struct scmi_xfer *t; 190 struct scmi_msg_resp_perf_attributes *attr; 191 192 ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, 0, 193 sizeof(*attr), &t); 194 if (ret) 195 return ret; 196 197 attr = t->rx.buf; 198 199 ret = ph->xops->do_xfer(ph, t); 200 if (!ret) { 201 u16 flags = le16_to_cpu(attr->flags); 202 203 pi->num_domains = le16_to_cpu(attr->num_domains); 204 pi->power_scale_mw = POWER_SCALE_IN_MILLIWATT(flags); 205 if (PROTOCOL_REV_MAJOR(pi->version) >= 0x3) 206 pi->power_scale_uw = POWER_SCALE_IN_MICROWATT(flags); 207 pi->stats_addr = le32_to_cpu(attr->stats_addr_low) | 208 (u64)le32_to_cpu(attr->stats_addr_high) << 32; 209 pi->stats_size = le32_to_cpu(attr->stats_size); 210 } 211 212 ph->xops->xfer_put(ph, t); 213 return ret; 214} 215 216static int 217scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph, 218 u32 domain, struct perf_dom_info *dom_info, 219 u32 version) 220{ 221 int ret; 222 u32 flags; 223 struct scmi_xfer *t; 224 struct scmi_msg_resp_perf_domain_attributes *attr; 225 226 ret = ph->xops->xfer_get_init(ph, PERF_DOMAIN_ATTRIBUTES, 227 sizeof(domain), sizeof(*attr), &t); 228 if (ret) 229 return ret; 230 231 put_unaligned_le32(domain, t->tx.buf); 232 attr = t->rx.buf; 233 234 ret = ph->xops->do_xfer(ph, t); 235 if (!ret) { 236 flags = le32_to_cpu(attr->flags); 237 238 dom_info->set_limits = SUPPORTS_SET_LIMITS(flags); 239 dom_info->set_perf = SUPPORTS_SET_PERF_LVL(flags); 240 dom_info->perf_limit_notify = SUPPORTS_PERF_LIMIT_NOTIFY(flags); 241 dom_info->perf_level_notify = SUPPORTS_PERF_LEVEL_NOTIFY(flags); 242 dom_info->perf_fastchannels = SUPPORTS_PERF_FASTCHANNELS(flags); 243 dom_info->sustained_freq_khz = 244 le32_to_cpu(attr->sustained_freq_khz); 245 dom_info->sustained_perf_level = 246 le32_to_cpu(attr->sustained_perf_level); 247 if (!dom_info->sustained_freq_khz || 248 !dom_info->sustained_perf_level) 249 /* CPUFreq converts to kHz, hence default 1000 */ 250 dom_info->mult_factor = 1000; 251 else 252 dom_info->mult_factor = 253 (dom_info->sustained_freq_khz * 1000) / 254 dom_info->sustained_perf_level; 255 strscpy(dom_info->name, attr->name, SCMI_SHORT_NAME_MAX_SIZE); 256 } 257 258 ph->xops->xfer_put(ph, t); 259 260 /* 261 * If supported overwrite short name with the extended one; 262 * on error just carry on and use already provided short name. 263 */ 264 if (!ret && PROTOCOL_REV_MAJOR(version) >= 0x3 && 265 SUPPORTS_EXTENDED_NAMES(flags)) 266 ph->hops->extended_name_get(ph, PERF_DOMAIN_NAME_GET, domain, 267 dom_info->name, SCMI_MAX_STR_SIZE); 268 269 return ret; 270} 271 272static int opp_cmp_func(const void *opp1, const void *opp2) 273{ 274 const struct scmi_opp *t1 = opp1, *t2 = opp2; 275 276 return t1->perf - t2->perf; 277} 278 279struct scmi_perf_ipriv { 280 u32 domain; 281 struct perf_dom_info *perf_dom; 282}; 283 284static void iter_perf_levels_prepare_message(void *message, 285 unsigned int desc_index, 286 const void *priv) 287{ 288 struct scmi_msg_perf_describe_levels *msg = message; 289 const struct scmi_perf_ipriv *p = priv; 290 291 msg->domain = cpu_to_le32(p->domain); 292 /* Set the number of OPPs to be skipped/already read */ 293 msg->level_index = cpu_to_le32(desc_index); 294} 295 296static int iter_perf_levels_update_state(struct scmi_iterator_state *st, 297 const void *response, void *priv) 298{ 299 const struct scmi_msg_resp_perf_describe_levels *r = response; 300 301 st->num_returned = le16_to_cpu(r->num_returned); 302 st->num_remaining = le16_to_cpu(r->num_remaining); 303 304 return 0; 305} 306 307static int 308iter_perf_levels_process_response(const struct scmi_protocol_handle *ph, 309 const void *response, 310 struct scmi_iterator_state *st, void *priv) 311{ 312 struct scmi_opp *opp; 313 const struct scmi_msg_resp_perf_describe_levels *r = response; 314 struct scmi_perf_ipriv *p = priv; 315 316 opp = &p->perf_dom->opp[st->desc_index + st->loop_idx]; 317 opp->perf = le32_to_cpu(r->opp[st->loop_idx].perf_val); 318 opp->power = le32_to_cpu(r->opp[st->loop_idx].power); 319 opp->trans_latency_us = 320 le16_to_cpu(r->opp[st->loop_idx].transition_latency_us); 321 p->perf_dom->opp_count++; 322 323 dev_dbg(ph->dev, "Level %d Power %d Latency %dus\n", 324 opp->perf, opp->power, opp->trans_latency_us); 325 326 return 0; 327} 328 329static int 330scmi_perf_describe_levels_get(const struct scmi_protocol_handle *ph, u32 domain, 331 struct perf_dom_info *perf_dom) 332{ 333 int ret; 334 void *iter; 335 struct scmi_iterator_ops ops = { 336 .prepare_message = iter_perf_levels_prepare_message, 337 .update_state = iter_perf_levels_update_state, 338 .process_response = iter_perf_levels_process_response, 339 }; 340 struct scmi_perf_ipriv ppriv = { 341 .domain = domain, 342 .perf_dom = perf_dom, 343 }; 344 345 iter = ph->hops->iter_response_init(ph, &ops, MAX_OPPS, 346 PERF_DESCRIBE_LEVELS, 347 sizeof(struct scmi_msg_perf_describe_levels), 348 &ppriv); 349 if (IS_ERR(iter)) 350 return PTR_ERR(iter); 351 352 ret = ph->hops->iter_response_run(iter); 353 if (ret) 354 return ret; 355 356 if (perf_dom->opp_count) 357 sort(perf_dom->opp, perf_dom->opp_count, 358 sizeof(struct scmi_opp), opp_cmp_func, NULL); 359 360 return ret; 361} 362 363#define SCMI_PERF_FC_RING_DB(w) \ 364do { \ 365 u##w val = 0; \ 366 \ 367 if (db->mask) \ 368 val = ioread##w(db->addr) & db->mask; \ 369 iowrite##w((u##w)db->set | val, db->addr); \ 370} while (0) 371 372static void scmi_perf_fc_ring_db(struct scmi_fc_db_info *db) 373{ 374 if (!db || !db->addr) 375 return; 376 377 if (db->width == 1) 378 SCMI_PERF_FC_RING_DB(8); 379 else if (db->width == 2) 380 SCMI_PERF_FC_RING_DB(16); 381 else if (db->width == 4) 382 SCMI_PERF_FC_RING_DB(32); 383 else /* db->width == 8 */ 384#ifdef CONFIG_64BIT 385 SCMI_PERF_FC_RING_DB(64); 386#else 387 { 388 u64 val = 0; 389 390 if (db->mask) 391 val = ioread64_hi_lo(db->addr) & db->mask; 392 iowrite64_hi_lo(db->set | val, db->addr); 393 } 394#endif 395} 396 397static int scmi_perf_mb_limits_set(const struct scmi_protocol_handle *ph, 398 u32 domain, u32 max_perf, u32 min_perf) 399{ 400 int ret; 401 struct scmi_xfer *t; 402 struct scmi_perf_set_limits *limits; 403 404 ret = ph->xops->xfer_get_init(ph, PERF_LIMITS_SET, 405 sizeof(*limits), 0, &t); 406 if (ret) 407 return ret; 408 409 limits = t->tx.buf; 410 limits->domain = cpu_to_le32(domain); 411 limits->max_level = cpu_to_le32(max_perf); 412 limits->min_level = cpu_to_le32(min_perf); 413 414 ret = ph->xops->do_xfer(ph, t); 415 416 ph->xops->xfer_put(ph, t); 417 return ret; 418} 419 420static int scmi_perf_limits_set(const struct scmi_protocol_handle *ph, 421 u32 domain, u32 max_perf, u32 min_perf) 422{ 423 struct scmi_perf_info *pi = ph->get_priv(ph); 424 struct perf_dom_info *dom = pi->dom_info + domain; 425 426 if (PROTOCOL_REV_MAJOR(pi->version) >= 0x3 && !max_perf && !min_perf) 427 return -EINVAL; 428 429 if (dom->fc_info && dom->fc_info->limit_set_addr) { 430 iowrite32(max_perf, dom->fc_info->limit_set_addr); 431 iowrite32(min_perf, dom->fc_info->limit_set_addr + 4); 432 scmi_perf_fc_ring_db(dom->fc_info->limit_set_db); 433 return 0; 434 } 435 436 return scmi_perf_mb_limits_set(ph, domain, max_perf, min_perf); 437} 438 439static int scmi_perf_mb_limits_get(const struct scmi_protocol_handle *ph, 440 u32 domain, u32 *max_perf, u32 *min_perf) 441{ 442 int ret; 443 struct scmi_xfer *t; 444 struct scmi_perf_get_limits *limits; 445 446 ret = ph->xops->xfer_get_init(ph, PERF_LIMITS_GET, 447 sizeof(__le32), 0, &t); 448 if (ret) 449 return ret; 450 451 put_unaligned_le32(domain, t->tx.buf); 452 453 ret = ph->xops->do_xfer(ph, t); 454 if (!ret) { 455 limits = t->rx.buf; 456 457 *max_perf = le32_to_cpu(limits->max_level); 458 *min_perf = le32_to_cpu(limits->min_level); 459 } 460 461 ph->xops->xfer_put(ph, t); 462 return ret; 463} 464 465static int scmi_perf_limits_get(const struct scmi_protocol_handle *ph, 466 u32 domain, u32 *max_perf, u32 *min_perf) 467{ 468 struct scmi_perf_info *pi = ph->get_priv(ph); 469 struct perf_dom_info *dom = pi->dom_info + domain; 470 471 if (dom->fc_info && dom->fc_info->limit_get_addr) { 472 *max_perf = ioread32(dom->fc_info->limit_get_addr); 473 *min_perf = ioread32(dom->fc_info->limit_get_addr + 4); 474 return 0; 475 } 476 477 return scmi_perf_mb_limits_get(ph, domain, max_perf, min_perf); 478} 479 480static int scmi_perf_mb_level_set(const struct scmi_protocol_handle *ph, 481 u32 domain, u32 level, bool poll) 482{ 483 int ret; 484 struct scmi_xfer *t; 485 struct scmi_perf_set_level *lvl; 486 487 ret = ph->xops->xfer_get_init(ph, PERF_LEVEL_SET, sizeof(*lvl), 0, &t); 488 if (ret) 489 return ret; 490 491 t->hdr.poll_completion = poll; 492 lvl = t->tx.buf; 493 lvl->domain = cpu_to_le32(domain); 494 lvl->level = cpu_to_le32(level); 495 496 ret = ph->xops->do_xfer(ph, t); 497 498 ph->xops->xfer_put(ph, t); 499 return ret; 500} 501 502static int scmi_perf_level_set(const struct scmi_protocol_handle *ph, 503 u32 domain, u32 level, bool poll) 504{ 505 struct scmi_perf_info *pi = ph->get_priv(ph); 506 struct perf_dom_info *dom = pi->dom_info + domain; 507 508 if (dom->fc_info && dom->fc_info->level_set_addr) { 509 iowrite32(level, dom->fc_info->level_set_addr); 510 scmi_perf_fc_ring_db(dom->fc_info->level_set_db); 511 return 0; 512 } 513 514 return scmi_perf_mb_level_set(ph, domain, level, poll); 515} 516 517static int scmi_perf_mb_level_get(const struct scmi_protocol_handle *ph, 518 u32 domain, u32 *level, bool poll) 519{ 520 int ret; 521 struct scmi_xfer *t; 522 523 ret = ph->xops->xfer_get_init(ph, PERF_LEVEL_GET, 524 sizeof(u32), sizeof(u32), &t); 525 if (ret) 526 return ret; 527 528 t->hdr.poll_completion = poll; 529 put_unaligned_le32(domain, t->tx.buf); 530 531 ret = ph->xops->do_xfer(ph, t); 532 if (!ret) 533 *level = get_unaligned_le32(t->rx.buf); 534 535 ph->xops->xfer_put(ph, t); 536 return ret; 537} 538 539static int scmi_perf_level_get(const struct scmi_protocol_handle *ph, 540 u32 domain, u32 *level, bool poll) 541{ 542 struct scmi_perf_info *pi = ph->get_priv(ph); 543 struct perf_dom_info *dom = pi->dom_info + domain; 544 545 if (dom->fc_info && dom->fc_info->level_get_addr) { 546 *level = ioread32(dom->fc_info->level_get_addr); 547 return 0; 548 } 549 550 return scmi_perf_mb_level_get(ph, domain, level, poll); 551} 552 553static int scmi_perf_level_limits_notify(const struct scmi_protocol_handle *ph, 554 u32 domain, int message_id, 555 bool enable) 556{ 557 int ret; 558 struct scmi_xfer *t; 559 struct scmi_perf_notify_level_or_limits *notify; 560 561 ret = ph->xops->xfer_get_init(ph, message_id, sizeof(*notify), 0, &t); 562 if (ret) 563 return ret; 564 565 notify = t->tx.buf; 566 notify->domain = cpu_to_le32(domain); 567 notify->notify_enable = enable ? cpu_to_le32(BIT(0)) : 0; 568 569 ret = ph->xops->do_xfer(ph, t); 570 571 ph->xops->xfer_put(ph, t); 572 return ret; 573} 574 575static bool scmi_perf_fc_size_is_valid(u32 msg, u32 size) 576{ 577 if ((msg == PERF_LEVEL_GET || msg == PERF_LEVEL_SET) && size == 4) 578 return true; 579 if ((msg == PERF_LIMITS_GET || msg == PERF_LIMITS_SET) && size == 8) 580 return true; 581 return false; 582} 583 584static void 585scmi_perf_domain_desc_fc(const struct scmi_protocol_handle *ph, u32 domain, 586 u32 message_id, void __iomem **p_addr, 587 struct scmi_fc_db_info **p_db) 588{ 589 int ret; 590 u32 flags; 591 u64 phys_addr; 592 u8 size; 593 void __iomem *addr; 594 struct scmi_xfer *t; 595 struct scmi_fc_db_info *db; 596 struct scmi_perf_get_fc_info *info; 597 struct scmi_msg_resp_perf_desc_fc *resp; 598 599 if (!p_addr) 600 return; 601 602 ret = ph->xops->xfer_get_init(ph, PERF_DESCRIBE_FASTCHANNEL, 603 sizeof(*info), sizeof(*resp), &t); 604 if (ret) 605 return; 606 607 info = t->tx.buf; 608 info->domain = cpu_to_le32(domain); 609 info->message_id = cpu_to_le32(message_id); 610 611 ret = ph->xops->do_xfer(ph, t); 612 if (ret) 613 goto err_xfer; 614 615 resp = t->rx.buf; 616 flags = le32_to_cpu(resp->attr); 617 size = le32_to_cpu(resp->chan_size); 618 if (!scmi_perf_fc_size_is_valid(message_id, size)) 619 goto err_xfer; 620 621 phys_addr = le32_to_cpu(resp->chan_addr_low); 622 phys_addr |= (u64)le32_to_cpu(resp->chan_addr_high) << 32; 623 addr = devm_ioremap(ph->dev, phys_addr, size); 624 if (!addr) 625 goto err_xfer; 626 *p_addr = addr; 627 628 if (p_db && SUPPORTS_DOORBELL(flags)) { 629 db = devm_kzalloc(ph->dev, sizeof(*db), GFP_KERNEL); 630 if (!db) 631 goto err_xfer; 632 633 size = 1 << DOORBELL_REG_WIDTH(flags); 634 phys_addr = le32_to_cpu(resp->db_addr_low); 635 phys_addr |= (u64)le32_to_cpu(resp->db_addr_high) << 32; 636 addr = devm_ioremap(ph->dev, phys_addr, size); 637 if (!addr) 638 goto err_xfer; 639 640 db->addr = addr; 641 db->width = size; 642 db->set = le32_to_cpu(resp->db_set_lmask); 643 db->set |= (u64)le32_to_cpu(resp->db_set_hmask) << 32; 644 db->mask = le32_to_cpu(resp->db_preserve_lmask); 645 db->mask |= (u64)le32_to_cpu(resp->db_preserve_hmask) << 32; 646 *p_db = db; 647 } 648err_xfer: 649 ph->xops->xfer_put(ph, t); 650} 651 652static void scmi_perf_domain_init_fc(const struct scmi_protocol_handle *ph, 653 u32 domain, struct scmi_fc_info **p_fc) 654{ 655 struct scmi_fc_info *fc; 656 657 fc = devm_kzalloc(ph->dev, sizeof(*fc), GFP_KERNEL); 658 if (!fc) 659 return; 660 661 scmi_perf_domain_desc_fc(ph, domain, PERF_LEVEL_SET, 662 &fc->level_set_addr, &fc->level_set_db); 663 scmi_perf_domain_desc_fc(ph, domain, PERF_LEVEL_GET, 664 &fc->level_get_addr, NULL); 665 scmi_perf_domain_desc_fc(ph, domain, PERF_LIMITS_SET, 666 &fc->limit_set_addr, &fc->limit_set_db); 667 scmi_perf_domain_desc_fc(ph, domain, PERF_LIMITS_GET, 668 &fc->limit_get_addr, NULL); 669 *p_fc = fc; 670} 671 672/* Device specific ops */ 673static int scmi_dev_domain_id(struct device *dev) 674{ 675 struct of_phandle_args clkspec; 676 677 if (of_parse_phandle_with_args(dev->of_node, "clocks", "#clock-cells", 678 0, &clkspec)) 679 return -EINVAL; 680 681 return clkspec.args[0]; 682} 683 684static int scmi_dvfs_device_opps_add(const struct scmi_protocol_handle *ph, 685 struct device *dev) 686{ 687 int idx, ret, domain; 688 unsigned long freq; 689 struct scmi_opp *opp; 690 struct perf_dom_info *dom; 691 struct scmi_perf_info *pi = ph->get_priv(ph); 692 693 domain = scmi_dev_domain_id(dev); 694 if (domain < 0) 695 return domain; 696 697 dom = pi->dom_info + domain; 698 699 for (opp = dom->opp, idx = 0; idx < dom->opp_count; idx++, opp++) { 700 freq = opp->perf * dom->mult_factor; 701 702 ret = dev_pm_opp_add(dev, freq, 0); 703 if (ret) { 704 dev_warn(dev, "failed to add opp %luHz\n", freq); 705 706 while (idx-- > 0) { 707 freq = (--opp)->perf * dom->mult_factor; 708 dev_pm_opp_remove(dev, freq); 709 } 710 return ret; 711 } 712 } 713 return 0; 714} 715 716static int 717scmi_dvfs_transition_latency_get(const struct scmi_protocol_handle *ph, 718 struct device *dev) 719{ 720 struct perf_dom_info *dom; 721 struct scmi_perf_info *pi = ph->get_priv(ph); 722 int domain = scmi_dev_domain_id(dev); 723 724 if (domain < 0) 725 return domain; 726 727 dom = pi->dom_info + domain; 728 /* uS to nS */ 729 return dom->opp[dom->opp_count - 1].trans_latency_us * 1000; 730} 731 732static int scmi_dvfs_freq_set(const struct scmi_protocol_handle *ph, u32 domain, 733 unsigned long freq, bool poll) 734{ 735 struct scmi_perf_info *pi = ph->get_priv(ph); 736 struct perf_dom_info *dom = pi->dom_info + domain; 737 738 return scmi_perf_level_set(ph, domain, freq / dom->mult_factor, poll); 739} 740 741static int scmi_dvfs_freq_get(const struct scmi_protocol_handle *ph, u32 domain, 742 unsigned long *freq, bool poll) 743{ 744 int ret; 745 u32 level; 746 struct scmi_perf_info *pi = ph->get_priv(ph); 747 struct perf_dom_info *dom = pi->dom_info + domain; 748 749 ret = scmi_perf_level_get(ph, domain, &level, poll); 750 if (!ret) 751 *freq = level * dom->mult_factor; 752 753 return ret; 754} 755 756static int scmi_dvfs_est_power_get(const struct scmi_protocol_handle *ph, 757 u32 domain, unsigned long *freq, 758 unsigned long *power) 759{ 760 struct scmi_perf_info *pi = ph->get_priv(ph); 761 struct perf_dom_info *dom; 762 unsigned long opp_freq; 763 int idx, ret = -EINVAL; 764 struct scmi_opp *opp; 765 766 dom = pi->dom_info + domain; 767 if (!dom) 768 return -EIO; 769 770 for (opp = dom->opp, idx = 0; idx < dom->opp_count; idx++, opp++) { 771 opp_freq = opp->perf * dom->mult_factor; 772 if (opp_freq < *freq) 773 continue; 774 775 *freq = opp_freq; 776 *power = opp->power; 777 ret = 0; 778 break; 779 } 780 781 return ret; 782} 783 784static bool scmi_fast_switch_possible(const struct scmi_protocol_handle *ph, 785 struct device *dev) 786{ 787 struct perf_dom_info *dom; 788 struct scmi_perf_info *pi = ph->get_priv(ph); 789 790 dom = pi->dom_info + scmi_dev_domain_id(dev); 791 792 return dom->fc_info && dom->fc_info->level_set_addr; 793} 794 795static bool scmi_power_scale_mw_get(const struct scmi_protocol_handle *ph) 796{ 797 struct scmi_perf_info *pi = ph->get_priv(ph); 798 799 return pi->power_scale_mw; 800} 801 802static const struct scmi_perf_proto_ops perf_proto_ops = { 803 .limits_set = scmi_perf_limits_set, 804 .limits_get = scmi_perf_limits_get, 805 .level_set = scmi_perf_level_set, 806 .level_get = scmi_perf_level_get, 807 .device_domain_id = scmi_dev_domain_id, 808 .transition_latency_get = scmi_dvfs_transition_latency_get, 809 .device_opps_add = scmi_dvfs_device_opps_add, 810 .freq_set = scmi_dvfs_freq_set, 811 .freq_get = scmi_dvfs_freq_get, 812 .est_power_get = scmi_dvfs_est_power_get, 813 .fast_switch_possible = scmi_fast_switch_possible, 814 .power_scale_mw_get = scmi_power_scale_mw_get, 815}; 816 817static int scmi_perf_set_notify_enabled(const struct scmi_protocol_handle *ph, 818 u8 evt_id, u32 src_id, bool enable) 819{ 820 int ret, cmd_id; 821 822 if (evt_id >= ARRAY_SIZE(evt_2_cmd)) 823 return -EINVAL; 824 825 cmd_id = evt_2_cmd[evt_id]; 826 ret = scmi_perf_level_limits_notify(ph, src_id, cmd_id, enable); 827 if (ret) 828 pr_debug("FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n", 829 evt_id, src_id, ret); 830 831 return ret; 832} 833 834static void *scmi_perf_fill_custom_report(const struct scmi_protocol_handle *ph, 835 u8 evt_id, ktime_t timestamp, 836 const void *payld, size_t payld_sz, 837 void *report, u32 *src_id) 838{ 839 void *rep = NULL; 840 841 switch (evt_id) { 842 case SCMI_EVENT_PERFORMANCE_LIMITS_CHANGED: 843 { 844 const struct scmi_perf_limits_notify_payld *p = payld; 845 struct scmi_perf_limits_report *r = report; 846 847 if (sizeof(*p) != payld_sz) 848 break; 849 850 r->timestamp = timestamp; 851 r->agent_id = le32_to_cpu(p->agent_id); 852 r->domain_id = le32_to_cpu(p->domain_id); 853 r->range_max = le32_to_cpu(p->range_max); 854 r->range_min = le32_to_cpu(p->range_min); 855 *src_id = r->domain_id; 856 rep = r; 857 break; 858 } 859 case SCMI_EVENT_PERFORMANCE_LEVEL_CHANGED: 860 { 861 const struct scmi_perf_level_notify_payld *p = payld; 862 struct scmi_perf_level_report *r = report; 863 864 if (sizeof(*p) != payld_sz) 865 break; 866 867 r->timestamp = timestamp; 868 r->agent_id = le32_to_cpu(p->agent_id); 869 r->domain_id = le32_to_cpu(p->domain_id); 870 r->performance_level = le32_to_cpu(p->performance_level); 871 *src_id = r->domain_id; 872 rep = r; 873 break; 874 } 875 default: 876 break; 877 } 878 879 return rep; 880} 881 882static int scmi_perf_get_num_sources(const struct scmi_protocol_handle *ph) 883{ 884 struct scmi_perf_info *pi = ph->get_priv(ph); 885 886 if (!pi) 887 return -EINVAL; 888 889 return pi->num_domains; 890} 891 892static const struct scmi_event perf_events[] = { 893 { 894 .id = SCMI_EVENT_PERFORMANCE_LIMITS_CHANGED, 895 .max_payld_sz = sizeof(struct scmi_perf_limits_notify_payld), 896 .max_report_sz = sizeof(struct scmi_perf_limits_report), 897 }, 898 { 899 .id = SCMI_EVENT_PERFORMANCE_LEVEL_CHANGED, 900 .max_payld_sz = sizeof(struct scmi_perf_level_notify_payld), 901 .max_report_sz = sizeof(struct scmi_perf_level_report), 902 }, 903}; 904 905static const struct scmi_event_ops perf_event_ops = { 906 .get_num_sources = scmi_perf_get_num_sources, 907 .set_notify_enabled = scmi_perf_set_notify_enabled, 908 .fill_custom_report = scmi_perf_fill_custom_report, 909}; 910 911static const struct scmi_protocol_events perf_protocol_events = { 912 .queue_sz = SCMI_PROTO_QUEUE_SZ, 913 .ops = &perf_event_ops, 914 .evts = perf_events, 915 .num_events = ARRAY_SIZE(perf_events), 916}; 917 918static int scmi_perf_protocol_init(const struct scmi_protocol_handle *ph) 919{ 920 int domain, ret; 921 u32 version; 922 struct scmi_perf_info *pinfo; 923 924 ret = ph->xops->version_get(ph, &version); 925 if (ret) 926 return ret; 927 928 dev_dbg(ph->dev, "Performance Version %d.%d\n", 929 PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); 930 931 pinfo = devm_kzalloc(ph->dev, sizeof(*pinfo), GFP_KERNEL); 932 if (!pinfo) 933 return -ENOMEM; 934 935 ret = scmi_perf_attributes_get(ph, pinfo); 936 if (ret) 937 return ret; 938 939 pinfo->dom_info = devm_kcalloc(ph->dev, pinfo->num_domains, 940 sizeof(*pinfo->dom_info), GFP_KERNEL); 941 if (!pinfo->dom_info) 942 return -ENOMEM; 943 944 for (domain = 0; domain < pinfo->num_domains; domain++) { 945 struct perf_dom_info *dom = pinfo->dom_info + domain; 946 947 scmi_perf_domain_attributes_get(ph, domain, dom, version); 948 scmi_perf_describe_levels_get(ph, domain, dom); 949 950 if (dom->perf_fastchannels) 951 scmi_perf_domain_init_fc(ph, domain, &dom->fc_info); 952 } 953 954 pinfo->version = version; 955 956 return ph->set_priv(ph, pinfo); 957} 958 959static const struct scmi_protocol scmi_perf = { 960 .id = SCMI_PROTOCOL_PERF, 961 .owner = THIS_MODULE, 962 .instance_init = &scmi_perf_protocol_init, 963 .ops = &perf_proto_ops, 964 .events = &perf_protocol_events, 965}; 966 967DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(perf, scmi_perf)