Merge branch 'pm-cpufreq'
[linux-block.git] / drivers / firmware / arm_scmi / powercap.c
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                                    &fc[POWERCAP_FC_CAP].rate_limit);
708
709         ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
710                                    POWERCAP_CAP_GET, 4, domain,
711                                    &fc[POWERCAP_FC_CAP].get_addr, NULL,
712                                    &fc[POWERCAP_FC_CAP].rate_limit);
713
714         ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
715                                    POWERCAP_PAI_SET, 4, domain,
716                                    &fc[POWERCAP_FC_PAI].set_addr,
717                                    &fc[POWERCAP_FC_PAI].set_db,
718                                    &fc[POWERCAP_FC_PAI].rate_limit);
719
720         ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
721                                    POWERCAP_PAI_GET, 4, domain,
722                                    &fc[POWERCAP_FC_PAI].get_addr, NULL,
723                                    &fc[POWERCAP_PAI_GET].rate_limit);
724
725         *p_fc = fc;
726 }
727
728 static int scmi_powercap_notify(const struct scmi_protocol_handle *ph,
729                                 u32 domain, int message_id, bool enable)
730 {
731         int ret;
732         struct scmi_xfer *t;
733
734         switch (message_id) {
735         case POWERCAP_CAP_NOTIFY:
736         {
737                 struct scmi_msg_powercap_notify_cap *notify;
738
739                 ret = ph->xops->xfer_get_init(ph, message_id,
740                                               sizeof(*notify), 0, &t);
741                 if (ret)
742                         return ret;
743
744                 notify = t->tx.buf;
745                 notify->domain = cpu_to_le32(domain);
746                 notify->notify_enable = cpu_to_le32(enable ? BIT(0) : 0);
747                 break;
748         }
749         case POWERCAP_MEASUREMENTS_NOTIFY:
750         {
751                 u32 low, high;
752                 struct scmi_msg_powercap_notify_thresh *notify;
753
754                 /*
755                  * Note that we have to pick the most recently configured
756                  * thresholds to build a proper POWERCAP_MEASUREMENTS_NOTIFY
757                  * enable request and we fail, complaining, if no thresholds
758                  * were ever set, since this is an indication the API has been
759                  * used wrongly.
760                  */
761                 ret = scmi_powercap_measurements_threshold_get(ph, domain,
762                                                                &low, &high);
763                 if (ret)
764                         return ret;
765
766                 if (enable && !low && !high) {
767                         dev_err(ph->dev,
768                                 "Invalid Measurements Notify thresholds: %u/%u\n",
769                                 low, high);
770                         return -EINVAL;
771                 }
772
773                 ret = ph->xops->xfer_get_init(ph, message_id,
774                                               sizeof(*notify), 0, &t);
775                 if (ret)
776                         return ret;
777
778                 notify = t->tx.buf;
779                 notify->domain = cpu_to_le32(domain);
780                 notify->notify_enable = cpu_to_le32(enable ? BIT(0) : 0);
781                 notify->power_thresh_low = cpu_to_le32(low);
782                 notify->power_thresh_high = cpu_to_le32(high);
783                 break;
784         }
785         default:
786                 return -EINVAL;
787         }
788
789         ret = ph->xops->do_xfer(ph, t);
790
791         ph->xops->xfer_put(ph, t);
792         return ret;
793 }
794
795 static int
796 scmi_powercap_set_notify_enabled(const struct scmi_protocol_handle *ph,
797                                  u8 evt_id, u32 src_id, bool enable)
798 {
799         int ret, cmd_id;
800         struct powercap_info *pi = ph->get_priv(ph);
801
802         if (evt_id >= ARRAY_SIZE(evt_2_cmd) || src_id >= pi->num_domains)
803                 return -EINVAL;
804
805         cmd_id = evt_2_cmd[evt_id];
806         ret = scmi_powercap_notify(ph, src_id, cmd_id, enable);
807         if (ret)
808                 pr_debug("FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n",
809                          evt_id, src_id, ret);
810         else if (cmd_id == POWERCAP_MEASUREMENTS_NOTIFY)
811                 /*
812                  * On success save the current notification enabled state, so
813                  * as to be able to properly update the notification thresholds
814                  * when they are modified on a domain for which measurement
815                  * notifications were currently enabled.
816                  *
817                  * This is needed because the SCMI Notification core machinery
818                  * and API does not support passing per-notification custom
819                  * arguments at callback registration time.
820                  *
821                  * Note that this can be done here with a simple flag since the
822                  * SCMI core Notifications code takes care of keeping proper
823                  * per-domain enables refcounting, so that this helper function
824                  * will be called only once (for enables) when the first user
825                  * registers a callback on this domain and once more (disable)
826                  * when the last user de-registers its callback.
827                  */
828                 pi->states[src_id].meas_notif_enabled = enable;
829
830         return ret;
831 }
832
833 static void *
834 scmi_powercap_fill_custom_report(const struct scmi_protocol_handle *ph,
835                                  u8 evt_id, ktime_t timestamp,
836                                  const void *payld, size_t payld_sz,
837                                  void *report, u32 *src_id)
838 {
839         void *rep = NULL;
840
841         switch (evt_id) {
842         case SCMI_EVENT_POWERCAP_CAP_CHANGED:
843         {
844                 const struct scmi_powercap_cap_changed_notify_payld *p = payld;
845                 struct scmi_powercap_cap_changed_report *r = report;
846
847                 if (sizeof(*p) != payld_sz)
848                         break;
849
850                 r->timestamp = timestamp;
851                 r->agent_id = le32_to_cpu(p->agent_id);
852                 r->domain_id = le32_to_cpu(p->domain_id);
853                 r->power_cap = le32_to_cpu(p->power_cap);
854                 r->pai = le32_to_cpu(p->pai);
855                 *src_id = r->domain_id;
856                 rep = r;
857                 break;
858         }
859         case SCMI_EVENT_POWERCAP_MEASUREMENTS_CHANGED:
860         {
861                 const struct scmi_powercap_meas_changed_notify_payld *p = payld;
862                 struct scmi_powercap_meas_changed_report *r = report;
863
864                 if (sizeof(*p) != payld_sz)
865                         break;
866
867                 r->timestamp = timestamp;
868                 r->agent_id = le32_to_cpu(p->agent_id);
869                 r->domain_id = le32_to_cpu(p->domain_id);
870                 r->power = le32_to_cpu(p->power);
871                 *src_id = r->domain_id;
872                 rep = r;
873                 break;
874         }
875         default:
876                 break;
877         }
878
879         return rep;
880 }
881
882 static int
883 scmi_powercap_get_num_sources(const struct scmi_protocol_handle *ph)
884 {
885         struct powercap_info *pi = ph->get_priv(ph);
886
887         if (!pi)
888                 return -EINVAL;
889
890         return pi->num_domains;
891 }
892
893 static const struct scmi_event powercap_events[] = {
894         {
895                 .id = SCMI_EVENT_POWERCAP_CAP_CHANGED,
896                 .max_payld_sz =
897                         sizeof(struct scmi_powercap_cap_changed_notify_payld),
898                 .max_report_sz =
899                         sizeof(struct scmi_powercap_cap_changed_report),
900         },
901         {
902                 .id = SCMI_EVENT_POWERCAP_MEASUREMENTS_CHANGED,
903                 .max_payld_sz =
904                         sizeof(struct scmi_powercap_meas_changed_notify_payld),
905                 .max_report_sz =
906                         sizeof(struct scmi_powercap_meas_changed_report),
907         },
908 };
909
910 static const struct scmi_event_ops powercap_event_ops = {
911         .get_num_sources = scmi_powercap_get_num_sources,
912         .set_notify_enabled = scmi_powercap_set_notify_enabled,
913         .fill_custom_report = scmi_powercap_fill_custom_report,
914 };
915
916 static const struct scmi_protocol_events powercap_protocol_events = {
917         .queue_sz = SCMI_PROTO_QUEUE_SZ,
918         .ops = &powercap_event_ops,
919         .evts = powercap_events,
920         .num_events = ARRAY_SIZE(powercap_events),
921 };
922
923 static int
924 scmi_powercap_protocol_init(const struct scmi_protocol_handle *ph)
925 {
926         int domain, ret;
927         u32 version;
928         struct powercap_info *pinfo;
929
930         ret = ph->xops->version_get(ph, &version);
931         if (ret)
932                 return ret;
933
934         dev_dbg(ph->dev, "Powercap Version %d.%d\n",
935                 PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
936
937         pinfo = devm_kzalloc(ph->dev, sizeof(*pinfo), GFP_KERNEL);
938         if (!pinfo)
939                 return -ENOMEM;
940
941         ret = scmi_powercap_attributes_get(ph, pinfo);
942         if (ret)
943                 return ret;
944
945         pinfo->powercaps = devm_kcalloc(ph->dev, pinfo->num_domains,
946                                         sizeof(*pinfo->powercaps),
947                                         GFP_KERNEL);
948         if (!pinfo->powercaps)
949                 return -ENOMEM;
950
951         pinfo->states = devm_kcalloc(ph->dev, pinfo->num_domains,
952                                      sizeof(*pinfo->states), GFP_KERNEL);
953         if (!pinfo->states)
954                 return -ENOMEM;
955
956         /*
957          * Note that any failure in retrieving any domain attribute leads to
958          * the whole Powercap protocol initialization failure: this way the
959          * reported Powercap domains are all assured, when accessed, to be well
960          * formed and correlated by sane parent-child relationship (if any).
961          */
962         for (domain = 0; domain < pinfo->num_domains; domain++) {
963                 ret = scmi_powercap_domain_attributes_get(ph, pinfo, domain);
964                 if (ret)
965                         return ret;
966
967                 if (pinfo->powercaps[domain].fastchannels)
968                         scmi_powercap_domain_init_fc(ph, domain,
969                                                      &pinfo->powercaps[domain].fc_info);
970
971                 /* Grab initial state when disable is supported. */
972                 if (PROTOCOL_REV_MAJOR(version) >= 0x2) {
973                         ret = __scmi_powercap_cap_get(ph,
974                                                       &pinfo->powercaps[domain],
975                                                       &pinfo->states[domain].last_pcap);
976                         if (ret)
977                                 return ret;
978
979                         pinfo->states[domain].enabled =
980                                 !!pinfo->states[domain].last_pcap;
981                 }
982         }
983
984         pinfo->version = version;
985         return ph->set_priv(ph, pinfo, version);
986 }
987
988 static const struct scmi_protocol scmi_powercap = {
989         .id = SCMI_PROTOCOL_POWERCAP,
990         .owner = THIS_MODULE,
991         .instance_init = &scmi_powercap_protocol_init,
992         .ops = &powercap_proto_ops,
993         .events = &powercap_protocol_events,
994         .supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION,
995 };
996
997 DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(powercap, scmi_powercap)