mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-03 21:48:15 +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>;
 | 
			
		||||
			#size-cells = <0>;
 | 
			
		||||
 | 
			
		||||
			protocol@10 {
 | 
			
		||||
				reg = <0x10>;
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			clk_scmi: protocol@14 {
 | 
			
		||||
				reg = <0x14>;
 | 
			
		||||
				#clock-cells = <1>;
 | 
			
		||||
				linaro,sandbox-channel-id = <0x14>;
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			reset_scmi: protocol@16 {
 | 
			
		||||
 | 
			
		||||
@ -88,11 +88,21 @@ struct sandbox_scmi_devices {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#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_agent_ctx - Get the simulated SCMI agent context
 | 
			
		||||
 * @dev:	Reference to the test agent
 | 
			
		||||
 * @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
 | 
			
		||||
@ -101,7 +111,12 @@ struct sandbox_scmi_service *sandbox_scmi_service_ctx(void);
 | 
			
		||||
 */
 | 
			
		||||
struct sandbox_scmi_devices *sandbox_scmi_devices_ctx(struct udevice *dev);
 | 
			
		||||
#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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -13,17 +13,8 @@
 | 
			
		||||
#include <asm/types.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)
 | 
			
		||||
{
 | 
			
		||||
	struct scmi_clk_priv *priv = dev_get_priv(dev);
 | 
			
		||||
	struct scmi_clk_protocol_attr_out out;
 | 
			
		||||
	struct scmi_msg msg = {
 | 
			
		||||
		.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;
 | 
			
		||||
 | 
			
		||||
	ret = devm_scmi_process_msg(dev, priv->channel, &msg);
 | 
			
		||||
	ret = devm_scmi_process_msg(dev, &msg);
 | 
			
		||||
	if (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)
 | 
			
		||||
{
 | 
			
		||||
	struct scmi_clk_priv *priv = dev_get_priv(dev);
 | 
			
		||||
	struct scmi_clk_attribute_in in = {
 | 
			
		||||
		.clock_id = clkid,
 | 
			
		||||
	};
 | 
			
		||||
@ -59,7 +49,7 @@ static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name)
 | 
			
		||||
	};
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = devm_scmi_process_msg(dev, priv->channel, &msg);
 | 
			
		||||
	ret = devm_scmi_process_msg(dev, &msg);
 | 
			
		||||
	if (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)
 | 
			
		||||
{
 | 
			
		||||
	struct scmi_clk_priv *priv = dev_get_priv(clk->dev);
 | 
			
		||||
	struct scmi_clk_state_in in = {
 | 
			
		||||
		.clock_id = clk->id,
 | 
			
		||||
		.attributes = enable,
 | 
			
		||||
@ -81,7 +70,7 @@ static int scmi_clk_gate(struct clk *clk, int enable)
 | 
			
		||||
					  in, out);
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg);
 | 
			
		||||
	ret = devm_scmi_process_msg(clk->dev, &msg);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
@ -100,7 +89,6 @@ static int scmi_clk_disable(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 = {
 | 
			
		||||
		.clock_id = clk->id,
 | 
			
		||||
	};
 | 
			
		||||
@ -110,7 +98,7 @@ static ulong scmi_clk_get_rate(struct clk *clk)
 | 
			
		||||
					  in, out);
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg);
 | 
			
		||||
	ret = devm_scmi_process_msg(clk->dev, &msg);
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		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)
 | 
			
		||||
{
 | 
			
		||||
	struct scmi_clk_priv *priv = dev_get_priv(clk->dev);
 | 
			
		||||
	struct scmi_clk_rate_set_in in = {
 | 
			
		||||
		.clock_id = clk->id,
 | 
			
		||||
		.flags = SCMI_CLK_RATE_ROUND_CLOSEST,
 | 
			
		||||
@ -136,7 +123,7 @@ static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
 | 
			
		||||
					  in, out);
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg);
 | 
			
		||||
	ret = devm_scmi_process_msg(clk->dev, &msg);
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		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)
 | 
			
		||||
{
 | 
			
		||||
	struct scmi_clk_priv *priv = dev_get_priv(dev);
 | 
			
		||||
	struct clk *clk;
 | 
			
		||||
	size_t num_clocks, i;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = devm_scmi_of_get_channel(dev, &priv->channel);
 | 
			
		||||
	ret = devm_scmi_of_get_channel(dev);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
@ -205,5 +191,4 @@ U_BOOT_DRIVER(scmi_clock) = {
 | 
			
		||||
	.id = UCLASS_CLK,
 | 
			
		||||
	.ops = &scmi_clk_ops,
 | 
			
		||||
	.probe = scmi_clk_probe,
 | 
			
		||||
	.priv_auto = sizeof(struct scmi_clk_priv *),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,5 @@
 | 
			
		||||
obj-y	+= scmi_agent-uclass.o
 | 
			
		||||
obj-y	+= base.o
 | 
			
		||||
obj-y	+= smt.o
 | 
			
		||||
obj-$(CONFIG_SCMI_AGENT_SMCCC)		+= smccc_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,
 | 
			
		||||
				 struct udevice *protocol,
 | 
			
		||||
				 struct scmi_channel **channel)
 | 
			
		||||
{
 | 
			
		||||
	struct scmi_mbox_channel *base_chan = dev_get_plat(dev);
 | 
			
		||||
	struct scmi_mbox_channel *chan;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	if (!dev_read_prop(dev, "shmem", NULL)) {
 | 
			
		||||
	if (!dev_read_prop(protocol, "shmem", NULL)) {
 | 
			
		||||
		/* Uses agent base channel */
 | 
			
		||||
		*channel = container_of(base_chan, struct scmi_channel, ref);
 | 
			
		||||
 | 
			
		||||
@ -112,7 +113,7 @@ static int scmi_mbox_get_channel(struct udevice *dev,
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
 | 
			
		||||
	/* Setup a dedicated channel for the protocol */
 | 
			
		||||
	ret = setup_channel(dev, chan);
 | 
			
		||||
	ret = setup_channel(protocol, chan);
 | 
			
		||||
	if (ret) {
 | 
			
		||||
		free(chan);
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
@ -149,7 +149,7 @@ static int open_channel(struct udevice *dev, struct scmi_optee_channel *chan,
 | 
			
		||||
	struct tee_param param[1] = { };
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	memset(sess, 0, sizeof(sess));
 | 
			
		||||
	memset(sess, 0, sizeof(*sess));
 | 
			
		||||
 | 
			
		||||
	sess->tee = tee_find_device(NULL, NULL, NULL, NULL);
 | 
			
		||||
	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,
 | 
			
		||||
				  struct udevice *protocol,
 | 
			
		||||
				  struct scmi_channel **channel)
 | 
			
		||||
{
 | 
			
		||||
	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;
 | 
			
		||||
	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 */
 | 
			
		||||
		*channel = container_of(base_chan, struct scmi_channel, ref);
 | 
			
		||||
 | 
			
		||||
@ -343,7 +344,7 @@ static int scmi_optee_get_channel(struct udevice *dev,
 | 
			
		||||
	if (!chan)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
 | 
			
		||||
	ret = setup_channel(dev, chan);
 | 
			
		||||
	ret = setup_channel(protocol, chan);
 | 
			
		||||
	if (ret) {
 | 
			
		||||
		free(chan);
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
@ -14,11 +14,14 @@
 | 
			
		||||
#include <asm/io.h>
 | 
			
		||||
#include <asm/scmi_test.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
 | 
			
		||||
 * processing. It simulates few of the SCMI services for some of the
 | 
			
		||||
 * SCMI protocols embedded in U-Boot. Currently:
 | 
			
		||||
 * - SCMI base protocol
 | 
			
		||||
 * - SCMI clock protocol emulates an agent exposing 2 clocks
 | 
			
		||||
 * - SCMI reset protocol emulates an agent exposing a reset controller
 | 
			
		||||
 * - SCMI voltage domain protocol emulates an agent exposing 2 regulators
 | 
			
		||||
@ -33,6 +36,41 @@
 | 
			
		||||
 * 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[] = {
 | 
			
		||||
	{ .rate = 333 },
 | 
			
		||||
	{ .rate = 200 },
 | 
			
		||||
@ -48,11 +86,9 @@ static struct sandbox_scmi_voltd scmi_voltd[] = {
 | 
			
		||||
	{ .id = 1, .voltage_uv = 1800000 },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct sandbox_scmi_service sandbox_scmi_service_state;
 | 
			
		||||
 | 
			
		||||
struct sandbox_scmi_service *sandbox_scmi_service_ctx(void)
 | 
			
		||||
struct sandbox_scmi_agent *sandbox_scmi_agent_ctx(struct udevice *dev)
 | 
			
		||||
{
 | 
			
		||||
	return &sandbox_scmi_service_state;
 | 
			
		||||
	return dev_get_priv(dev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* 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,
 | 
			
		||||
					       struct scmi_msg *msg)
 | 
			
		||||
{
 | 
			
		||||
@ -470,11 +816,108 @@ static int sandbox_scmi_voltd_level_get(struct udevice *dev,
 | 
			
		||||
	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,
 | 
			
		||||
					 struct scmi_channel *channel,
 | 
			
		||||
					 struct scmi_msg *msg)
 | 
			
		||||
{
 | 
			
		||||
	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:
 | 
			
		||||
		switch (msg->message_id) {
 | 
			
		||||
		case SCMI_PROTOCOL_ATTRIBUTES:
 | 
			
		||||
@ -517,7 +960,6 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev,
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case SCMI_PROTOCOL_ID_BASE:
 | 
			
		||||
	case SCMI_PROTOCOL_ID_POWER_DOMAIN:
 | 
			
		||||
	case SCMI_PROTOCOL_ID_SYSTEM:
 | 
			
		||||
	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)
 | 
			
		||||
{
 | 
			
		||||
	struct sandbox_scmi_agent *agent = dev_get_priv(dev);
 | 
			
		||||
 | 
			
		||||
	if (agent != sandbox_scmi_service_ctx()->agent)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	debug_print_agent_state(dev, "removed");
 | 
			
		||||
 | 
			
		||||
	/* We only need to dereference the agent in the context */
 | 
			
		||||
	sandbox_scmi_service_ctx()->agent = NULL;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -558,9 +992,6 @@ static int sandbox_scmi_test_probe(struct udevice *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct sandbox_scmi_agent *agent = dev_get_priv(dev);
 | 
			
		||||
 | 
			
		||||
	if (sandbox_scmi_service_ctx()->agent)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	*agent = (struct sandbox_scmi_agent){
 | 
			
		||||
		.clk = 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");
 | 
			
		||||
 | 
			
		||||
	/* Save reference for tests purpose */
 | 
			
		||||
	sandbox_scmi_service_ctx()->agent = agent;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -584,6 +1012,7 @@ static const struct udevice_id sandbox_scmi_test_ids[] = {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct scmi_agent_ops sandbox_scmi_test_ops = {
 | 
			
		||||
	.of_get_channel = sandbox_scmi_of_get_channel,
 | 
			
		||||
	.process_msg = sandbox_scmi_test_process_msg,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -592,6 +1021,8 @@ U_BOOT_DRIVER(sandbox_scmi_agent) = {
 | 
			
		||||
	.id = UCLASS_SCMI_AGENT,
 | 
			
		||||
	.of_match = sandbox_scmi_test_ids,
 | 
			
		||||
	.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,
 | 
			
		||||
	.remove = sandbox_scmi_test_remove,
 | 
			
		||||
	.ops = &sandbox_scmi_test_ops,
 | 
			
		||||
 | 
			
		||||
@ -8,6 +8,7 @@
 | 
			
		||||
#include <common.h>
 | 
			
		||||
#include <dm.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <scmi_agent.h>
 | 
			
		||||
#include <scmi_agent-uclass.h>
 | 
			
		||||
#include <scmi_protocols.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_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 n;
 | 
			
		||||
@ -51,8 +164,191 @@ int scmi_to_linux_errno(s32 scmi_code)
 | 
			
		||||
	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
 | 
			
		||||
 * 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;
 | 
			
		||||
	ofnode node;
 | 
			
		||||
	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) {
 | 
			
		||||
		struct driver *drv = NULL;
 | 
			
		||||
		u32 protocol_id;
 | 
			
		||||
 | 
			
		||||
		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))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		drv = NULL;
 | 
			
		||||
		name = ofnode_get_name(node);
 | 
			
		||||
		switch (protocol_id) {
 | 
			
		||||
		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);
 | 
			
		||||
			break;
 | 
			
		||||
		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);
 | 
			
		||||
			break;
 | 
			
		||||
		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");
 | 
			
		||||
				if (!ofnode_valid(node)) {
 | 
			
		||||
					dev_err(dev, "no regulators node\n");
 | 
			
		||||
@ -102,70 +436,26 @@ static int scmi_bind_protocols(struct udevice *dev)
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ret = device_bind(dev, drv, name, NULL, node, NULL);
 | 
			
		||||
		if (ret)
 | 
			
		||||
		ret = device_bind(dev, drv, name, NULL, node, &proto);
 | 
			
		||||
		if (ret) {
 | 
			
		||||
			dev_err(dev, "failed to bind %s protocol\n", drv->name);
 | 
			
		||||
			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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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) = {
 | 
			
		||||
	.id		= UCLASS_SCMI_AGENT,
 | 
			
		||||
	.name		= "scmi_agent",
 | 
			
		||||
	.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,
 | 
			
		||||
				  struct udevice *protocol,
 | 
			
		||||
				  struct scmi_channel **channel)
 | 
			
		||||
{
 | 
			
		||||
	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;
 | 
			
		||||
	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 */
 | 
			
		||||
		*channel = container_of(base_chan, struct scmi_channel, ref);
 | 
			
		||||
 | 
			
		||||
@ -100,7 +101,7 @@ static int scmi_smccc_get_channel(struct udevice *dev,
 | 
			
		||||
	if (!chan)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
 | 
			
		||||
	ret = setup_channel(dev, chan);
 | 
			
		||||
	ret = setup_channel(protocol, chan);
 | 
			
		||||
	if (ret) {
 | 
			
		||||
		free(chan);
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
@ -25,18 +25,9 @@ struct scmi_regulator_platdata {
 | 
			
		||||
	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)
 | 
			
		||||
{
 | 
			
		||||
	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 = {
 | 
			
		||||
		.domain_id = pdata->domain_id,
 | 
			
		||||
		.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);
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = devm_scmi_process_msg(dev, priv->channel, &msg);
 | 
			
		||||
	ret = devm_scmi_process_msg(dev, &msg);
 | 
			
		||||
	if (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)
 | 
			
		||||
{
 | 
			
		||||
	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 = {
 | 
			
		||||
		.domain_id = pdata->domain_id,
 | 
			
		||||
	};
 | 
			
		||||
@ -67,7 +57,7 @@ static int scmi_voltd_get_enable(struct udevice *dev)
 | 
			
		||||
					  in, out);
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = devm_scmi_process_msg(dev, priv->channel, &msg);
 | 
			
		||||
	ret = devm_scmi_process_msg(dev, &msg);
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		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)
 | 
			
		||||
{
 | 
			
		||||
	struct scmi_regulator_priv *priv = dev_get_priv(dev);
 | 
			
		||||
	struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
 | 
			
		||||
	struct scmi_voltd_level_set_in in = {
 | 
			
		||||
		.domain_id = pdata->domain_id,
 | 
			
		||||
@ -92,7 +81,7 @@ static int scmi_voltd_set_voltage_level(struct udevice *dev, int uV)
 | 
			
		||||
					  in, out);
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = devm_scmi_process_msg(dev, priv->channel, &msg);
 | 
			
		||||
	ret = devm_scmi_process_msg(dev, &msg);
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		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)
 | 
			
		||||
{
 | 
			
		||||
	struct scmi_regulator_priv *priv = dev_get_priv(dev);
 | 
			
		||||
	struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
 | 
			
		||||
	struct scmi_voltd_level_get_in in = {
 | 
			
		||||
		.domain_id = pdata->domain_id,
 | 
			
		||||
@ -112,7 +100,7 @@ static int scmi_voltd_get_voltage_level(struct udevice *dev)
 | 
			
		||||
					  in, out);
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = devm_scmi_process_msg(dev, priv->channel, &msg);
 | 
			
		||||
	ret = devm_scmi_process_msg(dev, &msg);
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
@ -140,7 +128,6 @@ static int scmi_regulator_of_to_plat(struct udevice *dev)
 | 
			
		||||
static int scmi_regulator_probe(struct udevice *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_out out = { 0 };
 | 
			
		||||
	struct scmi_msg scmi_msg = {
 | 
			
		||||
@ -153,14 +140,14 @@ static int scmi_regulator_probe(struct udevice *dev)
 | 
			
		||||
	};
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = devm_scmi_of_get_channel(dev->parent, &priv->channel);
 | 
			
		||||
	ret = devm_scmi_of_get_channel(dev);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	/* Check voltage domain is known from SCMI server */
 | 
			
		||||
	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) {
 | 
			
		||||
		dev_err(dev, "Failed to query voltage domain %u: %d\n",
 | 
			
		||||
			pdata->domain_id, ret);
 | 
			
		||||
@ -184,7 +171,6 @@ U_BOOT_DRIVER(scmi_regulator) = {
 | 
			
		||||
	.probe = scmi_regulator_probe,
 | 
			
		||||
	.of_to_plat = scmi_regulator_of_to_plat,
 | 
			
		||||
	.plat_auto = sizeof(struct scmi_regulator_platdata),
 | 
			
		||||
	.priv_auto = sizeof(struct scmi_regulator_priv *),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int scmi_regulator_bind(struct udevice *dev)
 | 
			
		||||
 | 
			
		||||
@ -13,17 +13,8 @@
 | 
			
		||||
#include <scmi_protocols.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)
 | 
			
		||||
{
 | 
			
		||||
	struct scmi_reset_priv *priv = dev_get_priv(rst->dev);
 | 
			
		||||
	struct scmi_rd_reset_in in = {
 | 
			
		||||
		.domain_id = rst->id,
 | 
			
		||||
		.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);
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = devm_scmi_process_msg(rst->dev, priv->channel, &msg);
 | 
			
		||||
	ret = devm_scmi_process_msg(rst->dev, &msg);
 | 
			
		||||
	if (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)
 | 
			
		||||
{
 | 
			
		||||
	struct scmi_reset_priv *priv = dev_get_priv(rst->dev);
 | 
			
		||||
	struct scmi_rd_attr_in in = {
 | 
			
		||||
		.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
 | 
			
		||||
	 * the reset domain exists.
 | 
			
		||||
	 */
 | 
			
		||||
	ret = devm_scmi_process_msg(rst->dev, priv->channel, &msg);
 | 
			
		||||
	ret = devm_scmi_process_msg(rst->dev, &msg);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
@ -83,9 +73,7 @@ static const struct reset_ops scmi_reset_domain_ops = {
 | 
			
		||||
 | 
			
		||||
static int scmi_reset_probe(struct udevice *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct scmi_reset_priv *priv = dev_get_priv(dev);
 | 
			
		||||
 | 
			
		||||
	return devm_scmi_of_get_channel(dev, &priv->channel);
 | 
			
		||||
	return devm_scmi_of_get_channel(dev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
U_BOOT_DRIVER(scmi_reset_domain) = {
 | 
			
		||||
@ -93,5 +81,4 @@ U_BOOT_DRIVER(scmi_reset_domain) = {
 | 
			
		||||
	.id = UCLASS_RESET,
 | 
			
		||||
	.ops = &scmi_reset_domain_ops,
 | 
			
		||||
	.probe = scmi_reset_probe,
 | 
			
		||||
	.priv_auto = sizeof(struct scmi_reset_priv *),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -123,6 +123,7 @@ enum uclass_id {
 | 
			
		||||
	UCLASS_RNG,		/* Random Number Generator */
 | 
			
		||||
	UCLASS_RTC,		/* Real time clock device */
 | 
			
		||||
	UCLASS_SCMI_AGENT,	/* Interface with an SCMI server */
 | 
			
		||||
	UCLASS_SCMI_BASE,	/* Interface for SCMI Base protocol */
 | 
			
		||||
	UCLASS_SCSI,		/* SCSI device */
 | 
			
		||||
	UCLASS_SERIAL,		/* Serial UART */
 | 
			
		||||
	UCLASS_SIMPLE_BUS,	/* Bus with child devices */
 | 
			
		||||
 | 
			
		||||
@ -5,10 +5,89 @@
 | 
			
		||||
#ifndef _SCMI_AGENT_UCLASS_H
 | 
			
		||||
#define _SCMI_AGENT_UCLASS_H
 | 
			
		||||
 | 
			
		||||
struct udevice;
 | 
			
		||||
#include <scmi_protocols.h>
 | 
			
		||||
#include <dm/device.h>
 | 
			
		||||
 | 
			
		||||
struct scmi_msg;
 | 
			
		||||
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.
 | 
			
		||||
 */
 | 
			
		||||
@ -16,16 +95,18 @@ struct scmi_agent_ops {
 | 
			
		||||
	/*
 | 
			
		||||
	 * 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
 | 
			
		||||
	 * 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
 | 
			
		||||
	 *
 | 
			
		||||
	 * @dev:		SCMI protocol device using the transport
 | 
			
		||||
	 * @dev:		SCMI agent device using the transport
 | 
			
		||||
	 * @msg:		SCMI message to be transmitted
 | 
			
		||||
	 */
 | 
			
		||||
	int (*process_msg)(struct udevice *dev, struct scmi_channel *channel,
 | 
			
		||||
 | 
			
		||||
@ -10,11 +10,20 @@
 | 
			
		||||
#ifndef SCMI_AGENT_H
 | 
			
		||||
#define SCMI_AGENT_H
 | 
			
		||||
 | 
			
		||||
#include <scmi_protocols.h>
 | 
			
		||||
#include <asm/types.h>
 | 
			
		||||
 | 
			
		||||
struct udevice;
 | 
			
		||||
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
 | 
			
		||||
 *
 | 
			
		||||
@ -49,10 +58,9 @@ struct scmi_msg {
 | 
			
		||||
 * devm_scmi_of_get_channel() - Get SCMI channel handle from SCMI agent DT node
 | 
			
		||||
 *
 | 
			
		||||
 * @dev:	Device requesting a channel
 | 
			
		||||
 * @channel:	Output reference to the SCMI channel upon success
 | 
			
		||||
 * @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
 | 
			
		||||
@ -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.
 | 
			
		||||
 *
 | 
			
		||||
 * @dev:	SCMI device
 | 
			
		||||
 * @channel:	Communication channel for the device
 | 
			
		||||
 * @msg:	Message structure reference
 | 
			
		||||
 * Return: 0 on success and a negative errno on failure
 | 
			
		||||
 */
 | 
			
		||||
int devm_scmi_process_msg(struct udevice *dev, struct scmi_channel *channel,
 | 
			
		||||
			  struct scmi_msg *msg);
 | 
			
		||||
int devm_scmi_process_msg(struct udevice *dev, 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
 | 
			
		||||
 | 
			
		||||
@ -49,6 +49,501 @@ enum scmi_discovery_id {
 | 
			
		||||
	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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										195
									
								
								test/dm/scmi.c
									
									
									
									
									
								
							
							
						
						
									
										195
									
								
								test/dm/scmi.c
									
									
									
									
									
								
							@ -16,6 +16,9 @@
 | 
			
		||||
#include <clk.h>
 | 
			
		||||
#include <dm.h>
 | 
			
		||||
#include <reset.h>
 | 
			
		||||
#include <scmi_agent.h>
 | 
			
		||||
#include <scmi_agent-uclass.h>
 | 
			
		||||
#include <scmi_protocols.h>
 | 
			
		||||
#include <asm/scmi_test.h>
 | 
			
		||||
#include <dm/device-internal.h>
 | 
			
		||||
#include <dm/test.h>
 | 
			
		||||
@ -23,22 +26,11 @@
 | 
			
		||||
#include <power/regulator.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,
 | 
			
		||||
					  struct sandbox_scmi_agent *agent,
 | 
			
		||||
					  struct udevice *dev)
 | 
			
		||||
{
 | 
			
		||||
	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 */
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
	/* 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_assertnonnull(agent->clk);
 | 
			
		||||
	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,
 | 
			
		||||
					  struct sandbox_scmi_agent **ctx,
 | 
			
		||||
					  struct udevice **dev)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	struct udevice *agent_dev;
 | 
			
		||||
 | 
			
		||||
	ret = ut_assert_scmi_state_preprobe(uts);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
	ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi",
 | 
			
		||||
					      &agent_dev));
 | 
			
		||||
	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",
 | 
			
		||||
					      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,
 | 
			
		||||
					     struct udevice *dev)
 | 
			
		||||
{
 | 
			
		||||
	/* un-probe */
 | 
			
		||||
	ut_assertok(device_remove(dev, DM_REMOVE_NORMAL));
 | 
			
		||||
 | 
			
		||||
	/* Not sure test devices are fully removed, agent may not be visible */
 | 
			
		||||
	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)
 | 
			
		||||
{
 | 
			
		||||
	struct sandbox_scmi_agent *ctx;
 | 
			
		||||
	struct udevice *dev = NULL;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = load_sandbox_scmi_test_devices(uts, &dev);
 | 
			
		||||
	ret = load_sandbox_scmi_test_devices(uts, &ctx, &dev);
 | 
			
		||||
	if (!ret)
 | 
			
		||||
		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);
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
	struct sandbox_scmi_devices *scmi_devices;
 | 
			
		||||
	struct sandbox_scmi_service *scmi_ctx;
 | 
			
		||||
	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;
 | 
			
		||||
 | 
			
		||||
	ret = load_sandbox_scmi_test_devices(uts, &dev);
 | 
			
		||||
	ret = load_sandbox_scmi_test_devices(uts, &agent, &dev);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	scmi_devices = sandbox_scmi_devices_ctx(dev);
 | 
			
		||||
	ut_assertnonnull(scmi_devices);
 | 
			
		||||
	scmi_ctx = sandbox_scmi_service_ctx();
 | 
			
		||||
	ut_assertnonnull(scmi_ctx);
 | 
			
		||||
	agent = scmi_ctx->agent;
 | 
			
		||||
	ut_assertnonnull(agent);
 | 
			
		||||
 | 
			
		||||
	/* Sandbox SCMI clock protocol has its own channel */
 | 
			
		||||
	ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi",
 | 
			
		||||
					      &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 */
 | 
			
		||||
	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)
 | 
			
		||||
{
 | 
			
		||||
	struct sandbox_scmi_devices *scmi_devices;
 | 
			
		||||
	struct sandbox_scmi_service *scmi_ctx;
 | 
			
		||||
	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;
 | 
			
		||||
 | 
			
		||||
	ret = load_sandbox_scmi_test_devices(uts, &dev);
 | 
			
		||||
	ret = load_sandbox_scmi_test_devices(uts, &agent, &dev);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	scmi_devices = sandbox_scmi_devices_ctx(dev);
 | 
			
		||||
	ut_assertnonnull(scmi_devices);
 | 
			
		||||
	scmi_ctx = sandbox_scmi_service_ctx();
 | 
			
		||||
	ut_assertnonnull(scmi_ctx);
 | 
			
		||||
	agent = scmi_ctx->agent;
 | 
			
		||||
	ut_assertnonnull(agent);
 | 
			
		||||
 | 
			
		||||
	/* Sandbox SCMI reset protocol doesn't have its own channel */
 | 
			
		||||
	ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi",
 | 
			
		||||
					      &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 */
 | 
			
		||||
	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)
 | 
			
		||||
{
 | 
			
		||||
	struct sandbox_scmi_devices *scmi_devices;
 | 
			
		||||
	struct sandbox_scmi_service *scmi_ctx;
 | 
			
		||||
	struct sandbox_scmi_agent *agent;
 | 
			
		||||
	struct sandbox_scmi_devices *scmi_devices;
 | 
			
		||||
	struct dm_regulator_uclass_plat *uc_pdata;
 | 
			
		||||
	struct udevice *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);
 | 
			
		||||
	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 */
 | 
			
		||||
	regul0_dev = scmi_devices->regul[0];
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user