firmware: arm_scmi: Add basic support for SCMI v3.2 pincontrol protocol
[linux-2.6-block.git] / drivers / firmware / arm_scmi / pinctrl.c
CommitLineData
2145af01
PF
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
40enum 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
51struct scmi_msg_settings_conf {
52 __le32 identifier;
53 __le32 function_id;
54 __le32 attributes;
55 __le32 configs[];
56};
57
58struct scmi_msg_settings_get {
59 __le32 identifier;
60 __le32 attributes;
61};
62
63struct scmi_resp_settings_get {
64 __le32 function_selected;
65 __le32 num_configs;
66 __le32 configs[];
67};
68
69struct scmi_msg_pinctrl_protocol_attributes {
70 __le32 attributes_low;
71 __le32 attributes_high;
72};
73
74struct scmi_msg_pinctrl_attributes {
75 __le32 identifier;
76 __le32 flags;
77};
78
79struct scmi_resp_pinctrl_attributes {
80 __le32 attributes;
81 u8 name[SCMI_SHORT_NAME_MAX_SIZE];
82};
83
84struct scmi_msg_pinctrl_list_assoc {
85 __le32 identifier;
86 __le32 flags;
87 __le32 index;
88};
89
90struct scmi_resp_pinctrl_list_assoc {
91 __le32 flags;
92 __le16 array[];
93};
94
95struct scmi_msg_request {
96 __le32 identifier;
97 __le32 flags;
98};
99
100struct scmi_group_info {
101 char name[SCMI_MAX_STR_SIZE];
102 bool present;
103 u32 *group_pins;
104 u32 nr_pins;
105};
106
107struct scmi_function_info {
108 char name[SCMI_MAX_STR_SIZE];
109 bool present;
110 u32 *groups;
111 u32 nr_groups;
112};
113
114struct scmi_pin_info {
115 char name[SCMI_MAX_STR_SIZE];
116 bool present;
117};
118
119struct 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
129static 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
157static 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
174static 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
190static 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
243struct scmi_pinctrl_ipriv {
244 u32 selector;
245 enum scmi_pinctrl_selector_type type;
246 u32 *array;
247};
248
249static 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
261static 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
272static int
273iter_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
286static 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
321struct 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
330static void
331iter_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
351static int
352iter_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
369static int
370iter_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
393static int
394scmi_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
436static 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
448static 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
462static int
463scmi_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
523static 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
554static 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
587static 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
593static 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
598static 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
631static 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
656static 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
683static 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
715static 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
739static int
740scmi_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
767static 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
773static 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
789static 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
813static 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
830static 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
843static 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
884static 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
908static 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};
916DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(pinctrl, scmi_pinctrl)