]> Git Repo - J-u-boot.git/blob - cmd/scmi.c
Merge tag 'u-boot-stm32-20241017' of https://source.denx.de/u-boot/custodians/u-boot-stm
[J-u-boot.git] / cmd / scmi.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  *  SCMI (System Control and Management Interface) utility command
4  *
5  *  Copyright (c) 2023 Linaro Limited
6  *              Author: AKASHI Takahiro
7  */
8
9 #include <command.h>
10 #include <exports.h>
11 #include <scmi_agent.h>
12 #include <scmi_agent-uclass.h>
13 #include <stdlib.h>
14 #include <asm/types.h>
15 #include <dm/device.h>
16 #include <dm/uclass.h> /* uclass_get_device */
17 #include <linux/bitfield.h>
18 #include <linux/bitops.h>
19
20 struct {
21         enum scmi_std_protocol id;
22         const char *name;
23 } protocol_name[] = {
24         {SCMI_PROTOCOL_ID_BASE, "Base"},
25         {SCMI_PROTOCOL_ID_POWER_DOMAIN, "Power domain management"},
26         {SCMI_PROTOCOL_ID_SYSTEM, "System power management"},
27         {SCMI_PROTOCOL_ID_PERF, "Performance domain management"},
28         {SCMI_PROTOCOL_ID_CLOCK, "Clock management"},
29         {SCMI_PROTOCOL_ID_SENSOR, "Sensor management"},
30         {SCMI_PROTOCOL_ID_RESET_DOMAIN, "Reset domain management"},
31         {SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN, "Voltage domain management"},
32 };
33
34 /**
35  * get_agent() - get SCMI agent device
36  *
37  * Return:      Pointer to SCMI agent device on success, NULL on failure
38  */
39 static struct udevice *get_agent(void)
40 {
41         struct udevice *agent;
42
43         if (uclass_get_device(UCLASS_SCMI_AGENT, 0, &agent)) {
44                 printf("Cannot find any SCMI agent\n");
45                 return NULL;
46         }
47
48         return agent;
49 }
50
51 /**
52  * get_base_proto() - get SCMI base protocol device
53  * @agent:      SCMI agent device
54  *
55  * Return:      Pointer to SCMI base protocol device on success,
56  *              NULL on failure
57  */
58 static struct udevice *get_base_proto(struct udevice *agent)
59 {
60         struct udevice *base_proto;
61
62         if (!agent) {
63                 agent = get_agent();
64                 if (!agent)
65                         return NULL;
66         }
67
68         base_proto = scmi_get_protocol(agent, SCMI_PROTOCOL_ID_BASE);
69         if (!base_proto) {
70                 printf("SCMI base protocol not found\n");
71                 return NULL;
72         }
73
74         return base_proto;
75 }
76
77 /**
78  * get_proto_name() - get the name of SCMI protocol
79  *
80  * @id:         SCMI Protocol ID
81  *
82  * Get the printable name of the protocol, @id
83  *
84  * Return:      Name string on success, NULL on failure
85  */
86 static const char *get_proto_name(enum scmi_std_protocol id)
87 {
88         int i;
89
90         for (i = 0; i < ARRAY_SIZE(protocol_name); i++)
91                 if (id == protocol_name[i].id)
92                         return protocol_name[i].name;
93
94         return NULL;
95 }
96
97 /**
98  * do_scmi_info() - get the information of SCMI services
99  *
100  * @cmdtp:      Command table
101  * @flag:       Command flag
102  * @argc:       Number of arguments
103  * @argv:       Argument array
104  *
105  * Get the information of SCMI services using various interfaces
106  * provided by the Base protocol.
107  *
108  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
109  */
110 static int do_scmi_info(struct cmd_tbl *cmdtp, int flag, int argc,
111                         char * const argv[])
112 {
113         struct udevice *agent, *base_proto;
114         u32 agent_id, num_protocols;
115         u8 *agent_name, *protocols;
116         int i, ret;
117
118         if (argc != 1)
119                 return CMD_RET_USAGE;
120
121         agent = get_agent();
122         if (!agent)
123                 return CMD_RET_FAILURE;
124         base_proto = get_base_proto(agent);
125         if (!base_proto)
126                 return CMD_RET_FAILURE;
127
128         printf("SCMI device: %s\n", agent->name);
129         printf("  protocol version: 0x%x\n", scmi_version(agent));
130         printf("  # of agents: %d\n", scmi_num_agents(agent));
131         for (i = 0; i < scmi_num_agents(agent); i++) {
132                 ret = scmi_base_discover_agent(base_proto, i, &agent_id,
133                                                &agent_name);
134                 if (ret) {
135                         if (ret != -EOPNOTSUPP)
136                                 printf("base_discover_agent() failed for id: %d (%d)\n",
137                                        i, ret);
138                         break;
139                 }
140                 printf("    %c%2d: %s\n", i == scmi_agent_id(agent) ? '>' : ' ',
141                        i, agent_name);
142                 free(agent_name);
143         }
144         printf("  # of protocols: %d\n", scmi_num_protocols(agent));
145         num_protocols = scmi_num_protocols(agent);
146         protocols = scmi_protocols(agent);
147         if (protocols)
148                 for (i = 0; i < num_protocols; i++)
149                         printf("      %s\n", get_proto_name(protocols[i]));
150         printf("  vendor: %s\n", scmi_vendor(agent));
151         printf("  sub vendor: %s\n", scmi_sub_vendor(agent));
152         printf("  impl version: 0x%x\n", scmi_impl_version(agent));
153
154         return CMD_RET_SUCCESS;
155 }
156
157 /**
158  * do_scmi_set_dev() - set access permission to device
159  *
160  * @cmdtp:      Command table
161  * @flag:       Command flag
162  * @argc:       Number of arguments
163  * @argv:       Argument array
164  *
165  * Set access permission to device with SCMI_BASE_SET_DEVICE_PERMISSIONS
166  *
167  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
168  */
169 static int do_scmi_set_dev(struct cmd_tbl *cmdtp, int flag, int argc,
170                            char * const argv[])
171 {
172         u32 agent_id, device_id, flags, attributes;
173         char *end;
174         struct udevice *base_proto;
175         int ret;
176
177         if (argc != 4)
178                 return CMD_RET_USAGE;
179
180         agent_id = simple_strtoul(argv[1], &end, 16);
181         if (*end != '\0')
182                 return CMD_RET_USAGE;
183
184         device_id = simple_strtoul(argv[2], &end, 16);
185         if (*end != '\0')
186                 return CMD_RET_USAGE;
187
188         flags = simple_strtoul(argv[3], &end, 16);
189         if (*end != '\0')
190                 return CMD_RET_USAGE;
191
192         base_proto = get_base_proto(NULL);
193         if (!base_proto)
194                 return CMD_RET_FAILURE;
195
196         ret = scmi_base_protocol_message_attrs(base_proto,
197                                                SCMI_BASE_SET_DEVICE_PERMISSIONS,
198                                                &attributes);
199         if (ret) {
200                 printf("This operation is not supported\n");
201                 return CMD_RET_FAILURE;
202         }
203
204         ret = scmi_base_set_device_permissions(base_proto, agent_id,
205                                                device_id, flags);
206         if (ret) {
207                 printf("%s access to device:%u failed (%d)\n",
208                        flags ? "Allowing" : "Denying", device_id, ret);
209                 return CMD_RET_FAILURE;
210         }
211
212         return CMD_RET_SUCCESS;
213 }
214
215 /**
216  * do_scmi_set_proto() - set protocol permission to device
217  *
218  * @cmdtp:      Command table
219  * @flag:       Command flag
220  * @argc:       Number of arguments
221  * @argv:       Argument array
222  *
223  * Set protocol permission to device with SCMI_BASE_SET_PROTOCOL_PERMISSIONS
224  *
225  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
226  */
227 static int do_scmi_set_proto(struct cmd_tbl *cmdtp, int flag, int argc,
228                              char * const argv[])
229 {
230         u32 agent_id, device_id, protocol_id, flags, attributes;
231         char *end;
232         struct udevice *base_proto;
233         int ret;
234
235         if (argc != 5)
236                 return CMD_RET_USAGE;
237
238         agent_id = simple_strtoul(argv[1], &end, 16);
239         if (*end != '\0')
240                 return CMD_RET_USAGE;
241
242         device_id = simple_strtoul(argv[2], &end, 16);
243         if (*end != '\0')
244                 return CMD_RET_USAGE;
245
246         protocol_id = simple_strtoul(argv[3], &end, 16);
247         if (*end != '\0')
248                 return CMD_RET_USAGE;
249
250         flags = simple_strtoul(argv[4], &end, 16);
251         if (*end != '\0')
252                 return CMD_RET_USAGE;
253
254         base_proto = get_base_proto(NULL);
255         if (!base_proto)
256                 return CMD_RET_FAILURE;
257
258         ret = scmi_base_protocol_message_attrs(base_proto,
259                                                SCMI_BASE_SET_PROTOCOL_PERMISSIONS,
260                                                &attributes);
261         if (ret) {
262                 printf("This operation is not supported\n");
263                 return CMD_RET_FAILURE;
264         }
265
266         ret = scmi_base_set_protocol_permissions(base_proto, agent_id,
267                                                  device_id, protocol_id,
268                                                  flags);
269         if (ret) {
270                 printf("%s access to protocol:0x%x on device:%u failed (%d)\n",
271                        flags ? "Allowing" : "Denying", protocol_id, device_id,
272                        ret);
273                 return CMD_RET_FAILURE;
274         }
275
276         return CMD_RET_SUCCESS;
277 }
278
279 /**
280  * do_scmi_reset() - reset platform resource settings
281  *
282  * @cmdtp:      Command table
283  * @flag:       Command flag
284  * @argc:       Number of arguments
285  * @argv:       Argument array
286  *
287  * Reset platform resource settings with BASE_RESET_AGENT_CONFIGURATION
288  *
289  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
290  */
291 static int do_scmi_reset(struct cmd_tbl *cmdtp, int flag, int argc,
292                          char * const argv[])
293 {
294         u32 agent_id, flags, attributes;
295         char *end;
296         struct udevice *base_proto;
297         int ret;
298
299         if (argc != 3)
300                 return CMD_RET_USAGE;
301
302         agent_id = simple_strtoul(argv[1], &end, 16);
303         if (*end != '\0')
304                 return CMD_RET_USAGE;
305
306         flags = simple_strtoul(argv[2], &end, 16);
307         if (*end != '\0')
308                 return CMD_RET_USAGE;
309
310         base_proto = get_base_proto(NULL);
311         if (!base_proto)
312                 return CMD_RET_FAILURE;
313
314         ret = scmi_base_protocol_message_attrs(base_proto,
315                                                SCMI_BASE_RESET_AGENT_CONFIGURATION,
316                                                &attributes);
317         if (ret) {
318                 printf("Reset is not supported\n");
319                 return CMD_RET_FAILURE;
320         }
321
322         ret = scmi_base_reset_agent_configuration(base_proto, agent_id, flags);
323         if (ret) {
324                 printf("Reset failed (%d)\n", ret);
325                 return CMD_RET_FAILURE;
326         }
327
328         return CMD_RET_SUCCESS;
329 }
330
331 static struct cmd_tbl cmd_scmi_sub[] = {
332         U_BOOT_CMD_MKENT(info, CONFIG_SYS_MAXARGS, 1,
333                          do_scmi_info, "", ""),
334         U_BOOT_CMD_MKENT(perm_dev, CONFIG_SYS_MAXARGS, 1,
335                          do_scmi_set_dev, "", ""),
336         U_BOOT_CMD_MKENT(perm_proto, CONFIG_SYS_MAXARGS, 1,
337                          do_scmi_set_proto, "", ""),
338         U_BOOT_CMD_MKENT(reset, CONFIG_SYS_MAXARGS, 1,
339                          do_scmi_reset, "", ""),
340 };
341
342 /**
343  * do_scmi() - SCMI utility
344  *
345  * @cmdtp:      Command table
346  * @flag:       Command flag
347  * @argc:       Number of arguments
348  * @argv:       Argument array
349  *
350  * Provide user interfaces to SCMI protocols.
351  *
352  * Return:      CMD_RET_SUCCESS on success,
353  *              CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
354  */
355 static int do_scmi(struct cmd_tbl *cmdtp, int flag,
356                    int argc, char *const argv[])
357 {
358         struct cmd_tbl *cp;
359
360         if (argc < 2)
361                 return CMD_RET_USAGE;
362
363         argc--; argv++;
364
365         cp = find_cmd_tbl(argv[0], cmd_scmi_sub, ARRAY_SIZE(cmd_scmi_sub));
366         if (!cp)
367                 return CMD_RET_USAGE;
368
369         return cp->cmd(cmdtp, flag, argc, argv);
370 }
371
372 U_BOOT_LONGHELP(scmi,
373         " - SCMI utility\n"
374         " info - get the info of SCMI services\n"
375         " perm_dev <agent-id in hex> <device-id in hex> <flags in hex>\n"
376         "   - set access permission to device\n"
377         " perm_proto <agent-id in hex> <device-id in hex> <protocol-id in hex> <flags in hex>\n"
378         "   - set protocol permission to device\n"
379         " reset <agent-id in hex> <flags in hex>\n"
380         "   - reset platform resource settings\n");
381
382 U_BOOT_CMD(scmi, CONFIG_SYS_MAXARGS, 0, do_scmi, "SCMI utility",
383            scmi_help_text);
This page took 0.046252 seconds and 4 git commands to generate.