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