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