mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-04 14:00:19 +00:00 
			
		
		
		
	Merge branch '2023-10-13-firmware-scmi-updates'
- Fix a memset call in the optee_agent code. Then to quote the author for the rest of the changes: This patch series allows users to access SCMI base protocol provided by SCMI server (platform). See SCMI specification document v3.2 beta[1] for more details about SCMI base protocol. What is currently not implemented is - SCMI_BASE_NOTIFY_ERRORS command and notification callback mechanism This feature won't be very useful in the current U-Boot environment. [1] https://developer.arm.com/documentation/den0056/e/?lang=en
This commit is contained in:
		
						commit
						25edd247a8
					
				@ -732,13 +732,10 @@
 | 
				
			|||||||
			#address-cells = <1>;
 | 
								#address-cells = <1>;
 | 
				
			||||||
			#size-cells = <0>;
 | 
								#size-cells = <0>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			protocol@10 {
 | 
					 | 
				
			||||||
				reg = <0x10>;
 | 
					 | 
				
			||||||
			};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			clk_scmi: protocol@14 {
 | 
								clk_scmi: protocol@14 {
 | 
				
			||||||
				reg = <0x14>;
 | 
									reg = <0x14>;
 | 
				
			||||||
				#clock-cells = <1>;
 | 
									#clock-cells = <1>;
 | 
				
			||||||
 | 
									linaro,sandbox-channel-id = <0x14>;
 | 
				
			||||||
			};
 | 
								};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			reset_scmi: protocol@16 {
 | 
								reset_scmi: protocol@16 {
 | 
				
			||||||
 | 
				
			|||||||
@ -88,11 +88,21 @@ struct sandbox_scmi_devices {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_SCMI_FIRMWARE
 | 
					#ifdef CONFIG_SCMI_FIRMWARE
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * sandbox_scmi_channel_id - Get the channel id
 | 
				
			||||||
 | 
					 * @dev:	Reference to the SCMI protocol device
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return:	Channel id
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					unsigned int sandbox_scmi_channel_id(struct udevice *dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * sandbox_scmi_service_ctx - Get the simulated SCMI services context
 | 
					 * sandbox_scmi_service_ctx - Get the simulated SCMI services context
 | 
				
			||||||
 | 
					 * sandbox_scmi_agent_ctx - Get the simulated SCMI agent context
 | 
				
			||||||
 | 
					 * @dev:	Reference to the test agent
 | 
				
			||||||
 * @return:	Reference to backend simulated resources state
 | 
					 * @return:	Reference to backend simulated resources state
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
struct sandbox_scmi_service *sandbox_scmi_service_ctx(void);
 | 
					struct sandbox_scmi_agent *sandbox_scmi_agent_ctx(struct udevice *dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * sandbox_scmi_devices_ctx - Get references to devices accessed through SCMI
 | 
					 * sandbox_scmi_devices_ctx - Get references to devices accessed through SCMI
 | 
				
			||||||
@ -101,7 +111,12 @@ struct sandbox_scmi_service *sandbox_scmi_service_ctx(void);
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
struct sandbox_scmi_devices *sandbox_scmi_devices_ctx(struct udevice *dev);
 | 
					struct sandbox_scmi_devices *sandbox_scmi_devices_ctx(struct udevice *dev);
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
static inline struct sandbox_scmi_service *sandbox_scmi_service_ctx(void)
 | 
					inline unsigned int sandbox_scmi_channel_id(struct udevice *dev);
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct sandbox_scmi_agent *sandbox_scmi_agent_ctx(struct udevice *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -13,17 +13,8 @@
 | 
				
			|||||||
#include <asm/types.h>
 | 
					#include <asm/types.h>
 | 
				
			||||||
#include <linux/clk-provider.h>
 | 
					#include <linux/clk-provider.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * struct scmi_clk_priv - Private data for SCMI clocks
 | 
					 | 
				
			||||||
 * @channel: Reference to the SCMI channel to use
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
struct scmi_clk_priv {
 | 
					 | 
				
			||||||
	struct scmi_channel *channel;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks)
 | 
					static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct scmi_clk_priv *priv = dev_get_priv(dev);
 | 
					 | 
				
			||||||
	struct scmi_clk_protocol_attr_out out;
 | 
						struct scmi_clk_protocol_attr_out out;
 | 
				
			||||||
	struct scmi_msg msg = {
 | 
						struct scmi_msg msg = {
 | 
				
			||||||
		.protocol_id = SCMI_PROTOCOL_ID_CLOCK,
 | 
							.protocol_id = SCMI_PROTOCOL_ID_CLOCK,
 | 
				
			||||||
@ -33,7 +24,7 @@ static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks)
 | 
				
			|||||||
	};
 | 
						};
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = devm_scmi_process_msg(dev, priv->channel, &msg);
 | 
						ret = devm_scmi_process_msg(dev, &msg);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -44,7 +35,6 @@ static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name)
 | 
					static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct scmi_clk_priv *priv = dev_get_priv(dev);
 | 
					 | 
				
			||||||
	struct scmi_clk_attribute_in in = {
 | 
						struct scmi_clk_attribute_in in = {
 | 
				
			||||||
		.clock_id = clkid,
 | 
							.clock_id = clkid,
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
@ -59,7 +49,7 @@ static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name)
 | 
				
			|||||||
	};
 | 
						};
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = devm_scmi_process_msg(dev, priv->channel, &msg);
 | 
						ret = devm_scmi_process_msg(dev, &msg);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -70,7 +60,6 @@ static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static int scmi_clk_gate(struct clk *clk, int enable)
 | 
					static int scmi_clk_gate(struct clk *clk, int enable)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct scmi_clk_priv *priv = dev_get_priv(clk->dev);
 | 
					 | 
				
			||||||
	struct scmi_clk_state_in in = {
 | 
						struct scmi_clk_state_in in = {
 | 
				
			||||||
		.clock_id = clk->id,
 | 
							.clock_id = clk->id,
 | 
				
			||||||
		.attributes = enable,
 | 
							.attributes = enable,
 | 
				
			||||||
@ -81,7 +70,7 @@ static int scmi_clk_gate(struct clk *clk, int enable)
 | 
				
			|||||||
					  in, out);
 | 
										  in, out);
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg);
 | 
						ret = devm_scmi_process_msg(clk->dev, &msg);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -100,7 +89,6 @@ static int scmi_clk_disable(struct clk *clk)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static ulong scmi_clk_get_rate(struct clk *clk)
 | 
					static ulong scmi_clk_get_rate(struct clk *clk)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct scmi_clk_priv *priv = dev_get_priv(clk->dev);
 | 
					 | 
				
			||||||
	struct scmi_clk_rate_get_in in = {
 | 
						struct scmi_clk_rate_get_in in = {
 | 
				
			||||||
		.clock_id = clk->id,
 | 
							.clock_id = clk->id,
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
@ -110,7 +98,7 @@ static ulong scmi_clk_get_rate(struct clk *clk)
 | 
				
			|||||||
					  in, out);
 | 
										  in, out);
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg);
 | 
						ret = devm_scmi_process_msg(clk->dev, &msg);
 | 
				
			||||||
	if (ret < 0)
 | 
						if (ret < 0)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -123,7 +111,6 @@ static ulong scmi_clk_get_rate(struct clk *clk)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
 | 
					static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct scmi_clk_priv *priv = dev_get_priv(clk->dev);
 | 
					 | 
				
			||||||
	struct scmi_clk_rate_set_in in = {
 | 
						struct scmi_clk_rate_set_in in = {
 | 
				
			||||||
		.clock_id = clk->id,
 | 
							.clock_id = clk->id,
 | 
				
			||||||
		.flags = SCMI_CLK_RATE_ROUND_CLOSEST,
 | 
							.flags = SCMI_CLK_RATE_ROUND_CLOSEST,
 | 
				
			||||||
@ -136,7 +123,7 @@ static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
 | 
				
			|||||||
					  in, out);
 | 
										  in, out);
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg);
 | 
						ret = devm_scmi_process_msg(clk->dev, &msg);
 | 
				
			||||||
	if (ret < 0)
 | 
						if (ret < 0)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -149,12 +136,11 @@ static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static int scmi_clk_probe(struct udevice *dev)
 | 
					static int scmi_clk_probe(struct udevice *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct scmi_clk_priv *priv = dev_get_priv(dev);
 | 
					 | 
				
			||||||
	struct clk *clk;
 | 
						struct clk *clk;
 | 
				
			||||||
	size_t num_clocks, i;
 | 
						size_t num_clocks, i;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = devm_scmi_of_get_channel(dev, &priv->channel);
 | 
						ret = devm_scmi_of_get_channel(dev);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -205,5 +191,4 @@ U_BOOT_DRIVER(scmi_clock) = {
 | 
				
			|||||||
	.id = UCLASS_CLK,
 | 
						.id = UCLASS_CLK,
 | 
				
			||||||
	.ops = &scmi_clk_ops,
 | 
						.ops = &scmi_clk_ops,
 | 
				
			||||||
	.probe = scmi_clk_probe,
 | 
						.probe = scmi_clk_probe,
 | 
				
			||||||
	.priv_auto = sizeof(struct scmi_clk_priv *),
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,5 @@
 | 
				
			|||||||
obj-y	+= scmi_agent-uclass.o
 | 
					obj-y	+= scmi_agent-uclass.o
 | 
				
			||||||
 | 
					obj-y	+= base.o
 | 
				
			||||||
obj-y	+= smt.o
 | 
					obj-y	+= smt.o
 | 
				
			||||||
obj-$(CONFIG_SCMI_AGENT_SMCCC)		+= smccc_agent.o
 | 
					obj-$(CONFIG_SCMI_AGENT_SMCCC)		+= smccc_agent.o
 | 
				
			||||||
obj-$(CONFIG_SCMI_AGENT_MAILBOX)	+= mailbox_agent.o
 | 
					obj-$(CONFIG_SCMI_AGENT_MAILBOX)	+= mailbox_agent.o
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										664
									
								
								drivers/firmware/scmi/base.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										664
									
								
								drivers/firmware/scmi/base.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,664 @@
 | 
				
			|||||||
 | 
					// SPDX-License-Identifier: GPL-2.0+
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * SCMI Base protocol as U-Boot device
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2023 Linaro Limited
 | 
				
			||||||
 | 
					 *		author: AKASHI Takahiro <takahiro.akashi@linaro.org>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <common.h>
 | 
				
			||||||
 | 
					#include <dm.h>
 | 
				
			||||||
 | 
					#include <scmi_agent.h>
 | 
				
			||||||
 | 
					#include <scmi_protocols.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <asm/types.h>
 | 
				
			||||||
 | 
					#include <dm/device_compat.h>
 | 
				
			||||||
 | 
					#include <linux/kernel.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_generic_protocol_version - get protocol version
 | 
				
			||||||
 | 
					 * @dev:	SCMI device
 | 
				
			||||||
 | 
					 * @id:		SCMI protocol ID
 | 
				
			||||||
 | 
					 * @version:	Pointer to SCMI protocol version
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Obtain the protocol version number in @version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int scmi_generic_protocol_version(struct udevice *dev,
 | 
				
			||||||
 | 
									  enum scmi_std_protocol id, u32 *version)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scmi_protocol_version_out out;
 | 
				
			||||||
 | 
						struct scmi_msg msg = {
 | 
				
			||||||
 | 
							.protocol_id = id,
 | 
				
			||||||
 | 
							.message_id = SCMI_PROTOCOL_VERSION,
 | 
				
			||||||
 | 
							.out_msg = (u8 *)&out,
 | 
				
			||||||
 | 
							.out_msg_sz = sizeof(out),
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = devm_scmi_process_msg(dev, &msg);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						if (out.status)
 | 
				
			||||||
 | 
							return scmi_to_linux_errno(out.status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*version = out.version;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_base_protocol_version_int - get Base protocol version
 | 
				
			||||||
 | 
					 * @dev:	SCMI device
 | 
				
			||||||
 | 
					 * @version:	Pointer to SCMI protocol version
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Obtain the protocol version number in @version for Base protocol.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int scmi_base_protocol_version_int(struct udevice *dev, u32 *version)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return scmi_generic_protocol_version(dev, SCMI_PROTOCOL_ID_BASE,
 | 
				
			||||||
 | 
										     version);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_protocol_attrs_int - get protocol attributes
 | 
				
			||||||
 | 
					 * @dev:		SCMI device
 | 
				
			||||||
 | 
					 * @num_agents:		Number of SCMI agents
 | 
				
			||||||
 | 
					 * @num_protocols:	Number of SCMI protocols
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Obtain the protocol attributes, the number of agents and the number
 | 
				
			||||||
 | 
					 * of protocols, in @num_agents and @num_protocols respectively, that
 | 
				
			||||||
 | 
					 * the device provides.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int scmi_protocol_attrs_int(struct udevice *dev, u32 *num_agents,
 | 
				
			||||||
 | 
									   u32 *num_protocols)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scmi_protocol_attrs_out out;
 | 
				
			||||||
 | 
						struct scmi_msg msg = {
 | 
				
			||||||
 | 
							.protocol_id = SCMI_PROTOCOL_ID_BASE,
 | 
				
			||||||
 | 
							.message_id = SCMI_PROTOCOL_ATTRIBUTES,
 | 
				
			||||||
 | 
							.out_msg = (u8 *)&out,
 | 
				
			||||||
 | 
							.out_msg_sz = sizeof(out),
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = devm_scmi_process_msg(dev, &msg);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						if (out.status)
 | 
				
			||||||
 | 
							return scmi_to_linux_errno(out.status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*num_agents = SCMI_PROTOCOL_ATTRS_NUM_AGENTS(out.attributes);
 | 
				
			||||||
 | 
						*num_protocols = SCMI_PROTOCOL_ATTRS_NUM_PROTOCOLS(out.attributes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_protocol_message_attrs_int - get message-specific attributes
 | 
				
			||||||
 | 
					 * @dev:		SCMI device
 | 
				
			||||||
 | 
					 * @message_id:		SCMI message ID
 | 
				
			||||||
 | 
					 * @attributes:		Message-specific attributes
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Obtain the message-specific attributes in @attributes.
 | 
				
			||||||
 | 
					 * This command succeeds if the message is implemented and available.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int scmi_protocol_message_attrs_int(struct udevice *dev, u32 message_id,
 | 
				
			||||||
 | 
										   u32 *attributes)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scmi_protocol_msg_attrs_out out;
 | 
				
			||||||
 | 
						struct scmi_msg msg = {
 | 
				
			||||||
 | 
							.protocol_id = SCMI_PROTOCOL_ID_BASE,
 | 
				
			||||||
 | 
							.message_id = SCMI_PROTOCOL_MESSAGE_ATTRIBUTES,
 | 
				
			||||||
 | 
							.in_msg = (u8 *)&message_id,
 | 
				
			||||||
 | 
							.in_msg_sz = sizeof(message_id),
 | 
				
			||||||
 | 
							.out_msg = (u8 *)&out,
 | 
				
			||||||
 | 
							.out_msg_sz = sizeof(out),
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = devm_scmi_process_msg(dev, &msg);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						if (out.status)
 | 
				
			||||||
 | 
							return scmi_to_linux_errno(out.status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*attributes = out.attributes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_base_discover_vendor_int - get vendor name
 | 
				
			||||||
 | 
					 * @dev:	SCMI device
 | 
				
			||||||
 | 
					 * @vendor:	Pointer to vendor name
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Obtain the vendor's name in @vendor.
 | 
				
			||||||
 | 
					 * It is a caller's responsibility to free @vendor.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int scmi_base_discover_vendor_int(struct udevice *dev, u8 **vendor)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scmi_base_discover_vendor_out out;
 | 
				
			||||||
 | 
						struct scmi_msg msg = {
 | 
				
			||||||
 | 
							.protocol_id = SCMI_PROTOCOL_ID_BASE,
 | 
				
			||||||
 | 
							.message_id = SCMI_BASE_DISCOVER_VENDOR,
 | 
				
			||||||
 | 
							.out_msg = (u8 *)&out,
 | 
				
			||||||
 | 
							.out_msg_sz = sizeof(out),
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!vendor)
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = devm_scmi_process_msg(dev, &msg);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						if (out.status)
 | 
				
			||||||
 | 
							return scmi_to_linux_errno(out.status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*vendor = strdup(out.vendor_identifier);
 | 
				
			||||||
 | 
						if (!*vendor)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_base_discover_sub_vendor_int - get sub-vendor name
 | 
				
			||||||
 | 
					 * @dev:	SCMI device
 | 
				
			||||||
 | 
					 * @sub_vendor:	Pointer to sub-vendor name
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Obtain the sub-vendor's name in @sub_vendor.
 | 
				
			||||||
 | 
					 * It is a caller's responsibility to free @sub_vendor.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int scmi_base_discover_sub_vendor_int(struct udevice *dev,
 | 
				
			||||||
 | 
										     u8 **sub_vendor)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scmi_base_discover_vendor_out out;
 | 
				
			||||||
 | 
						struct scmi_msg msg = {
 | 
				
			||||||
 | 
							.protocol_id = SCMI_PROTOCOL_ID_BASE,
 | 
				
			||||||
 | 
							.message_id = SCMI_BASE_DISCOVER_SUB_VENDOR,
 | 
				
			||||||
 | 
							.out_msg = (u8 *)&out,
 | 
				
			||||||
 | 
							.out_msg_sz = sizeof(out),
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!sub_vendor)
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = devm_scmi_process_msg(dev, &msg);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						if (out.status)
 | 
				
			||||||
 | 
							return scmi_to_linux_errno(out.status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*sub_vendor = strdup(out.vendor_identifier);
 | 
				
			||||||
 | 
						if (!*sub_vendor)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_base_discover_impl_version_int - get implementation version
 | 
				
			||||||
 | 
					 * @dev:		SCMI device
 | 
				
			||||||
 | 
					 * @impl_version:	Pointer to implementation version
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Obtain the implementation version number in @impl_version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int scmi_base_discover_impl_version_int(struct udevice *dev,
 | 
				
			||||||
 | 
										       u32 *impl_version)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scmi_base_discover_impl_version_out out;
 | 
				
			||||||
 | 
						struct scmi_msg msg = {
 | 
				
			||||||
 | 
							.protocol_id = SCMI_PROTOCOL_ID_BASE,
 | 
				
			||||||
 | 
							.message_id = SCMI_BASE_DISCOVER_IMPL_VERSION,
 | 
				
			||||||
 | 
							.out_msg = (u8 *)&out,
 | 
				
			||||||
 | 
							.out_msg_sz = sizeof(out),
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = devm_scmi_process_msg(dev, &msg);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						if (out.status)
 | 
				
			||||||
 | 
							return scmi_to_linux_errno(out.status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*impl_version = out.impl_version;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_base_discover_list_protocols_int - get list of protocols
 | 
				
			||||||
 | 
					 * @dev:	SCMI device
 | 
				
			||||||
 | 
					 * @protocols:	Pointer to array of SCMI protocols
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Obtain the list of protocols provided in @protocols.
 | 
				
			||||||
 | 
					 * The number of elements in @protocols always match to the number of
 | 
				
			||||||
 | 
					 * protocols returned by smci_protocol_attrs() when this function succeeds.
 | 
				
			||||||
 | 
					 * It is a caller's responsibility to free @protocols.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: the number of protocols in @protocols on success, error code on
 | 
				
			||||||
 | 
					 * failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int scmi_base_discover_list_protocols_int(struct udevice *dev,
 | 
				
			||||||
 | 
											 u8 **protocols)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scmi_base_discover_list_protocols_out out;
 | 
				
			||||||
 | 
						int cur;
 | 
				
			||||||
 | 
						struct scmi_msg msg = {
 | 
				
			||||||
 | 
							.protocol_id = SCMI_PROTOCOL_ID_BASE,
 | 
				
			||||||
 | 
							.message_id = SCMI_BASE_DISCOVER_LIST_PROTOCOLS,
 | 
				
			||||||
 | 
							.in_msg = (u8 *)&cur,
 | 
				
			||||||
 | 
							.in_msg_sz = sizeof(cur),
 | 
				
			||||||
 | 
							.out_msg = (u8 *)&out,
 | 
				
			||||||
 | 
							.out_msg_sz = sizeof(out),
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						u32 num_agents, num_protocols;
 | 
				
			||||||
 | 
						u8 *buf;
 | 
				
			||||||
 | 
						int i, ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = scmi_base_protocol_attrs(dev, &num_agents, &num_protocols);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						buf = calloc(sizeof(u8), num_protocols);
 | 
				
			||||||
 | 
						if (!buf)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cur = 0;
 | 
				
			||||||
 | 
						do {
 | 
				
			||||||
 | 
							ret = devm_scmi_process_msg(dev, &msg);
 | 
				
			||||||
 | 
							if (ret)
 | 
				
			||||||
 | 
								goto err;
 | 
				
			||||||
 | 
							if (out.status) {
 | 
				
			||||||
 | 
								ret = scmi_to_linux_errno(out.status);
 | 
				
			||||||
 | 
								goto err;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (i = 0; i < out.num_protocols; i++, cur++)
 | 
				
			||||||
 | 
								buf[cur] = out.protocols[i / 4] >> ((i % 4) * 8);
 | 
				
			||||||
 | 
						} while (cur < num_protocols);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*protocols = buf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return num_protocols;
 | 
				
			||||||
 | 
					err:
 | 
				
			||||||
 | 
						free(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_base_discover_agent_int - identify agent
 | 
				
			||||||
 | 
					 * @dev:		SCMI device
 | 
				
			||||||
 | 
					 * @agent_id:		SCMI agent ID
 | 
				
			||||||
 | 
					 * @ret_agent_id:	Pointer to SCMI agent ID
 | 
				
			||||||
 | 
					 * @name:		Pointer to SCMI agent name
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Obtain the agent's name in @name. If @agent_id is equal to 0xffffffff,
 | 
				
			||||||
 | 
					 * this function returns the caller's agent id in @ret_agent_id.
 | 
				
			||||||
 | 
					 * It is a caller's responsibility to free @name.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int scmi_base_discover_agent_int(struct udevice *dev, u32 agent_id,
 | 
				
			||||||
 | 
										u32 *ret_agent_id, u8 **name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scmi_base_discover_agent_out out;
 | 
				
			||||||
 | 
						struct scmi_msg msg = {
 | 
				
			||||||
 | 
							.protocol_id = SCMI_PROTOCOL_ID_BASE,
 | 
				
			||||||
 | 
							.message_id = SCMI_BASE_DISCOVER_AGENT,
 | 
				
			||||||
 | 
							.in_msg = (u8 *)&agent_id,
 | 
				
			||||||
 | 
							.in_msg_sz = sizeof(agent_id),
 | 
				
			||||||
 | 
							.out_msg = (u8 *)&out,
 | 
				
			||||||
 | 
							.out_msg_sz = sizeof(out),
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = devm_scmi_process_msg(dev, &msg);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						if (out.status)
 | 
				
			||||||
 | 
							return scmi_to_linux_errno(out.status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ret_agent_id)
 | 
				
			||||||
 | 
							*ret_agent_id = out.agent_id;
 | 
				
			||||||
 | 
						if (name) {
 | 
				
			||||||
 | 
							*name = strdup(out.name);
 | 
				
			||||||
 | 
							if (!*name)
 | 
				
			||||||
 | 
								return -ENOMEM;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_base_set_device_permissions_int - configure access permission to device
 | 
				
			||||||
 | 
					 * @dev:	SCMI device
 | 
				
			||||||
 | 
					 * @agent_id:	SCMI agent ID
 | 
				
			||||||
 | 
					 * @device_id:	ID of device to access
 | 
				
			||||||
 | 
					 * @flags:	A set of flags
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Ask for allowing or denying access permission to the device, @device_id.
 | 
				
			||||||
 | 
					 * The meaning of @flags is defined in SCMI specification.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int scmi_base_set_device_permissions_int(struct udevice *dev, u32 agent_id,
 | 
				
			||||||
 | 
											u32 device_id, u32 flags)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scmi_base_set_device_permissions_in in = {
 | 
				
			||||||
 | 
							.agent_id = agent_id,
 | 
				
			||||||
 | 
							.device_id = device_id,
 | 
				
			||||||
 | 
							.flags = flags,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						s32 status;
 | 
				
			||||||
 | 
						struct scmi_msg msg = {
 | 
				
			||||||
 | 
							.protocol_id = SCMI_PROTOCOL_ID_BASE,
 | 
				
			||||||
 | 
							.message_id = SCMI_BASE_SET_DEVICE_PERMISSIONS,
 | 
				
			||||||
 | 
							.in_msg = (u8 *)&in,
 | 
				
			||||||
 | 
							.in_msg_sz = sizeof(in),
 | 
				
			||||||
 | 
							.out_msg = (u8 *)&status,
 | 
				
			||||||
 | 
							.out_msg_sz = sizeof(status),
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = devm_scmi_process_msg(dev, &msg);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						if (status)
 | 
				
			||||||
 | 
							return scmi_to_linux_errno(status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_base_set_protocol_permissions_int - configure access permission to
 | 
				
			||||||
 | 
					 *					    protocol on device
 | 
				
			||||||
 | 
					 * @dev:	SCMI device
 | 
				
			||||||
 | 
					 * @agent_id:	SCMI agent ID
 | 
				
			||||||
 | 
					 * @device_id:	ID of device to access
 | 
				
			||||||
 | 
					 * @command_id:	SCMI command ID
 | 
				
			||||||
 | 
					 * @flags:	A set of flags
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Ask for allowing or denying access permission to the protocol, @command_id,
 | 
				
			||||||
 | 
					 * on the device, @device_id.
 | 
				
			||||||
 | 
					 * The meaning of @flags is defined in SCMI specification.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int scmi_base_set_protocol_permissions_int(struct udevice *dev,
 | 
				
			||||||
 | 
											  u32 agent_id, u32 device_id,
 | 
				
			||||||
 | 
											  u32 command_id, u32 flags)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scmi_base_set_protocol_permissions_in in = {
 | 
				
			||||||
 | 
							.agent_id = agent_id,
 | 
				
			||||||
 | 
							.device_id = device_id,
 | 
				
			||||||
 | 
							.command_id = command_id,
 | 
				
			||||||
 | 
							.flags = flags,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						s32 status;
 | 
				
			||||||
 | 
						struct scmi_msg msg = {
 | 
				
			||||||
 | 
							.protocol_id = SCMI_PROTOCOL_ID_BASE,
 | 
				
			||||||
 | 
							.message_id = SCMI_BASE_SET_PROTOCOL_PERMISSIONS,
 | 
				
			||||||
 | 
							.in_msg = (u8 *)&in,
 | 
				
			||||||
 | 
							.in_msg_sz = sizeof(in),
 | 
				
			||||||
 | 
							.out_msg = (u8 *)&status,
 | 
				
			||||||
 | 
							.out_msg_sz = sizeof(status),
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = devm_scmi_process_msg(dev, &msg);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						if (status)
 | 
				
			||||||
 | 
							return scmi_to_linux_errno(status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_base_reset_agent_configuration_int - reset resource settings
 | 
				
			||||||
 | 
					 * @dev:	SCMI device
 | 
				
			||||||
 | 
					 * @agent_id:	SCMI agent ID
 | 
				
			||||||
 | 
					 * @flags:	A set of flags
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Reset all the resource settings against @agent_id.
 | 
				
			||||||
 | 
					 * The meaning of @flags is defined in SCMI specification.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int scmi_base_reset_agent_configuration_int(struct udevice *dev,
 | 
				
			||||||
 | 
											   u32 agent_id, u32 flags)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scmi_base_reset_agent_configuration_in in = {
 | 
				
			||||||
 | 
							.agent_id = agent_id,
 | 
				
			||||||
 | 
							.flags = flags,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						s32 status;
 | 
				
			||||||
 | 
						struct scmi_msg msg = {
 | 
				
			||||||
 | 
							.protocol_id = SCMI_PROTOCOL_ID_BASE,
 | 
				
			||||||
 | 
							.message_id = SCMI_BASE_RESET_AGENT_CONFIGURATION,
 | 
				
			||||||
 | 
							.in_msg = (u8 *)&in,
 | 
				
			||||||
 | 
							.in_msg_sz = sizeof(in),
 | 
				
			||||||
 | 
							.out_msg = (u8 *)&status,
 | 
				
			||||||
 | 
							.out_msg_sz = sizeof(status),
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = devm_scmi_process_msg(dev, &msg);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						if (status)
 | 
				
			||||||
 | 
							return scmi_to_linux_errno(status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_base_probe - probe base protocol device
 | 
				
			||||||
 | 
					 * @dev:	SCMI device
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Probe the device for SCMI base protocol and initialize the private data.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int scmi_base_probe(struct udevice *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u32 version;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = devm_scmi_of_get_channel(dev);
 | 
				
			||||||
 | 
						if (ret) {
 | 
				
			||||||
 | 
							dev_err(dev, "get_channel failed\n");
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ret = scmi_base_protocol_version_int(dev, &version);
 | 
				
			||||||
 | 
						if (ret) {
 | 
				
			||||||
 | 
							dev_err(dev, "getting protocol version failed\n");
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (version < SCMI_BASE_PROTOCOL_VERSION)
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct scmi_base_ops scmi_base_ops = {
 | 
				
			||||||
 | 
						/* Commands */
 | 
				
			||||||
 | 
						.protocol_version = scmi_base_protocol_version_int,
 | 
				
			||||||
 | 
						.protocol_attrs = scmi_protocol_attrs_int,
 | 
				
			||||||
 | 
						.protocol_message_attrs = scmi_protocol_message_attrs_int,
 | 
				
			||||||
 | 
						.base_discover_vendor = scmi_base_discover_vendor_int,
 | 
				
			||||||
 | 
						.base_discover_sub_vendor = scmi_base_discover_sub_vendor_int,
 | 
				
			||||||
 | 
						.base_discover_impl_version = scmi_base_discover_impl_version_int,
 | 
				
			||||||
 | 
						.base_discover_list_protocols = scmi_base_discover_list_protocols_int,
 | 
				
			||||||
 | 
						.base_discover_agent = scmi_base_discover_agent_int,
 | 
				
			||||||
 | 
						.base_notify_errors = NULL,
 | 
				
			||||||
 | 
						.base_set_device_permissions = scmi_base_set_device_permissions_int,
 | 
				
			||||||
 | 
						.base_set_protocol_permissions = scmi_base_set_protocol_permissions_int,
 | 
				
			||||||
 | 
						.base_reset_agent_configuration =
 | 
				
			||||||
 | 
								scmi_base_reset_agent_configuration_int,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int scmi_base_protocol_version(struct udevice *dev, u32 *version)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct scmi_base_ops *ops = device_get_ops(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ops->protocol_version)
 | 
				
			||||||
 | 
							return (*ops->protocol_version)(dev, version);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return -EOPNOTSUPP;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int scmi_base_protocol_attrs(struct udevice *dev, u32 *num_agents,
 | 
				
			||||||
 | 
								     u32 *num_protocols)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct scmi_base_ops *ops = device_get_ops(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ops->protocol_attrs)
 | 
				
			||||||
 | 
							return (*ops->protocol_attrs)(dev, num_agents, num_protocols);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return -EOPNOTSUPP;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int scmi_base_protocol_message_attrs(struct udevice *dev, u32 message_id,
 | 
				
			||||||
 | 
									     u32 *attributes)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct scmi_base_ops *ops = device_get_ops(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ops->protocol_message_attrs)
 | 
				
			||||||
 | 
							return (*ops->protocol_message_attrs)(dev, message_id,
 | 
				
			||||||
 | 
											      attributes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return -EOPNOTSUPP;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int scmi_base_discover_vendor(struct udevice *dev, u8 **vendor)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct scmi_base_ops *ops = device_get_ops(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ops->base_discover_vendor)
 | 
				
			||||||
 | 
							return (*ops->base_discover_vendor)(dev, vendor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return -EOPNOTSUPP;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int scmi_base_discover_sub_vendor(struct udevice *dev, u8 **sub_vendor)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct scmi_base_ops *ops = device_get_ops(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ops->base_discover_sub_vendor)
 | 
				
			||||||
 | 
							return (*ops->base_discover_sub_vendor)(dev, sub_vendor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return -EOPNOTSUPP;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int scmi_base_discover_impl_version(struct udevice *dev, u32 *impl_version)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct scmi_base_ops *ops = device_get_ops(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ops->base_discover_impl_version)
 | 
				
			||||||
 | 
							return (*ops->base_discover_impl_version)(dev, impl_version);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return -EOPNOTSUPP;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int scmi_base_discover_list_protocols(struct udevice *dev, u8 **protocols)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct scmi_base_ops *ops = device_get_ops(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ops->base_discover_list_protocols)
 | 
				
			||||||
 | 
							return (*ops->base_discover_list_protocols)(dev, protocols);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return -EOPNOTSUPP;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int scmi_base_discover_agent(struct udevice *dev, u32 agent_id,
 | 
				
			||||||
 | 
								     u32 *ret_agent_id, u8 **name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct scmi_base_ops *ops = device_get_ops(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ops->base_discover_agent)
 | 
				
			||||||
 | 
							return (*ops->base_discover_agent)(dev, agent_id, ret_agent_id,
 | 
				
			||||||
 | 
											   name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return -EOPNOTSUPP;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int scmi_base_notify_errors(struct udevice *dev, u32 enable)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct scmi_base_ops *ops = device_get_ops(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ops->base_notify_errors)
 | 
				
			||||||
 | 
							return (*ops->base_notify_errors)(dev, enable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return -EOPNOTSUPP;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int scmi_base_set_device_permissions(struct udevice *dev, u32 agent_id,
 | 
				
			||||||
 | 
									     u32 device_id, u32 flags)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct scmi_base_ops *ops = device_get_ops(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ops->base_set_device_permissions)
 | 
				
			||||||
 | 
							return (*ops->base_set_device_permissions)(dev, agent_id,
 | 
				
			||||||
 | 
												   device_id, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return -EOPNOTSUPP;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int scmi_base_set_protocol_permissions(struct udevice *dev,
 | 
				
			||||||
 | 
									       u32 agent_id, u32 device_id,
 | 
				
			||||||
 | 
									       u32 command_id, u32 flags)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct scmi_base_ops *ops = device_get_ops(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ops->base_set_protocol_permissions)
 | 
				
			||||||
 | 
							return (*ops->base_set_protocol_permissions)(dev, agent_id,
 | 
				
			||||||
 | 
												     device_id,
 | 
				
			||||||
 | 
												     command_id,
 | 
				
			||||||
 | 
												     flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return -EOPNOTSUPP;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int scmi_base_reset_agent_configuration(struct udevice *dev, u32 agent_id,
 | 
				
			||||||
 | 
										u32 flags)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct scmi_base_ops *ops = device_get_ops(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ops->base_reset_agent_configuration)
 | 
				
			||||||
 | 
							return (*ops->base_reset_agent_configuration)(dev, agent_id,
 | 
				
			||||||
 | 
												      flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return -EOPNOTSUPP;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					U_BOOT_DRIVER(scmi_base_drv) = {
 | 
				
			||||||
 | 
						.id = UCLASS_SCMI_BASE,
 | 
				
			||||||
 | 
						.name = "scmi_base_drv",
 | 
				
			||||||
 | 
						.ops = &scmi_base_ops,
 | 
				
			||||||
 | 
						.probe = scmi_base_probe,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					UCLASS_DRIVER(scmi_base) = {
 | 
				
			||||||
 | 
						.id		= UCLASS_SCMI_BASE,
 | 
				
			||||||
 | 
						.name		= "scmi_base",
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@ -94,13 +94,14 @@ static int setup_channel(struct udevice *dev, struct scmi_mbox_channel *chan)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int scmi_mbox_get_channel(struct udevice *dev,
 | 
					static int scmi_mbox_get_channel(struct udevice *dev,
 | 
				
			||||||
 | 
									 struct udevice *protocol,
 | 
				
			||||||
				 struct scmi_channel **channel)
 | 
									 struct scmi_channel **channel)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct scmi_mbox_channel *base_chan = dev_get_plat(dev);
 | 
						struct scmi_mbox_channel *base_chan = dev_get_plat(dev);
 | 
				
			||||||
	struct scmi_mbox_channel *chan;
 | 
						struct scmi_mbox_channel *chan;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!dev_read_prop(dev, "shmem", NULL)) {
 | 
						if (!dev_read_prop(protocol, "shmem", NULL)) {
 | 
				
			||||||
		/* Uses agent base channel */
 | 
							/* Uses agent base channel */
 | 
				
			||||||
		*channel = container_of(base_chan, struct scmi_channel, ref);
 | 
							*channel = container_of(base_chan, struct scmi_channel, ref);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -112,7 +113,7 @@ static int scmi_mbox_get_channel(struct udevice *dev,
 | 
				
			|||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Setup a dedicated channel for the protocol */
 | 
						/* Setup a dedicated channel for the protocol */
 | 
				
			||||||
	ret = setup_channel(dev, chan);
 | 
						ret = setup_channel(protocol, chan);
 | 
				
			||||||
	if (ret) {
 | 
						if (ret) {
 | 
				
			||||||
		free(chan);
 | 
							free(chan);
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
				
			|||||||
@ -149,7 +149,7 @@ static int open_channel(struct udevice *dev, struct scmi_optee_channel *chan,
 | 
				
			|||||||
	struct tee_param param[1] = { };
 | 
						struct tee_param param[1] = { };
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memset(sess, 0, sizeof(sess));
 | 
						memset(sess, 0, sizeof(*sess));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sess->tee = tee_find_device(NULL, NULL, NULL, NULL);
 | 
						sess->tee = tee_find_device(NULL, NULL, NULL, NULL);
 | 
				
			||||||
	if (!sess->tee)
 | 
						if (!sess->tee)
 | 
				
			||||||
@ -324,6 +324,7 @@ static int setup_channel(struct udevice *dev, struct scmi_optee_channel *chan)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int scmi_optee_get_channel(struct udevice *dev,
 | 
					static int scmi_optee_get_channel(struct udevice *dev,
 | 
				
			||||||
 | 
									  struct udevice *protocol,
 | 
				
			||||||
				  struct scmi_channel **channel)
 | 
									  struct scmi_channel **channel)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct scmi_optee_channel *base_chan = dev_get_plat(dev);
 | 
						struct scmi_optee_channel *base_chan = dev_get_plat(dev);
 | 
				
			||||||
@ -331,7 +332,7 @@ static int scmi_optee_get_channel(struct udevice *dev,
 | 
				
			|||||||
	u32 channel_id;
 | 
						u32 channel_id;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (dev_read_u32(dev, "linaro,optee-channel-id", &channel_id)) {
 | 
						if (dev_read_u32(protocol, "linaro,optee-channel-id", &channel_id)) {
 | 
				
			||||||
		/* Uses agent base channel */
 | 
							/* Uses agent base channel */
 | 
				
			||||||
		*channel = container_of(base_chan, struct scmi_channel, ref);
 | 
							*channel = container_of(base_chan, struct scmi_channel, ref);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -343,7 +344,7 @@ static int scmi_optee_get_channel(struct udevice *dev,
 | 
				
			|||||||
	if (!chan)
 | 
						if (!chan)
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = setup_channel(dev, chan);
 | 
						ret = setup_channel(protocol, chan);
 | 
				
			||||||
	if (ret) {
 | 
						if (ret) {
 | 
				
			||||||
		free(chan);
 | 
							free(chan);
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
				
			|||||||
@ -14,11 +14,14 @@
 | 
				
			|||||||
#include <asm/io.h>
 | 
					#include <asm/io.h>
 | 
				
			||||||
#include <asm/scmi_test.h>
 | 
					#include <asm/scmi_test.h>
 | 
				
			||||||
#include <dm/device_compat.h>
 | 
					#include <dm/device_compat.h>
 | 
				
			||||||
 | 
					#include <linux/bitfield.h>
 | 
				
			||||||
 | 
					#include <linux/kernel.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * The sandbox SCMI agent driver simulates to some extend a SCMI message
 | 
					 * The sandbox SCMI agent driver simulates to some extend a SCMI message
 | 
				
			||||||
 * processing. It simulates few of the SCMI services for some of the
 | 
					 * processing. It simulates few of the SCMI services for some of the
 | 
				
			||||||
 * SCMI protocols embedded in U-Boot. Currently:
 | 
					 * SCMI protocols embedded in U-Boot. Currently:
 | 
				
			||||||
 | 
					 * - SCMI base protocol
 | 
				
			||||||
 * - SCMI clock protocol emulates an agent exposing 2 clocks
 | 
					 * - SCMI clock protocol emulates an agent exposing 2 clocks
 | 
				
			||||||
 * - SCMI reset protocol emulates an agent exposing a reset controller
 | 
					 * - SCMI reset protocol emulates an agent exposing a reset controller
 | 
				
			||||||
 * - SCMI voltage domain protocol emulates an agent exposing 2 regulators
 | 
					 * - SCMI voltage domain protocol emulates an agent exposing 2 regulators
 | 
				
			||||||
@ -33,6 +36,41 @@
 | 
				
			|||||||
 * various uclass devices, as clocks and reset controllers.
 | 
					 * various uclass devices, as clocks and reset controllers.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SANDBOX_SCMI_BASE_PROTOCOL_VERSION SCMI_BASE_PROTOCOL_VERSION
 | 
				
			||||||
 | 
					#define SANDBOX_SCMI_VENDOR "U-Boot"
 | 
				
			||||||
 | 
					#define SANDBOX_SCMI_SUB_VENDOR "Sandbox"
 | 
				
			||||||
 | 
					#define SANDBOX_SCMI_IMPL_VERSION 0x1
 | 
				
			||||||
 | 
					#define SANDBOX_SCMI_AGENT_NAME "OSPM"
 | 
				
			||||||
 | 
					#define SANDBOX_SCMI_PLATFORM_NAME "platform"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * struct sandbox_channel - Description of sandbox transport
 | 
				
			||||||
 | 
					 * @channel_id:		Channel identifier
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Dummy channel. This will be used to test if a protocol-specific
 | 
				
			||||||
 | 
					 * channel is properly used.
 | 
				
			||||||
 | 
					 * Id 0 means a channel for the sandbox agent.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct sandbox_channel {
 | 
				
			||||||
 | 
						unsigned int channel_id;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * struct scmi_channel - Channel instance referenced in SCMI drivers
 | 
				
			||||||
 | 
					 * @ref: Reference to local channel instance
 | 
				
			||||||
 | 
					 **/
 | 
				
			||||||
 | 
					struct scmi_channel {
 | 
				
			||||||
 | 
						struct sandbox_channel ref;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static u8 protocols[] = {
 | 
				
			||||||
 | 
						SCMI_PROTOCOL_ID_CLOCK,
 | 
				
			||||||
 | 
						SCMI_PROTOCOL_ID_RESET_DOMAIN,
 | 
				
			||||||
 | 
						SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NUM_PROTOCOLS ARRAY_SIZE(protocols)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct sandbox_scmi_clk scmi_clk[] = {
 | 
					static struct sandbox_scmi_clk scmi_clk[] = {
 | 
				
			||||||
	{ .rate = 333 },
 | 
						{ .rate = 333 },
 | 
				
			||||||
	{ .rate = 200 },
 | 
						{ .rate = 200 },
 | 
				
			||||||
@ -48,11 +86,9 @@ static struct sandbox_scmi_voltd scmi_voltd[] = {
 | 
				
			|||||||
	{ .id = 1, .voltage_uv = 1800000 },
 | 
						{ .id = 1, .voltage_uv = 1800000 },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct sandbox_scmi_service sandbox_scmi_service_state;
 | 
					struct sandbox_scmi_agent *sandbox_scmi_agent_ctx(struct udevice *dev)
 | 
				
			||||||
 | 
					 | 
				
			||||||
struct sandbox_scmi_service *sandbox_scmi_service_ctx(void)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return &sandbox_scmi_service_state;
 | 
						return dev_get_priv(dev);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void debug_print_agent_state(struct udevice *dev, char *str)
 | 
					static void debug_print_agent_state(struct udevice *dev, char *str)
 | 
				
			||||||
@ -114,6 +150,316 @@ static struct sandbox_scmi_voltd *get_scmi_voltd_state(uint domain_id)
 | 
				
			|||||||
 * Sandbox SCMI agent ops
 | 
					 * Sandbox SCMI agent ops
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Base Protocol */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * sandbox_scmi_base_protocol_version - implement SCMI_BASE_PROTOCOL_VERSION
 | 
				
			||||||
 | 
					 * @dev:	SCMI device
 | 
				
			||||||
 | 
					 * @msg:	SCMI message
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Implement SCMI_BASE_PROTOCOL_VERSION command.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int sandbox_scmi_base_protocol_version(struct udevice *dev,
 | 
				
			||||||
 | 
										      struct scmi_msg *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scmi_protocol_version_out *out = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!msg->out_msg || msg->out_msg_sz < sizeof(*out))
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						out = (struct scmi_protocol_version_out *)msg->out_msg;
 | 
				
			||||||
 | 
						out->version = SANDBOX_SCMI_BASE_PROTOCOL_VERSION;
 | 
				
			||||||
 | 
						out->status = SCMI_SUCCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * sandbox_scmi_base_protocol_attrs - implement SCMI_BASE_PROTOCOL_ATTRIBUTES
 | 
				
			||||||
 | 
					 * @dev:	SCMI device
 | 
				
			||||||
 | 
					 * @msg:	SCMI message
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Implement SCMI_BASE_PROTOCOL_ATTRIBUTES command.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int sandbox_scmi_base_protocol_attrs(struct udevice *dev,
 | 
				
			||||||
 | 
										    struct scmi_msg *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scmi_protocol_attrs_out *out = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!msg->out_msg || msg->out_msg_sz < sizeof(*out))
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						out = (struct scmi_protocol_attrs_out *)msg->out_msg;
 | 
				
			||||||
 | 
						out->attributes = FIELD_PREP(0xff00, 2) | NUM_PROTOCOLS;
 | 
				
			||||||
 | 
						out->status = SCMI_SUCCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * sandbox_scmi_base_message_attrs - implement
 | 
				
			||||||
 | 
					 *					SCMI_BASE_PROTOCOL_MESSAGE_ATTRIBUTES
 | 
				
			||||||
 | 
					 * @dev:	SCMI device
 | 
				
			||||||
 | 
					 * @msg:	SCMI message
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Implement SCMI_BASE_PROTOCOL_MESSAGE_ATTRIBUTES command.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int sandbox_scmi_base_message_attrs(struct udevice *dev,
 | 
				
			||||||
 | 
										   struct scmi_msg *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u32 message_id;
 | 
				
			||||||
 | 
						struct scmi_protocol_msg_attrs_out *out = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!msg->in_msg || msg->in_msg_sz < sizeof(message_id) ||
 | 
				
			||||||
 | 
						    !msg->out_msg || msg->out_msg_sz < sizeof(*out))
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						message_id = *(u32 *)msg->in_msg;
 | 
				
			||||||
 | 
						out = (struct scmi_protocol_msg_attrs_out *)msg->out_msg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (message_id >= SCMI_PROTOCOL_VERSION &&
 | 
				
			||||||
 | 
						    message_id <= SCMI_BASE_RESET_AGENT_CONFIGURATION &&
 | 
				
			||||||
 | 
						    message_id != SCMI_BASE_NOTIFY_ERRORS) {
 | 
				
			||||||
 | 
							out->attributes = 0;
 | 
				
			||||||
 | 
							out->status = SCMI_SUCCESS;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							out->status = SCMI_NOT_FOUND;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * sandbox_scmi_base_discover_vendor - implement SCMI_BASE_DISCOVER_VENDOR
 | 
				
			||||||
 | 
					 * @dev:	SCMI device
 | 
				
			||||||
 | 
					 * @msg:	SCMI message
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Implement SCMI_BASE_DISCOVER_VENDOR command
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int sandbox_scmi_base_discover_vendor(struct udevice *dev,
 | 
				
			||||||
 | 
										     struct scmi_msg *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scmi_base_discover_vendor_out *out = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!msg->out_msg || msg->out_msg_sz < sizeof(*out))
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						out = (struct scmi_base_discover_vendor_out *)msg->out_msg;
 | 
				
			||||||
 | 
						strcpy(out->vendor_identifier, SANDBOX_SCMI_VENDOR);
 | 
				
			||||||
 | 
						out->status = SCMI_SUCCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * sandbox_scmi_base_discover_sub_vendor - implement
 | 
				
			||||||
 | 
					 *						SCMI_BASE_DISCOVER_SUB_VENDOR
 | 
				
			||||||
 | 
					 * @dev:	SCMI device
 | 
				
			||||||
 | 
					 * @msg:	SCMI message
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Implement SCMI_BASE_DISCOVER_SUB_VENDOR command
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int sandbox_scmi_base_discover_sub_vendor(struct udevice *dev,
 | 
				
			||||||
 | 
											 struct scmi_msg *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scmi_base_discover_vendor_out *out = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!msg->out_msg || msg->out_msg_sz < sizeof(*out))
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						out = (struct scmi_base_discover_vendor_out *)msg->out_msg;
 | 
				
			||||||
 | 
						strcpy(out->vendor_identifier, SANDBOX_SCMI_SUB_VENDOR);
 | 
				
			||||||
 | 
						out->status = SCMI_SUCCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * sandbox_scmi_base_discover_impl_version - implement
 | 
				
			||||||
 | 
					 *				SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION
 | 
				
			||||||
 | 
					 * @dev:	SCMI device
 | 
				
			||||||
 | 
					 * @msg:	SCMI message
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Implement SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION command
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int sandbox_scmi_base_discover_impl_version(struct udevice *dev,
 | 
				
			||||||
 | 
											   struct scmi_msg *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scmi_base_discover_impl_version_out *out = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!msg->out_msg || msg->out_msg_sz < sizeof(*out))
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						out = (struct scmi_base_discover_impl_version_out *)msg->out_msg;
 | 
				
			||||||
 | 
						out->impl_version = SANDBOX_SCMI_IMPL_VERSION;
 | 
				
			||||||
 | 
						out->status = SCMI_SUCCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * sandbox_scmi_base_discover_list_protocols - implement
 | 
				
			||||||
 | 
					 *					SCMI_BASE_DISCOVER_LIST_PROTOCOLS
 | 
				
			||||||
 | 
					 * @dev:	SCMI device
 | 
				
			||||||
 | 
					 * @msg:	SCMI message
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Implement SCMI_BASE_DISCOVER_LIST_PROTOCOLS command
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int sandbox_scmi_base_discover_list_protocols(struct udevice *dev,
 | 
				
			||||||
 | 
											     struct scmi_msg *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scmi_base_discover_list_protocols_out *out = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!msg->out_msg || msg->out_msg_sz < sizeof(*out))
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						out = (struct scmi_base_discover_list_protocols_out *)msg->out_msg;
 | 
				
			||||||
 | 
						memcpy(out->protocols, protocols, sizeof(protocols));
 | 
				
			||||||
 | 
						out->num_protocols = NUM_PROTOCOLS;
 | 
				
			||||||
 | 
						out->status = SCMI_SUCCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * sandbox_scmi_base_discover_agent - implement SCMI_BASE_DISCOVER_AGENT
 | 
				
			||||||
 | 
					 * @dev:	SCMI device
 | 
				
			||||||
 | 
					 * @msg:	SCMI message
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Implement SCMI_BASE_DISCOVER_AGENT command
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int sandbox_scmi_base_discover_agent(struct udevice *dev,
 | 
				
			||||||
 | 
										    struct scmi_msg *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u32 agent_id;
 | 
				
			||||||
 | 
						struct scmi_base_discover_agent_out *out = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!msg->in_msg || msg->in_msg_sz < sizeof(agent_id) ||
 | 
				
			||||||
 | 
						    !msg->out_msg || msg->out_msg_sz < sizeof(*out))
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						agent_id = *(u32 *)msg->in_msg;
 | 
				
			||||||
 | 
						out = (struct scmi_base_discover_agent_out *)msg->out_msg;
 | 
				
			||||||
 | 
						out->status = SCMI_SUCCESS;
 | 
				
			||||||
 | 
						if (agent_id == 0xffffffff || agent_id == 1) {
 | 
				
			||||||
 | 
							out->agent_id = 1;
 | 
				
			||||||
 | 
							strcpy(out->name, SANDBOX_SCMI_AGENT_NAME);
 | 
				
			||||||
 | 
						} else if (!agent_id) {
 | 
				
			||||||
 | 
							out->agent_id = agent_id;
 | 
				
			||||||
 | 
							strcpy(out->name, SANDBOX_SCMI_PLATFORM_NAME);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							out->status = SCMI_NOT_FOUND;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * sandbox_scmi_base_set_device_permissions - implement
 | 
				
			||||||
 | 
					 *						SCMI_BASE_SET_DEVICE_PERMISSIONS
 | 
				
			||||||
 | 
					 * @dev:	SCMI device
 | 
				
			||||||
 | 
					 * @msg:	SCMI message
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Implement SCMI_BASE_SET_DEVICE_PERMISSIONS command
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int sandbox_scmi_base_set_device_permissions(struct udevice *dev,
 | 
				
			||||||
 | 
											    struct scmi_msg *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scmi_base_set_device_permissions_in *in = NULL;
 | 
				
			||||||
 | 
						u32 *status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
 | 
				
			||||||
 | 
						    !msg->out_msg || msg->out_msg_sz < sizeof(*status))
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						in = (struct scmi_base_set_device_permissions_in *)msg->in_msg;
 | 
				
			||||||
 | 
						status = (u32 *)msg->out_msg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (in->agent_id != 1 || in->device_id != 0)
 | 
				
			||||||
 | 
							*status = SCMI_NOT_FOUND;
 | 
				
			||||||
 | 
						else if (in->flags & ~SCMI_BASE_SET_DEVICE_PERMISSIONS_ACCESS)
 | 
				
			||||||
 | 
							*status = SCMI_INVALID_PARAMETERS;
 | 
				
			||||||
 | 
						else if (in->flags & SCMI_BASE_SET_DEVICE_PERMISSIONS_ACCESS)
 | 
				
			||||||
 | 
							*status = SCMI_SUCCESS;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							/* unset not allowed */
 | 
				
			||||||
 | 
							*status = SCMI_DENIED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * sandbox_scmi_base_set_protocol_permissions - implement
 | 
				
			||||||
 | 
					 *					SCMI_BASE_SET_PROTOCOL_PERMISSIONS
 | 
				
			||||||
 | 
					 * @dev:	SCMI device
 | 
				
			||||||
 | 
					 * @msg:	SCMI message
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Implement SCMI_BASE_SET_PROTOCOL_PERMISSIONS command
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int sandbox_scmi_base_set_protocol_permissions(struct udevice *dev,
 | 
				
			||||||
 | 
											      struct scmi_msg *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scmi_base_set_protocol_permissions_in *in = NULL;
 | 
				
			||||||
 | 
						u32 *status;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
 | 
				
			||||||
 | 
						    !msg->out_msg || msg->out_msg_sz < sizeof(*status))
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						in = (struct scmi_base_set_protocol_permissions_in *)msg->in_msg;
 | 
				
			||||||
 | 
						status = (u32 *)msg->out_msg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < ARRAY_SIZE(protocols); i++)
 | 
				
			||||||
 | 
							if (protocols[i] == in->command_id)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
						if (in->agent_id != 1 || in->device_id != 0 ||
 | 
				
			||||||
 | 
						    i == ARRAY_SIZE(protocols))
 | 
				
			||||||
 | 
							*status = SCMI_NOT_FOUND;
 | 
				
			||||||
 | 
						else if (in->flags & ~SCMI_BASE_SET_PROTOCOL_PERMISSIONS_ACCESS)
 | 
				
			||||||
 | 
							*status = SCMI_INVALID_PARAMETERS;
 | 
				
			||||||
 | 
						else if (in->flags & SCMI_BASE_SET_PROTOCOL_PERMISSIONS_ACCESS)
 | 
				
			||||||
 | 
							*status = SCMI_SUCCESS;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							/* unset not allowed */
 | 
				
			||||||
 | 
							*status = SCMI_DENIED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * sandbox_scmi_base_reset_agent_configuration - implement
 | 
				
			||||||
 | 
					 *					SCMI_BASE_RESET_AGENT_CONFIGURATION
 | 
				
			||||||
 | 
					 * @dev:	SCMI device
 | 
				
			||||||
 | 
					 * @msg:	SCMI message
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Implement SCMI_BASE_RESET_AGENT_CONFIGURATION command
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int sandbox_scmi_base_reset_agent_configuration(struct udevice *dev,
 | 
				
			||||||
 | 
											       struct scmi_msg *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scmi_base_reset_agent_configuration_in *in = NULL;
 | 
				
			||||||
 | 
						u32 *status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
 | 
				
			||||||
 | 
						    !msg->out_msg || msg->out_msg_sz < sizeof(*status))
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						in = (struct scmi_base_reset_agent_configuration_in *)msg->in_msg;
 | 
				
			||||||
 | 
						status = (u32 *)msg->out_msg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (in->agent_id != 1)
 | 
				
			||||||
 | 
							*status = SCMI_NOT_FOUND;
 | 
				
			||||||
 | 
						else if (in->flags & ~SCMI_BASE_RESET_ALL_ACCESS_PERMISSIONS)
 | 
				
			||||||
 | 
							*status = SCMI_INVALID_PARAMETERS;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							*status = SCMI_DENIED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Clock Protocol */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int sandbox_scmi_clock_protocol_attribs(struct udevice *dev,
 | 
					static int sandbox_scmi_clock_protocol_attribs(struct udevice *dev,
 | 
				
			||||||
					       struct scmi_msg *msg)
 | 
										       struct scmi_msg *msg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -470,11 +816,108 @@ static int sandbox_scmi_voltd_level_get(struct udevice *dev,
 | 
				
			|||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * sandbox_scmi_of_get_channel - assigne a channel
 | 
				
			||||||
 | 
					 * @dev:	SCMI agent device
 | 
				
			||||||
 | 
					 * @protocol:	SCMI protocol device
 | 
				
			||||||
 | 
					 * @channel:	Pointer to channel info
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Assign a channel for the protocol, @protocol, in @channel,
 | 
				
			||||||
 | 
					 * based on a device tree's property.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int sandbox_scmi_of_get_channel(struct udevice *dev,
 | 
				
			||||||
 | 
									       struct udevice *protocol,
 | 
				
			||||||
 | 
									       struct scmi_channel **channel)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct sandbox_channel *agent_chan = dev_get_plat(dev);
 | 
				
			||||||
 | 
						struct sandbox_channel *chan;
 | 
				
			||||||
 | 
						u32 channel_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (dev_read_u32(protocol, "linaro,sandbox-channel-id", &channel_id)) {
 | 
				
			||||||
 | 
							/* Uses agent channel */
 | 
				
			||||||
 | 
							*channel = container_of(agent_chan, struct scmi_channel, ref);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Setup a dedicated channel */
 | 
				
			||||||
 | 
						chan = calloc(1, sizeof(*chan));
 | 
				
			||||||
 | 
						if (!chan)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						chan->channel_id = channel_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*channel = container_of(chan, struct scmi_channel, ref);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * sandbox_scmi_of_to_plat - assigne a channel to agent
 | 
				
			||||||
 | 
					 * @dev:	SCMI agent device
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Assign a channel for the agent, @protocol.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: always 0
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int sandbox_scmi_of_to_plat(struct udevice *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct sandbox_channel *chan = dev_get_plat(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* The channel for agent is always 0 */
 | 
				
			||||||
 | 
						chan->channel_id = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unsigned int sandbox_scmi_channel_id(struct udevice *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scmi_agent_proto_priv *priv;
 | 
				
			||||||
 | 
						struct sandbox_channel *chan;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						priv = dev_get_parent_priv(dev);
 | 
				
			||||||
 | 
						chan = (struct sandbox_channel *)&priv->channel->ref;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return chan->channel_id;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int sandbox_scmi_test_process_msg(struct udevice *dev,
 | 
					static int sandbox_scmi_test_process_msg(struct udevice *dev,
 | 
				
			||||||
					 struct scmi_channel *channel,
 | 
										 struct scmi_channel *channel,
 | 
				
			||||||
					 struct scmi_msg *msg)
 | 
										 struct scmi_msg *msg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	switch (msg->protocol_id) {
 | 
						switch (msg->protocol_id) {
 | 
				
			||||||
 | 
						case SCMI_PROTOCOL_ID_BASE:
 | 
				
			||||||
 | 
							switch (msg->message_id) {
 | 
				
			||||||
 | 
							case SCMI_PROTOCOL_VERSION:
 | 
				
			||||||
 | 
								return sandbox_scmi_base_protocol_version(dev, msg);
 | 
				
			||||||
 | 
							case SCMI_PROTOCOL_ATTRIBUTES:
 | 
				
			||||||
 | 
								return sandbox_scmi_base_protocol_attrs(dev, msg);
 | 
				
			||||||
 | 
							case SCMI_PROTOCOL_MESSAGE_ATTRIBUTES:
 | 
				
			||||||
 | 
								return sandbox_scmi_base_message_attrs(dev, msg);
 | 
				
			||||||
 | 
							case SCMI_BASE_DISCOVER_VENDOR:
 | 
				
			||||||
 | 
								return sandbox_scmi_base_discover_vendor(dev, msg);
 | 
				
			||||||
 | 
							case SCMI_BASE_DISCOVER_SUB_VENDOR:
 | 
				
			||||||
 | 
								return sandbox_scmi_base_discover_sub_vendor(dev, msg);
 | 
				
			||||||
 | 
							case SCMI_BASE_DISCOVER_IMPL_VERSION:
 | 
				
			||||||
 | 
								return sandbox_scmi_base_discover_impl_version(dev, msg);
 | 
				
			||||||
 | 
							case SCMI_BASE_DISCOVER_LIST_PROTOCOLS:
 | 
				
			||||||
 | 
								return sandbox_scmi_base_discover_list_protocols(dev, msg);
 | 
				
			||||||
 | 
							case SCMI_BASE_DISCOVER_AGENT:
 | 
				
			||||||
 | 
								return sandbox_scmi_base_discover_agent(dev, msg);
 | 
				
			||||||
 | 
							case SCMI_BASE_NOTIFY_ERRORS:
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case SCMI_BASE_SET_DEVICE_PERMISSIONS:
 | 
				
			||||||
 | 
								return sandbox_scmi_base_set_device_permissions(dev, msg);
 | 
				
			||||||
 | 
							case SCMI_BASE_SET_PROTOCOL_PERMISSIONS:
 | 
				
			||||||
 | 
								return sandbox_scmi_base_set_protocol_permissions(dev, msg);
 | 
				
			||||||
 | 
							case SCMI_BASE_RESET_AGENT_CONFIGURATION:
 | 
				
			||||||
 | 
								return sandbox_scmi_base_reset_agent_configuration(dev, msg);
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	case SCMI_PROTOCOL_ID_CLOCK:
 | 
						case SCMI_PROTOCOL_ID_CLOCK:
 | 
				
			||||||
		switch (msg->message_id) {
 | 
							switch (msg->message_id) {
 | 
				
			||||||
		case SCMI_PROTOCOL_ATTRIBUTES:
 | 
							case SCMI_PROTOCOL_ATTRIBUTES:
 | 
				
			||||||
@ -517,7 +960,6 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev,
 | 
				
			|||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SCMI_PROTOCOL_ID_BASE:
 | 
					 | 
				
			||||||
	case SCMI_PROTOCOL_ID_POWER_DOMAIN:
 | 
						case SCMI_PROTOCOL_ID_POWER_DOMAIN:
 | 
				
			||||||
	case SCMI_PROTOCOL_ID_SYSTEM:
 | 
						case SCMI_PROTOCOL_ID_SYSTEM:
 | 
				
			||||||
	case SCMI_PROTOCOL_ID_PERF:
 | 
						case SCMI_PROTOCOL_ID_PERF:
 | 
				
			||||||
@ -541,16 +983,8 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static int sandbox_scmi_test_remove(struct udevice *dev)
 | 
					static int sandbox_scmi_test_remove(struct udevice *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sandbox_scmi_agent *agent = dev_get_priv(dev);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (agent != sandbox_scmi_service_ctx()->agent)
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	debug_print_agent_state(dev, "removed");
 | 
						debug_print_agent_state(dev, "removed");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* We only need to dereference the agent in the context */
 | 
					 | 
				
			||||||
	sandbox_scmi_service_ctx()->agent = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -558,9 +992,6 @@ static int sandbox_scmi_test_probe(struct udevice *dev)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	struct sandbox_scmi_agent *agent = dev_get_priv(dev);
 | 
						struct sandbox_scmi_agent *agent = dev_get_priv(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sandbox_scmi_service_ctx()->agent)
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	*agent = (struct sandbox_scmi_agent){
 | 
						*agent = (struct sandbox_scmi_agent){
 | 
				
			||||||
		.clk = scmi_clk,
 | 
							.clk = scmi_clk,
 | 
				
			||||||
		.clk_count = ARRAY_SIZE(scmi_clk),
 | 
							.clk_count = ARRAY_SIZE(scmi_clk),
 | 
				
			||||||
@ -572,9 +1003,6 @@ static int sandbox_scmi_test_probe(struct udevice *dev)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	debug_print_agent_state(dev, "probed");
 | 
						debug_print_agent_state(dev, "probed");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Save reference for tests purpose */
 | 
					 | 
				
			||||||
	sandbox_scmi_service_ctx()->agent = agent;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -584,6 +1012,7 @@ static const struct udevice_id sandbox_scmi_test_ids[] = {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct scmi_agent_ops sandbox_scmi_test_ops = {
 | 
					struct scmi_agent_ops sandbox_scmi_test_ops = {
 | 
				
			||||||
 | 
						.of_get_channel = sandbox_scmi_of_get_channel,
 | 
				
			||||||
	.process_msg = sandbox_scmi_test_process_msg,
 | 
						.process_msg = sandbox_scmi_test_process_msg,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -592,6 +1021,8 @@ U_BOOT_DRIVER(sandbox_scmi_agent) = {
 | 
				
			|||||||
	.id = UCLASS_SCMI_AGENT,
 | 
						.id = UCLASS_SCMI_AGENT,
 | 
				
			||||||
	.of_match = sandbox_scmi_test_ids,
 | 
						.of_match = sandbox_scmi_test_ids,
 | 
				
			||||||
	.priv_auto	= sizeof(struct sandbox_scmi_agent),
 | 
						.priv_auto	= sizeof(struct sandbox_scmi_agent),
 | 
				
			||||||
 | 
						.plat_auto	= sizeof(struct sandbox_channel),
 | 
				
			||||||
 | 
						.of_to_plat	= sandbox_scmi_of_to_plat,
 | 
				
			||||||
	.probe = sandbox_scmi_test_probe,
 | 
						.probe = sandbox_scmi_test_probe,
 | 
				
			||||||
	.remove = sandbox_scmi_test_remove,
 | 
						.remove = sandbox_scmi_test_remove,
 | 
				
			||||||
	.ops = &sandbox_scmi_test_ops,
 | 
						.ops = &sandbox_scmi_test_ops,
 | 
				
			||||||
 | 
				
			|||||||
@ -8,6 +8,7 @@
 | 
				
			|||||||
#include <common.h>
 | 
					#include <common.h>
 | 
				
			||||||
#include <dm.h>
 | 
					#include <dm.h>
 | 
				
			||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <scmi_agent.h>
 | 
				
			||||||
#include <scmi_agent-uclass.h>
 | 
					#include <scmi_agent-uclass.h>
 | 
				
			||||||
#include <scmi_protocols.h>
 | 
					#include <scmi_protocols.h>
 | 
				
			||||||
#include <dm/device_compat.h>
 | 
					#include <dm/device_compat.h>
 | 
				
			||||||
@ -37,6 +38,118 @@ static const struct error_code scmi_linux_errmap[] = {
 | 
				
			|||||||
	{ .scmi = SCMI_PROTOCOL_ERROR, .errno = -EPROTO, },
 | 
						{ .scmi = SCMI_PROTOCOL_ERROR, .errno = -EPROTO, },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_protocol_is_supported - check availability of protocol
 | 
				
			||||||
 | 
					 * @dev:	SCMI agent device
 | 
				
			||||||
 | 
					 * @proto_id:	Identifier of protocol
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * check if the protocol, @proto_id, is provided by the SCMI agent,
 | 
				
			||||||
 | 
					 * @dev.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return:	0 on success, error code otherwise
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static bool scmi_protocol_is_supported(struct udevice *dev,
 | 
				
			||||||
 | 
									       enum scmi_std_protocol proto_id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scmi_agent_priv *priv;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (proto_id == SCMI_PROTOCOL_ID_BASE)
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						priv = dev_get_uclass_plat(dev);
 | 
				
			||||||
 | 
						if (!priv) {
 | 
				
			||||||
 | 
							dev_err(dev, "No priv data found\n");
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < priv->num_protocols; i++)
 | 
				
			||||||
 | 
							if (priv->protocols[i] == proto_id)
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct udevice *scmi_get_protocol(struct udevice *dev,
 | 
				
			||||||
 | 
									  enum scmi_std_protocol id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scmi_agent_priv *priv;
 | 
				
			||||||
 | 
						struct udevice *proto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						priv = dev_get_uclass_plat(dev);
 | 
				
			||||||
 | 
						if (!priv) {
 | 
				
			||||||
 | 
							dev_err(dev, "No priv data found\n");
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (id) {
 | 
				
			||||||
 | 
						case SCMI_PROTOCOL_ID_BASE:
 | 
				
			||||||
 | 
							proto = priv->base_dev;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SCMI_PROTOCOL_ID_CLOCK:
 | 
				
			||||||
 | 
							proto = priv->clock_dev;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SCMI_PROTOCOL_ID_RESET_DOMAIN:
 | 
				
			||||||
 | 
							proto = priv->resetdom_dev;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
 | 
				
			||||||
 | 
							proto = priv->voltagedom_dev;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							dev_err(dev, "Protocol not supported\n");
 | 
				
			||||||
 | 
							proto = NULL;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (proto && device_probe(proto))
 | 
				
			||||||
 | 
							dev_err(dev, "Probe failed\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return proto;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_add_protocol - add protocol to agent
 | 
				
			||||||
 | 
					 * @dev:	SCMI agent device
 | 
				
			||||||
 | 
					 * @proto_id:	SCMI protocol ID
 | 
				
			||||||
 | 
					 * @proto:	SCMI protocol device
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Associate the protocol instance, @proto, to the agent, @dev,
 | 
				
			||||||
 | 
					 * for later use.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return:	0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int scmi_add_protocol(struct udevice *dev,
 | 
				
			||||||
 | 
								     enum scmi_std_protocol proto_id,
 | 
				
			||||||
 | 
								     struct udevice *proto)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scmi_agent_priv *priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						priv = dev_get_uclass_plat(dev);
 | 
				
			||||||
 | 
						if (!priv) {
 | 
				
			||||||
 | 
							dev_err(dev, "No priv data found\n");
 | 
				
			||||||
 | 
							return -ENODEV;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (proto_id) {
 | 
				
			||||||
 | 
						case SCMI_PROTOCOL_ID_BASE:
 | 
				
			||||||
 | 
							priv->base_dev = proto;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SCMI_PROTOCOL_ID_CLOCK:
 | 
				
			||||||
 | 
							priv->clock_dev = proto;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SCMI_PROTOCOL_ID_RESET_DOMAIN:
 | 
				
			||||||
 | 
							priv->resetdom_dev = proto;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
 | 
				
			||||||
 | 
							priv->voltagedom_dev = proto;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							dev_err(dev, "Protocol not supported\n");
 | 
				
			||||||
 | 
							return -EPROTO;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int scmi_to_linux_errno(s32 scmi_code)
 | 
					int scmi_to_linux_errno(s32 scmi_code)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int n;
 | 
						int n;
 | 
				
			||||||
@ -51,8 +164,191 @@ int scmi_to_linux_errno(s32 scmi_code)
 | 
				
			|||||||
	return -EPROTO;
 | 
						return -EPROTO;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct udevice *find_scmi_protocol_device(struct udevice *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct udevice *parent = NULL, *protocol;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (protocol = dev; protocol; protocol = parent) {
 | 
				
			||||||
 | 
							parent = dev_get_parent(protocol);
 | 
				
			||||||
 | 
							if (!parent ||
 | 
				
			||||||
 | 
							    device_get_uclass_id(parent) == UCLASS_SCMI_AGENT)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!parent) {
 | 
				
			||||||
 | 
							dev_err(dev, "Invalid SCMI device, agent not found\n");
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return protocol;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct scmi_agent_ops *transport_dev_ops(struct udevice *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (const struct scmi_agent_ops *)dev->driver->ops;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_of_get_channel() - Get SCMI channel handle
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @dev:	SCMI agent device
 | 
				
			||||||
 | 
					 * @channel:	Output reference to the SCMI channel upon success
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * On return, @channel will be set.
 | 
				
			||||||
 | 
					 * Return	0 on success and a negative errno on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int scmi_of_get_channel(struct udevice *dev, struct udevice *protocol,
 | 
				
			||||||
 | 
								       struct scmi_channel **channel)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct scmi_agent_ops *ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ops = transport_dev_ops(dev);
 | 
				
			||||||
 | 
						if (ops->of_get_channel)
 | 
				
			||||||
 | 
							return ops->of_get_channel(dev, protocol, channel);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return -EPROTONOSUPPORT;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int devm_scmi_of_get_channel(struct udevice *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct udevice *protocol;
 | 
				
			||||||
 | 
						struct scmi_agent_proto_priv *priv;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protocol = find_scmi_protocol_device(dev);
 | 
				
			||||||
 | 
						if (!protocol)
 | 
				
			||||||
 | 
							return -ENODEV;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						priv = dev_get_parent_priv(protocol);
 | 
				
			||||||
 | 
						ret = scmi_of_get_channel(protocol->parent, protocol, &priv->channel);
 | 
				
			||||||
 | 
						if (ret == -EPROTONOSUPPORT) {
 | 
				
			||||||
 | 
							/* Drivers without a get_channel operator don't need a channel ref */
 | 
				
			||||||
 | 
							priv->channel = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_process_msg() - Send and process an SCMI message
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Send a message to an SCMI server.
 | 
				
			||||||
 | 
					 * Caller sets scmi_msg::out_msg_sz to the output message buffer size.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @dev:	SCMI agent device
 | 
				
			||||||
 | 
					 * @channel:	Communication channel for the device
 | 
				
			||||||
 | 
					 * @msg:	Message structure reference
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * On return, scmi_msg::out_msg_sz stores the response payload size.
 | 
				
			||||||
 | 
					 * Return:	0 on success and a negative errno on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int scmi_process_msg(struct udevice *dev, struct scmi_channel *channel,
 | 
				
			||||||
 | 
								    struct scmi_msg *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct scmi_agent_ops *ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ops = transport_dev_ops(dev);
 | 
				
			||||||
 | 
						if (ops->process_msg)
 | 
				
			||||||
 | 
							return ops->process_msg(dev, channel, msg);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return -EPROTONOSUPPORT;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct udevice *protocol;
 | 
				
			||||||
 | 
						struct scmi_agent_proto_priv *priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protocol = find_scmi_protocol_device(dev);
 | 
				
			||||||
 | 
						if (!protocol)
 | 
				
			||||||
 | 
							return -ENODEV;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						priv = dev_get_parent_priv(protocol);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return scmi_process_msg(protocol->parent, priv->channel, msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_fill_base_info - get base information about SCMI server
 | 
				
			||||||
 | 
					 * @agent:	SCMI agent device
 | 
				
			||||||
 | 
					 * @dev:	SCMI protocol device
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * By using Base protocol commands, collect the base information
 | 
				
			||||||
 | 
					 * about SCMI server.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int scmi_fill_base_info(struct udevice *agent, struct udevice *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scmi_agent_priv *priv = dev_get_uclass_plat(agent);
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = scmi_base_protocol_version(dev, &priv->version);
 | 
				
			||||||
 | 
						if (ret) {
 | 
				
			||||||
 | 
							dev_err(dev, "protocol_version() failed (%d)\n", ret);
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						/* check for required version */
 | 
				
			||||||
 | 
						if (priv->version < SCMI_BASE_PROTOCOL_VERSION) {
 | 
				
			||||||
 | 
							dev_err(dev, "base protocol version (%d) lower than expected\n",
 | 
				
			||||||
 | 
								priv->version);
 | 
				
			||||||
 | 
							return -EPROTO;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = scmi_base_protocol_attrs(dev, &priv->num_agents,
 | 
				
			||||||
 | 
									       &priv->num_protocols);
 | 
				
			||||||
 | 
						if (ret) {
 | 
				
			||||||
 | 
							dev_err(dev, "protocol_attrs() failed (%d)\n", ret);
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ret = scmi_base_discover_vendor(dev, &priv->vendor);
 | 
				
			||||||
 | 
						if (ret) {
 | 
				
			||||||
 | 
							dev_err(dev, "base_discover_vendor() failed (%d)\n", ret);
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ret = scmi_base_discover_sub_vendor(dev, &priv->sub_vendor);
 | 
				
			||||||
 | 
						if (ret) {
 | 
				
			||||||
 | 
							if (ret != -EOPNOTSUPP) {
 | 
				
			||||||
 | 
								dev_err(dev, "base_discover_sub_vendor() failed (%d)\n",
 | 
				
			||||||
 | 
									ret);
 | 
				
			||||||
 | 
								return ret;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							priv->sub_vendor = "NA";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ret = scmi_base_discover_impl_version(dev, &priv->impl_version);
 | 
				
			||||||
 | 
						if (ret) {
 | 
				
			||||||
 | 
							dev_err(dev, "base_discover_impl_version() failed (%d)\n",
 | 
				
			||||||
 | 
								ret);
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = scmi_base_discover_agent(dev, 0xffffffff,
 | 
				
			||||||
 | 
									       &priv->agent_id, &priv->agent_name);
 | 
				
			||||||
 | 
						if (ret) {
 | 
				
			||||||
 | 
							if (ret != -EOPNOTSUPP) {
 | 
				
			||||||
 | 
								dev_err(dev,
 | 
				
			||||||
 | 
									"base_discover_agent() failed for myself (%d)\n",
 | 
				
			||||||
 | 
									ret);
 | 
				
			||||||
 | 
								return ret;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							priv->agent_id = 0xffffffff;
 | 
				
			||||||
 | 
							priv->agent_name = "NA";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = scmi_base_discover_list_protocols(dev, &priv->protocols);
 | 
				
			||||||
 | 
						if (ret != priv->num_protocols) {
 | 
				
			||||||
 | 
							dev_err(dev, "base_discover_list_protocols() failed (%d)\n",
 | 
				
			||||||
 | 
								ret);
 | 
				
			||||||
 | 
							return -EPROTO;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * SCMI agent devices binds devices of various uclasses depeding on
 | 
					 * SCMI agent devices binds devices of various uclasses depending on
 | 
				
			||||||
 * the FDT description. scmi_bind_protocol() is a generic bind sequence
 | 
					 * the FDT description. scmi_bind_protocol() is a generic bind sequence
 | 
				
			||||||
 * called by the uclass at bind stage, that is uclass post_bind.
 | 
					 * called by the uclass at bind stage, that is uclass post_bind.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -61,9 +357,43 @@ static int scmi_bind_protocols(struct udevice *dev)
 | 
				
			|||||||
	int ret = 0;
 | 
						int ret = 0;
 | 
				
			||||||
	ofnode node;
 | 
						ofnode node;
 | 
				
			||||||
	const char *name;
 | 
						const char *name;
 | 
				
			||||||
 | 
						struct driver *drv;
 | 
				
			||||||
 | 
						struct udevice *agent, *proto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!uclass_get_device(UCLASS_SCMI_AGENT, 1, &agent)) {
 | 
				
			||||||
 | 
							/* This is a second SCMI agent */
 | 
				
			||||||
 | 
							dev_err(dev, "Cannot have more than one SCMI agent\n");
 | 
				
			||||||
 | 
							return -EEXIST;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* initialize the device from device tree */
 | 
				
			||||||
 | 
						drv = DM_DRIVER_GET(scmi_base_drv);
 | 
				
			||||||
 | 
						name = "scmi-base.0";
 | 
				
			||||||
 | 
						ret = device_bind(dev, drv, name, NULL, ofnode_null(), &proto);
 | 
				
			||||||
 | 
						if (ret) {
 | 
				
			||||||
 | 
							dev_err(dev, "failed to bind base protocol\n");
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ret = scmi_add_protocol(dev, SCMI_PROTOCOL_ID_BASE, proto);
 | 
				
			||||||
 | 
						if (ret) {
 | 
				
			||||||
 | 
							dev_err(dev, "failed to add protocol: %s, ret: %d\n",
 | 
				
			||||||
 | 
								proto->name, ret);
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = device_probe(proto);
 | 
				
			||||||
 | 
						if (ret) {
 | 
				
			||||||
 | 
							dev_err(dev, "failed to probe base protocol\n");
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = scmi_fill_base_info(dev, proto);
 | 
				
			||||||
 | 
						if (ret) {
 | 
				
			||||||
 | 
							dev_err(dev, "failed to get base information\n");
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_for_each_subnode(node, dev) {
 | 
						dev_for_each_subnode(node, dev) {
 | 
				
			||||||
		struct driver *drv = NULL;
 | 
					 | 
				
			||||||
		u32 protocol_id;
 | 
							u32 protocol_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!ofnode_is_enabled(node))
 | 
							if (!ofnode_is_enabled(node))
 | 
				
			||||||
@ -72,18 +402,22 @@ static int scmi_bind_protocols(struct udevice *dev)
 | 
				
			|||||||
		if (ofnode_read_u32(node, "reg", &protocol_id))
 | 
							if (ofnode_read_u32(node, "reg", &protocol_id))
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							drv = NULL;
 | 
				
			||||||
		name = ofnode_get_name(node);
 | 
							name = ofnode_get_name(node);
 | 
				
			||||||
		switch (protocol_id) {
 | 
							switch (protocol_id) {
 | 
				
			||||||
		case SCMI_PROTOCOL_ID_CLOCK:
 | 
							case SCMI_PROTOCOL_ID_CLOCK:
 | 
				
			||||||
			if (CONFIG_IS_ENABLED(CLK_SCMI))
 | 
								if (CONFIG_IS_ENABLED(CLK_SCMI) &&
 | 
				
			||||||
 | 
								    scmi_protocol_is_supported(dev, protocol_id))
 | 
				
			||||||
				drv = DM_DRIVER_GET(scmi_clock);
 | 
									drv = DM_DRIVER_GET(scmi_clock);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case SCMI_PROTOCOL_ID_RESET_DOMAIN:
 | 
							case SCMI_PROTOCOL_ID_RESET_DOMAIN:
 | 
				
			||||||
			if (IS_ENABLED(CONFIG_RESET_SCMI))
 | 
								if (IS_ENABLED(CONFIG_RESET_SCMI) &&
 | 
				
			||||||
 | 
								    scmi_protocol_is_supported(dev, protocol_id))
 | 
				
			||||||
				drv = DM_DRIVER_GET(scmi_reset_domain);
 | 
									drv = DM_DRIVER_GET(scmi_reset_domain);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
 | 
							case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
 | 
				
			||||||
			if (IS_ENABLED(CONFIG_DM_REGULATOR_SCMI)) {
 | 
								if (IS_ENABLED(CONFIG_DM_REGULATOR_SCMI) &&
 | 
				
			||||||
 | 
								    scmi_protocol_is_supported(dev, protocol_id)) {
 | 
				
			||||||
				node = ofnode_find_subnode(node, "regulators");
 | 
									node = ofnode_find_subnode(node, "regulators");
 | 
				
			||||||
				if (!ofnode_valid(node)) {
 | 
									if (!ofnode_valid(node)) {
 | 
				
			||||||
					dev_err(dev, "no regulators node\n");
 | 
										dev_err(dev, "no regulators node\n");
 | 
				
			||||||
@ -102,70 +436,26 @@ static int scmi_bind_protocols(struct udevice *dev)
 | 
				
			|||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ret = device_bind(dev, drv, name, NULL, node, NULL);
 | 
							ret = device_bind(dev, drv, name, NULL, node, &proto);
 | 
				
			||||||
		if (ret)
 | 
							if (ret) {
 | 
				
			||||||
 | 
								dev_err(dev, "failed to bind %s protocol\n", drv->name);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ret = scmi_add_protocol(dev, protocol_id, proto);
 | 
				
			||||||
 | 
							if (ret) {
 | 
				
			||||||
 | 
								dev_err(dev, "failed to add protocol: %s, ret: %d\n",
 | 
				
			||||||
 | 
									proto->name, ret);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct udevice *find_scmi_transport_device(struct udevice *dev)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct udevice *parent = dev;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	do {
 | 
					 | 
				
			||||||
		parent = dev_get_parent(parent);
 | 
					 | 
				
			||||||
	} while (parent && device_get_uclass_id(parent) != UCLASS_SCMI_AGENT);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!parent)
 | 
					 | 
				
			||||||
		dev_err(dev, "Invalid SCMI device, agent not found\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return parent;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const struct scmi_agent_ops *transport_dev_ops(struct udevice *dev)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return (const struct scmi_agent_ops *)dev->driver->ops;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int devm_scmi_of_get_channel(struct udevice *dev, struct scmi_channel **channel)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct udevice *parent;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	parent = find_scmi_transport_device(dev);
 | 
					 | 
				
			||||||
	if (!parent)
 | 
					 | 
				
			||||||
		return -ENODEV;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (transport_dev_ops(parent)->of_get_channel)
 | 
					 | 
				
			||||||
		return transport_dev_ops(parent)->of_get_channel(parent, channel);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Drivers without a get_channel operator don't need a channel ref */
 | 
					 | 
				
			||||||
	*channel = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int devm_scmi_process_msg(struct udevice *dev, struct scmi_channel *channel,
 | 
					 | 
				
			||||||
			  struct scmi_msg *msg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	const struct scmi_agent_ops *ops;
 | 
					 | 
				
			||||||
	struct udevice *parent;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	parent = find_scmi_transport_device(dev);
 | 
					 | 
				
			||||||
	if (!parent)
 | 
					 | 
				
			||||||
		return -ENODEV;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ops = transport_dev_ops(parent);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (ops->process_msg)
 | 
					 | 
				
			||||||
		return ops->process_msg(parent, channel, msg);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return -EPROTONOSUPPORT;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
UCLASS_DRIVER(scmi_agent) = {
 | 
					UCLASS_DRIVER(scmi_agent) = {
 | 
				
			||||||
	.id		= UCLASS_SCMI_AGENT,
 | 
						.id		= UCLASS_SCMI_AGENT,
 | 
				
			||||||
	.name		= "scmi_agent",
 | 
						.name		= "scmi_agent",
 | 
				
			||||||
	.post_bind	= scmi_bind_protocols,
 | 
						.post_bind	= scmi_bind_protocols,
 | 
				
			||||||
 | 
						.per_device_plat_auto = sizeof(struct scmi_agent_priv),
 | 
				
			||||||
 | 
						.per_child_auto	= sizeof(struct scmi_agent_proto_priv),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -81,6 +81,7 @@ static int setup_channel(struct udevice *dev, struct scmi_smccc_channel *chan)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int scmi_smccc_get_channel(struct udevice *dev,
 | 
					static int scmi_smccc_get_channel(struct udevice *dev,
 | 
				
			||||||
 | 
									  struct udevice *protocol,
 | 
				
			||||||
				  struct scmi_channel **channel)
 | 
									  struct scmi_channel **channel)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct scmi_smccc_channel *base_chan = dev_get_plat(dev);
 | 
						struct scmi_smccc_channel *base_chan = dev_get_plat(dev);
 | 
				
			||||||
@ -88,7 +89,7 @@ static int scmi_smccc_get_channel(struct udevice *dev,
 | 
				
			|||||||
	u32 func_id;
 | 
						u32 func_id;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (dev_read_u32(dev, "arm,smc-id", &func_id)) {
 | 
						if (dev_read_u32(protocol, "arm,smc-id", &func_id)) {
 | 
				
			||||||
		/* Uses agent base channel */
 | 
							/* Uses agent base channel */
 | 
				
			||||||
		*channel = container_of(base_chan, struct scmi_channel, ref);
 | 
							*channel = container_of(base_chan, struct scmi_channel, ref);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -100,7 +101,7 @@ static int scmi_smccc_get_channel(struct udevice *dev,
 | 
				
			|||||||
	if (!chan)
 | 
						if (!chan)
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = setup_channel(dev, chan);
 | 
						ret = setup_channel(protocol, chan);
 | 
				
			||||||
	if (ret) {
 | 
						if (ret) {
 | 
				
			||||||
		free(chan);
 | 
							free(chan);
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
				
			|||||||
@ -25,18 +25,9 @@ struct scmi_regulator_platdata {
 | 
				
			|||||||
	u32 domain_id;
 | 
						u32 domain_id;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * struct scmi_regulator_priv - Private data for SCMI voltage regulator
 | 
					 | 
				
			||||||
 * @channel: Reference to the SCMI channel to use
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
struct scmi_regulator_priv {
 | 
					 | 
				
			||||||
	struct scmi_channel *channel;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int scmi_voltd_set_enable(struct udevice *dev, bool enable)
 | 
					static int scmi_voltd_set_enable(struct udevice *dev, bool enable)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
 | 
						struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
 | 
				
			||||||
	struct scmi_regulator_priv *priv = dev_get_priv(dev);
 | 
					 | 
				
			||||||
	struct scmi_voltd_config_set_in in = {
 | 
						struct scmi_voltd_config_set_in in = {
 | 
				
			||||||
		.domain_id = pdata->domain_id,
 | 
							.domain_id = pdata->domain_id,
 | 
				
			||||||
		.config = enable ? SCMI_VOLTD_CONFIG_ON : SCMI_VOLTD_CONFIG_OFF,
 | 
							.config = enable ? SCMI_VOLTD_CONFIG_ON : SCMI_VOLTD_CONFIG_OFF,
 | 
				
			||||||
@ -47,7 +38,7 @@ static int scmi_voltd_set_enable(struct udevice *dev, bool enable)
 | 
				
			|||||||
					  in, out);
 | 
										  in, out);
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = devm_scmi_process_msg(dev, priv->channel, &msg);
 | 
						ret = devm_scmi_process_msg(dev, &msg);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -57,7 +48,6 @@ static int scmi_voltd_set_enable(struct udevice *dev, bool enable)
 | 
				
			|||||||
static int scmi_voltd_get_enable(struct udevice *dev)
 | 
					static int scmi_voltd_get_enable(struct udevice *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
 | 
						struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
 | 
				
			||||||
	struct scmi_regulator_priv *priv = dev_get_priv(dev);
 | 
					 | 
				
			||||||
	struct scmi_voltd_config_get_in in = {
 | 
						struct scmi_voltd_config_get_in in = {
 | 
				
			||||||
		.domain_id = pdata->domain_id,
 | 
							.domain_id = pdata->domain_id,
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
@ -67,7 +57,7 @@ static int scmi_voltd_get_enable(struct udevice *dev)
 | 
				
			|||||||
					  in, out);
 | 
										  in, out);
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = devm_scmi_process_msg(dev, priv->channel, &msg);
 | 
						ret = devm_scmi_process_msg(dev, &msg);
 | 
				
			||||||
	if (ret < 0)
 | 
						if (ret < 0)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -80,7 +70,6 @@ static int scmi_voltd_get_enable(struct udevice *dev)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static int scmi_voltd_set_voltage_level(struct udevice *dev, int uV)
 | 
					static int scmi_voltd_set_voltage_level(struct udevice *dev, int uV)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct scmi_regulator_priv *priv = dev_get_priv(dev);
 | 
					 | 
				
			||||||
	struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
 | 
						struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
 | 
				
			||||||
	struct scmi_voltd_level_set_in in = {
 | 
						struct scmi_voltd_level_set_in in = {
 | 
				
			||||||
		.domain_id = pdata->domain_id,
 | 
							.domain_id = pdata->domain_id,
 | 
				
			||||||
@ -92,7 +81,7 @@ static int scmi_voltd_set_voltage_level(struct udevice *dev, int uV)
 | 
				
			|||||||
					  in, out);
 | 
										  in, out);
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = devm_scmi_process_msg(dev, priv->channel, &msg);
 | 
						ret = devm_scmi_process_msg(dev, &msg);
 | 
				
			||||||
	if (ret < 0)
 | 
						if (ret < 0)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -101,7 +90,6 @@ static int scmi_voltd_set_voltage_level(struct udevice *dev, int uV)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static int scmi_voltd_get_voltage_level(struct udevice *dev)
 | 
					static int scmi_voltd_get_voltage_level(struct udevice *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct scmi_regulator_priv *priv = dev_get_priv(dev);
 | 
					 | 
				
			||||||
	struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
 | 
						struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
 | 
				
			||||||
	struct scmi_voltd_level_get_in in = {
 | 
						struct scmi_voltd_level_get_in in = {
 | 
				
			||||||
		.domain_id = pdata->domain_id,
 | 
							.domain_id = pdata->domain_id,
 | 
				
			||||||
@ -112,7 +100,7 @@ static int scmi_voltd_get_voltage_level(struct udevice *dev)
 | 
				
			|||||||
					  in, out);
 | 
										  in, out);
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = devm_scmi_process_msg(dev, priv->channel, &msg);
 | 
						ret = devm_scmi_process_msg(dev, &msg);
 | 
				
			||||||
	if (ret < 0)
 | 
						if (ret < 0)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -140,7 +128,6 @@ static int scmi_regulator_of_to_plat(struct udevice *dev)
 | 
				
			|||||||
static int scmi_regulator_probe(struct udevice *dev)
 | 
					static int scmi_regulator_probe(struct udevice *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
 | 
						struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
 | 
				
			||||||
	struct scmi_regulator_priv *priv = dev_get_priv(dev);
 | 
					 | 
				
			||||||
	struct scmi_voltd_attr_in in = { 0 };
 | 
						struct scmi_voltd_attr_in in = { 0 };
 | 
				
			||||||
	struct scmi_voltd_attr_out out = { 0 };
 | 
						struct scmi_voltd_attr_out out = { 0 };
 | 
				
			||||||
	struct scmi_msg scmi_msg = {
 | 
						struct scmi_msg scmi_msg = {
 | 
				
			||||||
@ -153,14 +140,14 @@ static int scmi_regulator_probe(struct udevice *dev)
 | 
				
			|||||||
	};
 | 
						};
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = devm_scmi_of_get_channel(dev->parent, &priv->channel);
 | 
						ret = devm_scmi_of_get_channel(dev);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Check voltage domain is known from SCMI server */
 | 
						/* Check voltage domain is known from SCMI server */
 | 
				
			||||||
	in.domain_id = pdata->domain_id;
 | 
						in.domain_id = pdata->domain_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = devm_scmi_process_msg(dev, priv->channel, &scmi_msg);
 | 
						ret = devm_scmi_process_msg(dev, &scmi_msg);
 | 
				
			||||||
	if (ret) {
 | 
						if (ret) {
 | 
				
			||||||
		dev_err(dev, "Failed to query voltage domain %u: %d\n",
 | 
							dev_err(dev, "Failed to query voltage domain %u: %d\n",
 | 
				
			||||||
			pdata->domain_id, ret);
 | 
								pdata->domain_id, ret);
 | 
				
			||||||
@ -184,7 +171,6 @@ U_BOOT_DRIVER(scmi_regulator) = {
 | 
				
			|||||||
	.probe = scmi_regulator_probe,
 | 
						.probe = scmi_regulator_probe,
 | 
				
			||||||
	.of_to_plat = scmi_regulator_of_to_plat,
 | 
						.of_to_plat = scmi_regulator_of_to_plat,
 | 
				
			||||||
	.plat_auto = sizeof(struct scmi_regulator_platdata),
 | 
						.plat_auto = sizeof(struct scmi_regulator_platdata),
 | 
				
			||||||
	.priv_auto = sizeof(struct scmi_regulator_priv *),
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int scmi_regulator_bind(struct udevice *dev)
 | 
					static int scmi_regulator_bind(struct udevice *dev)
 | 
				
			||||||
 | 
				
			|||||||
@ -13,17 +13,8 @@
 | 
				
			|||||||
#include <scmi_protocols.h>
 | 
					#include <scmi_protocols.h>
 | 
				
			||||||
#include <asm/types.h>
 | 
					#include <asm/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * struct scmi_reset_priv - Private data for SCMI reset controller
 | 
					 | 
				
			||||||
 * @channel: Reference to the SCMI channel to use
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
struct scmi_reset_priv {
 | 
					 | 
				
			||||||
	struct scmi_channel *channel;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int scmi_reset_set_level(struct reset_ctl *rst, bool assert_not_deassert)
 | 
					static int scmi_reset_set_level(struct reset_ctl *rst, bool assert_not_deassert)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct scmi_reset_priv *priv = dev_get_priv(rst->dev);
 | 
					 | 
				
			||||||
	struct scmi_rd_reset_in in = {
 | 
						struct scmi_rd_reset_in in = {
 | 
				
			||||||
		.domain_id = rst->id,
 | 
							.domain_id = rst->id,
 | 
				
			||||||
		.flags = assert_not_deassert ? SCMI_RD_RESET_FLAG_ASSERT : 0,
 | 
							.flags = assert_not_deassert ? SCMI_RD_RESET_FLAG_ASSERT : 0,
 | 
				
			||||||
@ -35,7 +26,7 @@ static int scmi_reset_set_level(struct reset_ctl *rst, bool assert_not_deassert)
 | 
				
			|||||||
					  in, out);
 | 
										  in, out);
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = devm_scmi_process_msg(rst->dev, priv->channel, &msg);
 | 
						ret = devm_scmi_process_msg(rst->dev, &msg);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -54,7 +45,6 @@ static int scmi_reset_deassert(struct reset_ctl *rst)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static int scmi_reset_request(struct reset_ctl *rst)
 | 
					static int scmi_reset_request(struct reset_ctl *rst)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct scmi_reset_priv *priv = dev_get_priv(rst->dev);
 | 
					 | 
				
			||||||
	struct scmi_rd_attr_in in = {
 | 
						struct scmi_rd_attr_in in = {
 | 
				
			||||||
		.domain_id = rst->id,
 | 
							.domain_id = rst->id,
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
@ -68,7 +58,7 @@ static int scmi_reset_request(struct reset_ctl *rst)
 | 
				
			|||||||
	 * We don't really care about the attribute, just check
 | 
						 * We don't really care about the attribute, just check
 | 
				
			||||||
	 * the reset domain exists.
 | 
						 * the reset domain exists.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	ret = devm_scmi_process_msg(rst->dev, priv->channel, &msg);
 | 
						ret = devm_scmi_process_msg(rst->dev, &msg);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -83,9 +73,7 @@ static const struct reset_ops scmi_reset_domain_ops = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static int scmi_reset_probe(struct udevice *dev)
 | 
					static int scmi_reset_probe(struct udevice *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct scmi_reset_priv *priv = dev_get_priv(dev);
 | 
						return devm_scmi_of_get_channel(dev);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return devm_scmi_of_get_channel(dev, &priv->channel);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
U_BOOT_DRIVER(scmi_reset_domain) = {
 | 
					U_BOOT_DRIVER(scmi_reset_domain) = {
 | 
				
			||||||
@ -93,5 +81,4 @@ U_BOOT_DRIVER(scmi_reset_domain) = {
 | 
				
			|||||||
	.id = UCLASS_RESET,
 | 
						.id = UCLASS_RESET,
 | 
				
			||||||
	.ops = &scmi_reset_domain_ops,
 | 
						.ops = &scmi_reset_domain_ops,
 | 
				
			||||||
	.probe = scmi_reset_probe,
 | 
						.probe = scmi_reset_probe,
 | 
				
			||||||
	.priv_auto = sizeof(struct scmi_reset_priv *),
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -123,6 +123,7 @@ enum uclass_id {
 | 
				
			|||||||
	UCLASS_RNG,		/* Random Number Generator */
 | 
						UCLASS_RNG,		/* Random Number Generator */
 | 
				
			||||||
	UCLASS_RTC,		/* Real time clock device */
 | 
						UCLASS_RTC,		/* Real time clock device */
 | 
				
			||||||
	UCLASS_SCMI_AGENT,	/* Interface with an SCMI server */
 | 
						UCLASS_SCMI_AGENT,	/* Interface with an SCMI server */
 | 
				
			||||||
 | 
						UCLASS_SCMI_BASE,	/* Interface for SCMI Base protocol */
 | 
				
			||||||
	UCLASS_SCSI,		/* SCSI device */
 | 
						UCLASS_SCSI,		/* SCSI device */
 | 
				
			||||||
	UCLASS_SERIAL,		/* Serial UART */
 | 
						UCLASS_SERIAL,		/* Serial UART */
 | 
				
			||||||
	UCLASS_SIMPLE_BUS,	/* Bus with child devices */
 | 
						UCLASS_SIMPLE_BUS,	/* Bus with child devices */
 | 
				
			||||||
 | 
				
			|||||||
@ -5,10 +5,89 @@
 | 
				
			|||||||
#ifndef _SCMI_AGENT_UCLASS_H
 | 
					#ifndef _SCMI_AGENT_UCLASS_H
 | 
				
			||||||
#define _SCMI_AGENT_UCLASS_H
 | 
					#define _SCMI_AGENT_UCLASS_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct udevice;
 | 
					#include <scmi_protocols.h>
 | 
				
			||||||
 | 
					#include <dm/device.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct scmi_msg;
 | 
					struct scmi_msg;
 | 
				
			||||||
struct scmi_channel;
 | 
					struct scmi_channel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * struct scmi_agent_priv - private data maintained by agent instance
 | 
				
			||||||
 | 
					 * @version:		Version
 | 
				
			||||||
 | 
					 * @num_agents:		Number of agents
 | 
				
			||||||
 | 
					 * @num_protocols:	Number of protocols
 | 
				
			||||||
 | 
					 * @impl_version:	Implementation version
 | 
				
			||||||
 | 
					 * @protocols:		Array of protocol IDs
 | 
				
			||||||
 | 
					 * @vendor:		Vendor name
 | 
				
			||||||
 | 
					 * @sub_vendor:		Sub-vendor name
 | 
				
			||||||
 | 
					 * @agent_name:		Agent name
 | 
				
			||||||
 | 
					 * @agent_id:		Identifier of agent
 | 
				
			||||||
 | 
					 * @base_dev:		SCMI base protocol device
 | 
				
			||||||
 | 
					 * @clock_dev:		SCMI clock protocol device
 | 
				
			||||||
 | 
					 * @resetdom_dev:	SCMI reset domain protocol device
 | 
				
			||||||
 | 
					 * @voltagedom_dev:	SCMI voltage domain protocol device
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct scmi_agent_priv {
 | 
				
			||||||
 | 
						u32 version;
 | 
				
			||||||
 | 
						u32 num_agents;
 | 
				
			||||||
 | 
						u32 num_protocols;
 | 
				
			||||||
 | 
						u32 impl_version;
 | 
				
			||||||
 | 
						u8 *protocols;
 | 
				
			||||||
 | 
						u8 *vendor;
 | 
				
			||||||
 | 
						u8 *sub_vendor;
 | 
				
			||||||
 | 
						u8 *agent_name;
 | 
				
			||||||
 | 
						u32 agent_id;
 | 
				
			||||||
 | 
						struct udevice *base_dev;
 | 
				
			||||||
 | 
						struct udevice *clock_dev;
 | 
				
			||||||
 | 
						struct udevice *resetdom_dev;
 | 
				
			||||||
 | 
						struct udevice *voltagedom_dev;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline u32 scmi_version(struct udevice *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->version;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline u32 scmi_num_agents(struct udevice *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->num_agents;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline u32 scmi_num_protocols(struct udevice *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->num_protocols;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline u32 scmi_impl_version(struct udevice *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->impl_version;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline u8 *scmi_protocols(struct udevice *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->protocols;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline u8 *scmi_vendor(struct udevice *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->vendor;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline u8 *scmi_sub_vendor(struct udevice *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->sub_vendor;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline u8 *scmi_agent_name(struct udevice *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->agent_name;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline u32 scmi_agent_id(struct udevice *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->agent_id;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * struct scmi_transport_ops - The functions that a SCMI transport layer must implement.
 | 
					 * struct scmi_transport_ops - The functions that a SCMI transport layer must implement.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -16,16 +95,18 @@ struct scmi_agent_ops {
 | 
				
			|||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * of_get_channel - Get SCMI channel from SCMI agent device tree node
 | 
						 * of_get_channel - Get SCMI channel from SCMI agent device tree node
 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
	 * @dev:		SCMI protocol device using the transport
 | 
						 * @dev:		SCMI agent device using the transport
 | 
				
			||||||
 | 
						 * @protocol:		SCMI protocol device using the transport
 | 
				
			||||||
	 * @channel:		Output reference to SCMI channel upon success
 | 
						 * @channel:		Output reference to SCMI channel upon success
 | 
				
			||||||
	 * Return 0 upon success and a negative errno on failure
 | 
						 * Return 0 upon success and a negative errno on failure
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	int (*of_get_channel)(struct udevice *dev, struct scmi_channel **channel);
 | 
						int (*of_get_channel)(struct udevice *dev, struct udevice *protocol,
 | 
				
			||||||
 | 
								      struct scmi_channel **channel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * process_msg - Request transport to get the SCMI message processed
 | 
						 * process_msg - Request transport to get the SCMI message processed
 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
	 * @dev:		SCMI protocol device using the transport
 | 
						 * @dev:		SCMI agent device using the transport
 | 
				
			||||||
	 * @msg:		SCMI message to be transmitted
 | 
						 * @msg:		SCMI message to be transmitted
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	int (*process_msg)(struct udevice *dev, struct scmi_channel *channel,
 | 
						int (*process_msg)(struct udevice *dev, struct scmi_channel *channel,
 | 
				
			||||||
 | 
				
			|||||||
@ -10,11 +10,20 @@
 | 
				
			|||||||
#ifndef SCMI_AGENT_H
 | 
					#ifndef SCMI_AGENT_H
 | 
				
			||||||
#define SCMI_AGENT_H
 | 
					#define SCMI_AGENT_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <scmi_protocols.h>
 | 
				
			||||||
#include <asm/types.h>
 | 
					#include <asm/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct udevice;
 | 
					struct udevice;
 | 
				
			||||||
struct scmi_channel;
 | 
					struct scmi_channel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * struct scmi_agent_proto_priv - Private data in device for SCMI agent
 | 
				
			||||||
 | 
					 * @channel: Reference to the SCMI channel to use
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct scmi_agent_proto_priv {
 | 
				
			||||||
 | 
						struct scmi_channel *channel;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * struct scmi_msg - Context of a SCMI message sent and the response received
 | 
					 * struct scmi_msg - Context of a SCMI message sent and the response received
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@ -49,10 +58,9 @@ struct scmi_msg {
 | 
				
			|||||||
 * devm_scmi_of_get_channel() - Get SCMI channel handle from SCMI agent DT node
 | 
					 * devm_scmi_of_get_channel() - Get SCMI channel handle from SCMI agent DT node
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @dev:	Device requesting a channel
 | 
					 * @dev:	Device requesting a channel
 | 
				
			||||||
 * @channel:	Output reference to the SCMI channel upon success
 | 
					 | 
				
			||||||
 * @return 0 on success and a negative errno on failure
 | 
					 * @return 0 on success and a negative errno on failure
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int devm_scmi_of_get_channel(struct udevice *dev, struct scmi_channel **channel);
 | 
					int devm_scmi_of_get_channel(struct udevice *dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * devm_scmi_process_msg() - Send and process an SCMI message
 | 
					 * devm_scmi_process_msg() - Send and process an SCMI message
 | 
				
			||||||
@ -62,12 +70,23 @@ int devm_scmi_of_get_channel(struct udevice *dev, struct scmi_channel **channel)
 | 
				
			|||||||
 * On return, scmi_msg::out_msg_sz stores the response payload size.
 | 
					 * On return, scmi_msg::out_msg_sz stores the response payload size.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @dev:	SCMI device
 | 
					 * @dev:	SCMI device
 | 
				
			||||||
 * @channel:	Communication channel for the device
 | 
					 | 
				
			||||||
 * @msg:	Message structure reference
 | 
					 * @msg:	Message structure reference
 | 
				
			||||||
 * Return: 0 on success and a negative errno on failure
 | 
					 * Return: 0 on success and a negative errno on failure
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int devm_scmi_process_msg(struct udevice *dev, struct scmi_channel *channel,
 | 
					int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg);
 | 
				
			||||||
			  struct scmi_msg *msg);
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_get_protocol() - get protocol instance
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @dev:	SCMI agent device
 | 
				
			||||||
 | 
					 * @id:		SCMI protocol ID
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Obtain the device instance for given protocol ID, @id.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return:	Pointer to the device if found, null otherwise
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct udevice *scmi_get_protocol(struct udevice *dev,
 | 
				
			||||||
 | 
									  enum scmi_std_protocol id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * scmi_to_linux_errno() - Convert an SCMI error code into a Linux errno code
 | 
					 * scmi_to_linux_errno() - Convert an SCMI error code into a Linux errno code
 | 
				
			||||||
 | 
				
			|||||||
@ -49,6 +49,501 @@ enum scmi_discovery_id {
 | 
				
			|||||||
	SCMI_PROTOCOL_MESSAGE_ATTRIBUTES = 0x2,
 | 
						SCMI_PROTOCOL_MESSAGE_ATTRIBUTES = 0x2,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * SCMI Base Protocol
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define SCMI_BASE_PROTOCOL_VERSION 0x20000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum scmi_base_message_id {
 | 
				
			||||||
 | 
						SCMI_BASE_DISCOVER_VENDOR = 0x3,
 | 
				
			||||||
 | 
						SCMI_BASE_DISCOVER_SUB_VENDOR = 0x4,
 | 
				
			||||||
 | 
						SCMI_BASE_DISCOVER_IMPL_VERSION = 0x5,
 | 
				
			||||||
 | 
						SCMI_BASE_DISCOVER_LIST_PROTOCOLS = 0x6,
 | 
				
			||||||
 | 
						SCMI_BASE_DISCOVER_AGENT = 0x7,
 | 
				
			||||||
 | 
						SCMI_BASE_NOTIFY_ERRORS = 0x8,
 | 
				
			||||||
 | 
						SCMI_BASE_SET_DEVICE_PERMISSIONS = 0x9,
 | 
				
			||||||
 | 
						SCMI_BASE_SET_PROTOCOL_PERMISSIONS = 0xa,
 | 
				
			||||||
 | 
						SCMI_BASE_RESET_AGENT_CONFIGURATION = 0xb,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SCMI_BASE_NAME_LENGTH_MAX 16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * struct scmi_protocol_version_out - Response for SCMI_PROTOCOL_VERSION
 | 
				
			||||||
 | 
					 *					command
 | 
				
			||||||
 | 
					 * @status:	SCMI command status
 | 
				
			||||||
 | 
					 * @version:	Protocol version
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct scmi_protocol_version_out {
 | 
				
			||||||
 | 
						s32 status;
 | 
				
			||||||
 | 
						u32 version;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * struct scmi_protocol_attrs_out - Response for SCMI_PROTOCOL_ATTRIBUTES
 | 
				
			||||||
 | 
					 *					command
 | 
				
			||||||
 | 
					 * @status:	SCMI command status
 | 
				
			||||||
 | 
					 * @attributes:	Protocol attributes or implementation details
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct scmi_protocol_attrs_out {
 | 
				
			||||||
 | 
						s32 status;
 | 
				
			||||||
 | 
						u32 attributes;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SCMI_PROTOCOL_ATTRS_NUM_AGENTS(attributes) \
 | 
				
			||||||
 | 
									(((attributes) & GENMASK(15, 8)) >> 8)
 | 
				
			||||||
 | 
					#define SCMI_PROTOCOL_ATTRS_NUM_PROTOCOLS(attributes) \
 | 
				
			||||||
 | 
									((attributes) & GENMASK(7, 0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * struct scmi_protocol_msg_attrs_out - Response for
 | 
				
			||||||
 | 
					 *					SCMI_PROTOCOL_MESSAGE_ATTRIBUTES command
 | 
				
			||||||
 | 
					 * @status:	SCMI command status
 | 
				
			||||||
 | 
					 * @attributes:	Message-specific attributes
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct scmi_protocol_msg_attrs_out {
 | 
				
			||||||
 | 
						s32 status;
 | 
				
			||||||
 | 
						u32 attributes;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * struct scmi_base_discover_vendor_out - Response for
 | 
				
			||||||
 | 
					 *					  SCMI_BASE_DISCOVER_VENDOR or
 | 
				
			||||||
 | 
					 *					  SCMI_BASE_DISCOVER_SUB_VENDOR command
 | 
				
			||||||
 | 
					 * @status:		SCMI command status
 | 
				
			||||||
 | 
					 * @vendor_identifier:	Name of vendor or sub-vendor in string
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct scmi_base_discover_vendor_out {
 | 
				
			||||||
 | 
						s32 status;
 | 
				
			||||||
 | 
						u8 vendor_identifier[SCMI_BASE_NAME_LENGTH_MAX];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * struct scmi_base_discover_impl_version_out - Response for
 | 
				
			||||||
 | 
					 *					SCMI_BASE_DISCOVER_IMPL_VERSION command
 | 
				
			||||||
 | 
					 * @status:		SCMI command status
 | 
				
			||||||
 | 
					 * @impl_version:	Vendor-specific implementation version
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct scmi_base_discover_impl_version_out {
 | 
				
			||||||
 | 
						s32 status;
 | 
				
			||||||
 | 
						u32 impl_version;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * struct scmi_base_discover_list_protocols_out - Response for
 | 
				
			||||||
 | 
					 *				SCMI_BASE_DISCOVER_LIST_PROTOCOLS command
 | 
				
			||||||
 | 
					 * @status:		SCMI command status
 | 
				
			||||||
 | 
					 * @num_protocols:	Number of SCMI protocols in @protocol
 | 
				
			||||||
 | 
					 * @protocols:		Array of packed SCMI protocol ID's
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct scmi_base_discover_list_protocols_out {
 | 
				
			||||||
 | 
						s32 status;
 | 
				
			||||||
 | 
						u32 num_protocols;
 | 
				
			||||||
 | 
						u32 protocols[3];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * struct scmi_base_discover_agent_out - Response for
 | 
				
			||||||
 | 
					 *					 SCMI_BASE_DISCOVER_AGENT command
 | 
				
			||||||
 | 
					 * @status:	SCMI command status
 | 
				
			||||||
 | 
					 * @agent_id:	SCMI agent ID
 | 
				
			||||||
 | 
					 * @name:	Name of agent in string
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct scmi_base_discover_agent_out {
 | 
				
			||||||
 | 
						s32 status;
 | 
				
			||||||
 | 
						u32 agent_id;
 | 
				
			||||||
 | 
						u8 name[SCMI_BASE_NAME_LENGTH_MAX];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SCMI_BASE_NOTIFY_ERRORS_ENABLE BIT(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * struct scmi_base_set_device_permissions_in - Parameters for
 | 
				
			||||||
 | 
					 *					SCMI_BASE_SET_DEVICE_PERMISSIONS command
 | 
				
			||||||
 | 
					 * @agent_id:	SCMI agent ID
 | 
				
			||||||
 | 
					 * @device_id:	device ID
 | 
				
			||||||
 | 
					 * @flags:	A set of flags
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct scmi_base_set_device_permissions_in {
 | 
				
			||||||
 | 
						u32 agent_id;
 | 
				
			||||||
 | 
						u32 device_id;
 | 
				
			||||||
 | 
						u32 flags;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SCMI_BASE_SET_DEVICE_PERMISSIONS_ACCESS BIT(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * struct scmi_base_set_protocol_permissions_in - Parameters for
 | 
				
			||||||
 | 
					 *				SCMI_BASE_SET_PROTOCOL_PERMISSIONS command
 | 
				
			||||||
 | 
					 * @agent_id:		SCMI agent ID
 | 
				
			||||||
 | 
					 * @device_id:		device ID
 | 
				
			||||||
 | 
					 * @command_id:		command ID
 | 
				
			||||||
 | 
					 * @flags:		A set of flags
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct scmi_base_set_protocol_permissions_in {
 | 
				
			||||||
 | 
						u32 agent_id;
 | 
				
			||||||
 | 
						u32 device_id;
 | 
				
			||||||
 | 
						u32 command_id;
 | 
				
			||||||
 | 
						u32 flags;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SCMI_BASE_SET_PROTOCOL_PERMISSIONS_COMMAND GENMASK(7, 0)
 | 
				
			||||||
 | 
					#define SCMI_BASE_SET_PROTOCOL_PERMISSIONS_ACCESS BIT(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * struct scmi_base_reset_agent_configuration_in - Parameters for
 | 
				
			||||||
 | 
					 *				SCMI_BASE_RESET_AGENT_CONFIGURATION command
 | 
				
			||||||
 | 
					 * @agent_id:	SCMI agent ID
 | 
				
			||||||
 | 
					 * @flags:	A set of flags
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct scmi_base_reset_agent_configuration_in {
 | 
				
			||||||
 | 
						u32 agent_id;
 | 
				
			||||||
 | 
						u32 flags;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SCMI_BASE_RESET_ALL_ACCESS_PERMISSIONS BIT(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * struct scmi_base_ops - SCMI base protocol interfaces
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct scmi_base_ops {
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * protocol_version - get Base protocol version
 | 
				
			||||||
 | 
						 * @dev:	SCMI protocol device
 | 
				
			||||||
 | 
						 * @version:	Pointer to SCMI protocol version
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Obtain the protocol version number in @version for Base protocol.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						int (*protocol_version)(struct udevice *dev, u32 *version);
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * protocol_attrs - get protocol attributes
 | 
				
			||||||
 | 
						 * @dev:		SCMI protocol device
 | 
				
			||||||
 | 
						 * @num_agents:		Number of SCMI agents
 | 
				
			||||||
 | 
						 * @num_protocols:	Number of SCMI protocols
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Obtain the protocol attributes, the number of agents and the number
 | 
				
			||||||
 | 
						 * of protocols, in @num_agents and @num_protocols respectively, that
 | 
				
			||||||
 | 
						 * the device provides.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						int (*protocol_attrs)(struct udevice *dev, u32 *num_agents,
 | 
				
			||||||
 | 
								      u32 *num_protocols);
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * protocol_message_attrs - get message-specific attributes
 | 
				
			||||||
 | 
						 * @dev:		SCMI protocol device
 | 
				
			||||||
 | 
						 * @message_id:		SCMI message ID
 | 
				
			||||||
 | 
						 * @attributes:		Message-specific attributes
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Obtain the message-specific attributes in @attributes.
 | 
				
			||||||
 | 
						 * This command succeeds if the message is implemented and available.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						int (*protocol_message_attrs)(struct udevice *dev, u32 message_id,
 | 
				
			||||||
 | 
									      u32 *attributes);
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * base_discover_vendor - get vendor name
 | 
				
			||||||
 | 
						 * @dev:	SCMI protocol device
 | 
				
			||||||
 | 
						 * @vendor:	Pointer to vendor name
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Obtain the vendor's name in @vendor.
 | 
				
			||||||
 | 
						 * It is a caller's responsibility to free @vendor.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						int (*base_discover_vendor)(struct udevice *dev, u8 **vendor);
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * base_discover_sub_vendor - get sub-vendor name
 | 
				
			||||||
 | 
						 * @dev:	SCMI protocol device
 | 
				
			||||||
 | 
						 * @sub_vendor:	Pointer to sub-vendor name
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Obtain the sub-vendor's name in @sub_vendor.
 | 
				
			||||||
 | 
						 * It is a caller's responsibility to free @sub_vendor.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						int (*base_discover_sub_vendor)(struct udevice *dev, u8 **sub_vendor);
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * base_discover_impl_version - get implementation version
 | 
				
			||||||
 | 
						 * @dev:		SCMI protocol device
 | 
				
			||||||
 | 
						 * @impl_version:	Pointer to implementation version
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Obtain the implementation version number in @impl_version.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						int (*base_discover_impl_version)(struct udevice *dev,
 | 
				
			||||||
 | 
										  u32 *impl_version);
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * base_discover_list_protocols - get list of protocols
 | 
				
			||||||
 | 
						 * @dev:	SCMI protocol device
 | 
				
			||||||
 | 
						 * @protocols:	Pointer to array of SCMI protocols
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Obtain the list of protocols provided in @protocols.
 | 
				
			||||||
 | 
						 * The number of elements in @protocols always match to the number of
 | 
				
			||||||
 | 
						 * protocols returned by smci_protocol_attrs() when this function
 | 
				
			||||||
 | 
						 * succeeds.
 | 
				
			||||||
 | 
						 * It is a caller's responsibility to free @protocols.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Return: the number of protocols in @protocols on success,
 | 
				
			||||||
 | 
						 * error code on failure
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						int (*base_discover_list_protocols)(struct udevice *dev,
 | 
				
			||||||
 | 
										    u8 **protocols);
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * base_discover_agent - identify agent
 | 
				
			||||||
 | 
						 * @dev:		SCMI protocol device
 | 
				
			||||||
 | 
						 * @agent_id:		SCMI agent ID
 | 
				
			||||||
 | 
						 * @ret_agent_id:	Pointer to SCMI agent ID
 | 
				
			||||||
 | 
						 * @name:		Pointer to SCMI agent name
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Obtain the agent's name in @name. If @agent_id is equal to
 | 
				
			||||||
 | 
						 * 0xffffffff, * this function returns the caller's agent id in
 | 
				
			||||||
 | 
						 * @ret_agent_id.
 | 
				
			||||||
 | 
						 * It is a caller's responsibility to free @name.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						int (*base_discover_agent)(struct udevice *dev, u32 agent_id,
 | 
				
			||||||
 | 
									   u32 *ret_agent_id, u8 **name);
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * base_notify_errors - configure error notification
 | 
				
			||||||
 | 
						 * @dev:	SCMI protocol device
 | 
				
			||||||
 | 
						 * @enable:	Operation
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Enable or disable error notification from SCMI firmware.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						int (*base_notify_errors)(struct udevice *dev, u32 enable);
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * base_set_device_permissions - configure access permission to device
 | 
				
			||||||
 | 
						 * @dev:	SCMI protocol device
 | 
				
			||||||
 | 
						 * @agent_id:	SCMI agent ID
 | 
				
			||||||
 | 
						 * @device_id:	ID of device to access
 | 
				
			||||||
 | 
						 * @flags:	A set of flags
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Ask for allowing or denying access permission to the device,
 | 
				
			||||||
 | 
						 * @device_id. The meaning of @flags is defined in SCMI specification.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						int (*base_set_device_permissions)(struct udevice *dev, u32 agent_id,
 | 
				
			||||||
 | 
										   u32 device_id, u32 flags);
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * base_set_protocol_permissions - configure access permission to
 | 
				
			||||||
 | 
						 *				   protocol on device
 | 
				
			||||||
 | 
						 * @dev:	SCMI protocol device
 | 
				
			||||||
 | 
						 * @agent_id:	SCMI agent ID
 | 
				
			||||||
 | 
						 * @device_id:	ID of device to access
 | 
				
			||||||
 | 
						 * @command_id:	command ID
 | 
				
			||||||
 | 
						 * @flags:	A set of flags
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Ask for allowing or denying access permission to the protocol,
 | 
				
			||||||
 | 
						 * @command_id, on the device, @device_id.
 | 
				
			||||||
 | 
						 * The meaning of @flags is defined in SCMI specification.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						int (*base_set_protocol_permissions)(struct udevice *dev, u32 agent_id,
 | 
				
			||||||
 | 
										     u32 device_id, u32 command_id,
 | 
				
			||||||
 | 
										     u32 flags);
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * base_reset_agent_configuration - reset resource settings
 | 
				
			||||||
 | 
						 * @dev:	SCMI protocol device
 | 
				
			||||||
 | 
						 * @agent_id:	SCMI agent ID
 | 
				
			||||||
 | 
						 * @flags:	A set of flags
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Reset all the resource settings against @agent_id.
 | 
				
			||||||
 | 
						 * The meaning of @flags is defined in SCMI specification.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						int (*base_reset_agent_configuration)(struct udevice *dev, u32 agent_id,
 | 
				
			||||||
 | 
										      u32 flags);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_generic_protocol_version - get protocol version
 | 
				
			||||||
 | 
					 * @dev:	SCMI protocol device
 | 
				
			||||||
 | 
					 * @id:		SCMI protocol ID
 | 
				
			||||||
 | 
					 * @version:	Pointer to SCMI protocol version
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Obtain the protocol version number in @version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int scmi_generic_protocol_version(struct udevice *dev,
 | 
				
			||||||
 | 
									  enum scmi_std_protocol id, u32 *version);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_base_protocol_version - get Base protocol version
 | 
				
			||||||
 | 
					 * @dev:	SCMI protocol device
 | 
				
			||||||
 | 
					 * @version:	Pointer to SCMI protocol version
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Obtain the protocol version number in @version for Base protocol.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int scmi_base_protocol_version(struct udevice *dev, u32 *version);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_protocol_attrs - get protocol attributes
 | 
				
			||||||
 | 
					 * @dev:		SCMI protocol device
 | 
				
			||||||
 | 
					 * @num_agents:		Number of SCMI agents
 | 
				
			||||||
 | 
					 * @num_protocols:	Number of SCMI protocols
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Obtain the protocol attributes, the number of agents and the number
 | 
				
			||||||
 | 
					 * of protocols, in @num_agents and @num_protocols respectively, that
 | 
				
			||||||
 | 
					 * the device provides.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int scmi_base_protocol_attrs(struct udevice *dev, u32 *num_agents,
 | 
				
			||||||
 | 
								     u32 *num_protocols);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_protocol_message_attrs - get message-specific attributes
 | 
				
			||||||
 | 
					 * @dev:		SCMI protocol device
 | 
				
			||||||
 | 
					 * @message_id:		SCMI message ID
 | 
				
			||||||
 | 
					 * @attributes:		Message-specific attributes
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Obtain the message-specific attributes in @attributes.
 | 
				
			||||||
 | 
					 * This command succeeds if the message is implemented and available.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int scmi_base_protocol_message_attrs(struct udevice *dev, u32 message_id,
 | 
				
			||||||
 | 
									     u32 *attributes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_base_discover_vendor - get vendor name
 | 
				
			||||||
 | 
					 * @dev:	SCMI protocol device
 | 
				
			||||||
 | 
					 * @vendor:	Pointer to vendor name
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Obtain the vendor's name in @vendor.
 | 
				
			||||||
 | 
					 * It is a caller's responsibility to free @vendor.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int scmi_base_discover_vendor(struct udevice *dev, u8 **vendor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_base_discover_sub_vendor - get sub-vendor name
 | 
				
			||||||
 | 
					 * @dev:	SCMI protocol device
 | 
				
			||||||
 | 
					 * @sub_vendor:	Pointer to sub-vendor name
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Obtain the sub-vendor's name in @sub_vendor.
 | 
				
			||||||
 | 
					 * It is a caller's responsibility to free @sub_vendor.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int scmi_base_discover_sub_vendor(struct udevice *dev, u8 **sub_vendor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_base_discover_impl_version - get implementation version
 | 
				
			||||||
 | 
					 * @dev:		SCMI protocol device
 | 
				
			||||||
 | 
					 * @impl_version:	Pointer to implementation version
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Obtain the implementation version number in @impl_version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int scmi_base_discover_impl_version(struct udevice *dev, u32 *impl_version);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_base_discover_list_protocols - get list of protocols
 | 
				
			||||||
 | 
					 * @dev:	SCMI protocol device
 | 
				
			||||||
 | 
					 * @protocols:	Pointer to array of SCMI protocols
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Obtain the list of protocols provided in @protocols.
 | 
				
			||||||
 | 
					 * The number of elements in @protocols always match to the number of
 | 
				
			||||||
 | 
					 * protocols returned by smci_protocol_attrs() when this function succeeds.
 | 
				
			||||||
 | 
					 * It is a caller's responsibility to free @protocols.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: the number of protocols in @protocols on success, error code on
 | 
				
			||||||
 | 
					 * failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int scmi_base_discover_list_protocols(struct udevice *dev, u8 **protocols);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_base_discover_agent - identify agent
 | 
				
			||||||
 | 
					 * @dev:		SCMI protocol device
 | 
				
			||||||
 | 
					 * @agent_id:		SCMI agent ID
 | 
				
			||||||
 | 
					 * @ret_agent_id:	Pointer to SCMI agent ID
 | 
				
			||||||
 | 
					 * @name:		Pointer to SCMI agent name
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Obtain the agent's name in @name. If @agent_id is equal to 0xffffffff,
 | 
				
			||||||
 | 
					 * this function returns the caller's agent id in @ret_agent_id.
 | 
				
			||||||
 | 
					 * It is a caller's responsibility to free @name.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int scmi_base_discover_agent(struct udevice *dev, u32 agent_id,
 | 
				
			||||||
 | 
								     u32 *ret_agent_id, u8 **name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_base_notify_errors - configure error notification
 | 
				
			||||||
 | 
					 * @dev:	SCMI protocol device
 | 
				
			||||||
 | 
					 * @enable:	Operation
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Enable or disable error notification from SCMI firmware.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int scmi_base_notify_errors(struct udevice *dev, u32 enable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_base_set_device_permissions - configure access permission to device
 | 
				
			||||||
 | 
					 * @dev:	SCMI protocol device
 | 
				
			||||||
 | 
					 * @agent_id:	SCMI agent ID
 | 
				
			||||||
 | 
					 * @device_id:	ID of device to access
 | 
				
			||||||
 | 
					 * @flags:	A set of flags
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Ask for allowing or denying access permission to the device, @device_id.
 | 
				
			||||||
 | 
					 * The meaning of @flags is defined in SCMI specification.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int scmi_base_set_device_permissions(struct udevice *dev, u32 agent_id,
 | 
				
			||||||
 | 
									     u32 device_id, u32 flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_base_set_protocol_permissions - configure access permission to
 | 
				
			||||||
 | 
					 *					protocol on device
 | 
				
			||||||
 | 
					 * @dev:	SCMI protocol device
 | 
				
			||||||
 | 
					 * @agent_id:	SCMI agent ID
 | 
				
			||||||
 | 
					 * @device_id:	ID of device to access
 | 
				
			||||||
 | 
					 * @command_id:	SCMI command ID
 | 
				
			||||||
 | 
					 * @flags:	A set of flags
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Ask for allowing or denying access permission to the protocol, @command_id,
 | 
				
			||||||
 | 
					 * on the device, @device_id.
 | 
				
			||||||
 | 
					 * The meaning of @flags is defined in SCMI specification.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int scmi_base_set_protocol_permissions(struct udevice *dev,
 | 
				
			||||||
 | 
									       u32 agent_id, u32 device_id,
 | 
				
			||||||
 | 
									       u32 command_id, u32 flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * scmi_base_reset_agent_configuration - reset resource settings
 | 
				
			||||||
 | 
					 * @dev:	SCMI protocol device
 | 
				
			||||||
 | 
					 * @agent_id:	SCMI agent ID
 | 
				
			||||||
 | 
					 * @flags:	A set of flags
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Reset all the resource settings against @agent_id.
 | 
				
			||||||
 | 
					 * The meaning of @flags is defined in SCMI specification.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int scmi_base_reset_agent_configuration(struct udevice *dev, u32 agent_id,
 | 
				
			||||||
 | 
										u32 flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * SCMI Clock Protocol
 | 
					 * SCMI Clock Protocol
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										195
									
								
								test/dm/scmi.c
									
									
									
									
									
								
							
							
						
						
									
										195
									
								
								test/dm/scmi.c
									
									
									
									
									
								
							@ -16,6 +16,9 @@
 | 
				
			|||||||
#include <clk.h>
 | 
					#include <clk.h>
 | 
				
			||||||
#include <dm.h>
 | 
					#include <dm.h>
 | 
				
			||||||
#include <reset.h>
 | 
					#include <reset.h>
 | 
				
			||||||
 | 
					#include <scmi_agent.h>
 | 
				
			||||||
 | 
					#include <scmi_agent-uclass.h>
 | 
				
			||||||
 | 
					#include <scmi_protocols.h>
 | 
				
			||||||
#include <asm/scmi_test.h>
 | 
					#include <asm/scmi_test.h>
 | 
				
			||||||
#include <dm/device-internal.h>
 | 
					#include <dm/device-internal.h>
 | 
				
			||||||
#include <dm/test.h>
 | 
					#include <dm/test.h>
 | 
				
			||||||
@ -23,22 +26,11 @@
 | 
				
			|||||||
#include <power/regulator.h>
 | 
					#include <power/regulator.h>
 | 
				
			||||||
#include <test/ut.h>
 | 
					#include <test/ut.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int ut_assert_scmi_state_preprobe(struct unit_test_state *uts)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct sandbox_scmi_service *scmi_ctx = sandbox_scmi_service_ctx();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ut_assertnonnull(scmi_ctx);
 | 
					 | 
				
			||||||
	ut_assertnull(scmi_ctx->agent);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts,
 | 
					static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts,
 | 
				
			||||||
 | 
										  struct sandbox_scmi_agent *agent,
 | 
				
			||||||
					  struct udevice *dev)
 | 
										  struct udevice *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sandbox_scmi_devices *scmi_devices;
 | 
						struct sandbox_scmi_devices *scmi_devices;
 | 
				
			||||||
	struct sandbox_scmi_service *scmi_ctx;
 | 
					 | 
				
			||||||
	struct sandbox_scmi_agent *agent;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Device references to check context against test sequence */
 | 
						/* Device references to check context against test sequence */
 | 
				
			||||||
	scmi_devices = sandbox_scmi_devices_ctx(dev);
 | 
						scmi_devices = sandbox_scmi_devices_ctx(dev);
 | 
				
			||||||
@ -48,10 +40,6 @@ static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts,
 | 
				
			|||||||
	ut_asserteq(2, scmi_devices->regul_count);
 | 
						ut_asserteq(2, scmi_devices->regul_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* State of the simulated SCMI server exposed */
 | 
						/* State of the simulated SCMI server exposed */
 | 
				
			||||||
	scmi_ctx = sandbox_scmi_service_ctx();
 | 
					 | 
				
			||||||
	ut_assertnonnull(scmi_ctx);
 | 
					 | 
				
			||||||
	agent = scmi_ctx->agent;
 | 
					 | 
				
			||||||
	ut_assertnonnull(agent);
 | 
					 | 
				
			||||||
	ut_asserteq(3, agent->clk_count);
 | 
						ut_asserteq(3, agent->clk_count);
 | 
				
			||||||
	ut_assertnonnull(agent->clk);
 | 
						ut_assertnonnull(agent->clk);
 | 
				
			||||||
	ut_asserteq(1, agent->reset_count);
 | 
						ut_asserteq(1, agent->reset_count);
 | 
				
			||||||
@ -63,27 +51,32 @@ static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts,
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int load_sandbox_scmi_test_devices(struct unit_test_state *uts,
 | 
					static int load_sandbox_scmi_test_devices(struct unit_test_state *uts,
 | 
				
			||||||
 | 
										  struct sandbox_scmi_agent **ctx,
 | 
				
			||||||
					  struct udevice **dev)
 | 
										  struct udevice **dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret;
 | 
						struct udevice *agent_dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = ut_assert_scmi_state_preprobe(uts);
 | 
						ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi",
 | 
				
			||||||
	if (ret)
 | 
										      &agent_dev));
 | 
				
			||||||
		return ret;
 | 
						ut_assertnonnull(agent_dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*ctx = sandbox_scmi_agent_ctx(agent_dev);
 | 
				
			||||||
 | 
						ut_assertnonnull(*ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* probe */
 | 
				
			||||||
	ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "sandbox_scmi",
 | 
						ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "sandbox_scmi",
 | 
				
			||||||
					      dev));
 | 
										      dev));
 | 
				
			||||||
	ut_assertnonnull(*dev);
 | 
						ut_assertnonnull(*dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ut_assert_scmi_state_postprobe(uts, *dev);
 | 
						return ut_assert_scmi_state_postprobe(uts, *ctx, *dev);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int release_sandbox_scmi_test_devices(struct unit_test_state *uts,
 | 
					static int release_sandbox_scmi_test_devices(struct unit_test_state *uts,
 | 
				
			||||||
					     struct udevice *dev)
 | 
										     struct udevice *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						/* un-probe */
 | 
				
			||||||
	ut_assertok(device_remove(dev, DM_REMOVE_NORMAL));
 | 
						ut_assertok(device_remove(dev, DM_REMOVE_NORMAL));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Not sure test devices are fully removed, agent may not be visible */
 | 
					 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -93,10 +86,11 @@ static int release_sandbox_scmi_test_devices(struct unit_test_state *uts,
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
static int dm_test_scmi_sandbox_agent(struct unit_test_state *uts)
 | 
					static int dm_test_scmi_sandbox_agent(struct unit_test_state *uts)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct sandbox_scmi_agent *ctx;
 | 
				
			||||||
	struct udevice *dev = NULL;
 | 
						struct udevice *dev = NULL;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = load_sandbox_scmi_test_devices(uts, &dev);
 | 
						ret = load_sandbox_scmi_test_devices(uts, &ctx, &dev);
 | 
				
			||||||
	if (!ret)
 | 
						if (!ret)
 | 
				
			||||||
		ret = release_sandbox_scmi_test_devices(uts, dev);
 | 
							ret = release_sandbox_scmi_test_devices(uts, dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -104,25 +98,136 @@ static int dm_test_scmi_sandbox_agent(struct unit_test_state *uts)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
DM_TEST(dm_test_scmi_sandbox_agent, UT_TESTF_SCAN_FDT);
 | 
					DM_TEST(dm_test_scmi_sandbox_agent, UT_TESTF_SCAN_FDT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int dm_test_scmi_base(struct unit_test_state *uts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct udevice *agent_dev, *base;
 | 
				
			||||||
 | 
						struct scmi_agent_priv *priv;
 | 
				
			||||||
 | 
						u32 version, num_agents, num_protocols, impl_version;
 | 
				
			||||||
 | 
						u32 attributes, agent_id;
 | 
				
			||||||
 | 
						u8 *vendor, *agent_name, *protocols;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* preparation */
 | 
				
			||||||
 | 
						ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi",
 | 
				
			||||||
 | 
										      &agent_dev));
 | 
				
			||||||
 | 
						ut_assertnonnull(agent_dev);
 | 
				
			||||||
 | 
						ut_assertnonnull(priv = dev_get_uclass_plat(agent_dev));
 | 
				
			||||||
 | 
						ut_assertnonnull(base = scmi_get_protocol(agent_dev,
 | 
				
			||||||
 | 
											  SCMI_PROTOCOL_ID_BASE));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* version */
 | 
				
			||||||
 | 
						ret = scmi_base_protocol_version(base, &version);
 | 
				
			||||||
 | 
						ut_assertok(ret);
 | 
				
			||||||
 | 
						ut_asserteq(priv->version, version);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* protocol attributes */
 | 
				
			||||||
 | 
						ret = scmi_base_protocol_attrs(base, &num_agents, &num_protocols);
 | 
				
			||||||
 | 
						ut_assertok(ret);
 | 
				
			||||||
 | 
						ut_asserteq(priv->num_agents, num_agents);
 | 
				
			||||||
 | 
						ut_asserteq(priv->num_protocols, num_protocols);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* discover vendor */
 | 
				
			||||||
 | 
						ret = scmi_base_discover_vendor(base, &vendor);
 | 
				
			||||||
 | 
						ut_assertok(ret);
 | 
				
			||||||
 | 
						ut_asserteq_str(priv->vendor, vendor);
 | 
				
			||||||
 | 
						free(vendor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* message attributes */
 | 
				
			||||||
 | 
						ret = scmi_base_protocol_message_attrs(base,
 | 
				
			||||||
 | 
										       SCMI_BASE_DISCOVER_SUB_VENDOR,
 | 
				
			||||||
 | 
										       &attributes);
 | 
				
			||||||
 | 
						ut_assertok(ret);
 | 
				
			||||||
 | 
						ut_assertok(attributes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* discover sub vendor */
 | 
				
			||||||
 | 
						ret = scmi_base_discover_sub_vendor(base, &vendor);
 | 
				
			||||||
 | 
						ut_assertok(ret);
 | 
				
			||||||
 | 
						ut_asserteq_str(priv->sub_vendor, vendor);
 | 
				
			||||||
 | 
						free(vendor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* impl version */
 | 
				
			||||||
 | 
						ret = scmi_base_discover_impl_version(base, &impl_version);
 | 
				
			||||||
 | 
						ut_assertok(ret);
 | 
				
			||||||
 | 
						ut_asserteq(priv->impl_version, impl_version);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* discover agent (my self) */
 | 
				
			||||||
 | 
						ret = scmi_base_discover_agent(base, 0xffffffff, &agent_id,
 | 
				
			||||||
 | 
									       &agent_name);
 | 
				
			||||||
 | 
						ut_assertok(ret);
 | 
				
			||||||
 | 
						ut_asserteq(priv->agent_id, agent_id);
 | 
				
			||||||
 | 
						ut_asserteq_str(priv->agent_name, agent_name);
 | 
				
			||||||
 | 
						free(agent_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* discover protocols */
 | 
				
			||||||
 | 
						ret = scmi_base_discover_list_protocols(base, &protocols);
 | 
				
			||||||
 | 
						ut_asserteq(num_protocols, ret);
 | 
				
			||||||
 | 
						ut_asserteq_mem(priv->protocols, protocols, sizeof(u8) * num_protocols);
 | 
				
			||||||
 | 
						free(protocols);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * NOTE: Sandbox SCMI driver handles device-0 only. It supports setting
 | 
				
			||||||
 | 
						 * access and protocol permissions, but doesn't allow unsetting them nor
 | 
				
			||||||
 | 
						 * resetting the configurations.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						/* set device permissions */
 | 
				
			||||||
 | 
						ret = scmi_base_set_device_permissions(base, agent_id, 0,
 | 
				
			||||||
 | 
										       SCMI_BASE_SET_DEVICE_PERMISSIONS_ACCESS);
 | 
				
			||||||
 | 
						ut_assertok(ret); /* SCMI_SUCCESS */
 | 
				
			||||||
 | 
						ret = scmi_base_set_device_permissions(base, agent_id, 1,
 | 
				
			||||||
 | 
										       SCMI_BASE_SET_DEVICE_PERMISSIONS_ACCESS);
 | 
				
			||||||
 | 
						ut_asserteq(-ENOENT, ret); /* SCMI_NOT_FOUND */
 | 
				
			||||||
 | 
						ret = scmi_base_set_device_permissions(base, agent_id, 0, 0);
 | 
				
			||||||
 | 
						ut_asserteq(-EACCES, ret); /* SCMI_DENIED */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* set protocol permissions */
 | 
				
			||||||
 | 
						ret = scmi_base_set_protocol_permissions(base, agent_id, 0,
 | 
				
			||||||
 | 
											 SCMI_PROTOCOL_ID_CLOCK,
 | 
				
			||||||
 | 
											 SCMI_BASE_SET_PROTOCOL_PERMISSIONS_ACCESS);
 | 
				
			||||||
 | 
						ut_assertok(ret); /* SCMI_SUCCESS */
 | 
				
			||||||
 | 
						ret = scmi_base_set_protocol_permissions(base, agent_id, 1,
 | 
				
			||||||
 | 
											 SCMI_PROTOCOL_ID_CLOCK,
 | 
				
			||||||
 | 
											 SCMI_BASE_SET_PROTOCOL_PERMISSIONS_ACCESS);
 | 
				
			||||||
 | 
						ut_asserteq(-ENOENT, ret); /* SCMI_NOT_FOUND */
 | 
				
			||||||
 | 
						ret = scmi_base_set_protocol_permissions(base, agent_id, 0,
 | 
				
			||||||
 | 
											 SCMI_PROTOCOL_ID_CLOCK, 0);
 | 
				
			||||||
 | 
						ut_asserteq(-EACCES, ret); /* SCMI_DENIED */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* reset agent configuration */
 | 
				
			||||||
 | 
						ret = scmi_base_reset_agent_configuration(base, agent_id, 0);
 | 
				
			||||||
 | 
						ut_asserteq(-EACCES, ret); /* SCMI_DENIED */
 | 
				
			||||||
 | 
						ret = scmi_base_reset_agent_configuration(base, agent_id,
 | 
				
			||||||
 | 
											  SCMI_BASE_RESET_ALL_ACCESS_PERMISSIONS);
 | 
				
			||||||
 | 
						ut_asserteq(-EACCES, ret); /* SCMI_DENIED */
 | 
				
			||||||
 | 
						ret = scmi_base_reset_agent_configuration(base, agent_id, 0);
 | 
				
			||||||
 | 
						ut_asserteq(-EACCES, ret); /* SCMI_DENIED */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DM_TEST(dm_test_scmi_base, UT_TESTF_SCAN_FDT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dm_test_scmi_clocks(struct unit_test_state *uts)
 | 
					static int dm_test_scmi_clocks(struct unit_test_state *uts)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sandbox_scmi_devices *scmi_devices;
 | 
					 | 
				
			||||||
	struct sandbox_scmi_service *scmi_ctx;
 | 
					 | 
				
			||||||
	struct sandbox_scmi_agent *agent;
 | 
						struct sandbox_scmi_agent *agent;
 | 
				
			||||||
	struct udevice *dev;
 | 
						struct sandbox_scmi_devices *scmi_devices;
 | 
				
			||||||
 | 
						struct udevice *agent_dev, *clock_dev, *dev;
 | 
				
			||||||
	int ret_dev;
 | 
						int ret_dev;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = load_sandbox_scmi_test_devices(uts, &dev);
 | 
						ret = load_sandbox_scmi_test_devices(uts, &agent, &dev);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	scmi_devices = sandbox_scmi_devices_ctx(dev);
 | 
						scmi_devices = sandbox_scmi_devices_ctx(dev);
 | 
				
			||||||
	ut_assertnonnull(scmi_devices);
 | 
						ut_assertnonnull(scmi_devices);
 | 
				
			||||||
	scmi_ctx = sandbox_scmi_service_ctx();
 | 
					
 | 
				
			||||||
	ut_assertnonnull(scmi_ctx);
 | 
						/* Sandbox SCMI clock protocol has its own channel */
 | 
				
			||||||
	agent = scmi_ctx->agent;
 | 
						ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi",
 | 
				
			||||||
	ut_assertnonnull(agent);
 | 
										      &agent_dev));
 | 
				
			||||||
 | 
						ut_assertnonnull(agent_dev);
 | 
				
			||||||
 | 
						clock_dev = scmi_get_protocol(agent_dev, SCMI_PROTOCOL_ID_CLOCK);
 | 
				
			||||||
 | 
						ut_assertnonnull(clock_dev);
 | 
				
			||||||
 | 
						ut_asserteq(0x14, sandbox_scmi_channel_id(clock_dev));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Test SCMI clocks rate manipulation */
 | 
						/* Test SCMI clocks rate manipulation */
 | 
				
			||||||
	ut_asserteq(333, agent->clk[0].rate);
 | 
						ut_asserteq(333, agent->clk[0].rate);
 | 
				
			||||||
@ -169,22 +274,25 @@ DM_TEST(dm_test_scmi_clocks, UT_TESTF_SCAN_FDT);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static int dm_test_scmi_resets(struct unit_test_state *uts)
 | 
					static int dm_test_scmi_resets(struct unit_test_state *uts)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sandbox_scmi_devices *scmi_devices;
 | 
					 | 
				
			||||||
	struct sandbox_scmi_service *scmi_ctx;
 | 
					 | 
				
			||||||
	struct sandbox_scmi_agent *agent;
 | 
						struct sandbox_scmi_agent *agent;
 | 
				
			||||||
	struct udevice *dev = NULL;
 | 
						struct sandbox_scmi_devices *scmi_devices;
 | 
				
			||||||
 | 
						struct udevice *agent_dev, *reset_dev, *dev = NULL;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = load_sandbox_scmi_test_devices(uts, &dev);
 | 
						ret = load_sandbox_scmi_test_devices(uts, &agent, &dev);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	scmi_devices = sandbox_scmi_devices_ctx(dev);
 | 
						scmi_devices = sandbox_scmi_devices_ctx(dev);
 | 
				
			||||||
	ut_assertnonnull(scmi_devices);
 | 
						ut_assertnonnull(scmi_devices);
 | 
				
			||||||
	scmi_ctx = sandbox_scmi_service_ctx();
 | 
					
 | 
				
			||||||
	ut_assertnonnull(scmi_ctx);
 | 
						/* Sandbox SCMI reset protocol doesn't have its own channel */
 | 
				
			||||||
	agent = scmi_ctx->agent;
 | 
						ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi",
 | 
				
			||||||
	ut_assertnonnull(agent);
 | 
										      &agent_dev));
 | 
				
			||||||
 | 
						ut_assertnonnull(agent_dev);
 | 
				
			||||||
 | 
						reset_dev = scmi_get_protocol(agent_dev, SCMI_PROTOCOL_ID_RESET_DOMAIN);
 | 
				
			||||||
 | 
						ut_assertnonnull(reset_dev);
 | 
				
			||||||
 | 
						ut_asserteq(0x0, sandbox_scmi_channel_id(reset_dev));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Test SCMI resect controller manipulation */
 | 
						/* Test SCMI resect controller manipulation */
 | 
				
			||||||
	ut_assert(!agent->reset[0].asserted);
 | 
						ut_assert(!agent->reset[0].asserted);
 | 
				
			||||||
@ -201,21 +309,16 @@ DM_TEST(dm_test_scmi_resets, UT_TESTF_SCAN_FDT);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static int dm_test_scmi_voltage_domains(struct unit_test_state *uts)
 | 
					static int dm_test_scmi_voltage_domains(struct unit_test_state *uts)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sandbox_scmi_devices *scmi_devices;
 | 
					 | 
				
			||||||
	struct sandbox_scmi_service *scmi_ctx;
 | 
					 | 
				
			||||||
	struct sandbox_scmi_agent *agent;
 | 
						struct sandbox_scmi_agent *agent;
 | 
				
			||||||
 | 
						struct sandbox_scmi_devices *scmi_devices;
 | 
				
			||||||
	struct dm_regulator_uclass_plat *uc_pdata;
 | 
						struct dm_regulator_uclass_plat *uc_pdata;
 | 
				
			||||||
	struct udevice *dev;
 | 
						struct udevice *dev;
 | 
				
			||||||
	struct udevice *regul0_dev;
 | 
						struct udevice *regul0_dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ut_assertok(load_sandbox_scmi_test_devices(uts, &dev));
 | 
						ut_assertok(load_sandbox_scmi_test_devices(uts, &agent, &dev));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	scmi_devices = sandbox_scmi_devices_ctx(dev);
 | 
						scmi_devices = sandbox_scmi_devices_ctx(dev);
 | 
				
			||||||
	ut_assertnonnull(scmi_devices);
 | 
						ut_assertnonnull(scmi_devices);
 | 
				
			||||||
	scmi_ctx = sandbox_scmi_service_ctx();
 | 
					 | 
				
			||||||
	ut_assertnonnull(scmi_ctx);
 | 
					 | 
				
			||||||
	agent = scmi_ctx->agent;
 | 
					 | 
				
			||||||
	ut_assertnonnull(agent);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Set/Get an SCMI voltage domain level */
 | 
						/* Set/Get an SCMI voltage domain level */
 | 
				
			||||||
	regul0_dev = scmi_devices->regul[0];
 | 
						regul0_dev = scmi_devices->regul[0];
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user