1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * System Control and Management Interface (SCMI) Powercap Protocol 4 * 5 * Copyright (C) 2022 ARM Ltd. 6 */ 7 8 #define pr_fmt(fmt) "SCMI Notifications POWERCAP - " fmt 9 10 #include <linux/bitfield.h> 11 #include <linux/io.h> 12 #include <linux/module.h> 13 #include <linux/scmi_protocol.h> 14 15 #include <trace/events/scmi.h> 16 17 #include "protocols.h" 18 #include "notify.h" 19 20 enum scmi_powercap_protocol_cmd { 21 POWERCAP_DOMAIN_ATTRIBUTES = 0x3, 22 POWERCAP_CAP_GET = 0x4, 23 POWERCAP_CAP_SET = 0x5, 24 POWERCAP_PAI_GET = 0x6, 25 POWERCAP_PAI_SET = 0x7, 26 POWERCAP_DOMAIN_NAME_GET = 0x8, 27 POWERCAP_MEASUREMENTS_GET = 0x9, 28 POWERCAP_CAP_NOTIFY = 0xa, 29 POWERCAP_MEASUREMENTS_NOTIFY = 0xb, 30 POWERCAP_DESCRIBE_FASTCHANNEL = 0xc, 31 }; 32 33 enum { 34 POWERCAP_FC_CAP, 35 POWERCAP_FC_PAI, 36 POWERCAP_FC_MAX, 37 }; 38 39 struct scmi_msg_resp_powercap_domain_attributes { 40 __le32 attributes; 41 #define SUPPORTS_POWERCAP_CAP_CHANGE_NOTIFY(x) ((x) & BIT(31)) 42 #define SUPPORTS_POWERCAP_MEASUREMENTS_CHANGE_NOTIFY(x) ((x) & BIT(30)) 43 #define SUPPORTS_ASYNC_POWERCAP_CAP_SET(x) ((x) & BIT(29)) 44 #define SUPPORTS_EXTENDED_NAMES(x) ((x) & BIT(28)) 45 #define SUPPORTS_POWERCAP_CAP_CONFIGURATION(x) ((x) & BIT(27)) 46 #define SUPPORTS_POWERCAP_MONITORING(x) ((x) & BIT(26)) 47 #define SUPPORTS_POWERCAP_PAI_CONFIGURATION(x) ((x) & BIT(25)) 48 #define SUPPORTS_POWERCAP_FASTCHANNELS(x) ((x) & BIT(22)) 49 #define POWERCAP_POWER_UNIT(x) \ 50 (FIELD_GET(GENMASK(24, 23), (x))) 51 #define SUPPORTS_POWER_UNITS_MW(x) \ 52 (POWERCAP_POWER_UNIT(x) == 0x2) 53 #define SUPPORTS_POWER_UNITS_UW(x) \ 54 (POWERCAP_POWER_UNIT(x) == 0x1) 55 u8 name[SCMI_SHORT_NAME_MAX_SIZE]; 56 __le32 min_pai; 57 __le32 max_pai; 58 __le32 pai_step; 59 __le32 min_power_cap; 60 __le32 max_power_cap; 61 __le32 power_cap_step; 62 __le32 sustainable_power; 63 __le32 accuracy; 64 __le32 parent_id; 65 }; 66 67 struct scmi_msg_powercap_set_cap_or_pai { 68 __le32 domain; 69 __le32 flags; 70 #define CAP_SET_ASYNC BIT(1) 71 #define CAP_SET_IGNORE_DRESP BIT(0) 72 __le32 value; 73 }; 74 75 struct scmi_msg_resp_powercap_cap_set_complete { 76 __le32 domain; 77 __le32 power_cap; 78 }; 79 80 struct scmi_msg_resp_powercap_meas_get { 81 __le32 power; 82 __le32 pai; 83 }; 84 85 struct scmi_msg_powercap_notify_cap { 86 __le32 domain; 87 __le32 notify_enable; 88 }; 89 90 struct scmi_msg_powercap_notify_thresh { 91 __le32 domain; 92 __le32 notify_enable; 93 __le32 power_thresh_low; 94 __le32 power_thresh_high; 95 }; 96 97 struct scmi_powercap_cap_changed_notify_payld { 98 __le32 agent_id; 99 __le32 domain_id; 100 __le32 power_cap; 101 __le32 pai; 102 }; 103 104 struct scmi_powercap_meas_changed_notify_payld { 105 __le32 agent_id; 106 __le32 domain_id; 107 __le32 power; 108 }; 109 110 struct scmi_powercap_state { 111 bool enabled; 112 u32 last_pcap; 113 bool meas_notif_enabled; 114 u64 thresholds; 115 #define THRESH_LOW(p, id) \ 116 (lower_32_bits((p)->states[(id)].thresholds)) 117 #define THRESH_HIGH(p, id) \ 118 (upper_32_bits((p)->states[(id)].thresholds)) 119 }; 120 121 struct powercap_info { 122 u32 version; 123 int num_domains; 124 struct scmi_powercap_state *states; 125 struct scmi_powercap_info *powercaps; 126 }; 127 128 static enum scmi_powercap_protocol_cmd evt_2_cmd[] = { 129 POWERCAP_CAP_NOTIFY, 130 POWERCAP_MEASUREMENTS_NOTIFY, 131 }; 132 133 static int scmi_powercap_notify(const struct scmi_protocol_handle *ph, 134 u32 domain, int message_id, bool enable); 135 136 static int 137 scmi_powercap_attributes_get(const struct scmi_protocol_handle *ph, 138 struct powercap_info *pi) 139 { 140 int ret; 141 struct scmi_xfer *t; 142 143 ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, 0, 144 sizeof(u32), &t); 145 if (ret) 146 return ret; 147 148 ret = ph->xops->do_xfer(ph, t); 149 if (!ret) { 150 u32 attributes; 151 152 attributes = get_unaligned_le32(t->rx.buf); 153 pi->num_domains = FIELD_GET(GENMASK(15, 0), attributes); 154 } 155 156 ph->xops->xfer_put(ph, t); 157 return ret; 158 } 159 160 static inline int 161 scmi_powercap_validate(unsigned int min_val, unsigned int max_val, 162 unsigned int step_val, bool configurable) 163 { 164 if (!min_val || !max_val) 165 return -EPROTO; 166 167 if ((configurable && min_val == max_val) || 168 (!configurable && min_val != max_val)) 169 return -EPROTO; 170 171 if (min_val != max_val && !step_val) 172 return -EPROTO; 173 174 return 0; 175 } 176 177 static int 178 scmi_powercap_domain_attributes_get(const struct scmi_protocol_handle *ph, 179 struct powercap_info *pinfo, u32 domain) 180 { 181 int ret; 182 u32 flags; 183 struct scmi_xfer *t; 184 struct scmi_powercap_info *dom_info = pinfo->powercaps + domain; 185 struct scmi_msg_resp_powercap_domain_attributes *resp; 186 187 ret = ph->xops->xfer_get_init(ph, POWERCAP_DOMAIN_ATTRIBUTES, 188 sizeof(domain), sizeof(*resp), &t); 189 if (ret) 190 return ret; 191 192 put_unaligned_le32(domain, t->tx.buf); 193 resp = t->rx.buf; 194 195 ret = ph->xops->do_xfer(ph, t); 196 if (!ret) { 197 flags = le32_to_cpu(resp->attributes); 198 199 dom_info->id = domain; 200 dom_info->notify_powercap_cap_change = 201 SUPPORTS_POWERCAP_CAP_CHANGE_NOTIFY(flags); 202 dom_info->notify_powercap_measurement_change = 203 SUPPORTS_POWERCAP_MEASUREMENTS_CHANGE_NOTIFY(flags); 204 dom_info->async_powercap_cap_set = 205 SUPPORTS_ASYNC_POWERCAP_CAP_SET(flags); 206 dom_info->powercap_cap_config = 207 SUPPORTS_POWERCAP_CAP_CONFIGURATION(flags); 208 dom_info->powercap_monitoring = 209 SUPPORTS_POWERCAP_MONITORING(flags); 210 dom_info->powercap_pai_config = 211 SUPPORTS_POWERCAP_PAI_CONFIGURATION(flags); 212 dom_info->powercap_scale_mw = 213 SUPPORTS_POWER_UNITS_MW(flags); 214 dom_info->powercap_scale_uw = 215 SUPPORTS_POWER_UNITS_UW(flags); 216 dom_info->fastchannels = 217 SUPPORTS_POWERCAP_FASTCHANNELS(flags); 218 219 strscpy(dom_info->name, resp->name, SCMI_SHORT_NAME_MAX_SIZE); 220 221 dom_info->min_pai = le32_to_cpu(resp->min_pai); 222 dom_info->max_pai = le32_to_cpu(resp->max_pai); 223 dom_info->pai_step = le32_to_cpu(resp->pai_step); 224 ret = scmi_powercap_validate(dom_info->min_pai, 225 dom_info->max_pai, 226 dom_info->pai_step, 227 dom_info->powercap_pai_config); 228 if (ret) { 229 dev_err(ph->dev, 230 "Platform reported inconsistent PAI config for domain %d - %s\n", 231 dom_info->id, dom_info->name); 232 goto clean; 233 } 234 235 dom_info->min_power_cap = le32_to_cpu(resp->min_power_cap); 236 dom_info->max_power_cap = le32_to_cpu(resp->max_power_cap); 237 dom_info->power_cap_step = le32_to_cpu(resp->power_cap_step); 238 ret = scmi_powercap_validate(dom_info->min_power_cap, 239 dom_info->max_power_cap, 240 dom_info->power_cap_step, 241 dom_info->powercap_cap_config); 242 if (ret) { 243 dev_err(ph->dev, 244 "Platform reported inconsistent CAP config for domain %d - %s\n", 245 dom_info->id, dom_info->name); 246 goto clean; 247 } 248 249 dom_info->sustainable_power = 250 le32_to_cpu(resp->sustainable_power); 251 dom_info->accuracy = le32_to_cpu(resp->accuracy); 252 253 dom_info->parent_id = le32_to_cpu(resp->parent_id); 254 if (dom_info->parent_id != SCMI_POWERCAP_ROOT_ZONE_ID && 255 (dom_info->parent_id >= pinfo->num_domains || 256 dom_info->parent_id == dom_info->id)) { 257 dev_err(ph->dev, 258 "Platform reported inconsistent parent ID for domain %d - %s\n", 259 dom_info->id, dom_info->name); 260 ret = -ENODEV; 261 } 262 } 263 264 clean: 265 ph->xops->xfer_put(ph, t); 266 267 /* 268 * If supported overwrite short name with the extended one; 269 * on error just carry on and use already provided short name. 270 */ 271 if (!ret && SUPPORTS_EXTENDED_NAMES(flags)) 272 ph->hops->extended_name_get(ph, POWERCAP_DOMAIN_NAME_GET, 273 domain, dom_info->name, 274 SCMI_MAX_STR_SIZE); 275 276 return ret; 277 } 278 279 static int scmi_powercap_num_domains_get(const struct scmi_protocol_handle *ph) 280 { 281 struct powercap_info *pi = ph->get_priv(ph); 282 283 return pi->num_domains; 284 } 285 286 static const struct scmi_powercap_info * 287 scmi_powercap_dom_info_get(const struct scmi_protocol_handle *ph, u32 domain_id) 288 { 289 struct powercap_info *pi = ph->get_priv(ph); 290 291 if (domain_id >= pi->num_domains) 292 return NULL; 293 294 return pi->powercaps + domain_id; 295 } 296 297 static int scmi_powercap_xfer_cap_get(const struct scmi_protocol_handle *ph, 298 u32 domain_id, u32 *power_cap) 299 { 300 int ret; 301 struct scmi_xfer *t; 302 303 ret = ph->xops->xfer_get_init(ph, POWERCAP_CAP_GET, sizeof(u32), 304 sizeof(u32), &t); 305 if (ret) 306 return ret; 307 308 put_unaligned_le32(domain_id, t->tx.buf); 309 ret = ph->xops->do_xfer(ph, t); 310 if (!ret) 311 *power_cap = get_unaligned_le32(t->rx.buf); 312 313 ph->xops->xfer_put(ph, t); 314 315 return ret; 316 } 317 318 static int __scmi_powercap_cap_get(const struct scmi_protocol_handle *ph, 319 const struct scmi_powercap_info *dom, 320 u32 *power_cap) 321 { 322 if (dom->fc_info && dom->fc_info[POWERCAP_FC_CAP].get_addr) { 323 *power_cap = ioread32(dom->fc_info[POWERCAP_FC_CAP].get_addr); 324 trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_CAP_GET, 325 dom->id, *power_cap, 0); 326 return 0; 327 } 328 329 return scmi_powercap_xfer_cap_get(ph, dom->id, power_cap); 330 } 331 332 static int scmi_powercap_cap_get(const struct scmi_protocol_handle *ph, 333 u32 domain_id, u32 *power_cap) 334 { 335 const struct scmi_powercap_info *dom; 336 337 if (!power_cap) 338 return -EINVAL; 339 340 dom = scmi_powercap_dom_info_get(ph, domain_id); 341 if (!dom) 342 return -EINVAL; 343 344 return __scmi_powercap_cap_get(ph, dom, power_cap); 345 } 346 347 static int scmi_powercap_xfer_cap_set(const struct scmi_protocol_handle *ph, 348 const struct scmi_powercap_info *pc, 349 u32 power_cap, bool ignore_dresp) 350 { 351 int ret; 352 struct scmi_xfer *t; 353 struct scmi_msg_powercap_set_cap_or_pai *msg; 354 355 ret = ph->xops->xfer_get_init(ph, POWERCAP_CAP_SET, 356 sizeof(*msg), 0, &t); 357 if (ret) 358 return ret; 359 360 msg = t->tx.buf; 361 msg->domain = cpu_to_le32(pc->id); 362 msg->flags = 363 cpu_to_le32(FIELD_PREP(CAP_SET_ASYNC, !!pc->async_powercap_cap_set) | 364 FIELD_PREP(CAP_SET_IGNORE_DRESP, !!ignore_dresp)); 365 msg->value = cpu_to_le32(power_cap); 366 367 if (!pc->async_powercap_cap_set || ignore_dresp) { 368 ret = ph->xops->do_xfer(ph, t); 369 } else { 370 ret = ph->xops->do_xfer_with_response(ph, t); 371 if (!ret) { 372 struct scmi_msg_resp_powercap_cap_set_complete *resp; 373 374 resp = t->rx.buf; 375 if (le32_to_cpu(resp->domain) == pc->id) 376 dev_dbg(ph->dev, 377 "Powercap ID %d CAP set async to %u\n", 378 pc->id, 379 get_unaligned_le32(&resp->power_cap)); 380 else 381 ret = -EPROTO; 382 } 383 } 384 385 ph->xops->xfer_put(ph, t); 386 return ret; 387 } 388 389 static int __scmi_powercap_cap_set(const struct scmi_protocol_handle *ph, 390 struct powercap_info *pi, u32 domain_id, 391 u32 power_cap, bool ignore_dresp) 392 { 393 int ret = -EINVAL; 394 const struct scmi_powercap_info *pc; 395 396 pc = scmi_powercap_dom_info_get(ph, domain_id); 397 if (!pc || !pc->powercap_cap_config) 398 return ret; 399 400 if (power_cap && 401 (power_cap < pc->min_power_cap || power_cap > pc->max_power_cap)) 402 return ret; 403 404 if (pc->fc_info && pc->fc_info[POWERCAP_FC_CAP].set_addr) { 405 struct scmi_fc_info *fci = &pc->fc_info[POWERCAP_FC_CAP]; 406 407 iowrite32(power_cap, fci->set_addr); 408 ph->hops->fastchannel_db_ring(fci->set_db); 409 trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_CAP_SET, 410 domain_id, power_cap, 0); 411 ret = 0; 412 } else { 413 ret = scmi_powercap_xfer_cap_set(ph, pc, power_cap, 414 ignore_dresp); 415 } 416 417 /* Save the last explicitly set non-zero powercap value */ 418 if (PROTOCOL_REV_MAJOR(pi->version) >= 0x2 && !ret && power_cap) 419 pi->states[domain_id].last_pcap = power_cap; 420 421 return ret; 422 } 423 424 static int scmi_powercap_cap_set(const struct scmi_protocol_handle *ph, 425 u32 domain_id, u32 power_cap, 426 bool ignore_dresp) 427 { 428 struct powercap_info *pi = ph->get_priv(ph); 429 430 /* 431 * Disallow zero as a possible explicitly requested powercap: 432 * there are enable/disable operations for this. 433 */ 434 if (!power_cap) 435 return -EINVAL; 436 437 /* Just log the last set request if acting on a disabled domain */ 438 if (PROTOCOL_REV_MAJOR(pi->version) >= 0x2 && 439 !pi->states[domain_id].enabled) { 440 pi->states[domain_id].last_pcap = power_cap; 441 return 0; 442 } 443 444 return __scmi_powercap_cap_set(ph, pi, domain_id, 445 power_cap, ignore_dresp); 446 } 447 448 static int scmi_powercap_xfer_pai_get(const struct scmi_protocol_handle *ph, 449 u32 domain_id, u32 *pai) 450 { 451 int ret; 452 struct scmi_xfer *t; 453 454 ret = ph->xops->xfer_get_init(ph, POWERCAP_PAI_GET, sizeof(u32), 455 sizeof(u32), &t); 456 if (ret) 457 return ret; 458 459 put_unaligned_le32(domain_id, t->tx.buf); 460 ret = ph->xops->do_xfer(ph, t); 461 if (!ret) 462 *pai = get_unaligned_le32(t->rx.buf); 463 464 ph->xops->xfer_put(ph, t); 465 466 return ret; 467 } 468 469 static int scmi_powercap_pai_get(const struct scmi_protocol_handle *ph, 470 u32 domain_id, u32 *pai) 471 { 472 struct scmi_powercap_info *dom; 473 struct powercap_info *pi = ph->get_priv(ph); 474 475 if (!pai || domain_id >= pi->num_domains) 476 return -EINVAL; 477 478 dom = pi->powercaps + domain_id; 479 if (dom->fc_info && dom->fc_info[POWERCAP_FC_PAI].get_addr) { 480 *pai = ioread32(dom->fc_info[POWERCAP_FC_PAI].get_addr); 481 trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_PAI_GET, 482 domain_id, *pai, 0); 483 return 0; 484 } 485 486 return scmi_powercap_xfer_pai_get(ph, domain_id, pai); 487 } 488 489 static int scmi_powercap_xfer_pai_set(const struct scmi_protocol_handle *ph, 490 u32 domain_id, u32 pai) 491 { 492 int ret; 493 struct scmi_xfer *t; 494 struct scmi_msg_powercap_set_cap_or_pai *msg; 495 496 ret = ph->xops->xfer_get_init(ph, POWERCAP_PAI_SET, 497 sizeof(*msg), 0, &t); 498 if (ret) 499 return ret; 500 501 msg = t->tx.buf; 502 msg->domain = cpu_to_le32(domain_id); 503 msg->flags = cpu_to_le32(0); 504 msg->value = cpu_to_le32(pai); 505 506 ret = ph->xops->do_xfer(ph, t); 507 508 ph->xops->xfer_put(ph, t); 509 return ret; 510 } 511 512 static int scmi_powercap_pai_set(const struct scmi_protocol_handle *ph, 513 u32 domain_id, u32 pai) 514 { 515 const struct scmi_powercap_info *pc; 516 517 pc = scmi_powercap_dom_info_get(ph, domain_id); 518 if (!pc || !pc->powercap_pai_config || !pai || 519 pai < pc->min_pai || pai > pc->max_pai) 520 return -EINVAL; 521 522 if (pc->fc_info && pc->fc_info[POWERCAP_FC_PAI].set_addr) { 523 struct scmi_fc_info *fci = &pc->fc_info[POWERCAP_FC_PAI]; 524 525 trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_PAI_SET, 526 domain_id, pai, 0); 527 iowrite32(pai, fci->set_addr); 528 ph->hops->fastchannel_db_ring(fci->set_db); 529 return 0; 530 } 531 532 return scmi_powercap_xfer_pai_set(ph, domain_id, pai); 533 } 534 535 static int scmi_powercap_measurements_get(const struct scmi_protocol_handle *ph, 536 u32 domain_id, u32 *average_power, 537 u32 *pai) 538 { 539 int ret; 540 struct scmi_xfer *t; 541 struct scmi_msg_resp_powercap_meas_get *resp; 542 const struct scmi_powercap_info *pc; 543 544 pc = scmi_powercap_dom_info_get(ph, domain_id); 545 if (!pc || !pc->powercap_monitoring || !pai || !average_power) 546 return -EINVAL; 547 548 ret = ph->xops->xfer_get_init(ph, POWERCAP_MEASUREMENTS_GET, 549 sizeof(u32), sizeof(*resp), &t); 550 if (ret) 551 return ret; 552 553 resp = t->rx.buf; 554 put_unaligned_le32(domain_id, t->tx.buf); 555 ret = ph->xops->do_xfer(ph, t); 556 if (!ret) { 557 *average_power = le32_to_cpu(resp->power); 558 *pai = le32_to_cpu(resp->pai); 559 } 560 561 ph->xops->xfer_put(ph, t); 562 return ret; 563 } 564 565 static int 566 scmi_powercap_measurements_threshold_get(const struct scmi_protocol_handle *ph, 567 u32 domain_id, u32 *power_thresh_low, 568 u32 *power_thresh_high) 569 { 570 struct powercap_info *pi = ph->get_priv(ph); 571 572 if (!power_thresh_low || !power_thresh_high || 573 domain_id >= pi->num_domains) 574 return -EINVAL; 575 576 *power_thresh_low = THRESH_LOW(pi, domain_id); 577 *power_thresh_high = THRESH_HIGH(pi, domain_id); 578 579 return 0; 580 } 581 582 static int 583 scmi_powercap_measurements_threshold_set(const struct scmi_protocol_handle *ph, 584 u32 domain_id, u32 power_thresh_low, 585 u32 power_thresh_high) 586 { 587 int ret = 0; 588 struct powercap_info *pi = ph->get_priv(ph); 589 590 if (domain_id >= pi->num_domains || 591 power_thresh_low > power_thresh_high) 592 return -EINVAL; 593 594 /* Anything to do ? */ 595 if (THRESH_LOW(pi, domain_id) == power_thresh_low && 596 THRESH_HIGH(pi, domain_id) == power_thresh_high) 597 return ret; 598 599 pi->states[domain_id].thresholds = 600 (FIELD_PREP(GENMASK_ULL(31, 0), power_thresh_low) | 601 FIELD_PREP(GENMASK_ULL(63, 32), power_thresh_high)); 602 603 /* Update thresholds if notification already enabled */ 604 if (pi->states[domain_id].meas_notif_enabled) 605 ret = scmi_powercap_notify(ph, domain_id, 606 POWERCAP_MEASUREMENTS_NOTIFY, 607 true); 608 609 return ret; 610 } 611 612 static int scmi_powercap_cap_enable_set(const struct scmi_protocol_handle *ph, 613 u32 domain_id, bool enable) 614 { 615 int ret; 616 u32 power_cap; 617 struct powercap_info *pi = ph->get_priv(ph); 618 619 if (PROTOCOL_REV_MAJOR(pi->version) < 0x2) 620 return -EINVAL; 621 622 if (enable == pi->states[domain_id].enabled) 623 return 0; 624 625 if (enable) { 626 /* Cannot enable with a zero powercap. */ 627 if (!pi->states[domain_id].last_pcap) 628 return -EINVAL; 629 630 ret = __scmi_powercap_cap_set(ph, pi, domain_id, 631 pi->states[domain_id].last_pcap, 632 true); 633 } else { 634 ret = __scmi_powercap_cap_set(ph, pi, domain_id, 0, true); 635 } 636 637 if (ret) 638 return ret; 639 640 /* 641 * Update our internal state to reflect final platform state: the SCMI 642 * server could have ignored a disable request and kept enforcing some 643 * powercap limit requested by other agents. 644 */ 645 ret = scmi_powercap_cap_get(ph, domain_id, &power_cap); 646 if (!ret) 647 pi->states[domain_id].enabled = !!power_cap; 648 649 return ret; 650 } 651 652 static int scmi_powercap_cap_enable_get(const struct scmi_protocol_handle *ph, 653 u32 domain_id, bool *enable) 654 { 655 int ret; 656 u32 power_cap; 657 struct powercap_info *pi = ph->get_priv(ph); 658 659 *enable = true; 660 if (PROTOCOL_REV_MAJOR(pi->version) < 0x2) 661 return 0; 662 663 /* 664 * Report always real platform state; platform could have ignored 665 * a previous disable request. Default true on any error. 666 */ 667 ret = scmi_powercap_cap_get(ph, domain_id, &power_cap); 668 if (!ret) 669 *enable = !!power_cap; 670 671 /* Update internal state with current real platform state */ 672 pi->states[domain_id].enabled = *enable; 673 674 return 0; 675 } 676 677 static const struct scmi_powercap_proto_ops powercap_proto_ops = { 678 .num_domains_get = scmi_powercap_num_domains_get, 679 .info_get = scmi_powercap_dom_info_get, 680 .cap_get = scmi_powercap_cap_get, 681 .cap_set = scmi_powercap_cap_set, 682 .cap_enable_set = scmi_powercap_cap_enable_set, 683 .cap_enable_get = scmi_powercap_cap_enable_get, 684 .pai_get = scmi_powercap_pai_get, 685 .pai_set = scmi_powercap_pai_set, 686 .measurements_get = scmi_powercap_measurements_get, 687 .measurements_threshold_set = scmi_powercap_measurements_threshold_set, 688 .measurements_threshold_get = scmi_powercap_measurements_threshold_get, 689 }; 690 691 static void scmi_powercap_domain_init_fc(const struct scmi_protocol_handle *ph, 692 u32 domain, struct scmi_fc_info **p_fc) 693 { 694 struct scmi_fc_info *fc; 695 696 fc = devm_kcalloc(ph->dev, POWERCAP_FC_MAX, sizeof(*fc), GFP_KERNEL); 697 if (!fc) 698 return; 699 700 ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL, 701 POWERCAP_CAP_SET, 4, domain, 702 &fc[POWERCAP_FC_CAP].set_addr, 703 &fc[POWERCAP_FC_CAP].set_db); 704 705 ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL, 706 POWERCAP_CAP_GET, 4, domain, 707 &fc[POWERCAP_FC_CAP].get_addr, NULL); 708 709 ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL, 710 POWERCAP_PAI_SET, 4, domain, 711 &fc[POWERCAP_FC_PAI].set_addr, 712 &fc[POWERCAP_FC_PAI].set_db); 713 714 ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL, 715 POWERCAP_PAI_GET, 4, domain, 716 &fc[POWERCAP_FC_PAI].get_addr, NULL); 717 718 *p_fc = fc; 719 } 720 721 static int scmi_powercap_notify(const struct scmi_protocol_handle *ph, 722 u32 domain, int message_id, bool enable) 723 { 724 int ret; 725 struct scmi_xfer *t; 726 727 switch (message_id) { 728 case POWERCAP_CAP_NOTIFY: 729 { 730 struct scmi_msg_powercap_notify_cap *notify; 731 732 ret = ph->xops->xfer_get_init(ph, message_id, 733 sizeof(*notify), 0, &t); 734 if (ret) 735 return ret; 736 737 notify = t->tx.buf; 738 notify->domain = cpu_to_le32(domain); 739 notify->notify_enable = cpu_to_le32(enable ? BIT(0) : 0); 740 break; 741 } 742 case POWERCAP_MEASUREMENTS_NOTIFY: 743 { 744 u32 low, high; 745 struct scmi_msg_powercap_notify_thresh *notify; 746 747 /* 748 * Note that we have to pick the most recently configured 749 * thresholds to build a proper POWERCAP_MEASUREMENTS_NOTIFY 750 * enable request and we fail, complaining, if no thresholds 751 * were ever set, since this is an indication the API has been 752 * used wrongly. 753 */ 754 ret = scmi_powercap_measurements_threshold_get(ph, domain, 755 &low, &high); 756 if (ret) 757 return ret; 758 759 if (enable && !low && !high) { 760 dev_err(ph->dev, 761 "Invalid Measurements Notify thresholds: %u/%u\n", 762 low, high); 763 return -EINVAL; 764 } 765 766 ret = ph->xops->xfer_get_init(ph, message_id, 767 sizeof(*notify), 0, &t); 768 if (ret) 769 return ret; 770 771 notify = t->tx.buf; 772 notify->domain = cpu_to_le32(domain); 773 notify->notify_enable = cpu_to_le32(enable ? BIT(0) : 0); 774 notify->power_thresh_low = cpu_to_le32(low); 775 notify->power_thresh_high = cpu_to_le32(high); 776 break; 777 } 778 default: 779 return -EINVAL; 780 } 781 782 ret = ph->xops->do_xfer(ph, t); 783 784 ph->xops->xfer_put(ph, t); 785 return ret; 786 } 787 788 static int 789 scmi_powercap_set_notify_enabled(const struct scmi_protocol_handle *ph, 790 u8 evt_id, u32 src_id, bool enable) 791 { 792 int ret, cmd_id; 793 struct powercap_info *pi = ph->get_priv(ph); 794 795 if (evt_id >= ARRAY_SIZE(evt_2_cmd) || src_id >= pi->num_domains) 796 return -EINVAL; 797 798 cmd_id = evt_2_cmd[evt_id]; 799 ret = scmi_powercap_notify(ph, src_id, cmd_id, enable); 800 if (ret) 801 pr_debug("FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n", 802 evt_id, src_id, ret); 803 else if (cmd_id == POWERCAP_MEASUREMENTS_NOTIFY) 804 /* 805 * On success save the current notification enabled state, so 806 * as to be able to properly update the notification thresholds 807 * when they are modified on a domain for which measurement 808 * notifications were currently enabled. 809 * 810 * This is needed because the SCMI Notification core machinery 811 * and API does not support passing per-notification custom 812 * arguments at callback registration time. 813 * 814 * Note that this can be done here with a simple flag since the 815 * SCMI core Notifications code takes care of keeping proper 816 * per-domain enables refcounting, so that this helper function 817 * will be called only once (for enables) when the first user 818 * registers a callback on this domain and once more (disable) 819 * when the last user de-registers its callback. 820 */ 821 pi->states[src_id].meas_notif_enabled = enable; 822 823 return ret; 824 } 825 826 static void * 827 scmi_powercap_fill_custom_report(const struct scmi_protocol_handle *ph, 828 u8 evt_id, ktime_t timestamp, 829 const void *payld, size_t payld_sz, 830 void *report, u32 *src_id) 831 { 832 void *rep = NULL; 833 834 switch (evt_id) { 835 case SCMI_EVENT_POWERCAP_CAP_CHANGED: 836 { 837 const struct scmi_powercap_cap_changed_notify_payld *p = payld; 838 struct scmi_powercap_cap_changed_report *r = report; 839 840 if (sizeof(*p) != payld_sz) 841 break; 842 843 r->timestamp = timestamp; 844 r->agent_id = le32_to_cpu(p->agent_id); 845 r->domain_id = le32_to_cpu(p->domain_id); 846 r->power_cap = le32_to_cpu(p->power_cap); 847 r->pai = le32_to_cpu(p->pai); 848 *src_id = r->domain_id; 849 rep = r; 850 break; 851 } 852 case SCMI_EVENT_POWERCAP_MEASUREMENTS_CHANGED: 853 { 854 const struct scmi_powercap_meas_changed_notify_payld *p = payld; 855 struct scmi_powercap_meas_changed_report *r = report; 856 857 if (sizeof(*p) != payld_sz) 858 break; 859 860 r->timestamp = timestamp; 861 r->agent_id = le32_to_cpu(p->agent_id); 862 r->domain_id = le32_to_cpu(p->domain_id); 863 r->power = le32_to_cpu(p->power); 864 *src_id = r->domain_id; 865 rep = r; 866 break; 867 } 868 default: 869 break; 870 } 871 872 return rep; 873 } 874 875 static int 876 scmi_powercap_get_num_sources(const struct scmi_protocol_handle *ph) 877 { 878 struct powercap_info *pi = ph->get_priv(ph); 879 880 if (!pi) 881 return -EINVAL; 882 883 return pi->num_domains; 884 } 885 886 static const struct scmi_event powercap_events[] = { 887 { 888 .id = SCMI_EVENT_POWERCAP_CAP_CHANGED, 889 .max_payld_sz = 890 sizeof(struct scmi_powercap_cap_changed_notify_payld), 891 .max_report_sz = 892 sizeof(struct scmi_powercap_cap_changed_report), 893 }, 894 { 895 .id = SCMI_EVENT_POWERCAP_MEASUREMENTS_CHANGED, 896 .max_payld_sz = 897 sizeof(struct scmi_powercap_meas_changed_notify_payld), 898 .max_report_sz = 899 sizeof(struct scmi_powercap_meas_changed_report), 900 }, 901 }; 902 903 static const struct scmi_event_ops powercap_event_ops = { 904 .get_num_sources = scmi_powercap_get_num_sources, 905 .set_notify_enabled = scmi_powercap_set_notify_enabled, 906 .fill_custom_report = scmi_powercap_fill_custom_report, 907 }; 908 909 static const struct scmi_protocol_events powercap_protocol_events = { 910 .queue_sz = SCMI_PROTO_QUEUE_SZ, 911 .ops = &powercap_event_ops, 912 .evts = powercap_events, 913 .num_events = ARRAY_SIZE(powercap_events), 914 }; 915 916 static int 917 scmi_powercap_protocol_init(const struct scmi_protocol_handle *ph) 918 { 919 int domain, ret; 920 u32 version; 921 struct powercap_info *pinfo; 922 923 ret = ph->xops->version_get(ph, &version); 924 if (ret) 925 return ret; 926 927 dev_dbg(ph->dev, "Powercap Version %d.%d\n", 928 PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); 929 930 pinfo = devm_kzalloc(ph->dev, sizeof(*pinfo), GFP_KERNEL); 931 if (!pinfo) 932 return -ENOMEM; 933 934 ret = scmi_powercap_attributes_get(ph, pinfo); 935 if (ret) 936 return ret; 937 938 pinfo->powercaps = devm_kcalloc(ph->dev, pinfo->num_domains, 939 sizeof(*pinfo->powercaps), 940 GFP_KERNEL); 941 if (!pinfo->powercaps) 942 return -ENOMEM; 943 944 pinfo->states = devm_kcalloc(ph->dev, pinfo->num_domains, 945 sizeof(*pinfo->states), GFP_KERNEL); 946 if (!pinfo->states) 947 return -ENOMEM; 948 949 /* 950 * Note that any failure in retrieving any domain attribute leads to 951 * the whole Powercap protocol initialization failure: this way the 952 * reported Powercap domains are all assured, when accessed, to be well 953 * formed and correlated by sane parent-child relationship (if any). 954 */ 955 for (domain = 0; domain < pinfo->num_domains; domain++) { 956 ret = scmi_powercap_domain_attributes_get(ph, pinfo, domain); 957 if (ret) 958 return ret; 959 960 if (pinfo->powercaps[domain].fastchannels) 961 scmi_powercap_domain_init_fc(ph, domain, 962 &pinfo->powercaps[domain].fc_info); 963 964 /* Grab initial state when disable is supported. */ 965 if (PROTOCOL_REV_MAJOR(version) >= 0x2) { 966 ret = __scmi_powercap_cap_get(ph, 967 &pinfo->powercaps[domain], 968 &pinfo->states[domain].last_pcap); 969 if (ret) 970 return ret; 971 972 pinfo->states[domain].enabled = 973 !!pinfo->states[domain].last_pcap; 974 } 975 } 976 977 pinfo->version = version; 978 return ph->set_priv(ph, pinfo); 979 } 980 981 static const struct scmi_protocol scmi_powercap = { 982 .id = SCMI_PROTOCOL_POWERCAP, 983 .owner = THIS_MODULE, 984 .instance_init = &scmi_powercap_protocol_init, 985 .ops = &powercap_proto_ops, 986 .events = &powercap_protocol_events, 987 }; 988 989 DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(powercap, scmi_powercap) 990