Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 66 additions & 11 deletions Documentation/devicetree/bindings/arm/arm,scmi.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,44 @@ the SCMI as described in ARM document number ARM DEN 0056A ("ARM System Control
and Management Interface Platform Design Document")[0] provide for OSPM in
the device tree.

The SCMI agent node with its properties shall be under the /firmware/ node.

Each protocol supported by an agent be defined by a sub-node in the SCMI
agent node as described in the following sections.

For a given SCMI agent node, the communication channel properties, as defined
by related SCMI tranport compatible bindings, can be either defined in the
root node of the SCMI device or in the subnode of the related SCMI protocol
supported by the device. In the former case, the communcation propoerties
are shared by all protocol. In the later case, each protocol node must
define all communication configuration expected by the related transport
channel.

Required properties common to all SCMI agent node:

- #address-cells : should be '1' if the device has sub-nodes, maps to
protocol identifier for a given sub-node.
- #size-cells : should be '0' as 'reg' property doesn't have any size
associated with it.

SCMI Agent over Mailbox transport channel
-----------------------------------------

SCMI messages can be exchange between agent and the SCMI server using a
mailbox device for message notification and a piece of shared memory for
message payload and protocol data transfer.

Required properties:

The scmi node with the following properties shall be under the /firmware/ node.
- compatible : "arm,scmi"

- compatible : shall be "arm,scmi"
- mboxes: List of phandle and mailbox channel specifiers. It should contain
exactly one or two mailboxes, one for transmitting messages("tx")
and another optional for receiving the notifications("rx") if
supported.

- shmem : List of phandle pointing to the shared memory(SHM) area as per
generic mailbox client binding.
- #address-cells : should be '1' if the device has sub-nodes, maps to
protocol identifier for a given sub-node.
- #size-cells : should be '0' as 'reg' property doesn't have any size
associated with it.

Optional properties:

Expand All @@ -37,11 +60,42 @@ The mailbox is the only permitted method of calling the SCMI firmware.
Mailbox doorbell is used as a mechanism to alert the presence of a
messages and/or notification.

Each protocol supported shall have a sub-node with corresponding compatible
as described in the following sections. If the platform supports dedicated
communication channel for a particular protocol, the 3 properties namely:
mboxes, mbox-names and shmem shall be present in the sub-node corresponding
to that protocol.
SCMI Agent over Arm SMCCC transport channel
-------------------------------------------

On Arm based systems that support secure world invocation through secure
monitor, SCMI messages can be exchange between agent and the SCMI server
using an Arm SMC or HVC instruction for message notification and a piece
of shared memory for message payload and protocol data transfer.

Required properties:

- compatible : "arm,scmi-smc"

- shmem : List of phandle pointing to the shared memory(SHM) area as per
generic mailbox client binding.

- arm,smc-id : function identifier used a argument to the SMC/HVC instruction
as defined in Arm SMCCC specification [6].

- method : "smc" or "hvc"
Optional property defining the conduit method for to be used
for invoking the SCMI server in secure world.
"smc" states instruction SMC #0 is used whereas "hvc" states
instruction HVC #0 is used.

SCMI Agent over on OP-TEE Service
---------------------------------

On systems that support OP-TEE, SCMI messages can be exchange between agent
and the SCMI server using an OP-TEE invocation.

Required properties:

- compatible : "linaro,scmi-optee"

- agent-id : agent identifier assigned to the agent/channel and known from
the SCMI server in OP-TEE.

Clock/Performance bindings for the clocks/OPPs based on SCMI Message Protocol
------------------------------------------------------------
Expand Down Expand Up @@ -104,6 +158,7 @@ Required sub-node properties:
[3] Documentation/devicetree/bindings/thermal/thermal.txt
[4] Documentation/devicetree/bindings/sram/sram.yaml
[5] Documentation/devicetree/bindings/reset/reset.txt
[6] https://developer.arm.com/docs/den0028/latest

Example:

Expand Down
2 changes: 1 addition & 1 deletion drivers/firmware/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ menu "Firmware Drivers"
config ARM_SCMI_PROTOCOL
bool "ARM System Control and Management Interface (SCMI) Message Protocol"
depends on ARM || ARM64 || COMPILE_TEST
depends on MAILBOX
depends on MAILBOX || HAVE_ARM_SMCCC || OPTEE
help
ARM System Control and Management Interface (SCMI) protocol is a
set of operating system-independent software interfaces that are
Expand Down
5 changes: 4 additions & 1 deletion drivers/firmware/arm_scmi/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
obj-y = scmi-bus.o scmi-driver.o scmi-protocols.o scmi-transport.o
scmi-bus-y = bus.o
scmi-driver-y = driver.o
scmi-transport-y = mailbox.o shmem.o
scmi-transport-y = shmem.o
scmi-transport-$(CONFIG_MAILBOX) += mailbox.o
scmi-transport-$(CONFIG_HAVE_ARM_SMCCC) += smc.o
scmi-transport-$(CONFIG_OPTEE) += optee_service.o
scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o
obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
8 changes: 6 additions & 2 deletions drivers/firmware/arm_scmi/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
*
* Copyright (C) 2018 ARM Ltd.
*/
#ifndef ARM_SCMI_COMMON_H
#define ARM_SCMI_COMMON_H

#include <linux/bitfield.h>
#include <linux/completion.h>
Expand Down Expand Up @@ -172,7 +174,6 @@ struct scmi_chan_info {
/**
* struct scmi_transport_ops - Structure representing a SCMI transport ops
*
* @chan_available: Callback to check if channel is available or not
* @chan_setup: Callback to allocate and setup a channel
* @chan_free: Callback to free a channel
* @send_message: Callback to send a message
Expand All @@ -181,7 +182,6 @@ struct scmi_chan_info {
* @poll_done: Callback to poll transfer status
*/
struct scmi_transport_ops {
bool (*chan_available)(struct device *dev, int idx);
int (*chan_setup)(struct scmi_chan_info *cinfo, struct device *dev,
bool tx);
int (*chan_free)(int id, void *p, void *data);
Expand Down Expand Up @@ -210,6 +210,8 @@ struct scmi_desc {
};

extern const struct scmi_desc scmi_mailbox_desc;
extern const struct scmi_desc scmi_smc_desc;
extern const struct scmi_desc scmi_optee_desc;

void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr);
void scmi_free_channel(struct scmi_chan_info *cinfo, struct idr *idr, int id);
Expand All @@ -224,3 +226,5 @@ void shmem_fetch_response(struct scmi_shared_mem __iomem *shmem,
struct scmi_xfer *xfer);
bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem,
struct scmi_xfer *xfer);

#endif /* ARM_SCMI_COMMON_H */
35 changes: 28 additions & 7 deletions drivers/firmware/arm_scmi/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -261,13 +261,17 @@ void scmi_xfer_put(const struct scmi_handle *handle, struct scmi_xfer *xfer)

#define SCMI_MAX_POLL_TO_NS (100 * NSEC_PER_USEC)

static bool scmi_xfer_done_no_timeout(struct scmi_chan_info *cinfo,
struct scmi_xfer *xfer, ktime_t stop)
static bool scmi_poll_done(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer)
{
struct scmi_info *info = handle_to_scmi_info(cinfo->handle);

return info->desc->ops->poll_done(cinfo, xfer) ||
ktime_after(ktime_get(), stop);
return info->desc->ops->poll_done(cinfo, xfer);
}

static bool scmi_xfer_done_no_timeout(struct scmi_chan_info *cinfo,
struct scmi_xfer *xfer, ktime_t stop)
{
return scmi_poll_done(cinfo, xfer) || ktime_after(ktime_get(), stop);
}

/**
Expand Down Expand Up @@ -297,7 +301,7 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
xfer->hdr.poll_completion);

ret = info->desc->ops->send_message(cinfo, xfer);
if (ret < 0) {
if (ret) {
dev_dbg(dev, "Failed to send message %d\n", ret);
return ret;
}
Expand All @@ -307,7 +311,7 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)

spin_until_cond(scmi_xfer_done_no_timeout(cinfo, xfer, stop));

if (ktime_before(ktime_get(), stop))
if (scmi_poll_done(cinfo, xfer))
info->desc->ops->fetch_response(cinfo, xfer);
else
ret = -ETIMEDOUT;
Expand Down Expand Up @@ -566,6 +570,14 @@ static int scmi_xfer_info_init(struct scmi_info *sinfo)
return 0;
}

/* SCMI root node has no reg property */
static bool node_is_scmi_root_node(const struct device_node *np)
{
u32 protocol_id;

return of_property_read_u32(np, "reg", &protocol_id);
}

static int scmi_chan_setup(struct scmi_info *info, struct device *dev,
int prot_id, bool tx)
{
Expand All @@ -582,7 +594,8 @@ static int scmi_chan_setup(struct scmi_info *info, struct device *dev,
if (cinfo)
return 0;

if (!info->desc->ops->chan_available(dev, idx)) {
/* Channels are defined in SCMI device root node */
if (!node_is_scmi_root_node(dev->of_node)) {
cinfo = idr_find(idr, SCMI_PROTOCOL_BASE);
if (unlikely(!cinfo)) /* Possible only if platform has no Rx */
return -EINVAL;
Expand Down Expand Up @@ -826,7 +839,15 @@ ATTRIBUTE_GROUPS(versions);

/* Each compatible listed below must have descriptor associated with it */
static const struct of_device_id scmi_of_match[] = {
#ifdef CONFIG_MAILBOX
{ .compatible = "arm,scmi", .data = &scmi_mailbox_desc },
#endif
#ifdef CONFIG_HAVE_ARM_SMCCC
{ .compatible = "arm,scmi-smc", .data = &scmi_smc_desc},
#endif
#ifdef CONFIG_OPTEE
{ .compatible = "arm,scmi-optee", .data = &scmi_optee_desc },
#endif
{ /* Sentinel */ },
};

Expand Down
7 changes: 0 additions & 7 deletions drivers/firmware/arm_scmi/mailbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,6 @@ static void rx_callback(struct mbox_client *cl, void *m)
scmi_rx_callback(smbox->cinfo, shmem_read_header(smbox->shmem));
}

static bool mailbox_chan_available(struct device *dev, int idx)
{
return !of_parse_phandle_with_args(dev->of_node, "mboxes",
"#mbox-cells", idx, NULL);
}

static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
bool tx)
{
Expand Down Expand Up @@ -167,7 +161,6 @@ mailbox_poll_done(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer)
}

static struct scmi_transport_ops scmi_mailbox_ops = {
.chan_available = mailbox_chan_available,
.chan_setup = mailbox_chan_setup,
.chan_free = mailbox_chan_free,
.send_message = mailbox_send_message,
Expand Down
Loading