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