Merge tag 'tpm-master-28012025' of https://source.denx.de/u-boot/custodians/u-boot-tpm
[u-boot.git] / cmd / scmi.c
blobcfbca63e1644e387dd80e1a445301eff39ec68b5
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * SCMI (System Control and Management Interface) utility command
5 * Copyright (c) 2023 Linaro Limited
6 * Author: AKASHI Takahiro
7 */
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>
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"},
34 /**
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");
45 return NULL;
48 return agent;
51 /**
52 * get_base_proto() - get SCMI base protocol device
53 * @agent: SCMI agent device
55 * Return: Pointer to SCMI base protocol device on success,
56 * NULL on failure
58 static struct udevice *get_base_proto(struct udevice *agent)
60 struct udevice *base_proto;
62 if (!agent) {
63 agent = get_agent();
64 if (!agent)
65 return NULL;
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;
74 return base_proto;
77 /**
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)
88 int i;
90 for (i = 0; i < ARRAY_SIZE(protocol_name); i++)
91 if (id == protocol_name[i].id)
92 return protocol_name[i].name;
94 return NULL;
97 /**
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,
111 char * const argv[])
113 struct udevice *agent, *base_proto;
114 u32 agent_id, num_protocols;
115 u8 *agent_name, *protocols;
116 int i, ret;
118 if (argc != 1)
119 return CMD_RET_USAGE;
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;
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;
140 printf(" %c%2d: %s\n", i == scmi_agent_id(agent) ? '>' : ' ',
141 i, agent_name);
142 free(agent_name);
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));
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,
170 char * const argv[])
172 u32 agent_id, device_id, flags, attributes;
173 char *end;
174 struct udevice *base_proto;
175 int ret;
177 if (argc != 4)
178 return CMD_RET_USAGE;
180 agent_id = simple_strtoul(argv[1], &end, 16);
181 if (*end != '\0')
182 return CMD_RET_USAGE;
184 device_id = simple_strtoul(argv[2], &end, 16);
185 if (*end != '\0')
186 return CMD_RET_USAGE;
188 flags = simple_strtoul(argv[3], &end, 16);
189 if (*end != '\0')
190 return CMD_RET_USAGE;
192 base_proto = get_base_proto(NULL);
193 if (!base_proto)
194 return CMD_RET_FAILURE;
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;
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;
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,
228 char * const argv[])
230 u32 agent_id, device_id, protocol_id, flags, attributes;
231 char *end;
232 struct udevice *base_proto;
233 int ret;
235 if (argc != 5)
236 return CMD_RET_USAGE;
238 agent_id = simple_strtoul(argv[1], &end, 16);
239 if (*end != '\0')
240 return CMD_RET_USAGE;
242 device_id = simple_strtoul(argv[2], &end, 16);
243 if (*end != '\0')
244 return CMD_RET_USAGE;
246 protocol_id = simple_strtoul(argv[3], &end, 16);
247 if (*end != '\0')
248 return CMD_RET_USAGE;
250 flags = simple_strtoul(argv[4], &end, 16);
251 if (*end != '\0')
252 return CMD_RET_USAGE;
254 base_proto = get_base_proto(NULL);
255 if (!base_proto)
256 return CMD_RET_FAILURE;
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;
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;
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,
292 char * const argv[])
294 u32 agent_id, flags, attributes;
295 char *end;
296 struct udevice *base_proto;
297 int ret;
299 if (argc != 3)
300 return CMD_RET_USAGE;
302 agent_id = simple_strtoul(argv[1], &end, 16);
303 if (*end != '\0')
304 return CMD_RET_USAGE;
306 flags = simple_strtoul(argv[2], &end, 16);
307 if (*end != '\0')
308 return CMD_RET_USAGE;
310 base_proto = get_base_proto(NULL);
311 if (!base_proto)
312 return CMD_RET_FAILURE;
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;
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;
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[])
358 struct cmd_tbl *cp;
360 if (argc < 2)
361 return CMD_RET_USAGE;
363 argc--; argv++;
365 cp = find_cmd_tbl(argv[0], cmd_scmi_sub, ARRAY_SIZE(cmd_scmi_sub));
366 if (!cp)
367 return CMD_RET_USAGE;
369 return cp->cmd(cmdtp, flag, argc, argv);
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");
382 U_BOOT_CMD(scmi, CONFIG_SYS_MAXARGS, 0, do_scmi, "SCMI utility",
383 scmi_help_text);