xref: /linux/drivers/firmware/arm_scmi/powercap.c (revision bba2c3615bd6cfee7456d1130f2e6b01b3f4e9ba)
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 		if (!scmi_powercap_dom_info_get(ph, domain_id))
458 			return -EINVAL;
459 
460 		if (!pi->states[domain_id].enabled) {
461 			pi->states[domain_id].last_pcap = power_cap;
462 			return 0;
463 		}
464 	}
465 
466 	return __scmi_powercap_cap_set(ph, pi, domain_id,
467 				       power_cap, ignore_dresp);
468 }
469 
470 static int scmi_powercap_xfer_pai_get(const struct scmi_protocol_handle *ph,
471 				      u32 domain_id, u32 *pai)
472 {
473 	int ret;
474 	struct scmi_xfer *t;
475 
476 	ret = ph->xops->xfer_get_init(ph, POWERCAP_PAI_GET, sizeof(u32),
477 				      sizeof(u32), &t);
478 	if (ret)
479 		return ret;
480 
481 	put_unaligned_le32(domain_id, t->tx.buf);
482 	ret = ph->xops->do_xfer(ph, t);
483 	if (!ret)
484 		*pai = get_unaligned_le32(t->rx.buf);
485 
486 	ph->xops->xfer_put(ph, t);
487 
488 	return ret;
489 }
490 
491 static int scmi_powercap_pai_get(const struct scmi_protocol_handle *ph,
492 				 u32 domain_id, u32 *pai)
493 {
494 	struct scmi_powercap_info *dom;
495 	struct powercap_info *pi = ph->get_priv(ph);
496 
497 	if (!pai || domain_id >= pi->num_domains)
498 		return -EINVAL;
499 
500 	dom = pi->powercaps + domain_id;
501 	if (dom->fc_info && dom->fc_info[POWERCAP_FC_PAI].get_addr) {
502 		*pai = ioread32(dom->fc_info[POWERCAP_FC_PAI].get_addr);
503 		trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_PAI_GET,
504 				   domain_id, *pai, 0);
505 		return 0;
506 	}
507 
508 	return scmi_powercap_xfer_pai_get(ph, domain_id, pai);
509 }
510 
511 static int scmi_powercap_xfer_pai_set(const struct scmi_protocol_handle *ph,
512 				      u32 domain_id, u32 pai)
513 {
514 	int ret;
515 	struct scmi_xfer *t;
516 	struct scmi_msg_powercap_set_cap_or_pai *msg;
517 
518 	ret = ph->xops->xfer_get_init(ph, POWERCAP_PAI_SET,
519 				      sizeof(*msg), 0, &t);
520 	if (ret)
521 		return ret;
522 
523 	msg = t->tx.buf;
524 	msg->domain = cpu_to_le32(domain_id);
525 	msg->flags = cpu_to_le32(0);
526 	msg->value = cpu_to_le32(pai);
527 
528 	ret = ph->xops->do_xfer(ph, t);
529 
530 	ph->xops->xfer_put(ph, t);
531 	return ret;
532 }
533 
534 static int scmi_powercap_pai_set(const struct scmi_protocol_handle *ph,
535 				 u32 domain_id, u32 pai)
536 {
537 	const struct scmi_powercap_info *pc;
538 
539 	pc = scmi_powercap_dom_info_get(ph, domain_id);
540 	if (!pc || !pc->powercap_pai_config || !pai ||
541 	    pai < pc->min_pai || pai > pc->max_pai)
542 		return -EINVAL;
543 
544 	if (pc->fc_info && pc->fc_info[POWERCAP_FC_PAI].set_addr) {
545 		struct scmi_fc_info *fci = &pc->fc_info[POWERCAP_FC_PAI];
546 
547 		trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_PAI_SET,
548 				   domain_id, pai, 0);
549 		iowrite32(pai, fci->set_addr);
550 		ph->hops->fastchannel_db_ring(fci->set_db);
551 		return 0;
552 	}
553 
554 	return scmi_powercap_xfer_pai_set(ph, domain_id, pai);
555 }
556 
557 static int scmi_powercap_measurements_get(const struct scmi_protocol_handle *ph,
558 					  u32 domain_id, u32 *average_power,
559 					  u32 *pai)
560 {
561 	int ret;
562 	struct scmi_xfer *t;
563 	struct scmi_msg_resp_powercap_meas_get *resp;
564 	const struct scmi_powercap_info *pc;
565 
566 	pc = scmi_powercap_dom_info_get(ph, domain_id);
567 	if (!pc || !pc->powercap_monitoring || !pai || !average_power)
568 		return -EINVAL;
569 
570 	ret = ph->xops->xfer_get_init(ph, POWERCAP_MEASUREMENTS_GET,
571 				      sizeof(u32), sizeof(*resp), &t);
572 	if (ret)
573 		return ret;
574 
575 	resp = t->rx.buf;
576 	put_unaligned_le32(domain_id, t->tx.buf);
577 	ret = ph->xops->do_xfer(ph, t);
578 	if (!ret) {
579 		*average_power = le32_to_cpu(resp->power);
580 		*pai = le32_to_cpu(resp->pai);
581 	}
582 
583 	ph->xops->xfer_put(ph, t);
584 	return ret;
585 }
586 
587 static int
588 scmi_powercap_measurements_threshold_get(const struct scmi_protocol_handle *ph,
589 					 u32 domain_id, u32 *power_thresh_low,
590 					 u32 *power_thresh_high)
591 {
592 	struct powercap_info *pi = ph->get_priv(ph);
593 
594 	if (!power_thresh_low || !power_thresh_high ||
595 	    domain_id >= pi->num_domains)
596 		return -EINVAL;
597 
598 	*power_thresh_low =  THRESH_LOW(pi, domain_id);
599 	*power_thresh_high = THRESH_HIGH(pi, domain_id);
600 
601 	return 0;
602 }
603 
604 static int
605 scmi_powercap_measurements_threshold_set(const struct scmi_protocol_handle *ph,
606 					 u32 domain_id, u32 power_thresh_low,
607 					 u32 power_thresh_high)
608 {
609 	int ret = 0;
610 	struct powercap_info *pi = ph->get_priv(ph);
611 
612 	if (domain_id >= pi->num_domains ||
613 	    power_thresh_low > power_thresh_high)
614 		return -EINVAL;
615 
616 	/* Anything to do ? */
617 	if (THRESH_LOW(pi, domain_id) == power_thresh_low &&
618 	    THRESH_HIGH(pi, domain_id) == power_thresh_high)
619 		return ret;
620 
621 	pi->states[domain_id].thresholds =
622 		(FIELD_PREP(GENMASK_ULL(31, 0), power_thresh_low) |
623 		 FIELD_PREP(GENMASK_ULL(63, 32), power_thresh_high));
624 
625 	/* Update thresholds if notification already enabled */
626 	if (pi->states[domain_id].meas_notif_enabled)
627 		ret = scmi_powercap_notify(ph, domain_id,
628 					   POWERCAP_MEASUREMENTS_NOTIFY,
629 					   true);
630 
631 	return ret;
632 }
633 
634 static int scmi_powercap_cap_enable_set(const struct scmi_protocol_handle *ph,
635 					u32 domain_id, bool enable)
636 {
637 	int ret;
638 	u32 power_cap;
639 	struct powercap_info *pi = ph->get_priv(ph);
640 
641 	if (PROTOCOL_REV_MAJOR(ph->version) < 0x2)
642 		return -EINVAL;
643 
644 	if (!scmi_powercap_dom_info_get(ph, domain_id))
645 		return -EINVAL;
646 
647 	if (enable == pi->states[domain_id].enabled)
648 		return 0;
649 
650 	if (enable) {
651 		/* Cannot enable with a zero powercap. */
652 		if (!pi->states[domain_id].last_pcap)
653 			return -EINVAL;
654 
655 		ret = __scmi_powercap_cap_set(ph, pi, domain_id,
656 					      pi->states[domain_id].last_pcap,
657 					      true);
658 	} else {
659 		ret = __scmi_powercap_cap_set(ph, pi, domain_id, 0, true);
660 	}
661 
662 	if (ret)
663 		return ret;
664 
665 	/*
666 	 * Update our internal state to reflect final platform state: the SCMI
667 	 * server could have ignored a disable request and kept enforcing some
668 	 * powercap limit requested by other agents.
669 	 */
670 	ret = scmi_powercap_cap_get(ph, domain_id, &power_cap);
671 	if (!ret)
672 		pi->states[domain_id].enabled = !!power_cap;
673 
674 	return ret;
675 }
676 
677 static int scmi_powercap_cap_enable_get(const struct scmi_protocol_handle *ph,
678 					u32 domain_id, bool *enable)
679 {
680 	int ret;
681 	u32 power_cap;
682 	struct powercap_info *pi = ph->get_priv(ph);
683 
684 	*enable = true;
685 	if (PROTOCOL_REV_MAJOR(ph->version) < 0x2)
686 		return 0;
687 
688 	if (!scmi_powercap_dom_info_get(ph, domain_id))
689 		return -EINVAL;
690 
691 	/*
692 	 * Report always real platform state; platform could have ignored
693 	 * a previous disable request. Default true on any error.
694 	 */
695 	ret = scmi_powercap_cap_get(ph, domain_id, &power_cap);
696 	if (!ret)
697 		*enable = !!power_cap;
698 
699 	/* Update internal state with current real platform state */
700 	pi->states[domain_id].enabled = *enable;
701 
702 	return 0;
703 }
704 
705 static const struct scmi_powercap_proto_ops powercap_proto_ops = {
706 	.num_domains_get = scmi_powercap_num_domains_get,
707 	.info_get = scmi_powercap_dom_info_get,
708 	.cap_get = scmi_powercap_cap_get,
709 	.cap_set = scmi_powercap_cap_set,
710 	.cap_enable_set = scmi_powercap_cap_enable_set,
711 	.cap_enable_get = scmi_powercap_cap_enable_get,
712 	.pai_get = scmi_powercap_pai_get,
713 	.pai_set = scmi_powercap_pai_set,
714 	.measurements_get = scmi_powercap_measurements_get,
715 	.measurements_threshold_set = scmi_powercap_measurements_threshold_set,
716 	.measurements_threshold_get = scmi_powercap_measurements_threshold_get,
717 };
718 
719 static void scmi_powercap_domain_init_fc(const struct scmi_protocol_handle *ph,
720 					 u32 domain, struct scmi_fc_info **p_fc)
721 {
722 	struct scmi_fc_info *fc;
723 
724 	fc = devm_kcalloc(ph->dev, POWERCAP_FC_MAX, sizeof(*fc), GFP_KERNEL);
725 	if (!fc)
726 		return;
727 
728 	ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
729 				   POWERCAP_CAP_SET, 4, domain,
730 				   &fc[POWERCAP_FC_CAP].set_addr,
731 				   &fc[POWERCAP_FC_CAP].set_db,
732 				   &fc[POWERCAP_FC_CAP].rate_limit);
733 
734 	ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
735 				   POWERCAP_CAP_GET, 4, domain,
736 				   &fc[POWERCAP_FC_CAP].get_addr, NULL,
737 				   &fc[POWERCAP_FC_CAP].rate_limit);
738 
739 	ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
740 				   POWERCAP_PAI_SET, 4, domain,
741 				   &fc[POWERCAP_FC_PAI].set_addr,
742 				   &fc[POWERCAP_FC_PAI].set_db,
743 				   &fc[POWERCAP_FC_PAI].rate_limit);
744 
745 	ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
746 				   POWERCAP_PAI_GET, 4, domain,
747 				   &fc[POWERCAP_FC_PAI].get_addr, NULL,
748 				   &fc[POWERCAP_FC_PAI].rate_limit);
749 
750 	*p_fc = fc;
751 }
752 
753 static int scmi_powercap_notify(const struct scmi_protocol_handle *ph,
754 				u32 domain, int message_id, bool enable)
755 {
756 	int ret;
757 	struct scmi_xfer *t;
758 
759 	switch (message_id) {
760 	case POWERCAP_CAP_NOTIFY:
761 	{
762 		struct scmi_msg_powercap_notify_cap *notify;
763 
764 		ret = ph->xops->xfer_get_init(ph, message_id,
765 					      sizeof(*notify), 0, &t);
766 		if (ret)
767 			return ret;
768 
769 		notify = t->tx.buf;
770 		notify->domain = cpu_to_le32(domain);
771 		notify->notify_enable = cpu_to_le32(enable ? BIT(0) : 0);
772 		break;
773 	}
774 	case POWERCAP_MEASUREMENTS_NOTIFY:
775 	{
776 		u32 low, high;
777 		struct scmi_msg_powercap_notify_thresh *notify;
778 
779 		/*
780 		 * Note that we have to pick the most recently configured
781 		 * thresholds to build a proper POWERCAP_MEASUREMENTS_NOTIFY
782 		 * enable request and we fail, complaining, if no thresholds
783 		 * were ever set, since this is an indication the API has been
784 		 * used wrongly.
785 		 */
786 		ret = scmi_powercap_measurements_threshold_get(ph, domain,
787 							       &low, &high);
788 		if (ret)
789 			return ret;
790 
791 		if (enable && !low && !high) {
792 			dev_err(ph->dev,
793 				"Invalid Measurements Notify thresholds: %u/%u\n",
794 				low, high);
795 			return -EINVAL;
796 		}
797 
798 		ret = ph->xops->xfer_get_init(ph, message_id,
799 					      sizeof(*notify), 0, &t);
800 		if (ret)
801 			return ret;
802 
803 		notify = t->tx.buf;
804 		notify->domain = cpu_to_le32(domain);
805 		notify->notify_enable = cpu_to_le32(enable ? BIT(0) : 0);
806 		notify->power_thresh_low = cpu_to_le32(low);
807 		notify->power_thresh_high = cpu_to_le32(high);
808 		break;
809 	}
810 	default:
811 		return -EINVAL;
812 	}
813 
814 	ret = ph->xops->do_xfer(ph, t);
815 
816 	ph->xops->xfer_put(ph, t);
817 	return ret;
818 }
819 
820 static bool
821 scmi_powercap_notify_supported(const struct scmi_protocol_handle *ph,
822 			       u8 evt_id, u32 src_id)
823 {
824 	bool supported = false;
825 	const struct scmi_powercap_info *dom_info;
826 	struct powercap_info *pi = ph->get_priv(ph);
827 
828 	if (evt_id >= ARRAY_SIZE(evt_2_cmd) || src_id >= pi->num_domains)
829 		return false;
830 
831 	dom_info = pi->powercaps + src_id;
832 	if (evt_id == SCMI_EVENT_POWERCAP_CAP_CHANGED)
833 		supported = dom_info->notify_powercap_cap_change;
834 	else if (evt_id == SCMI_EVENT_POWERCAP_MEASUREMENTS_CHANGED)
835 		supported = dom_info->notify_powercap_measurement_change;
836 
837 	return supported;
838 }
839 
840 static int
841 scmi_powercap_set_notify_enabled(const struct scmi_protocol_handle *ph,
842 				 u8 evt_id, u32 src_id, bool enable)
843 {
844 	int ret, cmd_id;
845 	struct powercap_info *pi = ph->get_priv(ph);
846 
847 	if (evt_id >= ARRAY_SIZE(evt_2_cmd) || src_id >= pi->num_domains)
848 		return -EINVAL;
849 
850 	cmd_id = evt_2_cmd[evt_id];
851 	ret = scmi_powercap_notify(ph, src_id, cmd_id, enable);
852 	if (ret)
853 		pr_debug("FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n",
854 			 evt_id, src_id, ret);
855 	else if (cmd_id == POWERCAP_MEASUREMENTS_NOTIFY)
856 		/*
857 		 * On success save the current notification enabled state, so
858 		 * as to be able to properly update the notification thresholds
859 		 * when they are modified on a domain for which measurement
860 		 * notifications were currently enabled.
861 		 *
862 		 * This is needed because the SCMI Notification core machinery
863 		 * and API does not support passing per-notification custom
864 		 * arguments at callback registration time.
865 		 *
866 		 * Note that this can be done here with a simple flag since the
867 		 * SCMI core Notifications code takes care of keeping proper
868 		 * per-domain enables refcounting, so that this helper function
869 		 * will be called only once (for enables) when the first user
870 		 * registers a callback on this domain and once more (disable)
871 		 * when the last user de-registers its callback.
872 		 */
873 		pi->states[src_id].meas_notif_enabled = enable;
874 
875 	return ret;
876 }
877 
878 static void *
879 scmi_powercap_fill_custom_report(const struct scmi_protocol_handle *ph,
880 				 u8 evt_id, ktime_t timestamp,
881 				 const void *payld, size_t payld_sz,
882 				 void *report, u32 *src_id)
883 {
884 	void *rep = NULL;
885 
886 	switch (evt_id) {
887 	case SCMI_EVENT_POWERCAP_CAP_CHANGED:
888 	{
889 		const struct scmi_powercap_cap_changed_notify_payld *p = payld;
890 		struct scmi_powercap_cap_changed_report *r = report;
891 
892 		if (sizeof(*p) != payld_sz)
893 			break;
894 
895 		r->timestamp = timestamp;
896 		r->agent_id = le32_to_cpu(p->agent_id);
897 		r->domain_id = le32_to_cpu(p->domain_id);
898 		r->power_cap = le32_to_cpu(p->power_cap);
899 		r->pai = le32_to_cpu(p->pai);
900 		*src_id = r->domain_id;
901 		rep = r;
902 		break;
903 	}
904 	case SCMI_EVENT_POWERCAP_MEASUREMENTS_CHANGED:
905 	{
906 		const struct scmi_powercap_meas_changed_notify_payld *p = payld;
907 		struct scmi_powercap_meas_changed_report *r = report;
908 
909 		if (sizeof(*p) != payld_sz)
910 			break;
911 
912 		r->timestamp = timestamp;
913 		r->agent_id = le32_to_cpu(p->agent_id);
914 		r->domain_id = le32_to_cpu(p->domain_id);
915 		r->power = le32_to_cpu(p->power);
916 		*src_id = r->domain_id;
917 		rep = r;
918 		break;
919 	}
920 	default:
921 		break;
922 	}
923 
924 	return rep;
925 }
926 
927 static int
928 scmi_powercap_get_num_sources(const struct scmi_protocol_handle *ph)
929 {
930 	struct powercap_info *pi = ph->get_priv(ph);
931 
932 	if (!pi)
933 		return -EINVAL;
934 
935 	return pi->num_domains;
936 }
937 
938 static const struct scmi_event powercap_events[] = {
939 	{
940 		.id = SCMI_EVENT_POWERCAP_CAP_CHANGED,
941 		.max_payld_sz =
942 			sizeof(struct scmi_powercap_cap_changed_notify_payld),
943 		.max_report_sz =
944 			sizeof(struct scmi_powercap_cap_changed_report),
945 	},
946 	{
947 		.id = SCMI_EVENT_POWERCAP_MEASUREMENTS_CHANGED,
948 		.max_payld_sz =
949 			sizeof(struct scmi_powercap_meas_changed_notify_payld),
950 		.max_report_sz =
951 			sizeof(struct scmi_powercap_meas_changed_report),
952 	},
953 };
954 
955 static const struct scmi_event_ops powercap_event_ops = {
956 	.is_notify_supported = scmi_powercap_notify_supported,
957 	.get_num_sources = scmi_powercap_get_num_sources,
958 	.set_notify_enabled = scmi_powercap_set_notify_enabled,
959 	.fill_custom_report = scmi_powercap_fill_custom_report,
960 };
961 
962 static const struct scmi_protocol_events powercap_protocol_events = {
963 	.queue_sz = SCMI_PROTO_QUEUE_SZ,
964 	.ops = &powercap_event_ops,
965 	.evts = powercap_events,
966 	.num_events = ARRAY_SIZE(powercap_events),
967 };
968 
969 static int
970 scmi_powercap_protocol_init(const struct scmi_protocol_handle *ph)
971 {
972 	int domain, ret;
973 	struct powercap_info *pinfo;
974 
975 	dev_dbg(ph->dev, "Powercap Version %d.%d\n",
976 		PROTOCOL_REV_MAJOR(ph->version), PROTOCOL_REV_MINOR(ph->version));
977 
978 	pinfo = devm_kzalloc(ph->dev, sizeof(*pinfo), GFP_KERNEL);
979 	if (!pinfo)
980 		return -ENOMEM;
981 
982 	ret = scmi_powercap_attributes_get(ph, pinfo);
983 	if (ret)
984 		return ret;
985 
986 	pinfo->powercaps = devm_kcalloc(ph->dev, pinfo->num_domains,
987 					sizeof(*pinfo->powercaps),
988 					GFP_KERNEL);
989 	if (!pinfo->powercaps)
990 		return -ENOMEM;
991 
992 	pinfo->states = devm_kcalloc(ph->dev, pinfo->num_domains,
993 				     sizeof(*pinfo->states), GFP_KERNEL);
994 	if (!pinfo->states)
995 		return -ENOMEM;
996 
997 	/*
998 	 * Note that any failure in retrieving any domain attribute leads to
999 	 * the whole Powercap protocol initialization failure: this way the
1000 	 * reported Powercap domains are all assured, when accessed, to be well
1001 	 * formed and correlated by sane parent-child relationship (if any).
1002 	 */
1003 	for (domain = 0; domain < pinfo->num_domains; domain++) {
1004 		ret = scmi_powercap_domain_attributes_get(ph, pinfo, domain);
1005 		if (ret)
1006 			return ret;
1007 
1008 		if (pinfo->powercaps[domain].fastchannels)
1009 			scmi_powercap_domain_init_fc(ph, domain,
1010 						     &pinfo->powercaps[domain].fc_info);
1011 
1012 		/* Grab initial state when disable is supported. */
1013 		if (PROTOCOL_REV_MAJOR(ph->version) >= 0x2) {
1014 			ret = __scmi_powercap_cap_get(ph,
1015 						      &pinfo->powercaps[domain],
1016 						      &pinfo->states[domain].last_pcap);
1017 			if (ret)
1018 				return ret;
1019 
1020 			pinfo->states[domain].enabled =
1021 				!!pinfo->states[domain].last_pcap;
1022 		}
1023 	}
1024 
1025 	return ph->set_priv(ph, pinfo);
1026 }
1027 
1028 static const struct scmi_protocol scmi_powercap = {
1029 	.id = SCMI_PROTOCOL_POWERCAP,
1030 	.owner = THIS_MODULE,
1031 	.instance_init = &scmi_powercap_protocol_init,
1032 	.ops = &powercap_proto_ops,
1033 	.events = &powercap_protocol_events,
1034 	.supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION,
1035 };
1036 
1037 DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(powercap, scmi_powercap)
1038