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