Skip to content

Commit

Permalink
Merge tag 'scmi-updates-6.14' of https://git.kernel.org/pub/scm/linux…
Browse files Browse the repository at this point in the history
…/kernel/git/sudeep.holla/linux into soc/drivers

Arm SCMI updates for 6.14

This mainly has 2 updates:
1. Extension of the transport properties read from devicetree to support
   multiple SCMI platform/server instances
2. Addition of the capability to automatically load the proper SCMI vendor
   protocol module. The vendor protocol selection is already provided by
   the SCMI core while the automatic loading of vendor protocols was not.

* tag 'scmi-updates-6.14' of https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux:
  firmware: arm_scmi: Add aliases to transport modules
  firmware: arm_scmi: Add module aliases to i.MX vendor protocols
  firmware: arm_scmi: Support vendor protocol modules autoloading
  firmware: arm_scmi: Allow transport properties for multiple instances

Link: https://lore.kernel.org/r/20250102154024.2168165-1-sudeep.holla@arm.com
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
  • Loading branch information
Arnd Bergmann committed Jan 15, 2025
2 parents 8de2819 + 3f3f0e5 commit 14ade5a
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 29 deletions.
4 changes: 2 additions & 2 deletions drivers/firmware/arm_scmi/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ struct scmi_transport_core_operations {
*/
struct scmi_transport {
struct device *supplier;
struct scmi_desc *desc;
struct scmi_desc desc;
struct scmi_transport_core_operations **core_ops;
};

Expand All @@ -468,7 +468,7 @@ static int __tag##_probe(struct platform_device *pdev) \
device_set_of_node_from_dev(&spdev->dev, dev); \
\
strans.supplier = dev; \
strans.desc = &(__desc); \
memcpy(&strans.desc, &(__desc), sizeof(strans.desc)); \
strans.core_ops = &(__core_ops); \
\
ret = platform_device_add_data(spdev, &strans, sizeof(strans)); \
Expand Down
74 changes: 55 additions & 19 deletions drivers/firmware/arm_scmi/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <linux/io.h>
#include <linux/io-64-nonatomic-hi-lo.h>
#include <linux/kernel.h>
#include <linux/kmod.h>
#include <linux/ktime.h>
#include <linux/hashtable.h>
#include <linux/list.h>
Expand All @@ -43,6 +44,8 @@
#define CREATE_TRACE_POINTS
#include <trace/events/scmi.h>

#define SCMI_VENDOR_MODULE_ALIAS_FMT "scmi-protocol-0x%02x-%s"

static DEFINE_IDA(scmi_id);

static DEFINE_XARRAY(scmi_protocols);
Expand Down Expand Up @@ -275,6 +278,44 @@ scmi_vendor_protocol_lookup(int protocol_id, char *vendor_id,
return proto;
}

static const struct scmi_protocol *
scmi_vendor_protocol_get(int protocol_id, struct scmi_revision_info *version)
{
const struct scmi_protocol *proto;

proto = scmi_vendor_protocol_lookup(protocol_id, version->vendor_id,
version->sub_vendor_id,
version->impl_ver);
if (!proto) {
int ret;

pr_debug("Looking for '" SCMI_VENDOR_MODULE_ALIAS_FMT "'\n",
protocol_id, version->vendor_id);

/* Note that vendor_id is mandatory for vendor protocols */
ret = request_module(SCMI_VENDOR_MODULE_ALIAS_FMT,
protocol_id, version->vendor_id);
if (ret) {
pr_warn("Problem loading module for protocol 0x%x\n",
protocol_id);
return NULL;
}

/* Lookup again, once modules loaded */
proto = scmi_vendor_protocol_lookup(protocol_id,
version->vendor_id,
version->sub_vendor_id,
version->impl_ver);
}

if (proto)
pr_info("Loaded SCMI Vendor Protocol 0x%x - %s %s %X\n",
protocol_id, proto->vendor_id ?: "",
proto->sub_vendor_id ?: "", proto->impl_ver);

return proto;
}

static const struct scmi_protocol *
scmi_protocol_get(int protocol_id, struct scmi_revision_info *version)
{
Expand All @@ -283,22 +324,15 @@ scmi_protocol_get(int protocol_id, struct scmi_revision_info *version)
if (protocol_id < SCMI_PROTOCOL_VENDOR_BASE)
proto = xa_load(&scmi_protocols, protocol_id);
else
proto = scmi_vendor_protocol_lookup(protocol_id,
version->vendor_id,
version->sub_vendor_id,
version->impl_ver);
proto = scmi_vendor_protocol_get(protocol_id, version);

if (!proto || !try_module_get(proto->owner)) {
pr_warn("SCMI Protocol 0x%x not found!\n", protocol_id);
return NULL;
}

pr_debug("Found SCMI Protocol 0x%x\n", protocol_id);

if (protocol_id >= SCMI_PROTOCOL_VENDOR_BASE)
pr_info("Loaded SCMI Vendor Protocol 0x%x - %s %s %X\n",
protocol_id, proto->vendor_id ?: "",
proto->sub_vendor_id ?: "", proto->impl_ver);

return proto;
}

Expand Down Expand Up @@ -366,7 +400,9 @@ int scmi_protocol_register(const struct scmi_protocol *proto)
return ret;
}

