GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / firmware / arm_scmi / perf.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * System Control and Management Interface (SCMI) Performance Protocol
4  *
5  * Copyright (C) 2018-2022 ARM Ltd.
6  */
7
8 #define pr_fmt(fmt) "SCMI Notifications PERF - " fmt
9
10 #include <linux/bits.h>
11 #include <linux/of.h>
12 #include <linux/io.h>
13 #include <linux/io-64-nonatomic-hi-lo.h>
14 #include <linux/module.h>
15 #include <linux/platform_device.h>
16 #include <linux/pm_opp.h>
17 #include <linux/scmi_protocol.h>
18 #include <linux/sort.h>
19
20 #include "protocols.h"
21 #include "notify.h"
22
23 #define MAX_OPPS                16
24
25 enum scmi_performance_protocol_cmd {
26         PERF_DOMAIN_ATTRIBUTES = 0x3,
27         PERF_DESCRIBE_LEVELS = 0x4,
28         PERF_LIMITS_SET = 0x5,
29         PERF_LIMITS_GET = 0x6,
30         PERF_LEVEL_SET = 0x7,
31         PERF_LEVEL_GET = 0x8,
32         PERF_NOTIFY_LIMITS = 0x9,
33         PERF_NOTIFY_LEVEL = 0xa,
34         PERF_DESCRIBE_FASTCHANNEL = 0xb,
35         PERF_DOMAIN_NAME_GET = 0xc,
36 };
37
38 struct scmi_opp {
39         u32 perf;
40         u32 power;
41         u32 trans_latency_us;
42 };
43
44 struct scmi_msg_resp_perf_attributes {
45         __le16 num_domains;
46         __le16 flags;
47 #define POWER_SCALE_IN_MILLIWATT(x)     ((x) & BIT(0))
48 #define POWER_SCALE_IN_MICROWATT(x)     ((x) & BIT(1))
49         __le32 stats_addr_low;
50         __le32 stats_addr_high;
51         __le32 stats_size;
52 };
53
54 struct scmi_msg_resp_perf_domain_attributes {
55         __le32 flags;
56 #define SUPPORTS_SET_LIMITS(x)          ((x) & BIT(31))
57 #define SUPPORTS_SET_PERF_LVL(x)        ((x) & BIT(30))
58 #define SUPPORTS_PERF_LIMIT_NOTIFY(x)   ((x) & BIT(29))
59 #define SUPPORTS_PERF_LEVEL_NOTIFY(x)   ((x) & BIT(28))
60 #define SUPPORTS_PERF_FASTCHANNELS(x)   ((x) & BIT(27))
61 #define SUPPORTS_EXTENDED_NAMES(x)      ((x) & BIT(26))
62         __le32 rate_limit_us;
63         __le32 sustained_freq_khz;
64         __le32 sustained_perf_level;
65             u8 name[SCMI_SHORT_NAME_MAX_SIZE];
66 };
67
68 struct scmi_msg_perf_describe_levels {
69         __le32 domain;
70         __le32 level_index;
71 };
72
73 struct scmi_perf_set_limits {
74         __le32 domain;
75         __le32 max_level;
76         __le32 min_level;
77 };
78
79 struct scmi_perf_get_limits {
80         __le32 max_level;
81         __le32 min_level;
82 };
83
84 struct scmi_perf_set_level {
85         __le32 domain;
86         __le32 level;
87 };
88
89 struct scmi_perf_notify_level_or_limits {
90         __le32 domain;
91         __le32 notify_enable;
92 };
93
94 struct scmi_perf_limits_notify_payld {
95         __le32 agent_id;
96         __le32 domain_id;
97         __le32 range_max;
98         __le32 range_min;
99 };
100
101 struct scmi_perf_level_notify_payld {
102         __le32 agent_id;
103         __le32 domain_id;
104         __le32 performance_level;
105 };
106
107 struct scmi_msg_resp_perf_describe_levels {
108         __le16 num_returned;
109         __le16 num_remaining;
110         struct {
111                 __le32 perf_val;
112                 __le32 power;
113                 __le16 transition_latency_us;
114                 __le16 reserved;
115         } opp[];
116 };
117
118 struct scmi_perf_get_fc_info {
119         __le32 domain;
120         __le32 message_id;
121 };
122
123 struct scmi_msg_resp_perf_desc_fc {
124         __le32 attr;
125 #define SUPPORTS_DOORBELL(x)            ((x) & BIT(0))
126 #define DOORBELL_REG_WIDTH(x)           FIELD_GET(GENMASK(2, 1), (x))
127         __le32 rate_limit;
128         __le32 chan_addr_low;
129         __le32 chan_addr_high;
130         __le32 chan_size;
131         __le32 db_addr_low;
132         __le32 db_addr_high;
133         __le32 db_set_lmask;
134         __le32 db_set_hmask;
135         __le32 db_preserve_lmask;
136         __le32 db_preserve_hmask;
137 };
138
139 struct scmi_fc_db_info {
140         int width;
141         u64 set;
142         u64 mask;
143         void __iomem *addr;
144 };
145
146 struct scmi_fc_info {
147         void __iomem *level_set_addr;
148         void __iomem *limit_set_addr;
149         void __iomem *level_get_addr;
150         void __iomem *limit_get_addr;
151         struct scmi_fc_db_info *level_set_db;
152         struct scmi_fc_db_info *limit_set_db;
153 };
154
155 struct perf_dom_info {
156         bool set_limits;
157         bool set_perf;
158         bool perf_limit_notify;
159         bool perf_level_notify;
160         bool perf_fastchannels;
161         u32 opp_count;
162         u32 sustained_freq_khz;
163         u32 sustained_perf_level;
164         u32 mult_factor;
165         char name[SCMI_MAX_STR_SIZE];
166         struct scmi_opp opp[MAX_OPPS];
167         struct scmi_fc_info *fc_info;
168 };
169
170 struct scmi_perf_info {
171         u32 version;
172         int num_domains;
173         bool power_scale_mw;
174         bool power_scale_uw;
175         u64 stats_addr;
176         u32 stats_size;
177         struct perf_dom_info *dom_info;
178 };
179
180 static enum scmi_performance_protocol_cmd evt_2_cmd[] = {
181         PERF_NOTIFY_LIMITS,
182         PERF_NOTIFY_LEVEL,
183 };
184
185 static int scmi_perf_attributes_get(const struct scmi_protocol_handle *ph,
186                                     struct scmi_perf_info *pi)
187 {
188         int ret;
189         struct scmi_xfer *t;
190         struct scmi_msg_resp_perf_attributes *attr;
191
192         ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, 0,
193                                       sizeof(*attr), &t);
194         if (ret)
195                 return ret;
196
197         attr = t->rx.buf;
198
199         ret = ph->xops->do_xfer(ph, t);
200         if (!ret) {
201                 u16 flags = le16_to_cpu(attr->flags);
202
203                 pi->num_domains = le16_to_cpu(attr->num_domains);
204                 pi->power_scale_mw = POWER_SCALE_IN_MILLIWATT(flags);
205                 if (PROTOCOL_REV_MAJOR(pi->version) >= 0x3)
206                         pi->power_scale_uw = POWER_SCALE_IN_MICROWATT(flags);
207                 pi->stats_addr = le32_to_cpu(attr->stats_addr_low) |
208                                 (u64)le32_to_cpu(attr->stats_addr_high) << 32;
209                 pi->stats_size = le32_to_cpu(attr->stats_size);
210         }
211
212         ph->xops->xfer_put(ph, t);
213         return ret;
214 }
215
216 static int
217 scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph,
218                                 u32 domain, struct perf_dom_info *dom_info,
219                                 u32 version)
220 {
221         int ret;
222         u32 flags;
223         struct scmi_xfer *t;
224         struct scmi_msg_resp_perf_domain_attributes *attr;
225
226         ret = ph->xops->xfer_get_init(ph, PERF_DOMAIN_ATTRIBUTES,
227                                      sizeof(domain), sizeof(*attr), &t);
228         if (ret)
229                 return ret;
230
231         put_unaligned_le32(domain, t->tx.buf);
232         attr = t->rx.buf;
233
234         ret = ph->xops->do_xfer(ph, t);
235         if (!ret) {
236                 flags = le32_to_cpu(attr->flags);
237
238                 dom_info->set_limits = SUPPORTS_SET_LIMITS(flags);
239                 dom_info->set_perf = SUPPORTS_SET_PERF_LVL(flags);
240                 dom_info->perf_limit_notify = SUPPORTS_PERF_LIMIT_NOTIFY(flags);
241                 dom_info->perf_level_notify = SUPPORTS_PERF_LEVEL_NOTIFY(flags);
242                 dom_info->perf_fastchannels = SUPPORTS_PERF_FASTCHANNELS(flags);
243                 dom_info->sustained_freq_khz =
244                                         le32_to_cpu(attr->sustained_freq_khz);
245                 dom_info->sustained_perf_level =
246                                         le32_to_cpu(attr->sustained_perf_level);
247                 if (!dom_info->sustained_freq_khz ||
248                     !dom_info->sustained_perf_level)
249                         /* CPUFreq converts to kHz, hence default 1000 */
250                         dom_info->mult_factor = 1000;
251                 else
252                         dom_info->mult_factor =
253                                         (dom_info->sustained_freq_khz * 1000) /
254                                         dom_info->sustained_perf_level;
255                 strscpy(dom_info->name, attr->name, SCMI_SHORT_NAME_MAX_SIZE);
256         }
257
258         ph->xops->xfer_put(ph, t);
259
260         /*
261          * If supported overwrite short name with the extended one;
262          * on error just carry on and use already provided short name.
263          */
264         if (!ret && PROTOCOL_REV_MAJOR(version) >= 0x3 &&
265             SUPPORTS_EXTENDED_NAMES(flags))
266                 ph->hops->extended_name_get(ph, PERF_DOMAIN_NAME_GET, domain,
267                                             dom_info->name, SCMI_MAX_STR_SIZE);
268
269         return ret;
270 }
271
272 static int opp_cmp_func(const void *opp1, const void *opp2)
273 {
274         const struct scmi_opp *t1 = opp1, *t2 = opp2;
275
276         return t1->perf - t2->perf;
277 }
278
279 struct scmi_perf_ipriv {
280         u32 domain;
281         struct perf_dom_info *perf_dom;
282 };
283
284 static void iter_perf_levels_prepare_message(void *message,
285                                              unsigned int desc_index,
286                                              const void *priv)
287 {
288         struct scmi_msg_perf_describe_levels *msg = message;
289         const struct scmi_perf_ipriv *p = priv;
290
291         msg->domain = cpu_to_le32(p->domain);
292         /* Set the number of OPPs to be skipped/already read */
293         msg->level_index = cpu_to_le32(desc_index);
294 }
295
296 static int iter_perf_levels_update_state(struct scmi_iterator_state *st,
297                                          const void *response, void *priv)
298 {
299         const struct scmi_msg_resp_perf_describe_levels *r = response;
300
301         st->num_returned = le16_to_cpu(r->num_returned);
302         st->num_remaining = le16_to_cpu(r->num_remaining);
303
304         return 0;
305 }
306
307 static int
308 iter_perf_levels_process_response(const struct scmi_protocol_handle *ph,
309                                   const void *response,
310                                   struct scmi_iterator_state *st, void *priv)
311 {
312         struct scmi_opp *opp;
313         const struct scmi_msg_resp_perf_describe_levels *r = response;
314         struct scmi_perf_ipriv *p = priv;
315
316         opp = &p->perf_dom->opp[st->desc_index + st->loop_idx];
317         opp->perf = le32_to_cpu(r->opp[st->loop_idx].perf_val);
318         opp->power = le32_to_cpu(r->opp[st->loop_idx].power);
319         opp->trans_latency_us =
320                 le16_to_cpu(r->opp[st->loop_idx].transition_latency_us);
321         p->perf_dom->opp_count++;
322
323         dev_dbg(ph->dev, "Level %d Power %d Latency %dus\n",
324                 opp->perf, opp->power, opp->trans_latency_us);
325
326         return 0;
327 }
328
329 static int
330 scmi_perf_describe_levels_get(const struct scmi_protocol_handle *ph, u32 domain,
331                               struct perf_dom_info *perf_dom)
332 {
333         int ret;
334         void *iter;
335         struct scmi_iterator_ops ops = {
336                 .prepare_message = iter_perf_levels_prepare_message,
337                 .update_state = iter_perf_levels_update_state,
338                 .process_response = iter_perf_levels_process_response,
339         };
340         struct scmi_perf_ipriv ppriv = {
341                 .domain = domain,
342                 .perf_dom = perf_dom,
343         };
344
345         iter = ph->hops->iter_response_init(ph, &ops, MAX_OPPS,
346                                             PERF_DESCRIBE_LEVELS,
347                                             sizeof(struct scmi_msg_perf_describe_levels),
348                                             &ppriv);
349         if (IS_ERR(iter))
350                 return PTR_ERR(iter);
351
352         ret = ph->hops->iter_response_run(iter);
353         if (ret)
354                 return ret;
355
356         if (perf_dom->opp_count)
357                 sort(perf_dom->opp, perf_dom->opp_count,
358                      sizeof(struct scmi_opp), opp_cmp_func, NULL);
359
360         return ret;
361 }
362
363 #define SCMI_PERF_FC_RING_DB(w)                         \
364 do {                                                    \
365         u##w val = 0;                                   \
366                                                         \
367         if (db->mask)                                   \
368                 val = ioread##w(db->addr) & db->mask;   \
369         iowrite##w((u##w)db->set | val, db->addr);      \
370 } while (0)
371
372 static void scmi_perf_fc_ring_db(struct scmi_fc_db_info *db)
373 {
374         if (!db || !db->addr)
375                 return;
376
377         if (db->width == 1)
378                 SCMI_PERF_FC_RING_DB(8);
379         else if (db->width == 2)
380                 SCMI_PERF_FC_RING_DB(16);
381         else if (db->width == 4)
382                 SCMI_PERF_FC_RING_DB(32);
383         else /* db->width == 8 */
384 #ifdef CONFIG_64BIT
385                 SCMI_PERF_FC_RING_DB(64);
386 #else
387         {
388                 u64 val = 0;
389
390                 if (db->mask)
391                         val = ioread64_hi_lo(db->addr) & db->mask;
392                 iowrite64_hi_lo(db->set | val, db->addr);
393         }
394 #endif
395 }
396
397 static int scmi_perf_mb_limits_set(const struct scmi_protocol_handle *ph,
398                                    u32 domain, u32 max_perf, u32 min_perf)
399 {
400         int ret;
401         struct scmi_xfer *t;
402         struct scmi_perf_set_limits *limits;
403
404         ret = ph->xops->xfer_get_init(ph, PERF_LIMITS_SET,
405                                       sizeof(*limits), 0, &t);
406         if (ret)
407                 return ret;
408
409         limits = t->tx.buf;
410         limits->domain = cpu_to_le32(domain);
411         limits->max_level = cpu_to_le32(max_perf);
412         limits->min_level = cpu_to_le32(min_perf);
413
414         ret = ph->xops->do_xfer(ph, t);
415
416         ph->xops->xfer_put(ph, t);
417         return ret;
418 }
419
420 static int scmi_perf_limits_set(const struct scmi_protocol_handle *ph,
421                                 u32 domain, u32 max_perf, u32 min_perf)
422 {
423         struct scmi_perf_info *pi = ph->get_priv(ph);
424         struct perf_dom_info *dom = pi->dom_info + domain;
425
426         if (PROTOCOL_REV_MAJOR(pi->version) >= 0x3 && !max_perf && !min_perf)
427                 return -EINVAL;
428
429         if (dom->fc_info && dom->fc_info->limit_set_addr) {
430                 iowrite32(max_perf, dom->fc_info->limit_set_addr);
431                 iowrite32(min_perf, dom->fc_info->limit_set_addr + 4);
432                 scmi_perf_fc_ring_db(dom->fc_info->limit_set_db);
433                 return 0;
434         }
435
436         return scmi_perf_mb_limits_set(ph, domain, max_perf, min_perf);
437 }
438
439 static int scmi_perf_mb_limits_get(const struct scmi_protocol_handle *ph,
440                                    u32 domain, u32 *max_perf, u32 *min_perf)
441 {
442         int ret;
443         struct scmi_xfer *t;
444         struct scmi_perf_get_limits *limits;
445
446         ret = ph->xops->xfer_get_init(ph, PERF_LIMITS_GET,
447                                       sizeof(__le32), 0, &t);
448         if (ret)
449                 return ret;
450
451         put_unaligned_le32(domain, t->tx.buf);
452
453         ret = ph->xops->do_xfer(ph, t);
454         if (!ret) {
455                 limits = t->rx.buf;
456
457                 *max_perf = le32_to_cpu(limits->max_level);
458                 *min_perf = le32_to_cpu(limits->min_level);
459         }
460
461         ph->xops->xfer_put(ph, t);
462         return ret;
463 }
464
465 static int scmi_perf_limits_get(const struct scmi_protocol_handle *ph,
466                                 u32 domain, u32 *max_perf, u32 *min_perf)
467 {
468         struct scmi_perf_info *pi = ph->get_priv(ph);
469         struct perf_dom_info *dom = pi->dom_info + domain;
470
471         if (dom->fc_info && dom->fc_info->limit_get_addr) {
472                 *max_perf = ioread32(dom->fc_info->limit_get_addr);
473                 *min_perf = ioread32(dom->fc_info->limit_get_addr + 4);
474                 return 0;
475         }
476
477         return scmi_perf_mb_limits_get(ph, domain, max_perf, min_perf);
478 }
479
480 static int scmi_perf_mb_level_set(const struct scmi_protocol_handle *ph,
481                                   u32 domain, u32 level, bool poll)
482 {
483         int ret;
484         struct scmi_xfer *t;
485         struct scmi_perf_set_level *lvl;
486
487         ret = ph->xops->xfer_get_init(ph, PERF_LEVEL_SET, sizeof(*lvl), 0, &t);
488         if (ret)
489                 return ret;
490
491         t->hdr.poll_completion = poll;
492         lvl = t->tx.buf;
493         lvl->domain = cpu_to_le32(domain);
494         lvl->level = cpu_to_le32(level);
495
496         ret = ph->xops->do_xfer(ph, t);
497
498         ph->xops->xfer_put(ph, t);
499         return ret;
500 }
501
502 static int scmi_perf_level_set(const struct scmi_protocol_handle *ph,
503                                u32 domain, u32 level, bool poll)
504 {
505         struct scmi_perf_info *pi = ph->get_priv(ph);
506         struct perf_dom_info *dom = pi->dom_info + domain;
507
508         if (dom->fc_info && dom->fc_info->level_set_addr) {
509                 iowrite32(level, dom->fc_info->level_set_addr);
510                 scmi_perf_fc_ring_db(dom->fc_info->level_set_db);
511                 return 0;
512         }
513
514         return scmi_perf_mb_level_set(ph, domain, level, poll);
515 }
516
517 static int scmi_perf_mb_level_get(const struct scmi_protocol_handle *ph,
518                                   u32 domain, u32 *level, bool poll)
519 {
520         int ret;
521         struct scmi_xfer *t;
522
523         ret = ph->xops->xfer_get_init(ph, PERF_LEVEL_GET,
524                                      sizeof(u32), sizeof(u32), &t);
525         if (ret)
526                 return ret;
527
528         t->hdr.poll_completion = poll;
529         put_unaligned_le32(domain, t->tx.buf);
530
531         ret = ph->xops->do_xfer(ph, t);
532         if (!ret)
533                 *level = get_unaligned_le32(t->rx.buf);
534
535         ph->xops->xfer_put(ph, t);
536         return ret;
537 }
538
539 static int scmi_perf_level_get(const struct scmi_protocol_handle *ph,
540                                u32 domain, u32 *level, bool poll)
541 {
542         struct scmi_perf_info *pi = ph->get_priv(ph);
543         struct perf_dom_info *dom = pi->dom_info + domain;
544
545         if (dom->fc_info && dom->fc_info->level_get_addr) {
546                 *level = ioread32(dom->fc_info->level_get_addr);
547                 return 0;
548         }
549
550         return scmi_perf_mb_level_get(ph, domain, level, poll);
551 }
552
553 static int scmi_perf_level_limits_notify(const struct scmi_protocol_handle *ph,
554                                          u32 domain, int message_id,
555                                          bool enable)
556 {
557         int ret;
558         struct scmi_xfer *t;
559         struct scmi_perf_notify_level_or_limits *notify;
560
561         ret = ph->xops->xfer_get_init(ph, message_id, sizeof(*notify), 0, &t);
562         if (ret)
563                 return ret;
564
565         notify = t->tx.buf;
566         notify->domain = cpu_to_le32(domain);
567         notify->notify_enable = enable ? cpu_to_le32(BIT(0)) : 0;
568
569         ret = ph->xops->do_xfer(ph, t);
570
571         ph->xops->xfer_put(ph, t);
572         return ret;
573 }
574
575 static bool scmi_perf_fc_size_is_valid(u32 msg, u32 size)
576 {
577         if ((msg == PERF_LEVEL_GET || msg == PERF_LEVEL_SET) && size == 4)
578                 return true;
579         if ((msg == PERF_LIMITS_GET || msg == PERF_LIMITS_SET) && size == 8)
580                 return true;
581         return false;
582 }
583
584 static void
585 scmi_perf_domain_desc_fc(const struct scmi_protocol_handle *ph, u32 domain,
586                          u32 message_id, void __iomem **p_addr,
587                          struct scmi_fc_db_info **p_db)
588 {
589         int ret;
590         u32 flags;
591         u64 phys_addr;
592         u8 size;
593         void __iomem *addr;
594         struct scmi_xfer *t;
595         struct scmi_fc_db_info *db;
596         struct scmi_perf_get_fc_info *info;
597         struct scmi_msg_resp_perf_desc_fc *resp;
598
599         if (!p_addr)
600                 return;
601
602         ret = ph->xops->xfer_get_init(ph, PERF_DESCRIBE_FASTCHANNEL,
603                                       sizeof(*info), sizeof(*resp), &t);
604         if (ret)
605                 return;
606
607         info = t->tx.buf;
608         info->domain = cpu_to_le32(domain);
609         info->message_id = cpu_to_le32(message_id);
610
611         ret = ph->xops->do_xfer(ph, t);
612         if (ret)
613                 goto err_xfer;
614
615         resp = t->rx.buf;
616         flags = le32_to_cpu(resp->attr);
617         size = le32_to_cpu(resp->chan_size);
618         if (!scmi_perf_fc_size_is_valid(message_id, size))
619                 goto err_xfer;
620
621         phys_addr = le32_to_cpu(resp->chan_addr_low);
622         phys_addr |= (u64)le32_to_cpu(resp->chan_addr_high) << 32;
623         addr = devm_ioremap(ph->dev, phys_addr, size);
624         if (!addr)
625                 goto err_xfer;
626         *p_addr = addr;
627
628         if (p_db && SUPPORTS_DOORBELL(flags)) {
629                 db = devm_kzalloc(ph->dev, sizeof(*db), GFP_KERNEL);
630                 if (!db)
631                         goto err_xfer;
632
633                 size = 1 << DOORBELL_REG_WIDTH(flags);
634                 phys_addr = le32_to_cpu(resp->db_addr_low);
635                 phys_addr |= (u64)le32_to_cpu(resp->db_addr_high) << 32;
636                 addr = devm_ioremap(ph->dev, phys_addr, size);
637                 if (!addr)
638                         goto err_xfer;
639
640                 db->addr = addr;
641                 db->width = size;
642                 db->set = le32_to_cpu(resp->db_set_lmask);
643                 db->set |= (u64)le32_to_cpu(resp->db_set_hmask) << 32;
644                 db->mask = le32_to_cpu(resp->db_preserve_lmask);
645                 db->mask |= (u64)le32_to_cpu(resp->db_preserve_hmask) << 32;
646                 *p_db = db;
647         }
648 err_xfer:
649         ph->xops->xfer_put(ph, t);
650 }
651
652 static void scmi_perf_domain_init_fc(const struct scmi_protocol_handle *ph,
653                                      u32 domain, struct scmi_fc_info **p_fc)
654 {
655         struct scmi_fc_info *fc;
656
657         fc = devm_kzalloc(ph->dev, sizeof(*fc), GFP_KERNEL);
658         if (!fc)
659                 return;
660
661         scmi_perf_domain_desc_fc(ph, domain, PERF_LEVEL_SET,
662                                  &fc->level_set_addr, &fc->level_set_db);
663         scmi_perf_domain_desc_fc(ph, domain, PERF_LEVEL_GET,
664                                  &fc->level_get_addr, NULL);
665         scmi_perf_domain_desc_fc(ph, domain, PERF_LIMITS_SET,
666                                  &fc->limit_set_addr, &fc->limit_set_db);
667         scmi_perf_domain_desc_fc(ph, domain, PERF_LIMITS_GET,
668                                  &fc->limit_get_addr, NULL);
669         *p_fc = fc;
670 }
671
672 /* Device specific ops */
673 static int scmi_dev_domain_id(struct device *dev)
674 {
675         struct of_phandle_args clkspec;
676
677         if (of_parse_phandle_with_args(dev->of_node, "clocks", "#clock-cells",
678                                        0, &clkspec))
679                 return -EINVAL;
680
681         return clkspec.args[0];
682 }
683
684 static int scmi_dvfs_device_opps_add(const struct scmi_protocol_handle *ph,
685                                      struct device *dev)
686 {
687         int idx, ret, domain;
688         unsigned long freq;
689         struct scmi_opp *opp;
690         struct perf_dom_info *dom;
691         struct scmi_perf_info *pi = ph->get_priv(ph);
692
693         domain = scmi_dev_domain_id(dev);
694         if (domain < 0)
695                 return domain;
696
697         dom = pi->dom_info + domain;
698
699         for (opp = dom->opp, idx = 0; idx < dom->opp_count; idx++, opp++) {
700                 freq = opp->perf * dom->mult_factor;
701
702                 ret = dev_pm_opp_add(dev, freq, 0);
703                 if (ret) {
704                         dev_warn(dev, "failed to add opp %luHz\n", freq);
705
706                         while (idx-- > 0) {
707                                 freq = (--opp)->perf * dom->mult_factor;
708                                 dev_pm_opp_remove(dev, freq);
709                         }
710                         return ret;
711                 }
712         }
713         return 0;
714 }
715
716 static int
717 scmi_dvfs_transition_latency_get(const struct scmi_protocol_handle *ph,
718                                  struct device *dev)
719 {
720         struct perf_dom_info *dom;
721         struct scmi_perf_info *pi = ph->get_priv(ph);
722         int domain = scmi_dev_domain_id(dev);
723
724         if (domain < 0)
725                 return domain;
726
727         dom = pi->dom_info + domain;
728         /* uS to nS */
729         return dom->opp[dom->opp_count - 1].trans_latency_us * 1000;
730 }
731
732 static int scmi_dvfs_freq_set(const struct scmi_protocol_handle *ph, u32 domain,
733                               unsigned long freq, bool poll)
734 {
735         struct scmi_perf_info *pi = ph->get_priv(ph);
736         struct perf_dom_info *dom = pi->dom_info + domain;
737
738         return scmi_perf_level_set(ph, domain, freq / dom->mult_factor, poll);
739 }
740
741 static int scmi_dvfs_freq_get(const struct scmi_protocol_handle *ph, u32 domain,
742                               unsigned long *freq, bool poll)
743 {
744         int ret;
745         u32 level;
746         struct scmi_perf_info *pi = ph->get_priv(ph);
747         struct perf_dom_info *dom = pi->dom_info + domain;
748
749         ret = scmi_perf_level_get(ph, domain, &level, poll);
750         if (!ret)
751                 *freq = level * dom->mult_factor;
752
753         return ret;
754 }
755
756 static int scmi_dvfs_est_power_get(const struct scmi_protocol_handle *ph,
757                                    u32 domain, unsigned long *freq,
758                                    unsigned long *power)
759 {
760         struct scmi_perf_info *pi = ph->get_priv(ph);
761         struct perf_dom_info *dom;
762         unsigned long opp_freq;
763         int idx, ret = -EINVAL;
764         struct scmi_opp *opp;
765
766         dom = pi->dom_info + domain;
767         if (!dom)
768                 return -EIO;
769
770         for (opp = dom->opp, idx = 0; idx < dom->opp_count; idx++, opp++) {
771                 opp_freq = opp->perf * dom->mult_factor;
772                 if (opp_freq < *freq)
773                         continue;
774
775                 *freq = opp_freq;
776                 *power = opp->power;
777                 ret = 0;
778                 break;
779         }
780
781         return ret;
782 }
783
784 static bool scmi_fast_switch_possible(const struct scmi_protocol_handle *ph,
785                                       struct device *dev)
786 {
787         struct perf_dom_info *dom;
788         struct scmi_perf_info *pi = ph->get_priv(ph);
789
790         dom = pi->dom_info + scmi_dev_domain_id(dev);
791
792         return dom->fc_info && dom->fc_info->level_set_addr;
793 }
794
795 static bool scmi_power_scale_mw_get(const struct scmi_protocol_handle *ph)
796 {
797         struct scmi_perf_info *pi = ph->get_priv(ph);
798
799         return pi->power_scale_mw;
800 }
801
802 static const struct scmi_perf_proto_ops perf_proto_ops = {
803         .limits_set = scmi_perf_limits_set,
804         .limits_get = scmi_perf_limits_get,
805         .level_set = scmi_perf_level_set,
806         .level_get = scmi_perf_level_get,
807         .device_domain_id = scmi_dev_domain_id,
808         .transition_latency_get = scmi_dvfs_transition_latency_get,
809         .device_opps_add = scmi_dvfs_device_opps_add,
810         .freq_set = scmi_dvfs_freq_set,
811         .freq_get = scmi_dvfs_freq_get,
812         .est_power_get = scmi_dvfs_est_power_get,
813         .fast_switch_possible = scmi_fast_switch_possible,
814         .power_scale_mw_get = scmi_power_scale_mw_get,
815 };
816
817 static int scmi_perf_set_notify_enabled(const struct scmi_protocol_handle *ph,
818                                         u8 evt_id, u32 src_id, bool enable)
819 {
820         int ret, cmd_id;
821
822         if (evt_id >= ARRAY_SIZE(evt_2_cmd))
823                 return -EINVAL;
824
825         cmd_id = evt_2_cmd[evt_id];
826         ret = scmi_perf_level_limits_notify(ph, src_id, cmd_id, enable);
827         if (ret)
828                 pr_debug("FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n",
829                          evt_id, src_id, ret);
830
831         return ret;
832 }
833
834 static void *scmi_perf_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_PERFORMANCE_LIMITS_CHANGED:
843         {
844                 const struct scmi_perf_limits_notify_payld *p = payld;
845                 struct scmi_perf_limits_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->range_max = le32_to_cpu(p->range_max);
854                 r->range_min = le32_to_cpu(p->range_min);
855                 *src_id = r->domain_id;
856                 rep = r;
857                 break;
858         }
859         case SCMI_EVENT_PERFORMANCE_LEVEL_CHANGED:
860         {
861                 const struct scmi_perf_level_notify_payld *p = payld;
862                 struct scmi_perf_level_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->performance_level = le32_to_cpu(p->performance_level);
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 scmi_perf_get_num_sources(const struct scmi_protocol_handle *ph)
883 {
884         struct scmi_perf_info *pi = ph->get_priv(ph);
885
886         if (!pi)
887                 return -EINVAL;
888
889         return pi->num_domains;
890 }
891
892 static const struct scmi_event perf_events[] = {
893         {
894                 .id = SCMI_EVENT_PERFORMANCE_LIMITS_CHANGED,
895                 .max_payld_sz = sizeof(struct scmi_perf_limits_notify_payld),
896                 .max_report_sz = sizeof(struct scmi_perf_limits_report),
897         },
898         {
899                 .id = SCMI_EVENT_PERFORMANCE_LEVEL_CHANGED,
900                 .max_payld_sz = sizeof(struct scmi_perf_level_notify_payld),
901                 .max_report_sz = sizeof(struct scmi_perf_level_report),
902         },
903 };
904
905 static const struct scmi_event_ops perf_event_ops = {
906         .get_num_sources = scmi_perf_get_num_sources,
907         .set_notify_enabled = scmi_perf_set_notify_enabled,
908         .fill_custom_report = scmi_perf_fill_custom_report,
909 };
910
911 static const struct scmi_protocol_events perf_protocol_events = {
912         .queue_sz = SCMI_PROTO_QUEUE_SZ,
913         .ops = &perf_event_ops,
914         .evts = perf_events,
915         .num_events = ARRAY_SIZE(perf_events),
916 };
917
918 static int scmi_perf_protocol_init(const struct scmi_protocol_handle *ph)
919 {
920         int domain, ret;
921         u32 version;
922         struct scmi_perf_info *pinfo;
923
924         ret = ph->xops->version_get(ph, &version);
925         if (ret)
926                 return ret;
927
928         dev_dbg(ph->dev, "Performance Version %d.%d\n",
929                 PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
930
931         pinfo = devm_kzalloc(ph->dev, sizeof(*pinfo), GFP_KERNEL);
932         if (!pinfo)
933                 return -ENOMEM;
934
935         ret = scmi_perf_attributes_get(ph, pinfo);
936         if (ret)
937                 return ret;
938
939         pinfo->dom_info = devm_kcalloc(ph->dev, pinfo->num_domains,
940                                        sizeof(*pinfo->dom_info), GFP_KERNEL);
941         if (!pinfo->dom_info)
942                 return -ENOMEM;
943
944         for (domain = 0; domain < pinfo->num_domains; domain++) {
945                 struct perf_dom_info *dom = pinfo->dom_info + domain;
946
947                 scmi_perf_domain_attributes_get(ph, domain, dom, version);
948                 scmi_perf_describe_levels_get(ph, domain, dom);
949
950                 if (dom->perf_fastchannels)
951                         scmi_perf_domain_init_fc(ph, domain, &dom->fc_info);
952         }
953
954         pinfo->version = version;
955
956         return ph->set_priv(ph, pinfo);
957 }
958
959 static const struct scmi_protocol scmi_perf = {
960         .id = SCMI_PROTOCOL_PERF,
961         .owner = THIS_MODULE,
962         .instance_init = &scmi_perf_protocol_init,
963         .ops = &perf_proto_ops,
964         .events = &perf_protocol_events,
965 };
966
967 DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(perf, scmi_perf)