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
scmi_powercap_attributes_get(const struct scmi_protocol_handle * ph,struct powercap_info * pi)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
scmi_powercap_validate(unsigned int min_val,unsigned int max_val,unsigned int step_val,bool configurable)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
scmi_powercap_domain_attributes_get(const struct scmi_protocol_handle * ph,struct powercap_info * pinfo,u32 domain)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
scmi_powercap_num_domains_get(const struct scmi_protocol_handle * ph)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 *
scmi_powercap_dom_info_get(const struct scmi_protocol_handle * ph,u32 domain_id)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
scmi_powercap_xfer_cap_get(const struct scmi_protocol_handle * ph,u32 domain_id,u32 * power_cap)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
__scmi_powercap_cap_get(const struct scmi_protocol_handle * ph,const struct scmi_powercap_info * dom,u32 * power_cap)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
scmi_powercap_cap_get(const struct scmi_protocol_handle * ph,u32 domain_id,u32 * power_cap)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
scmi_powercap_xfer_cap_set(const struct scmi_protocol_handle * ph,const struct scmi_powercap_info * pc,u32 power_cap,bool ignore_dresp)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
__scmi_powercap_cap_set(const struct scmi_protocol_handle * ph,struct powercap_info * pi,u32 domain_id,u32 power_cap,bool ignore_dresp)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
scmi_powercap_cap_set(const struct scmi_protocol_handle * ph,u32 domain_id,u32 power_cap,bool ignore_dresp)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
scmi_powercap_xfer_pai_get(const struct scmi_protocol_handle * ph,u32 domain_id,u32 * pai)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
scmi_powercap_pai_get(const struct scmi_protocol_handle * ph,u32 domain_id,u32 * pai)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
scmi_powercap_xfer_pai_set(const struct scmi_protocol_handle * ph,u32 domain_id,u32 pai)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
scmi_powercap_pai_set(const struct scmi_protocol_handle * ph,u32 domain_id,u32 pai)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
scmi_powercap_measurements_get(const struct scmi_protocol_handle * ph,u32 domain_id,u32 * average_power,u32 * pai)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
scmi_powercap_measurements_threshold_get(const struct scmi_protocol_handle * ph,u32 domain_id,u32 * power_thresh_low,u32 * power_thresh_high)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
scmi_powercap_measurements_threshold_set(const struct scmi_protocol_handle * ph,u32 domain_id,u32 power_thresh_low,u32 power_thresh_high)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
scmi_powercap_cap_enable_set(const struct scmi_protocol_handle * ph,u32 domain_id,bool enable)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
scmi_powercap_cap_enable_get(const struct scmi_protocol_handle * ph,u32 domain_id,bool * enable)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
scmi_powercap_domain_init_fc(const struct scmi_protocol_handle * ph,u32 domain,struct scmi_fc_info ** p_fc)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
scmi_powercap_notify(const struct scmi_protocol_handle * ph,u32 domain,int message_id,bool enable)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
scmi_powercap_set_notify_enabled(const struct scmi_protocol_handle * ph,u8 evt_id,u32 src_id,bool enable)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 *
scmi_powercap_fill_custom_report(const struct scmi_protocol_handle * ph,u8 evt_id,ktime_t timestamp,const void * payld,size_t payld_sz,void * report,u32 * src_id)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
scmi_powercap_get_num_sources(const struct scmi_protocol_handle * ph)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
scmi_powercap_protocol_init(const struct scmi_protocol_handle * ph)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