pr_debug("Registered SCMI Protocol 0x%x\n", proto->id);
pr_debug("Registered SCMI Protocol 0x%x - %s %s 0x%08X\n",
proto->id, proto->vendor_id, proto->sub_vendor_id,
proto->impl_ver);

return 0;
}
Expand Down Expand Up @@ -3028,7 +3064,7 @@ static const struct scmi_desc *scmi_transport_setup(struct device *dev)
int ret;

trans = dev_get_platdata(dev);
if (!trans || !trans->desc || !trans->supplier || !trans->core_ops)
if (!trans || !trans->supplier || !trans->core_ops)
return NULL;

if (!device_link_add(dev, trans->supplier, DL_FLAG_AUTOREMOVE_CONSUMER)) {
Expand All @@ -3043,33 +3079,33 @@ static const struct scmi_desc *scmi_transport_setup(struct device *dev)
dev_info(dev, "Using %s\n", dev_driver_string(trans->supplier));

ret = of_property_read_u32(dev->of_node, "arm,max-rx-timeout-ms",
&trans->desc->max_rx_timeout_ms);
&trans->desc.max_rx_timeout_ms);
if (ret && ret != -EINVAL)
dev_err(dev, "Malformed arm,max-rx-timeout-ms DT property.\n");

ret = of_property_read_u32(dev->of_node, "arm,max-msg-size",
&trans->desc->max_msg_size);
&trans->desc.max_msg_size);
if (ret && ret != -EINVAL)
dev_err(dev, "Malformed arm,max-msg-size DT property.\n");

ret = of_property_read_u32(dev->of_node, "arm,max-msg",
&trans->desc->max_msg);
&trans->desc.max_msg);
if (ret && ret != -EINVAL)
dev_err(dev, "Malformed arm,max-msg DT property.\n");

dev_info(dev,
"SCMI max-rx-timeout: %dms / max-msg-size: %dbytes / max-msg: %d\n",
trans->desc->max_rx_timeout_ms, trans->desc->max_msg_size,
trans->desc->max_msg);
trans->desc.max_rx_timeout_ms, trans->desc.max_msg_size,
trans->desc.max_msg);

/* System wide atomic threshold for atomic ops .. if any */
if (!of_property_read_u32(dev->of_node, "atomic-threshold-us",
&trans->desc->atomic_threshold))
&trans->desc.atomic_threshold))
dev_info(dev,
"SCMI System wide atomic threshold set to %u us\n",
trans->desc->atomic_threshold);
trans->desc.atomic_threshold);

return trans->desc;
return &trans->desc;
}

