From: Cristian Marussi <cristian.marussi@arm.com>
To: "Peng Fan (OSS)" <peng.fan@oss.nxp.com>
Cc: Sudeep Holla <sudeep.holla@arm.com>,
Cristian Marussi <cristian.marussi@arm.com>,
Shawn Guo <shawnguo@kernel.org>,
Sascha Hauer <s.hauer@pengutronix.de>,
Pengutronix Kernel Team <kernel@pengutronix.de>,
Fabio Estevam <festevam@gmail.com>, Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Dan Carpenter <dan.carpenter@linaro.org>,
linux-kernel@vger.kernel.org, arm-scmi@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, imx@lists.linux.dev,
devicetree@vger.kernel.org, Peng Fan <peng.fan@nxp.com>
Subject: Re: [PATCH v2 3/7] firmware: arm_scmi: imx: Add i.MX95 LMM protocol
Date: Mon, 24 Feb 2025 15:54:19 +0000 [thread overview]
Message-ID: <Z7yWK3E5inW39jeJ@pluto> (raw)
In-Reply-To: <20250212-imx-lmm-cpu-v2-3-3aee005968c1@nxp.com>
On Wed, Feb 12, 2025 at 03:40:25PM +0800, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
>
> Add Logical Machine Management(LMM) protocol which is intended for boot,
> shutdown, and reset of other logical machines (LM). It is usually used to
> allow one LM to manager another used as an offload or accelerator engine.
>
Hi,
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
> drivers/firmware/arm_scmi/vendors/imx/Kconfig | 11 +
> drivers/firmware/arm_scmi/vendors/imx/Makefile | 1 +
> drivers/firmware/arm_scmi/vendors/imx/imx-sm-lmm.c | 270 +++++++++++++++++++++
> include/linux/scmi_imx_protocol.h | 31 +++
> 4 files changed, 313 insertions(+)
>
> diff --git a/drivers/firmware/arm_scmi/vendors/imx/Kconfig b/drivers/firmware/arm_scmi/vendors/imx/Kconfig
> index a01bf5e47301d2f93c9bfc7eebc77e083ea4ed75..1a936fc87d2350e2a21bccd45dfbeebfa3b90286 100644
> --- a/drivers/firmware/arm_scmi/vendors/imx/Kconfig
> +++ b/drivers/firmware/arm_scmi/vendors/imx/Kconfig
> @@ -12,6 +12,17 @@ config IMX_SCMI_BBM_EXT
> To compile this driver as a module, choose M here: the
> module will be called imx-sm-bbm.
>
> +config IMX_SCMI_LMM_EXT
> + tristate "i.MX SCMI LMM EXTENSION"
> + depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
> + default y if ARCH_MXC
> + help
> + This enables i.MX System Logical Machine Protocol to
> + manage Logical Machines boot, shutdown and etc.
> +
> + To compile this driver as a module, choose M here: the
> + module will be called imx-sm-lmm.
> +
> config IMX_SCMI_MISC_EXT
> tristate "i.MX SCMI MISC EXTENSION"
> depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
> diff --git a/drivers/firmware/arm_scmi/vendors/imx/Makefile b/drivers/firmware/arm_scmi/vendors/imx/Makefile
> index d3ee6d5449244a4f5cdf6abcf1845f312c512325..f39a99ccaf9af757475e8b112d224669444d7ddc 100644
> --- a/drivers/firmware/arm_scmi/vendors/imx/Makefile
> +++ b/drivers/firmware/arm_scmi/vendors/imx/Makefile
> @@ -1,3 +1,4 @@
> # SPDX-License-Identifier: GPL-2.0-only
> obj-$(CONFIG_IMX_SCMI_BBM_EXT) += imx-sm-bbm.o
> +obj-$(CONFIG_IMX_SCMI_LMM_EXT) += imx-sm-lmm.o
> obj-$(CONFIG_IMX_SCMI_MISC_EXT) += imx-sm-misc.o
> diff --git a/drivers/firmware/arm_scmi/vendors/imx/imx-sm-lmm.c b/drivers/firmware/arm_scmi/vendors/imx/imx-sm-lmm.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..4b9211df2329623fae0400039db91cb2b98cded1
> --- /dev/null
> +++ b/drivers/firmware/arm_scmi/vendors/imx/imx-sm-lmm.c
> @@ -0,0 +1,270 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * System control and Management Interface (SCMI) NXP LMM Protocol
> + *
> + * Copyright 2025 NXP
> + */
> +
> +#include <linux/bits.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/scmi_protocol.h>
> +#include <linux/scmi_imx_protocol.h>
> +
> +#include "../../protocols.h"
> +#include "../../notify.h"
> +
> +#define SCMI_PROTOCOL_SUPPORTED_VERSION 0x10000
> +
> +enum scmi_imx_lmm_protocol_cmd {
> + SCMI_IMX_LMM_ATTRIBUTES = 0x3,
> + SCMI_IMX_LMM_BOOT = 0x4,
> + SCMI_IMX_LMM_RESET = 0x5,
> + SCMI_IMX_LMM_SHUTDOWN = 0x6,
> + SCMI_IMX_LMM_WAKE = 0x7,
> + SCMI_IMX_LMM_SUSPEND = 0x8,
> + SCMI_IMX_LMM_NOTIFY = 0x9,
> + SCMI_IMX_LMM_RESET_REASON = 0xA,
> + SCMI_IMX_LMM_POWER_ON = 0xB,
> + SCMI_IMX_LMM_RESET_VECTOR_SET = 0xC,
> +};
> +
> +struct scmi_imx_lmm_priv {
> + u32 nr_lmm;
> +};
> +
> +#define SCMI_IMX_LMM_PROTO_ATTR_NUM_LM(x) (((x) & 0xFFU))
> +struct scmi_msg_imx_lmm_protocol_attributes {
> + __le32 attributes;
> +};
> +
> +struct scmi_msg_imx_lmm_attributes_out {
> + __le32 lmid;
> + __le32 attributes;
> + __le32 state;
> + __le32 errstatus;
> + u8 name[LMM_MAX_NAME];
> +};
> +
> +struct scmi_imx_lmm_reset_vector_set_in {
> + __le32 lmid;
> + __le32 cpuid;
> +#define SCMI_LMM_VEC_FLAGS_TABLE BIT(0)
> + __le32 flags;
> + __le32 resetvectorlow;
> + __le32 resetvectorhigh;
> +};
> +
> +struct scmi_imx_lmm_shutdown_in {
> + __le32 lmid;
> + __le32 flags;
> +};
> +
> +static int scmi_imx_lmm_validate_lmid(const struct scmi_protocol_handle *ph, u32 lmid)
> +{
> + struct scmi_imx_lmm_priv *priv = ph->get_priv(ph);
> +
> + if (lmid >= priv->nr_lmm)
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> +static int scmi_imx_lmm_attributes(const struct scmi_protocol_handle *ph,
> + u32 lmid, struct scmi_imx_lmm_info *info)
> +{
> + struct scmi_msg_imx_lmm_attributes_out *out;
> + struct scmi_xfer *t;
> + int ret;
> +
> + ret = ph->xops->xfer_get_init(ph, SCMI_IMX_LMM_ATTRIBUTES, sizeof(u32), 0, &t);
> + if (ret)
> + return ret;
> +
> + put_unaligned_le32(lmid, t->tx.buf);
> + ret = ph->xops->do_xfer(ph, t);
> + if (!ret) {
> + out = t->rx.buf;
> + info->lmid = le32_to_cpu(out->lmid);
> + info->state = le32_to_cpu(out->state);
> + info->errstatus = le32_to_cpu(out->errstatus);
> + strscpy(info->name, out->name);
> + dev_dbg(ph->dev, "i.MX LMM: Logical Machine(%d), name: %s\n",
> + info->lmid, out->name);
> + } else {
> + dev_err(ph->dev, "i.MX LMM: Failed to get info of Logical Machine(%u)\n", lmid);
> + }
> +
> + ph->xops->xfer_put(ph, t);
> +
> + return ret;
> +}
> +
> +static int scmi_imx_lmm_boot(const struct scmi_protocol_handle *ph, u32 lmid)
> +{
> + struct scmi_xfer *t;
> + int ret;
> +
> + ret = scmi_imx_lmm_validate_lmid(ph, lmid);
> + if (ret)
> + return ret;
> +
> + ret = ph->xops->xfer_get_init(ph, SCMI_IMX_LMM_BOOT, sizeof(u32),
> + 0, &t);
> + if (ret)
> + return ret;
> +
> + put_unaligned_le32(lmid, t->tx.buf);
> + ret = ph->xops->do_xfer(ph, t);
> +
> + ph->xops->xfer_put(ph, t);
> +
> + return ret;
> +}
> +
..this....
> +static int scmi_imx_lmm_power_on(const struct scmi_protocol_handle *ph, u32 lmid)
> +{
> + struct scmi_xfer *t;
> + int ret;
> +
> + ret = scmi_imx_lmm_validate_lmid(ph, lmid);
> + if (ret)
> + return ret;
> +
> + ret = ph->xops->xfer_get_init(ph, SCMI_IMX_LMM_POWER_ON, sizeof(u32),
> + 0, &t);
> + if (ret)
> + return ret;
> +
> + put_unaligned_le32(lmid, t->tx.buf);
> + ret = ph->xops->do_xfer(ph, t);
> +
> + ph->xops->xfer_put(ph, t);
> +
> + return ret;
> +}
...can be refatcored to use one common workhorse fcuntion sued by both
ops...
> +
> +static int scmi_imx_lmm_reset_vector_set(const struct scmi_protocol_handle *ph,
> + u32 lmid, u32 cpuid, u32 flags, u64 vector)
> +{
> + struct scmi_imx_lmm_reset_vector_set_in *in;
> + struct scmi_xfer *t;
> + int ret;
> +
> + ret = ph->xops->xfer_get_init(ph, SCMI_IMX_LMM_RESET_VECTOR_SET, sizeof(*in),
> + 0, &t);
> + if (ret)
> + return ret;
> +
> + in = t->tx.buf;
> + in->lmid = cpu_to_le32(lmid);
> + in->cpuid = cpu_to_le32(cpuid);
> + in->flags = cpu_to_le32(flags);
...bitfields in a flag field must not be enianity converted...only
eventually subfields representing numbers (liek you did above)...
..I feel FIELD_PREP should be fine...or even BIT(0) really given what
these flags represents...
...again check issues with smatch....
> + in->resetvectorlow = cpu_to_le32(lower_32_bits(vector));
> + in->resetvectorhigh = cpu_to_le32(upper_32_bits(vector));
> + ret = ph->xops->do_xfer(ph, t);
> +
> + ph->xops->xfer_put(ph, t);
> +
> + return ret;
> +}
> +
> +static int scmi_imx_lmm_shutdown(const struct scmi_protocol_handle *ph, u32 lmid,
> + u32 flags)
> +{
> + struct scmi_imx_lmm_shutdown_in *in;
> + struct scmi_xfer *t;
> + int ret;
> +
> + ret = scmi_imx_lmm_validate_lmid(ph, lmid);
> + if (ret)
> + return ret;
> +
> + ret = ph->xops->xfer_get_init(ph, SCMI_IMX_LMM_SHUTDOWN, sizeof(*in),
> + 0, &t);
> + if (ret)
> + return ret;
> +
> + in = t->tx.buf;
> + in->lmid = cpu_to_le32(lmid);
> + in->flags = cpu_to_le32(flags);
Same here, smatch would complain if you remove straight away this
cpu_to_le32(), BUT this is a bitfield and does NOT contain any
longer-than-2 number value that needs to be endianess manipulated...you
just have to be able to set the required BIT 0 and 1, whitouth pissing
off smatch :P
> + ret = ph->xops->do_xfer(ph, t);
> +
> + ph->xops->xfer_put(ph, t);
> +
> + return ret;
> +}
> +
> +static const struct scmi_imx_lmm_proto_ops scmi_imx_lmm_proto_ops = {
> + .lmm_boot = scmi_imx_lmm_boot,
> + .lmm_info = scmi_imx_lmm_attributes,
> + .lmm_power_on = scmi_imx_lmm_power_on,
> + .lmm_reset_vector_set = scmi_imx_lmm_reset_vector_set,
> + .lmm_shutdown = scmi_imx_lmm_shutdown,
> +};
> +
> +static int scmi_imx_lmm_protocol_attributes_get(const struct scmi_protocol_handle *ph,
> + struct scmi_imx_lmm_priv *priv)
> +{
> + struct scmi_msg_imx_lmm_protocol_attributes *attr;
> + struct scmi_xfer *t;
> + int ret;
> +
> + ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, 0,
> + sizeof(*attr), &t);
> + if (ret)
> + return ret;
> +
> + attr = t->rx.buf;
> +
> + ret = ph->xops->do_xfer(ph, t);
> + if (!ret) {
> + priv->nr_lmm = SCMI_IMX_LMM_PROTO_ATTR_NUM_LM(le32_to_cpu(attr->attributes));
This seems wrong to me...you have an 8bit field to extract from an
attribute field...so I would at first cut the byte out and then convert
to LE, NOT the other way around like you are doing
(i.e.: le32_to_cpu((attr->attributes & 0xFF))).
Even BETTER to use:
le32_get_bits((x), GENMASK(7, 0))
...the thing is, being a single byte you really SHOULD NOT need to address
any endianity concern (i.e. FIELD_GET(GENMASK(7, 0), (x))), BUT I fear that
if you dont use some of the le32_ accessors smatch/sparse will complain since
the message field is, correctly, declared as __le32.
So le32_get_bits is the way to go (bit check with the static analyzer :P)
> + dev_info(ph->dev, "i.MX LMM: %d Logical Machines\n",
> + priv->nr_lmm);
> + }
> +
> + ph->xops->xfer_put(ph, t);
> +
> + return ret;
> +}
> +
> +static int scmi_imx_lmm_protocol_init(const struct scmi_protocol_handle *ph)
> +{
> + struct scmi_imx_lmm_priv *info;
> + u32 version;
> + int ret;
> +
> + ret = ph->xops->version_get(ph, &version);
> + if (ret)
> + return ret;
> +
> + dev_info(ph->dev, "NXP SM LMM Version %d.%d\n",
> + PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
> +
> + info = devm_kzalloc(ph->dev, sizeof(*info), GFP_KERNEL);
> + if (!info)
> + return -ENOMEM;
> +
> + ret = scmi_imx_lmm_protocol_attributes_get(ph, info);
> + if (ret)
> + return ret;
> +
> + return ph->set_priv(ph, info, version);
> +}
> +
> +static const struct scmi_protocol scmi_imx_lmm = {
> + .id = SCMI_PROTOCOL_IMX_LMM,
> + .owner = THIS_MODULE,
> + .instance_init = &scmi_imx_lmm_protocol_init,
> + .ops = &scmi_imx_lmm_proto_ops,
> + .supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION,
> + .vendor_id = SCMI_IMX_VENDOR,
> + .sub_vendor_id = SCMI_IMX_SUBVENDOR,
> +};
> +module_scmi_protocol(scmi_imx_lmm);
> +
Should this also be added:
MODULE_ALIAS("scmi-protocol-" __stringify(SCMI_PROTOCOL_IMX_LMM) "-" SCMI_IMX_VENDOR);
...after this went in:
commit d4cc8912cbff4990940b33cc61a9b09ddaee9704
Author: Cristian Marussi <cristian.marussi@arm.com>
Date: Mon Dec 9 16:49:56 2024 +0000
firmware: arm_scmi: Add module aliases to i.MX vendor protocol
...I think is in v6.14-rc already to rebae on...
> +MODULE_DESCRIPTION("i.MX SCMI LMM driver");
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/scmi_imx_protocol.h b/include/linux/scmi_imx_protocol.h
> index 53b356a26414279f4aaaa8287c32209ed1ad57b4..07779c36ef9a126907e26e304a8feca16fd60ab2 100644
> --- a/include/linux/scmi_imx_protocol.h
> +++ b/include/linux/scmi_imx_protocol.h
> @@ -11,8 +11,10 @@
> #include <linux/bitfield.h>
> #include <linux/device.h>
> #include <linux/notifier.h>
> +#include <linux/scmi_protocol.h>
> #include <linux/types.h>
>
> +#define SCMI_PROTOCOL_IMX_LMM 0x80
> #define SCMI_PROTOCOL_IMX_BBM 0x81
> #define SCMI_PROTOCOL_IMX_MISC 0x84
>
> @@ -57,4 +59,33 @@ struct scmi_imx_misc_proto_ops {
> int (*misc_ctrl_req_notify)(const struct scmi_protocol_handle *ph,
> u32 ctrl_id, u32 evt_id, u32 flags);
> };
> +
> +#define LMM_ID_DISCOVER 0xFFFFFFFFU
What is this ? Documented anywhere ?
> +#define LMM_MAX_NAME 16
> +
> +enum scmi_imx_lmm_state {
> + LMM_STATE_LM_OFF,
> + LMM_STATE_LM_ON,
> + LMM_STATE_LM_SUSPEND,
> + LMM_STATE_LM_POWERED,
> +};
> +
> +struct scmi_imx_lmm_info {
> + u32 lmid;
> + enum scmi_imx_lmm_state state;
> + u32 errstatus;
> + u8 name[LMM_MAX_NAME];
> +};
> +
> +struct scmi_imx_lmm_proto_ops {
> + int (*lmm_boot)(const struct scmi_protocol_handle *ph, u32 lmid);
> + int (*lmm_info)(const struct scmi_protocol_handle *ph, u32 lmid,
> + struct scmi_imx_lmm_info *info);
> + int (*lmm_power_on)(const struct scmi_protocol_handle *ph, u32 lmid);
> + int (*lmm_reset_vector_set)(const struct scmi_protocol_handle *ph,
> + u32 lmid, u32 cpuid, u32 flags, u64 vector);
> + int (*lmm_shutdown)(const struct scmi_protocol_handle *ph, u32 lmid,
> + u32 flags);
> +};
> +
> #endif
>
Thanks,
Cristian
next prev parent reply other threads:[~2025-02-24 15:54 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-12 7:40 [PATCH v2 0/7] firmware: scmi/imx: Add i.MX95 LMM/CPU Protocol Peng Fan (OSS)
2025-02-12 7:40 ` [PATCH v2 1/7] firmware: arm_scmi: imx: Add LMM and CPU documentation Peng Fan (OSS)
2025-02-24 12:28 ` Cristian Marussi
2025-02-25 9:07 ` Peng Fan
2025-02-25 11:54 ` Cristian Marussi
2025-02-12 7:40 ` [PATCH v2 2/7] dt-bindings: firmware: Add i.MX95 SCMI LMM and CPU protocol Peng Fan (OSS)
2025-02-19 21:46 ` Rob Herring
2025-02-24 3:01 ` Peng Fan
2025-02-12 7:40 ` [PATCH v2 3/7] firmware: arm_scmi: imx: Add i.MX95 LMM protocol Peng Fan (OSS)
2025-02-24 15:54 ` Cristian Marussi [this message]
2025-02-25 9:25 ` Peng Fan
2025-02-12 7:40 ` [PATCH v2 4/7] firmware: arm_scmi: imx: Add i.MX95 CPU Protocol Peng Fan (OSS)
2025-02-24 18:10 ` Cristian Marussi
2025-02-25 9:29 ` Peng Fan
2025-02-12 7:40 ` [PATCH v2 5/7] firmware: imx: Add i.MX95 SCMI LMM driver Peng Fan (OSS)
2025-02-25 11:25 ` Cristian Marussi
2025-02-12 7:40 ` [PATCH v2 6/7] firmware: imx: Add i.MX95 SCMI CPU driver Peng Fan (OSS)
2025-02-25 11:28 ` Cristian Marussi
2025-02-12 7:40 ` [PATCH v2 7/7] MAINTAINERS: add entry for i.MX SCMI extensions Peng Fan (OSS)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Z7yWK3E5inW39jeJ@pluto \
--to=cristian.marussi@arm.com \
--cc=arm-scmi@vger.kernel.org \
--cc=conor+dt@kernel.org \
--cc=dan.carpenter@linaro.org \
--cc=devicetree@vger.kernel.org \
--cc=festevam@gmail.com \
--cc=imx@lists.linux.dev \
--cc=kernel@pengutronix.de \
--cc=krzk+dt@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=peng.fan@nxp.com \
--cc=peng.fan@oss.nxp.com \
--cc=robh@kernel.org \
--cc=s.hauer@pengutronix.de \
--cc=shawnguo@kernel.org \
--cc=sudeep.holla@arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.