Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/firmware/arm_scmi/pinctrl.c
26428 views
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
919