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