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