1 // SPDX-License-Identifier: GPL-2.0+
3 * SCMI (System Control and Management Interface) utility command
5 * Copyright (c) 2023 Linaro Limited
6 * Author: AKASHI Takahiro
11 #include <scmi_agent.h>
12 #include <scmi_agent-uclass.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>
21 enum scmi_std_protocol id
;
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"},
35 * get_agent() - get SCMI agent device
37 * Return: Pointer to SCMI agent device on success, NULL on failure
39 static struct udevice
*get_agent(void)
41 struct udevice
*agent
;
43 if (uclass_get_device(UCLASS_SCMI_AGENT
, 0, &agent
)) {
44 printf("Cannot find any SCMI agent\n");
52 * get_base_proto() - get SCMI base protocol device
53 * @agent: SCMI agent device
55 * Return: Pointer to SCMI base protocol device on success,
58 static struct udevice
*get_base_proto(struct udevice
*agent
)
60 struct udevice
*base_proto
;
68 base_proto
= scmi_get_protocol(agent
, SCMI_PROTOCOL_ID_BASE
);
70 printf("SCMI base protocol not found\n");
78 * get_proto_name() - get the name of SCMI protocol
80 * @id: SCMI Protocol ID
82 * Get the printable name of the protocol, @id
84 * Return: Name string on success, NULL on failure
86 static const char *get_proto_name(enum scmi_std_protocol id
)
90 for (i
= 0; i
< ARRAY_SIZE(protocol_name
); i
++)
91 if (id
== protocol_name
[i
].id
)
92 return protocol_name
[i
].name
;
98 * do_scmi_info() - get the information of SCMI services
100 * @cmdtp: Command table
101 * @flag: Command flag
102 * @argc: Number of arguments
103 * @argv: Argument array
105 * Get the information of SCMI services using various interfaces
106 * provided by the Base protocol.
108 * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
110 static int do_scmi_info(struct cmd_tbl
*cmdtp
, int flag
, int argc
,
113 struct udevice
*agent
, *base_proto
;
114 u32 agent_id
, num_protocols
;
115 u8
*agent_name
, *protocols
;
119 return CMD_RET_USAGE
;
123 return CMD_RET_FAILURE
;
124 base_proto
= get_base_proto(agent
);
126 return CMD_RET_FAILURE
;
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
,
135 if (ret
!= -EOPNOTSUPP
)
136 printf("base_discover_agent() failed for id: %d (%d)\n",
140 printf(" %c%2d: %s\n", i
== scmi_agent_id(agent
) ? '>' : ' ',
144 printf(" # of protocols: %d\n", scmi_num_protocols(agent
));
145 num_protocols
= scmi_num_protocols(agent
);
146 protocols
= scmi_protocols(agent
);
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
));
154 return CMD_RET_SUCCESS
;
158 * do_scmi_set_dev() - set access permission to device
160 * @cmdtp: Command table
161 * @flag: Command flag
162 * @argc: Number of arguments
163 * @argv: Argument array
165 * Set access permission to device with SCMI_BASE_SET_DEVICE_PERMISSIONS
167 * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
169 static int do_scmi_set_dev(struct cmd_tbl
*cmdtp
, int flag
, int argc
,
172 u32 agent_id
, device_id
, flags
, attributes
;
174 struct udevice
*base_proto
;
178 return CMD_RET_USAGE
;
180 agent_id
= simple_strtoul(argv
[1], &end
, 16);
182 return CMD_RET_USAGE
;
184 device_id
= simple_strtoul(argv
[2], &end
, 16);
186 return CMD_RET_USAGE
;
188 flags
= simple_strtoul(argv
[3], &end
, 16);
190 return CMD_RET_USAGE
;
192 base_proto
= get_base_proto(NULL
);
194 return CMD_RET_FAILURE
;
196 ret
= scmi_base_protocol_message_attrs(base_proto
,
197 SCMI_BASE_SET_DEVICE_PERMISSIONS
,
200 printf("This operation is not supported\n");
201 return CMD_RET_FAILURE
;
204 ret
= scmi_base_set_device_permissions(base_proto
, agent_id
,
207 printf("%s access to device:%u failed (%d)\n",
208 flags
? "Allowing" : "Denying", device_id
, ret
);
209 return CMD_RET_FAILURE
;
212 return CMD_RET_SUCCESS
;
216 * do_scmi_set_proto() - set protocol permission to device
218 * @cmdtp: Command table
219 * @flag: Command flag
220 * @argc: Number of arguments
221 * @argv: Argument array
223 * Set protocol permission to device with SCMI_BASE_SET_PROTOCOL_PERMISSIONS
225 * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
227 static int do_scmi_set_proto(struct cmd_tbl
*cmdtp
, int flag
, int argc
,
230 u32 agent_id
, device_id
, protocol_id
, flags
, attributes
;
232 struct udevice
*base_proto
;
236 return CMD_RET_USAGE
;
238 agent_id
= simple_strtoul(argv
[1], &end
, 16);
240 return CMD_RET_USAGE
;
242 device_id
= simple_strtoul(argv
[2], &end
, 16);
244 return CMD_RET_USAGE
;
246 protocol_id
= simple_strtoul(argv
[3], &end
, 16);
248 return CMD_RET_USAGE
;
250 flags
= simple_strtoul(argv
[4], &end
, 16);
252 return CMD_RET_USAGE
;
254 base_proto
= get_base_proto(NULL
);
256 return CMD_RET_FAILURE
;
258 ret
= scmi_base_protocol_message_attrs(base_proto
,
259 SCMI_BASE_SET_PROTOCOL_PERMISSIONS
,
262 printf("This operation is not supported\n");
263 return CMD_RET_FAILURE
;
266 ret
= scmi_base_set_protocol_permissions(base_proto
, agent_id
,
267 device_id
, protocol_id
,
270 printf("%s access to protocol:0x%x on device:%u failed (%d)\n",
271 flags
? "Allowing" : "Denying", protocol_id
, device_id
,
273 return CMD_RET_FAILURE
;
276 return CMD_RET_SUCCESS
;
280 * do_scmi_reset() - reset platform resource settings
282 * @cmdtp: Command table
283 * @flag: Command flag
284 * @argc: Number of arguments
285 * @argv: Argument array
287 * Reset platform resource settings with BASE_RESET_AGENT_CONFIGURATION
289 * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
291 static int do_scmi_reset(struct cmd_tbl
*cmdtp
, int flag
, int argc
,
294 u32 agent_id
, flags
, attributes
;
296 struct udevice
*base_proto
;
300 return CMD_RET_USAGE
;
302 agent_id
= simple_strtoul(argv
[1], &end
, 16);
304 return CMD_RET_USAGE
;
306 flags
= simple_strtoul(argv
[2], &end
, 16);
308 return CMD_RET_USAGE
;
310 base_proto
= get_base_proto(NULL
);
312 return CMD_RET_FAILURE
;
314 ret
= scmi_base_protocol_message_attrs(base_proto
,
315 SCMI_BASE_RESET_AGENT_CONFIGURATION
,
318 printf("Reset is not supported\n");
319 return CMD_RET_FAILURE
;
322 ret
= scmi_base_reset_agent_configuration(base_proto
, agent_id
, flags
);
324 printf("Reset failed (%d)\n", ret
);
325 return CMD_RET_FAILURE
;
328 return CMD_RET_SUCCESS
;
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
, "", ""),
343 * do_scmi() - SCMI utility
345 * @cmdtp: Command table
346 * @flag: Command flag
347 * @argc: Number of arguments
348 * @argv: Argument array
350 * Provide user interfaces to SCMI protocols.
352 * Return: CMD_RET_SUCCESS on success,
353 * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
355 static int do_scmi(struct cmd_tbl
*cmdtp
, int flag
,
356 int argc
, char *const argv
[])
361 return CMD_RET_USAGE
;
365 cp
= find_cmd_tbl(argv
[0], cmd_scmi_sub
, ARRAY_SIZE(cmd_scmi_sub
));
367 return CMD_RET_USAGE
;
369 return cp
->cmd(cmdtp
, flag
, argc
, argv
);
372 U_BOOT_LONGHELP(scmi
,
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");
382 U_BOOT_CMD(scmi
, CONFIG_SYS_MAXARGS
, 0, do_scmi
, "SCMI utility",