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