1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * System Control and Management Interface (SCMI) Voltage Protocol
4  *
5  * Copyright (C) 2020 ARM Ltd.
6  */
7 
8 #include <linux/scmi_protocol.h>
9 
10 #include "common.h"
11 
12 #define VOLTAGE_DOMS_NUM_MASK		GENMASK(15, 0)
13 #define REMAINING_LEVELS_MASK		GENMASK(31, 16)
14 #define RETURNED_LEVELS_MASK		GENMASK(11, 0)
15 
16 enum scmi_voltage_protocol_cmd {
17 	VOLTAGE_DOMAIN_ATTRIBUTES = 0x3,
18 	VOLTAGE_DESCRIBE_LEVELS = 0x4,
19 	VOLTAGE_CONFIG_SET = 0x5,
20 	VOLTAGE_CONFIG_GET = 0x6,
21 	VOLTAGE_LEVEL_SET = 0x7,
22 	VOLTAGE_LEVEL_GET = 0x8,
23 };
24 
25 #define NUM_VOLTAGE_DOMAINS(x)	((u16)(FIELD_GET(VOLTAGE_DOMS_NUM_MASK, (x))))
26 
27 struct scmi_msg_resp_domain_attributes {
28 	__le32 attr;
29 	u8 name[SCMI_MAX_STR_SIZE];
30 };
31 
32 struct scmi_msg_cmd_describe_levels {
33 	__le32 domain_id;
34 	__le32 level_index;
35 };
36 
37 struct scmi_msg_resp_describe_levels {
38 	__le32 flags;
39 #define NUM_REMAINING_LEVELS(f)	((u16)(FIELD_GET(REMAINING_LEVELS_MASK, (f))))
40 #define NUM_RETURNED_LEVELS(f)	((u16)(FIELD_GET(RETURNED_LEVELS_MASK, (f))))
41 #define SUPPORTS_SEGMENTED_LEVELS(f)	((f) & BIT(12))
42 	__le32 voltage[];
43 };
44 
45 struct scmi_msg_cmd_config_set {
46 	__le32 domain_id;
47 	__le32 config;
48 };
49 
50 struct scmi_msg_cmd_level_set {
51 	__le32 domain_id;
52 	__le32 flags;
53 	__le32 voltage_level;
54 };
55 
56 struct voltage_info {
57 	unsigned int version;
58 	unsigned int num_domains;
59 	struct scmi_voltage_info *domains;
60 };
61 
62 static int scmi_protocol_attributes_get(const struct scmi_handle *handle,
63 					struct voltage_info *vinfo)
64 {
65 	int ret;
66 	struct scmi_xfer *t;
67 
68 	ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES,
69 				 SCMI_PROTOCOL_VOLTAGE, 0, sizeof(__le32), &t);
70 	if (ret)
71 		return ret;
72 
73 	ret = scmi_do_xfer(handle, t);
74 	if (!ret)
75 		vinfo->num_domains =
76 			NUM_VOLTAGE_DOMAINS(get_unaligned_le32(t->rx.buf));
77 
78 	scmi_xfer_put(handle, t);
79 	return ret;
80 }
81 
82 static int scmi_init_voltage_levels(struct device *dev,
83 				    struct scmi_voltage_info *v,
84 				    u32 num_returned, u32 num_remaining,
85 				    bool segmented)
86 {
87 	u32 num_levels;
88 
89 	num_levels = num_returned + num_remaining;
90 	/*
91 	 * segmented levels entries are represented by a single triplet
92 	 * returned all in one go.
93 	 */
94 	if (!num_levels ||
95 	    (segmented && (num_remaining || num_returned != 3))) {
96 		dev_err(dev,
97 			"Invalid level descriptor(%d/%d/%d) for voltage dom %d\n",
98 			num_levels, num_returned, num_remaining, v->id);
99 		return -EINVAL;
100 	}
101 
102 	v->levels_uv = devm_kcalloc(dev, num_levels, sizeof(u32), GFP_KERNEL);
103 	if (!v->levels_uv)
104 		return -ENOMEM;
105 
106 	v->num_levels = num_levels;
107 	v->segmented = segmented;
108 
109 	return 0;
110 }
111 
112 static int scmi_voltage_descriptors_get(const struct scmi_handle *handle,
113 					struct voltage_info *vinfo)
114 {
115 	int ret, dom;
116 	struct scmi_xfer *td, *tl;
117 	struct device *dev = handle->dev;
118 	struct scmi_msg_resp_domain_attributes *resp_dom;
119 	struct scmi_msg_resp_describe_levels *resp_levels;
120 
121 	ret = scmi_xfer_get_init(handle, VOLTAGE_DOMAIN_ATTRIBUTES,
122 				 SCMI_PROTOCOL_VOLTAGE, sizeof(__le32),
123 				 sizeof(*resp_dom), &td);
124 	if (ret)
125 		return ret;
126 	resp_dom = td->rx.buf;
127 
128 	ret = scmi_xfer_get_init(handle, VOLTAGE_DESCRIBE_LEVELS,
129 				 SCMI_PROTOCOL_VOLTAGE, sizeof(__le64), 0, &tl);
130 	if (ret)
131 		goto outd;
132 	resp_levels = tl->rx.buf;
133 
134 	for (dom = 0; dom < vinfo->num_domains; dom++) {
135 		u32 desc_index = 0;
136 		u16 num_returned = 0, num_remaining = 0;
137 		struct scmi_msg_cmd_describe_levels *cmd;
138 		struct scmi_voltage_info *v;
139 
140 		/* Retrieve domain attributes at first ... */
141 		put_unaligned_le32(dom, td->tx.buf);
142 		ret = scmi_do_xfer(handle, td);
143 		/* Skip domain on comms error */
144 		if (ret)
145 			continue;
146 
147 		v = vinfo->domains + dom;
148 		v->id = dom;
149 		v->attributes = le32_to_cpu(resp_dom->attr);
150 		strlcpy(v->name, resp_dom->name, SCMI_MAX_STR_SIZE);
151 
152 		cmd = tl->tx.buf;
153 		/* ...then retrieve domain levels descriptions */
154 		do {
155 			u32 flags;
156 			int cnt;
157 
158 			cmd->domain_id = cpu_to_le32(v->id);
159 			cmd->level_index = desc_index;
160 			ret = scmi_do_xfer(handle, tl);
161 			if (ret)
162 				break;
163 
164 			flags = le32_to_cpu(resp_levels->flags);
165 			num_returned = NUM_RETURNED_LEVELS(flags);
166 			num_remaining = NUM_REMAINING_LEVELS(flags);
167 
168 			/* Allocate space for num_levels if not already done */
169 			if (!v->num_levels) {
170 				ret = scmi_init_voltage_levels(dev, v,
171 							       num_returned,
172 							       num_remaining,
173 					      SUPPORTS_SEGMENTED_LEVELS(flags));
174 				if (ret)
175 					break;
176 			}
177 
178 			if (desc_index + num_returned > v->num_levels) {
179 				dev_err(handle->dev,
180 					"No. of voltage levels can't exceed %d\n",
181 					v->num_levels);
182 				ret = -EINVAL;
183 				break;
184 			}
185 
186 			for (cnt = 0; cnt < num_returned; cnt++) {
187 				s32 val;
188 
189 				val =
190 				    (s32)le32_to_cpu(resp_levels->voltage[cnt]);
191 				v->levels_uv[desc_index + cnt] = val;
192 				if (val < 0)
193 					v->negative_volts_allowed = true;
194 			}
195 
196 			desc_index += num_returned;
197 
198 			scmi_reset_rx_to_maxsz(handle, tl);
199 			/* check both to avoid infinite loop due to buggy fw */
200 		} while (num_returned && num_remaining);
201 
202 		if (ret) {
203 			v->num_levels = 0;
204 			devm_kfree(dev, v->levels_uv);
205 		}
206 
207 		scmi_reset_rx_to_maxsz(handle, td);
208 	}
209 
210 	scmi_xfer_put(handle, tl);
211 outd:
212 	scmi_xfer_put(handle, td);
213 
214 	return ret;
215 }
216 
217 static int __scmi_voltage_get_u32(const struct scmi_handle *handle,
218 				  u8 cmd_id, u32 domain_id, u32 *value)
219 {
220 	int ret;
221 	struct scmi_xfer *t;
222 	struct voltage_info *vinfo = handle->voltage_priv;
223 
224 	if (domain_id >= vinfo->num_domains)
225 		return -EINVAL;
226 
227 	ret = scmi_xfer_get_init(handle, cmd_id,
228 				 SCMI_PROTOCOL_VOLTAGE,
229 				 sizeof(__le32), 0, &t);
230 	if (ret)
231 		return ret;
232 
233 	put_unaligned_le32(domain_id, t->tx.buf);
234 	ret = scmi_do_xfer(handle, t);
235 	if (!ret)
236 		*value = get_unaligned_le32(t->rx.buf);
237 
238 	scmi_xfer_put(handle, t);
239 	return ret;
240 }
241 
242 static int scmi_voltage_config_set(const struct scmi_handle *handle,
243 				   u32 domain_id, u32 config)
244 {
245 	int ret;
246 	struct scmi_xfer *t;
247 	struct voltage_info *vinfo = handle->voltage_priv;
248 	struct scmi_msg_cmd_config_set *cmd;
249 
250 	if (domain_id >= vinfo->num_domains)
251 		return -EINVAL;
252 
253 	ret = scmi_xfer_get_init(handle, VOLTAGE_CONFIG_SET,
254 				 SCMI_PROTOCOL_VOLTAGE,
255 				 sizeof(*cmd), 0, &t);
256 	if (ret)
257 		return ret;
258 
259 	cmd = t->tx.buf;
260 	cmd->domain_id = cpu_to_le32(domain_id);
261 	cmd->config = cpu_to_le32(config & GENMASK(3, 0));
262 
263 	ret = scmi_do_xfer(handle, t);
264 
265 	scmi_xfer_put(handle, t);
266 	return ret;
267 }
268 
269 static int scmi_voltage_config_get(const struct scmi_handle *handle,
270 				   u32 domain_id, u32 *config)
271 {
272 	return __scmi_voltage_get_u32(handle, VOLTAGE_CONFIG_GET,
273 				      domain_id, config);
274 }
275 
276 static int scmi_voltage_level_set(const struct scmi_handle *handle,
277 				  u32 domain_id, u32 flags, s32 volt_uV)
278 {
279 	int ret;
280 	struct scmi_xfer *t;
281 	struct voltage_info *vinfo = handle->voltage_priv;
282 	struct scmi_msg_cmd_level_set *cmd;
283 
284 	if (domain_id >= vinfo->num_domains)
285 		return -EINVAL;
286 
287 	ret = scmi_xfer_get_init(handle, VOLTAGE_LEVEL_SET,
288 				 SCMI_PROTOCOL_VOLTAGE,
289 				 sizeof(*cmd), 0, &t);
290 	if (ret)
291 		return ret;
292 
293 	cmd = t->tx.buf;
294 	cmd->domain_id = cpu_to_le32(domain_id);
295 	cmd->flags = cpu_to_le32(flags);
296 	cmd->voltage_level = cpu_to_le32(volt_uV);
297 
298 	ret = scmi_do_xfer(handle, t);
299 
300 	scmi_xfer_put(handle, t);
301 	return ret;
302 }
303 
304 static int scmi_voltage_level_get(const struct scmi_handle *handle,
305 				  u32 domain_id, s32 *volt_uV)
306 {
307 	return __scmi_voltage_get_u32(handle, VOLTAGE_LEVEL_GET,
308 				      domain_id, (u32 *)volt_uV);
309 }
310 
311 static const struct scmi_voltage_info * __must_check
312 scmi_voltage_info_get(const struct scmi_handle *handle, u32 domain_id)
313 {
314 	struct voltage_info *vinfo = handle->voltage_priv;
315 
316 	if (domain_id >= vinfo->num_domains ||
317 	    !vinfo->domains[domain_id].num_levels)
318 		return NULL;
319 
320 	return vinfo->domains + domain_id;
321 }
322 
323 static int scmi_voltage_domains_num_get(const struct scmi_handle *handle)
324 {
325 	struct voltage_info *vinfo = handle->voltage_priv;
326 
327 	return vinfo->num_domains;
328 }
329 
330 static struct scmi_voltage_ops voltage_ops = {
331 	.num_domains_get = scmi_voltage_domains_num_get,
332 	.info_get = scmi_voltage_info_get,
333 	.config_set = scmi_voltage_config_set,
334 	.config_get = scmi_voltage_config_get,
335 	.level_set = scmi_voltage_level_set,
336 	.level_get = scmi_voltage_level_get,
337 };
338 
339 static int scmi_voltage_protocol_init(struct scmi_handle *handle)
340 {
341 	int ret;
342 	u32 version;
343 	struct voltage_info *vinfo;
344 
345 	ret = scmi_version_get(handle, SCMI_PROTOCOL_VOLTAGE, &version);
346 	if (ret)
347 		return ret;
348 
349 	dev_dbg(handle->dev, "Voltage Version %d.%d\n",
350 		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
351 
352 	vinfo = devm_kzalloc(handle->dev, sizeof(*vinfo), GFP_KERNEL);
353 	if (!vinfo)
354 		return -ENOMEM;
355 	vinfo->version = version;
356 
357 	ret = scmi_protocol_attributes_get(handle, vinfo);
358 	if (ret)
359 		return ret;
360 
361 	if (vinfo->num_domains) {
362 		vinfo->domains = devm_kcalloc(handle->dev, vinfo->num_domains,
363 					      sizeof(*vinfo->domains),
364 					      GFP_KERNEL);
365 		if (!vinfo->domains)
366 			return -ENOMEM;
367 		ret = scmi_voltage_descriptors_get(handle, vinfo);
368 		if (ret)
369 			return ret;
370 	} else {
371 		dev_warn(handle->dev, "No Voltage domains found.\n");
372 	}
373 
374 	handle->voltage_ops = &voltage_ops;
375 	handle->voltage_priv = vinfo;
376 
377 	return 0;
378 }
379 
380 DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_VOLTAGE, voltage)
381