firmware: arm_scmi: Make SMC transport a standalone driver

Make SCMI SMC transport a standalone driver that can be optionally
loaded as a module.

CC: Peng Fan <peng.fan@nxp.com>
CC: Nikunj Kela <quic_nkela@quicinc.com>
Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
Message-Id: <20240812173340.3912830-7-cristian.marussi@arm.com>
[sudeep.holla: moved Clang Thumb2 build fix to the new makefile]
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
This commit is contained in:
Cristian Marussi 2024-08-12 18:33:37 +01:00 committed by Sudeep Holla
parent b53515fa17
commit a41759500b
7 changed files with 62 additions and 49 deletions

View File

@ -84,32 +84,6 @@ config ARM_SCMI_TRANSPORT_OPTEE
If you want the ARM SCMI PROTOCOL stack to include support for a
transport based on OP-TEE SCMI service, answer Y.
config ARM_SCMI_TRANSPORT_SMC
bool "SCMI transport based on SMC"
depends on HAVE_ARM_SMCCC_DISCOVERY
select ARM_SCMI_HAVE_TRANSPORT
select ARM_SCMI_HAVE_SHMEM
default y
help
Enable SMC based transport for SCMI.
If you want the ARM SCMI PROTOCOL stack to include support for a
transport based on SMC, answer Y.
config ARM_SCMI_TRANSPORT_SMC_ATOMIC_ENABLE
bool "Enable atomic mode support for SCMI SMC transport"
depends on ARM_SCMI_TRANSPORT_SMC
help
Enable support of atomic operation for SCMI SMC based transport.
If you want the SCMI SMC based transport to operate in atomic
mode, avoiding any kind of sleeping behaviour for selected
transactions on the TX path, answer Y.
Enabling atomic mode operations allows any SCMI driver using this
transport to optionally ask for atomic SCMI transactions and operate
in atomic context too, at the price of using a number of busy-waiting
primitives all over instead. If unsure say N.
config ARM_SCMI_TRANSPORT_VIRTIO
bool "SCMI transport based on VirtIO"
depends on VIRTIO=y || VIRTIO=ARM_SCMI_PROTOCOL

View File

@ -5,7 +5,6 @@ scmi-core-objs := $(scmi-bus-y)
scmi-driver-y = driver.o notify.o
scmi-driver-$(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT) += raw_mode.o
scmi-transport-$(CONFIG_ARM_SCMI_HAVE_SHMEM) = shmem.o
scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_SMC) += smc.o
scmi-transport-$(CONFIG_ARM_SCMI_HAVE_MSG) += msg.o
scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_VIRTIO) += virtio.o
scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_OPTEE) += optee.o
@ -19,10 +18,3 @@ obj-$(CONFIG_ARM_SCMI_PROTOCOL) += scmi-core.o
obj-$(CONFIG_ARM_SCMI_PROTOCOL) += scmi-module.o
obj-$(CONFIG_ARM_SCMI_POWER_CONTROL) += scmi_power_control.o
ifeq ($(CONFIG_THUMB2_KERNEL)$(CONFIG_CC_IS_CLANG),yy)
# The use of R7 in the SMCCC conflicts with the compiler's use of R7 as a frame
# pointer in Thumb2 mode, which is forcibly enabled by Clang when profiling
# hooks are inserted via the -pg switch.
CFLAGS_REMOVE_smc.o += $(CC_FLAGS_FTRACE)
endif

View File

