blob: 78ee2ffd2daeae7a0fcd81f708bffd910619e95c [file] [log] [blame]
AKASHI Takahirod1ce56a2023-10-11 19:07:00 +09001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * SCMI Base protocol as U-Boot device
4 *
5 * Copyright (C) 2023 Linaro Limited
6 * author: AKASHI Takahiro <takahiro.akashi@linaro.org>
7 */
8
AKASHI Takahirod1ce56a2023-10-11 19:07:00 +09009#include <dm.h>
10#include <scmi_agent.h>
11#include <scmi_protocols.h>
12#include <stdlib.h>
13#include <string.h>
14#include <asm/types.h>
15#include <dm/device_compat.h>
16#include <linux/kernel.h>
17
18/**
19 * scmi_generic_protocol_version - get protocol version
20 * @dev: SCMI device
21 * @id: SCMI protocol ID
22 * @version: Pointer to SCMI protocol version
23 *
24 * Obtain the protocol version number in @version.
25 *
26 * Return: 0 on success, error code on failure
27 */
28int scmi_generic_protocol_version(struct udevice *dev,
29 enum scmi_std_protocol id, u32 *version)
30{
31 struct scmi_protocol_version_out out;
32 struct scmi_msg msg = {
33 .protocol_id = id,
34 .message_id = SCMI_PROTOCOL_VERSION,
35 .out_msg = (u8 *)&out,
36 .out_msg_sz = sizeof(out),
37 };
38 int ret;
39
40 ret = devm_scmi_process_msg(dev, &msg);
41 if (ret)
42 return ret;
43 if (out.status)
44 return scmi_to_linux_errno(out.status);
45
46 *version = out.version;
47
48 return 0;
49}
50
51/**
52 * scmi_base_protocol_version_int - get Base protocol version
53 * @dev: SCMI device
54 * @version: Pointer to SCMI protocol version
55 *
56 * Obtain the protocol version number in @version for Base protocol.
57 *
58 * Return: 0 on success, error code on failure
59 */
60static int scmi_base_protocol_version_int(struct udevice *dev, u32 *version)
61{
62 return scmi_generic_protocol_version(dev, SCMI_PROTOCOL_ID_BASE,
63 version);
64}
65
66/**
67 * scmi_protocol_attrs_int - get protocol attributes
68 * @dev: SCMI device
69 * @num_agents: Number of SCMI agents
70 * @num_protocols: Number of SCMI protocols
71 *
72 * Obtain the protocol attributes, the number of agents and the number
73 * of protocols, in @num_agents and @num_protocols respectively, that
74 * the device provides.
75 *
76 * Return: 0 on success, error code on failure
77 */
78static int scmi_protocol_attrs_int(struct udevice *dev, u32 *num_agents,
79 u32 *num_protocols)
80{
81 struct scmi_protocol_attrs_out out;
82 struct scmi_msg msg = {
83 .protocol_id = SCMI_PROTOCOL_ID_BASE,
84 .message_id = SCMI_PROTOCOL_ATTRIBUTES,
85 .out_msg = (u8 *)&out,
86 .out_msg_sz = sizeof(out),
87 };
88 int ret;
89
90 ret = devm_scmi_process_msg(dev, &msg);
91 if (ret)
92 return ret;
93 if (out.status)
94 return scmi_to_linux_errno(out.status);
95
96 *num_agents = SCMI_PROTOCOL_ATTRS_NUM_AGENTS(out.attributes);
97 *num_protocols = SCMI_PROTOCOL_ATTRS_NUM_PROTOCOLS(out.attributes);
98
99 return 0;
100}
101
102/**
103 * scmi_protocol_message_attrs_int - get message-specific attributes
104 * @dev: SCMI device
105 * @message_id: SCMI message ID
106 * @attributes: Message-specific attributes
107 *
108 * Obtain the message-specific attributes in @attributes.
109 * This command succeeds if the message is implemented and available.
110 *
111 * Return: 0 on success, error code on failure
112 */
113static int scmi_protocol_message_attrs_int(struct udevice *dev, u32 message_id,
114 u32 *attributes)
115{
116 struct scmi_protocol_msg_attrs_out out;
117 struct scmi_msg msg = {
118 .protocol_id = SCMI_PROTOCOL_ID_BASE,
119 .message_id = SCMI_PROTOCOL_MESSAGE_ATTRIBUTES,
120 .in_msg = (u8 *)&message_id,
121 .in_msg_sz = sizeof(message_id),
122 .out_msg = (u8 *)&out,
123 .out_msg_sz = sizeof(out),
124 };
125 int ret;
126
127 ret = devm_scmi_process_msg(dev, &msg);
128 if (ret)
129 return ret;
130 if (out.status)
131 return scmi_to_linux_errno(out.status);
132
133 *attributes = out.attributes;
134
135 return 0;
136}
137
138/**
139 * scmi_base_discover_vendor_int - get vendor name
140 * @dev: SCMI device
141 * @vendor: Pointer to vendor name
142 *
143 * Obtain the vendor's name in @vendor.
144 * It is a caller's responsibility to free @vendor.
145 *
146 * Return: 0 on success, error code on failure
147 */
148static int scmi_base_discover_vendor_int(struct udevice *dev, u8 **vendor)
149{
150 struct scmi_base_discover_vendor_out out;
151 struct scmi_msg msg = {
152 .protocol_id = SCMI_PROTOCOL_ID_BASE,
153 .message_id = SCMI_BASE_DISCOVER_VENDOR,
154 .out_msg = (u8 *)&out,
155 .out_msg_sz = sizeof(out),
156 };
157 int ret;
158
159 if (!vendor)
160 return -EINVAL;
161
162 ret = devm_scmi_process_msg(dev, &msg);
163 if (ret)
164 return ret;
165 if (out.status)
166 return scmi_to_linux_errno(out.status);
167
168 *vendor = strdup(out.vendor_identifier);
169 if (!*vendor)
170 return -ENOMEM;
171
172 return 0;
173}
174
175/**
176 * scmi_base_discover_sub_vendor_int - get sub-vendor name
177 * @dev: SCMI device
178 * @sub_vendor: Pointer to sub-vendor name
179 *
180 * Obtain the sub-vendor's name in @sub_vendor.
181 * It is a caller's responsibility to free @sub_vendor.
182 *
183 * Return: 0 on success, error code on failure
184 */
185static int scmi_base_discover_sub_vendor_int(struct udevice *dev,
186 u8 **sub_vendor)
187{
188 struct scmi_base_discover_vendor_out out;
189 struct scmi_msg msg = {
190 .protocol_id = SCMI_PROTOCOL_ID_BASE,
191 .message_id = SCMI_BASE_DISCOVER_SUB_VENDOR,
192 .out_msg = (u8 *)&out,
193 .out_msg_sz = sizeof(out),
194 };
195 int ret;
196
197 if (!sub_vendor)
198 return -EINVAL;
199
200 ret = devm_scmi_process_msg(dev, &msg);
201 if (ret)
202 return ret;
203 if (out.status)
204 return scmi_to_linux_errno(out.status);
205
206 *sub_vendor = strdup(out.vendor_identifier);
207 if (!*sub_vendor)
208 return -ENOMEM;
209
210 return 0;
211}
212
213/**
214 * scmi_base_discover_impl_version_int - get implementation version
215 * @dev: SCMI device
216 * @impl_version: Pointer to implementation version
217 *
218 * Obtain the implementation version number in @impl_version.
219 *
220 * Return: 0 on success, error code on failure
221 */
222static int scmi_base_discover_impl_version_int(struct udevice *dev,
223 u32 *impl_version)
224{
225 struct scmi_base_discover_impl_version_out out;
226 struct scmi_msg msg = {
227 .protocol_id = SCMI_PROTOCOL_ID_BASE,
228 .message_id = SCMI_BASE_DISCOVER_IMPL_VERSION,
229 .out_msg = (u8 *)&out,
230 .out_msg_sz = sizeof(out),
231 };
232 int ret;
233
234 ret = devm_scmi_process_msg(dev, &msg);
235 if (ret)
236 return ret;
237 if (out.status)
238 return scmi_to_linux_errno(out.status);
239
240 *impl_version = out.impl_version;
241
242 return 0;
243}
244
245/**
246 * scmi_base_discover_list_protocols_int - get list of protocols
247 * @dev: SCMI device
248 * @protocols: Pointer to array of SCMI protocols
249 *
250 * Obtain the list of protocols provided in @protocols.
251 * The number of elements in @protocols always match to the number of
252 * protocols returned by smci_protocol_attrs() when this function succeeds.
253 * It is a caller's responsibility to free @protocols.
254 *
255 * Return: the number of protocols in @protocols on success, error code on
256 * failure
257 */
258static int scmi_base_discover_list_protocols_int(struct udevice *dev,
259 u8 **protocols)
260{
Ye Li57fa1632025-04-28 18:37:33 +0800261 struct scmi_base_discover_list_protocols_out *out;
AKASHI Takahirod1ce56a2023-10-11 19:07:00 +0900262 int cur;
263 struct scmi_msg msg = {
264 .protocol_id = SCMI_PROTOCOL_ID_BASE,
265 .message_id = SCMI_BASE_DISCOVER_LIST_PROTOCOLS,
266 .in_msg = (u8 *)&cur,
267 .in_msg_sz = sizeof(cur),
268 .out_msg = (u8 *)&out,
269 .out_msg_sz = sizeof(out),
270 };
Ye Li57fa1632025-04-28 18:37:33 +0800271 u32 num_agents, num_protocols, out_size;
AKASHI Takahirod1ce56a2023-10-11 19:07:00 +0900272 u8 *buf;
273 int i, ret;
274
275 ret = scmi_base_protocol_attrs(dev, &num_agents, &num_protocols);
276 if (ret)
277 return ret;
278
Ye Li57fa1632025-04-28 18:37:33 +0800279 out_size = sizeof(*out) + sizeof(u32) * (1 + num_protocols / 4);
280 out = calloc(1, out_size);
281 if (!out)
282 return -ENOMEM;
283 msg.out_msg = (u8 *)out;
284 msg.out_msg_sz = out_size;
285
AKASHI Takahirod1ce56a2023-10-11 19:07:00 +0900286 buf = calloc(sizeof(u8), num_protocols);
Ye Li57fa1632025-04-28 18:37:33 +0800287 if (!buf) {
288 free(out);
AKASHI Takahirod1ce56a2023-10-11 19:07:00 +0900289 return -ENOMEM;
Ye Li57fa1632025-04-28 18:37:33 +0800290 }
AKASHI Takahirod1ce56a2023-10-11 19:07:00 +0900291
292 cur = 0;
293 do {
294 ret = devm_scmi_process_msg(dev, &msg);
295 if (ret)
296 goto err;
Ye Li57fa1632025-04-28 18:37:33 +0800297 if (out->status) {
298 ret = scmi_to_linux_errno(out->status);
AKASHI Takahirod1ce56a2023-10-11 19:07:00 +0900299 goto err;
300 }
301
Ye Li57fa1632025-04-28 18:37:33 +0800302 for (i = 0; i < out->num_protocols; i++, cur++)
303 buf[cur] = out->protocols[i / 4] >> ((i % 4) * 8);
AKASHI Takahirod1ce56a2023-10-11 19:07:00 +0900304 } while (cur < num_protocols);
305
306 *protocols = buf;
307
308 return num_protocols;
309err:
310 free(buf);
Ye Li57fa1632025-04-28 18:37:33 +0800311 free(out);
AKASHI Takahirod1ce56a2023-10-11 19:07:00 +0900312
313 return ret;
314}
315
316/**
317 * scmi_base_discover_agent_int - identify agent
318 * @dev: SCMI device
319 * @agent_id: SCMI agent ID
320 * @ret_agent_id: Pointer to SCMI agent ID
321 * @name: Pointer to SCMI agent name
322 *
323 * Obtain the agent's name in @name. If @agent_id is equal to 0xffffffff,
324 * this function returns the caller's agent id in @ret_agent_id.
325 * It is a caller's responsibility to free @name.
326 *
327 * Return: 0 on success, error code on failure
328 */
329static int scmi_base_discover_agent_int(struct udevice *dev, u32 agent_id,
330 u32 *ret_agent_id, u8 **name)
331{
332 struct scmi_base_discover_agent_out out;
333 struct scmi_msg msg = {
334 .protocol_id = SCMI_PROTOCOL_ID_BASE,
335 .message_id = SCMI_BASE_DISCOVER_AGENT,
336 .in_msg = (u8 *)&agent_id,
337 .in_msg_sz = sizeof(agent_id),
338 .out_msg = (u8 *)&out,
339 .out_msg_sz = sizeof(out),
340 };
341 int ret;
342
343 ret = devm_scmi_process_msg(dev, &msg);
344 if (ret)
345 return ret;
346 if (out.status)
347 return scmi_to_linux_errno(out.status);
348
349 if (ret_agent_id)
350 *ret_agent_id = out.agent_id;
351 if (name) {
352 *name = strdup(out.name);
353 if (!*name)
354 return -ENOMEM;
355 }
356
357 return 0;
358}
359
360/**
361 * scmi_base_set_device_permissions_int - configure access permission to device
362 * @dev: SCMI device
363 * @agent_id: SCMI agent ID
364 * @device_id: ID of device to access
365 * @flags: A set of flags
366 *
367 * Ask for allowing or denying access permission to the device, @device_id.
368 * The meaning of @flags is defined in SCMI specification.
369 *
370 * Return: 0 on success, error code on failure
371 */
372static int scmi_base_set_device_permissions_int(struct udevice *dev, u32 agent_id,
373 u32 device_id, u32 flags)
374{
375 struct scmi_base_set_device_permissions_in in = {
376 .agent_id = agent_id,
377 .device_id = device_id,
378 .flags = flags,
379 };
380 s32 status;
381 struct scmi_msg msg = {
382 .protocol_id = SCMI_PROTOCOL_ID_BASE,
383 .message_id = SCMI_BASE_SET_DEVICE_PERMISSIONS,
384 .in_msg = (u8 *)&in,
385 .in_msg_sz = sizeof(in),
386 .out_msg = (u8 *)&status,
387 .out_msg_sz = sizeof(status),
388 };
389 int ret;
390
391 ret = devm_scmi_process_msg(dev, &msg);
392 if (ret)
393 return ret;
394 if (status)
395 return scmi_to_linux_errno(status);
396
397 return 0;
398}
399
400/**
401 * scmi_base_set_protocol_permissions_int - configure access permission to
402 * protocol on device
403 * @dev: SCMI device
404 * @agent_id: SCMI agent ID
405 * @device_id: ID of device to access
406 * @command_id: SCMI command ID
407 * @flags: A set of flags
408 *
409 * Ask for allowing or denying access permission to the protocol, @command_id,
410 * on the device, @device_id.
411 * The meaning of @flags is defined in SCMI specification.
412 *
413 * Return: 0 on success, error code on failure
414 */
415static int scmi_base_set_protocol_permissions_int(struct udevice *dev,
416 u32 agent_id, u32 device_id,
417 u32 command_id, u32 flags)
418{
419 struct scmi_base_set_protocol_permissions_in in = {
420 .agent_id = agent_id,
421 .device_id = device_id,
422 .command_id = command_id,
423 .flags = flags,
424 };
425 s32 status;
426 struct scmi_msg msg = {
427 .protocol_id = SCMI_PROTOCOL_ID_BASE,
428 .message_id = SCMI_BASE_SET_PROTOCOL_PERMISSIONS,
429 .in_msg = (u8 *)&in,
430 .in_msg_sz = sizeof(in),
431 .out_msg = (u8 *)&status,
432 .out_msg_sz = sizeof(status),
433 };
434 int ret;
435
436 ret = devm_scmi_process_msg(dev, &msg);
437 if (ret)
438 return ret;
439 if (status)
440 return scmi_to_linux_errno(status);
441
442 return 0;
443}
444
445/**
446 * scmi_base_reset_agent_configuration_int - reset resource settings
447 * @dev: SCMI device
448 * @agent_id: SCMI agent ID
449 * @flags: A set of flags
450 *
451 * Reset all the resource settings against @agent_id.
452 * The meaning of @flags is defined in SCMI specification.
453 *
454 * Return: 0 on success, error code on failure
455 */
456static int scmi_base_reset_agent_configuration_int(struct udevice *dev,
457 u32 agent_id, u32 flags)
458{
459 struct scmi_base_reset_agent_configuration_in in = {
460 .agent_id = agent_id,
461 .flags = flags,
462 };
463 s32 status;
464 struct scmi_msg msg = {
465 .protocol_id = SCMI_PROTOCOL_ID_BASE,
466 .message_id = SCMI_BASE_RESET_AGENT_CONFIGURATION,
467 .in_msg = (u8 *)&in,
468 .in_msg_sz = sizeof(in),
469 .out_msg = (u8 *)&status,
470 .out_msg_sz = sizeof(status),
471 };
472 int ret;
473
474 ret = devm_scmi_process_msg(dev, &msg);
475 if (ret)
476 return ret;
477 if (status)
478 return scmi_to_linux_errno(status);
479
480 return 0;
481}
482
483/**
484 * scmi_base_probe - probe base protocol device
485 * @dev: SCMI device
486 *
487 * Probe the device for SCMI base protocol and initialize the private data.
488 *
489 * Return: 0 on success, error code on failure
490 */
491static int scmi_base_probe(struct udevice *dev)
492{
AKASHI Takahiro3413c312023-10-11 19:07:01 +0900493 u32 version;
AKASHI Takahirod1ce56a2023-10-11 19:07:00 +0900494 int ret;
495
496 ret = devm_scmi_of_get_channel(dev);
497 if (ret) {
498 dev_err(dev, "get_channel failed\n");
499 return ret;
500 }
AKASHI Takahiro3413c312023-10-11 19:07:01 +0900501 ret = scmi_base_protocol_version_int(dev, &version);
502 if (ret) {
503 dev_err(dev, "getting protocol version failed\n");
504 return ret;
505 }
506 if (version < SCMI_BASE_PROTOCOL_VERSION)
507 return -EINVAL;
AKASHI Takahirod1ce56a2023-10-11 19:07:00 +0900508
509 return ret;
510}
511
512static struct scmi_base_ops scmi_base_ops = {
513 /* Commands */
514 .protocol_version = scmi_base_protocol_version_int,
515 .protocol_attrs = scmi_protocol_attrs_int,
516 .protocol_message_attrs = scmi_protocol_message_attrs_int,
517 .base_discover_vendor = scmi_base_discover_vendor_int,
518 .base_discover_sub_vendor = scmi_base_discover_sub_vendor_int,
519 .base_discover_impl_version = scmi_base_discover_impl_version_int,
520 .base_discover_list_protocols = scmi_base_discover_list_protocols_int,
521 .base_discover_agent = scmi_base_discover_agent_int,
522 .base_notify_errors = NULL,
523 .base_set_device_permissions = scmi_base_set_device_permissions_int,
524 .base_set_protocol_permissions = scmi_base_set_protocol_permissions_int,
525 .base_reset_agent_configuration =
526 scmi_base_reset_agent_configuration_int,
527};
528
529int scmi_base_protocol_version(struct udevice *dev, u32 *version)
530{
531 const struct scmi_base_ops *ops = device_get_ops(dev);
532
533 if (ops->protocol_version)
534 return (*ops->protocol_version)(dev, version);
535
536 return -EOPNOTSUPP;
537}
538
539int scmi_base_protocol_attrs(struct udevice *dev, u32 *num_agents,
540 u32 *num_protocols)
541{
542 const struct scmi_base_ops *ops = device_get_ops(dev);
543
544 if (ops->protocol_attrs)
545 return (*ops->protocol_attrs)(dev, num_agents, num_protocols);
546
547 return -EOPNOTSUPP;
548}
549
550int scmi_base_protocol_message_attrs(struct udevice *dev, u32 message_id,
551 u32 *attributes)
552{
553 const struct scmi_base_ops *ops = device_get_ops(dev);
554
555 if (ops->protocol_message_attrs)
556 return (*ops->protocol_message_attrs)(dev, message_id,
557 attributes);
558
559 return -EOPNOTSUPP;
560}
561
562int scmi_base_discover_vendor(struct udevice *dev, u8 **vendor)
563{
564 const struct scmi_base_ops *ops = device_get_ops(dev);
565
566 if (ops->base_discover_vendor)
567 return (*ops->base_discover_vendor)(dev, vendor);
568
569 return -EOPNOTSUPP;
570}
571
572int scmi_base_discover_sub_vendor(struct udevice *dev, u8 **sub_vendor)
573{
574 const struct scmi_base_ops *ops = device_get_ops(dev);
575
576 if (ops->base_discover_sub_vendor)
577 return (*ops->base_discover_sub_vendor)(dev, sub_vendor);
578
579 return -EOPNOTSUPP;
580}
581
582int scmi_base_discover_impl_version(struct udevice *dev, u32 *impl_version)
583{
584 const struct scmi_base_ops *ops = device_get_ops(dev);
585
586 if (ops->base_discover_impl_version)
587 return (*ops->base_discover_impl_version)(dev, impl_version);
588
589 return -EOPNOTSUPP;
590}
591
592int scmi_base_discover_list_protocols(struct udevice *dev, u8 **protocols)
593{
594 const struct scmi_base_ops *ops = device_get_ops(dev);
595
596 if (ops->base_discover_list_protocols)
597 return (*ops->base_discover_list_protocols)(dev, protocols);
598
599 return -EOPNOTSUPP;
600}
601
602int scmi_base_discover_agent(struct udevice *dev, u32 agent_id,
603 u32 *ret_agent_id, u8 **name)
604{
605 const struct scmi_base_ops *ops = device_get_ops(dev);
606
607 if (ops->base_discover_agent)
608 return (*ops->base_discover_agent)(dev, agent_id, ret_agent_id,
609 name);
610
611 return -EOPNOTSUPP;
612}
613
614int scmi_base_notify_errors(struct udevice *dev, u32 enable)
615{
616 const struct scmi_base_ops *ops = device_get_ops(dev);
617
618 if (ops->base_notify_errors)
619 return (*ops->base_notify_errors)(dev, enable);
620
621 return -EOPNOTSUPP;
622}
623
624int scmi_base_set_device_permissions(struct udevice *dev, u32 agent_id,
625 u32 device_id, u32 flags)
626{
627 const struct scmi_base_ops *ops = device_get_ops(dev);
628
629 if (ops->base_set_device_permissions)
630 return (*ops->base_set_device_permissions)(dev, agent_id,
631 device_id, flags);
632
633 return -EOPNOTSUPP;
634}
635
636int scmi_base_set_protocol_permissions(struct udevice *dev,
637 u32 agent_id, u32 device_id,
638 u32 command_id, u32 flags)
639{
640 const struct scmi_base_ops *ops = device_get_ops(dev);
641
642 if (ops->base_set_protocol_permissions)
643 return (*ops->base_set_protocol_permissions)(dev, agent_id,
644 device_id,
645 command_id,
646 flags);
647
648 return -EOPNOTSUPP;
649}
650
651int scmi_base_reset_agent_configuration(struct udevice *dev, u32 agent_id,
652 u32 flags)
653{
654 const struct scmi_base_ops *ops = device_get_ops(dev);
655
656 if (ops->base_reset_agent_configuration)
657 return (*ops->base_reset_agent_configuration)(dev, agent_id,
658 flags);
659
660 return -EOPNOTSUPP;
661}
662
663U_BOOT_DRIVER(scmi_base_drv) = {
664 .id = UCLASS_SCMI_BASE,
665 .name = "scmi_base_drv",
666 .ops = &scmi_base_ops,
667 .probe = scmi_base_probe,
668};
669
670UCLASS_DRIVER(scmi_base) = {
671 .id = UCLASS_SCMI_BASE,
672 .name = "scmi_base",
673};