@@ -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
new file mode 100644
@@ -0,0 +1,517 @@
+// 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 <asm/types.h>
+#include <dm/device_compat.h>
+#include <linux/kernel.h>
+
+/**
+ * struct scmi_base_priv - Private data for SCMI base protocol
+ * @channel: Reference to the SCMI channel to use
+ */
+struct scmi_base_priv {
+ struct scmi_channel *channel;
+};
+
+/**
+ * scmi_protocol_version - get protocol version
+ * @dev: Device
+ * @version: Pointer to protocol version
+ *
+ * Obtain the protocol version number in @version.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+static int scmi_protocol_version(struct udevice *dev, u32 *version)
+{
+ struct scmi_base_priv *priv = dev_get_priv(dev);
+ struct scmi_protocol_version_out out;
+ struct scmi_msg msg = {
+ .protocol_id = SCMI_PROTOCOL_ID_BASE,
+ .message_id = SCMI_PROTOCOL_VERSION,
+ .out_msg = (u8 *)&out,
+ .out_msg_sz = sizeof(out),
+ };
+ int ret;
+
+ ret = devm_scmi_process_msg(dev, priv->channel, &msg);
+ if (ret)
+ return ret;
+ if (out.status)
+ return scmi_to_linux_errno(out.status);
+
+ *version = out.version;
+
+ return 0;
+}
+
+/**
+ * scmi_protocol_attrs - get protocol attributes
+ * @dev: Device
+ * @num_agents: Number of agents
+ * @num_protocols: Number of 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 otherwise
+ */
+static int scmi_protocol_attrs(struct udevice *dev, u32 *num_agents,
+ u32 *num_protocols)
+{
+ struct scmi_base_priv *priv = dev_get_priv(dev);
+ 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, priv->channel, &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 - get message-specific attributes
+ * @dev: Device
+ * @message_id: Identifier of message
+ * @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 otherwise
+ */
+static int scmi_protocol_message_attrs(struct udevice *dev, u32 message_id,
+ u32 *attributes)
+{
+ struct scmi_base_priv *priv = dev_get_priv(dev);
+ 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, priv->channel, &msg);
+ if (ret)
+ return ret;
+ if (out.status)
+ return scmi_to_linux_errno(out.status);
+
+ *attributes = out.attributes;
+
+ return 0;
+}
+
+/**
+ * scmi_base_discover_vendor - get vendor name
+ * @dev: Device
+ * @vendor: Vendor name
+ *
+ * Obtain the vendor's name in @vendor.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+static int scmi_base_discover_vendor(struct udevice *dev, u8 *vendor)
+{
+ struct scmi_base_priv *priv = dev_get_priv(dev);
+ 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;
+
+ ret = devm_scmi_process_msg(dev, priv->channel, &msg);
+ if (ret)
+ return ret;
+ if (out.status)
+ return scmi_to_linux_errno(out.status);
+
+ strcpy(vendor, out.vendor_identifier);
+
+ return 0;
+}
+
+/**
+ * scmi_base_discover_sub_vendor - get sub-vendor name
+ * @dev: Device
+ * @sub_vendor: Sub-vendor name
+ *
+ * Obtain the sub-vendor's name in @sub_vendor.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+static int scmi_base_discover_sub_vendor(struct udevice *dev, u8 *sub_vendor)
+{
+ struct scmi_base_priv *priv = dev_get_priv(dev);
+ 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;
+
+ ret = devm_scmi_process_msg(dev, priv->channel, &msg);
+ if (ret)
+ return ret;
+ if (out.status)
+ return scmi_to_linux_errno(out.status);
+
+ strcpy(sub_vendor, out.vendor_identifier);
+
+ return 0;
+}
+
+/**
+ * scmi_base_discover_impl_version - get implementation version
+ * @dev: Device
+ * @impl_version: Pointer to implementation version
+ *
+ * Obtain the implementation version number in @impl_version.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+static int scmi_base_discover_impl_version(struct udevice *dev, u32 *impl_version)
+{
+ struct scmi_base_priv *priv = dev_get_priv(dev);
+ 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, priv->channel, &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 - get list of protocols
+ * @dev: Device
+ * @protocols: Pointer to array of 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 otherwise
+ */
+static int scmi_base_discover_list_protocols(struct udevice *dev, u8 **protocols)
+{
+ struct scmi_base_priv *priv = dev_get_priv(dev);
+ 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_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, priv->channel, &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 - identify agent
+ * @dev: Device
+ * @agent_id: Identifier of agent
+ * @ret_agent_id: Pointer to identifier of agent
+ * @name: 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.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+static int scmi_base_discover_agent(struct udevice *dev, u32 agent_id,
+ u32 *ret_agent_id, u8 *name)
+{
+ struct scmi_base_priv *priv = dev_get_priv(dev);
+ 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, priv->channel, &msg);
+ if (ret)
+ return ret;
+ if (out.status)
+ return scmi_to_linux_errno(out.status);
+
+ strcpy(name, out.name);
+ *ret_agent_id = out.agent_id;
+
+ return 0;
+}
+
+/**
+ * scmi_base_notify_errors - configure error notification
+ * @dev: Device
+ * @enable: Operation
+ *
+ * This function is not yet implemented.
+ *
+ * Return: always -EOPNOTSUPP
+ */
+static int scmi_base_notify_errors(struct udevice *dev, u32 enable)
+{
+ return -EOPNOTSUPP;
+}
+
+/**
+ * scmi_base_set_device_permissions - configure access permission to device
+ * @dev: Device
+ * @agent_id: Identifier of agent
+ * @device_id: Identifier 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 otherwise
+ */
+static int scmi_base_set_device_permissions(struct udevice *dev, u32 agent_id,
+ u32 device_id, u32 flags)
+{
+ struct scmi_base_priv *priv = dev_get_priv(dev);
+ 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, priv->channel, &msg);
+ if (ret)
+ return ret;
+ if (status)
+ return scmi_to_linux_errno(status);
+
+ return 0;
+}
+
+/**
+ * scmi_base_set_protocol_permissions - configure access permission to protocol
+ on device
+ * @dev: Device
+ * @agent_id: Identifier of agent
+ * @device_id: Identifier of device to access
+ * @command_id: Identifier of command
+ * @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 otherwise
+ */
+static int scmi_base_set_protocol_permissions(struct udevice *dev, u32 agent_id,
+ u32 device_id, u32 command_id,
+ u32 flags)
+{
+ struct scmi_base_priv *priv = dev_get_priv(dev);
+ 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, priv->channel, &msg);
+ if (ret)
+ return ret;
+ if (status)
+ return scmi_to_linux_errno(status);
+
+ return 0;
+}
+
+/**
+ * scmi_base_reset_agent_configuration - reset resource settings
+ * @dev: Device
+ * @agent_id: Identifier of agent
+ * @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 otherwise
+ */
+static int scmi_base_reset_agent_configuration(struct udevice *dev, u32 agent_id,
+ u32 flags)
+{
+ struct scmi_base_priv *priv = dev_get_priv(dev);
+ 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, priv->channel, &msg);
+ if (ret)
+ return ret;
+ if (status)
+ return scmi_to_linux_errno(status);
+
+ return 0;
+}
+
+/**
+ * scmi_base_probe - probe base protocol device
+ * @dev: Device
+ *
+ * Probe the device for SCMI base protocol and initialize the private data.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+static int scmi_base_probe(struct udevice *dev)
+{
+ struct scmi_base_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = devm_scmi_of_get_channel(dev, &priv->channel);
+ if (ret) {
+ dev_err(dev, "get_channel failed\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+struct scmi_base_ops scmi_base_ops = {
+ /* Commands */
+ .protocol_version = scmi_protocol_version,
+ .protocol_attrs = scmi_protocol_attrs,
+ .protocol_message_attrs = scmi_protocol_message_attrs,
+ .base_discover_vendor = scmi_base_discover_vendor,
+ .base_discover_sub_vendor = scmi_base_discover_sub_vendor,
+ .base_discover_impl_version = scmi_base_discover_impl_version,
+ .base_discover_list_protocols = scmi_base_discover_list_protocols,
+ .base_discover_agent = scmi_base_discover_agent,
+ .base_notify_errors = scmi_base_notify_errors,
+ .base_set_device_permissions = scmi_base_set_device_permissions,
+ .base_set_protocol_permissions = scmi_base_set_protocol_permissions,
+ .base_reset_agent_configuration = scmi_base_reset_agent_configuration,
+};
+
+U_BOOT_DRIVER(scmi_base_drv) = {
+ .id = UCLASS_SCMI_BASE,
+ .name = "scmi_base_drv",
+ .ops = &scmi_base_ops,
+ .probe = scmi_base_probe,
+ .priv_auto = sizeof(struct scmi_base_priv *),
+};
+
+UCLASS_DRIVER(scmi_base) = {
+ .id = UCLASS_SCMI_BASE,
+ .name = "scmi_base",
+};
@@ -116,6 +116,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 */
@@ -15,6 +15,8 @@
* https://developer.arm.com/docs/den0056/b
*/
+#define SCMI_BASE_NAME_LENGTH_MAX 16
+
enum scmi_std_protocol {
SCMI_PROTOCOL_ID_BASE = 0x10,
SCMI_PROTOCOL_ID_POWER_DOMAIN = 0x11,
@@ -41,12 +43,207 @@ enum scmi_status_code {
};
/*
- * Generic message IDs
+ * SCMI Base Protocol
*/
-enum scmi_discovery_id {
+#define SCMI_BASE_PROTOCOL_VERSION 0x20000
+
+enum scmi_base_message_id {
SCMI_PROTOCOL_VERSION = 0x0,
SCMI_PROTOCOL_ATTRIBUTES = 0x1,
SCMI_PROTOCOL_MESSAGE_ATTRIBUTES = 0x2,
+ 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,
+};
+
+/**
+ * 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: Identifier 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 protocols in @protocol
+ * @protocols: Array of packed 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: Identifier of agent
+ * @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: Identifier of agent
+ * @device_id: Identifier of device
+ * @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: Identifier of agent
+ * @device_id: Identifier of device
+ * @command_id: Identifier of command
+ * @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: Identifier of agent
+ * @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
+ * @protocol_version: Function pointer for
+ * PROTOCOL_VERSION
+ * @protocol_attrs: Function pointer for
+ * PROTOCOL_ATTRIBUTES
+ * @protocol_message_attrs: Function pointer for
+ * PROTOCOL_MESSAGE_ATTRIBUTES
+ * @base_discover_vendor: Function pointer for
+ * BASE_DISCOVER_VENDOR
+ * @base_discover_sub_vendor: Function pointer for
+ * BASE_DISCOVER_SUB_VENDOR
+ * @base_discover_impl_version: Function pointer for
+ * BASE_DISCOVER_IMPLEMENTATION_VERSION
+ * @base_discover_list_protocols: Function pointer for
+ * BASE_DISCOVER_LIST_PROTOCOLS
+ * @base_discover_agent: Function pointer for
+ * BASE_DISCOVER_AGENT
+ * @base_notify_errors: Function pointer for
+ * BASE_NOTIFY_ERRORS
+ * @base_set_device_permissions: Function pointer for
+ * BASE_SET_DEVICE_PROTOCOLS
+ * @base_set_protocol_permissions: Function pointer for
+ * BASE_SET_PROTOCOL_PERMISSIONS
+ * @base_reset_agent_configuration: Function pointer for
+ * BASE_RESET_AGENT_CONFIGURATION
+ */
+struct scmi_base_ops {
+ int (*protocol_version)(struct udevice *dev, u32 *version);
+ int (*protocol_attrs)(struct udevice *dev, u32 *num_agents,
+ u32 *num_protocols);
+ int (*protocol_message_attrs)(struct udevice *dev, u32 message_id,
+ u32 *attributes);
+ int (*base_discover_vendor)(struct udevice *dev, u8 *vendor);
+ int (*base_discover_sub_vendor)(struct udevice *dev, u8 *sub_vendor);
+ int (*base_discover_impl_version)(struct udevice *dev, u32 *impl_version);
+ int (*base_discover_list_protocols)(struct udevice *dev, u8 **protocols);
+ int (*base_discover_agent)(struct udevice *dev, u32 agent_id,
+ u32 *ret_agent_id, u8 *name);
+ int (*base_notify_errors)(struct udevice *dev, u32 enable);
+ int (*base_set_device_permissions)(struct udevice *dev, u32 agent_id,
+ u32 device_id, u32 flags);
+ int (*base_set_protocol_permissions)(struct udevice *dev, u32 agent_id,
+ u32 device_id, u32 command_id,
+ u32 flags);
+ int (*base_reset_agent_configuration)(struct udevice *dev, u32 agent_id,
+ u32 flags);
};
/*
SCMI base protocol is mandatory according to the SCMI specification. With this patch, SCMI base protocol can be accessed via SCMI transport layers. All the commands, except SCMI_BASE_NOTIFY_ERRORS, are supported. This is because U-Boot doesn't support interrupts and the current transport layers are not able to handle asynchronous messages properly. Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org> --- drivers/firmware/scmi/Makefile | 1 + drivers/firmware/scmi/base.c | 517 +++++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + include/scmi_protocols.h | 201 ++++++++++++- 4 files changed, 718 insertions(+), 2 deletions(-) create mode 100644 drivers/firmware/scmi/base.c