1 // SPDX-License-Identifier: GPL-2.0
3 * System Control and Management Interface (SCMI) Pinctrl Protocol
5 * Copyright (C) 2024 EPAM
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>
20 #include "protocols.h"
22 /* Updated only after ALL the mandatory features for that version are merged */
23 #define SCMI_PROTOCOL_SUPPORTED_VERSION 0x10000
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))
29 #define EXT_NAME_FLAG(x) le32_get_bits((x), BIT(31))
30 #define NUM_ELEMS(x) le32_get_bits((x), GENMASK(15, 0))
32 #define REMAINING(x) le32_get_bits((x), GENMASK(31, 16))
33 #define RETURNED(x) le32_get_bits((x), GENMASK(11, 0))
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)
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,
51 struct scmi_msg_settings_conf
{
58 struct scmi_msg_settings_get
{
63 struct scmi_resp_settings_get
{
64 __le32 function_selected
;
69 struct scmi_msg_pinctrl_protocol_attributes
{
70 __le32 attributes_low
;
71 __le32 attributes_high
;
74 struct scmi_msg_pinctrl_attributes
{
79 struct scmi_resp_pinctrl_attributes
{
81 u8 name
[SCMI_SHORT_NAME_MAX_SIZE
];
84 struct scmi_msg_pinctrl_list_assoc
{
90 struct scmi_resp_pinctrl_list_assoc
{
95 struct scmi_msg_request
{
100 struct scmi_group_info
{
101 char name
[SCMI_MAX_STR_SIZE
];
107 struct scmi_function_info
{
108 char name
[SCMI_MAX_STR_SIZE
];
114 struct scmi_pin_info
{
115 char name
[SCMI_MAX_STR_SIZE
];
119 struct scmi_pinctrl_info
{
124 struct scmi_group_info
*groups
;
125 struct scmi_function_info
*functions
;
126 struct scmi_pin_info
*pins
;
129 static int scmi_pinctrl_attributes_get(const struct scmi_protocol_handle
*ph
,
130 struct scmi_pinctrl_info
*pi
)
134 struct scmi_msg_pinctrl_protocol_attributes
*attr
;
136 ret
= ph
->xops
->xfer_get_init(ph
, PROTOCOL_ATTRIBUTES
, 0, sizeof(*attr
), &t
);
142 ret
= ph
->xops
->do_xfer(ph
, t
);
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");
153 ph
->xops
->xfer_put(ph
, t
);
157 static int scmi_pinctrl_count_get(const struct scmi_protocol_handle
*ph
,
158 enum scmi_pinctrl_selector_type type
)
160 struct scmi_pinctrl_info
*pi
= ph
->get_priv(ph
);
166 return pi
->nr_groups
;
168 return pi
->nr_functions
;
174 static int scmi_pinctrl_validate_id(const struct scmi_protocol_handle
*ph
,
176 enum scmi_pinctrl_selector_type type
)
180 value
= scmi_pinctrl_count_get(ph
, type
);
184 if (selector
>= value
|| value
== 0)
190 static int scmi_pinctrl_attributes(const struct scmi_protocol_handle
*ph
,
191 enum scmi_pinctrl_selector_type type
,
192 u32 selector
, char *name
,
197 struct scmi_msg_pinctrl_attributes
*tx
;
198 struct scmi_resp_pinctrl_attributes
*rx
;
204 ret
= scmi_pinctrl_validate_id(ph
, selector
, type
);
208 ret
= ph
->xops
->xfer_get_init(ph
, PINCTRL_ATTRIBUTES
, sizeof(*tx
),
215 tx
->identifier
= cpu_to_le32(selector
);
216 tx
->flags
= cpu_to_le32(type
);
218 ret
= ph
->xops
->do_xfer(ph
, t
);
221 *n_elems
= NUM_ELEMS(rx
->attributes
);
223 strscpy(name
, rx
->name
, SCMI_SHORT_NAME_MAX_SIZE
);
225 ext_name_flag
= !!EXT_NAME_FLAG(rx
->attributes
);
228 ph
->xops
->xfer_put(ph
, t
);
233 * If supported overwrite short name with the extended one;
234 * on error just carry on and use already provided short name.
237 ret
= ph
->hops
->extended_name_get(ph
, PINCTRL_NAME_GET
,
238 selector
, (u32
*)&type
, name
,
243 struct scmi_pinctrl_ipriv
{
245 enum scmi_pinctrl_selector_type type
;
249 static void iter_pinctrl_assoc_prepare_message(void *message
,
253 struct scmi_msg_pinctrl_list_assoc
*msg
= message
;
254 const struct scmi_pinctrl_ipriv
*p
= priv
;
256 msg
->identifier
= cpu_to_le32(p
->selector
);
257 msg
->flags
= cpu_to_le32(p
->type
);
258 msg
->index
= cpu_to_le32(desc_index
);
261 static int iter_pinctrl_assoc_update_state(struct scmi_iterator_state
*st
,
262 const void *response
, void *priv
)
264 const struct scmi_resp_pinctrl_list_assoc
*r
= response
;
266 st
->num_returned
= RETURNED(r
->flags
);
267 st
->num_remaining
= REMAINING(r
->flags
);
273 iter_pinctrl_assoc_process_response(const struct scmi_protocol_handle
*ph
,
274 const void *response
,
275 struct scmi_iterator_state
*st
, void *priv
)
277 const struct scmi_resp_pinctrl_list_assoc
*r
= response
;
278 struct scmi_pinctrl_ipriv
*p
= priv
;
280 p
->array
[st
->desc_index
+ st
->loop_idx
] =
281 le16_to_cpu(r
->array
[st
->loop_idx
]);
286 static int scmi_pinctrl_list_associations(const struct scmi_protocol_handle
*ph
,
288 enum scmi_pinctrl_selector_type type
,
289 u16 size
, u32
*array
)
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
,
298 struct scmi_pinctrl_ipriv ipriv
= {
299 .selector
= selector
,
304 if (!array
|| !size
|| type
== PIN_TYPE
)
307 ret
= scmi_pinctrl_validate_id(ph
, selector
, type
);
311 iter
= ph
->hops
->iter_response_init(ph
, &ops
, size
,
312 PINCTRL_LIST_ASSOCIATIONS
,
313 sizeof(struct scmi_msg_pinctrl_list_assoc
),
316 return PTR_ERR(iter
);
318 return ph
->hops
->iter_response_run(iter
);
321 struct scmi_settings_get_ipriv
{
323 enum scmi_pinctrl_selector_type type
;
325 unsigned int *nr_configs
;
326 enum scmi_pinctrl_conf_type
*config_types
;
331 iter_pinctrl_settings_get_prepare_message(void *message
, u32 desc_index
,
334 struct scmi_msg_settings_get
*msg
= message
;
335 const struct scmi_settings_get_ipriv
*p
= priv
;
338 attributes
= FIELD_PREP(SELECTOR_MASK
, p
->type
);
341 attributes
|= FIELD_PREP(CONFIG_FLAG_MASK
, 1) |
342 FIELD_PREP(SKIP_CONFIGS_MASK
, desc_index
);
344 attributes
|= FIELD_PREP(CONFIG_TYPE_MASK
, p
->config_types
[0]);
347 msg
->attributes
= cpu_to_le32(attributes
);
348 msg
->identifier
= cpu_to_le32(p
->selector
);
352 iter_pinctrl_settings_get_update_state(struct scmi_iterator_state
*st
,
353 const void *response
, void *priv
)
355 const struct scmi_resp_settings_get
*r
= response
;
356 struct scmi_settings_get_ipriv
*p
= priv
;
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));
362 st
->num_returned
= 1;
363 st
->num_remaining
= 0;
370 iter_pinctrl_settings_get_process_response(const struct scmi_protocol_handle
*ph
,
371 const void *response
,
372 struct scmi_iterator_state
*st
,
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]);
381 p
->config_types
[st
->desc_index
+ st
->loop_idx
] = type
;
383 if (p
->config_types
[0] != type
)
387 p
->config_values
[st
->desc_index
+ st
->loop_idx
] = val
;
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
,
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
,
408 struct scmi_settings_get_ipriv ipriv
= {
409 .selector
= selector
,
411 .get_all
= (max_configs
> 1),
412 .nr_configs
= nr_configs
,
413 .config_types
= config_types
,
414 .config_values
= config_values
,
417 if (!config_types
|| !config_values
|| type
== FUNCTION_TYPE
)
420 ret
= scmi_pinctrl_validate_id(ph
, selector
, type
);
424 /* Prepare to count returned configs */
426 iter
= ph
->hops
->iter_response_init(ph
, &ops
, max_configs
,
427 PINCTRL_SETTINGS_GET
,
428 sizeof(struct scmi_msg_settings_get
),
431 return PTR_ERR(iter
);
433 return ph
->hops
->iter_response_run(iter
);
436 static int scmi_pinctrl_settings_get_one(const struct scmi_protocol_handle
*ph
,
438 enum scmi_pinctrl_selector_type type
,
439 enum scmi_pinctrl_conf_type config_type
,
442 unsigned int nr_configs
= 1;
444 return scmi_pinctrl_settings_get(ph
, selector
, type
, &nr_configs
,
445 &config_type
, config_value
);
448 static int scmi_pinctrl_settings_get_all(const struct scmi_protocol_handle
*ph
,
450 enum scmi_pinctrl_selector_type type
,
451 unsigned int *nr_configs
,
452 enum scmi_pinctrl_conf_type
*config_types
,
455 if (!nr_configs
|| *nr_configs
== 0)
458 return scmi_pinctrl_settings_get(ph
, selector
, type
, nr_configs
,
459 config_types
, config_values
);
463 scmi_pinctrl_settings_conf(const struct scmi_protocol_handle
*ph
,
465 enum scmi_pinctrl_selector_type type
,
467 enum scmi_pinctrl_conf_type
*config_type
,
471 struct scmi_msg_settings_conf
*tx
;
474 u32 configs_in_chunk
, conf_num
= 0;
476 int max_msg_size
= ph
->hops
->get_max_msg_size(ph
);
478 if (!config_type
|| !config_value
|| type
== FUNCTION_TYPE
)
481 ret
= scmi_pinctrl_validate_id(ph
, selector
, type
);
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
;
490 ret
= ph
->xops
->xfer_get_init(ph
, PINCTRL_SETTINGS_CONFIGURE
,
492 chunk
* 2 * sizeof(__le32
), 0, &t
);
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
);
503 for (i
= 0; i
< chunk
; i
++) {
505 cpu_to_le32(config_type
[conf_num
+ i
]);
506 tx
->configs
[i
* 2 + 1] =
507 cpu_to_le32(config_value
[conf_num
+ i
]);
510 ret
= ph
->xops
->do_xfer(ph
, t
);
512 ph
->xops
->xfer_put(ph
, t
);
523 static int scmi_pinctrl_function_select(const struct scmi_protocol_handle
*ph
,
525 enum scmi_pinctrl_selector_type type
,
530 struct scmi_msg_settings_conf
*tx
;
533 ret
= scmi_pinctrl_validate_id(ph
, group
, type
);
537 ret
= ph
->xops
->xfer_get_init(ph
, PINCTRL_SETTINGS_CONFIGURE
,
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
);
548 ret
= ph
->xops
->do_xfer(ph
, t
);
549 ph
->xops
->xfer_put(ph
, t
);
554 static int scmi_pinctrl_request_free(const struct scmi_protocol_handle
*ph
,
556 enum scmi_pinctrl_selector_type type
,
557 enum scmi_pinctrl_protocol_cmd cmd
)
561 struct scmi_msg_request
*tx
;
563 if (type
== FUNCTION_TYPE
)
566 if (cmd
!= PINCTRL_REQUEST
&& cmd
!= PINCTRL_RELEASE
)
569 ret
= scmi_pinctrl_validate_id(ph
, identifier
, type
);
573 ret
= ph
->xops
->xfer_get_init(ph
, cmd
, sizeof(*tx
), 0, &t
);
578 tx
->identifier
= cpu_to_le32(identifier
);
579 tx
->flags
= cpu_to_le32(type
);
581 ret
= ph
->xops
->do_xfer(ph
, t
);
582 ph
->xops
->xfer_put(ph
, t
);
587 static int scmi_pinctrl_pin_request(const struct scmi_protocol_handle
*ph
,
590 return scmi_pinctrl_request_free(ph
, pin
, PIN_TYPE
, PINCTRL_REQUEST
);
593 static int scmi_pinctrl_pin_free(const struct scmi_protocol_handle
*ph
, u32 pin
)
595 return scmi_pinctrl_request_free(ph
, pin
, PIN_TYPE
, PINCTRL_RELEASE
);
598 static int scmi_pinctrl_get_group_info(const struct scmi_protocol_handle
*ph
,
600 struct scmi_group_info
*group
)
604 ret
= scmi_pinctrl_attributes(ph
, GROUP_TYPE
, selector
, group
->name
,
609 if (!group
->nr_pins
) {
610 dev_err(ph
->dev
, "Group %d has 0 elements", selector
);
614 group
->group_pins
= kmalloc_array(group
->nr_pins
,
615 sizeof(*group
->group_pins
),
617 if (!group
->group_pins
)
620 ret
= scmi_pinctrl_list_associations(ph
, selector
, GROUP_TYPE
,
621 group
->nr_pins
, group
->group_pins
);
623 kfree(group
->group_pins
);
627 group
->present
= true;
631 static int scmi_pinctrl_get_group_name(const struct scmi_protocol_handle
*ph
,
632 u32 selector
, const char **name
)
634 struct scmi_pinctrl_info
*pi
= ph
->get_priv(ph
);
639 if (selector
>= pi
->nr_groups
|| pi
->nr_groups
== 0)
642 if (!pi
->groups
[selector
].present
) {
645 ret
= scmi_pinctrl_get_group_info(ph
, selector
,
646 &pi
->groups
[selector
]);
651 *name
= pi
->groups
[selector
].name
;
656 static int scmi_pinctrl_group_pins_get(const struct scmi_protocol_handle
*ph
,
657 u32 selector
, const u32
**pins
,
660 struct scmi_pinctrl_info
*pi
= ph
->get_priv(ph
);
662 if (!pins
|| !nr_pins
)
665 if (selector
>= pi
->nr_groups
|| pi
->nr_groups
== 0)
668 if (!pi
->groups
[selector
].present
) {
671 ret
= scmi_pinctrl_get_group_info(ph
, selector
,
672 &pi
->groups
[selector
]);
677 *pins
= pi
->groups
[selector
].group_pins
;
678 *nr_pins
= pi
->groups
[selector
].nr_pins
;
683 static int scmi_pinctrl_get_function_info(const struct scmi_protocol_handle
*ph
,
685 struct scmi_function_info
*func
)
689 ret
= scmi_pinctrl_attributes(ph
, FUNCTION_TYPE
, selector
, func
->name
,
694 if (!func
->nr_groups
) {
695 dev_err(ph
->dev
, "Function %d has 0 elements", selector
);
699 func
->groups
= kmalloc_array(func
->nr_groups
, sizeof(*func
->groups
),
704 ret
= scmi_pinctrl_list_associations(ph
, selector
, FUNCTION_TYPE
,
705 func
->nr_groups
, func
->groups
);
711 func
->present
= true;
715 static int scmi_pinctrl_get_function_name(const struct scmi_protocol_handle
*ph
,
716 u32 selector
, const char **name
)
718 struct scmi_pinctrl_info
*pi
= ph
->get_priv(ph
);
723 if (selector
>= pi
->nr_functions
|| pi
->nr_functions
== 0)
726 if (!pi
->functions
[selector
].present
) {
729 ret
= scmi_pinctrl_get_function_info(ph
, selector
,
730 &pi
->functions
[selector
]);
735 *name
= pi
->functions
[selector
].name
;
740 scmi_pinctrl_function_groups_get(const struct scmi_protocol_handle
*ph
,
741 u32 selector
, u32
*nr_groups
,
744 struct scmi_pinctrl_info
*pi
= ph
->get_priv(ph
);
746 if (!groups
|| !nr_groups
)
749 if (selector
>= pi
->nr_functions
|| pi
->nr_functions
== 0)
752 if (!pi
->functions
[selector
].present
) {
755 ret
= scmi_pinctrl_get_function_info(ph
, selector
,
756 &pi
->functions
[selector
]);
761 *groups
= pi
->functions
[selector
].groups
;
762 *nr_groups
= pi
->functions
[selector
].nr_groups
;
767 static int scmi_pinctrl_mux_set(const struct scmi_protocol_handle
*ph
,
768 u32 selector
, u32 group
)
770 return scmi_pinctrl_function_select(ph
, group
, GROUP_TYPE
, selector
);
773 static int scmi_pinctrl_get_pin_info(const struct scmi_protocol_handle
*ph
,
774 u32 selector
, struct scmi_pin_info
*pin
)
781 ret
= scmi_pinctrl_attributes(ph
, PIN_TYPE
, selector
, pin
->name
, NULL
);
789 static int scmi_pinctrl_get_pin_name(const struct scmi_protocol_handle
*ph
,
790 u32 selector
, const char **name
)
792 struct scmi_pinctrl_info
*pi
= ph
->get_priv(ph
);
797 if (selector
>= pi
->nr_pins
)
800 if (!pi
->pins
[selector
].present
) {
803 ret
= scmi_pinctrl_get_pin_info(ph
, selector
, &pi
->pins
[selector
]);
808 *name
= pi
->pins
[selector
].name
;
813 static int scmi_pinctrl_name_get(const struct scmi_protocol_handle
*ph
,
815 enum scmi_pinctrl_selector_type type
,
820 return scmi_pinctrl_get_pin_name(ph
, selector
, name
);
822 return scmi_pinctrl_get_group_name(ph
, selector
, name
);
824 return scmi_pinctrl_get_function_name(ph
, selector
, name
);
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
,
843 static int scmi_pinctrl_protocol_init(const struct scmi_protocol_handle
*ph
)
847 struct scmi_pinctrl_info
*pinfo
;
849 ret
= ph
->xops
->version_get(ph
, &version
);
853 dev_dbg(ph
->dev
, "Pinctrl Version %d.%d\n",
854 PROTOCOL_REV_MAJOR(version
), PROTOCOL_REV_MINOR(version
));
856 pinfo
= devm_kzalloc(ph
->dev
, sizeof(*pinfo
), GFP_KERNEL
);
860 ret
= scmi_pinctrl_attributes_get(ph
, pinfo
);
864 pinfo
->pins
= devm_kcalloc(ph
->dev
, pinfo
->nr_pins
,
865 sizeof(*pinfo
->pins
), GFP_KERNEL
);
869 pinfo
->groups
= devm_kcalloc(ph
->dev
, pinfo
->nr_groups
,
870 sizeof(*pinfo
->groups
), GFP_KERNEL
);
874 pinfo
->functions
= devm_kcalloc(ph
->dev
, pinfo
->nr_functions
,
875 sizeof(*pinfo
->functions
), GFP_KERNEL
);
876 if (!pinfo
->functions
)
879 pinfo
->version
= version
;
881 return ph
->set_priv(ph
, pinfo
, version
);
884 static int scmi_pinctrl_protocol_deinit(const struct scmi_protocol_handle
*ph
)
887 struct scmi_pinctrl_info
*pi
= ph
->get_priv(ph
);
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;
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;
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
,
917 DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(pinctrl
, scmi_pinctrl
)