@ -286,9 +286,6 @@ int scmi_xfer_raw_inflight_register(const struct scmi_handle *handle,
int scmi_xfer_raw_wait_for_message_response(struct scmi_chan_info *cinfo,
struct scmi_xfer *xfer,
unsigned int timeout_ms);
#ifdef CONFIG_ARM_SCMI_TRANSPORT_SMC
extern const struct scmi_desc scmi_smc_desc;
#endif
#ifdef CONFIG_ARM_SCMI_TRANSPORT_VIRTIO
extern const struct scmi_desc scmi_virtio_desc;
#endif

View File

@ -3321,11 +3321,6 @@ static const struct of_device_id scmi_of_match[] = {
#ifdef CONFIG_ARM_SCMI_TRANSPORT_OPTEE
{ .compatible = "linaro,scmi-optee", .data = &scmi_optee_desc },
#endif
#ifdef CONFIG_ARM_SCMI_TRANSPORT_SMC
{ .compatible = "arm,scmi-smc", .data = &scmi_smc_desc},
{ .compatible = "arm,scmi-smc-param", .data = &scmi_smc_desc},
{ .compatible = "qcom,scmi-smc", .data = &scmi_smc_desc},
#endif
#ifdef CONFIG_ARM_SCMI_TRANSPORT_VIRTIO
{ .compatible = "arm,scmi-virtio", .data = &scmi_virtio_desc},
#endif

View File

@ -34,4 +34,32 @@ config ARM_SCMI_TRANSPORT_MAILBOX
This driver can also be built as a module. If so, the module
will be called scmi_transport_mailbox.
config ARM_SCMI_TRANSPORT_SMC
tristate "SCMI transport based on SMC"
depends on HAVE_ARM_SMCCC_DISCOVERY
select ARM_SCMI_HAVE_TRANSPORT
select ARM_SCMI_HAVE_SHMEM
default y
help
Enable SMC based transport for SCMI.
If you want the ARM SCMI PROTOCOL stack to include support for a
transport based on SMC, answer Y.
This driver can also be built as a module. If so, the module
will be called scmi_transport_smc.
config ARM_SCMI_TRANSPORT_SMC_ATOMIC_ENABLE
bool "Enable atomic mode support for SCMI SMC transport"
depends on ARM_SCMI_TRANSPORT_SMC
help
Enable support of atomic operation for SCMI SMC based transport.
If you want the SCMI SMC based transport to operate in atomic
mode, avoiding any kind of sleeping behaviour for selected
transactions on the TX path, answer Y.
Enabling atomic mode operations allows any SCMI driver using this
transport to optionally ask for atomic SCMI transactions and operate
in atomic context too, at the price of using a number of busy-waiting
primitives all over instead. If unsure say N.
endmenu

View File

@ -1,4 +1,12 @@
# SPDX-License-Identifier: GPL-2.0-only
scmi_transport_mailbox-objs := mailbox.o
obj-$(CONFIG_ARM_SCMI_TRANSPORT_MAILBOX) += scmi_transport_mailbox.o
scmi_transport_smc-objs := smc.o
obj-$(CONFIG_ARM_SCMI_TRANSPORT_SMC) += scmi_transport_smc.o
ifeq ($(CONFIG_THUMB2_KERNEL)$(CONFIG_CC_IS_CLANG),yy)
# The use of R7 in the SMCCC conflicts with the compiler's use of R7 as a frame
# pointer in Thumb2 mode, which is forcibly enabled by Clang when profiling
# hooks are inserted via the -pg switch.
CFLAGS_REMOVE_smc.o += $(CC_FLAGS_FTRACE)
endif

View File

@ -16,10 +16,11 @@
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/limits.h>
#include <linux/platform_device.h>
#include <linux/processor.h>
#include <linux/slab.h>
#include "common.h"
#include "../common.h"
/*
* The shmem address is split into 4K page and offset.
@ -69,12 +70,14 @@ struct scmi_smc {
unsigned long cap_id;
};
static struct scmi_transport_core_operations *core;
static irqreturn_t smc_msg_done_isr(int irq, void *data)
{
struct scmi_smc *scmi_info = data;
scmi_rx_callback(scmi_info->cinfo,
scmi_shmem_ops.read_header(scmi_info->shmem), NULL);
core->rx_callback(scmi_info->cinfo,
core->shmem->read_header(scmi_info->shmem), NULL);
return IRQ_HANDLED;
}
@ -141,7 +144,7 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
if (!scmi_info)
return -ENOMEM;
scmi_info->shmem = scmi_shmem_ops.setup_iomap(cinfo, dev, tx, &res);
scmi_info->shmem = core->shmem->setup_iomap(cinfo, dev, tx, &res);
if (IS_ERR(scmi_info->shmem))
return PTR_ERR(scmi_info->shmem);
@ -226,7 +229,7 @@ static int smc_send_message(struct scmi_chan_info *cinfo,
*/
smc_channel_lock_acquire(scmi_info, xfer);
scmi_shmem_ops.tx_prepare(scmi_info->shmem, xfer, cinfo);
core->shmem->tx_prepare(scmi_info->shmem, xfer, cinfo);
if (scmi_info->cap_id != ULONG_MAX)
arm_smccc_1_1_invoke(scmi_info->func_id, scmi_info->cap_id, 0,
@ -250,7 +253,7 @@ static void smc_fetch_response(struct scmi_chan_info *cinfo,
{
struct scmi_smc *scmi_info = cinfo->transport_info;
scmi_shmem_ops.fetch_response(scmi_info->shmem, xfer);
core->shmem->fetch_response(scmi_info->shmem, xfer);
}
static void smc_mark_txdone(struct scmi_chan_info *cinfo, int ret,
@ -270,7 +273,7 @@ static const struct scmi_transport_ops scmi_smc_ops = {
.fetch_response = smc_fetch_response,
};
const struct scmi_desc scmi_smc_desc = {
static const struct scmi_desc scmi_smc_desc = {
.ops = &scmi_smc_ops,
.max_rx_timeout_ms = 30,
.max_msg = 20,
@ -286,3 +289,19 @@ const struct scmi_desc scmi_smc_desc = {
.sync_cmds_completed_on_ret = true,
.atomic_enabled = IS_ENABLED(CONFIG_ARM_SCMI_TRANSPORT_SMC_ATOMIC_ENABLE),
};
static const struct of_device_id scmi_of_match[] = {
{ .compatible = "arm,scmi-smc" },
{ .compatible = "arm,scmi-smc-param" },
{ .compatible = "qcom,scmi-smc" },
{ /* Sentinel */ },
};
DEFINE_SCMI_TRANSPORT_DRIVER(scmi_smc, scmi_smc_driver, scmi_smc_desc,
scmi_of_match, core);
module_platform_driver(scmi_smc_driver);
MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
MODULE_AUTHOR("Nikunj Kela <quic_nkela@quicinc.com>");
MODULE_DESCRIPTION("SCMI SMC Transport driver");
MODULE_LICENSE("GPL");