static int scmi_probe(struct platform_device *pdev)
Expand Down
1 change: 1 addition & 0 deletions drivers/firmware/arm_scmi/transports/mailbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,7 @@ static const struct of_device_id scmi_of_match[] = {
{ .compatible = "arm,scmi" },
{ /* Sentinel */ },
};
MODULE_DEVICE_TABLE(of, scmi_of_match);

DEFINE_SCMI_TRANSPORT_DRIVER(scmi_mailbox, scmi_mailbox_driver,
scmi_mailbox_desc, scmi_of_match, core);
Expand Down
1 change: 1 addition & 0 deletions drivers/firmware/arm_scmi/transports/smc.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ static const struct of_device_id scmi_of_match[] = {
{ .compatible = "qcom,scmi-smc" },
{ /* Sentinel */ },
};
MODULE_DEVICE_TABLE(of, scmi_of_match);

DEFINE_SCMI_TRANSPORT_DRIVER(scmi_smc, scmi_smc_driver, scmi_smc_desc,
scmi_of_match, core);
Expand Down
1 change: 1 addition & 0 deletions drivers/firmware/arm_scmi/transports/virtio.c
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,7 @@ static const struct virtio_device_id id_table[] = {
{ VIRTIO_ID_SCMI, VIRTIO_DEV_ANY_ID },
{ 0 }
};
MODULE_DEVICE_TABLE(virtio, id_table);

static struct virtio_driver virtio_scmi_driver = {
.driver.name = "scmi-virtio",
Expand Down
5 changes: 3 additions & 2 deletions drivers/firmware/arm_scmi/vendors/imx/imx-sm-bbm.c
Original file line number Diff line number Diff line change
Expand Up @@ -374,10 +374,11 @@ static const struct scmi_protocol scmi_imx_bbm = {
.ops = &scmi_imx_bbm_proto_ops,
.events = &scmi_imx_bbm_protocol_events,
.supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION,
.vendor_id = "NXP",
.sub_vendor_id = "IMX",
.vendor_id = SCMI_IMX_VENDOR,
.sub_vendor_id = SCMI_IMX_SUBVENDOR,
};
module_scmi_protocol(scmi_imx_bbm);

MODULE_ALIAS("scmi-protocol-" __stringify(SCMI_PROTOCOL_IMX_BBM) "-" SCMI_IMX_VENDOR);
MODULE_DESCRIPTION("i.MX SCMI BBM driver");
MODULE_LICENSE("GPL");
5 changes: 3 additions & 2 deletions drivers/firmware/arm_scmi/vendors/imx/imx-sm-misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,10 +309,11 @@ static const struct scmi_protocol scmi_imx_misc = {
.ops = &scmi_imx_misc_proto_ops,
.events = &scmi_imx_misc_protocol_events,
.supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION,
.vendor_id = "NXP",
.sub_vendor_id = "IMX",
.vendor_id = SCMI_IMX_VENDOR,
.sub_vendor_id = SCMI_IMX_SUBVENDOR,
};
module_scmi_protocol(scmi_imx_misc);

MODULE_ALIAS("scmi-protocol-" __stringify(SCMI_PROTOCOL_IMX_MISC) "-" SCMI_IMX_VENDOR);
MODULE_DESCRIPTION("i.MX SCMI MISC driver");
MODULE_LICENSE("GPL");
9 changes: 5 additions & 4 deletions include/linux/scmi_imx_protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@
#include <linux/notifier.h>
#include <linux/types.h>

enum scmi_nxp_protocol {
SCMI_PROTOCOL_IMX_BBM = 0x81,
SCMI_PROTOCOL_IMX_MISC = 0x84,
};
#define SCMI_PROTOCOL_IMX_BBM 0x81
#define SCMI_PROTOCOL_IMX_MISC 0x84

#define SCMI_IMX_VENDOR "NXP"
#define SCMI_IMX_SUBVENDOR "IMX"

struct scmi_imx_bbm_proto_ops {
int (*rtc_time_set)(const struct scmi_protocol_handle *ph, u32 id,
Expand Down

0 comments on commit 14ade5a

Please sign in to comment.