xref: /openbmc/linux/drivers/firmware/arm_scmi/perf.c (revision dd5e5554)
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)
968