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