1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * System Control and Management Interface (SCMI) Voltage Protocol
4  *
5  * Copyright (C) 2020-2022 ARM Ltd.
6  */
7 
8 #include <linux/module.h>
9 #include <linux/scmi_protocol.h>
10 
11 #include "protocols.h"
12 
13 #define VOLTAGE_DOMS_NUM_MASK		GENMASK(15, 0)
14 #define REMAINING_LEVELS_MASK		GENMASK(31, 16)
15 #define RETURNED_LEVELS_MASK		GENMASK(11, 0)
16 
17 enum scmi_voltage_protocol_cmd {
18 	VOLTAGE_DOMAIN_ATTRIBUTES = 0x3,
19 	VOLTAGE_DESCRIBE_LEVELS = 0x4,
20 	VOLTAGE_CONFIG_SET = 0x5,
21 	VOLTAGE_CONFIG_GET = 0x6,
22 	VOLTAGE_LEVEL_SET = 0x7,
23 	VOLTAGE_LEVEL_GET = 0x8,
24 	VOLTAGE_DOMAIN_NAME_GET = 0x09,
25 };
26 
27 #define NUM_VOLTAGE_DOMAINS(x)	((u16)(FIELD_GET(VOLTAGE_DOMS_NUM_MASK, (x))))
28 
29 struct scmi_msg_resp_domain_attributes {
30 	__le32 attr;
31 #define SUPPORTS_ASYNC_LEVEL_SET(x)	((x) & BIT(31))
32 #define SUPPORTS_EXTENDED_NAMES(x)	((x) & BIT(30))
33 	u8 name[SCMI_SHORT_NAME_MAX_SIZE];
34 };
35 
36 struct scmi_msg_cmd_describe_levels {
37 	__le32 domain_id;
38 	__le32 level_index;
39 };
40 
41 struct scmi_msg_resp_describe_levels {
42 	__le32 flags;
43 #define NUM_REMAINING_LEVELS(f)	((u16)(FIELD_GET(REMAINING_LEVELS_MASK, (f))))
44 #define NUM_RETURNED_LEVELS(f)	((u16)(FIELD_GET(RETURNED_LEVELS_MASK, (f))))
45 #define SUPPORTS_SEGMENTED_LEVELS(f)	((f) & BIT(12))
46 	__le32 voltage[];
47 };
48 
49 struct scmi_msg_cmd_config_set {
50 	__le32 domain_id;
51 	__le32 config;
52 };
53 
54 struct scmi_msg_cmd_level_set {
55 	__le32 domain_id;
56 	__le32 flags;
57 	__le32 voltage_level;
58 };
59 
60 struct scmi_resp_voltage_level_set_complete {
61 	__le32 domain_id;
62 	__le32 voltage_level;
63 };
64 
65 struct voltage_info {
66 	unsigned int version;
67 	unsigned int num_domains;
68 	struct scmi_voltage_info *domains;
69 };
70 
71 static int scmi_protocol_attributes_get(const struct scmi_protocol_handle *ph,
72 					struct voltage_info *vinfo)
73 {
74 	int ret;
75 	struct scmi_xfer *t;
76 
77 	ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, 0,
78 				      sizeof(__le32), &t);
79 	if (ret)
80 		return ret;
81 
82 	ret = ph->xops->do_xfer(ph, t);
83 	if (!ret)
84 		vinfo->num_domains =
85 			NUM_VOLTAGE_DOMAINS(get_unaligned_le32(t->rx.buf));
86 
87 	ph->xops->xfer_put(ph, t);
88 	return ret;
89 }
90 
91 static int scmi_init_voltage_levels(struct device *dev,
92 				    struct scmi_voltage_info *v,
93 				    u32 num_returned, u32 num_remaining,
94 				    bool segmented)
95 {
96 	u32 num_levels;
97 
98 	num_levels = num_returned + num_remaining;
99 	/*
100 	 * segmented levels entries are represented by a single triplet
101 	 * returned all in one go.
102 	 */
103 	if (!num_levels ||
104 	    (segmented && (num_remaining || num_returned != 3))) {
105 		dev_err(dev,
106 			"Invalid level descriptor(%d/%d/%d) for voltage dom %d\n",
107 			num_levels, num_returned, num_remaining, v->id);
108 		return -EINVAL;
109 	}
110 
111 	v->levels_uv = devm_kcalloc(dev, num_levels, sizeof(u32), GFP_KERNEL);
112 	if (!v->levels_uv)
113 		return -ENOMEM;
114 
115 	v->num_levels = num_levels;
116 	v->segmented = segmented;
117 
118 	return 0;
119 }
120 
121 struct scmi_volt_ipriv {
122 	struct device *dev;
123 	struct scmi_voltage_info *v;
124 };
125 
126 static void iter_volt_levels_prepare_message(void *message,
127 					     unsigned int desc_index,
128 					     const void *priv)
129 {
130 	struct scmi_msg_cmd_describe_levels *msg = message;
131 	const struct scmi_volt_ipriv *p = priv;
132 
133 	msg->domain_id = cpu_to_le32(p->v->id);
134 	msg->level_index = cpu_to_le32(desc_index);
135 }
136 
137 static int iter_volt_levels_update_state(struct scmi_iterator_state *st,
138 					 const void *response, void *priv)
139 {
140 	int ret = 0;
141 	u32 flags;
142 	const struct scmi_msg_resp_describe_levels *r = response;
143 	struct scmi_volt_ipriv *p = priv;
144 
145 	flags = le32_to_cpu(r->flags);
146 	st->num_returned = NUM_RETURNED_LEVELS(flags);
147 	st->num_remaining = NUM_REMAINING_LEVELS(flags);
148 
149 	/* Allocate space for num_levels if not already done */
150 	if (!p->v->num_levels) {
151 		ret = scmi_init_voltage_levels(p->dev, p->v, st->num_returned,
152 					       st->num_remaining,
153 					      SUPPORTS_SEGMENTED_LEVELS(flags));
154 		if (!ret)
155 			st->max_resources = p->v->num_levels;
156 	}
157 
158 	return ret;
159 }
160 
161 static int
162 iter_volt_levels_process_response(const struct scmi_protocol_handle *ph,
163 				  const void *response,
164 				  struct scmi_iterator_state *st, void *priv)
165 {
166 	s32 val;
167 	const struct scmi_msg_resp_describe_levels *r = response;
168 	struct scmi_volt_ipriv *p = priv;
169 
170 	val = (s32)le32_to_cpu(r->voltage[st->loop_idx]);
171 	p->v->levels_uv[st->desc_index + st->loop_idx] = val;
172 	if (val < 0)
173 		p->v->negative_volts_allowed = true;
174 
175 	return 0;
176 }
177 
178 static int scmi_voltage_levels_get(const struct scmi_protocol_handle *ph,
179 				   struct scmi_voltage_info *v)
180 {
181 	int ret;
182 	void *iter;
183 	struct scmi_iterator_ops ops = {
184 		.prepare_message = iter_volt_levels_prepare_message,
185 		.update_state = iter_volt_levels_update_state,
186 		.process_response = iter_volt_levels_process_response,
187 	};
188 	struct scmi_volt_ipriv vpriv = {
189 		.dev = ph->dev,
190 		.v = v,
191 	};
192 
193 	iter = ph->hops->iter_response_init(ph, &ops, v->num_levels,
194 					    VOLTAGE_DESCRIBE_LEVELS,
195 					    sizeof(struct scmi_msg_cmd_describe_levels),
196 					    &vpriv);
197 	if (IS_ERR(iter))
198 		return PTR_ERR(iter);
199 
200 	ret = ph->hops->iter_response_run(iter);
201 	if (ret) {
202 		v->num_levels = 0;
203 		devm_kfree(ph->dev, v->levels_uv);
204 	}
205 
206 	return ret;
207 }
208 
209 static int scmi_voltage_descriptors_get(const struct scmi_protocol_handle *ph,
210 					struct voltage_info *vinfo)
211 {
212 	int ret, dom;
213 	struct scmi_xfer *td;
214 	struct scmi_msg_resp_domain_attributes *resp_dom;
215 
216 	ret = ph->xops->xfer_get_init(ph, VOLTAGE_DOMAIN_ATTRIBUTES,
217 				      sizeof(__le32), sizeof(*resp_dom), &td);
218 	if (ret)
219 		return ret;
220 	resp_dom = td->rx.buf;
221 
222 	for (dom = 0; dom < vinfo->num_domains; dom++) {
223 		u32 attributes;
224 		struct scmi_voltage_info *v;
225 
226 		/* Retrieve domain attributes at first ... */
227 		put_unaligned_le32(dom, td->tx.buf);
228 		/* Skip domain on comms error */
229 		if (ph->xops->do_xfer(ph, td))
230 			continue;
231 
232 		v = vinfo->domains + dom;
233 		v->id = dom;
234 		attributes = le32_to_cpu(resp_dom->attr);
235 		strscpy(v->name, resp_dom->name, SCMI_SHORT_NAME_MAX_SIZE);
236 
237 		/*
238 		 * If supported overwrite short name with the extended one;
239 		 * on error just carry on and use already provided short name.
240 		 */
241 		if (PROTOCOL_REV_MAJOR(vinfo->version) >= 0x2) {
242 			if (SUPPORTS_EXTENDED_NAMES(attributes))
243 				ph->hops->extended_name_get(ph,
244 							VOLTAGE_DOMAIN_NAME_GET,
245 							v->id, v->name,
246 							SCMI_MAX_STR_SIZE);
247 			if (SUPPORTS_ASYNC_LEVEL_SET(attributes))
248 				v->async_level_set = true;
249 		}
250 
251 		/* Skip invalid voltage descriptors */
252 		scmi_voltage_levels_get(ph, v);
253 	}
254 
255 	ph->xops->xfer_put(ph, td);
256 
257 	return ret;
258 }
259 
260 static int __scmi_voltage_get_u32(const struct scmi_protocol_handle *ph,
261 				  u8 cmd_id, u32 domain_id, u32 *value)
262 {
263 	int ret;
264 	struct scmi_xfer *t;
265 	struct voltage_info *vinfo = ph->get_priv(ph);
266 
267 	if (domain_id >= vinfo->num_domains)
268 		return -EINVAL;
269 
270 	ret = ph->xops->xfer_get_init(ph, cmd_id, sizeof(__le32), 0, &t);
271 	if (ret)
272 		return ret;
273 
274 	put_unaligned_le32(domain_id, t->tx.buf);
275 	ret = ph->xops->do_xfer(ph, t);
276 	if (!ret)
277 		*value = get_unaligned_le32(t->rx.buf);
278 
279 	ph->xops->xfer_put(ph, t);
280 	return ret;
281 }
282 
283 static int scmi_voltage_config_set(const struct scmi_protocol_handle *ph,
284 				   u32 domain_id, u32 config)
285 {
286 	int ret;
287 	struct scmi_xfer *t;
288 	struct voltage_info *vinfo = ph->get_priv(ph);
289 	struct scmi_msg_cmd_config_set *cmd;
290 
291 	if (domain_id >= vinfo->num_domains)
292 		return -EINVAL;
293 
294 	ret = ph->xops->xfer_get_init(ph, VOLTAGE_CONFIG_SET,
295 				     sizeof(*cmd), 0, &t);
296 	if (ret)
297 		return ret;
298 
299 	cmd = t->tx.buf;
300 	cmd->domain_id = cpu_to_le32(domain_id);
301 	cmd->config = cpu_to_le32(config & GENMASK(3, 0));
302 
303 	ret = ph->xops->do_xfer(ph, t);
304 
305 	ph->xops->xfer_put(ph, t);
306 	return ret;
307 }
308 
309 static int scmi_voltage_config_get(const struct scmi_protocol_handle *ph,
310 				   u32 domain_id, u32 *config)
311 {
312 	return __scmi_voltage_get_u32(ph, VOLTAGE_CONFIG_GET,
313 				      domain_id, config);
314 }
315 
316 static int scmi_voltage_level_set(const struct scmi_protocol_handle *ph,
317 				  u32 domain_id,
318 				  enum scmi_voltage_level_mode mode,
319 				  s32 volt_uV)
320 {
321 	int ret;
322 	struct scmi_xfer *t;
323 	struct voltage_info *vinfo = ph->get_priv(ph);
324 	struct scmi_msg_cmd_level_set *cmd;
325 	struct scmi_voltage_info *v;
326 
327 	if (domain_id >= vinfo->num_domains)
328 		return -EINVAL;
329 
330 	ret = ph->xops->xfer_get_init(ph, VOLTAGE_LEVEL_SET,
331 				      sizeof(*cmd), 0, &t);
332 	if (ret)
333 		return ret;
334 
335 	v = vinfo->domains + domain_id;
336 
337 	cmd = t->tx.buf;
338 	cmd->domain_id = cpu_to_le32(domain_id);
339 	cmd->voltage_level = cpu_to_le32(volt_uV);
340 
341 	if (!v->async_level_set || mode != SCMI_VOLTAGE_LEVEL_SET_AUTO) {
342 		cmd->flags = cpu_to_le32(0x0);
343 		ret = ph->xops->do_xfer(ph, t);
344 	} else {
345 		cmd->flags = cpu_to_le32(0x1);
346 		ret = ph->xops->do_xfer_with_response(ph, t);
347 		if (!ret) {
348 			struct scmi_resp_voltage_level_set_complete *resp;
349 
350 			resp = t->rx.buf;
351 			if (le32_to_cpu(resp->domain_id) == domain_id)
352 				dev_dbg(ph->dev,
353 					"Voltage domain %d set async to %d\n",
354 					v->id,
355 					le32_to_cpu(resp->voltage_level));
356 			else
357 				ret = -EPROTO;
358 		}
359 	}
360 
361 	ph->xops->xfer_put(ph, t);
362 	return ret;
363 }
364 
365 static int scmi_voltage_level_get(const struct scmi_protocol_handle *ph,
366 				  u32 domain_id, s32 *volt_uV)
367 {
368 	return __scmi_voltage_get_u32(ph, VOLTAGE_LEVEL_GET,
369 				      domain_id, (u32 *)volt_uV);
370 }
371 
372 static const struct scmi_voltage_info * __must_check
373 scmi_voltage_info_get(const struct scmi_protocol_handle *ph, u32 domain_id)
374 {
375 	struct voltage_info *vinfo = ph->get_priv(ph);
376 
377 	if (domain_id >= vinfo->num_domains ||
378 	    !vinfo->domains[domain_id].num_levels)
379 		return NULL;
380 
381 	return vinfo->domains + domain_id;
382 }
383 
384 static int scmi_voltage_domains_num_get(const struct scmi_protocol_handle *ph)
385 {
386 	struct voltage_info *vinfo = ph->get_priv(ph);
387 
388 	return vinfo->num_domains;
389 }
390 
391 static struct scmi_voltage_proto_ops voltage_proto_ops = {
392 	.num_domains_get = scmi_voltage_domains_num_get,
393 	.info_get = scmi_voltage_info_get,
394 	.config_set = scmi_voltage_config_set,
395 	.config_get = scmi_voltage_config_get,
396 	.level_set = scmi_voltage_level_set,
397 	.level_get = scmi_voltage_level_get,
398 };
399 
400 static int scmi_voltage_protocol_init(const struct scmi_protocol_handle *ph)
401 {
402 	int ret;
403 	u32 version;
404 	struct voltage_info *vinfo;
405 
406 	ret = ph->xops->version_get(ph, &version);
407 	if (ret)
408 		return ret;
409 
410 	dev_dbg(ph->dev, "Voltage Version %d.%d\n",
411 		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
412 
413 	vinfo = devm_kzalloc(ph->dev, sizeof(*vinfo), GFP_KERNEL);
414 	if (!vinfo)
415 		return -ENOMEM;
416 	vinfo->version = version;
417 
418 	ret = scmi_protocol_attributes_get(ph, vinfo);
419 	if (ret)
420 		return ret;
421 
422 	if (vinfo->num_domains) {
423 		vinfo->domains = devm_kcalloc(ph->dev, vinfo->num_domains,
424 					      sizeof(*vinfo->domains),
425 					      GFP_KERNEL);
426 		if (!vinfo->domains)
427 			return -ENOMEM;
428 		ret = scmi_voltage_descriptors_get(ph, vinfo);
429 		if (ret)
430 			return ret;
431 	} else {
432 		dev_warn(ph->dev, "No Voltage domains found.\n");
433 	}
434 
435 	return ph->set_priv(ph, vinfo);
436 }
437 
438 static const struct scmi_protocol scmi_voltage = {
439 	.id = SCMI_PROTOCOL_VOLTAGE,
440 	.owner = THIS_MODULE,
441 	.instance_init = &scmi_voltage_protocol_init,
442 	.ops = &voltage_proto_ops,
443 };
444 
445 DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(voltage, scmi_voltage)
446