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