xref: /linux/drivers/firmware/arm_scmi/pinctrl.c (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * System Control and Management Interface (SCMI) Pinctrl Protocol
4  *
5  * Copyright (C) 2024 EPAM
6  * Copyright 2024 NXP
7  */
8 
9 #include <asm/byteorder.h>
10 #include <linux/bits.h>
11 #include <linux/bitfield.h>
12 #include <linux/device.h>
13 #include <linux/module.h>
14 #include <linux/scmi_protocol.h>
15 #include <linux/slab.h>
16 #include <linux/string.h>
17 #include <linux/types.h>
18 
19 #include "common.h"
20 #include "protocols.h"
21 
22 /* Updated only after ALL the mandatory features for that version are merged */
23 #define SCMI_PROTOCOL_SUPPORTED_VERSION		0x10000
24 
25 #define GET_GROUPS_NR(x)	le32_get_bits((x), GENMASK(31, 16))
26 #define GET_PINS_NR(x)		le32_get_bits((x), GENMASK(15, 0))
27 #define GET_FUNCTIONS_NR(x)	le32_get_bits((x), GENMASK(15, 0))
28 
29 #define EXT_NAME_FLAG(x)	le32_get_bits((x), BIT(31))
30 #define NUM_ELEMS(x)		le32_get_bits((x), GENMASK(15, 0))
31 
32 #define REMAINING(x)		le32_get_bits((x), GENMASK(31, 16))
33 #define RETURNED(x)		le32_get_bits((x), GENMASK(11, 0))
34 
35 #define CONFIG_FLAG_MASK	GENMASK(19, 18)
36 #define SELECTOR_MASK		GENMASK(17, 16)
37 #define SKIP_CONFIGS_MASK	GENMASK(15, 8)
38 #define CONFIG_TYPE_MASK	GENMASK(7, 0)
39 
40 enum scmi_pinctrl_protocol_cmd {
41 	PINCTRL_ATTRIBUTES = 0x3,
42 	PINCTRL_LIST_ASSOCIATIONS = 0x4,
43 	PINCTRL_SETTINGS_GET = 0x5,
44 	PINCTRL_SETTINGS_CONFIGURE = 0x6,
45 	PINCTRL_REQUEST = 0x7,
46 	PINCTRL_RELEASE = 0x8,
47 	PINCTRL_NAME_GET = 0x9,
48 	PINCTRL_SET_PERMISSIONS = 0xa,
49 };
50 
51 struct scmi_msg_settings_conf {
52 	__le32 identifier;
53 	__le32 function_id;
54 	__le32 attributes;
55 	__le32 configs[];
56 };
57 
58 struct scmi_msg_settings_get {
59 	__le32 identifier;
60 	__le32 attributes;
61 };
62 
63 struct scmi_resp_settings_get {
64 	__le32 function_selected;
65 	__le32 num_configs;
66 	__le32 configs[];
67 };
68 
69 struct scmi_msg_pinctrl_protocol_attributes {
70 	__le32 attributes_low;
71 	__le32 attributes_high;
72 };
73 
74 struct scmi_msg_pinctrl_attributes {
75 	__le32 identifier;
76 	__le32 flags;
77 };
78 
79 struct scmi_resp_pinctrl_attributes {
80 	__le32 attributes;
81 	u8 name[SCMI_SHORT_NAME_MAX_SIZE];
82 };
83 
84 struct scmi_msg_pinctrl_list_assoc {
85 	__le32 identifier;
86 	__le32 flags;
87 	__le32 index;
88 };
89 
90 struct scmi_resp_pinctrl_list_assoc {
91 	__le32 flags;
92 	__le16 array[];
93 };
94 
95 struct scmi_msg_request {
96 	__le32 identifier;
97 	__le32 flags;
98 };
99 
100 struct scmi_group_info {
101 	char name[SCMI_MAX_STR_SIZE];
102 	bool present;
103 	u32 *group_pins;
104 	u32 nr_pins;
105 };
106 
107 struct scmi_function_info {
108 	char name[SCMI_MAX_STR_SIZE];
109 	bool present;
110 	u32 *groups;
111 	u32 nr_groups;
112 };
113 
114 struct scmi_pin_info {
115 	char name[SCMI_MAX_STR_SIZE];
116 	bool present;
117 };
118 
119 struct scmi_pinctrl_info {
120 	u32 version;
121 	int nr_groups;
122 	int nr_functions;
123 	int nr_pins;
124 	struct scmi_group_info *groups;
125 	struct scmi_function_info *functions;
126 	struct scmi_pin_info *pins;
127 };
128 
scmi_pinctrl_attributes_get(const struct scmi_protocol_handle * ph,struct scmi_pinctrl_info * pi)129 static int scmi_pinctrl_attributes_get(const struct scmi_protocol_handle *ph,
130 				       struct scmi_pinctrl_info *pi)
131 {
132 	int ret;
133 	struct scmi_xfer *t;
134 	struct scmi_msg_pinctrl_protocol_attributes *attr;
135 
136 	ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, 0, sizeof(*attr), &t);
137 	if (ret)
138 		return ret;
139 
140 	attr = t->rx.buf;
141 
142 	ret = ph->xops->do_xfer(ph, t);
143 	if (!ret) {
144 		pi->nr_functions = GET_FUNCTIONS_NR(attr->attributes_high);
145 		pi->nr_groups = GET_GROUPS_NR(attr->attributes_low);
146 		pi->nr_pins = GET_PINS_NR(attr->attributes_low);
147 		if (pi->nr_pins == 0) {
148 			dev_warn(ph->dev, "returned zero pins\n");
149 			ret = -EINVAL;
150 		}
151 	}
152 
153 	ph->xops->xfer_put(ph, t);
154 	return ret;
155 }
156 
scmi_pinctrl_count_get(const struct scmi_protocol_handle * ph,enum scmi_pinctrl_selector_type type)157 static int scmi_pinctrl_count_get(const struct scmi_protocol_handle *ph,
158 				  enum scmi_pinctrl_selector_type type)
159 {
160 	struct scmi_pinctrl_info *pi = ph->get_priv(ph);
161 
162 	switch (type) {
163 	case PIN_TYPE:
164 		return pi->nr_pins;
165 	case GROUP_TYPE:
166 		return pi->nr_groups;
167 	case FUNCTION_TYPE:
168 		return pi->nr_functions;
169 	default:
170 		return -EINVAL;
171 	}
172 }
173 
scmi_pinctrl_validate_id(const struct scmi_protocol_handle * ph,u32 selector,enum scmi_pinctrl_selector_type type)174 static int scmi_pinctrl_validate_id(const struct scmi_protocol_handle *ph,
175 				    u32 selector,
176 				    enum scmi_pinctrl_selector_type type)
177 {
178 	int value;
179 
180 	value = scmi_pinctrl_count_get(ph, type);
181 	if (value < 0)
182 		return value;
183 
184 	if (selector >= value || value == 0)
185 		return -EINVAL;
186 
187 	return 0;
188 }
189 
scmi_pinctrl_attributes(const struct scmi_protocol_handle * ph,enum scmi_pinctrl_selector_type type,u32 selector,char * name,u32 * n_elems)190 static int scmi_pinctrl_attributes(const struct scmi_protocol_handle *ph,
191 				   enum scmi_pinctrl_selector_type type,
192 				   u32 selector, char *name,
193 				   u32 *n_elems)
194 {
195 	int ret;
196 	struct scmi_xfer *t;
197 	struct scmi_msg_pinctrl_attributes *tx;
198 	struct scmi_resp_pinctrl_attributes *rx;
199 	bool ext_name_flag;
200 
201 	if (!name)
202 		return -EINVAL;
203 
204 	ret = scmi_pinctrl_validate_id(ph, selector, type);
205 	if (ret)
206 		return ret;
207 
208 	ret = ph->xops->xfer_get_init(ph, PINCTRL_ATTRIBUTES, sizeof(*tx),
209 				      sizeof(*rx), &t);
210 	if (ret)
211 		return ret;
212 
213 	tx = t->tx.buf;
214 	rx = t->rx.buf;
215 	tx->identifier = cpu_to_le32(selector);
216 	tx->flags = cpu_to_le32(type);
217 
218 	ret = ph->xops->do_xfer(ph, t);
219 	if (!ret) {
220 		if (n_elems)
221 			*n_elems = NUM_ELEMS(rx->attributes);
222 
223 		strscpy(name, rx->name, SCMI_SHORT_NAME_MAX_SIZE);
224 
225 		ext_name_flag = !!EXT_NAME_FLAG(rx->attributes);
226 	}
227 
228 	ph->xops->xfer_put(ph, t);
229 
230 	if (ret)
231 		return ret;
232 	/*
233 	 * If supported overwrite short name with the extended one;
234 	 * on error just carry on and use already provided short name.
235 	 */
236 	if (ext_name_flag)
237 		ret = ph->hops->extended_name_get(ph, PINCTRL_NAME_GET,
238 						  selector, (u32 *)&type, name,
239 						  SCMI_MAX_STR_SIZE);
240 	return ret;
241 }
242 
243 struct scmi_pinctrl_ipriv {
244 	u32 selector;
245 	enum scmi_pinctrl_selector_type type;
246 	u32 *array;
247 };
248 
iter_pinctrl_assoc_prepare_message(void * message,u32 desc_index,const void * priv)249 static void iter_pinctrl_assoc_prepare_message(void *message,
250 					       u32 desc_index,
251 					       const void *priv)
252 {
253 	struct scmi_msg_pinctrl_list_assoc *msg = message;
254 	const struct scmi_pinctrl_ipriv *p = priv;
255 
256 	msg->identifier = cpu_to_le32(p->selector);
257 	msg->flags = cpu_to_le32(p->type);
258 	msg->index = cpu_to_le32(desc_index);
259 }
260 
iter_pinctrl_assoc_update_state(struct scmi_iterator_state * st,const void * response,void * priv)261 static int iter_pinctrl_assoc_update_state(struct scmi_iterator_state *st,
262 					   const void *response, void *priv)
263 {
264 	const struct scmi_resp_pinctrl_list_assoc *r = response;
265 
266 	st->num_returned = RETURNED(r->flags);
267 	st->num_remaining = REMAINING(r->flags);
268 
269 	return 0;
270 }
271 
272 static int
iter_pinctrl_assoc_process_response(const struct scmi_protocol_handle * ph,const void * response,struct scmi_iterator_state * st,void * priv)273 iter_pinctrl_assoc_process_response(const struct scmi_protocol_handle *ph,
274 				    const void *response,
275 				    struct scmi_iterator_state *st, void *priv)
276 {
277 	const struct scmi_resp_pinctrl_list_assoc *r = response;
278 	struct scmi_pinctrl_ipriv *p = priv;
279 
280 	p->array[st->desc_index + st->loop_idx] =
281 		le16_to_cpu(r->array[st->loop_idx]);
282 
283 	return 0;
284 }
285 
scmi_pinctrl_list_associations(const struct scmi_protocol_handle * ph,u32 selector,enum scmi_pinctrl_selector_type type,u16 size,u32 * array)286 static int scmi_pinctrl_list_associations(const struct scmi_protocol_handle *ph,
287 					  u32 selector,
288 					  enum scmi_pinctrl_selector_type type,
289 					  u16 size, u32 *array)
290 {
291 	int ret;
292 	void *iter;
293 	struct scmi_iterator_ops ops = {
294 		.prepare_message = iter_pinctrl_assoc_prepare_message,
295 		.update_state = iter_pinctrl_assoc_update_state,
296 		.process_response = iter_pinctrl_assoc_process_response,
297 	};
298 	struct scmi_pinctrl_ipriv ipriv = {
299 		.selector = selector,
300 		.type = type,
301 		.array = array,
302 	};
303 
304 	if (!array || !size || type == PIN_TYPE)
305 		return -EINVAL;
306 
307 	ret = scmi_pinctrl_validate_id(ph, selector, type);
308 	if (ret)
309 		return ret;
310 
311 	iter = ph->hops->iter_response_init(ph, &ops, size,
312 					    PINCTRL_LIST_ASSOCIATIONS,
313 					    sizeof(struct scmi_msg_pinctrl_list_assoc),
314 					    &ipriv);
315 	if (IS_ERR(iter))
316 		return PTR_ERR(iter);
317 
318 	return ph->hops->iter_response_run(iter);
319 }
320 
321 struct scmi_settings_get_ipriv {
322 	u32 selector;
323 	enum scmi_pinctrl_selector_type type;
324 	bool get_all;
325 	unsigned int *nr_configs;
326 	enum scmi_pinctrl_conf_type *config_types;
327 	u32 *config_values;
328 };
329 
330 static void
iter_pinctrl_settings_get_prepare_message(void * message,u32 desc_index,const void * priv)331 iter_pinctrl_settings_get_prepare_message(void *message, u32 desc_index,
332 					  const void *priv)
333 {
334 	struct scmi_msg_settings_get *msg = message;
335 	const struct scmi_settings_get_ipriv *p = priv;
336 	u32 attributes;
337 
338 	attributes = FIELD_PREP(SELECTOR_MASK, p->type);
339 
340 	if (p->get_all) {
341 		attributes |= FIELD_PREP(CONFIG_FLAG_MASK, 1) |
342 			FIELD_PREP(SKIP_CONFIGS_MASK, desc_index);
343 	} else {
344 		attributes |= FIELD_PREP(CONFIG_TYPE_MASK, p->config_types[0]);
345 	}
346 
347 	msg->attributes = cpu_to_le32(attributes);
348 	msg->identifier = cpu_to_le32(p->selector);
349 }
350 
351 static int
iter_pinctrl_settings_get_update_state(struct scmi_iterator_state * st,const void * response,void * priv)352 iter_pinctrl_settings_get_update_state(struct scmi_iterator_state *st,
353 				       const void *response, void *priv)
354 {
355 	const struct scmi_resp_settings_get *r = response;
356 	struct scmi_settings_get_ipriv *p = priv;
357 
358 	if (p->get_all) {
359 		st->num_returned = le32_get_bits(r->num_configs, GENMASK(7, 0));
360 		st->num_remaining = le32_get_bits(r->num_configs, GENMASK(31, 24));
361 	} else {
362 		st->num_returned = 1;
363 		st->num_remaining = 0;
364 	}
365 
366 	return 0;
367 }
368 
369 static int
iter_pinctrl_settings_get_process_response(const struct scmi_protocol_handle * ph,const void * response,struct scmi_iterator_state * st,void * priv)370 iter_pinctrl_settings_get_process_response(const struct scmi_protocol_handle *ph,
371 					   const void *response,
372 					   struct scmi_iterator_state *st,
373 					   void *priv)
374 {
375 	const struct scmi_resp_settings_get *r = response;
376 	struct scmi_settings_get_ipriv *p = priv;
377 	u32 type = le32_get_bits(r->configs[st->loop_idx * 2], GENMASK(7, 0));
378 	u32 val = le32_to_cpu(r->configs[st->loop_idx * 2 + 1]);
379 
380 	if (p->get_all) {
381 		p->config_types[st->desc_index + st->loop_idx] = type;
382 	} else {
383 		if (p->config_types[0] != type)
384 			return -EINVAL;
385 	}
386 
387 	p->config_values[st->desc_index + st->loop_idx] = val;
388 	++*p->nr_configs;
389 
390 	return 0;
391 }
392 
393 static int
scmi_pinctrl_settings_get(const struct scmi_protocol_handle * ph,u32 selector,enum scmi_pinctrl_selector_type type,unsigned int * nr_configs,enum scmi_pinctrl_conf_type * config_types,u32 * config_values)394 scmi_pinctrl_settings_get(const struct scmi_protocol_handle *ph, u32 selector,
395 			  enum scmi_pinctrl_selector_type type,
396 			  unsigned int *nr_configs,
397 			  enum scmi_pinctrl_conf_type *config_types,
398 			  u32 *config_values)
399 {
400 	int ret;
401 	void *iter;
402 	unsigned int max_configs = *nr_configs;
403 	struct scmi_iterator_ops ops = {
404 		.prepare_message = iter_pinctrl_settings_get_prepare_message,
405 		.update_state = iter_pinctrl_settings_get_update_state,
406 		.process_response = iter_pinctrl_settings_get_process_response,
407 	};
408 	struct scmi_settings_get_ipriv ipriv = {
409 		.selector = selector,
410 		.type = type,
411 		.get_all = (max_configs > 1),
412 		.nr_configs = nr_configs,
413 		.config_types = config_types,
414 		.config_values = config_values,
415 	};
416 
417 	if (!config_types || !config_values || type == FUNCTION_TYPE)
418 		return -EINVAL;
419 
420 	ret = scmi_pinctrl_validate_id(ph, selector, type);
421 	if (ret)
422 		return ret;
423 
424 	/* Prepare to count returned configs */
425 	*nr_configs = 0;
426 	iter = ph->hops->iter_response_init(ph, &ops, max_configs,
427 					    PINCTRL_SETTINGS_GET,
428 					    sizeof(struct scmi_msg_settings_get),
429 					    &ipriv);
430 	if (IS_ERR(iter))
431 		return PTR_ERR(iter);
432 
433 	return ph->hops->iter_response_run(iter);
434 }
435 
scmi_pinctrl_settings_get_one(const struct scmi_protocol_handle * ph,u32 selector,enum scmi_pinctrl_selector_type type,enum scmi_pinctrl_conf_type config_type,u32 * config_value)436 static int scmi_pinctrl_settings_get_one(const struct scmi_protocol_handle *ph,
437 					 u32 selector,
438 					 enum scmi_pinctrl_selector_type type,
439 					 enum scmi_pinctrl_conf_type config_type,
440 					 u32 *config_value)
441 {
442 	unsigned int nr_configs = 1;
443 
444 	return scmi_pinctrl_settings_get(ph, selector, type, &nr_configs,
445 					 &config_type, config_value);
446 }
447 
scmi_pinctrl_settings_get_all(const struct scmi_protocol_handle * ph,u32 selector,enum scmi_pinctrl_selector_type type,unsigned int * nr_configs,enum scmi_pinctrl_conf_type * config_types,u32 * config_values)448 static int scmi_pinctrl_settings_get_all(const struct scmi_protocol_handle *ph,
449 					 u32 selector,
450 					 enum scmi_pinctrl_selector_type type,
451 					 unsigned int *nr_configs,
452 					 enum scmi_pinctrl_conf_type *config_types,
453 					 u32 *config_values)
454 {
455 	if (!nr_configs || *nr_configs == 0)
456 		return -EINVAL;
457 
458 	return scmi_pinctrl_settings_get(ph, selector, type, nr_configs,
459 					 config_types, config_values);
460 }
461 
462 static int
scmi_pinctrl_settings_conf(const struct scmi_protocol_handle * ph,u32 selector,enum scmi_pinctrl_selector_type type,u32 nr_configs,enum scmi_pinctrl_conf_type * config_type,u32 * config_value)463 scmi_pinctrl_settings_conf(const struct scmi_protocol_handle *ph,
464 			   u32 selector,
465 			   enum scmi_pinctrl_selector_type type,
466 			   u32 nr_configs,
467 			   enum scmi_pinctrl_conf_type *config_type,
468 			   u32 *config_value)
469 {
470 	struct scmi_xfer *t;
471 	struct scmi_msg_settings_conf *tx;
472 	u32 attributes;
473 	int ret, i;
474 	u32 configs_in_chunk, conf_num = 0;
475 	u32 chunk;
476 	int max_msg_size = ph->hops->get_max_msg_size(ph);
477 
478 	if (!config_type || !config_value || type == FUNCTION_TYPE)
479 		return -EINVAL;
480 
481 	ret = scmi_pinctrl_validate_id(ph, selector, type);
482 	if (ret)
483 		return ret;
484 
485 	configs_in_chunk = (max_msg_size - sizeof(*tx)) / (sizeof(__le32) * 2);
486 	while (conf_num < nr_configs) {
487 		chunk = (nr_configs - conf_num > configs_in_chunk) ?
488 			configs_in_chunk : nr_configs - conf_num;
489 
490 		ret = ph->xops->xfer_get_init(ph, PINCTRL_SETTINGS_CONFIGURE,
491 					      sizeof(*tx) +
492 					      chunk * 2 * sizeof(__le32), 0, &t);
493 		if (ret)
494 			break;
495 
496 		tx = t->tx.buf;
497 		tx->identifier = cpu_to_le32(selector);
498 		tx->function_id = cpu_to_le32(0xFFFFFFFF);
499 		attributes = FIELD_PREP(GENMASK(1, 0), type) |
500 			FIELD_PREP(GENMASK(9, 2), chunk);
501 		tx->attributes = cpu_to_le32(attributes);
502 
503 		for (i = 0; i < chunk; i++) {
504 			tx->configs[i * 2] =
505 				cpu_to_le32(config_type[conf_num + i]);
506 			tx->configs[i * 2 + 1] =
507 				cpu_to_le32(config_value[conf_num + i]);
508 		}
509 
510 		ret = ph->xops->do_xfer(ph, t);
511 
512 		ph->xops->xfer_put(ph, t);
513 
514 		if (ret)
515 			break;
516 
517 		conf_num += chunk;
518 	}
519 
520 	return ret;
521 }
522 
scmi_pinctrl_function_select(const struct scmi_protocol_handle * ph,u32 group,enum scmi_pinctrl_selector_type type,u32 function_id)523 static int scmi_pinctrl_function_select(const struct scmi_protocol_handle *ph,
524 					u32 group,
525 					enum scmi_pinctrl_selector_type type,
526 					u32 function_id)
527 {
528 	int ret;
529 	struct scmi_xfer *t;
530 	struct scmi_msg_settings_conf *tx;
531 	u32 attributes;
532 
533 	ret = scmi_pinctrl_validate_id(ph, group, type);
534 	if (ret)
535 		return ret;
536 
537 	ret = ph->xops->xfer_get_init(ph, PINCTRL_SETTINGS_CONFIGURE,
538 				      sizeof(*tx), 0, &t);
539 	if (ret)
540 		return ret;
541 
542 	tx = t->tx.buf;
543 	tx->identifier = cpu_to_le32(group);
544 	tx->function_id = cpu_to_le32(function_id);
545 	attributes = FIELD_PREP(GENMASK(1, 0), type) | BIT(10);
546 	tx->attributes = cpu_to_le32(attributes);
547 
548 	ret = ph->xops->do_xfer(ph, t);
549 	ph->xops->xfer_put(ph, t);
550 
551 	return ret;
552 }
553 
scmi_pinctrl_request_free(const struct scmi_protocol_handle * ph,u32 identifier,enum scmi_pinctrl_selector_type type,enum scmi_pinctrl_protocol_cmd cmd)554 static int scmi_pinctrl_request_free(const struct scmi_protocol_handle *ph,
555 				     u32 identifier,
556 				     enum scmi_pinctrl_selector_type type,
557 				     enum scmi_pinctrl_protocol_cmd cmd)
558 {
559 	int ret;
560 	struct scmi_xfer *t;
561 	struct scmi_msg_request *tx;
562 
563 	if (type == FUNCTION_TYPE)
564 		return -EINVAL;
565 
566 	if (cmd != PINCTRL_REQUEST && cmd != PINCTRL_RELEASE)
567 		return -EINVAL;
568 
569 	ret = scmi_pinctrl_validate_id(ph, identifier, type);
570 	if (ret)
571 		return ret;
572 
573 	ret = ph->xops->xfer_get_init(ph, cmd, sizeof(*tx), 0, &t);
574 	if (ret)
575 		return ret;
576 
577 	tx = t->tx.buf;
578 	tx->identifier = cpu_to_le32(identifier);
579 	tx->flags = cpu_to_le32(type);
580 
581 	ret = ph->xops->do_xfer(ph, t);
582 	ph->xops->xfer_put(ph, t);
583 
584 	return ret;
585 }
586 
scmi_pinctrl_pin_request(const struct scmi_protocol_handle * ph,u32 pin)587 static int scmi_pinctrl_pin_request(const struct scmi_protocol_handle *ph,
588 				    u32 pin)
589 {
590 	return scmi_pinctrl_request_free(ph, pin, PIN_TYPE, PINCTRL_REQUEST);
591 }
592 
scmi_pinctrl_pin_free(const struct scmi_protocol_handle * ph,u32 pin)593 static int scmi_pinctrl_pin_free(const struct scmi_protocol_handle *ph, u32 pin)
594 {
595 	return scmi_pinctrl_request_free(ph, pin, PIN_TYPE, PINCTRL_RELEASE);
596 }
597 
scmi_pinctrl_get_group_info(const struct scmi_protocol_handle * ph,u32 selector,struct scmi_group_info * group)598 static int scmi_pinctrl_get_group_info(const struct scmi_protocol_handle *ph,
599 				       u32 selector,
600 				       struct scmi_group_info *group)
601 {
602 	int ret;
603 
604 	ret = scmi_pinctrl_attributes(ph, GROUP_TYPE, selector, group->name,
605 				      &group->nr_pins);
606 	if (ret)
607 		return ret;
608 
609 	if (!group->nr_pins) {
610 		dev_err(ph->dev, "Group %d has 0 elements", selector);
611 		return -ENODATA;
612 	}
613 
614 	group->group_pins = kmalloc_array(group->nr_pins,
615 					  sizeof(*group->group_pins),
616 					  GFP_KERNEL);
617 	if (!group->group_pins)
618 		return -ENOMEM;
619 
620 	ret = scmi_pinctrl_list_associations(ph, selector, GROUP_TYPE,
621 					     group->nr_pins, group->group_pins);
622 	if (ret) {
623 		kfree(group->group_pins);
624 		return ret;
625 	}
626 
627 	group->present = true;
628 	return 0;
629 }
630 
scmi_pinctrl_get_group_name(const struct scmi_protocol_handle * ph,u32 selector,const char ** name)631 static int scmi_pinctrl_get_group_name(const struct scmi_protocol_handle *ph,
632 				       u32 selector, const char **name)
633 {
634 	struct scmi_pinctrl_info *pi = ph->get_priv(ph);
635 
636 	if (!name)
637 		return -EINVAL;
638 
639 	if (selector >= pi->nr_groups || pi->nr_groups == 0)
640 		return -EINVAL;
641 
642 	if (!pi->groups[selector].present) {
643 		int ret;
644 
645 		ret = scmi_pinctrl_get_group_info(ph, selector,
646 						  &pi->groups[selector]);
647 		if (ret)
648 			return ret;
649 	}
650 
651 	*name = pi->groups[selector].name;
652 
653 	return 0;
654 }
655 
scmi_pinctrl_group_pins_get(const struct scmi_protocol_handle * ph,u32 selector,const u32 ** pins,u32 * nr_pins)656 static int scmi_pinctrl_group_pins_get(const struct scmi_protocol_handle *ph,
657 				       u32 selector, const u32 **pins,
658 				       u32 *nr_pins)
659 {
660 	struct scmi_pinctrl_info *pi = ph->get_priv(ph);
661 
662 	if (!pins || !nr_pins)
663 		return -EINVAL;
664 
665 	if (selector >= pi->nr_groups || pi->nr_groups == 0)
666 		return -EINVAL;
667 
668 	if (!pi->groups[selector].present) {
669 		int ret;
670 
671 		ret = scmi_pinctrl_get_group_info(ph, selector,
672 						  &pi->groups[selector]);
673 		if (ret)
674 			return ret;
675 	}
676 
677 	*pins = pi->groups[selector].group_pins;
678 	*nr_pins = pi->groups[selector].nr_pins;
679 
680 	return 0;
681 }
682 
scmi_pinctrl_get_function_info(const struct scmi_protocol_handle * ph,u32 selector,struct scmi_function_info * func)683 static int scmi_pinctrl_get_function_info(const struct scmi_protocol_handle *ph,
684 					  u32 selector,
685 					  struct scmi_function_info *func)
686 {
687 	int ret;
688 
689 	ret = scmi_pinctrl_attributes(ph, FUNCTION_TYPE, selector, func->name,
690 				      &func->nr_groups);
691 	if (ret)
692 		return ret;
693 
694 	if (!func->nr_groups) {
695 		dev_err(ph->dev, "Function %d has 0 elements", selector);
696 		return -ENODATA;
697 	}
698 
699 	func->groups = kmalloc_array(func->nr_groups, sizeof(*func->groups),
700 				     GFP_KERNEL);
701 	if (!func->groups)
702 		return -ENOMEM;
703 
704 	ret = scmi_pinctrl_list_associations(ph, selector, FUNCTION_TYPE,
705 					     func->nr_groups, func->groups);
706 	if (ret) {
707 		kfree(func->groups);
708 		return ret;
709 	}
710 
711 	func->present = true;
712 	return 0;
713 }
714 
scmi_pinctrl_get_function_name(const struct scmi_protocol_handle * ph,u32 selector,const char ** name)715 static int scmi_pinctrl_get_function_name(const struct scmi_protocol_handle *ph,
716 					  u32 selector, const char **name)
717 {
718 	struct scmi_pinctrl_info *pi = ph->get_priv(ph);
719 
720 	if (!name)
721 		return -EINVAL;
722 
723 	if (selector >= pi->nr_functions || pi->nr_functions == 0)
724 		return -EINVAL;
725 
726 	if (!pi->functions[selector].present) {
727 		int ret;
728 
729 		ret = scmi_pinctrl_get_function_info(ph, selector,
730 						     &pi->functions[selector]);
731 		if (ret)
732 			return ret;
733 	}
734 
735 	*name = pi->functions[selector].name;
736 	return 0;
737 }
738 
739 static int
scmi_pinctrl_function_groups_get(const struct scmi_protocol_handle * ph,u32 selector,u32 * nr_groups,const u32 ** groups)740 scmi_pinctrl_function_groups_get(const struct scmi_protocol_handle *ph,
741 				 u32 selector, u32 *nr_groups,
742 				 const u32 **groups)
743 {
744 	struct scmi_pinctrl_info *pi = ph->get_priv(ph);
745 
746 	if (!groups || !nr_groups)
747 		return -EINVAL;
748 
749 	if (selector >= pi->nr_functions || pi->nr_functions == 0)
750 		return -EINVAL;
751 
752 	if (!pi->functions[selector].present) {
753 		int ret;
754 
755 		ret = scmi_pinctrl_get_function_info(ph, selector,
756 						     &pi->functions[selector]);
757 		if (ret)
758 			return ret;
759 	}
760 
761 	*groups = pi->functions[selector].groups;
762 	*nr_groups = pi->functions[selector].nr_groups;
763 
764 	return 0;
765 }
766 
scmi_pinctrl_mux_set(const struct scmi_protocol_handle * ph,u32 selector,u32 group)767 static int scmi_pinctrl_mux_set(const struct scmi_protocol_handle *ph,
768 				u32 selector, u32 group)
769 {
770 	return scmi_pinctrl_function_select(ph, group, GROUP_TYPE, selector);
771 }
772 
scmi_pinctrl_get_pin_info(const struct scmi_protocol_handle * ph,u32 selector,struct scmi_pin_info * pin)773 static int scmi_pinctrl_get_pin_info(const struct scmi_protocol_handle *ph,
774 				     u32 selector, struct scmi_pin_info *pin)
775 {
776 	int ret;
777 
778 	if (!pin)
779 		return -EINVAL;
780 
781 	ret = scmi_pinctrl_attributes(ph, PIN_TYPE, selector, pin->name, NULL);
782 	if (ret)
783 		return ret;
784 
785 	pin->present = true;
786 	return 0;
787 }
788 
scmi_pinctrl_get_pin_name(const struct scmi_protocol_handle * ph,u32 selector,const char ** name)789 static int scmi_pinctrl_get_pin_name(const struct scmi_protocol_handle *ph,
790 				     u32 selector, const char **name)
791 {
792 	struct scmi_pinctrl_info *pi = ph->get_priv(ph);
793 
794 	if (!name)
795 		return -EINVAL;
796 
797 	if (selector >= pi->nr_pins)
798 		return -EINVAL;
799 
800 	if (!pi->pins[selector].present) {
801 		int ret;
802 
803 		ret = scmi_pinctrl_get_pin_info(ph, selector, &pi->pins[selector]);
804 		if (ret)
805 			return ret;
806 	}
807 
808 	*name = pi->pins[selector].name;
809 
810 	return 0;
811 }
812 
scmi_pinctrl_name_get(const struct scmi_protocol_handle * ph,u32 selector,enum scmi_pinctrl_selector_type type,const char ** name)813 static int scmi_pinctrl_name_get(const struct scmi_protocol_handle *ph,
814 				 u32 selector,
815 				 enum scmi_pinctrl_selector_type type,
816 				 const char **name)
817 {
818 	switch (type) {
819 	case PIN_TYPE:
820 		return scmi_pinctrl_get_pin_name(ph, selector, name);
821 	case GROUP_TYPE:
822 		return scmi_pinctrl_get_group_name(ph, selector, name);
823 	case FUNCTION_TYPE:
824 		return scmi_pinctrl_get_function_name(ph, selector, name);
825 	default:
826 		return -EINVAL;
827 	}
828 }
829 
830 static const struct scmi_pinctrl_proto_ops pinctrl_proto_ops = {
831 	.count_get = scmi_pinctrl_count_get,
832 	.name_get = scmi_pinctrl_name_get,
833 	.group_pins_get = scmi_pinctrl_group_pins_get,
834 	.function_groups_get = scmi_pinctrl_function_groups_get,
835 	.mux_set = scmi_pinctrl_mux_set,
836 	.settings_get_one = scmi_pinctrl_settings_get_one,
837 	.settings_get_all = scmi_pinctrl_settings_get_all,
838 	.settings_conf = scmi_pinctrl_settings_conf,
839 	.pin_request = scmi_pinctrl_pin_request,
840 	.pin_free = scmi_pinctrl_pin_free,
841 };
842 
scmi_pinctrl_protocol_init(const struct scmi_protocol_handle * ph)843 static int scmi_pinctrl_protocol_init(const struct scmi_protocol_handle *ph)
844 {
845 	int ret;
846 	u32 version;
847 	struct scmi_pinctrl_info *pinfo;
848 
849 	ret = ph->xops->version_get(ph, &version);
850 	if (ret)
851 		return ret;
852 
853 	dev_dbg(ph->dev, "Pinctrl Version %d.%d\n",
854 		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
855 
856 	pinfo = devm_kzalloc(ph->dev, sizeof(*pinfo), GFP_KERNEL);
857 	if (!pinfo)
858 		return -ENOMEM;
859 
860 	ret = scmi_pinctrl_attributes_get(ph, pinfo);
861 	if (ret)
862 		return ret;
863 
864 	pinfo->pins = devm_kcalloc(ph->dev, pinfo->nr_pins,
865 				   sizeof(*pinfo->pins), GFP_KERNEL);
866 	if (!pinfo->pins)
867 		return -ENOMEM;
868 
869 	pinfo->groups = devm_kcalloc(ph->dev, pinfo->nr_groups,
870 				     sizeof(*pinfo->groups), GFP_KERNEL);
871 	if (!pinfo->groups)
872 		return -ENOMEM;
873 
874 	pinfo->functions = devm_kcalloc(ph->dev, pinfo->nr_functions,
875 					sizeof(*pinfo->functions), GFP_KERNEL);
876 	if (!pinfo->functions)
877 		return -ENOMEM;
878 
879 	pinfo->version = version;
880 
881 	return ph->set_priv(ph, pinfo, version);
882 }
883 
scmi_pinctrl_protocol_deinit(const struct scmi_protocol_handle * ph)884 static int scmi_pinctrl_protocol_deinit(const struct scmi_protocol_handle *ph)
885 {
886 	int i;
887 	struct scmi_pinctrl_info *pi = ph->get_priv(ph);
888 
889 	/* Free groups_pins allocated in scmi_pinctrl_get_group_info */
890 	for (i = 0; i < pi->nr_groups; i++) {
891 		if (pi->groups[i].present) {
892 			kfree(pi->groups[i].group_pins);
893 			pi->groups[i].present = false;
894 		}
895 	}
896 
897 	/* Free groups allocated in scmi_pinctrl_get_function_info */
898 	for (i = 0; i < pi->nr_functions; i++) {
899 		if (pi->functions[i].present) {
900 			kfree(pi->functions[i].groups);
901 			pi->functions[i].present = false;
902 		}
903 	}
904 
905 	return 0;
906 }
907 
908 static const struct scmi_protocol scmi_pinctrl = {
909 	.id = SCMI_PROTOCOL_PINCTRL,
910 	.owner = THIS_MODULE,
911 	.instance_init = &scmi_pinctrl_protocol_init,
912 	.instance_deinit = &scmi_pinctrl_protocol_deinit,
913 	.ops = &pinctrl_proto_ops,
914 	.supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION,
915 };
916 
917 DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(pinctrl, scmi_pinctrl)
918