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