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