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