* [PATCH v2 01/12] scmi: refactor the code to hide a channel from devices
2023-07-26 8:37 [PATCH v2 00/12] firmware: scmi: add SCMI base protocol support AKASHI Takahiro
@ 2023-07-26 8:37 ` AKASHI Takahiro
2023-07-27 0:50 ` Simon Glass
2023-08-03 9:24 ` Etienne CARRIERE
2023-07-26 8:37 ` [PATCH v2 02/12] firmware: scmi: implement SCMI base protocol AKASHI Takahiro
` (10 subsequent siblings)
11 siblings, 2 replies; 40+ messages in thread
From: AKASHI Takahiro @ 2023-07-26 8:37 UTC (permalink / raw)
To: trini, sjg; +Cc: etienne.carriere, u-boot, AKASHI Takahiro
The commit 85dc58289238 ("firmware: scmi: prepare uclass to pass channel
reference") added an explicit parameter, channel, but it seems to make
the code complex.
Hiding this parameter will allow for adding a generic (protocol-agnostic)
helper function, i.e. for PROTOCOL_VERSION, in a later patch.
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
v2
* new patch
---
drivers/clk/clk_scmi.c | 27 ++-------
drivers/firmware/scmi/scmi_agent-uclass.c | 74 ++++++++++++++++++-----
drivers/power/regulator/scmi_regulator.c | 27 +++------
drivers/reset/reset-scmi.c | 19 +-----
include/scmi_agent.h | 15 +++--
5 files changed, 86 insertions(+), 76 deletions(-)
diff --git a/drivers/clk/clk_scmi.c b/drivers/clk/clk_scmi.c
index d172fed24c9d..34a49363a51a 100644
--- a/drivers/clk/clk_scmi.c
+++ b/drivers/clk/clk_scmi.c
@@ -13,17 +13,8 @@
#include <asm/types.h>
#include <linux/clk-provider.h>
-/**
- * struct scmi_clk_priv - Private data for SCMI clocks
- * @channel: Reference to the SCMI channel to use
- */
-struct scmi_clk_priv {
- struct scmi_channel *channel;
-};
-
static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks)
{
- struct scmi_clk_priv *priv = dev_get_priv(dev);
struct scmi_clk_protocol_attr_out out;
struct scmi_msg msg = {
.protocol_id = SCMI_PROTOCOL_ID_CLOCK,
@@ -33,7 +24,7 @@ static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks)
};
int ret;
- ret = devm_scmi_process_msg(dev, priv->channel, &msg);
+ ret = devm_scmi_process_msg(dev, &msg);
if (ret)
return ret;
@@ -44,7 +35,6 @@ static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks)
static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name)
{
- struct scmi_clk_priv *priv = dev_get_priv(dev);
struct scmi_clk_attribute_in in = {
.clock_id = clkid,
};
@@ -59,7 +49,7 @@ static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name)
};
int ret;
- ret = devm_scmi_process_msg(dev, priv->channel, &msg);
+ ret = devm_scmi_process_msg(dev, &msg);
if (ret)
return ret;
@@ -70,7 +60,6 @@ static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name)
static int scmi_clk_gate(struct clk *clk, int enable)
{
- struct scmi_clk_priv *priv = dev_get_priv(clk->dev);
struct scmi_clk_state_in in = {
.clock_id = clk->id,
.attributes = enable,
@@ -81,7 +70,7 @@ static int scmi_clk_gate(struct clk *clk, int enable)
in, out);
int ret;
- ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg);
+ ret = devm_scmi_process_msg(clk->dev, &msg);
if (ret)
return ret;
@@ -100,7 +89,6 @@ static int scmi_clk_disable(struct clk *clk)
static ulong scmi_clk_get_rate(struct clk *clk)
{
- struct scmi_clk_priv *priv = dev_get_priv(clk->dev);
struct scmi_clk_rate_get_in in = {
.clock_id = clk->id,
};
@@ -110,7 +98,7 @@ static ulong scmi_clk_get_rate(struct clk *clk)
in, out);
int ret;
- ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg);
+ ret = devm_scmi_process_msg(clk->dev, &msg);
if (ret < 0)
return ret;
@@ -123,7 +111,6 @@ static ulong scmi_clk_get_rate(struct clk *clk)
static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
{
- struct scmi_clk_priv *priv = dev_get_priv(clk->dev);
struct scmi_clk_rate_set_in in = {
.clock_id = clk->id,
.flags = SCMI_CLK_RATE_ROUND_CLOSEST,
@@ -136,7 +123,7 @@ static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
in, out);
int ret;
- ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg);
+ ret = devm_scmi_process_msg(clk->dev, &msg);
if (ret < 0)
return ret;
@@ -149,12 +136,11 @@ static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
static int scmi_clk_probe(struct udevice *dev)
{
- struct scmi_clk_priv *priv = dev_get_priv(dev);
struct clk *clk;
size_t num_clocks, i;
int ret;
- ret = devm_scmi_of_get_channel(dev, &priv->channel);
+ ret = devm_scmi_of_get_channel(dev);
if (ret)
return ret;
@@ -205,5 +191,4 @@ U_BOOT_DRIVER(scmi_clock) = {
.id = UCLASS_CLK,
.ops = &scmi_clk_ops,
.probe = scmi_clk_probe,
- .priv_auto = sizeof(struct scmi_clk_priv *),
};
diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c
index 02de692d66f3..39cf15c88f75 100644
--- a/drivers/firmware/scmi/scmi_agent-uclass.c
+++ b/drivers/firmware/scmi/scmi_agent-uclass.c
@@ -8,6 +8,7 @@
#include <common.h>
#include <dm.h>
#include <errno.h>
+#include <scmi_agent.h>
#include <scmi_agent-uclass.h>
#include <scmi_protocols.h>
#include <dm/device_compat.h>
@@ -129,43 +130,88 @@ static const struct scmi_agent_ops *transport_dev_ops(struct udevice *dev)
return (const struct scmi_agent_ops *)dev->driver->ops;
}
-int devm_scmi_of_get_channel(struct udevice *dev, struct scmi_channel **channel)
+/**
+ * scmi_of_get_channel() - Get SCMI channel handle
+ *
+ * @dev: SCMI agent device
+ * @channel: Output reference to the SCMI channel upon success
+ *
+ * On return, @channel will be set.
+ * Return 0 on success and a negative errno on failure
+ */
+static int scmi_of_get_channel(struct udevice *dev, struct scmi_channel **channel)
+{
+ const struct scmi_agent_ops *ops;
+
+ ops = transport_dev_ops(dev);
+ if (ops->of_get_channel)
+ return ops->of_get_channel(dev, channel);
+ else
+ return -EPROTONOSUPPORT;
+}
+
+int devm_scmi_of_get_channel(struct udevice *dev)
{
struct udevice *parent;
+ struct scmi_agent_proto_priv *priv = dev_get_parent_priv(dev);
+ int ret;
parent = find_scmi_transport_device(dev);
if (!parent)
return -ENODEV;
- if (transport_dev_ops(parent)->of_get_channel)
- return transport_dev_ops(parent)->of_get_channel(parent, channel);
+ ret = scmi_of_get_channel(parent, &priv->channel);
+ if (ret == -EPROTONOSUPPORT) {
+ /* Drivers without a get_channel operator don't need a channel ref */
+ priv->channel = NULL;
- /* Drivers without a get_channel operator don't need a channel ref */
- *channel = NULL;
+ return 0;
+ }
- return 0;
+ return ret;
}
-int devm_scmi_process_msg(struct udevice *dev, struct scmi_channel *channel,
- struct scmi_msg *msg)
+/**
+ * scmi_process_msg() - Send and process an SCMI message
+ *
+ * Send a message to an SCMI server.
+ * Caller sets scmi_msg::out_msg_sz to the output message buffer size.
+ *
+ * @dev: SCMI agent device
+ * @channel: Communication channel for the device
+ * @msg: Message structure reference
+ *
+ * On return, scmi_msg::out_msg_sz stores the response payload size.
+ * Return: 0 on success and a negative errno on failure
+ */
+static int scmi_process_msg(struct udevice *dev, struct scmi_channel *channel,
+ struct scmi_msg *msg)
{
const struct scmi_agent_ops *ops;
+
+ ops = transport_dev_ops(dev);
+ if (ops->process_msg)
+ return ops->process_msg(dev, channel, msg);
+ else
+ return -EPROTONOSUPPORT;
+}
+
+int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg)
+{
struct udevice *parent;
+ struct scmi_agent_proto_priv *priv = dev_get_parent_priv(dev);
parent = find_scmi_transport_device(dev);
if (!parent)
return -ENODEV;
- ops = transport_dev_ops(parent);
-
- if (ops->process_msg)
- return ops->process_msg(parent, channel, msg);
-
- return -EPROTONOSUPPORT;
+ return scmi_process_msg(parent, priv->channel, msg);
}
UCLASS_DRIVER(scmi_agent) = {
.id = UCLASS_SCMI_AGENT,
.name = "scmi_agent",
.post_bind = scmi_bind_protocols,
+ .per_device_plat_auto = sizeof(struct scmi_agent_priv),
+ .per_child_auto = sizeof(struct scmi_agent_proto_priv *),
};
diff --git a/drivers/power/regulator/scmi_regulator.c b/drivers/power/regulator/scmi_regulator.c
index 801148036ff6..08918b20872c 100644
--- a/drivers/power/regulator/scmi_regulator.c
+++ b/drivers/power/regulator/scmi_regulator.c
@@ -25,18 +25,9 @@ struct scmi_regulator_platdata {
u32 domain_id;
};
-/**
- * struct scmi_regulator_priv - Private data for SCMI voltage regulator
- * @channel: Reference to the SCMI channel to use
- */
-struct scmi_regulator_priv {
- struct scmi_channel *channel;
-};
-
static int scmi_voltd_set_enable(struct udevice *dev, bool enable)
{
struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
- struct scmi_regulator_priv *priv = dev_get_priv(dev);
struct scmi_voltd_config_set_in in = {
.domain_id = pdata->domain_id,
.config = enable ? SCMI_VOLTD_CONFIG_ON : SCMI_VOLTD_CONFIG_OFF,
@@ -47,7 +38,7 @@ static int scmi_voltd_set_enable(struct udevice *dev, bool enable)
in, out);
int ret;
- ret = devm_scmi_process_msg(dev, priv->channel, &msg);
+ ret = devm_scmi_process_msg(dev, &msg);
if (ret)
return ret;
@@ -57,7 +48,6 @@ static int scmi_voltd_set_enable(struct udevice *dev, bool enable)
static int scmi_voltd_get_enable(struct udevice *dev)
{
struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
- struct scmi_regulator_priv *priv = dev_get_priv(dev);
struct scmi_voltd_config_get_in in = {
.domain_id = pdata->domain_id,
};
@@ -67,7 +57,7 @@ static int scmi_voltd_get_enable(struct udevice *dev)
in, out);
int ret;
- ret = devm_scmi_process_msg(dev, priv->channel, &msg);
+ ret = devm_scmi_process_msg(dev, &msg);
if (ret < 0)
return ret;
@@ -80,7 +70,6 @@ static int scmi_voltd_get_enable(struct udevice *dev)
static int scmi_voltd_set_voltage_level(struct udevice *dev, int uV)
{
- struct scmi_regulator_priv *priv = dev_get_priv(dev);
struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
struct scmi_voltd_level_set_in in = {
.domain_id = pdata->domain_id,
@@ -92,7 +81,7 @@ static int scmi_voltd_set_voltage_level(struct udevice *dev, int uV)
in, out);
int ret;
- ret = devm_scmi_process_msg(dev, priv->channel, &msg);
+ ret = devm_scmi_process_msg(dev, &msg);
if (ret < 0)
return ret;
@@ -101,7 +90,6 @@ static int scmi_voltd_set_voltage_level(struct udevice *dev, int uV)
static int scmi_voltd_get_voltage_level(struct udevice *dev)
{
- struct scmi_regulator_priv *priv = dev_get_priv(dev);
struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
struct scmi_voltd_level_get_in in = {
.domain_id = pdata->domain_id,
@@ -112,7 +100,7 @@ static int scmi_voltd_get_voltage_level(struct udevice *dev)
in, out);
int ret;
- ret = devm_scmi_process_msg(dev, priv->channel, &msg);
+ ret = devm_scmi_process_msg(dev, &msg);
if (ret < 0)
return ret;
@@ -140,7 +128,6 @@ static int scmi_regulator_of_to_plat(struct udevice *dev)
static int scmi_regulator_probe(struct udevice *dev)
{
struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
- struct scmi_regulator_priv *priv = dev_get_priv(dev);
struct scmi_voltd_attr_in in = { 0 };
struct scmi_voltd_attr_out out = { 0 };
struct scmi_msg scmi_msg = {
@@ -153,14 +140,14 @@ static int scmi_regulator_probe(struct udevice *dev)
};
int ret;
- ret = devm_scmi_of_get_channel(dev->parent, &priv->channel);
+ ret = devm_scmi_of_get_channel(dev);
if (ret)
return ret;
/* Check voltage domain is known from SCMI server */
in.domain_id = pdata->domain_id;
- ret = devm_scmi_process_msg(dev, priv->channel, &scmi_msg);
+ ret = devm_scmi_process_msg(dev, &scmi_msg);
if (ret) {
dev_err(dev, "Failed to query voltage domain %u: %d\n",
pdata->domain_id, ret);
@@ -184,7 +171,6 @@ U_BOOT_DRIVER(scmi_regulator) = {
.probe = scmi_regulator_probe,
.of_to_plat = scmi_regulator_of_to_plat,
.plat_auto = sizeof(struct scmi_regulator_platdata),
- .priv_auto = sizeof(struct scmi_regulator_priv *),
};
static int scmi_regulator_bind(struct udevice *dev)
@@ -209,4 +195,5 @@ U_BOOT_DRIVER(scmi_voltage_domain) = {
.name = "scmi_voltage_domain",
.id = UCLASS_NOP,
.bind = scmi_regulator_bind,
+ .per_child_auto = sizeof(struct scmi_agent_proto_priv *),
};
diff --git a/drivers/reset/reset-scmi.c b/drivers/reset/reset-scmi.c
index 122556162ec3..b76711f0a8fb 100644
--- a/drivers/reset/reset-scmi.c
+++ b/drivers/reset/reset-scmi.c
@@ -13,17 +13,8 @@
#include <scmi_protocols.h>
#include <asm/types.h>
-/**
- * struct scmi_reset_priv - Private data for SCMI reset controller
- * @channel: Reference to the SCMI channel to use
- */
-struct scmi_reset_priv {
- struct scmi_channel *channel;
-};
-
static int scmi_reset_set_level(struct reset_ctl *rst, bool assert_not_deassert)
{
- struct scmi_reset_priv *priv = dev_get_priv(rst->dev);
struct scmi_rd_reset_in in = {
.domain_id = rst->id,
.flags = assert_not_deassert ? SCMI_RD_RESET_FLAG_ASSERT : 0,
@@ -35,7 +26,7 @@ static int scmi_reset_set_level(struct reset_ctl *rst, bool assert_not_deassert)
in, out);
int ret;
- ret = devm_scmi_process_msg(rst->dev, priv->channel, &msg);
+ ret = devm_scmi_process_msg(rst->dev, &msg);
if (ret)
return ret;
@@ -54,7 +45,6 @@ static int scmi_reset_deassert(struct reset_ctl *rst)
static int scmi_reset_request(struct reset_ctl *rst)
{
- struct scmi_reset_priv *priv = dev_get_priv(rst->dev);
struct scmi_rd_attr_in in = {
.domain_id = rst->id,
};
@@ -68,7 +58,7 @@ static int scmi_reset_request(struct reset_ctl *rst)
* We don't really care about the attribute, just check
* the reset domain exists.
*/
- ret = devm_scmi_process_msg(rst->dev, priv->channel, &msg);
+ ret = devm_scmi_process_msg(rst->dev, &msg);
if (ret)
return ret;
@@ -83,9 +73,7 @@ static const struct reset_ops scmi_reset_domain_ops = {
static int scmi_reset_probe(struct udevice *dev)
{
- struct scmi_reset_priv *priv = dev_get_priv(dev);
-
- return devm_scmi_of_get_channel(dev, &priv->channel);
+ return devm_scmi_of_get_channel(dev);
}
U_BOOT_DRIVER(scmi_reset_domain) = {
@@ -93,5 +81,4 @@ U_BOOT_DRIVER(scmi_reset_domain) = {
.id = UCLASS_RESET,
.ops = &scmi_reset_domain_ops,
.probe = scmi_reset_probe,
- .priv_auto = sizeof(struct scmi_reset_priv *),
};
diff --git a/include/scmi_agent.h b/include/scmi_agent.h
index ee6286366df7..577892029ff8 100644
--- a/include/scmi_agent.h
+++ b/include/scmi_agent.h
@@ -15,6 +15,14 @@
struct udevice;
struct scmi_channel;
+/**
+ * struct scmi_agent_proto_priv - Private data in device for SCMI agent
+ * @channel: Reference to the SCMI channel to use
+ */
+struct scmi_agent_proto_priv {
+ struct scmi_channel *channel;
+};
+
/*
* struct scmi_msg - Context of a SCMI message sent and the response received
*
@@ -49,10 +57,9 @@ struct scmi_msg {
* devm_scmi_of_get_channel() - Get SCMI channel handle from SCMI agent DT node
*
* @dev: Device requesting a channel
- * @channel: Output reference to the SCMI channel upon success
* @return 0 on success and a negative errno on failure
*/
-int devm_scmi_of_get_channel(struct udevice *dev, struct scmi_channel **channel);
+int devm_scmi_of_get_channel(struct udevice *dev);
/**
* devm_scmi_process_msg() - Send and process an SCMI message
@@ -62,12 +69,10 @@ int devm_scmi_of_get_channel(struct udevice *dev, struct scmi_channel **channel)
* On return, scmi_msg::out_msg_sz stores the response payload size.
*
* @dev: SCMI device
- * @channel: Communication channel for the device
* @msg: Message structure reference
* Return: 0 on success and a negative errno on failure
*/
-int devm_scmi_process_msg(struct udevice *dev, struct scmi_channel *channel,
- struct scmi_msg *msg);
+int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg);
/**
* scmi_to_linux_errno() - Convert an SCMI error code into a Linux errno code
--
2.41.0
^ permalink raw reply related [flat|nested] 40+ messages in thread* Re: [PATCH v2 01/12] scmi: refactor the code to hide a channel from devices
2023-07-26 8:37 ` [PATCH v2 01/12] scmi: refactor the code to hide a channel from devices AKASHI Takahiro
@ 2023-07-27 0:50 ` Simon Glass
2023-08-03 9:20 ` Etienne CARRIERE - foss
2023-08-03 9:24 ` Etienne CARRIERE
1 sibling, 1 reply; 40+ messages in thread
From: Simon Glass @ 2023-07-27 0:50 UTC (permalink / raw)
To: AKASHI Takahiro; +Cc: trini, etienne.carriere, u-boot
On Wed, 26 Jul 2023 at 02:38, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> The commit 85dc58289238 ("firmware: scmi: prepare uclass to pass channel
> reference") added an explicit parameter, channel, but it seems to make
> the code complex.
>
> Hiding this parameter will allow for adding a generic (protocol-agnostic)
> helper function, i.e. for PROTOCOL_VERSION, in a later patch.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
> v2
> * new patch
> ---
> drivers/clk/clk_scmi.c | 27 ++-------
> drivers/firmware/scmi/scmi_agent-uclass.c | 74 ++++++++++++++++++-----
> drivers/power/regulator/scmi_regulator.c | 27 +++------
> drivers/reset/reset-scmi.c | 19 +-----
> include/scmi_agent.h | 15 +++--
> 5 files changed, 86 insertions(+), 76 deletions(-)
>
Reviewed-by: Simon Glass <sjg@chromium.org>
^ permalink raw reply [flat|nested] 40+ messages in thread* Re: [PATCH v2 01/12] scmi: refactor the code to hide a channel from devices
2023-07-27 0:50 ` Simon Glass
@ 2023-08-03 9:20 ` Etienne CARRIERE - foss
0 siblings, 0 replies; 40+ messages in thread
From: Etienne CARRIERE - foss @ 2023-08-03 9:20 UTC (permalink / raw)
To: Simon Glass, AKASHI Takahiro
Cc: trini@konsulko.com, Etienne CARRIERE, u-boot@lists.denx.de
Hello Takahiro-san,
> From: U-Boot <u-boot-bounces@lists.denx.de> on behalf of Simon Glass <sjg@chromium.org>
> Sent: Thursday, July 27, 2023 2:50 AM
>
> On Wed, 26 Jul 2023 at 02:38, AKASHI Takahiro
> <takahiro.akashi@linaro.org> wrote:
> >
> > The commit 85dc58289238 ("firmware: scmi: prepare uclass to pass channel
> > reference") added an explicit parameter, channel, but it seems to make
> > the code complex.
> >
> > Hiding this parameter will allow for adding a generic (protocol-agnostic)
> > helper function, i.e. for PROTOCOL_VERSION, in a later patch.
> >
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > ---
> > v2
> > * new patch
> > ---
> > drivers/clk/clk_scmi.c | 27 ++-------
> > drivers/firmware/scmi/scmi_agent-uclass.c | 74 ++++++++++++++++++-----
> > drivers/power/regulator/scmi_regulator.c | 27 +++------
> > drivers/reset/reset-scmi.c | 19 +-----
> > include/scmi_agent.h | 15 +++--
> > 5 files changed, 86 insertions(+), 76 deletions(-)
> >
>
> Reviewed-by: Simon Glass <sjg@chromium.org>
Sorry for this late feedback. I initially saw no issues with this patch series
but testing the series against stm32mp135f-dk board which is using SCMI
resources, I saw the board failed to boot. The issue is related to udevice
parent tree and common clock framework. I'll post comments on patch 01/12.
Best regards,
Etienne
^ permalink raw reply [flat|nested] 40+ messages in thread
* RE: [PATCH v2 01/12] scmi: refactor the code to hide a channel from devices
2023-07-26 8:37 ` [PATCH v2 01/12] scmi: refactor the code to hide a channel from devices AKASHI Takahiro
2023-07-27 0:50 ` Simon Glass
@ 2023-08-03 9:24 ` Etienne CARRIERE
2023-08-07 10:03 ` AKASHI Takahiro
1 sibling, 1 reply; 40+ messages in thread
From: Etienne CARRIERE @ 2023-08-03 9:24 UTC (permalink / raw)
To: AKASHI Takahiro, trini@konsulko.com, sjg@chromium.org
Cc: u-boot@lists.denx.de
Hello Takahiro-san,
Sorry again for this late feedback.
Testing the series against stm32mp135f-dk board which is using SCMI resources, I see the board fails to boot.
> From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> To: trini@konsulko.com, sjg@chromium.org
> Cc: etienne.carriere@st.com, u-boot@lists.denx.de,
> AKASHI Takahiro <takahiro.akashi@linaro.org>
> Subject: [PATCH v2 01/12] scmi: refactor the code to hide a channel from devices
> Date: Wed, 26 Jul 2023 17:37:57 +0900 [thread overview]
> Message-ID: <20230726083808.140780-2-takahiro.akashi@linaro.org> (raw)
> In-Reply-To: <20230726083808.140780-1-takahiro.akashi@linaro.org>
>
> The commit 85dc58289238 ("firmware: scmi: prepare uclass to pass channel
> reference") added an explicit parameter, channel, but it seems to make
> the code complex.
>
> Hiding this parameter will allow for adding a generic (protocol-agnostic)
> helper function, i.e. for PROTOCOL_VERSION, in a later patch.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
>
> ---
> v2
> * new patch
> ---
> drivers/clk/clk_scmi.c | 27 ++-------
> drivers/firmware/scmi/scmi_agent-uclass.c | 74 ++++++++++++++++++-----
> drivers/power/regulator/scmi_regulator.c | 27 +++------
> drivers/reset/reset-scmi.c | 19 +-----
> include/scmi_agent.h | 15 +++--
> 5 files changed, 86 insertions(+), 76 deletions(-)
>
> diff --git a/drivers/clk/clk_scmi.c b/drivers/clk/clk_scmi.c
> index d172fed24c9d..34a49363a51a 100644
> --- a/drivers/clk/clk_scmi.c
> +++ b/drivers/clk/clk_scmi.c
> @@ -13,17 +13,8 @@
> #include <asm/types.h>
> #include <linux/clk-provider.h>
>
> -/**
> - * struct scmi_clk_priv - Private data for SCMI clocks
> - * @channel: Reference to the SCMI channel to use
> - */
> -struct scmi_clk_priv {
> - struct scmi_channel *channel;
> -};
> -
> static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks)
> {
> - struct scmi_clk_priv *priv = dev_get_priv(dev);
> struct scmi_clk_protocol_attr_out out;
> struct scmi_msg msg = {
> .protocol_id = SCMI_PROTOCOL_ID_CLOCK,
> @@ -33,7 +24,7 @@ static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks)
> };
> int ret;
>
> - ret = devm_scmi_process_msg(dev, priv->channel, &msg);
> + ret = devm_scmi_process_msg(dev, &msg);
> if (ret)
> return ret;
>
> @@ -44,7 +35,6 @@ static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks)
>
> static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name)
> {
> - struct scmi_clk_priv *priv = dev_get_priv(dev);
> struct scmi_clk_attribute_in in = {
> .clock_id = clkid,
> };
> @@ -59,7 +49,7 @@ static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name)
> };
> int ret;
>
> - ret = devm_scmi_process_msg(dev, priv->channel, &msg);
> + ret = devm_scmi_process_msg(dev, &msg);
> if (ret)
> return ret;
>
> @@ -70,7 +60,6 @@ static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name)
>
> static int scmi_clk_gate(struct clk *clk, int enable)
> {
> - struct scmi_clk_priv *priv = dev_get_priv(clk->dev);
> struct scmi_clk_state_in in = {
> .clock_id = clk->id,
> .attributes = enable,
> @@ -81,7 +70,7 @@ static int scmi_clk_gate(struct clk *clk, int enable)
> in, out);
> int ret;
>
> - ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg);
> + ret = devm_scmi_process_msg(clk->dev, &msg);
> if (ret)
> return ret;
>
> @@ -100,7 +89,6 @@ static int scmi_clk_disable(struct clk *clk)
>
> static ulong scmi_clk_get_rate(struct clk *clk)
> {
> - struct scmi_clk_priv *priv = dev_get_priv(clk->dev);
> struct scmi_clk_rate_get_in in = {
> .clock_id = clk->id,
> };
> @@ -110,7 +98,7 @@ static ulong scmi_clk_get_rate(struct clk *clk)
> in, out);
> int ret;
>
> - ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg);
> + ret = devm_scmi_process_msg(clk->dev, &msg);
> if (ret < 0)
> return ret;
>
> @@ -123,7 +111,6 @@ static ulong scmi_clk_get_rate(struct clk *clk)
>
> static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
> {
> - struct scmi_clk_priv *priv = dev_get_priv(clk->dev);
> struct scmi_clk_rate_set_in in = {
> .clock_id = clk->id,
> .flags = SCMI_CLK_RATE_ROUND_CLOSEST,
> @@ -136,7 +123,7 @@ static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
> in, out);
> int ret;
>
> - ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg);
> + ret = devm_scmi_process_msg(clk->dev, &msg);
> if (ret < 0)
> return ret;
>
> @@ -149,12 +136,11 @@ static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
>
> static int scmi_clk_probe(struct udevice *dev)
> {
> - struct scmi_clk_priv *priv = dev_get_priv(dev);
> struct clk *clk;
> size_t num_clocks, i;
> int ret;
>
> - ret = devm_scmi_of_get_channel(dev, &priv->channel);
> + ret = devm_scmi_of_get_channel(dev);
> if (ret)
> return ret;
>
> @@ -205,5 +191,4 @@ U_BOOT_DRIVER(scmi_clock) = {
> .id = UCLASS_CLK,
> .ops = &scmi_clk_ops,
> .probe = scmi_clk_probe,
> - .priv_auto = sizeof(struct scmi_clk_priv *),
> };
> diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c
> index 02de692d66f3..39cf15c88f75 100644
> --- a/drivers/firmware/scmi/scmi_agent-uclass.c
> +++ b/drivers/firmware/scmi/scmi_agent-uclass.c
> @@ -8,6 +8,7 @@
> #include <common.h>
> #include <dm.h>
> #include <errno.h>
> +#include <scmi_agent.h>
> #include <scmi_agent-uclass.h>
> #include <scmi_protocols.h>
> #include <dm/device_compat.h>
> @@ -129,43 +130,88 @@ static const struct scmi_agent_ops *transport_dev_ops(struct udevice *dev)
> return (const struct scmi_agent_ops *)dev->driver->ops;
> }
>
> -int devm_scmi_of_get_channel(struct udevice *dev, struct scmi_channel **channel)
> +/**
> + * scmi_of_get_channel() - Get SCMI channel handle
> + *
> + * @dev: SCMI agent device
> + * @channel: Output reference to the SCMI channel upon success
> + *
> + * On return, @channel will be set.
> + * Return 0 on success and a negative errno on failure
> + */
> +static int scmi_of_get_channel(struct udevice *dev, struct scmi_channel **channel)
> +{
> + const struct scmi_agent_ops *ops;
> +
> + ops = transport_dev_ops(dev);
> + if (ops->of_get_channel)
> + return ops->of_get_channel(dev, channel);
> + else
> + return -EPROTONOSUPPORT;
> +}
> +
> +int devm_scmi_of_get_channel(struct udevice *dev)
> {
> struct udevice *parent;
> + struct scmi_agent_proto_priv *priv = dev_get_parent_priv(dev);
This parent lookup does not match when CONFIG_CLK_CCF is enabled. When so,
the scmi clock device is on the clock itself but a child udevice of some
udevice held by the common clock framework (CCF).
Platforms from the stm32mp13 family do enable SCMI clock and CCF.
It can propose a way to go, using find_scmi_transport_device() to provide
the agent's 1st child private data as an output argument:
//patch-start
-static struct udevice *find_scmi_transport_device(struct udevice *dev)
+static struct udevice *
+find_scmi_transport_device(struct udevice *dev,
+ struct scmi_agent_proto_priv **priv)
{
struct udevice *parent = dev;
+ struct scmi_agent_proto_priv *parent_priv;
do {
+ parent_priv = dev_get_parent_priv(parent);
parent = dev_get_parent(parent);
} while (parent && device_get_uclass_id(parent) != UCLASS_SCMI_AGENT);
if (!parent)
dev_err(dev, "Invalid SCMI device, agent not found\n");
+ else if (priv)
+ *priv = parent_priv;
return parent;
}
//end patch
Tested OK on stm32mp13 with the remaining patch series applied (minor conflics).
BR,
etienne
> + int ret;
>
> parent = find_scmi_transport_device(dev);
> if (!parent)
> return -ENODEV;
>
> - if (transport_dev_ops(parent)->of_get_channel)
> - return transport_dev_ops(parent)->of_get_channel(parent, channel);
> + ret = scmi_of_get_channel(parent, &priv->channel);
> + if (ret == -EPROTONOSUPPORT) {
> + /* Drivers without a get_channel operator don't need a channel ref */
> + priv->channel = NULL;
>
> - /* Drivers without a get_channel operator don't need a channel ref */
> - *channel = NULL;
> + return 0;
> + }
>
> - return 0;
> + return ret;
> }
>
> -int devm_scmi_process_msg(struct udevice *dev, struct scmi_channel *channel,
> - struct scmi_msg *msg)
> +/**
> + * scmi_process_msg() - Send and process an SCMI message
> + *
> + * Send a message to an SCMI server.
> + * Caller sets scmi_msg::out_msg_sz to the output message buffer size.
> + *
> + * @dev: SCMI agent device
> + * @channel: Communication channel for the device
> + * @msg: Message structure reference
> + *
> + * On return, scmi_msg::out_msg_sz stores the response payload size.
> + * Return: 0 on success and a negative errno on failure
> + */
> +static int scmi_process_msg(struct udevice *dev, struct scmi_channel *channel,
> + struct scmi_msg *msg)
> {
> const struct scmi_agent_ops *ops;
> +
> + ops = transport_dev_ops(dev);
> + if (ops->process_msg)
> + return ops->process_msg(dev, channel, msg);
> + else
> + return -EPROTONOSUPPORT;
> +}
> +
> +int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg)
> +{
> struct udevice *parent;
> + struct scmi_agent_proto_priv *priv = dev_get_parent_priv(dev);
>
> parent = find_scmi_transport_device(dev);
> if (!parent)
> return -ENODEV;
>
> - ops = transport_dev_ops(parent);
> -
> - if (ops->process_msg)
> - return ops->process_msg(parent, channel, msg);
> -
> - return -EPROTONOSUPPORT;
> + return scmi_process_msg(parent, priv->channel, msg);
> }
>
> UCLASS_DRIVER(scmi_agent) = {
> .id = UCLASS_SCMI_AGENT,
> .name = "scmi_agent",
> .post_bind = scmi_bind_protocols,
> + .per_device_plat_auto = sizeof(struct scmi_agent_priv),
Typo: this added line belong to patch 04/12.
Regards,
Etienne
> + .per_child_auto = sizeof(struct scmi_agent_proto_priv *),
> };
> diff --git a/drivers/power/regulator/scmi_regulator.c b/drivers/power/regulator/scmi_regulator.c
> index 801148036ff6..08918b20872c 100644
> --- a/drivers/power/regulator/scmi_regulator.c
> +++ b/drivers/power/regulator/scmi_regulator.c
> @@ -25,18 +25,9 @@ struct scmi_regulator_platdata {
> u32 domain_id;
> };
>
> -/**
> - * struct scmi_regulator_priv - Private data for SCMI voltage regulator
> - * @channel: Reference to the SCMI channel to use
> - */
> -struct scmi_regulator_priv {
> - struct scmi_channel *channel;
> -};
> -
> static int scmi_voltd_set_enable(struct udevice *dev, bool enable)
> {
> struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
> - struct scmi_regulator_priv *priv = dev_get_priv(dev);
> struct scmi_voltd_config_set_in in = {
> .domain_id = pdata->domain_id,
> .config = enable ? SCMI_VOLTD_CONFIG_ON : SCMI_VOLTD_CONFIG_OFF,
> @@ -47,7 +38,7 @@ static int scmi_voltd_set_enable(struct udevice *dev, bool enable)
> in, out);
> int ret;
>
> - ret = devm_scmi_process_msg(dev, priv->channel, &msg);
> + ret = devm_scmi_process_msg(dev, &msg);
> if (ret)
> return ret;
>
> @@ -57,7 +48,6 @@ static int scmi_voltd_set_enable(struct udevice *dev, bool enable)
> static int scmi_voltd_get_enable(struct udevice *dev)
> {
> struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
> - struct scmi_regulator_priv *priv = dev_get_priv(dev);
> struct scmi_voltd_config_get_in in = {
> .domain_id = pdata->domain_id,
> };
> @@ -67,7 +57,7 @@ static int scmi_voltd_get_enable(struct udevice *dev)
> in, out);
> int ret;
>
> - ret = devm_scmi_process_msg(dev, priv->channel, &msg);
> + ret = devm_scmi_process_msg(dev, &msg);
> if (ret < 0)
> return ret;
>
> @@ -80,7 +70,6 @@ static int scmi_voltd_get_enable(struct udevice *dev)
>
> static int scmi_voltd_set_voltage_level(struct udevice *dev, int uV)
> {
> - struct scmi_regulator_priv *priv = dev_get_priv(dev);
> struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
> struct scmi_voltd_level_set_in in = {
> .domain_id = pdata->domain_id,
> @@ -92,7 +81,7 @@ static int scmi_voltd_set_voltage_level(struct udevice *dev, int uV)
> in, out);
> int ret;
>
> - ret = devm_scmi_process_msg(dev, priv->channel, &msg);
> + ret = devm_scmi_process_msg(dev, &msg);
> if (ret < 0)
> return ret;
>
> @@ -101,7 +90,6 @@ static int scmi_voltd_set_voltage_level(struct udevice *dev, int uV)
>
> static int scmi_voltd_get_voltage_level(struct udevice *dev)
> {
> - struct scmi_regulator_priv *priv = dev_get_priv(dev);
> struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
> struct scmi_voltd_level_get_in in = {
> .domain_id = pdata->domain_id,
> @@ -112,7 +100,7 @@ static int scmi_voltd_get_voltage_level(struct udevice *dev)
> in, out);
> int ret;
>
> - ret = devm_scmi_process_msg(dev, priv->channel, &msg);
> + ret = devm_scmi_process_msg(dev, &msg);
> if (ret < 0)
> return ret;
>
> @@ -140,7 +128,6 @@ static int scmi_regulator_of_to_plat(struct udevice *dev)
> static int scmi_regulator_probe(struct udevice *dev)
> {
> struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
> - struct scmi_regulator_priv *priv = dev_get_priv(dev);
> struct scmi_voltd_attr_in in = { 0 };
> struct scmi_voltd_attr_out out = { 0 };
> struct scmi_msg scmi_msg = {
> @@ -153,14 +140,14 @@ static int scmi_regulator_probe(struct udevice *dev)
> };
> int ret;
>
> - ret = devm_scmi_of_get_channel(dev->parent, &priv->channel);
> + ret = devm_scmi_of_get_channel(dev);
> if (ret)
> return ret;
>
> /* Check voltage domain is known from SCMI server */
> in.domain_id = pdata->domain_id;
>
> - ret = devm_scmi_process_msg(dev, priv->channel, &scmi_msg);
> + ret = devm_scmi_process_msg(dev, &scmi_msg);
> if (ret) {
> dev_err(dev, "Failed to query voltage domain %u: %d\n",
> pdata->domain_id, ret);
> @@ -184,7 +171,6 @@ U_BOOT_DRIVER(scmi_regulator) = {
> .probe = scmi_regulator_probe,
> .of_to_plat = scmi_regulator_of_to_plat,
> .plat_auto = sizeof(struct scmi_regulator_platdata),
> - .priv_auto = sizeof(struct scmi_regulator_priv *),
> };
>
> static int scmi_regulator_bind(struct udevice *dev)
> @@ -209,4 +195,5 @@ U_BOOT_DRIVER(scmi_voltage_domain) = {
> .name = "scmi_voltage_domain",
> .id = UCLASS_NOP,
> .bind = scmi_regulator_bind,
> + .per_child_auto = sizeof(struct scmi_agent_proto_priv *),
> };
> diff --git a/drivers/reset/reset-scmi.c b/drivers/reset/reset-scmi.c
> index 122556162ec3..b76711f0a8fb 100644
> --- a/drivers/reset/reset-scmi.c
> +++ b/drivers/reset/reset-scmi.c
> @@ -13,17 +13,8 @@
> #include <scmi_protocols.h>
> #include <asm/types.h>
>
> -/**
> - * struct scmi_reset_priv - Private data for SCMI reset controller
> - * @channel: Reference to the SCMI channel to use
> - */
> -struct scmi_reset_priv {
> - struct scmi_channel *channel;
> -};
> -
> static int scmi_reset_set_level(struct reset_ctl *rst, bool assert_not_deassert)
> {
> - struct scmi_reset_priv *priv = dev_get_priv(rst->dev);
> struct scmi_rd_reset_in in = {
> .domain_id = rst->id,
> .flags = assert_not_deassert ? SCMI_RD_RESET_FLAG_ASSERT : 0,
> @@ -35,7 +26,7 @@ static int scmi_reset_set_level(struct reset_ctl *rst, bool assert_not_deassert)
> in, out);
> int ret;
>
> - ret = devm_scmi_process_msg(rst->dev, priv->channel, &msg);
> + ret = devm_scmi_process_msg(rst->dev, &msg);
> if (ret)
> return ret;
>
> @@ -54,7 +45,6 @@ static int scmi_reset_deassert(struct reset_ctl *rst)
>
> static int scmi_reset_request(struct reset_ctl *rst)
> {
> - struct scmi_reset_priv *priv = dev_get_priv(rst->dev);
> struct scmi_rd_attr_in in = {
> .domain_id = rst->id,
> };
> @@ -68,7 +58,7 @@ static int scmi_reset_request(struct reset_ctl *rst)
> * We don't really care about the attribute, just check
> * the reset domain exists.
> */
> - ret = devm_scmi_process_msg(rst->dev, priv->channel, &msg);
> + ret = devm_scmi_process_msg(rst->dev, &msg);
> if (ret)
> return ret;
>
> @@ -83,9 +73,7 @@ static const struct reset_ops scmi_reset_domain_ops = {
>
> static int scmi_reset_probe(struct udevice *dev)
> {
> - struct scmi_reset_priv *priv = dev_get_priv(dev);
> -
> - return devm_scmi_of_get_channel(dev, &priv->channel);
> + return devm_scmi_of_get_channel(dev);
> }
>
> U_BOOT_DRIVER(scmi_reset_domain) = {
> @@ -93,5 +81,4 @@ U_BOOT_DRIVER(scmi_reset_domain) = {
> .id = UCLASS_RESET,
> .ops = &scmi_reset_domain_ops,
> .probe = scmi_reset_probe,
> - .priv_auto = sizeof(struct scmi_reset_priv *),
> };
> diff --git a/include/scmi_agent.h b/include/scmi_agent.h
> index ee6286366df7..577892029ff8 100644
> --- a/include/scmi_agent.h
> +++ b/include/scmi_agent.h
> @@ -15,6 +15,14 @@
> struct udevice;
> struct scmi_channel;
>
> +/**
> + * struct scmi_agent_proto_priv - Private data in device for SCMI agent
> + * @channel: Reference to the SCMI channel to use
> + */
> +struct scmi_agent_proto_priv {
> + struct scmi_channel *channel;
> +};
> +
> /*
> * struct scmi_msg - Context of a SCMI message sent and the response received
> *
> @@ -49,10 +57,9 @@ struct scmi_msg {
> * devm_scmi_of_get_channel() - Get SCMI channel handle from SCMI agent DT node
> *
> * @dev: Device requesting a channel
> - * @channel: Output reference to the SCMI channel upon success
> * @return 0 on success and a negative errno on failure
> */
> -int devm_scmi_of_get_channel(struct udevice *dev, struct scmi_channel **channel);
> +int devm_scmi_of_get_channel(struct udevice *dev);
>
> /**
> * devm_scmi_process_msg() - Send and process an SCMI message
> @@ -62,12 +69,10 @@ int devm_scmi_of_get_channel(struct udevice *dev, struct scmi_channel **channel)
> * On return, scmi_msg::out_msg_sz stores the response payload size.
> *
> * @dev: SCMI device
> - * @channel: Communication channel for the device
> * @msg: Message structure reference
> * Return: 0 on success and a negative errno on failure
> */
> -int devm_scmi_process_msg(struct udevice *dev, struct scmi_channel *channel,
> - struct scmi_msg *msg);
> +int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg);
>
> /**
> * scmi_to_linux_errno() - Convert an SCMI error code into a Linux errno code
> --
> 2.41.0
^ permalink raw reply [flat|nested] 40+ messages in thread* Re: [PATCH v2 01/12] scmi: refactor the code to hide a channel from devices
2023-08-03 9:24 ` Etienne CARRIERE
@ 2023-08-07 10:03 ` AKASHI Takahiro
2023-08-08 8:04 ` Etienne CARRIERE - foss
0 siblings, 1 reply; 40+ messages in thread
From: AKASHI Takahiro @ 2023-08-07 10:03 UTC (permalink / raw)
To: Etienne CARRIERE
Cc: trini@konsulko.com, sjg@chromium.org, u-boot@lists.denx.de
Hi Etienne,
On Thu, Aug 03, 2023 at 09:24:51AM +0000, Etienne CARRIERE wrote:
> Hello Takahiro-san,
>
> Sorry again for this late feedback.
> Testing the series against stm32mp135f-dk board which is using SCMI resources, I see the board fails to boot.
>
> > From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > To: trini@konsulko.com, sjg@chromium.org
> > Cc: etienne.carriere@st.com, u-boot@lists.denx.de,
> > AKASHI Takahiro <takahiro.akashi@linaro.org>
> > Subject: [PATCH v2 01/12] scmi: refactor the code to hide a channel from devices
> > Date: Wed, 26 Jul 2023 17:37:57 +0900 [thread overview]
> > Message-ID: <20230726083808.140780-2-takahiro.akashi@linaro.org> (raw)
> > In-Reply-To: <20230726083808.140780-1-takahiro.akashi@linaro.org>
> >
> > The commit 85dc58289238 ("firmware: scmi: prepare uclass to pass channel
> > reference") added an explicit parameter, channel, but it seems to make
> > the code complex.
> >
> > Hiding this parameter will allow for adding a generic (protocol-agnostic)
> > helper function, i.e. for PROTOCOL_VERSION, in a later patch.
> >
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> >
> > ---
> > v2
> > * new patch
> > ---
> > drivers/clk/clk_scmi.c | 27 ++-------
> > drivers/firmware/scmi/scmi_agent-uclass.c | 74 ++++++++++++++++++-----
> > drivers/power/regulator/scmi_regulator.c | 27 +++------
> > drivers/reset/reset-scmi.c | 19 +-----
> > include/scmi_agent.h | 15 +++--
> > 5 files changed, 86 insertions(+), 76 deletions(-)
> >
> > diff --git a/drivers/clk/clk_scmi.c b/drivers/clk/clk_scmi.c
> > index d172fed24c9d..34a49363a51a 100644
> > --- a/drivers/clk/clk_scmi.c
> > +++ b/drivers/clk/clk_scmi.c
> > @@ -13,17 +13,8 @@
> > #include <asm/types.h>
> > #include <linux/clk-provider.h>
> >
> > -/**
> > - * struct scmi_clk_priv - Private data for SCMI clocks
> > - * @channel: Reference to the SCMI channel to use
> > - */
> > -struct scmi_clk_priv {
> > - struct scmi_channel *channel;
> > -};
> > -
> > static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks)
> > {
> > - struct scmi_clk_priv *priv = dev_get_priv(dev);
> > struct scmi_clk_protocol_attr_out out;
> > struct scmi_msg msg = {
> > .protocol_id = SCMI_PROTOCOL_ID_CLOCK,
> > @@ -33,7 +24,7 @@ static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks)
> > };
> > int ret;
> >
> > - ret = devm_scmi_process_msg(dev, priv->channel, &msg);
> > + ret = devm_scmi_process_msg(dev, &msg);
> > if (ret)
> > return ret;
> >
> > @@ -44,7 +35,6 @@ static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks)
> >
> > static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name)
> > {
> > - struct scmi_clk_priv *priv = dev_get_priv(dev);
> > struct scmi_clk_attribute_in in = {
> > .clock_id = clkid,
> > };
> > @@ -59,7 +49,7 @@ static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name)
> > };
> > int ret;
> >
> > - ret = devm_scmi_process_msg(dev, priv->channel, &msg);
> > + ret = devm_scmi_process_msg(dev, &msg);
> > if (ret)
> > return ret;
> >
> > @@ -70,7 +60,6 @@ static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name)
> >
> > static int scmi_clk_gate(struct clk *clk, int enable)
> > {
> > - struct scmi_clk_priv *priv = dev_get_priv(clk->dev);
> > struct scmi_clk_state_in in = {
> > .clock_id = clk->id,
> > .attributes = enable,
> > @@ -81,7 +70,7 @@ static int scmi_clk_gate(struct clk *clk, int enable)
> > in, out);
> > int ret;
> >
> > - ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg);
> > + ret = devm_scmi_process_msg(clk->dev, &msg);
> > if (ret)
> > return ret;
> >
> > @@ -100,7 +89,6 @@ static int scmi_clk_disable(struct clk *clk)
> >
> > static ulong scmi_clk_get_rate(struct clk *clk)
> > {
> > - struct scmi_clk_priv *priv = dev_get_priv(clk->dev);
> > struct scmi_clk_rate_get_in in = {
> > .clock_id = clk->id,
> > };
> > @@ -110,7 +98,7 @@ static ulong scmi_clk_get_rate(struct clk *clk)
> > in, out);
> > int ret;
> >
> > - ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg);
> > + ret = devm_scmi_process_msg(clk->dev, &msg);
> > if (ret < 0)
> > return ret;
> >
> > @@ -123,7 +111,6 @@ static ulong scmi_clk_get_rate(struct clk *clk)
> >
> > static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
> > {
> > - struct scmi_clk_priv *priv = dev_get_priv(clk->dev);
> > struct scmi_clk_rate_set_in in = {
> > .clock_id = clk->id,
> > .flags = SCMI_CLK_RATE_ROUND_CLOSEST,
> > @@ -136,7 +123,7 @@ static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
> > in, out);
> > int ret;
> >
> > - ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg);
> > + ret = devm_scmi_process_msg(clk->dev, &msg);
> > if (ret < 0)
> > return ret;
> >
> > @@ -149,12 +136,11 @@ static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
> >
> > static int scmi_clk_probe(struct udevice *dev)
> > {
> > - struct scmi_clk_priv *priv = dev_get_priv(dev);
> > struct clk *clk;
> > size_t num_clocks, i;
> > int ret;
> >
> > - ret = devm_scmi_of_get_channel(dev, &priv->channel);
> > + ret = devm_scmi_of_get_channel(dev);
> > if (ret)
> > return ret;
> >
> > @@ -205,5 +191,4 @@ U_BOOT_DRIVER(scmi_clock) = {
> > .id = UCLASS_CLK,
> > .ops = &scmi_clk_ops,
> > .probe = scmi_clk_probe,
> > - .priv_auto = sizeof(struct scmi_clk_priv *),
> > };
> > diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c
> > index 02de692d66f3..39cf15c88f75 100644
> > --- a/drivers/firmware/scmi/scmi_agent-uclass.c
> > +++ b/drivers/firmware/scmi/scmi_agent-uclass.c
> > @@ -8,6 +8,7 @@
> > #include <common.h>
> > #include <dm.h>
> > #include <errno.h>
> > +#include <scmi_agent.h>
> > #include <scmi_agent-uclass.h>
> > #include <scmi_protocols.h>
> > #include <dm/device_compat.h>
> > @@ -129,43 +130,88 @@ static const struct scmi_agent_ops *transport_dev_ops(struct udevice *dev)
> > return (const struct scmi_agent_ops *)dev->driver->ops;
> > }
> >
> > -int devm_scmi_of_get_channel(struct udevice *dev, struct scmi_channel **channel)
> > +/**
> > + * scmi_of_get_channel() - Get SCMI channel handle
> > + *
> > + * @dev: SCMI agent device
> > + * @channel: Output reference to the SCMI channel upon success
> > + *
> > + * On return, @channel will be set.
> > + * Return 0 on success and a negative errno on failure
> > + */
> > +static int scmi_of_get_channel(struct udevice *dev, struct scmi_channel **channel)
> > +{
> > + const struct scmi_agent_ops *ops;
> > +
> > + ops = transport_dev_ops(dev);
> > + if (ops->of_get_channel)
> > + return ops->of_get_channel(dev, channel);
> > + else
> > + return -EPROTONOSUPPORT;
> > +}
> > +
> > +int devm_scmi_of_get_channel(struct udevice *dev)
> > {
> > struct udevice *parent;
> > + struct scmi_agent_proto_priv *priv = dev_get_parent_priv(dev);
>
> This parent lookup does not match when CONFIG_CLK_CCF is enabled. When so,
> the scmi clock device is on the clock itself but a child udevice of some
> udevice held by the common clock framework (CCF).
> Platforms from the stm32mp13 family do enable SCMI clock and CCF.
I tested my patch on sandbox, where CCF is also enabled,
and "ut dm scmi_clocks" is passed without any error.
So I'm not sure if the point you mentioned above is a root cause.
-Takahiro Akashi
> It can propose a way to go, using find_scmi_transport_device() to provide
> the agent's 1st child private data as an output argument:
> //patch-start
> -static struct udevice *find_scmi_transport_device(struct udevice *dev)
> +static struct udevice *
> +find_scmi_transport_device(struct udevice *dev,
> + struct scmi_agent_proto_priv **priv)
> {
> struct udevice *parent = dev;
> + struct scmi_agent_proto_priv *parent_priv;
>
> do {
> + parent_priv = dev_get_parent_priv(parent);
> parent = dev_get_parent(parent);
> } while (parent && device_get_uclass_id(parent) != UCLASS_SCMI_AGENT);
>
> if (!parent)
> dev_err(dev, "Invalid SCMI device, agent not found\n");
> + else if (priv)
> + *priv = parent_priv;
>
> return parent;
> }
> //end patch
>
> Tested OK on stm32mp13 with the remaining patch series applied (minor conflics).
>
> BR,
> etienne
>
>
> > + int ret;
> >
> > parent = find_scmi_transport_device(dev);
> > if (!parent)
> > return -ENODEV;
> >
> > - if (transport_dev_ops(parent)->of_get_channel)
> > - return transport_dev_ops(parent)->of_get_channel(parent, channel);
> > + ret = scmi_of_get_channel(parent, &priv->channel);
> > + if (ret == -EPROTONOSUPPORT) {
> > + /* Drivers without a get_channel operator don't need a channel ref */
> > + priv->channel = NULL;
> >
> > - /* Drivers without a get_channel operator don't need a channel ref */
> > - *channel = NULL;
> > + return 0;
> > + }
> >
> > - return 0;
> > + return ret;
> > }
> >
> > -int devm_scmi_process_msg(struct udevice *dev, struct scmi_channel *channel,
> > - struct scmi_msg *msg)
> > +/**
> > + * scmi_process_msg() - Send and process an SCMI message
> > + *
> > + * Send a message to an SCMI server.
> > + * Caller sets scmi_msg::out_msg_sz to the output message buffer size.
> > + *
> > + * @dev: SCMI agent device
> > + * @channel: Communication channel for the device
> > + * @msg: Message structure reference
> > + *
> > + * On return, scmi_msg::out_msg_sz stores the response payload size.
> > + * Return: 0 on success and a negative errno on failure
> > + */
> > +static int scmi_process_msg(struct udevice *dev, struct scmi_channel *channel,
> > + struct scmi_msg *msg)
> > {
> > const struct scmi_agent_ops *ops;
> > +
> > + ops = transport_dev_ops(dev);
> > + if (ops->process_msg)
> > + return ops->process_msg(dev, channel, msg);
> > + else
> > + return -EPROTONOSUPPORT;
> > +}
> > +
> > +int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg)
> > +{
> > struct udevice *parent;
> > + struct scmi_agent_proto_priv *priv = dev_get_parent_priv(dev);
> >
> > parent = find_scmi_transport_device(dev);
> > if (!parent)
> > return -ENODEV;
> >
> > - ops = transport_dev_ops(parent);
> > -
> > - if (ops->process_msg)
> > - return ops->process_msg(parent, channel, msg);
> > -
> > - return -EPROTONOSUPPORT;
> > + return scmi_process_msg(parent, priv->channel, msg);
> > }
> >
> > UCLASS_DRIVER(scmi_agent) = {
> > .id = UCLASS_SCMI_AGENT,
> > .name = "scmi_agent",
> > .post_bind = scmi_bind_protocols,
> > + .per_device_plat_auto = sizeof(struct scmi_agent_priv),
>
> Typo: this added line belong to patch 04/12.
>
> Regards,
> Etienne
>
> > + .per_child_auto = sizeof(struct scmi_agent_proto_priv *),
> > };
> > diff --git a/drivers/power/regulator/scmi_regulator.c b/drivers/power/regulator/scmi_regulator.c
> > index 801148036ff6..08918b20872c 100644
> > --- a/drivers/power/regulator/scmi_regulator.c
> > +++ b/drivers/power/regulator/scmi_regulator.c
> > @@ -25,18 +25,9 @@ struct scmi_regulator_platdata {
> > u32 domain_id;
> > };
> >
> > -/**
> > - * struct scmi_regulator_priv - Private data for SCMI voltage regulator
> > - * @channel: Reference to the SCMI channel to use
> > - */
> > -struct scmi_regulator_priv {
> > - struct scmi_channel *channel;
> > -};
> > -
> > static int scmi_voltd_set_enable(struct udevice *dev, bool enable)
> > {
> > struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
> > - struct scmi_regulator_priv *priv = dev_get_priv(dev);
> > struct scmi_voltd_config_set_in in = {
> > .domain_id = pdata->domain_id,
> > .config = enable ? SCMI_VOLTD_CONFIG_ON : SCMI_VOLTD_CONFIG_OFF,
> > @@ -47,7 +38,7 @@ static int scmi_voltd_set_enable(struct udevice *dev, bool enable)
> > in, out);
> > int ret;
> >
> > - ret = devm_scmi_process_msg(dev, priv->channel, &msg);
> > + ret = devm_scmi_process_msg(dev, &msg);
> > if (ret)
> > return ret;
> >
> > @@ -57,7 +48,6 @@ static int scmi_voltd_set_enable(struct udevice *dev, bool enable)
> > static int scmi_voltd_get_enable(struct udevice *dev)
> > {
> > struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
> > - struct scmi_regulator_priv *priv = dev_get_priv(dev);
> > struct scmi_voltd_config_get_in in = {
> > .domain_id = pdata->domain_id,
> > };
> > @@ -67,7 +57,7 @@ static int scmi_voltd_get_enable(struct udevice *dev)
> > in, out);
> > int ret;
> >
> > - ret = devm_scmi_process_msg(dev, priv->channel, &msg);
> > + ret = devm_scmi_process_msg(dev, &msg);
> > if (ret < 0)
> > return ret;
> >
> > @@ -80,7 +70,6 @@ static int scmi_voltd_get_enable(struct udevice *dev)
> >
> > static int scmi_voltd_set_voltage_level(struct udevice *dev, int uV)
> > {
> > - struct scmi_regulator_priv *priv = dev_get_priv(dev);
> > struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
> > struct scmi_voltd_level_set_in in = {
> > .domain_id = pdata->domain_id,
> > @@ -92,7 +81,7 @@ static int scmi_voltd_set_voltage_level(struct udevice *dev, int uV)
> > in, out);
> > int ret;
> >
> > - ret = devm_scmi_process_msg(dev, priv->channel, &msg);
> > + ret = devm_scmi_process_msg(dev, &msg);
> > if (ret < 0)
> > return ret;
> >
> > @@ -101,7 +90,6 @@ static int scmi_voltd_set_voltage_level(struct udevice *dev, int uV)
> >
> > static int scmi_voltd_get_voltage_level(struct udevice *dev)
> > {
> > - struct scmi_regulator_priv *priv = dev_get_priv(dev);
> > struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
> > struct scmi_voltd_level_get_in in = {
> > .domain_id = pdata->domain_id,
> > @@ -112,7 +100,7 @@ static int scmi_voltd_get_voltage_level(struct udevice *dev)
> > in, out);
> > int ret;
> >
> > - ret = devm_scmi_process_msg(dev, priv->channel, &msg);
> > + ret = devm_scmi_process_msg(dev, &msg);
> > if (ret < 0)
> > return ret;
> >
> > @@ -140,7 +128,6 @@ static int scmi_regulator_of_to_plat(struct udevice *dev)
> > static int scmi_regulator_probe(struct udevice *dev)
> > {
> > struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
> > - struct scmi_regulator_priv *priv = dev_get_priv(dev);
> > struct scmi_voltd_attr_in in = { 0 };
> > struct scmi_voltd_attr_out out = { 0 };
> > struct scmi_msg scmi_msg = {
> > @@ -153,14 +140,14 @@ static int scmi_regulator_probe(struct udevice *dev)
> > };
> > int ret;
> >
> > - ret = devm_scmi_of_get_channel(dev->parent, &priv->channel);
> > + ret = devm_scmi_of_get_channel(dev);
> > if (ret)
> > return ret;
> >
> > /* Check voltage domain is known from SCMI server */
> > in.domain_id = pdata->domain_id;
> >
> > - ret = devm_scmi_process_msg(dev, priv->channel, &scmi_msg);
> > + ret = devm_scmi_process_msg(dev, &scmi_msg);
> > if (ret) {
> > dev_err(dev, "Failed to query voltage domain %u: %d\n",
> > pdata->domain_id, ret);
> > @@ -184,7 +171,6 @@ U_BOOT_DRIVER(scmi_regulator) = {
> > .probe = scmi_regulator_probe,
> > .of_to_plat = scmi_regulator_of_to_plat,
> > .plat_auto = sizeof(struct scmi_regulator_platdata),
> > - .priv_auto = sizeof(struct scmi_regulator_priv *),
> > };
> >
> > static int scmi_regulator_bind(struct udevice *dev)
> > @@ -209,4 +195,5 @@ U_BOOT_DRIVER(scmi_voltage_domain) = {
> > .name = "scmi_voltage_domain",
> > .id = UCLASS_NOP,
> > .bind = scmi_regulator_bind,
> > + .per_child_auto = sizeof(struct scmi_agent_proto_priv *),
> > };
> > diff --git a/drivers/reset/reset-scmi.c b/drivers/reset/reset-scmi.c
> > index 122556162ec3..b76711f0a8fb 100644
> > --- a/drivers/reset/reset-scmi.c
> > +++ b/drivers/reset/reset-scmi.c
> > @@ -13,17 +13,8 @@
> > #include <scmi_protocols.h>
> > #include <asm/types.h>
> >
> > -/**
> > - * struct scmi_reset_priv - Private data for SCMI reset controller
> > - * @channel: Reference to the SCMI channel to use
> > - */
> > -struct scmi_reset_priv {
> > - struct scmi_channel *channel;
> > -};
> > -
> > static int scmi_reset_set_level(struct reset_ctl *rst, bool assert_not_deassert)
> > {
> > - struct scmi_reset_priv *priv = dev_get_priv(rst->dev);
> > struct scmi_rd_reset_in in = {
> > .domain_id = rst->id,
> > .flags = assert_not_deassert ? SCMI_RD_RESET_FLAG_ASSERT : 0,
> > @@ -35,7 +26,7 @@ static int scmi_reset_set_level(struct reset_ctl *rst, bool assert_not_deassert)
> > in, out);
> > int ret;
> >
> > - ret = devm_scmi_process_msg(rst->dev, priv->channel, &msg);
> > + ret = devm_scmi_process_msg(rst->dev, &msg);
> > if (ret)
> > return ret;
> >
> > @@ -54,7 +45,6 @@ static int scmi_reset_deassert(struct reset_ctl *rst)
> >
> > static int scmi_reset_request(struct reset_ctl *rst)
> > {
> > - struct scmi_reset_priv *priv = dev_get_priv(rst->dev);
> > struct scmi_rd_attr_in in = {
> > .domain_id = rst->id,
> > };
> > @@ -68,7 +58,7 @@ static int scmi_reset_request(struct reset_ctl *rst)
> > * We don't really care about the attribute, just check
> > * the reset domain exists.
> > */
> > - ret = devm_scmi_process_msg(rst->dev, priv->channel, &msg);
> > + ret = devm_scmi_process_msg(rst->dev, &msg);
> > if (ret)
> > return ret;
> >
> > @@ -83,9 +73,7 @@ static const struct reset_ops scmi_reset_domain_ops = {
> >
> > static int scmi_reset_probe(struct udevice *dev)
> > {
> > - struct scmi_reset_priv *priv = dev_get_priv(dev);
> > -
> > - return devm_scmi_of_get_channel(dev, &priv->channel);
> > + return devm_scmi_of_get_channel(dev);
> > }
> >
> > U_BOOT_DRIVER(scmi_reset_domain) = {
> > @@ -93,5 +81,4 @@ U_BOOT_DRIVER(scmi_reset_domain) = {
> > .id = UCLASS_RESET,
> > .ops = &scmi_reset_domain_ops,
> > .probe = scmi_reset_probe,
> > - .priv_auto = sizeof(struct scmi_reset_priv *),
> > };
> > diff --git a/include/scmi_agent.h b/include/scmi_agent.h
> > index ee6286366df7..577892029ff8 100644
> > --- a/include/scmi_agent.h
> > +++ b/include/scmi_agent.h
> > @@ -15,6 +15,14 @@
> > struct udevice;
> > struct scmi_channel;
> >
> > +/**
> > + * struct scmi_agent_proto_priv - Private data in device for SCMI agent
> > + * @channel: Reference to the SCMI channel to use
> > + */
> > +struct scmi_agent_proto_priv {
> > + struct scmi_channel *channel;
> > +};
> > +
> > /*
> > * struct scmi_msg - Context of a SCMI message sent and the response received
> > *
> > @@ -49,10 +57,9 @@ struct scmi_msg {
> > * devm_scmi_of_get_channel() - Get SCMI channel handle from SCMI agent DT node
> > *
> > * @dev: Device requesting a channel
> > - * @channel: Output reference to the SCMI channel upon success
> > * @return 0 on success and a negative errno on failure
> > */
> > -int devm_scmi_of_get_channel(struct udevice *dev, struct scmi_channel **channel);
> > +int devm_scmi_of_get_channel(struct udevice *dev);
> >
> > /**
> > * devm_scmi_process_msg() - Send and process an SCMI message
> > @@ -62,12 +69,10 @@ int devm_scmi_of_get_channel(struct udevice *dev, struct scmi_channel **channel)
> > * On return, scmi_msg::out_msg_sz stores the response payload size.
> > *
> > * @dev: SCMI device
> > - * @channel: Communication channel for the device
> > * @msg: Message structure reference
> > * Return: 0 on success and a negative errno on failure
> > */
> > -int devm_scmi_process_msg(struct udevice *dev, struct scmi_channel *channel,
> > - struct scmi_msg *msg);
> > +int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg);
> >
> > /**
> > * scmi_to_linux_errno() - Convert an SCMI error code into a Linux errno code
> > --
> > 2.41.0
^ permalink raw reply [flat|nested] 40+ messages in thread* Re: [PATCH v2 01/12] scmi: refactor the code to hide a channel from devices
2023-08-07 10:03 ` AKASHI Takahiro
@ 2023-08-08 8:04 ` Etienne CARRIERE - foss
0 siblings, 0 replies; 40+ messages in thread
From: Etienne CARRIERE - foss @ 2023-08-08 8:04 UTC (permalink / raw)
To: AKASHI Takahiro, Etienne CARRIERE
Cc: trini@konsulko.com, sjg@chromium.org, u-boot@lists.denx.de
Hello Akashi-san,
> From: AKASHI Takahiro
> Sent: Monday, August 7, 2023 12:03 PM
>
> Hi Etienne,
>
> On Thu, Aug 03, 2023 at 09:24:51AM +0000, Etienne CARRIERE wrote:
> > Hello Takahiro-san,
> >
> > Sorry again for this late feedback.
> > Testing the series against stm32mp135f-dk board which is using SCMI resources, I see the board fails to boot.
> >
> > > From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > > To: trini@konsulko.com, sjg@chromium.org
> > > Cc: etienne.carriere@st.com, u-boot@lists.denx.de,
> > > AKASHI Takahiro <takahiro.akashi@linaro.org>
> > > Subject: [PATCH v2 01/12] scmi: refactor the code to hide a channel from devices
> > > Date: Wed, 26 Jul 2023 17:37:57 +0900 [thread overview]
> > > Message-ID: <20230726083808.140780-2-takahiro.akashi@linaro.org> (raw)
> > > In-Reply-To: <20230726083808.140780-1-takahiro.akashi@linaro.org>
> > >
> > > The commit 85dc58289238 ("firmware: scmi: prepare uclass to pass channel
> > > reference") added an explicit parameter, channel, but it seems to make
> > > the code complex.
> > >
> > > Hiding this parameter will allow for adding a generic (protocol-agnostic)
> > > helper function, i.e. for PROTOCOL_VERSION, in a later patch.
> > >
> > > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > >
> > > ---
> > > v2
> > > * new patch
> > > ---
> > > drivers/clk/clk_scmi.c | 27 ++-------
> > > drivers/firmware/scmi/scmi_agent-uclass.c | 74 ++++++++++++++++++-----
> > > drivers/power/regulator/scmi_regulator.c | 27 +++------
> > > drivers/reset/reset-scmi.c | 19 +-----
> > > include/scmi_agent.h | 15 +++--
> > > 5 files changed, 86 insertions(+), 76 deletions(-)
> > >
> > > diff --git a/drivers/clk/clk_scmi.c b/drivers/clk/clk_scmi.c
> > > index d172fed24c9d..34a49363a51a 100644
> > > --- a/drivers/clk/clk_scmi.c
> > > +++ b/drivers/clk/clk_scmi.c
> > > @@ -13,17 +13,8 @@
> > > #include <asm/types.h>
> > > #include <linux/clk-provider.h>
> > >
> > > -/**
> > > - * struct scmi_clk_priv - Private data for SCMI clocks
> > > - * @channel: Reference to the SCMI channel to use
> > > - */
> > > -struct scmi_clk_priv {
> > > - struct scmi_channel *channel;
> > > -};
> > > -
> > > static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks)
> > > {
> > > - struct scmi_clk_priv *priv = dev_get_priv(dev);
> > > struct scmi_clk_protocol_attr_out out;
> > > struct scmi_msg msg = {
> > > .protocol_id = SCMI_PROTOCOL_ID_CLOCK,
> > > @@ -33,7 +24,7 @@ static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks)
> > > };
> > > int ret;
> > >
> > > - ret = devm_scmi_process_msg(dev, priv->channel, &msg);
> > > + ret = devm_scmi_process_msg(dev, &msg);
> > > if (ret)
> > > return ret;
> > >
> > > @@ -44,7 +35,6 @@ static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks)
> > >
> > > static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name)
> > > {
> > > - struct scmi_clk_priv *priv = dev_get_priv(dev);
> > > struct scmi_clk_attribute_in in = {
> > > .clock_id = clkid,
> > > };
> > > @@ -59,7 +49,7 @@ static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name)
> > > };
> > > int ret;
> > >
> > > - ret = devm_scmi_process_msg(dev, priv->channel, &msg);
> > > + ret = devm_scmi_process_msg(dev, &msg);
> > > if (ret)
> > > return ret;
> > >
> > > @@ -70,7 +60,6 @@ static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name)
> > >
> > > static int scmi_clk_gate(struct clk *clk, int enable)
> > > {
> > > - struct scmi_clk_priv *priv = dev_get_priv(clk->dev);
> > > struct scmi_clk_state_in in = {
> > > .clock_id = clk->id,
> > > .attributes = enable,
> > > @@ -81,7 +70,7 @@ static int scmi_clk_gate(struct clk *clk, int enable)
> > > in, out);
> > > int ret;
> > >
> > > - ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg);
> > > + ret = devm_scmi_process_msg(clk->dev, &msg);
> > > if (ret)
> > > return ret;
> > >
> > > @@ -100,7 +89,6 @@ static int scmi_clk_disable(struct clk *clk)
> > >
> > > static ulong scmi_clk_get_rate(struct clk *clk)
> > > {
> > > - struct scmi_clk_priv *priv = dev_get_priv(clk->dev);
> > > struct scmi_clk_rate_get_in in = {
> > > .clock_id = clk->id,
> > > };
> > > @@ -110,7 +98,7 @@ static ulong scmi_clk_get_rate(struct clk *clk)
> > > in, out);
> > > int ret;
> > >
> > > - ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg);
> > > + ret = devm_scmi_process_msg(clk->dev, &msg);
> > > if (ret < 0)
> > > return ret;
> > >
> > > @@ -123,7 +111,6 @@ static ulong scmi_clk_get_rate(struct clk *clk)
> > >
> > > static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
> > > {
> > > - struct scmi_clk_priv *priv = dev_get_priv(clk->dev);
> > > struct scmi_clk_rate_set_in in = {
> > > .clock_id = clk->id,
> > > .flags = SCMI_CLK_RATE_ROUND_CLOSEST,
> > > @@ -136,7 +123,7 @@ static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
> > > in, out);
> > > int ret;
> > >
> > > - ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg);
> > > + ret = devm_scmi_process_msg(clk->dev, &msg);
> > > if (ret < 0)
> > > return ret;
> > >
> > > @@ -149,12 +136,11 @@ static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
> > >
> > > static int scmi_clk_probe(struct udevice *dev)
> > > {
> > > - struct scmi_clk_priv *priv = dev_get_priv(dev);
> > > struct clk *clk;
> > > size_t num_clocks, i;
> > > int ret;
> > >
> > > - ret = devm_scmi_of_get_channel(dev, &priv->channel);
> > > + ret = devm_scmi_of_get_channel(dev);
> > > if (ret)
> > > return ret;
> > >
> > > @@ -205,5 +191,4 @@ U_BOOT_DRIVER(scmi_clock) = {
> > > .id = UCLASS_CLK,
> > > .ops = &scmi_clk_ops,
> > > .probe = scmi_clk_probe,
> > > - .priv_auto = sizeof(struct scmi_clk_priv *),
> > > };
> > > diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c
> > > index 02de692d66f3..39cf15c88f75 100644
> > > --- a/drivers/firmware/scmi/scmi_agent-uclass.c
> > > +++ b/drivers/firmware/scmi/scmi_agent-uclass.c
> > > @@ -8,6 +8,7 @@
> > > #include <common.h>
> > > #include <dm.h>
> > > #include <errno.h>
> > > +#include <scmi_agent.h>
> > > #include <scmi_agent-uclass.h>
> > > #include <scmi_protocols.h>
> > > #include <dm/device_compat.h>
> > > @@ -129,43 +130,88 @@ static const struct scmi_agent_ops *transport_dev_ops(struct udevice *dev)
> > > return (const struct scmi_agent_ops *)dev->driver->ops;
> > > }
> > >
> > > -int devm_scmi_of_get_channel(struct udevice *dev, struct scmi_channel **channel)
> > > +/**
> > > + * scmi_of_get_channel() - Get SCMI channel handle
> > > + *
> > > + * @dev: SCMI agent device
> > > + * @channel: Output reference to the SCMI channel upon success
> > > + *
> > > + * On return, @channel will be set.
> > > + * Return 0 on success and a negative errno on failure
> > > + */
> > > +static int scmi_of_get_channel(struct udevice *dev, struct scmi_channel **channel)
> > > +{
> > > + const struct scmi_agent_ops *ops;
> > > +
> > > + ops = transport_dev_ops(dev);
> > > + if (ops->of_get_channel)
> > > + return ops->of_get_channel(dev, channel);
> > > + else
> > > + return -EPROTONOSUPPORT;
> > > +}
> > > +
> > > +int devm_scmi_of_get_channel(struct udevice *dev)
> > > {
> > > struct udevice *parent;
> > > + struct scmi_agent_proto_priv *priv = dev_get_parent_priv(dev);
> >
> > This parent lookup does not match when CONFIG_CLK_CCF is enabled. When so,
> > the scmi clock device is on the clock itself but a child udevice of some
> > udevice held by the common clock framework (CCF).
> > Platforms from the stm32mp13 family do enable SCMI clock and CCF.
>
> I tested my patch on sandbox, where CCF is also enabled,
> and "ut dm scmi_clocks" is passed without any error.
> So I'm not sure if the point you mentioned above is a root cause.
Ok, i'll better investigate where stm32mp13 gets lost.
and why sandbox passes wher I would expect it to fail.
Best regards,
etienne
>
> -Takahiro Akashi
>
> > It can propose a way to go, using find_scmi_transport_device() to provide
> > the agent's 1st child private data as an output argument:
> > //patch-start
> > -static struct udevice *find_scmi_transport_device(struct udevice *dev)
> > +static struct udevice *
> > +find_scmi_transport_device(struct udevice *dev,
> > + struct scmi_agent_proto_priv **priv)
> > {
> > struct udevice *parent = dev;
> > + struct scmi_agent_proto_priv *parent_priv;
> >
> > do {
> > + parent_priv = dev_get_parent_priv(parent);
> > parent = dev_get_parent(parent);
> > } while (parent && device_get_uclass_id(parent) != UCLASS_SCMI_AGENT);
> >
> > if (!parent)
> > dev_err(dev, "Invalid SCMI device, agent not found\n");
> > + else if (priv)
> > + *priv = parent_priv;
> >
> > return parent;
> > }
> > //end patch
> >
> > Tested OK on stm32mp13 with the remaining patch series applied (minor conflics).
> >
> > BR,
> > etienne
> >
> >
> > > + int ret;
> > >
> > > parent = find_scmi_transport_device(dev);
> > > if (!parent)
> > > return -ENODEV;
> > >
> > > - if (transport_dev_ops(parent)->of_get_channel)
> > > - return transport_dev_ops(parent)->of_get_channel(parent, channel);
> > > + ret = scmi_of_get_channel(parent, &priv->channel);
> > > + if (ret == -EPROTONOSUPPORT) {
> > > + /* Drivers without a get_channel operator don't need a channel ref */
> > > + priv->channel = NULL;
> > >
> > > - /* Drivers without a get_channel operator don't need a channel ref */
> > > - *channel = NULL;
> > > + return 0;
> > > + }
> > >
> > > - return 0;
> > > + return ret;
> > > }
> > >
> > > -int devm_scmi_process_msg(struct udevice *dev, struct scmi_channel *channel,
> > > - struct scmi_msg *msg)
> > > +/**
> > > + * scmi_process_msg() - Send and process an SCMI message
> > > + *
> > > + * Send a message to an SCMI server.
> > > + * Caller sets scmi_msg::out_msg_sz to the output message buffer size.
> > > + *
> > > + * @dev: SCMI agent device
> > > + * @channel: Communication channel for the device
> > > + * @msg: Message structure reference
> > > + *
> > > + * On return, scmi_msg::out_msg_sz stores the response payload size.
> > > + * Return: 0 on success and a negative errno on failure
> > > + */
> > > +static int scmi_process_msg(struct udevice *dev, struct scmi_channel *channel,
> > > + struct scmi_msg *msg)
> > > {
> > > const struct scmi_agent_ops *ops;
> > > +
> > > + ops = transport_dev_ops(dev);
> > > + if (ops->process_msg)
> > > + return ops->process_msg(dev, channel, msg);
> > > + else
> > > + return -EPROTONOSUPPORT;
> > > +}
> > > +
> > > +int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg)
> > > +{
> > > struct udevice *parent;
> > > + struct scmi_agent_proto_priv *priv = dev_get_parent_priv(dev);
> > >
> > > parent = find_scmi_transport_device(dev);
> > > if (!parent)
> > > return -ENODEV;
> > >
> > > - ops = transport_dev_ops(parent);
> > > -
> > > - if (ops->process_msg)
> > > - return ops->process_msg(parent, channel, msg);
> > > -
> > > - return -EPROTONOSUPPORT;
> > > + return scmi_process_msg(parent, priv->channel, msg);
> > > }
> > >
> > > UCLASS_DRIVER(scmi_agent) = {
> > > .id = UCLASS_SCMI_AGENT,
> > > .name = "scmi_agent",
> > > .post_bind = scmi_bind_protocols,
> > > + .per_device_plat_auto = sizeof(struct scmi_agent_priv),
> >
> > Typo: this added line belong to patch 04/12.
> >
> > Regards,
> > Etienne
> >
> > > + .per_child_auto = sizeof(struct scmi_agent_proto_priv *),
> > > };
> > > diff --git a/drivers/power/regulator/scmi_regulator.c b/drivers/power/regulator/scmi_regulator.c
> > > index 801148036ff6..08918b20872c 100644
> > > --- a/drivers/power/regulator/scmi_regulator.c
> > > +++ b/drivers/power/regulator/scmi_regulator.c
> > > @@ -25,18 +25,9 @@ struct scmi_regulator_platdata {
> > > u32 domain_id;
> > > };
> > >
> > > -/**
> > > - * struct scmi_regulator_priv - Private data for SCMI voltage regulator
> > > - * @channel: Reference to the SCMI channel to use
> > > - */
> > > -struct scmi_regulator_priv {
> > > - struct scmi_channel *channel;
> > > -};
> > > -
> > > static int scmi_voltd_set_enable(struct udevice *dev, bool enable)
> > > {
> > > struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
> > > - struct scmi_regulator_priv *priv = dev_get_priv(dev);
> > > struct scmi_voltd_config_set_in in = {
> > > .domain_id = pdata->domain_id,
> > > .config = enable ? SCMI_VOLTD_CONFIG_ON : SCMI_VOLTD_CONFIG_OFF,
> > > @@ -47,7 +38,7 @@ static int scmi_voltd_set_enable(struct udevice *dev, bool enable)
> > > in, out);
> > > int ret;
> > >
> > > - ret = devm_scmi_process_msg(dev, priv->channel, &msg);
> > > + ret = devm_scmi_process_msg(dev, &msg);
> > > if (ret)
> > > return ret;
> > >
> > > @@ -57,7 +48,6 @@ static int scmi_voltd_set_enable(struct udevice *dev, bool enable)
> > > static int scmi_voltd_get_enable(struct udevice *dev)
> > > {
> > > struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
> > > - struct scmi_regulator_priv *priv = dev_get_priv(dev);
> > > struct scmi_voltd_config_get_in in = {
> > > .domain_id = pdata->domain_id,
> > > };
> > > @@ -67,7 +57,7 @@ static int scmi_voltd_get_enable(struct udevice *dev)
> > > in, out);
> > > int ret;
> > >
> > > - ret = devm_scmi_process_msg(dev, priv->channel, &msg);
> > > + ret = devm_scmi_process_msg(dev, &msg);
> > > if (ret < 0)
> > > return ret;
> > >
> > > @@ -80,7 +70,6 @@ static int scmi_voltd_get_enable(struct udevice *dev)
> > >
> > > static int scmi_voltd_set_voltage_level(struct udevice *dev, int uV)
> > > {
> > > - struct scmi_regulator_priv *priv = dev_get_priv(dev);
> > > struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
> > > struct scmi_voltd_level_set_in in = {
> > > .domain_id = pdata->domain_id,
> > > @@ -92,7 +81,7 @@ static int scmi_voltd_set_voltage_level(struct udevice *dev, int uV)
> > > in, out);
> > > int ret;
> > >
> > > - ret = devm_scmi_process_msg(dev, priv->channel, &msg);
> > > + ret = devm_scmi_process_msg(dev, &msg);
> > > if (ret < 0)
> > > return ret;
> > >
> > > @@ -101,7 +90,6 @@ static int scmi_voltd_set_voltage_level(struct udevice *dev, int uV)
> > >
> > > static int scmi_voltd_get_voltage_level(struct udevice *dev)
> > > {
> > > - struct scmi_regulator_priv *priv = dev_get_priv(dev);
> > > struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
> > > struct scmi_voltd_level_get_in in = {
> > > .domain_id = pdata->domain_id,
> > > @@ -112,7 +100,7 @@ static int scmi_voltd_get_voltage_level(struct udevice *dev)
> > > in, out);
> > > int ret;
> > >
> > > - ret = devm_scmi_process_msg(dev, priv->channel, &msg);
> > > + ret = devm_scmi_process_msg(dev, &msg);
> > > if (ret < 0)
> > > return ret;
> > >
> > > @@ -140,7 +128,6 @@ static int scmi_regulator_of_to_plat(struct udevice *dev)
> > > static int scmi_regulator_probe(struct udevice *dev)
> > > {
> > > struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
> > > - struct scmi_regulator_priv *priv = dev_get_priv(dev);
> > > struct scmi_voltd_attr_in in = { 0 };
> > > struct scmi_voltd_attr_out out = { 0 };
> > > struct scmi_msg scmi_msg = {
> > > @@ -153,14 +140,14 @@ static int scmi_regulator_probe(struct udevice *dev)
> > > };
> > > int ret;
> > >
> > > - ret = devm_scmi_of_get_channel(dev->parent, &priv->channel);
> > > + ret = devm_scmi_of_get_channel(dev);
> > > if (ret)
> > > return ret;
> > >
> > > /* Check voltage domain is known from SCMI server */
> > > in.domain_id = pdata->domain_id;
> > >
> > > - ret = devm_scmi_process_msg(dev, priv->channel, &scmi_msg);
> > > + ret = devm_scmi_process_msg(dev, &scmi_msg);
> > > if (ret) {
> > > dev_err(dev, "Failed to query voltage domain %u: %d\n",
> > > pdata->domain_id, ret);
> > > @@ -184,7 +171,6 @@ U_BOOT_DRIVER(scmi_regulator) = {
> > > .probe = scmi_regulator_probe,
> > > .of_to_plat = scmi_regulator_of_to_plat,
> > > .plat_auto = sizeof(struct scmi_regulator_platdata),
> > > - .priv_auto = sizeof(struct scmi_regulator_priv *),
> > > };
> > >
> > > static int scmi_regulator_bind(struct udevice *dev)
> > > @@ -209,4 +195,5 @@ U_BOOT_DRIVER(scmi_voltage_domain) = {
> > > .name = "scmi_voltage_domain",
> > > .id = UCLASS_NOP,
> > > .bind = scmi_regulator_bind,
> > > + .per_child_auto = sizeof(struct scmi_agent_proto_priv *),
> > > };
> > > diff --git a/drivers/reset/reset-scmi.c b/drivers/reset/reset-scmi.c
> > > index 122556162ec3..b76711f0a8fb 100644
> > > --- a/drivers/reset/reset-scmi.c
> > > +++ b/drivers/reset/reset-scmi.c
> > > @@ -13,17 +13,8 @@
> > > #include <scmi_protocols.h>
> > > #include <asm/types.h>
> > >
> > > -/**
> > > - * struct scmi_reset_priv - Private data for SCMI reset controller
> > > - * @channel: Reference to the SCMI channel to use
> > > - */
> > > -struct scmi_reset_priv {
> > > - struct scmi_channel *channel;
> > > -};
> > > -
> > > static int scmi_reset_set_level(struct reset_ctl *rst, bool assert_not_deassert)
> > > {
> > > - struct scmi_reset_priv *priv = dev_get_priv(rst->dev);
> > > struct scmi_rd_reset_in in = {
> > > .domain_id = rst->id,
> > > .flags = assert_not_deassert ? SCMI_RD_RESET_FLAG_ASSERT : 0,
> > > @@ -35,7 +26,7 @@ static int scmi_reset_set_level(struct reset_ctl *rst, bool assert_not_deassert)
> > > in, out);
> > > int ret;
> > >
> > > - ret = devm_scmi_process_msg(rst->dev, priv->channel, &msg);
> > > + ret = devm_scmi_process_msg(rst->dev, &msg);
> > > if (ret)
> > > return ret;
> > >
> > > @@ -54,7 +45,6 @@ static int scmi_reset_deassert(struct reset_ctl *rst)
> > >
> > > static int scmi_reset_request(struct reset_ctl *rst)
> > > {
> > > - struct scmi_reset_priv *priv = dev_get_priv(rst->dev);
> > > struct scmi_rd_attr_in in = {
> > > .domain_id = rst->id,
> > > };
> > > @@ -68,7 +58,7 @@ static int scmi_reset_request(struct reset_ctl *rst)
> > > * We don't really care about the attribute, just check
> > > * the reset domain exists.
> > > */
> > > - ret = devm_scmi_process_msg(rst->dev, priv->channel, &msg);
> > > + ret = devm_scmi_process_msg(rst->dev, &msg);
> > > if (ret)
> > > return ret;
> > >
> > > @@ -83,9 +73,7 @@ static const struct reset_ops scmi_reset_domain_ops = {
> > >
> > > static int scmi_reset_probe(struct udevice *dev)
> > > {
> > > - struct scmi_reset_priv *priv = dev_get_priv(dev);
> > > -
> > > - return devm_scmi_of_get_channel(dev, &priv->channel);
> > > + return devm_scmi_of_get_channel(dev);
> > > }
> > >
> > > U_BOOT_DRIVER(scmi_reset_domain) = {
> > > @@ -93,5 +81,4 @@ U_BOOT_DRIVER(scmi_reset_domain) = {
> > > .id = UCLASS_RESET,
> > > .ops = &scmi_reset_domain_ops,
> > > .probe = scmi_reset_probe,
> > > - .priv_auto = sizeof(struct scmi_reset_priv *),
> > > };
> > > diff --git a/include/scmi_agent.h b/include/scmi_agent.h
> > > index ee6286366df7..577892029ff8 100644
> > > --- a/include/scmi_agent.h
> > > +++ b/include/scmi_agent.h
> > > @@ -15,6 +15,14 @@
> > > struct udevice;
> > > struct scmi_channel;
> > >
> > > +/**
> > > + * struct scmi_agent_proto_priv - Private data in device for SCMI agent
> > > + * @channel: Reference to the SCMI channel to use
> > > + */
> > > +struct scmi_agent_proto_priv {
> > > + struct scmi_channel *channel;
> > > +};
> > > +
> > > /*
> > > * struct scmi_msg - Context of a SCMI message sent and the response received
> > > *
> > > @@ -49,10 +57,9 @@ struct scmi_msg {
> > > * devm_scmi_of_get_channel() - Get SCMI channel handle from SCMI agent DT node
> > > *
> > > * @dev: Device requesting a channel
> > > - * @channel: Output reference to the SCMI channel upon success
> > > * @return 0 on success and a negative errno on failure
> > > */
> > > -int devm_scmi_of_get_channel(struct udevice *dev, struct scmi_channel **channel);
> > > +int devm_scmi_of_get_channel(struct udevice *dev);
> > >
> > > /**
> > > * devm_scmi_process_msg() - Send and process an SCMI message
> > > @@ -62,12 +69,10 @@ int devm_scmi_of_get_channel(struct udevice *dev, struct scmi_channel **channel)
> > > * On return, scmi_msg::out_msg_sz stores the response payload size.
> > > *
> > > * @dev: SCMI device
> > > - * @channel: Communication channel for the device
> > > * @msg: Message structure reference
> > > * Return: 0 on success and a negative errno on failure
> > > */
> > > -int devm_scmi_process_msg(struct udevice *dev, struct scmi_channel *channel,
> > > - struct scmi_msg *msg);
> > > +int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg);
> > >
> > > /**
> > > * scmi_to_linux_errno() - Convert an SCMI error code into a Linux errno code
> > > --
> > > 2.41.0
>
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v2 02/12] firmware: scmi: implement SCMI base protocol
2023-07-26 8:37 [PATCH v2 00/12] firmware: scmi: add SCMI base protocol support AKASHI Takahiro
2023-07-26 8:37 ` [PATCH v2 01/12] scmi: refactor the code to hide a channel from devices AKASHI Takahiro
@ 2023-07-26 8:37 ` AKASHI Takahiro
2023-07-27 0:50 ` Simon Glass
2023-08-03 9:35 ` Etienne CARRIERE
2023-07-26 8:37 ` [PATCH v2 03/12] firmware: scmi: move scmi_bind_protocols() backward AKASHI Takahiro
` (9 subsequent siblings)
11 siblings, 2 replies; 40+ messages in thread
From: AKASHI Takahiro @ 2023-07-26 8:37 UTC (permalink / raw)
To: trini, sjg; +Cc: etienne.carriere, u-boot, AKASHI Takahiro
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>
---
v2
* add helper functions, removing direct uses of ops
* add function descriptions for each of functions in ops
---
drivers/firmware/scmi/Makefile | 1 +
drivers/firmware/scmi/base.c | 637 +++++++++++++++++++++++++++++++++
include/dm/uclass-id.h | 1 +
include/scmi_protocols.h | 345 ++++++++++++++++++
4 files changed, 984 insertions(+)
create mode 100644 drivers/firmware/scmi/base.c
diff --git a/drivers/firmware/scmi/Makefile b/drivers/firmware/scmi/Makefile
index b2ff483c75a1..1a23d4981709 100644
--- a/drivers/firmware/scmi/Makefile
+++ b/drivers/firmware/scmi/Makefile
@@ -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
diff --git a/drivers/firmware/scmi/base.c b/drivers/firmware/scmi/base.c
new file mode 100644
index 000000000000..2b61fa650d15
--- /dev/null
+++ b/drivers/firmware/scmi/base.c
@@ -0,0 +1,637 @@
+// 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>
+
+/**
+ * scmi_generic_protocol_version - get protocol version
+ * @dev: SCMI device
+ * @id: SCMI protocol ID
+ * @version: Pointer to SCMI protocol version
+ *
+ * Obtain the protocol version number in @version.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+int scmi_generic_protocol_version(struct udevice *dev,
+ enum scmi_std_protocol id, u32 *version)
+{
+ struct scmi_protocol_version_out out;
+ struct scmi_msg msg = {
+ .protocol_id = id,
+ .message_id = SCMI_PROTOCOL_VERSION,
+ .out_msg = (u8 *)&out,
+ .out_msg_sz = sizeof(out),
+ };
+ int ret;
+
+ ret = devm_scmi_process_msg(dev, &msg);
+ if (ret)
+ return ret;
+ if (out.status)
+ return scmi_to_linux_errno(out.status);
+
+ *version = out.version;
+
+ return 0;
+}
+
+/**
+ * scmi_base_protocol_version_int - get Base protocol version
+ * @dev: SCMI device
+ * @version: Pointer to SCMI protocol version
+ *
+ * Obtain the protocol version number in @version for Base protocol.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+static int scmi_base_protocol_version_int(struct udevice *dev, u32 *version)
+{
+ return scmi_generic_protocol_version(dev, SCMI_PROTOCOL_ID_BASE,
+ version);
+}
+
+/**
+ * scmi_protocol_attrs_int - get protocol attributes
+ * @dev: SCMI device
+ * @num_agents: Number of SCMI agents
+ * @num_protocols: Number of SCMI 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_int(struct udevice *dev, u32 *num_agents,
+ u32 *num_protocols)
+{
+ 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, &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_int - get message-specific attributes
+ * @dev: SCMI device
+ * @message_id: SCMI message ID
+ * @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_int(struct udevice *dev, u32 message_id,
+ u32 *attributes)
+{
+ 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, &msg);
+ if (ret)
+ return ret;
+ if (out.status)
+ return scmi_to_linux_errno(out.status);
+
+ *attributes = out.attributes;
+
+ return 0;
+}
+
+/**
+ * scmi_base_discover_vendor_int - get vendor name
+ * @dev: SCMI device
+ * @vendor: Vendor name
+ *
+ * Obtain the vendor's name in @vendor.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+static int scmi_base_discover_vendor_int(struct udevice *dev, u8 *vendor)
+{
+ 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, &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_int - get sub-vendor name
+ * @dev: SCMI 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_int(struct udevice *dev,
+ u8 *sub_vendor)
+{
+ 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, &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_int - get implementation version
+ * @dev: SCMI 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_int(struct udevice *dev,
+ u32 *impl_version)
+{
+ 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, &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_int - get list of protocols
+ * @dev: SCMI device
+ * @protocols: Pointer to array of SCMI 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_int(struct udevice *dev,
+ u8 **protocols)
+{
+ 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_base_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, &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_int - identify agent
+ * @dev: SCMI device
+ * @agent_id: SCMI agent ID
+ * @ret_agent_id: Pointer to SCMI agent ID
+ * @name: SCMI 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_int(struct udevice *dev, u32 agent_id,
+ u32 *ret_agent_id, u8 *name)
+{
+ 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, &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_set_device_permissions_int - configure access permission to device
+ * @dev: SCMI device
+ * @agent_id: SCMI agent ID
+ * @device_id: ID 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_int(struct udevice *dev, u32 agent_id,
+ u32 device_id, u32 flags)
+{
+ 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, &msg);
+ if (ret)
+ return ret;
+ if (status)
+ return scmi_to_linux_errno(status);
+
+ return 0;
+}
+
+/**
+ * scmi_base_set_protocol_permissions_int - configure access permission to
+ protocol on device
+ * @dev: SCMI device
+ * @agent_id: SCMI agent ID
+ * @device_id: ID of device to access
+ * @command_id: SCMI command ID
+ * @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_int(struct udevice *dev,
+ u32 agent_id, u32 device_id,
+ u32 command_id, u32 flags)
+{
+ 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, &msg);
+ if (ret)
+ return ret;
+ if (status)
+ return scmi_to_linux_errno(status);
+
+ return 0;
+}
+
+/**
+ * scmi_base_reset_agent_configuration_int - reset resource settings
+ * @dev: SCMI device
+ * @agent_id: SCMI agent ID
+ * @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_int(struct udevice *dev,
+ u32 agent_id, u32 flags)
+{
+ 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, &msg);
+ if (ret)
+ return ret;
+ if (status)
+ return scmi_to_linux_errno(status);
+
+ return 0;
+}
+
+/**
+ * scmi_base_probe - probe base protocol device
+ * @dev: SCMI 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)
+{
+ int ret;
+
+ ret = devm_scmi_of_get_channel(dev);
+ if (ret) {
+ dev_err(dev, "get_channel failed\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+struct scmi_base_ops scmi_base_ops = {
+ /* Commands */
+ .protocol_version = scmi_base_protocol_version_int,
+ .protocol_attrs = scmi_protocol_attrs_int,
+ .protocol_message_attrs = scmi_protocol_message_attrs_int,
+ .base_discover_vendor = scmi_base_discover_vendor_int,
+ .base_discover_sub_vendor = scmi_base_discover_sub_vendor_int,
+ .base_discover_impl_version = scmi_base_discover_impl_version_int,
+ .base_discover_list_protocols = scmi_base_discover_list_protocols_int,
+ .base_discover_agent = scmi_base_discover_agent_int,
+ .base_notify_errors = NULL,
+ .base_set_device_permissions = scmi_base_set_device_permissions_int,
+ .base_set_protocol_permissions = scmi_base_set_protocol_permissions_int,
+ .base_reset_agent_configuration =
+ scmi_base_reset_agent_configuration_int,
+};
+
+int scmi_base_protocol_version(struct udevice *dev, u32 *version)
+{
+ const struct scmi_base_ops *ops = device_get_ops(dev);
+
+ if (ops->protocol_version)
+ return (*ops->protocol_version)(dev, version);
+
+ return -EOPNOTSUPP;
+}
+
+int scmi_base_protocol_attrs(struct udevice *dev, u32 *num_agents,
+ u32 *num_protocols)
+{
+ const struct scmi_base_ops *ops = device_get_ops(dev);
+
+ if (ops->protocol_attrs)
+ return (*ops->protocol_attrs)(dev, num_agents, num_protocols);
+
+ return -EOPNOTSUPP;
+}
+
+int scmi_base_protocol_message_attrs(struct udevice *dev, u32 message_id,
+ u32 *attributes)
+{
+ const struct scmi_base_ops *ops = device_get_ops(dev);
+
+ if (ops->protocol_message_attrs)
+ return (*ops->protocol_message_attrs)(dev, message_id,
+ attributes);
+
+ return -EOPNOTSUPP;
+}
+
+int scmi_base_discover_vendor(struct udevice *dev, u8 *vendor)
+{
+ const struct scmi_base_ops *ops = device_get_ops(dev);
+
+ if (ops->base_discover_vendor)
+ return (*ops->base_discover_vendor)(dev, vendor);
+
+ return -EOPNOTSUPP;
+}
+
+int scmi_base_discover_sub_vendor(struct udevice *dev, u8 *sub_vendor)
+{
+ const struct scmi_base_ops *ops = device_get_ops(dev);
+
+ if (ops->base_discover_sub_vendor)
+ return (*ops->base_discover_sub_vendor)(dev, sub_vendor);
+
+ return -EOPNOTSUPP;
+}
+
+int scmi_base_discover_impl_version(struct udevice *dev, u32 *impl_version)
+{
+ const struct scmi_base_ops *ops = device_get_ops(dev);
+
+ if (ops->base_discover_impl_version)
+ return (*ops->base_discover_impl_version)(dev, impl_version);
+
+ return -EOPNOTSUPP;
+}
+
+int scmi_base_discover_list_protocols(struct udevice *dev, u8 **protocols)
+{
+ const struct scmi_base_ops *ops = device_get_ops(dev);
+
+ if (ops->base_discover_list_protocols)
+ return (*ops->base_discover_list_protocols)(dev, protocols);
+
+ return -EOPNOTSUPP;
+}
+
+int scmi_base_discover_agent(struct udevice *dev, u32 agent_id,
+ u32 *ret_agent_id, u8 *name)
+{
+ const struct scmi_base_ops *ops = device_get_ops(dev);
+
+ if (ops->base_discover_agent)
+ return (*ops->base_discover_agent)(dev, agent_id, ret_agent_id,
+ name);
+
+ return -EOPNOTSUPP;
+}
+
+int scmi_base_notify_errors(struct udevice *dev, u32 enable)
+{
+ const struct scmi_base_ops *ops = device_get_ops(dev);
+
+ if (ops->base_notify_errors)
+ return (*ops->base_notify_errors)(dev, enable);
+
+ return -EOPNOTSUPP;
+}
+
+int scmi_base_set_device_permissions(struct udevice *dev, u32 agent_id,
+ u32 device_id, u32 flags)
+{
+ const struct scmi_base_ops *ops = device_get_ops(dev);
+
+ if (ops->base_set_device_permissions)
+ return (*ops->base_set_device_permissions)(dev, agent_id,
+ device_id, flags);
+
+ return -EOPNOTSUPP;
+}
+
+int scmi_base_set_protocol_permissions(struct udevice *dev,
+ u32 agent_id, u32 device_id,
+ u32 command_id, u32 flags)
+{
+ const struct scmi_base_ops *ops = device_get_ops(dev);
+
+ if (ops->base_set_protocol_permissions)
+ return (*ops->base_set_protocol_permissions)(dev, agent_id,
+ device_id,
+ command_id,
+ flags);
+
+ return -EOPNOTSUPP;
+}
+
+int scmi_base_reset_agent_configuration(struct udevice *dev, u32 agent_id,
+ u32 flags)
+{
+ const struct scmi_base_ops *ops = device_get_ops(dev);
+
+ if (ops->base_reset_agent_configuration)
+ return (*ops->base_reset_agent_configuration)(dev, agent_id,
+ flags);
+
+ return -EOPNOTSUPP;
+}
+
+U_BOOT_DRIVER(scmi_base_drv) = {
+ .id = UCLASS_SCMI_BASE,
+ .name = "scmi_base_drv",
+ .ops = &scmi_base_ops,
+ .probe = scmi_base_probe,
+};
+
+UCLASS_DRIVER(scmi_base) = {
+ .id = UCLASS_SCMI_BASE,
+ .name = "scmi_base",
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 307ad6931ca7..f7a110852321 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -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 */
diff --git a/include/scmi_protocols.h b/include/scmi_protocols.h
index a220cb2a91ad..64fd740472b5 100644
--- a/include/scmi_protocols.h
+++ b/include/scmi_protocols.h
@@ -49,6 +49,351 @@ enum scmi_discovery_id {
SCMI_PROTOCOL_MESSAGE_ATTRIBUTES = 0x2,
};
+/*
+ * SCMI Base Protocol
+ */
+#define SCMI_BASE_PROTOCOL_VERSION 0x20000
+
+enum scmi_base_message_id {
+ 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,
+};
+
+#define SCMI_BASE_NAME_LENGTH_MAX 16
+
+/**
+ * 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: Name 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 SCMI protocols in @protocol
+ * @protocols: Array of packed SCMI 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: SCMI agent ID
+ * @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: SCMI agent ID
+ * @device_id: device ID
+ * @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: SCMI agent ID
+ * @device_id: device ID
+ * @command_id: command ID
+ * @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: SCMI agent ID
+ * @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
+ */
+struct scmi_base_ops {
+ /**
+ * protocol_version - get Base protocol version
+ * @dev: SCMI device
+ * @version: Pointer to SCMI protocol version
+ *
+ * Obtain the protocol version number in @version for Base protocol.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+ int (*protocol_version)(struct udevice *dev, u32 *version);
+ /**
+ * protocol_attrs - get protocol attributes
+ * @dev: SCMI device
+ * @num_agents: Number of SCMI agents
+ * @num_protocols: Number of SCMI 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
+ */
+ int (*protocol_attrs)(struct udevice *dev, u32 *num_agents,
+ u32 *num_protocols);
+ /**
+ * protocol_message_attrs - get message-specific attributes
+ * @dev: SCMI device
+ * @message_id: SCMI message ID
+ * @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
+ */
+ int (*protocol_message_attrs)(struct udevice *dev, u32 message_id,
+ u32 *attributes);
+ /**
+ * base_discover_vendor - get vendor name
+ * @dev: SCMI device
+ * @vendor: Vendor name
+ *
+ * Obtain the vendor's name in @vendor.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+ int (*base_discover_vendor)(struct udevice *dev, u8 *vendor);
+ /**
+ * base_discover_sub_vendor - get sub-vendor name
+ * @dev: SCMI device
+ * @sub_vendor: Sub-vendor name
+ *
+ * Obtain the sub-vendor's name in @sub_vendor.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+ int (*base_discover_sub_vendor)(struct udevice *dev, u8 *sub_vendor);
+ /**
+ * base_discover_impl_version - get implementation version
+ * @dev: SCMI device
+ * @impl_version: Pointer to implementation version
+ *
+ * Obtain the implementation version number in @impl_version.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+ int (*base_discover_impl_version)(struct udevice *dev, u32 *impl_version);
+ /**
+ * base_discover_list_protocols - get list of protocols
+ * @dev: SCMI device
+ * @protocols: Pointer to array of SCMI 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
+ */
+ int (*base_discover_list_protocols)(struct udevice *dev, u8 **protocols);
+ /**
+ * base_discover_agent - identify agent
+ * @dev: SCMI device
+ * @agent_id: SCMI agent ID
+ * @ret_agent_id: Pointer to SCMI agent ID
+ * @name: SCMI 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
+ */
+ int (*base_discover_agent)(struct udevice *dev, u32 agent_id,
+ u32 *ret_agent_id, u8 *name);
+ /**
+ * base_notify_errors - configure error notification
+ * @dev: SCMI device
+ * @enable: Operation
+ *
+ * This function is not yet implemented.
+ *
+ * Return: always -EOPNOTSUPP
+ */
+ int (*base_notify_errors)(struct udevice *dev, u32 enable);
+ /**
+ * base_set_device_permissions - configure access permission to device
+ * @dev: SCMI device
+ * @agent_id: SCMI agent ID
+ * @device_id: ID 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
+ */
+ int (*base_set_device_permissions)(struct udevice *dev, u32 agent_id,
+ u32 device_id, u32 flags);
+ /**
+ * base_set_protocol_permissions - configure access permission to
+ * protocol on device
+ * @dev: SCMI device
+ * @agent_id: SCMI agent ID
+ * @device_id: ID of device to access
+ * @command_id: command ID
+ * @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
+ */
+ int (*base_set_protocol_permissions)(struct udevice *dev, u32 agent_id,
+ u32 device_id, u32 command_id,
+ u32 flags);
+ /**
+ * base_reset_agent_configuration - reset resource settings
+ * @dev: SCMI device
+ * @agent_id: SCMI agent ID
+ * @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
+ */
+ int (*base_reset_agent_configuration)(struct udevice *dev, u32 agent_id,
+ u32 flags);
+};
+
+int scmi_base_protocol_version(struct udevice *dev, u32 *version);
+int scmi_base_protocol_attrs(struct udevice *dev, u32 *num_agents,
+ u32 *num_protocols);
+int scmi_base_protocol_message_attrs(struct udevice *dev, u32 message_id,
+ u32 *attributes);
+int scmi_base_discover_vendor(struct udevice *dev, u8 *vendor);
+int scmi_base_discover_sub_vendor(struct udevice *dev, u8 *sub_vendor);
+int scmi_base_discover_impl_version(struct udevice *dev, u32 *impl_version);
+int scmi_base_discover_list_protocols(struct udevice *dev, u8 **protocols);
+int scmi_base_discover_agent(struct udevice *dev, u32 agent_id,
+ u32 *ret_agent_id, u8 *name);
+int scmi_base_notify_errors(struct udevice *dev, u32 enable);
+int scmi_base_set_device_permissions(struct udevice *dev, u32 agent_id,
+ u32 device_id, u32 flags);
+int scmi_base_set_device_permissions(struct udevice *dev, u32 agent_id,
+ u32 device_id, u32 flags);
+int scmi_base_set_protocol_permissions(struct udevice *dev,
+ u32 agent_id, u32 device_id,
+ u32 command_id, u32 flags);
+int scmi_base_reset_agent_configuration(struct udevice *dev, u32 agent_id,
+ u32 flags);
+
+/**
+ * scmi_generic_protocol_version - get protocol version
+ * @dev: SCMI device
+ * @id: SCMI protocol ID
+ * @version: Pointer to SCMI protocol version
+ *
+ * Obtain the protocol version number in @version.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+int scmi_generic_protocol_version(struct udevice *dev,
+ enum scmi_std_protocol id, u32 *version);
+
/*
* SCMI Clock Protocol
*/
--
2.41.0
^ permalink raw reply related [flat|nested] 40+ messages in thread* Re: [PATCH v2 02/12] firmware: scmi: implement SCMI base protocol
2023-07-26 8:37 ` [PATCH v2 02/12] firmware: scmi: implement SCMI base protocol AKASHI Takahiro
@ 2023-07-27 0:50 ` Simon Glass
2023-08-03 9:35 ` Etienne CARRIERE
1 sibling, 0 replies; 40+ messages in thread
From: Simon Glass @ 2023-07-27 0:50 UTC (permalink / raw)
To: AKASHI Takahiro; +Cc: trini, etienne.carriere, u-boot
On Wed, 26 Jul 2023 at 02:38, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> 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>
> ---
> v2
> * add helper functions, removing direct uses of ops
> * add function descriptions for each of functions in ops
> ---
> drivers/firmware/scmi/Makefile | 1 +
> drivers/firmware/scmi/base.c | 637 +++++++++++++++++++++++++++++++++
> include/dm/uclass-id.h | 1 +
> include/scmi_protocols.h | 345 ++++++++++++++++++
> 4 files changed, 984 insertions(+)
> create mode 100644 drivers/firmware/scmi/base.c
Reviewed-by: Simon Glass <sjg@chromium.org>
^ permalink raw reply [flat|nested] 40+ messages in thread
* RE: [PATCH v2 02/12] firmware: scmi: implement SCMI base protocol
2023-07-26 8:37 ` [PATCH v2 02/12] firmware: scmi: implement SCMI base protocol AKASHI Takahiro
2023-07-27 0:50 ` Simon Glass
@ 2023-08-03 9:35 ` Etienne CARRIERE
2023-08-08 2:21 ` AKASHI Takahiro
1 sibling, 1 reply; 40+ messages in thread
From: Etienne CARRIERE @ 2023-08-03 9:35 UTC (permalink / raw)
To: AKASHI Takahiro, trini@konsulko.com, sjg@chromium.org
Cc: u-boot@lists.denx.de
Hello Takahiro-san,
> From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> Sent: Wednesday, July 26, 2023 10:37
>
> 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>
> ---
> v2
> * add helper functions, removing direct uses of ops
> * add function descriptions for each of functions in ops
A reported typo and a question on use of strcpy().
Otherwise the patch look to me. If you strongly feel strcpy() is safe, please get my R-b tag:
Reviewed-by: Etienne Carriere <etienne.carriere@foss.st.com>
> ---
> drivers/firmware/scmi/Makefile | 1 +
> drivers/firmware/scmi/base.c | 637 +++++++++++++++++++++++++++++++++
> include/dm/uclass-id.h | 1 +
> include/scmi_protocols.h | 345 ++++++++++++++++++
> 4 files changed, 984 insertions(+)
> create mode 100644 drivers/firmware/scmi/base.c
>
> diff --git a/drivers/firmware/scmi/Makefile b/drivers/firmware/scmi/Makefile
> index b2ff483c75a1..1a23d4981709 100644
> --- a/drivers/firmware/scmi/Makefile
> +++ b/drivers/firmware/scmi/Makefile
> @@ -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
> diff --git a/drivers/firmware/scmi/base.c b/drivers/firmware/scmi/base.c
> new file mode 100644
> index 000000000000..2b61fa650d15
> --- /dev/null
> +++ b/drivers/firmware/scmi/base.c
> @@ -0,0 +1,637 @@
> +// 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>
> +
> +/**
> + * scmi_generic_protocol_version - get protocol version
> + * @dev: SCMI device
> + * @id: SCMI protocol ID
> + * @version: Pointer to SCMI protocol version
> + *
> + * Obtain the protocol version number in @version.
> + *
> + * Return: 0 on success, error code otherwise
> + */
> +int scmi_generic_protocol_version(struct udevice *dev,
> + enum scmi_std_protocol id, u32 *version)
> +{
> + struct scmi_protocol_version_out out;
> + struct scmi_msg msg = {
> + .protocol_id = id,
> + .message_id = SCMI_PROTOCOL_VERSION,
> + .out_msg = (u8 *)&out,
> + .out_msg_sz = sizeof(out),
> + };
> + int ret;
> +
> + ret = devm_scmi_process_msg(dev, &msg);
> + if (ret)
> + return ret;
> + if (out.status)
> + return scmi_to_linux_errno(out.status);
> +
> + *version = out.version;
> +
> + return 0;
> +}
> +
> +/**
> + * scmi_base_protocol_version_int - get Base protocol version
> + * @dev: SCMI device
> + * @version: Pointer to SCMI protocol version
> + *
> + * Obtain the protocol version number in @version for Base protocol.
> + *
> + * Return: 0 on success, error code otherwise
> + */
> +static int scmi_base_protocol_version_int(struct udevice *dev, u32 *version)
> +{
> + return scmi_generic_protocol_version(dev, SCMI_PROTOCOL_ID_BASE,
> + version);
> +}
> +
> +/**
> + * scmi_protocol_attrs_int - get protocol attributes
> + * @dev: SCMI device
> + * @num_agents: Number of SCMI agents
> + * @num_protocols: Number of SCMI 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_int(struct udevice *dev, u32 *num_agents,
> + u32 *num_protocols)
> +{
> + 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, &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_int - get message-specific attributes
> + * @dev: SCMI device
> + * @message_id: SCMI message ID
> + * @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_int(struct udevice *dev, u32 message_id,
> + u32 *attributes)
> +{
> + 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, &msg);
> + if (ret)
> + return ret;
> + if (out.status)
> + return scmi_to_linux_errno(out.status);
> +
> + *attributes = out.attributes;
> +
> + return 0;
> +}
> +
> +/**
> + * scmi_base_discover_vendor_int - get vendor name
> + * @dev: SCMI device
> + * @vendor: Vendor name
> + *
> + * Obtain the vendor's name in @vendor.
> + *
> + * Return: 0 on success, error code otherwise
> + */
> +static int scmi_base_discover_vendor_int(struct udevice *dev, u8 *vendor)
> +{
> + 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, &msg);
> + if (ret)
> + return ret;
> + if (out.status)
> + return scmi_to_linux_errno(out.status);
> +
> + strcpy(vendor, out.vendor_identifier);
Nitpicking: there are no check on output string buffer size.
The implementation looks good as we expect SCMI platform firmware
complies with the specification. However I wonder if here
it's better to either use strncpy() or to explicit vendor[] argument size:
-static int scmi_base_discover_vendor_int(struct udevice *dev, u8 *vendor)
+static int scmi_base_discover_vendor_int(struct udevice *dev,
u8 vendor[SCMI_BASE_NAME_LENGTH_MAX])
Ditto in scmi_base_discover_sub_vendor_int() and scmi_base_discover_agent_int().
> +
> + return 0;
> +}
> +
> +/**
> + * scmi_base_discover_sub_vendor_int - get sub-vendor name
> + * @dev: SCMI 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_int(struct udevice *dev,
> + u8 *sub_vendor)
> +{
> + 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, &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_int - get implementation version
> + * @dev: SCMI 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_int(struct udevice *dev,
> + u32 *impl_version)
> +{
> + 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, &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_int - get list of protocols
> + * @dev: SCMI device
> + * @protocols: Pointer to array of SCMI 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_int(struct udevice *dev,
> + u8 **protocols)
> +{
> + 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_base_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, &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_int - identify agent
> + * @dev: SCMI device
> + * @agent_id: SCMI agent ID
> + * @ret_agent_id: Pointer to SCMI agent ID
> + * @name: SCMI 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_int(struct udevice *dev, u32 agent_id,
> + u32 *ret_agent_id, u8 *name)
> +{
> + 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, &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_set_device_permissions_int - configure access permission to device
> + * @dev: SCMI device
> + * @agent_id: SCMI agent ID
> + * @device_id: ID 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_int(struct udevice *dev, u32 agent_id,
> + u32 device_id, u32 flags)
> +{
> + 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, &msg);
> + if (ret)
> + return ret;
> + if (status)
> + return scmi_to_linux_errno(status);
> +
> + return 0;
> +}
> +
> +/**
> + * scmi_base_set_protocol_permissions_int - configure access permission to
> + protocol on device
> + * @dev: SCMI device
> + * @agent_id: SCMI agent ID
> + * @device_id: ID of device to access
> + * @command_id: SCMI command ID
> + * @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_int(struct udevice *dev,
> + u32 agent_id, u32 device_id,
> + u32 command_id, u32 flags)
> +{
> + 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, &msg);
> + if (ret)
> + return ret;
> + if (status)
> + return scmi_to_linux_errno(status);
> +
> + return 0;
> +}
> +
> +/**
> + * scmi_base_reset_agent_configuration_int - reset resource settings
> + * @dev: SCMI device
> + * @agent_id: SCMI agent ID
> + * @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_int(struct udevice *dev,
> + u32 agent_id, u32 flags)
> +{
> + 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, &msg);
> + if (ret)
> + return ret;
> + if (status)
> + return scmi_to_linux_errno(status);
> +
> + return 0;
> +}
> +
> +/**
> + * scmi_base_probe - probe base protocol device
> + * @dev: SCMI 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)
> +{
> + int ret;
> +
> + ret = devm_scmi_of_get_channel(dev);
> + if (ret) {
> + dev_err(dev, "get_channel failed\n");
> + return ret;
> + }
> +
> + return ret;
> +}
> +
> +struct scmi_base_ops scmi_base_ops = {
> + /* Commands */
> + .protocol_version = scmi_base_protocol_version_int,
> + .protocol_attrs = scmi_protocol_attrs_int,
> + .protocol_message_attrs = scmi_protocol_message_attrs_int,
> + .base_discover_vendor = scmi_base_discover_vendor_int,
> + .base_discover_sub_vendor = scmi_base_discover_sub_vendor_int,
> + .base_discover_impl_version = scmi_base_discover_impl_version_int,
> + .base_discover_list_protocols = scmi_base_discover_list_protocols_int,
> + .base_discover_agent = scmi_base_discover_agent_int,
> + .base_notify_errors = NULL,
> + .base_set_device_permissions = scmi_base_set_device_permissions_int,
> + .base_set_protocol_permissions = scmi_base_set_protocol_permissions_int,
> + .base_reset_agent_configuration =
> + scmi_base_reset_agent_configuration_int,
> +};
> +
> +int scmi_base_protocol_version(struct udevice *dev, u32 *version)
> +{
> + const struct scmi_base_ops *ops = device_get_ops(dev);
> +
> + if (ops->protocol_version)
> + return (*ops->protocol_version)(dev, version);
> +
> + return -EOPNOTSUPP;
> +}
> +
> +int scmi_base_protocol_attrs(struct udevice *dev, u32 *num_agents,
> + u32 *num_protocols)
> +{
> + const struct scmi_base_ops *ops = device_get_ops(dev);
> +
> + if (ops->protocol_attrs)
> + return (*ops->protocol_attrs)(dev, num_agents, num_protocols);
> +
> + return -EOPNOTSUPP;
> +}
> +
> +int scmi_base_protocol_message_attrs(struct udevice *dev, u32 message_id,
> + u32 *attributes)
> +{
> + const struct scmi_base_ops *ops = device_get_ops(dev);
> +
> + if (ops->protocol_message_attrs)
> + return (*ops->protocol_message_attrs)(dev, message_id,
> + attributes);
> +
> + return -EOPNOTSUPP;
> +}
> +
> +int scmi_base_discover_vendor(struct udevice *dev, u8 *vendor)
> +{
> + const struct scmi_base_ops *ops = device_get_ops(dev);
> +
> + if (ops->base_discover_vendor)
> + return (*ops->base_discover_vendor)(dev, vendor);
> +
> + return -EOPNOTSUPP;
> +}
> +
> +int scmi_base_discover_sub_vendor(struct udevice *dev, u8 *sub_vendor)
> +{
> + const struct scmi_base_ops *ops = device_get_ops(dev);
> +
> + if (ops->base_discover_sub_vendor)
> + return (*ops->base_discover_sub_vendor)(dev, sub_vendor);
> +
> + return -EOPNOTSUPP;
> +}
> +
> +int scmi_base_discover_impl_version(struct udevice *dev, u32 *impl_version)
> +{
> + const struct scmi_base_ops *ops = device_get_ops(dev);
> +
> + if (ops->base_discover_impl_version)
> + return (*ops->base_discover_impl_version)(dev, impl_version);
> +
> + return -EOPNOTSUPP;
> +}
> +
> +int scmi_base_discover_list_protocols(struct udevice *dev, u8 **protocols)
> +{
> + const struct scmi_base_ops *ops = device_get_ops(dev);
> +
> + if (ops->base_discover_list_protocols)
> + return (*ops->base_discover_list_protocols)(dev, protocols);
> +
> + return -EOPNOTSUPP;
> +}
> +
> +int scmi_base_discover_agent(struct udevice *dev, u32 agent_id,
> + u32 *ret_agent_id, u8 *name)
> +{
> + const struct scmi_base_ops *ops = device_get_ops(dev);
> +
> + if (ops->base_discover_agent)
> + return (*ops->base_discover_agent)(dev, agent_id, ret_agent_id,
> + name);
> +
> + return -EOPNOTSUPP;
> +}
> +
> +int scmi_base_notify_errors(struct udevice *dev, u32 enable)
> +{
> + const struct scmi_base_ops *ops = device_get_ops(dev);
> +
> + if (ops->base_notify_errors)
> + return (*ops->base_notify_errors)(dev, enable);
> +
> + return -EOPNOTSUPP;
> +}
> +
> +int scmi_base_set_device_permissions(struct udevice *dev, u32 agent_id,
> + u32 device_id, u32 flags)
> +{
> + const struct scmi_base_ops *ops = device_get_ops(dev);
> +
> + if (ops->base_set_device_permissions)
> + return (*ops->base_set_device_permissions)(dev, agent_id,
> + device_id, flags);
> +
> + return -EOPNOTSUPP;
> +}
> +
> +int scmi_base_set_protocol_permissions(struct udevice *dev,
> + u32 agent_id, u32 device_id,
> + u32 command_id, u32 flags)
> +{
> + const struct scmi_base_ops *ops = device_get_ops(dev);
> +
> + if (ops->base_set_protocol_permissions)
> + return (*ops->base_set_protocol_permissions)(dev, agent_id,
> + device_id,
> + command_id,
> + flags);
> +
> + return -EOPNOTSUPP;
> +}
> +
> +int scmi_base_reset_agent_configuration(struct udevice *dev, u32 agent_id,
> + u32 flags)
> +{
> + const struct scmi_base_ops *ops = device_get_ops(dev);
> +
> + if (ops->base_reset_agent_configuration)
> + return (*ops->base_reset_agent_configuration)(dev, agent_id,
> + flags);
> +
> + return -EOPNOTSUPP;
> +}
> +
> +U_BOOT_DRIVER(scmi_base_drv) = {
> + .id = UCLASS_SCMI_BASE,
> + .name = "scmi_base_drv",
> + .ops = &scmi_base_ops,
> + .probe = scmi_base_probe,
> +};
> +
> +UCLASS_DRIVER(scmi_base) = {
> + .id = UCLASS_SCMI_BASE,
> + .name = "scmi_base",
> +};
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index 307ad6931ca7..f7a110852321 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -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 */
> diff --git a/include/scmi_protocols.h b/include/scmi_protocols.h
> index a220cb2a91ad..64fd740472b5 100644
> --- a/include/scmi_protocols.h
> +++ b/include/scmi_protocols.h
> @@ -49,6 +49,351 @@ enum scmi_discovery_id {
> SCMI_PROTOCOL_MESSAGE_ATTRIBUTES = 0x2,
> };
>
> +/*
> + * SCMI Base Protocol
> + */
> +#define SCMI_BASE_PROTOCOL_VERSION 0x20000
> +
> +enum scmi_base_message_id {
> + 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,
> +};
> +
> +#define SCMI_BASE_NAME_LENGTH_MAX 16
> +
> +/**
> + * 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: Name 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 SCMI protocols in @protocol
> + * @protocols: Array of packed SCMI 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: SCMI agent ID
> + * @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: SCMI agent ID
> + * @device_id: device ID
> + * @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: SCMI agent ID
> + * @device_id: device ID
> + * @command_id: command ID
> + * @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: SCMI agent ID
> + * @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
> + */
> +struct scmi_base_ops {
> + /**
> + * protocol_version - get Base protocol version
> + * @dev: SCMI device
> + * @version: Pointer to SCMI protocol version
> + *
> + * Obtain the protocol version number in @version for Base protocol.
> + *
> + * Return: 0 on success, error code otherwise
> + */
> + int (*protocol_version)(struct udevice *dev, u32 *version);
> + /**
> + * protocol_attrs - get protocol attributes
> + * @dev: SCMI device
> + * @num_agents: Number of SCMI agents
> + * @num_protocols: Number of SCMI 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
> + */
> + int (*protocol_attrs)(struct udevice *dev, u32 *num_agents,
> + u32 *num_protocols);
> + /**
> + * protocol_message_attrs - get message-specific attributes
> + * @dev: SCMI device
> + * @message_id: SCMI message ID
> + * @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
> + */
> + int (*protocol_message_attrs)(struct udevice *dev, u32 message_id,
> + u32 *attributes);
> + /**
> + * base_discover_vendor - get vendor name
> + * @dev: SCMI device
> + * @vendor: Vendor name
> + *
> + * Obtain the vendor's name in @vendor.
> + *
> + * Return: 0 on success, error code otherwise
> + */
> + int (*base_discover_vendor)(struct udevice *dev, u8 *vendor);
> + /**
> + * base_discover_sub_vendor - get sub-vendor name
> + * @dev: SCMI device
> + * @sub_vendor: Sub-vendor name
> + *
> + * Obtain the sub-vendor's name in @sub_vendor.
> + *
> + * Return: 0 on success, error code otherwise
> + */
> + int (*base_discover_sub_vendor)(struct udevice *dev, u8 *sub_vendor);
> + /**
> + * base_discover_impl_version - get implementation version
> + * @dev: SCMI device
> + * @impl_version: Pointer to implementation version
> + *
> + * Obtain the implementation version number in @impl_version.
> + *
> + * Return: 0 on success, error code otherwise
> + */
> + int (*base_discover_impl_version)(struct udevice *dev, u32 *impl_version);
> + /**
> + * base_discover_list_protocols - get list of protocols
> + * @dev: SCMI device
> + * @protocols: Pointer to array of SCMI 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
> + */
> + int (*base_discover_list_protocols)(struct udevice *dev, u8 **protocols);
> + /**
> + * base_discover_agent - identify agent
> + * @dev: SCMI device
> + * @agent_id: SCMI agent ID
> + * @ret_agent_id: Pointer to SCMI agent ID
> + * @name: SCMI 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
> + */
> + int (*base_discover_agent)(struct udevice *dev, u32 agent_id,
> + u32 *ret_agent_id, u8 *name);
> + /**
> + * base_notify_errors - configure error notification
> + * @dev: SCMI device
> + * @enable: Operation
> + *
> + * This function is not yet implemented.
> + *
> + * Return: always -EOPNOTSUPP
> + */
> + int (*base_notify_errors)(struct udevice *dev, u32 enable);
> + /**
> + * base_set_device_permissions - configure access permission to device
> + * @dev: SCMI device
> + * @agent_id: SCMI agent ID
> + * @device_id: ID 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
> + */
> + int (*base_set_device_permissions)(struct udevice *dev, u32 agent_id,
> + u32 device_id, u32 flags);
> + /**
> + * base_set_protocol_permissions - configure access permission to
> + * protocol on device
> + * @dev: SCMI device
> + * @agent_id: SCMI agent ID
> + * @device_id: ID of device to access
> + * @command_id: command ID
> + * @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
> + */
> + int (*base_set_protocol_permissions)(struct udevice *dev, u32 agent_id,
> + u32 device_id, u32 command_id,
> + u32 flags);
> + /**
> + * base_reset_agent_configuration - reset resource settings
> + * @dev: SCMI device
> + * @agent_id: SCMI agent ID
> + * @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
> + */
> + int (*base_reset_agent_configuration)(struct udevice *dev, u32 agent_id,
> + u32 flags);
> +};
> +
> +int scmi_base_protocol_version(struct udevice *dev, u32 *version);
> +int scmi_base_protocol_attrs(struct udevice *dev, u32 *num_agents,
> + u32 *num_protocols);
> +int scmi_base_protocol_message_attrs(struct udevice *dev, u32 message_id,
> + u32 *attributes);
> +int scmi_base_discover_vendor(struct udevice *dev, u8 *vendor);
> +int scmi_base_discover_sub_vendor(struct udevice *dev, u8 *sub_vendor);
> +int scmi_base_discover_impl_version(struct udevice *dev, u32 *impl_version);
> +int scmi_base_discover_list_protocols(struct udevice *dev, u8 **protocols);
> +int scmi_base_discover_agent(struct udevice *dev, u32 agent_id,
> + u32 *ret_agent_id, u8 *name);
> +int scmi_base_notify_errors(struct udevice *dev, u32 enable);
> +int scmi_base_set_device_permissions(struct udevice *dev, u32 agent_id,
> + u32 device_id, u32 flags);
> +int scmi_base_set_device_permissions(struct udevice *dev, u32 agent_id,
> + u32 device_id, u32 flags);
typo: duplicated declaration.
BR,
Etienne
> +int scmi_base_set_protocol_permissions(struct udevice *dev,
> + u32 agent_id, u32 device_id,
> + u32 command_id, u32 flags);
> +int scmi_base_reset_agent_configuration(struct udevice *dev, u32 agent_id,
> + u32 flags);
> +
> +/**
> + * scmi_generic_protocol_version - get protocol version
> + * @dev: SCMI device
> + * @id: SCMI protocol ID
> + * @version: Pointer to SCMI protocol version
> + *
> + * Obtain the protocol version number in @version.
> + *
> + * Return: 0 on success, error code otherwise
> + */
> +int scmi_generic_protocol_version(struct udevice *dev,
> + enum scmi_std_protocol id, u32 *version);
> +
> /*
> * SCMI Clock Protocol
> */
> --
> 2.41.0
>
^ permalink raw reply [flat|nested] 40+ messages in thread* Re: [PATCH v2 02/12] firmware: scmi: implement SCMI base protocol
2023-08-03 9:35 ` Etienne CARRIERE
@ 2023-08-08 2:21 ` AKASHI Takahiro
0 siblings, 0 replies; 40+ messages in thread
From: AKASHI Takahiro @ 2023-08-08 2:21 UTC (permalink / raw)
To: Etienne CARRIERE
Cc: trini@konsulko.com, sjg@chromium.org, u-boot@lists.denx.de
Hi Etienne,
On Thu, Aug 03, 2023 at 09:35:57AM +0000, Etienne CARRIERE wrote:
> Hello Takahiro-san,
>
> > From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > Sent: Wednesday, July 26, 2023 10:37
> >
> > 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>
> > ---
> > v2
> > * add helper functions, removing direct uses of ops
> > * add function descriptions for each of functions in ops
>
> A reported typo and a question on use of strcpy().
Thank you for pointing out typos not only in this file, but also others.
While I won't reply each time, I will fix all those typos.
> Otherwise the patch look to me. If you strongly feel strcpy() is safe, please get my R-b tag:
My initial thought was that commands in Base protocol are expected
to be used mostly internally so the string size check can be superfluous.
But for more safety, I will change the code so that data for returned
strings are dynamically allocated by helper functions.
This approach will also be helpful and consistent, in the future, when
"exntended name" is supported in other protocols as well so people
don't have to worry about the maximum length in any case.
-Takahiro Akashi
> Reviewed-by: Etienne Carriere <etienne.carriere@foss.st.com>
>
> > ---
> > drivers/firmware/scmi/Makefile | 1 +
> > drivers/firmware/scmi/base.c | 637 +++++++++++++++++++++++++++++++++
> > include/dm/uclass-id.h | 1 +
> > include/scmi_protocols.h | 345 ++++++++++++++++++
> > 4 files changed, 984 insertions(+)
> > create mode 100644 drivers/firmware/scmi/base.c
> >
> > diff --git a/drivers/firmware/scmi/Makefile b/drivers/firmware/scmi/Makefile
> > index b2ff483c75a1..1a23d4981709 100644
> > --- a/drivers/firmware/scmi/Makefile
> > +++ b/drivers/firmware/scmi/Makefile
> > @@ -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
> > diff --git a/drivers/firmware/scmi/base.c b/drivers/firmware/scmi/base.c
> > new file mode 100644
> > index 000000000000..2b61fa650d15
> > --- /dev/null
> > +++ b/drivers/firmware/scmi/base.c
> > @@ -0,0 +1,637 @@
> > +// 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>
> > +
> > +/**
> > + * scmi_generic_protocol_version - get protocol version
> > + * @dev: SCMI device
> > + * @id: SCMI protocol ID
> > + * @version: Pointer to SCMI protocol version
> > + *
> > + * Obtain the protocol version number in @version.
> > + *
> > + * Return: 0 on success, error code otherwise
> > + */
> > +int scmi_generic_protocol_version(struct udevice *dev,
> > + enum scmi_std_protocol id, u32 *version)
> > +{
> > + struct scmi_protocol_version_out out;
> > + struct scmi_msg msg = {
> > + .protocol_id = id,
> > + .message_id = SCMI_PROTOCOL_VERSION,
> > + .out_msg = (u8 *)&out,
> > + .out_msg_sz = sizeof(out),
> > + };
> > + int ret;
> > +
> > + ret = devm_scmi_process_msg(dev, &msg);
> > + if (ret)
> > + return ret;
> > + if (out.status)
> > + return scmi_to_linux_errno(out.status);
> > +
> > + *version = out.version;
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * scmi_base_protocol_version_int - get Base protocol version
> > + * @dev: SCMI device
> > + * @version: Pointer to SCMI protocol version
> > + *
> > + * Obtain the protocol version number in @version for Base protocol.
> > + *
> > + * Return: 0 on success, error code otherwise
> > + */
> > +static int scmi_base_protocol_version_int(struct udevice *dev, u32 *version)
> > +{
> > + return scmi_generic_protocol_version(dev, SCMI_PROTOCOL_ID_BASE,
> > + version);
> > +}
> > +
> > +/**
> > + * scmi_protocol_attrs_int - get protocol attributes
> > + * @dev: SCMI device
> > + * @num_agents: Number of SCMI agents
> > + * @num_protocols: Number of SCMI 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_int(struct udevice *dev, u32 *num_agents,
> > + u32 *num_protocols)
> > +{
> > + 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, &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_int - get message-specific attributes
> > + * @dev: SCMI device
> > + * @message_id: SCMI message ID
> > + * @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_int(struct udevice *dev, u32 message_id,
> > + u32 *attributes)
> > +{
> > + 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, &msg);
> > + if (ret)
> > + return ret;
> > + if (out.status)
> > + return scmi_to_linux_errno(out.status);
> > +
> > + *attributes = out.attributes;
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * scmi_base_discover_vendor_int - get vendor name
> > + * @dev: SCMI device
> > + * @vendor: Vendor name
> > + *
> > + * Obtain the vendor's name in @vendor.
> > + *
> > + * Return: 0 on success, error code otherwise
> > + */
> > +static int scmi_base_discover_vendor_int(struct udevice *dev, u8 *vendor)
> > +{
> > + 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, &msg);
> > + if (ret)
> > + return ret;
> > + if (out.status)
> > + return scmi_to_linux_errno(out.status);
> > +
> > + strcpy(vendor, out.vendor_identifier);
>
> Nitpicking: there are no check on output string buffer size.
>
> The implementation looks good as we expect SCMI platform firmware
> complies with the specification. However I wonder if here
> it's better to either use strncpy() or to explicit vendor[] argument size:
>
> -static int scmi_base_discover_vendor_int(struct udevice *dev, u8 *vendor)
> +static int scmi_base_discover_vendor_int(struct udevice *dev,
> u8 vendor[SCMI_BASE_NAME_LENGTH_MAX])
>
> Ditto in scmi_base_discover_sub_vendor_int() and scmi_base_discover_agent_int().
>
>
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * scmi_base_discover_sub_vendor_int - get sub-vendor name
> > + * @dev: SCMI 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_int(struct udevice *dev,
> > + u8 *sub_vendor)
> > +{
> > + 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, &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_int - get implementation version
> > + * @dev: SCMI 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_int(struct udevice *dev,
> > + u32 *impl_version)
> > +{
> > + 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, &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_int - get list of protocols
> > + * @dev: SCMI device
> > + * @protocols: Pointer to array of SCMI 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_int(struct udevice *dev,
> > + u8 **protocols)
> > +{
> > + 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_base_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, &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_int - identify agent
> > + * @dev: SCMI device
> > + * @agent_id: SCMI agent ID
> > + * @ret_agent_id: Pointer to SCMI agent ID
> > + * @name: SCMI 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_int(struct udevice *dev, u32 agent_id,
> > + u32 *ret_agent_id, u8 *name)
> > +{
> > + 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, &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_set_device_permissions_int - configure access permission to device
> > + * @dev: SCMI device
> > + * @agent_id: SCMI agent ID
> > + * @device_id: ID 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_int(struct udevice *dev, u32 agent_id,
> > + u32 device_id, u32 flags)
> > +{
> > + 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, &msg);
> > + if (ret)
> > + return ret;
> > + if (status)
> > + return scmi_to_linux_errno(status);
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * scmi_base_set_protocol_permissions_int - configure access permission to
> > + protocol on device
> > + * @dev: SCMI device
> > + * @agent_id: SCMI agent ID
> > + * @device_id: ID of device to access
> > + * @command_id: SCMI command ID
> > + * @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_int(struct udevice *dev,
> > + u32 agent_id, u32 device_id,
> > + u32 command_id, u32 flags)
> > +{
> > + 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, &msg);
> > + if (ret)
> > + return ret;
> > + if (status)
> > + return scmi_to_linux_errno(status);
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * scmi_base_reset_agent_configuration_int - reset resource settings
> > + * @dev: SCMI device
> > + * @agent_id: SCMI agent ID
> > + * @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_int(struct udevice *dev,
> > + u32 agent_id, u32 flags)
> > +{
> > + 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, &msg);
> > + if (ret)
> > + return ret;
> > + if (status)
> > + return scmi_to_linux_errno(status);
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * scmi_base_probe - probe base protocol device
> > + * @dev: SCMI 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)
> > +{
> > + int ret;
> > +
> > + ret = devm_scmi_of_get_channel(dev);
> > + if (ret) {
> > + dev_err(dev, "get_channel failed\n");
> > + return ret;
> > + }
> > +
> > + return ret;
> > +}
> > +
> > +struct scmi_base_ops scmi_base_ops = {
> > + /* Commands */
> > + .protocol_version = scmi_base_protocol_version_int,
> > + .protocol_attrs = scmi_protocol_attrs_int,
> > + .protocol_message_attrs = scmi_protocol_message_attrs_int,
> > + .base_discover_vendor = scmi_base_discover_vendor_int,
> > + .base_discover_sub_vendor = scmi_base_discover_sub_vendor_int,
> > + .base_discover_impl_version = scmi_base_discover_impl_version_int,
> > + .base_discover_list_protocols = scmi_base_discover_list_protocols_int,
> > + .base_discover_agent = scmi_base_discover_agent_int,
> > + .base_notify_errors = NULL,
> > + .base_set_device_permissions = scmi_base_set_device_permissions_int,
> > + .base_set_protocol_permissions = scmi_base_set_protocol_permissions_int,
> > + .base_reset_agent_configuration =
> > + scmi_base_reset_agent_configuration_int,
> > +};
> > +
> > +int scmi_base_protocol_version(struct udevice *dev, u32 *version)
> > +{
> > + const struct scmi_base_ops *ops = device_get_ops(dev);
> > +
> > + if (ops->protocol_version)
> > + return (*ops->protocol_version)(dev, version);
> > +
> > + return -EOPNOTSUPP;
> > +}
> > +
> > +int scmi_base_protocol_attrs(struct udevice *dev, u32 *num_agents,
> > + u32 *num_protocols)
> > +{
> > + const struct scmi_base_ops *ops = device_get_ops(dev);
> > +
> > + if (ops->protocol_attrs)
> > + return (*ops->protocol_attrs)(dev, num_agents, num_protocols);
> > +
> > + return -EOPNOTSUPP;
> > +}
> > +
> > +int scmi_base_protocol_message_attrs(struct udevice *dev, u32 message_id,
> > + u32 *attributes)
> > +{
> > + const struct scmi_base_ops *ops = device_get_ops(dev);
> > +
> > + if (ops->protocol_message_attrs)
> > + return (*ops->protocol_message_attrs)(dev, message_id,
> > + attributes);
> > +
> > + return -EOPNOTSUPP;
> > +}
> > +
> > +int scmi_base_discover_vendor(struct udevice *dev, u8 *vendor)
> > +{
> > + const struct scmi_base_ops *ops = device_get_ops(dev);
> > +
> > + if (ops->base_discover_vendor)
> > + return (*ops->base_discover_vendor)(dev, vendor);
> > +
> > + return -EOPNOTSUPP;
> > +}
> > +
> > +int scmi_base_discover_sub_vendor(struct udevice *dev, u8 *sub_vendor)
> > +{
> > + const struct scmi_base_ops *ops = device_get_ops(dev);
> > +
> > + if (ops->base_discover_sub_vendor)
> > + return (*ops->base_discover_sub_vendor)(dev, sub_vendor);
> > +
> > + return -EOPNOTSUPP;
> > +}
> > +
> > +int scmi_base_discover_impl_version(struct udevice *dev, u32 *impl_version)
> > +{
> > + const struct scmi_base_ops *ops = device_get_ops(dev);
> > +
> > + if (ops->base_discover_impl_version)
> > + return (*ops->base_discover_impl_version)(dev, impl_version);
> > +
> > + return -EOPNOTSUPP;
> > +}
> > +
> > +int scmi_base_discover_list_protocols(struct udevice *dev, u8 **protocols)
> > +{
> > + const struct scmi_base_ops *ops = device_get_ops(dev);
> > +
> > + if (ops->base_discover_list_protocols)
> > + return (*ops->base_discover_list_protocols)(dev, protocols);
> > +
> > + return -EOPNOTSUPP;
> > +}
> > +
> > +int scmi_base_discover_agent(struct udevice *dev, u32 agent_id,
> > + u32 *ret_agent_id, u8 *name)
> > +{
> > + const struct scmi_base_ops *ops = device_get_ops(dev);
> > +
> > + if (ops->base_discover_agent)
> > + return (*ops->base_discover_agent)(dev, agent_id, ret_agent_id,
> > + name);
> > +
> > + return -EOPNOTSUPP;
> > +}
> > +
> > +int scmi_base_notify_errors(struct udevice *dev, u32 enable)
> > +{
> > + const struct scmi_base_ops *ops = device_get_ops(dev);
> > +
> > + if (ops->base_notify_errors)
> > + return (*ops->base_notify_errors)(dev, enable);
> > +
> > + return -EOPNOTSUPP;
> > +}
> > +
> > +int scmi_base_set_device_permissions(struct udevice *dev, u32 agent_id,
> > + u32 device_id, u32 flags)
> > +{
> > + const struct scmi_base_ops *ops = device_get_ops(dev);
> > +
> > + if (ops->base_set_device_permissions)
> > + return (*ops->base_set_device_permissions)(dev, agent_id,
> > + device_id, flags);
> > +
> > + return -EOPNOTSUPP;
> > +}
> > +
> > +int scmi_base_set_protocol_permissions(struct udevice *dev,
> > + u32 agent_id, u32 device_id,
> > + u32 command_id, u32 flags)
> > +{
> > + const struct scmi_base_ops *ops = device_get_ops(dev);
> > +
> > + if (ops->base_set_protocol_permissions)
> > + return (*ops->base_set_protocol_permissions)(dev, agent_id,
> > + device_id,
> > + command_id,
> > + flags);
> > +
> > + return -EOPNOTSUPP;
> > +}
> > +
> > +int scmi_base_reset_agent_configuration(struct udevice *dev, u32 agent_id,
> > + u32 flags)
> > +{
> > + const struct scmi_base_ops *ops = device_get_ops(dev);
> > +
> > + if (ops->base_reset_agent_configuration)
> > + return (*ops->base_reset_agent_configuration)(dev, agent_id,
> > + flags);
> > +
> > + return -EOPNOTSUPP;
> > +}
> > +
> > +U_BOOT_DRIVER(scmi_base_drv) = {
> > + .id = UCLASS_SCMI_BASE,
> > + .name = "scmi_base_drv",
> > + .ops = &scmi_base_ops,
> > + .probe = scmi_base_probe,
> > +};
> > +
> > +UCLASS_DRIVER(scmi_base) = {
> > + .id = UCLASS_SCMI_BASE,
> > + .name = "scmi_base",
> > +};
> > diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> > index 307ad6931ca7..f7a110852321 100644
> > --- a/include/dm/uclass-id.h
> > +++ b/include/dm/uclass-id.h
> > @@ -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 */
> > diff --git a/include/scmi_protocols.h b/include/scmi_protocols.h
> > index a220cb2a91ad..64fd740472b5 100644
> > --- a/include/scmi_protocols.h
> > +++ b/include/scmi_protocols.h
> > @@ -49,6 +49,351 @@ enum scmi_discovery_id {
> > SCMI_PROTOCOL_MESSAGE_ATTRIBUTES = 0x2,
> > };
> >
> > +/*
> > + * SCMI Base Protocol
> > + */
> > +#define SCMI_BASE_PROTOCOL_VERSION 0x20000
> > +
> > +enum scmi_base_message_id {
> > + 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,
> > +};
> > +
> > +#define SCMI_BASE_NAME_LENGTH_MAX 16
> > +
> > +/**
> > + * 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: Name 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 SCMI protocols in @protocol
> > + * @protocols: Array of packed SCMI 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: SCMI agent ID
> > + * @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: SCMI agent ID
> > + * @device_id: device ID
> > + * @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: SCMI agent ID
> > + * @device_id: device ID
> > + * @command_id: command ID
> > + * @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: SCMI agent ID
> > + * @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
> > + */
> > +struct scmi_base_ops {
> > + /**
> > + * protocol_version - get Base protocol version
> > + * @dev: SCMI device
> > + * @version: Pointer to SCMI protocol version
> > + *
> > + * Obtain the protocol version number in @version for Base protocol.
> > + *
> > + * Return: 0 on success, error code otherwise
> > + */
> > + int (*protocol_version)(struct udevice *dev, u32 *version);
> > + /**
> > + * protocol_attrs - get protocol attributes
> > + * @dev: SCMI device
> > + * @num_agents: Number of SCMI agents
> > + * @num_protocols: Number of SCMI 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
> > + */
> > + int (*protocol_attrs)(struct udevice *dev, u32 *num_agents,
> > + u32 *num_protocols);
> > + /**
> > + * protocol_message_attrs - get message-specific attributes
> > + * @dev: SCMI device
> > + * @message_id: SCMI message ID
> > + * @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
> > + */
> > + int (*protocol_message_attrs)(struct udevice *dev, u32 message_id,
> > + u32 *attributes);
> > + /**
> > + * base_discover_vendor - get vendor name
> > + * @dev: SCMI device
> > + * @vendor: Vendor name
> > + *
> > + * Obtain the vendor's name in @vendor.
> > + *
> > + * Return: 0 on success, error code otherwise
> > + */
> > + int (*base_discover_vendor)(struct udevice *dev, u8 *vendor);
> > + /**
> > + * base_discover_sub_vendor - get sub-vendor name
> > + * @dev: SCMI device
> > + * @sub_vendor: Sub-vendor name
> > + *
> > + * Obtain the sub-vendor's name in @sub_vendor.
> > + *
> > + * Return: 0 on success, error code otherwise
> > + */
> > + int (*base_discover_sub_vendor)(struct udevice *dev, u8 *sub_vendor);
> > + /**
> > + * base_discover_impl_version - get implementation version
> > + * @dev: SCMI device
> > + * @impl_version: Pointer to implementation version
> > + *
> > + * Obtain the implementation version number in @impl_version.
> > + *
> > + * Return: 0 on success, error code otherwise
> > + */
> > + int (*base_discover_impl_version)(struct udevice *dev, u32 *impl_version);
> > + /**
> > + * base_discover_list_protocols - get list of protocols
> > + * @dev: SCMI device
> > + * @protocols: Pointer to array of SCMI 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
> > + */
> > + int (*base_discover_list_protocols)(struct udevice *dev, u8 **protocols);
> > + /**
> > + * base_discover_agent - identify agent
> > + * @dev: SCMI device
> > + * @agent_id: SCMI agent ID
> > + * @ret_agent_id: Pointer to SCMI agent ID
> > + * @name: SCMI 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
> > + */
> > + int (*base_discover_agent)(struct udevice *dev, u32 agent_id,
> > + u32 *ret_agent_id, u8 *name);
> > + /**
> > + * base_notify_errors - configure error notification
> > + * @dev: SCMI device
> > + * @enable: Operation
> > + *
> > + * This function is not yet implemented.
> > + *
> > + * Return: always -EOPNOTSUPP
> > + */
> > + int (*base_notify_errors)(struct udevice *dev, u32 enable);
> > + /**
> > + * base_set_device_permissions - configure access permission to device
> > + * @dev: SCMI device
> > + * @agent_id: SCMI agent ID
> > + * @device_id: ID 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
> > + */
> > + int (*base_set_device_permissions)(struct udevice *dev, u32 agent_id,
> > + u32 device_id, u32 flags);
> > + /**
> > + * base_set_protocol_permissions - configure access permission to
> > + * protocol on device
> > + * @dev: SCMI device
> > + * @agent_id: SCMI agent ID
> > + * @device_id: ID of device to access
> > + * @command_id: command ID
> > + * @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
> > + */
> > + int (*base_set_protocol_permissions)(struct udevice *dev, u32 agent_id,
> > + u32 device_id, u32 command_id,
> > + u32 flags);
> > + /**
> > + * base_reset_agent_configuration - reset resource settings
> > + * @dev: SCMI device
> > + * @agent_id: SCMI agent ID
> > + * @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
> > + */
> > + int (*base_reset_agent_configuration)(struct udevice *dev, u32 agent_id,
> > + u32 flags);
> > +};
> > +
> > +int scmi_base_protocol_version(struct udevice *dev, u32 *version);
> > +int scmi_base_protocol_attrs(struct udevice *dev, u32 *num_agents,
> > + u32 *num_protocols);
> > +int scmi_base_protocol_message_attrs(struct udevice *dev, u32 message_id,
> > + u32 *attributes);
> > +int scmi_base_discover_vendor(struct udevice *dev, u8 *vendor);
> > +int scmi_base_discover_sub_vendor(struct udevice *dev, u8 *sub_vendor);
> > +int scmi_base_discover_impl_version(struct udevice *dev, u32 *impl_version);
> > +int scmi_base_discover_list_protocols(struct udevice *dev, u8 **protocols);
> > +int scmi_base_discover_agent(struct udevice *dev, u32 agent_id,
> > + u32 *ret_agent_id, u8 *name);
> > +int scmi_base_notify_errors(struct udevice *dev, u32 enable);
> > +int scmi_base_set_device_permissions(struct udevice *dev, u32 agent_id,
> > + u32 device_id, u32 flags);
> > +int scmi_base_set_device_permissions(struct udevice *dev, u32 agent_id,
> > + u32 device_id, u32 flags);
>
> typo: duplicated declaration.
>
> BR,
> Etienne
>
> > +int scmi_base_set_protocol_permissions(struct udevice *dev,
> > + u32 agent_id, u32 device_id,
> > + u32 command_id, u32 flags);
> > +int scmi_base_reset_agent_configuration(struct udevice *dev, u32 agent_id,
> > + u32 flags);
> > +
> > +/**
> > + * scmi_generic_protocol_version - get protocol version
> > + * @dev: SCMI device
> > + * @id: SCMI protocol ID
> > + * @version: Pointer to SCMI protocol version
> > + *
> > + * Obtain the protocol version number in @version.
> > + *
> > + * Return: 0 on success, error code otherwise
> > + */
> > +int scmi_generic_protocol_version(struct udevice *dev,
> > + enum scmi_std_protocol id, u32 *version);
> > +
> > /*
> > * SCMI Clock Protocol
> > */
> > --
> > 2.41.0
> >
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v2 03/12] firmware: scmi: move scmi_bind_protocols() backward
2023-07-26 8:37 [PATCH v2 00/12] firmware: scmi: add SCMI base protocol support AKASHI Takahiro
2023-07-26 8:37 ` [PATCH v2 01/12] scmi: refactor the code to hide a channel from devices AKASHI Takahiro
2023-07-26 8:37 ` [PATCH v2 02/12] firmware: scmi: implement SCMI base protocol AKASHI Takahiro
@ 2023-07-26 8:37 ` AKASHI Takahiro
2023-07-27 0:50 ` Simon Glass
2023-08-03 9:37 ` Etienne CARRIERE
2023-07-26 8:38 ` [PATCH v2 04/12] firmware: scmi: framework for installing additional protocols AKASHI Takahiro
` (8 subsequent siblings)
11 siblings, 2 replies; 40+ messages in thread
From: AKASHI Takahiro @ 2023-07-26 8:37 UTC (permalink / raw)
To: trini, sjg; +Cc: etienne.carriere, u-boot, AKASHI Takahiro
Move the location of scmi_bind_protocols() backward for changes
in later patches.
There is no change in functionality.
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
drivers/firmware/scmi/scmi_agent-uclass.c | 118 +++++++++++-----------
1 file changed, 59 insertions(+), 59 deletions(-)
diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c
index 39cf15c88f75..8693e4c447b7 100644
--- a/drivers/firmware/scmi/scmi_agent-uclass.c
+++ b/drivers/firmware/scmi/scmi_agent-uclass.c
@@ -52,65 +52,6 @@ int scmi_to_linux_errno(s32 scmi_code)
return -EPROTO;
}
-/*
- * SCMI agent devices binds devices of various uclasses depeding on
- * the FDT description. scmi_bind_protocol() is a generic bind sequence
- * called by the uclass at bind stage, that is uclass post_bind.
- */
-static int scmi_bind_protocols(struct udevice *dev)
-{
- int ret = 0;
- ofnode node;
- const char *name;
-
- dev_for_each_subnode(node, dev) {
- struct driver *drv = NULL;
- u32 protocol_id;
-
- if (!ofnode_is_enabled(node))
- continue;
-
- if (ofnode_read_u32(node, "reg", &protocol_id))
- continue;
-
- name = ofnode_get_name(node);
- switch (protocol_id) {
- case SCMI_PROTOCOL_ID_CLOCK:
- if (CONFIG_IS_ENABLED(CLK_SCMI))
- drv = DM_DRIVER_GET(scmi_clock);
- break;
- case SCMI_PROTOCOL_ID_RESET_DOMAIN:
- if (IS_ENABLED(CONFIG_RESET_SCMI))
- drv = DM_DRIVER_GET(scmi_reset_domain);
- break;
- case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
- if (IS_ENABLED(CONFIG_DM_REGULATOR_SCMI)) {
- node = ofnode_find_subnode(node, "regulators");
- if (!ofnode_valid(node)) {
- dev_err(dev, "no regulators node\n");
- return -ENXIO;
- }
- drv = DM_DRIVER_GET(scmi_voltage_domain);
- }
- break;
- default:
- break;
- }
-
- if (!drv) {
- dev_dbg(dev, "Ignore unsupported SCMI protocol %#x\n",
- protocol_id);
- continue;
- }
-
- ret = device_bind(dev, drv, name, NULL, node, NULL);
- if (ret)
- break;
- }
-
- return ret;
-}
-
static struct udevice *find_scmi_transport_device(struct udevice *dev)
{
struct udevice *parent = dev;
@@ -208,6 +149,65 @@ int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg)
return scmi_process_msg(parent, priv->channel, msg);
}
+/*
+ * SCMI agent devices binds devices of various uclasses depeding on
+ * the FDT description. scmi_bind_protocol() is a generic bind sequence
+ * called by the uclass at bind stage, that is uclass post_bind.
+ */
+static int scmi_bind_protocols(struct udevice *dev)
+{
+ int ret = 0;
+ ofnode node;
+ const char *name;
+
+ dev_for_each_subnode(node, dev) {
+ struct driver *drv = NULL;
+ u32 protocol_id;
+
+ if (!ofnode_is_enabled(node))
+ continue;
+
+ if (ofnode_read_u32(node, "reg", &protocol_id))
+ continue;
+
+ name = ofnode_get_name(node);
+ switch (protocol_id) {
+ case SCMI_PROTOCOL_ID_CLOCK:
+ if (CONFIG_IS_ENABLED(CLK_SCMI))
+ drv = DM_DRIVER_GET(scmi_clock);
+ break;
+ case SCMI_PROTOCOL_ID_RESET_DOMAIN:
+ if (IS_ENABLED(CONFIG_RESET_SCMI))
+ drv = DM_DRIVER_GET(scmi_reset_domain);
+ break;
+ case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
+ if (IS_ENABLED(CONFIG_DM_REGULATOR_SCMI)) {
+ node = ofnode_find_subnode(node, "regulators");
+ if (!ofnode_valid(node)) {
+ dev_err(dev, "no regulators node\n");
+ return -ENXIO;
+ }
+ drv = DM_DRIVER_GET(scmi_voltage_domain);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!drv) {
+ dev_dbg(dev, "Ignore unsupported SCMI protocol %#x\n",
+ protocol_id);
+ continue;
+ }
+
+ ret = device_bind(dev, drv, name, NULL, node, NULL);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
UCLASS_DRIVER(scmi_agent) = {
.id = UCLASS_SCMI_AGENT,
.name = "scmi_agent",
--
2.41.0
^ permalink raw reply related [flat|nested] 40+ messages in thread* Re: [PATCH v2 03/12] firmware: scmi: move scmi_bind_protocols() backward
2023-07-26 8:37 ` [PATCH v2 03/12] firmware: scmi: move scmi_bind_protocols() backward AKASHI Takahiro
@ 2023-07-27 0:50 ` Simon Glass
2023-08-03 9:37 ` Etienne CARRIERE
1 sibling, 0 replies; 40+ messages in thread
From: Simon Glass @ 2023-07-27 0:50 UTC (permalink / raw)
To: AKASHI Takahiro; +Cc: trini, etienne.carriere, u-boot
On Wed, 26 Jul 2023 at 02:38, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> Move the location of scmi_bind_protocols() backward for changes
> in later patches.
> There is no change in functionality.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
> drivers/firmware/scmi/scmi_agent-uclass.c | 118 +++++++++++-----------
> 1 file changed, 59 insertions(+), 59 deletions(-)
Reviewed-by: Simon Glass <sjg@chromium.org>
^ permalink raw reply [flat|nested] 40+ messages in thread
* RE: [PATCH v2 03/12] firmware: scmi: move scmi_bind_protocols() backward
2023-07-26 8:37 ` [PATCH v2 03/12] firmware: scmi: move scmi_bind_protocols() backward AKASHI Takahiro
2023-07-27 0:50 ` Simon Glass
@ 2023-08-03 9:37 ` Etienne CARRIERE
1 sibling, 0 replies; 40+ messages in thread
From: Etienne CARRIERE @ 2023-08-03 9:37 UTC (permalink / raw)
To: AKASHI Takahiro, trini@konsulko.com, sjg@chromium.org
Cc: u-boot@lists.denx.de
> From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> Sent: Wednesday, July 26, 2023 10:37
>
> Move the location of scmi_bind_protocols() backward for changes
> in later patches.
> There is no change in functionality.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
> drivers/firmware/scmi/scmi_agent-uclass.c | 118 +++++++++++-----------
> 1 file changed, 59 insertions(+), 59 deletions(-)
>
Reviewed-by: Etienne Carriere <etienne.carriere@foss.st.com>
> diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c
> index 39cf15c88f75..8693e4c447b7 100644
> --- a/drivers/firmware/scmi/scmi_agent-uclass.c
> +++ b/drivers/firmware/scmi/scmi_agent-uclass.c
> @@ -52,65 +52,6 @@ int scmi_to_linux_errno(s32 scmi_code)
> return -EPROTO;
> }
>
> -/*
> - * SCMI agent devices binds devices of various uclasses depeding on
> - * the FDT description. scmi_bind_protocol() is a generic bind sequence
> - * called by the uclass at bind stage, that is uclass post_bind.
> - */
> -static int scmi_bind_protocols(struct udevice *dev)
> -{
> - int ret = 0;
> - ofnode node;
> - const char *name;
> -
> - dev_for_each_subnode(node, dev) {
> - struct driver *drv = NULL;
> - u32 protocol_id;
> -
> - if (!ofnode_is_enabled(node))
> - continue;
> -
> - if (ofnode_read_u32(node, "reg", &protocol_id))
> - continue;
> -
> - name = ofnode_get_name(node);
> - switch (protocol_id) {
> - case SCMI_PROTOCOL_ID_CLOCK:
> - if (CONFIG_IS_ENABLED(CLK_SCMI))
> - drv = DM_DRIVER_GET(scmi_clock);
> - break;
> - case SCMI_PROTOCOL_ID_RESET_DOMAIN:
> - if (IS_ENABLED(CONFIG_RESET_SCMI))
> - drv = DM_DRIVER_GET(scmi_reset_domain);
> - break;
> - case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
> - if (IS_ENABLED(CONFIG_DM_REGULATOR_SCMI)) {
> - node = ofnode_find_subnode(node, "regulators");
> - if (!ofnode_valid(node)) {
> - dev_err(dev, "no regulators node\n");
> - return -ENXIO;
> - }
> - drv = DM_DRIVER_GET(scmi_voltage_domain);
> - }
> - break;
> - default:
> - break;
> - }
> -
> - if (!drv) {
> - dev_dbg(dev, "Ignore unsupported SCMI protocol %#x\n",
> - protocol_id);
> - continue;
> - }
> -
> - ret = device_bind(dev, drv, name, NULL, node, NULL);
> - if (ret)
> - break;
> - }
> -
> - return ret;
> -}
> -
> static struct udevice *find_scmi_transport_device(struct udevice *dev)
> {
> struct udevice *parent = dev;
> @@ -208,6 +149,65 @@ int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg)
> return scmi_process_msg(parent, priv->channel, msg);
> }
>
> +/*
> + * SCMI agent devices binds devices of various uclasses depeding on
> + * the FDT description. scmi_bind_protocol() is a generic bind sequence
> + * called by the uclass at bind stage, that is uclass post_bind.
> + */
> +static int scmi_bind_protocols(struct udevice *dev)
> +{
> + int ret = 0;
> + ofnode node;
> + const char *name;
> +
> + dev_for_each_subnode(node, dev) {
> + struct driver *drv = NULL;
> + u32 protocol_id;
> +
> + if (!ofnode_is_enabled(node))
> + continue;
> +
> + if (ofnode_read_u32(node, "reg", &protocol_id))
> + continue;
> +
> + name = ofnode_get_name(node);
> + switch (protocol_id) {
> + case SCMI_PROTOCOL_ID_CLOCK:
> + if (CONFIG_IS_ENABLED(CLK_SCMI))
> + drv = DM_DRIVER_GET(scmi_clock);
> + break;
> + case SCMI_PROTOCOL_ID_RESET_DOMAIN:
> + if (IS_ENABLED(CONFIG_RESET_SCMI))
> + drv = DM_DRIVER_GET(scmi_reset_domain);
> + break;
> + case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
> + if (IS_ENABLED(CONFIG_DM_REGULATOR_SCMI)) {
> + node = ofnode_find_subnode(node, "regulators");
> + if (!ofnode_valid(node)) {
> + dev_err(dev, "no regulators node\n");
> + return -ENXIO;
> + }
> + drv = DM_DRIVER_GET(scmi_voltage_domain);
> + }
> + break;
> + default:
> + break;
> + }
> +
> + if (!drv) {
> + dev_dbg(dev, "Ignore unsupported SCMI protocol %#x\n",
> + protocol_id);
> + continue;
> + }
> +
> + ret = device_bind(dev, drv, name, NULL, node, NULL);
> + if (ret)
> + break;
> + }
> +
> + return ret;
> +}
> +
> UCLASS_DRIVER(scmi_agent) = {
> .id = UCLASS_SCMI_AGENT,
> .name = "scmi_agent",
> --
> 2.41.0
>
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v2 04/12] firmware: scmi: framework for installing additional protocols
2023-07-26 8:37 [PATCH v2 00/12] firmware: scmi: add SCMI base protocol support AKASHI Takahiro
` (2 preceding siblings ...)
2023-07-26 8:37 ` [PATCH v2 03/12] firmware: scmi: move scmi_bind_protocols() backward AKASHI Takahiro
@ 2023-07-26 8:38 ` AKASHI Takahiro
2023-07-27 0:53 ` Simon Glass
2023-08-03 9:57 ` Etienne CARRIERE
2023-07-26 8:38 ` [PATCH v2 05/12] firmware: scmi: install base protocol to SCMI agent AKASHI Takahiro
` (7 subsequent siblings)
11 siblings, 2 replies; 40+ messages in thread
From: AKASHI Takahiro @ 2023-07-26 8:38 UTC (permalink / raw)
To: trini, sjg; +Cc: etienne.carriere, u-boot, AKASHI Takahiro
This framework allows SCMI protocols to be installed and bound to the agent
so that the agent can manage and utilize them later.
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
v2
* check for availability of protocols
---
drivers/firmware/scmi/scmi_agent-uclass.c | 100 +++++++++++++++++++++-
include/scmi_agent-uclass.h | 15 +++-
include/scmi_agent.h | 14 +++
3 files changed, 125 insertions(+), 4 deletions(-)
diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c
index 8693e4c447b7..2244fcf487e8 100644
--- a/drivers/firmware/scmi/scmi_agent-uclass.c
+++ b/drivers/firmware/scmi/scmi_agent-uclass.c
@@ -38,6 +38,86 @@ static const struct error_code scmi_linux_errmap[] = {
{ .scmi = SCMI_PROTOCOL_ERROR, .errno = -EPROTO, },
};
+/*
+ * NOTE: The only one instance should exist according to
+ * the current specification and device tree bindings.
+ */
+struct udevice *scmi_agent;
+
+struct udevice *scmi_get_protocol(struct udevice *dev,
+ enum scmi_std_protocol id)
+{
+ struct scmi_agent_priv *priv;
+ struct udevice *proto;
+
+ priv = dev_get_uclass_plat(dev);
+ if (!priv) {
+ dev_err(dev, "No priv data found\n");
+ return NULL;
+ }
+
+ switch (id) {
+ case SCMI_PROTOCOL_ID_CLOCK:
+ proto = priv->clock_dev;
+ break;
+ case SCMI_PROTOCOL_ID_RESET_DOMAIN:
+ proto = priv->resetdom_dev;
+ break;
+ case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
+ proto = priv->voltagedom_dev;
+ break;
+ default:
+ dev_err(dev, "Protocol not supported\n");
+ proto = NULL;
+ break;
+ }
+ if (proto && device_probe(proto))
+ dev_err(dev, "Probe failed\n");
+
+ return proto;
+}
+
+/**
+ * scmi_add_protocol - add protocol to agent
+ * @dev: SCMI agent device
+ * @proto_id: SCMI protocol ID
+ * @proto: SCMI protocol device
+ *
+ * Associate the protocol instance, @proto, to the agent, @dev,
+ * for later use.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+static int scmi_add_protocol(struct udevice *dev,
+ enum scmi_std_protocol proto_id,
+ struct udevice *proto)
+{
+ struct scmi_agent_priv *priv;
+
+ priv = dev_get_uclass_plat(dev);
+ if (!priv) {
+ dev_err(dev, "No priv data found\n");
+ return -ENODEV;
+ }
+
+ switch (proto_id) {
+ case SCMI_PROTOCOL_ID_CLOCK:
+ priv->clock_dev = proto;
+ break;
+ case SCMI_PROTOCOL_ID_RESET_DOMAIN:
+ priv->resetdom_dev = proto;
+ break;
+ case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
+ priv->voltagedom_dev = proto;
+ break;
+ default:
+ dev_err(dev, "Protocol not supported\n");
+ return -EPROTO;
+ }
+
+ return 0;
+}
+
int scmi_to_linux_errno(s32 scmi_code)
{
int n;
@@ -156,12 +236,14 @@ int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg)
*/
static int scmi_bind_protocols(struct udevice *dev)
{
+ struct udevice *agent;
int ret = 0;
ofnode node;
const char *name;
+ struct driver *drv;
+ struct udevice *proto;
dev_for_each_subnode(node, dev) {
- struct driver *drv = NULL;
u32 protocol_id;
if (!ofnode_is_enabled(node))
@@ -170,6 +252,7 @@ static int scmi_bind_protocols(struct udevice *dev)
if (ofnode_read_u32(node, "reg", &protocol_id))
continue;
+ drv = NULL;
name = ofnode_get_name(node);
switch (protocol_id) {
case SCMI_PROTOCOL_ID_CLOCK:
@@ -200,11 +283,22 @@ static int scmi_bind_protocols(struct udevice *dev)
continue;
}
- ret = device_bind(dev, drv, name, NULL, node, NULL);
- if (ret)
+ ret = device_bind(dev, drv, name, NULL, node, &proto);
+ if (ret) {
+ dev_err(dev, "failed to bind %s protocol\n", drv->name);
break;
+ }
+ ret = scmi_add_protocol(dev, protocol_id, proto);
+ if (ret) {
+ dev_err(dev, "failed to add protocol: %s, ret: %d\n",
+ proto->name, ret);
+ break;
+ }
}
+ if (!ret)
+ scmi_agent = dev;
+
return ret;
}
diff --git a/include/scmi_agent-uclass.h b/include/scmi_agent-uclass.h
index b1c93532c0ea..f9e7d3f51de1 100644
--- a/include/scmi_agent-uclass.h
+++ b/include/scmi_agent-uclass.h
@@ -5,10 +5,23 @@
#ifndef _SCMI_AGENT_UCLASS_H
#define _SCMI_AGENT_UCLASS_H
-struct udevice;
+#include <dm/device.h>
+
struct scmi_msg;
struct scmi_channel;
+/**
+ * struct scmi_agent_priv - private data maintained by agent instance
+ * @clock_dev: SCMI clock protocol device
+ * @clock_dev: SCMI reset domain protocol device
+ * @clock_dev: SCMI voltage domain protocol device
+ */
+struct scmi_agent_priv {
+ struct udevice *clock_dev;
+ struct udevice *resetdom_dev;
+ struct udevice *voltagedom_dev;
+};
+
/**
* struct scmi_transport_ops - The functions that a SCMI transport layer must implement.
*/
diff --git a/include/scmi_agent.h b/include/scmi_agent.h
index 577892029ff8..a5e7cf0592bc 100644
--- a/include/scmi_agent.h
+++ b/include/scmi_agent.h
@@ -11,6 +11,7 @@
#define SCMI_AGENT_H
#include <asm/types.h>
+#include <scmi_protocols.h>
struct udevice;
struct scmi_channel;
@@ -74,6 +75,19 @@ int devm_scmi_of_get_channel(struct udevice *dev);
*/
int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg);
+/**
+ * scmi_get_protocol() - get protocol instance
+ *
+ * @dev: SCMI agent device
+ * @id: SCMI protocol ID
+ *
+ * Obtain the device instance for given protocol ID, @id.
+ *
+ * Return: Pointer to the device if found, null otherwise
+ */
+struct udevice *scmi_get_protocol(struct udevice *dev,
+ enum scmi_std_protocol id);
+
/**
* scmi_to_linux_errno() - Convert an SCMI error code into a Linux errno code
*
--
2.41.0
^ permalink raw reply related [flat|nested] 40+ messages in thread* Re: [PATCH v2 04/12] firmware: scmi: framework for installing additional protocols
2023-07-26 8:38 ` [PATCH v2 04/12] firmware: scmi: framework for installing additional protocols AKASHI Takahiro
@ 2023-07-27 0:53 ` Simon Glass
2023-08-03 9:57 ` Etienne CARRIERE
1 sibling, 0 replies; 40+ messages in thread
From: Simon Glass @ 2023-07-27 0:53 UTC (permalink / raw)
To: AKASHI Takahiro; +Cc: trini, etienne.carriere, u-boot
On Wed, 26 Jul 2023 at 02:39, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> This framework allows SCMI protocols to be installed and bound to the agent
> so that the agent can manage and utilize them later.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
> v2
> * check for availability of protocols
> ---
> drivers/firmware/scmi/scmi_agent-uclass.c | 100 +++++++++++++++++++++-
> include/scmi_agent-uclass.h | 15 +++-
> include/scmi_agent.h | 14 +++
> 3 files changed, 125 insertions(+), 4 deletions(-)
Reviewed-by: Simon Glass <sjg@chromium.org>
^ permalink raw reply [flat|nested] 40+ messages in thread
* RE: [PATCH v2 04/12] firmware: scmi: framework for installing additional protocols
2023-07-26 8:38 ` [PATCH v2 04/12] firmware: scmi: framework for installing additional protocols AKASHI Takahiro
2023-07-27 0:53 ` Simon Glass
@ 2023-08-03 9:57 ` Etienne CARRIERE
1 sibling, 0 replies; 40+ messages in thread
From: Etienne CARRIERE @ 2023-08-03 9:57 UTC (permalink / raw)
To: AKASHI Takahiro, trini@konsulko.com, sjg@chromium.org
Cc: u-boot@lists.denx.de
> From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> Sent: Wednesday, July 26, 2023 10:38
>
> This framework allows SCMI protocols to be installed and bound to the agent
> so that the agent can manage and utilize them later.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
> v2
> * check for availability of protocols
Reviewed-by: Etienne Carriere <etienne.carriere@foss.st.com>
with 2 minor comments and with .per_device_plat_auto value set
by this patch instead of from patch v2 01/12.
> ---
> drivers/firmware/scmi/scmi_agent-uclass.c | 100 +++++++++++++++++++++-
> include/scmi_agent-uclass.h | 15 +++-
> include/scmi_agent.h | 14 +++
> 3 files changed, 125 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c
> index 8693e4c447b7..2244fcf487e8 100644
> --- a/drivers/firmware/scmi/scmi_agent-uclass.c
> +++ b/drivers/firmware/scmi/scmi_agent-uclass.c
> @@ -38,6 +38,86 @@ static const struct error_code scmi_linux_errmap[] = {
> { .scmi = SCMI_PROTOCOL_ERROR, .errno = -EPROTO, },
> };
>
> +/*
> + * NOTE: The only one instance should exist according to
> + * the current specification and device tree bindings.
> + */
> +struct udevice *scmi_agent;
> +
> +struct udevice *scmi_get_protocol(struct udevice *dev,
> + enum scmi_std_protocol id)
> +{
> + struct scmi_agent_priv *priv;
> + struct udevice *proto;
> +
> + priv = dev_get_uclass_plat(dev);
> + if (!priv) {
> + dev_err(dev, "No priv data found\n");
> + return NULL;
> + }
> +
> + switch (id) {
> + case SCMI_PROTOCOL_ID_CLOCK:
> + proto = priv->clock_dev;
> + break;
> + case SCMI_PROTOCOL_ID_RESET_DOMAIN:
> + proto = priv->resetdom_dev;
> + break;
> + case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
> + proto = priv->voltagedom_dev;
> + break;
> + default:
> + dev_err(dev, "Protocol not supported\n");
> + proto = NULL;
> + break;
> + }
> + if (proto && device_probe(proto))
> + dev_err(dev, "Probe failed\n");
> +
> + return proto;
> +}
> +
> +/**
> + * scmi_add_protocol - add protocol to agent
> + * @dev: SCMI agent device
> + * @proto_id: SCMI protocol ID
> + * @proto: SCMI protocol device
> + *
> + * Associate the protocol instance, @proto, to the agent, @dev,
> + * for later use.
> + *
> + * Return: 0 on success, error code otherwise
> + */
> +static int scmi_add_protocol(struct udevice *dev,
> + enum scmi_std_protocol proto_id,
> + struct udevice *proto)
> +{
> + struct scmi_agent_priv *priv;
> +
> + priv = dev_get_uclass_plat(dev);
> + if (!priv) {
> + dev_err(dev, "No priv data found\n");
> + return -ENODEV;
> + }
> +
> + switch (proto_id) {
> + case SCMI_PROTOCOL_ID_CLOCK:
> + priv->clock_dev = proto;
> + break;
> + case SCMI_PROTOCOL_ID_RESET_DOMAIN:
> + priv->resetdom_dev = proto;
> + break;
> + case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
> + priv->voltagedom_dev = proto;
> + break;
> + default:
> + dev_err(dev, "Protocol not supported\n");
> + return -EPROTO;
> + }
> +
> + return 0;
> +}
> +
> int scmi_to_linux_errno(s32 scmi_code)
> {
> int n;
> @@ -156,12 +236,14 @@ int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg)
> */
> static int scmi_bind_protocols(struct udevice *dev)
> {
> + struct udevice *agent;
> int ret = 0;
> ofnode node;
> const char *name;
> + struct driver *drv;
> + struct udevice *proto;
>
> dev_for_each_subnode(node, dev) {
> - struct driver *drv = NULL;
> u32 protocol_id;
>
> if (!ofnode_is_enabled(node))
> @@ -170,6 +252,7 @@ static int scmi_bind_protocols(struct udevice *dev)
> if (ofnode_read_u32(node, "reg", &protocol_id))
> continue;
>
> + drv = NULL;
> name = ofnode_get_name(node);
> switch (protocol_id) {
> case SCMI_PROTOCOL_ID_CLOCK:
> @@ -200,11 +283,22 @@ static int scmi_bind_protocols(struct udevice *dev)
> continue;
> }
>
> - ret = device_bind(dev, drv, name, NULL, node, NULL);
> - if (ret)
> + ret = device_bind(dev, drv, name, NULL, node, &proto);
> + if (ret) {
> + dev_err(dev, "failed to bind %s protocol\n", drv->name);
> break;
> + }
> + ret = scmi_add_protocol(dev, protocol_id, proto);
> + if (ret) {
> + dev_err(dev, "failed to add protocol: %s, ret: %d\n",
> + proto->name, ret);
> + break;
> + }
> }
>
> + if (!ret)
> + scmi_agent = dev;
> +
> return ret;
> }
>
> diff --git a/include/scmi_agent-uclass.h b/include/scmi_agent-uclass.h
> index b1c93532c0ea..f9e7d3f51de1 100644
> --- a/include/scmi_agent-uclass.h
> +++ b/include/scmi_agent-uclass.h
> @@ -5,10 +5,23 @@
> #ifndef _SCMI_AGENT_UCLASS_H
> #define _SCMI_AGENT_UCLASS_H
>
> -struct udevice;
> +#include <dm/device.h>
> +
> struct scmi_msg;
> struct scmi_channel;
>
> +/**
> + * struct scmi_agent_priv - private data maintained by agent instance
> + * @clock_dev: SCMI clock protocol device
> + * @clock_dev: SCMI reset domain protocol device
> + * @clock_dev: SCMI voltage domain protocol device
> + */
> +struct scmi_agent_priv {
> + struct udevice *clock_dev;
> + struct udevice *resetdom_dev;
> + struct udevice *voltagedom_dev;
Nitpicking: typo on @clock_dev, fixed in next patch v2 05/12 of the series.
Could be squashed here.
> +};
> +
> /**
> * struct scmi_transport_ops - The functions that a SCMI transport layer must implement.
> */
> diff --git a/include/scmi_agent.h b/include/scmi_agent.h
> index 577892029ff8..a5e7cf0592bc 100644
> --- a/include/scmi_agent.h
> +++ b/include/scmi_agent.h
> @@ -11,6 +11,7 @@
> #define SCMI_AGENT_H
>
> #include <asm/types.h>
> +#include <scmi_protocols.h>
Should swap the 2 lines.
BR,
Etienne
>
> struct udevice;
> struct scmi_channel;
> @@ -74,6 +75,19 @@ int devm_scmi_of_get_channel(struct udevice *dev);
> */
> int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg);
>
> +/**
> + * scmi_get_protocol() - get protocol instance
> + *
> + * @dev: SCMI agent device
> + * @id: SCMI protocol ID
> + *
> + * Obtain the device instance for given protocol ID, @id.
> + *
> + * Return: Pointer to the device if found, null otherwise
> + */
> +struct udevice *scmi_get_protocol(struct udevice *dev,
> + enum scmi_std_protocol id);
> +
> /**
> * scmi_to_linux_errno() - Convert an SCMI error code into a Linux errno code
> *
> --
> 2.41.0
>
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v2 05/12] firmware: scmi: install base protocol to SCMI agent
2023-07-26 8:37 [PATCH v2 00/12] firmware: scmi: add SCMI base protocol support AKASHI Takahiro
` (3 preceding siblings ...)
2023-07-26 8:38 ` [PATCH v2 04/12] firmware: scmi: framework for installing additional protocols AKASHI Takahiro
@ 2023-07-26 8:38 ` AKASHI Takahiro
2023-07-27 0:50 ` Simon Glass
2023-07-26 8:38 ` [PATCH v2 06/12] sandbox: remove SCMI base node definition from test.dts AKASHI Takahiro
` (6 subsequent siblings)
11 siblings, 1 reply; 40+ messages in thread
From: AKASHI Takahiro @ 2023-07-26 8:38 UTC (permalink / raw)
To: trini, sjg; +Cc: etienne.carriere, u-boot, AKASHI Takahiro
SCMI base protocol is mandatory, and once SCMI node is found in a device
tree, the protocol handle (udevice) is unconditionally installed to
the agent. Then basic information will be retrieved from SCMI server via
the protocol and saved into the agent instance's local storage.
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
v2
* use helper functions, removing direct uses of ops
---
drivers/firmware/scmi/scmi_agent-uclass.c | 116 ++++++++++++++++++++++
include/scmi_agent-uclass.h | 70 ++++++++++++-
2 files changed, 184 insertions(+), 2 deletions(-)
diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c
index 2244fcf487e8..279c2c218913 100644
--- a/drivers/firmware/scmi/scmi_agent-uclass.c
+++ b/drivers/firmware/scmi/scmi_agent-uclass.c
@@ -57,6 +57,9 @@ struct udevice *scmi_get_protocol(struct udevice *dev,
}
switch (id) {
+ case SCMI_PROTOCOL_ID_BASE:
+ proto = priv->base_dev;
+ break;
case SCMI_PROTOCOL_ID_CLOCK:
proto = priv->clock_dev;
break;
@@ -101,6 +104,9 @@ static int scmi_add_protocol(struct udevice *dev,
}
switch (proto_id) {
+ case SCMI_PROTOCOL_ID_BASE:
+ priv->base_dev = proto;
+ break;
case SCMI_PROTOCOL_ID_CLOCK:
priv->clock_dev = proto;
break;
@@ -229,6 +235,83 @@ int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg)
return scmi_process_msg(parent, priv->channel, msg);
}
+/**
+ * scmi_fill_base_info - get base information about SCMI server
+ * @agent: SCMI agent device
+ * @dev: SCMI protocol device
+ *
+ * By using Base protocol commands, collect the base information
+ * about SCMI server.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+static int scmi_fill_base_info(struct udevice *agent, struct udevice *dev)
+{
+ struct scmi_agent_priv *priv = dev_get_uclass_plat(agent);
+ int ret;
+
+ ret = scmi_base_protocol_version(dev, &priv->version);
+ if (ret) {
+ dev_err(dev, "protocol_version() failed (%d)\n", ret);
+ return ret;
+ }
+ /* check for required version */
+ if (priv->version < SCMI_BASE_PROTOCOL_VERSION) {
+ dev_err(dev, "base protocol version (%d) lower than expected\n",
+ priv->version);
+ return -EPROTO;
+ }
+
+ ret = scmi_base_protocol_attrs(dev, &priv->num_agents,
+ &priv->num_protocols);
+ if (ret) {
+ dev_err(dev, "protocol_attrs() failed (%d)\n", ret);
+ return ret;
+ }
+ ret = scmi_base_discover_vendor(dev, priv->vendor);
+ if (ret) {
+ dev_err(dev, "base_discover_vendor() failed (%d)\n", ret);
+ return ret;
+ }
+ ret = scmi_base_discover_sub_vendor(dev, priv->sub_vendor);
+ if (ret) {
+ if (ret != -EOPNOTSUPP) {
+ dev_err(dev, "base_discover_sub_vendor() failed (%d)\n",
+ ret);
+ return ret;
+ }
+ strcpy(priv->sub_vendor, "NA");
+ }
+ ret = scmi_base_discover_impl_version(dev, &priv->impl_version);
+ if (ret) {
+ dev_err(dev, "base_discover_impl_version() failed (%d)\n",
+ ret);
+ return ret;
+ }
+
+ priv->agent_id = 0xffffffff; /* to avoid false claim */
+ ret = scmi_base_discover_agent(dev, 0xffffffff,
+ &priv->agent_id, priv->agent_name);
+ if (ret) {
+ if (ret != -EOPNOTSUPP) {
+ dev_err(dev,
+ "base_discover_agent() failed for myself (%d)\n",
+ ret);
+ return ret;
+ }
+ priv->agent_name[0] = '\0';
+ }
+
+ ret = scmi_base_discover_list_protocols(dev, &priv->protocols);
+ if (ret != priv->num_protocols) {
+ dev_err(dev, "base_discover_list_protocols() failed (%d)\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
/*
* SCMI agent devices binds devices of various uclasses depeding on
* the FDT description. scmi_bind_protocol() is a generic bind sequence
@@ -243,6 +326,39 @@ static int scmi_bind_protocols(struct udevice *dev)
struct driver *drv;
struct udevice *proto;
+ if (!uclass_get_device(UCLASS_SCMI_AGENT, 1, &agent)) {
+ /* This is a second SCMI agent */
+ dev_err(dev, "Cannot have more than one SCMI agent\n");
+ return -EEXIST;
+ }
+
+ /* initialize the device from device tree */
+ drv = DM_DRIVER_GET(scmi_base_drv);
+ name = "scmi-base.0";
+ ret = device_bind(dev, drv, name, NULL, ofnode_null(), &proto);
+ if (ret) {
+ dev_err(dev, "failed to bind base protocol\n");
+ return ret;
+ }
+ ret = scmi_add_protocol(dev, SCMI_PROTOCOL_ID_BASE, proto);
+ if (ret) {
+ dev_err(dev, "failed to add protocol: %s, ret: %d\n",
+ proto->name, ret);
+ return ret;
+ }
+
+ ret = device_probe(proto);
+ if (ret) {
+ dev_err(dev, "failed to probe base protocol\n");
+ return ret;
+ }
+
+ ret = scmi_fill_base_info(dev, proto);
+ if (ret) {
+ dev_err(dev, "failed to get base information\n");
+ return ret;
+ }
+
dev_for_each_subnode(node, dev) {
u32 protocol_id;
diff --git a/include/scmi_agent-uclass.h b/include/scmi_agent-uclass.h
index f9e7d3f51de1..0043a93c8d90 100644
--- a/include/scmi_agent-uclass.h
+++ b/include/scmi_agent-uclass.h
@@ -5,6 +5,7 @@
#ifndef _SCMI_AGENT_UCLASS_H
#define _SCMI_AGENT_UCLASS_H
+#include <scmi_protocols.h>
#include <dm/device.h>
struct scmi_msg;
@@ -12,16 +13,81 @@ struct scmi_channel;
/**
* struct scmi_agent_priv - private data maintained by agent instance
+ * @version: Version
+ * @num_agents: Number of agents
+ * @num_protocols: Number of protocols
+ * @impl_version: Implementation version
+ * @protocols: Array of protocol IDs
+ * @vendor: Vendor name
+ * @sub_vendor: Sub-vendor name
+ * @agent_name: Agent name
+ * agent_id: Identifier of agent
+ * @base_dev: SCMI base protocol device
* @clock_dev: SCMI clock protocol device
- * @clock_dev: SCMI reset domain protocol device
- * @clock_dev: SCMI voltage domain protocol device
+ * @resetdom_dev: SCMI reset domain protocol device
+ * @voltagedom_dev: SCMI voltage domain protocol device
*/
struct scmi_agent_priv {
+ u32 version;
+ u32 num_agents;
+ u32 num_protocols;
+ u32 impl_version;
+ u8 *protocols;
+ u8 vendor[SCMI_BASE_NAME_LENGTH_MAX];
+ u8 sub_vendor[SCMI_BASE_NAME_LENGTH_MAX];
+ u8 agent_name[SCMI_BASE_NAME_LENGTH_MAX];
+ u32 agent_id;
+ struct udevice *base_dev;
struct udevice *clock_dev;
struct udevice *resetdom_dev;
struct udevice *voltagedom_dev;
};
+static inline u32 scmi_version(struct udevice *dev)
+{
+ return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->version;
+}
+
+static inline u32 scmi_num_agents(struct udevice *dev)
+{
+ return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->num_agents;
+}
+
+static inline u32 scmi_num_protocols(struct udevice *dev)
+{
+ return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->num_protocols;
+}
+
+static inline u32 scmi_impl_version(struct udevice *dev)
+{
+ return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->impl_version;
+}
+
+static inline u8 *scmi_protocols(struct udevice *dev)
+{
+ return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->protocols;
+}
+
+static inline u8 *scmi_vendor(struct udevice *dev)
+{
+ return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->vendor;
+}
+
+static inline u8 *scmi_sub_vendor(struct udevice *dev)
+{
+ return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->sub_vendor;
+}
+
+static inline u8 *scmi_agent_name(struct udevice *dev)
+{
+ return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->agent_name;
+}
+
+static inline u32 scmi_agent_id(struct udevice *dev)
+{
+ return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->agent_id;
+}
+
/**
* struct scmi_transport_ops - The functions that a SCMI transport layer must implement.
*/
--
2.41.0
^ permalink raw reply related [flat|nested] 40+ messages in thread* Re: [PATCH v2 05/12] firmware: scmi: install base protocol to SCMI agent
2023-07-26 8:38 ` [PATCH v2 05/12] firmware: scmi: install base protocol to SCMI agent AKASHI Takahiro
@ 2023-07-27 0:50 ` Simon Glass
2023-07-27 1:07 ` AKASHI Takahiro
0 siblings, 1 reply; 40+ messages in thread
From: Simon Glass @ 2023-07-27 0:50 UTC (permalink / raw)
To: AKASHI Takahiro; +Cc: trini, etienne.carriere, u-boot
Hi,
On Wed, 26 Jul 2023 at 02:39, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> SCMI base protocol is mandatory, and once SCMI node is found in a device
> tree, the protocol handle (udevice) is unconditionally installed to
> the agent. Then basic information will be retrieved from SCMI server via
> the protocol and saved into the agent instance's local storage.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
> v2
> * use helper functions, removing direct uses of ops
> ---
> drivers/firmware/scmi/scmi_agent-uclass.c | 116 ++++++++++++++++++++++
> include/scmi_agent-uclass.h | 70 ++++++++++++-
> 2 files changed, 184 insertions(+), 2 deletions(-)
>
Reviewed-by: Simon Glass <sjg@chromium.org>
> diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c
> index 2244fcf487e8..279c2c218913 100644
> --- a/drivers/firmware/scmi/scmi_agent-uclass.c
> +++ b/drivers/firmware/scmi/scmi_agent-uclass.c
> @@ -57,6 +57,9 @@ struct udevice *scmi_get_protocol(struct udevice *dev,
> }
>
> switch (id) {
> + case SCMI_PROTOCOL_ID_BASE:
> + proto = priv->base_dev;
> + break;
> case SCMI_PROTOCOL_ID_CLOCK:
> proto = priv->clock_dev;
> break;
> @@ -101,6 +104,9 @@ static int scmi_add_protocol(struct udevice *dev,
> }
>
> switch (proto_id) {
> + case SCMI_PROTOCOL_ID_BASE:
> + priv->base_dev = proto;
> + break;
> case SCMI_PROTOCOL_ID_CLOCK:
> priv->clock_dev = proto;
> break;
> @@ -229,6 +235,83 @@ int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg)
> return scmi_process_msg(parent, priv->channel, msg);
> }
>
> +/**
> + * scmi_fill_base_info - get base information about SCMI server
> + * @agent: SCMI agent device
> + * @dev: SCMI protocol device
> + *
> + * By using Base protocol commands, collect the base information
> + * about SCMI server.
> + *
> + * Return: 0 on success, error code otherwise
> + */
> +static int scmi_fill_base_info(struct udevice *agent, struct udevice *dev)
> +{
> + struct scmi_agent_priv *priv = dev_get_uclass_plat(agent);
> + int ret;
> +
> + ret = scmi_base_protocol_version(dev, &priv->version);
> + if (ret) {
> + dev_err(dev, "protocol_version() failed (%d)\n", ret);
> + return ret;
> + }
> + /* check for required version */
> + if (priv->version < SCMI_BASE_PROTOCOL_VERSION) {
> + dev_err(dev, "base protocol version (%d) lower than expected\n",
> + priv->version);
> + return -EPROTO;
> + }
> +
> + ret = scmi_base_protocol_attrs(dev, &priv->num_agents,
> + &priv->num_protocols);
> + if (ret) {
> + dev_err(dev, "protocol_attrs() failed (%d)\n", ret);
> + return ret;
> + }
> + ret = scmi_base_discover_vendor(dev, priv->vendor);
> + if (ret) {
> + dev_err(dev, "base_discover_vendor() failed (%d)\n", ret);
> + return ret;
> + }
> + ret = scmi_base_discover_sub_vendor(dev, priv->sub_vendor);
> + if (ret) {
> + if (ret != -EOPNOTSUPP) {
> + dev_err(dev, "base_discover_sub_vendor() failed (%d)\n",
> + ret);
> + return ret;
> + }
> + strcpy(priv->sub_vendor, "NA");
> + }
> + ret = scmi_base_discover_impl_version(dev, &priv->impl_version);
> + if (ret) {
> + dev_err(dev, "base_discover_impl_version() failed (%d)\n",
> + ret);
> + return ret;
> + }
> +
> + priv->agent_id = 0xffffffff; /* to avoid false claim */
> + ret = scmi_base_discover_agent(dev, 0xffffffff,
> + &priv->agent_id, priv->agent_name);
> + if (ret) {
> + if (ret != -EOPNOTSUPP) {
> + dev_err(dev,
> + "base_discover_agent() failed for myself (%d)\n",
> + ret);
> + return ret;
> + }
> + priv->agent_name[0] = '\0';
> + }
> +
> + ret = scmi_base_discover_list_protocols(dev, &priv->protocols);
> + if (ret != priv->num_protocols) {
> + dev_err(dev, "base_discover_list_protocols() failed (%d)\n",
> + ret);
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> /*
> * SCMI agent devices binds devices of various uclasses depeding on
> * the FDT description. scmi_bind_protocol() is a generic bind sequence
> @@ -243,6 +326,39 @@ static int scmi_bind_protocols(struct udevice *dev)
> struct driver *drv;
> struct udevice *proto;
>
> + if (!uclass_get_device(UCLASS_SCMI_AGENT, 1, &agent)) {
> + /* This is a second SCMI agent */
> + dev_err(dev, "Cannot have more than one SCMI agent\n");
> + return -EEXIST;
> + }
> +
> + /* initialize the device from device tree */
> + drv = DM_DRIVER_GET(scmi_base_drv);
> + name = "scmi-base.0";
> + ret = device_bind(dev, drv, name, NULL, ofnode_null(), &proto);
Why is this not in the devicetree too?
> + if (ret) {
> + dev_err(dev, "failed to bind base protocol\n");
> + return ret;
> + }
> + ret = scmi_add_protocol(dev, SCMI_PROTOCOL_ID_BASE, proto);
> + if (ret) {
> + dev_err(dev, "failed to add protocol: %s, ret: %d\n",
> + proto->name, ret);
> + return ret;
> + }
> +
> + ret = device_probe(proto);
> + if (ret) {
> + dev_err(dev, "failed to probe base protocol\n");
> + return ret;
> + }
> +
> + ret = scmi_fill_base_info(dev, proto);
> + if (ret) {
> + dev_err(dev, "failed to get base information\n");
> + return ret;
> + }
> +
> dev_for_each_subnode(node, dev) {
> u32 protocol_id;
>
> diff --git a/include/scmi_agent-uclass.h b/include/scmi_agent-uclass.h
> index f9e7d3f51de1..0043a93c8d90 100644
> --- a/include/scmi_agent-uclass.h
> +++ b/include/scmi_agent-uclass.h
> @@ -5,6 +5,7 @@
> #ifndef _SCMI_AGENT_UCLASS_H
> #define _SCMI_AGENT_UCLASS_H
>
> +#include <scmi_protocols.h>
> #include <dm/device.h>
>
> struct scmi_msg;
> @@ -12,16 +13,81 @@ struct scmi_channel;
>
> /**
> * struct scmi_agent_priv - private data maintained by agent instance
> + * @version: Version
> + * @num_agents: Number of agents
> + * @num_protocols: Number of protocols
> + * @impl_version: Implementation version
> + * @protocols: Array of protocol IDs
> + * @vendor: Vendor name
> + * @sub_vendor: Sub-vendor name
> + * @agent_name: Agent name
> + * agent_id: Identifier of agent
> + * @base_dev: SCMI base protocol device
> * @clock_dev: SCMI clock protocol device
> - * @clock_dev: SCMI reset domain protocol device
> - * @clock_dev: SCMI voltage domain protocol device
> + * @resetdom_dev: SCMI reset domain protocol device
> + * @voltagedom_dev: SCMI voltage domain protocol device
> */
> struct scmi_agent_priv {
> + u32 version;
> + u32 num_agents;
> + u32 num_protocols;
> + u32 impl_version;
> + u8 *protocols;
> + u8 vendor[SCMI_BASE_NAME_LENGTH_MAX];
> + u8 sub_vendor[SCMI_BASE_NAME_LENGTH_MAX];
> + u8 agent_name[SCMI_BASE_NAME_LENGTH_MAX];
> + u32 agent_id;
> + struct udevice *base_dev;
> struct udevice *clock_dev;
> struct udevice *resetdom_dev;
> struct udevice *voltagedom_dev;
> };
>
> +static inline u32 scmi_version(struct udevice *dev)
> +{
> + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->version;
> +}
> +
> +static inline u32 scmi_num_agents(struct udevice *dev)
> +{
> + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->num_agents;
> +}
> +
> +static inline u32 scmi_num_protocols(struct udevice *dev)
> +{
> + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->num_protocols;
> +}
> +
> +static inline u32 scmi_impl_version(struct udevice *dev)
> +{
> + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->impl_version;
> +}
> +
> +static inline u8 *scmi_protocols(struct udevice *dev)
> +{
> + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->protocols;
> +}
> +
> +static inline u8 *scmi_vendor(struct udevice *dev)
> +{
> + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->vendor;
> +}
> +
> +static inline u8 *scmi_sub_vendor(struct udevice *dev)
> +{
> + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->sub_vendor;
> +}
> +
> +static inline u8 *scmi_agent_name(struct udevice *dev)
> +{
> + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->agent_name;
> +}
> +
> +static inline u32 scmi_agent_id(struct udevice *dev)
> +{
> + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->agent_id;
> +}
Why these helper functions? It seems better to avoid inlining access
to dev_get_uclass_plat(). Are you worried about exposing the priv
struct to clients?
> +
> /**
> * struct scmi_transport_ops - The functions that a SCMI transport layer must implement.
> */
> --
> 2.41.0
>
Regards,
Simon
^ permalink raw reply [flat|nested] 40+ messages in thread* Re: [PATCH v2 05/12] firmware: scmi: install base protocol to SCMI agent
2023-07-27 0:50 ` Simon Glass
@ 2023-07-27 1:07 ` AKASHI Takahiro
2023-07-27 2:44 ` Simon Glass
2023-08-03 10:01 ` Etienne CARRIERE
0 siblings, 2 replies; 40+ messages in thread
From: AKASHI Takahiro @ 2023-07-27 1:07 UTC (permalink / raw)
To: Simon Glass; +Cc: trini, etienne.carriere, u-boot
Hi Simon,
Thank you for your extensive review.
On Wed, Jul 26, 2023 at 06:50:23PM -0600, Simon Glass wrote:
> Hi,
>
> On Wed, 26 Jul 2023 at 02:39, AKASHI Takahiro
> <takahiro.akashi@linaro.org> wrote:
> >
> > SCMI base protocol is mandatory, and once SCMI node is found in a device
> > tree, the protocol handle (udevice) is unconditionally installed to
> > the agent. Then basic information will be retrieved from SCMI server via
> > the protocol and saved into the agent instance's local storage.
> >
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > ---
> > v2
> > * use helper functions, removing direct uses of ops
> > ---
> > drivers/firmware/scmi/scmi_agent-uclass.c | 116 ++++++++++++++++++++++
> > include/scmi_agent-uclass.h | 70 ++++++++++++-
> > 2 files changed, 184 insertions(+), 2 deletions(-)
> >
>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> > diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c
> > index 2244fcf487e8..279c2c218913 100644
> > --- a/drivers/firmware/scmi/scmi_agent-uclass.c
> > +++ b/drivers/firmware/scmi/scmi_agent-uclass.c
> > @@ -57,6 +57,9 @@ struct udevice *scmi_get_protocol(struct udevice *dev,
> > }
> >
> > switch (id) {
> > + case SCMI_PROTOCOL_ID_BASE:
> > + proto = priv->base_dev;
> > + break;
> > case SCMI_PROTOCOL_ID_CLOCK:
> > proto = priv->clock_dev;
> > break;
> > @@ -101,6 +104,9 @@ static int scmi_add_protocol(struct udevice *dev,
> > }
> >
> > switch (proto_id) {
> > + case SCMI_PROTOCOL_ID_BASE:
> > + priv->base_dev = proto;
> > + break;
> > case SCMI_PROTOCOL_ID_CLOCK:
> > priv->clock_dev = proto;
> > break;
> > @@ -229,6 +235,83 @@ int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg)
> > return scmi_process_msg(parent, priv->channel, msg);
> > }
> >
> > +/**
> > + * scmi_fill_base_info - get base information about SCMI server
> > + * @agent: SCMI agent device
> > + * @dev: SCMI protocol device
> > + *
> > + * By using Base protocol commands, collect the base information
> > + * about SCMI server.
> > + *
> > + * Return: 0 on success, error code otherwise
> > + */
> > +static int scmi_fill_base_info(struct udevice *agent, struct udevice *dev)
> > +{
> > + struct scmi_agent_priv *priv = dev_get_uclass_plat(agent);
> > + int ret;
> > +
> > + ret = scmi_base_protocol_version(dev, &priv->version);
> > + if (ret) {
> > + dev_err(dev, "protocol_version() failed (%d)\n", ret);
> > + return ret;
> > + }
> > + /* check for required version */
> > + if (priv->version < SCMI_BASE_PROTOCOL_VERSION) {
> > + dev_err(dev, "base protocol version (%d) lower than expected\n",
> > + priv->version);
> > + return -EPROTO;
> > + }
> > +
> > + ret = scmi_base_protocol_attrs(dev, &priv->num_agents,
> > + &priv->num_protocols);
> > + if (ret) {
> > + dev_err(dev, "protocol_attrs() failed (%d)\n", ret);
> > + return ret;
> > + }
> > + ret = scmi_base_discover_vendor(dev, priv->vendor);
> > + if (ret) {
> > + dev_err(dev, "base_discover_vendor() failed (%d)\n", ret);
> > + return ret;
> > + }
> > + ret = scmi_base_discover_sub_vendor(dev, priv->sub_vendor);
> > + if (ret) {
> > + if (ret != -EOPNOTSUPP) {
> > + dev_err(dev, "base_discover_sub_vendor() failed (%d)\n",
> > + ret);
> > + return ret;
> > + }
> > + strcpy(priv->sub_vendor, "NA");
> > + }
> > + ret = scmi_base_discover_impl_version(dev, &priv->impl_version);
> > + if (ret) {
> > + dev_err(dev, "base_discover_impl_version() failed (%d)\n",
> > + ret);
> > + return ret;
> > + }
> > +
> > + priv->agent_id = 0xffffffff; /* to avoid false claim */
> > + ret = scmi_base_discover_agent(dev, 0xffffffff,
> > + &priv->agent_id, priv->agent_name);
> > + if (ret) {
> > + if (ret != -EOPNOTSUPP) {
> > + dev_err(dev,
> > + "base_discover_agent() failed for myself (%d)\n",
> > + ret);
> > + return ret;
> > + }
> > + priv->agent_name[0] = '\0';
> > + }
> > +
> > + ret = scmi_base_discover_list_protocols(dev, &priv->protocols);
> > + if (ret != priv->num_protocols) {
> > + dev_err(dev, "base_discover_list_protocols() failed (%d)\n",
> > + ret);
> > + return ret;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > /*
> > * SCMI agent devices binds devices of various uclasses depeding on
> > * the FDT description. scmi_bind_protocol() is a generic bind sequence
> > @@ -243,6 +326,39 @@ static int scmi_bind_protocols(struct udevice *dev)
> > struct driver *drv;
> > struct udevice *proto;
> >
> > + if (!uclass_get_device(UCLASS_SCMI_AGENT, 1, &agent)) {
> > + /* This is a second SCMI agent */
> > + dev_err(dev, "Cannot have more than one SCMI agent\n");
> > + return -EEXIST;
> > + }
> > +
> > + /* initialize the device from device tree */
> > + drv = DM_DRIVER_GET(scmi_base_drv);
> > + name = "scmi-base.0";
> > + ret = device_bind(dev, drv, name, NULL, ofnode_null(), &proto);
>
> Why is this not in the devicetree too?
I don't know the history of discussions, but it is
because no binding for the base protocol is necessary, I guess,
as it is a mandatory protocol without any customisable parameters.
Please see kernel's Documentation/devicetree/bindings/firmware/arm,scmi.yaml.
> > + if (ret) {
> > + dev_err(dev, "failed to bind base protocol\n");
> > + return ret;
> > + }
> > + ret = scmi_add_protocol(dev, SCMI_PROTOCOL_ID_BASE, proto);
> > + if (ret) {
> > + dev_err(dev, "failed to add protocol: %s, ret: %d\n",
> > + proto->name, ret);
> > + return ret;
> > + }
> > +
> > + ret = device_probe(proto);
> > + if (ret) {
> > + dev_err(dev, "failed to probe base protocol\n");
> > + return ret;
> > + }
> > +
> > + ret = scmi_fill_base_info(dev, proto);
> > + if (ret) {
> > + dev_err(dev, "failed to get base information\n");
> > + return ret;
> > + }
> > +
> > dev_for_each_subnode(node, dev) {
> > u32 protocol_id;
> >
> > diff --git a/include/scmi_agent-uclass.h b/include/scmi_agent-uclass.h
> > index f9e7d3f51de1..0043a93c8d90 100644
> > --- a/include/scmi_agent-uclass.h
> > +++ b/include/scmi_agent-uclass.h
> > @@ -5,6 +5,7 @@
> > #ifndef _SCMI_AGENT_UCLASS_H
> > #define _SCMI_AGENT_UCLASS_H
> >
> > +#include <scmi_protocols.h>
> > #include <dm/device.h>
> >
> > struct scmi_msg;
> > @@ -12,16 +13,81 @@ struct scmi_channel;
> >
> > /**
> > * struct scmi_agent_priv - private data maintained by agent instance
> > + * @version: Version
> > + * @num_agents: Number of agents
> > + * @num_protocols: Number of protocols
> > + * @impl_version: Implementation version
> > + * @protocols: Array of protocol IDs
> > + * @vendor: Vendor name
> > + * @sub_vendor: Sub-vendor name
> > + * @agent_name: Agent name
> > + * agent_id: Identifier of agent
> > + * @base_dev: SCMI base protocol device
> > * @clock_dev: SCMI clock protocol device
> > - * @clock_dev: SCMI reset domain protocol device
> > - * @clock_dev: SCMI voltage domain protocol device
> > + * @resetdom_dev: SCMI reset domain protocol device
> > + * @voltagedom_dev: SCMI voltage domain protocol device
> > */
> > struct scmi_agent_priv {
> > + u32 version;
> > + u32 num_agents;
> > + u32 num_protocols;
> > + u32 impl_version;
> > + u8 *protocols;
> > + u8 vendor[SCMI_BASE_NAME_LENGTH_MAX];
> > + u8 sub_vendor[SCMI_BASE_NAME_LENGTH_MAX];
> > + u8 agent_name[SCMI_BASE_NAME_LENGTH_MAX];
> > + u32 agent_id;
> > + struct udevice *base_dev;
> > struct udevice *clock_dev;
> > struct udevice *resetdom_dev;
> > struct udevice *voltagedom_dev;
> > };
> >
> > +static inline u32 scmi_version(struct udevice *dev)
> > +{
> > + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->version;
> > +}
> > +
> > +static inline u32 scmi_num_agents(struct udevice *dev)
> > +{
> > + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->num_agents;
> > +}
> > +
> > +static inline u32 scmi_num_protocols(struct udevice *dev)
> > +{
> > + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->num_protocols;
> > +}
> > +
> > +static inline u32 scmi_impl_version(struct udevice *dev)
> > +{
> > + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->impl_version;
> > +}
> > +
> > +static inline u8 *scmi_protocols(struct udevice *dev)
> > +{
> > + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->protocols;
> > +}
> > +
> > +static inline u8 *scmi_vendor(struct udevice *dev)
> > +{
> > + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->vendor;
> > +}
> > +
> > +static inline u8 *scmi_sub_vendor(struct udevice *dev)
> > +{
> > + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->sub_vendor;
> > +}
> > +
> > +static inline u8 *scmi_agent_name(struct udevice *dev)
> > +{
> > + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->agent_name;
> > +}
> > +
> > +static inline u32 scmi_agent_id(struct udevice *dev)
> > +{
> > + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->agent_id;
> > +}
>
> Why these helper functions? It seems better to avoid inlining access
> to dev_get_uclass_plat(). Are you worried about exposing the priv
> struct to clients?
Well, simply wanted to avoid repeating
"((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->)" in the code.
Thanks,
-Takahiro Akashi
> > +
> > /**
> > * struct scmi_transport_ops - The functions that a SCMI transport layer must implement.
> > */
> > --
> > 2.41.0
> >
>
> Regards,
> Simon
^ permalink raw reply [flat|nested] 40+ messages in thread* Re: [PATCH v2 05/12] firmware: scmi: install base protocol to SCMI agent
2023-07-27 1:07 ` AKASHI Takahiro
@ 2023-07-27 2:44 ` Simon Glass
2023-08-03 10:01 ` Etienne CARRIERE
1 sibling, 0 replies; 40+ messages in thread
From: Simon Glass @ 2023-07-27 2:44 UTC (permalink / raw)
To: AKASHI Takahiro, Simon Glass, trini, etienne.carriere, u-boot
Hi,
On Wed, 26 Jul 2023 at 19:07, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> Hi Simon,
>
> Thank you for your extensive review.
Cheers.
>
> On Wed, Jul 26, 2023 at 06:50:23PM -0600, Simon Glass wrote:
> > Hi,
> >
> > On Wed, 26 Jul 2023 at 02:39, AKASHI Takahiro
> > <takahiro.akashi@linaro.org> wrote:
> > >
> > > SCMI base protocol is mandatory, and once SCMI node is found in a device
> > > tree, the protocol handle (udevice) is unconditionally installed to
> > > the agent. Then basic information will be retrieved from SCMI server via
> > > the protocol and saved into the agent instance's local storage.
> > >
> > > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > > ---
> > > v2
> > > * use helper functions, removing direct uses of ops
> > > ---
> > > drivers/firmware/scmi/scmi_agent-uclass.c | 116 ++++++++++++++++++++++
> > > include/scmi_agent-uclass.h | 70 ++++++++++++-
> > > 2 files changed, 184 insertions(+), 2 deletions(-)
> > >
> >
> > Reviewed-by: Simon Glass <sjg@chromium.org>
> >
[..]
> > > +static inline u32 scmi_agent_id(struct udevice *dev)
> > > +{
> > > + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->agent_id;
> > > +}
> >
> > Why these helper functions? It seems better to avoid inlining access
> > to dev_get_uclass_plat(). Are you worried about exposing the priv
> > struct to clients?
>
> Well, simply wanted to avoid repeating
> "((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->)" in the code.
That's fine, so long as it would not be better for the caller to
obtain the priv pointer and just access the fields in the struct,
Regards,
Simon
^ permalink raw reply [flat|nested] 40+ messages in thread* RE: [PATCH v2 05/12] firmware: scmi: install base protocol to SCMI agent
2023-07-27 1:07 ` AKASHI Takahiro
2023-07-27 2:44 ` Simon Glass
@ 2023-08-03 10:01 ` Etienne CARRIERE
1 sibling, 0 replies; 40+ messages in thread
From: Etienne CARRIERE @ 2023-08-03 10:01 UTC (permalink / raw)
To: AKASHI Takahiro, Simon Glass; +Cc: trini@konsulko.com, u-boot@lists.denx.de
> From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> Sent: Thursday, July 27, 2023 03:07
>
> Hi Simon,
>
> Thank you for your extensive review.
>
> On Wed, Jul 26, 2023 at 06:50:23PM -0600, Simon Glass wrote:
> > Hi,
> >
> > On Wed, 26 Jul 2023 at 02:39, AKASHI Takahiro
> > <takahiro.akashi@linaro.org> wrote:
> > >
> > > SCMI base protocol is mandatory, and once SCMI node is found in a device
> > > tree, the protocol handle (udevice) is unconditionally installed to
> > > the agent. Then basic information will be retrieved from SCMI server via
> > > the protocol and saved into the agent instance's local storage.
> > >
> > > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > > ---
> > > v2
> > > * use helper functions, removing direct uses of ops
> > > ---
> > > drivers/firmware/scmi/scmi_agent-uclass.c | 116 ++++++++++++++++++++++
> > > include/scmi_agent-uclass.h | 70 ++++++++++++-
> > > 2 files changed, 184 insertions(+), 2 deletions(-)
> > >
> >
> > Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Etienne Carriere <etienne.carriere@foss.st.com>
with below reported typo preferrably addressed.
> >
> > > diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c
> > > index 2244fcf487e8..279c2c218913 100644
> > > --- a/drivers/firmware/scmi/scmi_agent-uclass.c
> > > +++ b/drivers/firmware/scmi/scmi_agent-uclass.c
> > > @@ -57,6 +57,9 @@ struct udevice *scmi_get_protocol(struct udevice *dev,
> > > }
> > >
> > > switch (id) {
> > > + case SCMI_PROTOCOL_ID_BASE:
> > > + proto = priv->base_dev;
> > > + break;
> > > case SCMI_PROTOCOL_ID_CLOCK:
> > > proto = priv->clock_dev;
> > > break;
> > > @@ -101,6 +104,9 @@ static int scmi_add_protocol(struct udevice *dev,
> > > }
> > >
> > > switch (proto_id) {
> > > + case SCMI_PROTOCOL_ID_BASE:
> > > + priv->base_dev = proto;
> > > + break;
> > > case SCMI_PROTOCOL_ID_CLOCK:
> > > priv->clock_dev = proto;
> > > break;
> > > @@ -229,6 +235,83 @@ int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg)
> > > return scmi_process_msg(parent, priv->channel, msg);
> > > }
> > >
> > > +/**
> > > + * scmi_fill_base_info - get base information about SCMI server
> > > + * @agent: SCMI agent device
> > > + * @dev: SCMI protocol device
> > > + *
> > > + * By using Base protocol commands, collect the base information
> > > + * about SCMI server.
> > > + *
> > > + * Return: 0 on success, error code otherwise
> > > + */
> > > +static int scmi_fill_base_info(struct udevice *agent, struct udevice *dev)
> > > +{
> > > + struct scmi_agent_priv *priv = dev_get_uclass_plat(agent);
> > > + int ret;
> > > +
> > > + ret = scmi_base_protocol_version(dev, &priv->version);
> > > + if (ret) {
> > > + dev_err(dev, "protocol_version() failed (%d)\n", ret);
> > > + return ret;
> > > + }
> > > + /* check for required version */
> > > + if (priv->version < SCMI_BASE_PROTOCOL_VERSION) {
> > > + dev_err(dev, "base protocol version (%d) lower than expected\n",
> > > + priv->version);
> > > + return -EPROTO;
> > > + }
> > > +
> > > + ret = scmi_base_protocol_attrs(dev, &priv->num_agents,
> > > + &priv->num_protocols);
> > > + if (ret) {
> > > + dev_err(dev, "protocol_attrs() failed (%d)\n", ret);
> > > + return ret;
> > > + }
> > > + ret = scmi_base_discover_vendor(dev, priv->vendor);
> > > + if (ret) {
> > > + dev_err(dev, "base_discover_vendor() failed (%d)\n", ret);
> > > + return ret;
> > > + }
> > > + ret = scmi_base_discover_sub_vendor(dev, priv->sub_vendor);
> > > + if (ret) {
> > > + if (ret != -EOPNOTSUPP) {
> > > + dev_err(dev, "base_discover_sub_vendor() failed (%d)\n",
> > > + ret);
> > > + return ret;
> > > + }
> > > + strcpy(priv->sub_vendor, "NA");
> > > + }
> > > + ret = scmi_base_discover_impl_version(dev, &priv->impl_version);
> > > + if (ret) {
> > > + dev_err(dev, "base_discover_impl_version() failed (%d)\n",
> > > + ret);
> > > + return ret;
> > > + }
> > > +
> > > + priv->agent_id = 0xffffffff; /* to avoid false claim */
> > > + ret = scmi_base_discover_agent(dev, 0xffffffff,
> > > + &priv->agent_id, priv->agent_name);
> > > + if (ret) {
> > > + if (ret != -EOPNOTSUPP) {
> > > + dev_err(dev,
> > > + "base_discover_agent() failed for myself (%d)\n",
> > > + ret);
> > > + return ret;
> > > + }
> > > + priv->agent_name[0] = '\0';
> > > + }
> > > +
> > > + ret = scmi_base_discover_list_protocols(dev, &priv->protocols);
> > > + if (ret != priv->num_protocols) {
> > > + dev_err(dev, "base_discover_list_protocols() failed (%d)\n",
> > > + ret);
> > > + return ret;
> > > + }
> > > +
> > > + return 0;
> > > +}
> > > +
> > > /*
> > > * SCMI agent devices binds devices of various uclasses depeding on
> > > * the FDT description. scmi_bind_protocol() is a generic bind sequence
> > > @@ -243,6 +326,39 @@ static int scmi_bind_protocols(struct udevice *dev)
> > > struct driver *drv;
> > > struct udevice *proto;
> > >
> > > + if (!uclass_get_device(UCLASS_SCMI_AGENT, 1, &agent)) {
> > > + /* This is a second SCMI agent */
> > > + dev_err(dev, "Cannot have more than one SCMI agent\n");
> > > + return -EEXIST;
> > > + }
> > > +
> > > + /* initialize the device from device tree */
> > > + drv = DM_DRIVER_GET(scmi_base_drv);
> > > + name = "scmi-base.0";
> > > + ret = device_bind(dev, drv, name, NULL, ofnode_null(), &proto);
> >
> > Why is this not in the devicetree too?
>
> I don't know the history of discussions, but it is
> because no binding for the base protocol is necessary, I guess,
> as it is a mandatory protocol without any customisable parameters.
> Please see kernel's Documentation/devicetree/bindings/firmware/arm,scmi.yaml.
>
> > > + if (ret) {
> > > + dev_err(dev, "failed to bind base protocol\n");
> > > + return ret;
> > > + }
> > > + ret = scmi_add_protocol(dev, SCMI_PROTOCOL_ID_BASE, proto);
> > > + if (ret) {
> > > + dev_err(dev, "failed to add protocol: %s, ret: %d\n",
> > > + proto->name, ret);
> > > + return ret;
> > > + }
> > > +
> > > + ret = device_probe(proto);
> > > + if (ret) {
> > > + dev_err(dev, "failed to probe base protocol\n");
> > > + return ret;
> > > + }
> > > +
> > > + ret = scmi_fill_base_info(dev, proto);
> > > + if (ret) {
> > > + dev_err(dev, "failed to get base information\n");
> > > + return ret;
> > > + }
> > > +
> > > dev_for_each_subnode(node, dev) {
> > > u32 protocol_id;
> > >
> > > diff --git a/include/scmi_agent-uclass.h b/include/scmi_agent-uclass.h
> > > index f9e7d3f51de1..0043a93c8d90 100644
> > > --- a/include/scmi_agent-uclass.h
> > > +++ b/include/scmi_agent-uclass.h
> > > @@ -5,6 +5,7 @@
> > > #ifndef _SCMI_AGENT_UCLASS_H
> > > #define _SCMI_AGENT_UCLASS_H
> > >
> > > +#include <scmi_protocols.h>
> > > #include <dm/device.h>
> > >
> > > struct scmi_msg;
> > > @@ -12,16 +13,81 @@ struct scmi_channel;
> > >
> > > /**
> > > * struct scmi_agent_priv - private data maintained by agent instance
> > > + * @version: Version
> > > + * @num_agents: Number of agents
> > > + * @num_protocols: Number of protocols
> > > + * @impl_version: Implementation version
> > > + * @protocols: Array of protocol IDs
> > > + * @vendor: Vendor name
> > > + * @sub_vendor: Sub-vendor name
> > > + * @agent_name: Agent name
> > > + * agent_id: Identifier of agent
typo: s/agent_id/@agent_id/
> > > + * @base_dev: SCMI base protocol device
> > > * @clock_dev: SCMI clock protocol device
> > > - * @clock_dev: SCMI reset domain protocol device
> > > - * @clock_dev: SCMI voltage domain protocol device
> > > + * @resetdom_dev: SCMI reset domain protocol device
> > > + * @voltagedom_dev: SCMI voltage domain protocol device
> > > */
> > > struct scmi_agent_priv {
> > > + u32 version;
> > > + u32 num_agents;
> > > + u32 num_protocols;
> > > + u32 impl_version;
> > > + u8 *protocols;
> > > + u8 vendor[SCMI_BASE_NAME_LENGTH_MAX];
> > > + u8 sub_vendor[SCMI_BASE_NAME_LENGTH_MAX];
> > > + u8 agent_name[SCMI_BASE_NAME_LENGTH_MAX];
> > > + u32 agent_id;
> > > + struct udevice *base_dev;
> > > struct udevice *clock_dev;
> > > struct udevice *resetdom_dev;
> > > struct udevice *voltagedom_dev;
> > > };
> > >
> > > +static inline u32 scmi_version(struct udevice *dev)
> > > +{
> > > + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->version;
> > > +}
> > > +
> > > +static inline u32 scmi_num_agents(struct udevice *dev)
> > > +{
> > > + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->num_agents;
> > > +}
> > > +
> > > +static inline u32 scmi_num_protocols(struct udevice *dev)
> > > +{
> > > + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->num_protocols;
> > > +}
> > > +
> > > +static inline u32 scmi_impl_version(struct udevice *dev)
> > > +{
> > > + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->impl_version;
> > > +}
> > > +
> > > +static inline u8 *scmi_protocols(struct udevice *dev)
> > > +{
> > > + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->protocols;
> > > +}
> > > +
> > > +static inline u8 *scmi_vendor(struct udevice *dev)
> > > +{
> > > + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->vendor;
> > > +}
> > > +
> > > +static inline u8 *scmi_sub_vendor(struct udevice *dev)
> > > +{
> > > + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->sub_vendor;
> > > +}
> > > +
> > > +static inline u8 *scmi_agent_name(struct udevice *dev)
> > > +{
> > > + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->agent_name;
> > > +}
> > > +
> > > +static inline u32 scmi_agent_id(struct udevice *dev)
> > > +{
> > > + return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->agent_id;
> > > +}
> >
> > Why these helper functions? It seems better to avoid inlining access
> > to dev_get_uclass_plat(). Are you worried about exposing the priv
> > struct to clients?
>
> Well, simply wanted to avoid repeating
> "((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->)" in the code.
>
> Thanks,
> -Takahiro Akashi
>
> > > +
> > > /**
> > > * struct scmi_transport_ops - The functions that a SCMI transport layer must implement.
> > > */
> > > --
> > > 2.41.0
> > >
> >
> > Regards,
> > Simon
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v2 06/12] sandbox: remove SCMI base node definition from test.dts
2023-07-26 8:37 [PATCH v2 00/12] firmware: scmi: add SCMI base protocol support AKASHI Takahiro
` (4 preceding siblings ...)
2023-07-26 8:38 ` [PATCH v2 05/12] firmware: scmi: install base protocol to SCMI agent AKASHI Takahiro
@ 2023-07-26 8:38 ` AKASHI Takahiro
2023-08-03 10:02 ` Etienne CARRIERE
2023-07-26 8:38 ` [PATCH v2 07/12] firmware: scmi: fake base protocol commands on sandbox AKASHI Takahiro
` (5 subsequent siblings)
11 siblings, 1 reply; 40+ messages in thread
From: AKASHI Takahiro @ 2023-07-26 8:38 UTC (permalink / raw)
To: trini, sjg; +Cc: etienne.carriere, u-boot, AKASHI Takahiro
SCMI base protocol is mandatory and doesn't need to be listed in a device
tree.
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
arch/sandbox/dts/test.dts | 4 ----
1 file changed, 4 deletions(-)
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index ff9f9222e6f9..2aad94681148 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -682,10 +682,6 @@
#address-cells = <1>;
#size-cells = <0>;
- protocol@10 {
- reg = <0x10>;
- };
-
clk_scmi: protocol@14 {
reg = <0x14>;
#clock-cells = <1>;
--
2.41.0
^ permalink raw reply related [flat|nested] 40+ messages in thread* RE: [PATCH v2 06/12] sandbox: remove SCMI base node definition from test.dts
2023-07-26 8:38 ` [PATCH v2 06/12] sandbox: remove SCMI base node definition from test.dts AKASHI Takahiro
@ 2023-08-03 10:02 ` Etienne CARRIERE
0 siblings, 0 replies; 40+ messages in thread
From: Etienne CARRIERE @ 2023-08-03 10:02 UTC (permalink / raw)
To: AKASHI Takahiro, trini@konsulko.com, sjg@chromium.org
Cc: u-boot@lists.denx.de
> From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> Sent: Wednesday, July 26, 2023 10:38
>
> SCMI base protocol is mandatory and doesn't need to be listed in a device
> tree.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Etienne Carriere <etienne.carriere@foss.st.com>
> ---
> arch/sandbox/dts/test.dts | 4 ----
> 1 file changed, 4 deletions(-)
>
> diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
> index ff9f9222e6f9..2aad94681148 100644
> --- a/arch/sandbox/dts/test.dts
> +++ b/arch/sandbox/dts/test.dts
> @@ -682,10 +682,6 @@
> #address-cells = <1>;
> #size-cells = <0>;
>
> - protocol@10 {
> - reg = <0x10>;
> - };
> -
> clk_scmi: protocol@14 {
> reg = <0x14>;
> #clock-cells = <1>;
> --
> 2.41.0
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v2 07/12] firmware: scmi: fake base protocol commands on sandbox
2023-07-26 8:37 [PATCH v2 00/12] firmware: scmi: add SCMI base protocol support AKASHI Takahiro
` (5 preceding siblings ...)
2023-07-26 8:38 ` [PATCH v2 06/12] sandbox: remove SCMI base node definition from test.dts AKASHI Takahiro
@ 2023-07-26 8:38 ` AKASHI Takahiro
2023-08-03 10:21 ` Etienne CARRIERE
2023-07-26 8:38 ` [PATCH v2 08/12] test: dm: simplify SCMI unit test " AKASHI Takahiro
` (4 subsequent siblings)
11 siblings, 1 reply; 40+ messages in thread
From: AKASHI Takahiro @ 2023-07-26 8:38 UTC (permalink / raw)
To: trini, sjg; +Cc: etienne.carriere, u-boot, AKASHI Takahiro
This is a simple implementation of SCMI base protocol for sandbox.
The main use is in SCMI unit test.
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
drivers/firmware/scmi/sandbox-scmi_agent.c | 359 ++++++++++++++++++++-
1 file changed, 358 insertions(+), 1 deletion(-)
diff --git a/drivers/firmware/scmi/sandbox-scmi_agent.c b/drivers/firmware/scmi/sandbox-scmi_agent.c
index 031882998dfa..1f0261ea5c94 100644
--- a/drivers/firmware/scmi/sandbox-scmi_agent.c
+++ b/drivers/firmware/scmi/sandbox-scmi_agent.c
@@ -14,11 +14,14 @@
#include <asm/io.h>
#include <asm/scmi_test.h>
#include <dm/device_compat.h>
+#include <linux/bitfield.h>
+#include <linux/kernel.h>
/*
* The sandbox SCMI agent driver simulates to some extend a SCMI message
* processing. It simulates few of the SCMI services for some of the
* SCMI protocols embedded in U-Boot. Currently:
+ * - SCMI base protocol
* - SCMI clock protocol emulates an agent exposing 2 clocks
* - SCMI reset protocol emulates an agent exposing a reset controller
* - SCMI voltage domain protocol emulates an agent exposing 2 regulators
@@ -33,6 +36,21 @@
* various uclass devices, as clocks and reset controllers.
*/
+#define SANDBOX_SCMI_BASE_PROTOCOL_VERSION SCMI_BASE_PROTOCOL_VERSION
+#define SANDBOX_SCMI_VENDOR "U-Boot"
+#define SANDBOX_SCMI_SUB_VENDOR "Sandbox"
+#define SANDBOX_SCMI_IMPL_VERSION 0x1
+#define SANDBOX_SCMI_AGENT_NAME "OSPM"
+#define SANDBOX_SCMI_PLATFORM_NAME "platform"
+
+static u8 protocols[] = {
+ SCMI_PROTOCOL_ID_CLOCK,
+ SCMI_PROTOCOL_ID_RESET_DOMAIN,
+ SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN,
+};
+
+#define NUM_PROTOCOLS ARRAY_SIZE(protocols)
+
static struct sandbox_scmi_clk scmi_clk[] = {
{ .rate = 333 },
{ .rate = 200 },
@@ -114,6 +132,316 @@ static struct sandbox_scmi_voltd *get_scmi_voltd_state(uint domain_id)
* Sandbox SCMI agent ops
*/
+/* Base Protocol */
+
+/**
+ * sandbox_scmi_base_protocol_version - implement SCMI_BASE_PROTOCOL_VERSION
+ * @udevice: SCMI device
+ * @msg: SCMI message
+ *
+ * Implement SCMI_BASE_PROTOCOL_VERSION command.
+ */
+static int sandbox_scmi_base_protocol_version(struct udevice *dev,
+ struct scmi_msg *msg)
+{
+ struct scmi_protocol_version_out *out = NULL;
+
+ if (!msg->out_msg || msg->out_msg_sz < sizeof(*out))
+ return -EINVAL;
+
+ out = (struct scmi_protocol_version_out *)msg->out_msg;
+ out->version = SANDBOX_SCMI_BASE_PROTOCOL_VERSION;
+ out->status = SCMI_SUCCESS;
+
+ return 0;
+}
+
+/**
+ * sandbox_scmi_base_protocol_attrs - implement SCMI_BASE_PROTOCOL_ATTRIBUTES
+ * @udevice: SCMI device
+ * @msg: SCMI message
+ *
+ * Implement SCMI_BASE_PROTOCOL_ATTRIBUTES command.
+ */
+static int sandbox_scmi_base_protocol_attrs(struct udevice *dev,
+ struct scmi_msg *msg)
+{
+ struct scmi_protocol_attrs_out *out = NULL;
+
+ if (!msg->out_msg || msg->out_msg_sz < sizeof(*out))
+ return -EINVAL;
+
+ out = (struct scmi_protocol_attrs_out *)msg->out_msg;
+ out->attributes = FIELD_PREP(0xff00, 2) | NUM_PROTOCOLS;
+ out->status = SCMI_SUCCESS;
+
+ return 0;
+}
+
+/**
+ * sandbox_scmi_base_message_attrs - implement
+ * SCMI_BASE_PROTOCOL_MESSAGE_ATTRIBUTES
+ * @udevice: SCMI device
+ * @msg: SCMI message
+ *
+ * Implement SCMI_BASE_PROTOCOL_MESSAGE_ATTRIBUTES command.
+ */
+static int sandbox_scmi_base_message_attrs(struct udevice *dev,
+ struct scmi_msg *msg)
+{
+ u32 message_id;
+ struct scmi_protocol_msg_attrs_out *out = NULL;
+
+ if (!msg->in_msg || msg->in_msg_sz < sizeof(message_id) ||
+ !msg->out_msg || msg->out_msg_sz < sizeof(*out))
+ return -EINVAL;
+
+ message_id = *(u32 *)msg->in_msg;
+ out = (struct scmi_protocol_msg_attrs_out *)msg->out_msg;
+
+ if (message_id >= SCMI_PROTOCOL_VERSION &&
+ message_id <= SCMI_BASE_RESET_AGENT_CONFIGURATION &&
+ message_id != SCMI_BASE_NOTIFY_ERRORS) {
+ out->attributes = 0;
+ out->status = SCMI_SUCCESS;
+ } else {
+ out->status = SCMI_NOT_FOUND;
+ }
+
+ return 0;
+}
+
+/**
+ * sandbox_scmi_base_discover_vendor - implement SCMI_BASE_DISCOVER_VENDOR
+ * @udevice: SCMI device
+ * @msg: SCMI message
+ *
+ * Implement SCMI_BASE_DISCOVER_VENDOR command
+ */
+static int sandbox_scmi_base_discover_vendor(struct udevice *dev,
+ struct scmi_msg *msg)
+{
+ struct scmi_base_discover_vendor_out *out = NULL;
+
+ if (!msg->out_msg || msg->out_msg_sz < sizeof(*out))
+ return -EINVAL;
+
+ out = (struct scmi_base_discover_vendor_out *)msg->out_msg;
+ strcpy(out->vendor_identifier, SANDBOX_SCMI_VENDOR);
+ out->status = SCMI_SUCCESS;
+
+ return 0;
+}
+
+/**
+ * sandbox_scmi_base_discover_sub_vendor - implement
+ * SCMI_BASE_DISCOVER_SUB_VENDOR
+ * @udevice: SCMI device
+ * @msg: SCMI message
+ *
+ * Implement SCMI_BASE_DISCOVER_SUB_VENDOR command
+ */
+static int sandbox_scmi_base_discover_sub_vendor(struct udevice *dev,
+ struct scmi_msg *msg)
+{
+ struct scmi_base_discover_vendor_out *out = NULL;
+
+ if (!msg->out_msg || msg->out_msg_sz < sizeof(*out))
+ return -EINVAL;
+
+ out = (struct scmi_base_discover_vendor_out *)msg->out_msg;
+ strcpy(out->vendor_identifier, SANDBOX_SCMI_SUB_VENDOR);
+ out->status = SCMI_SUCCESS;
+
+ return 0;
+}
+
+/**
+ * sandbox_scmi_base_discover_impl_version - implement
+ * SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION
+ * @udevice: SCMI device
+ * @msg: SCMI message
+ *
+ * Implement SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION command
+ */
+static int sandbox_scmi_base_discover_impl_version(struct udevice *dev,
+ struct scmi_msg *msg)
+{
+ struct scmi_base_discover_impl_version_out *out = NULL;
+
+ if (!msg->out_msg || msg->out_msg_sz < sizeof(*out))
+ return -EINVAL;
+
+ out = (struct scmi_base_discover_impl_version_out *)msg->out_msg;
+ out->impl_version = SANDBOX_SCMI_IMPL_VERSION;
+ out->status = SCMI_SUCCESS;
+
+ return 0;
+}
+
+/**
+ * sandbox_scmi_base_discover_list_protocols - implement
+ * SCMI_BASE_DISCOVER_LIST_PROTOCOLS
+ * @udevice: SCMI device
+ * @msg: SCMI message
+ *
+ * Implement SCMI_BASE_DISCOVER_LIST_PROTOCOLS command
+ */
+static int sandbox_scmi_base_discover_list_protocols(struct udevice *dev,
+ struct scmi_msg *msg)
+{
+ struct scmi_base_discover_list_protocols_out *out = NULL;
+
+ if (!msg->out_msg || msg->out_msg_sz < sizeof(*out))
+ return -EINVAL;
+
+ out = (struct scmi_base_discover_list_protocols_out *)msg->out_msg;
+ memcpy(out->protocols, protocols, sizeof(protocols));
+ out->num_protocols = NUM_PROTOCOLS;
+ out->status = SCMI_SUCCESS;
+
+ return 0;
+}
+
+/**
+ * sandbox_scmi_base_discover_agent - implement SCMI_BASE_DISCOVER_AGENT
+ * @udevice: SCMI device
+ * @msg: SCMI message
+ *
+ * Implement SCMI_BASE_DISCOVER_AGENT command
+ */
+static int sandbox_scmi_base_discover_agent(struct udevice *dev,
+ struct scmi_msg *msg)
+{
+ u32 agent_id;
+ struct scmi_base_discover_agent_out *out = NULL;
+
+ if (!msg->in_msg || msg->in_msg_sz < sizeof(agent_id) ||
+ !msg->out_msg || msg->out_msg_sz < sizeof(*out))
+ return -EINVAL;
+
+ agent_id = *(u32 *)msg->in_msg;
+ out = (struct scmi_base_discover_agent_out *)msg->out_msg;
+ out->status = SCMI_SUCCESS;
+ if (agent_id == 0xffffffff || agent_id == 1) {
+ out->agent_id = 1;
+ strcpy(out->name, SANDBOX_SCMI_AGENT_NAME);
+ } else if (!agent_id) {
+ out->agent_id = agent_id;
+ strcpy(out->name, SANDBOX_SCMI_PLATFORM_NAME);
+ } else {
+ out->status = SCMI_NOT_FOUND;
+ }
+
+ return 0;
+}
+
+/**
+ * sandbox_scmi_base_set_device_permissions - implement
+ * SCMI_BASE_SET_DEVICE_PERMISSIONS
+ * @udevice: SCMI device
+ * @msg: SCMI message
+ *
+ * Implement SCMI_BASE_SET_DEVICE_PERMISSIONS command
+ */
+static int sandbox_scmi_base_set_device_permissions(struct udevice *dev,
+ struct scmi_msg *msg)
+{
+ struct scmi_base_set_device_permissions_in *in = NULL;
+ u32 *status;
+
+ if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
+ !msg->out_msg || msg->out_msg_sz < sizeof(*status))
+ return -EINVAL;
+
+ in = (struct scmi_base_set_device_permissions_in *)msg->in_msg;
+ status = (u32 *)msg->out_msg;
+
+ if (in->agent_id != 1 || in->device_id != 0)
+ *status = SCMI_NOT_FOUND;
+ else if (in->flags & ~SCMI_BASE_SET_DEVICE_PERMISSIONS_ACCESS)
+ *status = SCMI_INVALID_PARAMETERS;
+ else if (in->flags & SCMI_BASE_SET_DEVICE_PERMISSIONS_ACCESS)
+ *status = SCMI_SUCCESS;
+ else
+ /* unset not allowed */
+ *status = SCMI_DENIED;
+
+ return 0;
+}
+
+/**
+ * sandbox_scmi_base_set_protocol_permissions - implement
+ * SCMI_BASE_SET_PROTOCOL_PERMISSIONS
+ * @udevice: SCMI device
+ * @msg: SCMI message
+ *
+ * Implement SCMI_BASE_SET_PROTOCOL_PERMISSIONS command
+ */
+static int sandbox_scmi_base_set_protocol_permissions(struct udevice *dev,
+ struct scmi_msg *msg)
+{
+ struct scmi_base_set_protocol_permissions_in *in = NULL;
+ u32 *status;
+ int i;
+
+ if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
+ !msg->out_msg || msg->out_msg_sz < sizeof(*status))
+ return -EINVAL;
+
+ in = (struct scmi_base_set_protocol_permissions_in *)msg->in_msg;
+ status = (u32 *)msg->out_msg;
+
+ for (i = 0; i < ARRAY_SIZE(protocols); i++)
+ if (protocols[i] == in->command_id)
+ break;
+ if (in->agent_id != 1 || in->device_id != 0 ||
+ i == ARRAY_SIZE(protocols))
+ *status = SCMI_NOT_FOUND;
+ else if (in->flags & ~SCMI_BASE_SET_PROTOCOL_PERMISSIONS_ACCESS)
+ *status = SCMI_INVALID_PARAMETERS;
+ else if (in->flags & SCMI_BASE_SET_PROTOCOL_PERMISSIONS_ACCESS)
+ *status = SCMI_SUCCESS;
+ else
+ /* unset not allowed */
+ *status = SCMI_DENIED;
+
+ return 0;
+}
+
+/**
+ * sandbox_scmi_base_reset_agent_configuration - implement
+ * SCMI_BASE_RESET_AGENT_CONFIGURATION
+ * @udevice: SCMI device
+ * @msg: SCMI message
+ *
+ * Implement SCMI_BASE_RESET_AGENT_CONFIGURATION command
+ */
+static int sandbox_scmi_base_reset_agent_configuration(struct udevice *dev,
+ struct scmi_msg *msg)
+{
+ struct scmi_base_reset_agent_configuration_in *in = NULL;
+ u32 *status;
+
+ if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
+ !msg->out_msg || msg->out_msg_sz < sizeof(*status))
+ return -EINVAL;
+
+ in = (struct scmi_base_reset_agent_configuration_in *)msg->in_msg;
+ status = (u32 *)msg->out_msg;
+
+ if (in->agent_id != 1)
+ *status = SCMI_NOT_FOUND;
+ else if (in->flags & ~SCMI_BASE_RESET_ALL_ACCESS_PERMISSIONS)
+ *status = SCMI_INVALID_PARAMETERS;
+ else
+ *status = SCMI_DENIED;
+
+ return 0;
+}
+
+/* Clock Protocol */
+
static int sandbox_scmi_clock_protocol_attribs(struct udevice *dev,
struct scmi_msg *msg)
{
@@ -475,6 +803,36 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev,
struct scmi_msg *msg)
{
switch (msg->protocol_id) {
+ case SCMI_PROTOCOL_ID_BASE:
+ switch (msg->message_id) {
+ case SCMI_PROTOCOL_VERSION:
+ return sandbox_scmi_base_protocol_version(dev, msg);
+ case SCMI_PROTOCOL_ATTRIBUTES:
+ return sandbox_scmi_base_protocol_attrs(dev, msg);
+ case SCMI_PROTOCOL_MESSAGE_ATTRIBUTES:
+ return sandbox_scmi_base_message_attrs(dev, msg);
+ case SCMI_BASE_DISCOVER_VENDOR:
+ return sandbox_scmi_base_discover_vendor(dev, msg);
+ case SCMI_BASE_DISCOVER_SUB_VENDOR:
+ return sandbox_scmi_base_discover_sub_vendor(dev, msg);
+ case SCMI_BASE_DISCOVER_IMPL_VERSION:
+ return sandbox_scmi_base_discover_impl_version(dev, msg);
+ case SCMI_BASE_DISCOVER_LIST_PROTOCOLS:
+ return sandbox_scmi_base_discover_list_protocols(dev, msg);
+ case SCMI_BASE_DISCOVER_AGENT:
+ return sandbox_scmi_base_discover_agent(dev, msg);
+ case SCMI_BASE_NOTIFY_ERRORS:
+ break;
+ case SCMI_BASE_SET_DEVICE_PERMISSIONS:
+ return sandbox_scmi_base_set_device_permissions(dev, msg);
+ case SCMI_BASE_SET_PROTOCOL_PERMISSIONS:
+ return sandbox_scmi_base_set_protocol_permissions(dev, msg);
+ case SCMI_BASE_RESET_AGENT_CONFIGURATION:
+ return sandbox_scmi_base_reset_agent_configuration(dev, msg);
+ default:
+ break;
+ }
+ break;
case SCMI_PROTOCOL_ID_CLOCK:
switch (msg->message_id) {
case SCMI_PROTOCOL_ATTRIBUTES:
@@ -517,7 +875,6 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev,
break;
}
break;
- case SCMI_PROTOCOL_ID_BASE:
case SCMI_PROTOCOL_ID_POWER_DOMAIN:
case SCMI_PROTOCOL_ID_SYSTEM:
case SCMI_PROTOCOL_ID_PERF:
--
2.41.0
^ permalink raw reply related [flat|nested] 40+ messages in thread* RE: [PATCH v2 07/12] firmware: scmi: fake base protocol commands on sandbox
2023-07-26 8:38 ` [PATCH v2 07/12] firmware: scmi: fake base protocol commands on sandbox AKASHI Takahiro
@ 2023-08-03 10:21 ` Etienne CARRIERE
0 siblings, 0 replies; 40+ messages in thread
From: Etienne CARRIERE @ 2023-08-03 10:21 UTC (permalink / raw)
To: AKASHI Takahiro, trini@konsulko.com, sjg@chromium.org
Cc: u-boot@lists.denx.de
> From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> Sent: Wednesday, July 26, 2023 10:38
>
> This is a simple implementation of SCMI base protocol for sandbox.
> The main use is in SCMI unit test.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Etienne Carriere <etienne.carriere@foss.st.com>
with reported typo addressed.
> ---
> drivers/firmware/scmi/sandbox-scmi_agent.c | 359 ++++++++++++++++++++-
> 1 file changed, 358 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/firmware/scmi/sandbox-scmi_agent.c b/drivers/firmware/scmi/sandbox-scmi_agent.c
> index 031882998dfa..1f0261ea5c94 100644
> --- a/drivers/firmware/scmi/sandbox-scmi_agent.c
> +++ b/drivers/firmware/scmi/sandbox-scmi_agent.c
> @@ -14,11 +14,14 @@
> #include <asm/io.h>
> #include <asm/scmi_test.h>
> #include <dm/device_compat.h>
> +#include <linux/bitfield.h>
> +#include <linux/kernel.h>
>
> /*
> * The sandbox SCMI agent driver simulates to some extend a SCMI message
> * processing. It simulates few of the SCMI services for some of the
> * SCMI protocols embedded in U-Boot. Currently:
> + * - SCMI base protocol
> * - SCMI clock protocol emulates an agent exposing 2 clocks
> * - SCMI reset protocol emulates an agent exposing a reset controller
> * - SCMI voltage domain protocol emulates an agent exposing 2 regulators
> @@ -33,6 +36,21 @@
> * various uclass devices, as clocks and reset controllers.
> */
>
> +#define SANDBOX_SCMI_BASE_PROTOCOL_VERSION SCMI_BASE_PROTOCOL_VERSION
> +#define SANDBOX_SCMI_VENDOR "U-Boot"
> +#define SANDBOX_SCMI_SUB_VENDOR "Sandbox"
> +#define SANDBOX_SCMI_IMPL_VERSION 0x1
> +#define SANDBOX_SCMI_AGENT_NAME "OSPM"
> +#define SANDBOX_SCMI_PLATFORM_NAME "platform"
> +
> +static u8 protocols[] = {
> + SCMI_PROTOCOL_ID_CLOCK,
> + SCMI_PROTOCOL_ID_RESET_DOMAIN,
> + SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN,
> +};
> +
> +#define NUM_PROTOCOLS ARRAY_SIZE(protocols)
> +
> static struct sandbox_scmi_clk scmi_clk[] = {
> { .rate = 333 },
> { .rate = 200 },
> @@ -114,6 +132,316 @@ static struct sandbox_scmi_voltd *get_scmi_voltd_state(uint domain_id)
> * Sandbox SCMI agent ops
> */
>
> +/* Base Protocol */
> +
> +/**
> + * sandbox_scmi_base_protocol_version - implement SCMI_BASE_PROTOCOL_VERSION
> + * @udevice: SCMI device
typo: s/udevice/dev/g here and in the other function inline descripion
comments below.
BR,
etienne
> + * @msg: SCMI message
> + *
> + * Implement SCMI_BASE_PROTOCOL_VERSION command.
> + */
> +static int sandbox_scmi_base_protocol_version(struct udevice *dev,
> + struct scmi_msg *msg)
> +{
> + struct scmi_protocol_version_out *out = NULL;
> +
> + if (!msg->out_msg || msg->out_msg_sz < sizeof(*out))
> + return -EINVAL;
> +
> + out = (struct scmi_protocol_version_out *)msg->out_msg;
> + out->version = SANDBOX_SCMI_BASE_PROTOCOL_VERSION;
> + out->status = SCMI_SUCCESS;
> +
> + return 0;
> +}
> +
> +/**
> + * sandbox_scmi_base_protocol_attrs - implement SCMI_BASE_PROTOCOL_ATTRIBUTES
> + * @udevice: SCMI device
> + * @msg: SCMI message
> + *
> + * Implement SCMI_BASE_PROTOCOL_ATTRIBUTES command.
> + */
> +static int sandbox_scmi_base_protocol_attrs(struct udevice *dev,
> + struct scmi_msg *msg)
> +{
> + struct scmi_protocol_attrs_out *out = NULL;
> +
> + if (!msg->out_msg || msg->out_msg_sz < sizeof(*out))
> + return -EINVAL;
> +
> + out = (struct scmi_protocol_attrs_out *)msg->out_msg;
> + out->attributes = FIELD_PREP(0xff00, 2) | NUM_PROTOCOLS;
> + out->status = SCMI_SUCCESS;
> +
> + return 0;
> +}
> +
> +/**
> + * sandbox_scmi_base_message_attrs - implement
> + * SCMI_BASE_PROTOCOL_MESSAGE_ATTRIBUTES
> + * @udevice: SCMI device
> + * @msg: SCMI message
> + *
> + * Implement SCMI_BASE_PROTOCOL_MESSAGE_ATTRIBUTES command.
> + */
> +static int sandbox_scmi_base_message_attrs(struct udevice *dev,
> + struct scmi_msg *msg)
> +{
> + u32 message_id;
> + struct scmi_protocol_msg_attrs_out *out = NULL;
> +
> + if (!msg->in_msg || msg->in_msg_sz < sizeof(message_id) ||
> + !msg->out_msg || msg->out_msg_sz < sizeof(*out))
> + return -EINVAL;
> +
> + message_id = *(u32 *)msg->in_msg;
> + out = (struct scmi_protocol_msg_attrs_out *)msg->out_msg;
> +
> + if (message_id >= SCMI_PROTOCOL_VERSION &&
> + message_id <= SCMI_BASE_RESET_AGENT_CONFIGURATION &&
> + message_id != SCMI_BASE_NOTIFY_ERRORS) {
> + out->attributes = 0;
> + out->status = SCMI_SUCCESS;
> + } else {
> + out->status = SCMI_NOT_FOUND;
> + }
> +
> + return 0;
> +}
> +
> +/**
> + * sandbox_scmi_base_discover_vendor - implement SCMI_BASE_DISCOVER_VENDOR
> + * @udevice: SCMI device
> + * @msg: SCMI message
> + *
> + * Implement SCMI_BASE_DISCOVER_VENDOR command
> + */
> +static int sandbox_scmi_base_discover_vendor(struct udevice *dev,
> + struct scmi_msg *msg)
> +{
> + struct scmi_base_discover_vendor_out *out = NULL;
> +
> + if (!msg->out_msg || msg->out_msg_sz < sizeof(*out))
> + return -EINVAL;
> +
> + out = (struct scmi_base_discover_vendor_out *)msg->out_msg;
> + strcpy(out->vendor_identifier, SANDBOX_SCMI_VENDOR);
> + out->status = SCMI_SUCCESS;
> +
> + return 0;
> +}
> +
> +/**
> + * sandbox_scmi_base_discover_sub_vendor - implement
> + * SCMI_BASE_DISCOVER_SUB_VENDOR
> + * @udevice: SCMI device
> + * @msg: SCMI message
> + *
> + * Implement SCMI_BASE_DISCOVER_SUB_VENDOR command
> + */
> +static int sandbox_scmi_base_discover_sub_vendor(struct udevice *dev,
> + struct scmi_msg *msg)
> +{
> + struct scmi_base_discover_vendor_out *out = NULL;
> +
> + if (!msg->out_msg || msg->out_msg_sz < sizeof(*out))
> + return -EINVAL;
> +
> + out = (struct scmi_base_discover_vendor_out *)msg->out_msg;
> + strcpy(out->vendor_identifier, SANDBOX_SCMI_SUB_VENDOR);
> + out->status = SCMI_SUCCESS;
> +
> + return 0;
> +}
> +
> +/**
> + * sandbox_scmi_base_discover_impl_version - implement
> + * SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION
> + * @udevice: SCMI device
> + * @msg: SCMI message
> + *
> + * Implement SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION command
> + */
> +static int sandbox_scmi_base_discover_impl_version(struct udevice *dev,
> + struct scmi_msg *msg)
> +{
> + struct scmi_base_discover_impl_version_out *out = NULL;
> +
> + if (!msg->out_msg || msg->out_msg_sz < sizeof(*out))
> + return -EINVAL;
> +
> + out = (struct scmi_base_discover_impl_version_out *)msg->out_msg;
> + out->impl_version = SANDBOX_SCMI_IMPL_VERSION;
> + out->status = SCMI_SUCCESS;
> +
> + return 0;
> +}
> +
> +/**
> + * sandbox_scmi_base_discover_list_protocols - implement
> + * SCMI_BASE_DISCOVER_LIST_PROTOCOLS
> + * @udevice: SCMI device
> + * @msg: SCMI message
> + *
> + * Implement SCMI_BASE_DISCOVER_LIST_PROTOCOLS command
> + */
> +static int sandbox_scmi_base_discover_list_protocols(struct udevice *dev,
> + struct scmi_msg *msg)
> +{
> + struct scmi_base_discover_list_protocols_out *out = NULL;
> +
> + if (!msg->out_msg || msg->out_msg_sz < sizeof(*out))
> + return -EINVAL;
> +
> + out = (struct scmi_base_discover_list_protocols_out *)msg->out_msg;
> + memcpy(out->protocols, protocols, sizeof(protocols));
> + out->num_protocols = NUM_PROTOCOLS;
> + out->status = SCMI_SUCCESS;
> +
> + return 0;
> +}
> +
> +/**
> + * sandbox_scmi_base_discover_agent - implement SCMI_BASE_DISCOVER_AGENT
> + * @udevice: SCMI device
> + * @msg: SCMI message
> + *
> + * Implement SCMI_BASE_DISCOVER_AGENT command
> + */
> +static int sandbox_scmi_base_discover_agent(struct udevice *dev,
> + struct scmi_msg *msg)
> +{
> + u32 agent_id;
> + struct scmi_base_discover_agent_out *out = NULL;
> +
> + if (!msg->in_msg || msg->in_msg_sz < sizeof(agent_id) ||
> + !msg->out_msg || msg->out_msg_sz < sizeof(*out))
> + return -EINVAL;
> +
> + agent_id = *(u32 *)msg->in_msg;
> + out = (struct scmi_base_discover_agent_out *)msg->out_msg;
> + out->status = SCMI_SUCCESS;
> + if (agent_id == 0xffffffff || agent_id == 1) {
> + out->agent_id = 1;
> + strcpy(out->name, SANDBOX_SCMI_AGENT_NAME);
> + } else if (!agent_id) {
> + out->agent_id = agent_id;
> + strcpy(out->name, SANDBOX_SCMI_PLATFORM_NAME);
> + } else {
> + out->status = SCMI_NOT_FOUND;
> + }
> +
> + return 0;
> +}
> +
> +/**
> + * sandbox_scmi_base_set_device_permissions - implement
> + * SCMI_BASE_SET_DEVICE_PERMISSIONS
> + * @udevice: SCMI device
> + * @msg: SCMI message
> + *
> + * Implement SCMI_BASE_SET_DEVICE_PERMISSIONS command
> + */
> +static int sandbox_scmi_base_set_device_permissions(struct udevice *dev,
> + struct scmi_msg *msg)
> +{
> + struct scmi_base_set_device_permissions_in *in = NULL;
> + u32 *status;
> +
> + if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
> + !msg->out_msg || msg->out_msg_sz < sizeof(*status))
> + return -EINVAL;
> +
> + in = (struct scmi_base_set_device_permissions_in *)msg->in_msg;
> + status = (u32 *)msg->out_msg;
> +
> + if (in->agent_id != 1 || in->device_id != 0)
> + *status = SCMI_NOT_FOUND;
> + else if (in->flags & ~SCMI_BASE_SET_DEVICE_PERMISSIONS_ACCESS)
> + *status = SCMI_INVALID_PARAMETERS;
> + else if (in->flags & SCMI_BASE_SET_DEVICE_PERMISSIONS_ACCESS)
> + *status = SCMI_SUCCESS;
> + else
> + /* unset not allowed */
> + *status = SCMI_DENIED;
> +
> + return 0;
> +}
> +
> +/**
> + * sandbox_scmi_base_set_protocol_permissions - implement
> + * SCMI_BASE_SET_PROTOCOL_PERMISSIONS
> + * @udevice: SCMI device
> + * @msg: SCMI message
> + *
> + * Implement SCMI_BASE_SET_PROTOCOL_PERMISSIONS command
> + */
> +static int sandbox_scmi_base_set_protocol_permissions(struct udevice *dev,
> + struct scmi_msg *msg)
> +{
> + struct scmi_base_set_protocol_permissions_in *in = NULL;
> + u32 *status;
> + int i;
> +
> + if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
> + !msg->out_msg || msg->out_msg_sz < sizeof(*status))
> + return -EINVAL;
> +
> + in = (struct scmi_base_set_protocol_permissions_in *)msg->in_msg;
> + status = (u32 *)msg->out_msg;
> +
> + for (i = 0; i < ARRAY_SIZE(protocols); i++)
> + if (protocols[i] == in->command_id)
> + break;
> + if (in->agent_id != 1 || in->device_id != 0 ||
> + i == ARRAY_SIZE(protocols))
> + *status = SCMI_NOT_FOUND;
> + else if (in->flags & ~SCMI_BASE_SET_PROTOCOL_PERMISSIONS_ACCESS)
> + *status = SCMI_INVALID_PARAMETERS;
> + else if (in->flags & SCMI_BASE_SET_PROTOCOL_PERMISSIONS_ACCESS)
> + *status = SCMI_SUCCESS;
> + else
> + /* unset not allowed */
> + *status = SCMI_DENIED;
> +
> + return 0;
> +}
> +
> +/**
> + * sandbox_scmi_base_reset_agent_configuration - implement
> + * SCMI_BASE_RESET_AGENT_CONFIGURATION
> + * @udevice: SCMI device
> + * @msg: SCMI message
> + *
> + * Implement SCMI_BASE_RESET_AGENT_CONFIGURATION command
> + */
> +static int sandbox_scmi_base_reset_agent_configuration(struct udevice *dev,
> + struct scmi_msg *msg)
> +{
> + struct scmi_base_reset_agent_configuration_in *in = NULL;
> + u32 *status;
> +
> + if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
> + !msg->out_msg || msg->out_msg_sz < sizeof(*status))
> + return -EINVAL;
> +
> + in = (struct scmi_base_reset_agent_configuration_in *)msg->in_msg;
> + status = (u32 *)msg->out_msg;
> +
> + if (in->agent_id != 1)
> + *status = SCMI_NOT_FOUND;
> + else if (in->flags & ~SCMI_BASE_RESET_ALL_ACCESS_PERMISSIONS)
> + *status = SCMI_INVALID_PARAMETERS;
> + else
> + *status = SCMI_DENIED;
> +
> + return 0;
> +}
> +
> +/* Clock Protocol */
> +
> static int sandbox_scmi_clock_protocol_attribs(struct udevice *dev,
> struct scmi_msg *msg)
> {
> @@ -475,6 +803,36 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev,
> struct scmi_msg *msg)
> {
> switch (msg->protocol_id) {
> + case SCMI_PROTOCOL_ID_BASE:
> + switch (msg->message_id) {
> + case SCMI_PROTOCOL_VERSION:
> + return sandbox_scmi_base_protocol_version(dev, msg);
> + case SCMI_PROTOCOL_ATTRIBUTES:
> + return sandbox_scmi_base_protocol_attrs(dev, msg);
> + case SCMI_PROTOCOL_MESSAGE_ATTRIBUTES:
> + return sandbox_scmi_base_message_attrs(dev, msg);
> + case SCMI_BASE_DISCOVER_VENDOR:
> + return sandbox_scmi_base_discover_vendor(dev, msg);
> + case SCMI_BASE_DISCOVER_SUB_VENDOR:
> + return sandbox_scmi_base_discover_sub_vendor(dev, msg);
> + case SCMI_BASE_DISCOVER_IMPL_VERSION:
> + return sandbox_scmi_base_discover_impl_version(dev, msg);
> + case SCMI_BASE_DISCOVER_LIST_PROTOCOLS:
> + return sandbox_scmi_base_discover_list_protocols(dev, msg);
> + case SCMI_BASE_DISCOVER_AGENT:
> + return sandbox_scmi_base_discover_agent(dev, msg);
> + case SCMI_BASE_NOTIFY_ERRORS:
> + break;
> + case SCMI_BASE_SET_DEVICE_PERMISSIONS:
> + return sandbox_scmi_base_set_device_permissions(dev, msg);
> + case SCMI_BASE_SET_PROTOCOL_PERMISSIONS:
> + return sandbox_scmi_base_set_protocol_permissions(dev, msg);
> + case SCMI_BASE_RESET_AGENT_CONFIGURATION:
> + return sandbox_scmi_base_reset_agent_configuration(dev, msg);
> + default:
> + break;
> + }
> + break;
> case SCMI_PROTOCOL_ID_CLOCK:
> switch (msg->message_id) {
> case SCMI_PROTOCOL_ATTRIBUTES:
> @@ -517,7 +875,6 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev,
> break;
> }
> break;
> - case SCMI_PROTOCOL_ID_BASE:
> case SCMI_PROTOCOL_ID_POWER_DOMAIN:
> case SCMI_PROTOCOL_ID_SYSTEM:
> case SCMI_PROTOCOL_ID_PERF:
> --
> 2.41.0
>
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v2 08/12] test: dm: simplify SCMI unit test on sandbox
2023-07-26 8:37 [PATCH v2 00/12] firmware: scmi: add SCMI base protocol support AKASHI Takahiro
` (6 preceding siblings ...)
2023-07-26 8:38 ` [PATCH v2 07/12] firmware: scmi: fake base protocol commands on sandbox AKASHI Takahiro
@ 2023-07-26 8:38 ` AKASHI Takahiro
2023-08-03 10:23 ` Etienne CARRIERE
2023-07-26 8:38 ` [PATCH v2 09/12] test: dm: add SCMI base protocol test AKASHI Takahiro
` (3 subsequent siblings)
11 siblings, 1 reply; 40+ messages in thread
From: AKASHI Takahiro @ 2023-07-26 8:38 UTC (permalink / raw)
To: trini, sjg; +Cc: etienne.carriere, u-boot, AKASHI Takahiro
Adding SCMI base protocol makes it inconvenient to hold the agent instance
(udevice) locally since the agent device will be re-created per each test.
Just remove it and simplify the test flows.
The test scenario is not changed at all.
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
arch/sandbox/include/asm/scmi_test.h | 7 ++-
drivers/firmware/scmi/sandbox-scmi_agent.c | 20 +------
drivers/firmware/scmi/scmi_agent-uclass.c | 3 -
test/dm/scmi.c | 64 +++++++---------------
4 files changed, 26 insertions(+), 68 deletions(-)
diff --git a/arch/sandbox/include/asm/scmi_test.h b/arch/sandbox/include/asm/scmi_test.h
index c72ec1e1cb25..2718336a9a50 100644
--- a/arch/sandbox/include/asm/scmi_test.h
+++ b/arch/sandbox/include/asm/scmi_test.h
@@ -89,10 +89,11 @@ struct sandbox_scmi_devices {
#ifdef CONFIG_SCMI_FIRMWARE
/**
- * sandbox_scmi_service_ctx - Get the simulated SCMI services context
+ * sandbox_scmi_agent_ctx - Get the simulated SCMI agent context
+ * @dev: Reference to the test agent
* @return: Reference to backend simulated resources state
*/
-struct sandbox_scmi_service *sandbox_scmi_service_ctx(void);
+struct sandbox_scmi_agent *sandbox_scmi_agent_ctx(struct udevice *dev);
/**
* sandbox_scmi_devices_ctx - Get references to devices accessed through SCMI
@@ -101,7 +102,7 @@ struct sandbox_scmi_service *sandbox_scmi_service_ctx(void);
*/
struct sandbox_scmi_devices *sandbox_scmi_devices_ctx(struct udevice *dev);
#else
-static inline struct sandbox_scmi_service *sandbox_scmi_service_ctx(void)
+static struct sandbox_scmi_agent *sandbox_scmi_agent_ctx(struct udevice *dev)
{
return NULL;
}
diff --git a/drivers/firmware/scmi/sandbox-scmi_agent.c b/drivers/firmware/scmi/sandbox-scmi_agent.c
index 1f0261ea5c94..ab8afb01de40 100644
--- a/drivers/firmware/scmi/sandbox-scmi_agent.c
+++ b/drivers/firmware/scmi/sandbox-scmi_agent.c
@@ -66,11 +66,9 @@ static struct sandbox_scmi_voltd scmi_voltd[] = {
{ .id = 1, .voltage_uv = 1800000 },
};
-static struct sandbox_scmi_service sandbox_scmi_service_state;
-
-struct sandbox_scmi_service *sandbox_scmi_service_ctx(void)
+struct sandbox_scmi_agent *sandbox_scmi_agent_ctx(struct udevice *dev)
{
- return &sandbox_scmi_service_state;
+ return dev_get_priv(dev);
}
static void debug_print_agent_state(struct udevice *dev, char *str)
@@ -898,16 +896,8 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev,
static int sandbox_scmi_test_remove(struct udevice *dev)
{
- struct sandbox_scmi_agent *agent = dev_get_priv(dev);
-
- if (agent != sandbox_scmi_service_ctx()->agent)
- return -EINVAL;
-
debug_print_agent_state(dev, "removed");
- /* We only need to dereference the agent in the context */
- sandbox_scmi_service_ctx()->agent = NULL;
-
return 0;
}
@@ -915,9 +905,6 @@ static int sandbox_scmi_test_probe(struct udevice *dev)
{
struct sandbox_scmi_agent *agent = dev_get_priv(dev);
- if (sandbox_scmi_service_ctx()->agent)
- return -EINVAL;
-
*agent = (struct sandbox_scmi_agent){
.clk = scmi_clk,
.clk_count = ARRAY_SIZE(scmi_clk),
@@ -929,9 +916,6 @@ static int sandbox_scmi_test_probe(struct udevice *dev)
debug_print_agent_state(dev, "probed");
- /* Save reference for tests purpose */
- sandbox_scmi_service_ctx()->agent = agent;
-
return 0;
};
diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c
index 279c2c218913..91cb172f3005 100644
--- a/drivers/firmware/scmi/scmi_agent-uclass.c
+++ b/drivers/firmware/scmi/scmi_agent-uclass.c
@@ -412,9 +412,6 @@ static int scmi_bind_protocols(struct udevice *dev)
}
}
- if (!ret)
- scmi_agent = dev;
-
return ret;
}
diff --git a/test/dm/scmi.c b/test/dm/scmi.c
index d87e2731ce42..881be3171b7c 100644
--- a/test/dm/scmi.c
+++ b/test/dm/scmi.c
@@ -23,22 +23,11 @@
#include <power/regulator.h>
#include <test/ut.h>
-static int ut_assert_scmi_state_preprobe(struct unit_test_state *uts)
-{
- struct sandbox_scmi_service *scmi_ctx = sandbox_scmi_service_ctx();
-
- ut_assertnonnull(scmi_ctx);
- ut_assertnull(scmi_ctx->agent);
-
- return 0;
-}
-
static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts,
+ struct sandbox_scmi_agent *agent,
struct udevice *dev)
{
struct sandbox_scmi_devices *scmi_devices;
- struct sandbox_scmi_service *scmi_ctx;
- struct sandbox_scmi_agent *agent;
/* Device references to check context against test sequence */
scmi_devices = sandbox_scmi_devices_ctx(dev);
@@ -48,10 +37,6 @@ static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts,
ut_asserteq(2, scmi_devices->regul_count);
/* State of the simulated SCMI server exposed */
- scmi_ctx = sandbox_scmi_service_ctx();
- ut_assertnonnull(scmi_ctx);
- agent = scmi_ctx->agent;
- ut_assertnonnull(agent);
ut_asserteq(3, agent->clk_count);
ut_assertnonnull(agent->clk);
ut_asserteq(1, agent->reset_count);
@@ -63,27 +48,32 @@ static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts,
}
static int load_sandbox_scmi_test_devices(struct unit_test_state *uts,
+ struct sandbox_scmi_agent **ctx,
struct udevice **dev)
{
- int ret;
+ struct udevice *agent_dev;
- ret = ut_assert_scmi_state_preprobe(uts);
- if (ret)
- return ret;
+ ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi",
+ &agent_dev));
+ ut_assertnonnull(agent_dev);
+
+ *ctx = sandbox_scmi_agent_ctx(agent_dev);
+ ut_assertnonnull(*ctx);
+ /* probe */
ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "sandbox_scmi",
dev));
ut_assertnonnull(*dev);
- return ut_assert_scmi_state_postprobe(uts, *dev);
+ return ut_assert_scmi_state_postprobe(uts, *ctx, *dev);
}
static int release_sandbox_scmi_test_devices(struct unit_test_state *uts,
struct udevice *dev)
{
+ /* un-probe */
ut_assertok(device_remove(dev, DM_REMOVE_NORMAL));
- /* Not sure test devices are fully removed, agent may not be visible */
return 0;
}
@@ -93,10 +83,11 @@ static int release_sandbox_scmi_test_devices(struct unit_test_state *uts,
*/
static int dm_test_scmi_sandbox_agent(struct unit_test_state *uts)
{
+ struct sandbox_scmi_agent *ctx;
struct udevice *dev = NULL;
int ret;
- ret = load_sandbox_scmi_test_devices(uts, &dev);
+ ret = load_sandbox_scmi_test_devices(uts, &ctx, &dev);
if (!ret)
ret = release_sandbox_scmi_test_devices(uts, dev);
@@ -106,23 +97,18 @@ DM_TEST(dm_test_scmi_sandbox_agent, UT_TESTF_SCAN_FDT);
static int dm_test_scmi_clocks(struct unit_test_state *uts)
{
- struct sandbox_scmi_devices *scmi_devices;
- struct sandbox_scmi_service *scmi_ctx;
struct sandbox_scmi_agent *agent;
+ struct sandbox_scmi_devices *scmi_devices;
struct udevice *dev;
int ret_dev;
int ret;
- ret = load_sandbox_scmi_test_devices(uts, &dev);
+ ret = load_sandbox_scmi_test_devices(uts, &agent, &dev);
if (ret)
return ret;
scmi_devices = sandbox_scmi_devices_ctx(dev);
ut_assertnonnull(scmi_devices);
- scmi_ctx = sandbox_scmi_service_ctx();
- ut_assertnonnull(scmi_ctx);
- agent = scmi_ctx->agent;
- ut_assertnonnull(agent);
/* Test SCMI clocks rate manipulation */
ut_asserteq(333, agent->clk[0].rate);
@@ -169,22 +155,17 @@ DM_TEST(dm_test_scmi_clocks, UT_TESTF_SCAN_FDT);
static int dm_test_scmi_resets(struct unit_test_state *uts)
{
- struct sandbox_scmi_devices *scmi_devices;
- struct sandbox_scmi_service *scmi_ctx;
struct sandbox_scmi_agent *agent;
+ struct sandbox_scmi_devices *scmi_devices;
struct udevice *dev = NULL;
int ret;
- ret = load_sandbox_scmi_test_devices(uts, &dev);
+ ret = load_sandbox_scmi_test_devices(uts, &agent, &dev);
if (ret)
return ret;
scmi_devices = sandbox_scmi_devices_ctx(dev);
ut_assertnonnull(scmi_devices);
- scmi_ctx = sandbox_scmi_service_ctx();
- ut_assertnonnull(scmi_ctx);
- agent = scmi_ctx->agent;
- ut_assertnonnull(agent);
/* Test SCMI resect controller manipulation */
ut_assert(!agent->reset[0].asserted);
@@ -201,21 +182,16 @@ DM_TEST(dm_test_scmi_resets, UT_TESTF_SCAN_FDT);
static int dm_test_scmi_voltage_domains(struct unit_test_state *uts)
{
- struct sandbox_scmi_devices *scmi_devices;
- struct sandbox_scmi_service *scmi_ctx;
struct sandbox_scmi_agent *agent;
+ struct sandbox_scmi_devices *scmi_devices;
struct dm_regulator_uclass_plat *uc_pdata;
struct udevice *dev;
struct udevice *regul0_dev;
- ut_assertok(load_sandbox_scmi_test_devices(uts, &dev));
+ ut_assertok(load_sandbox_scmi_test_devices(uts, &agent, &dev));
scmi_devices = sandbox_scmi_devices_ctx(dev);
ut_assertnonnull(scmi_devices);
- scmi_ctx = sandbox_scmi_service_ctx();
- ut_assertnonnull(scmi_ctx);
- agent = scmi_ctx->agent;
- ut_assertnonnull(agent);
/* Set/Get an SCMI voltage domain level */
regul0_dev = scmi_devices->regul[0];
--
2.41.0
^ permalink raw reply related [flat|nested] 40+ messages in thread* RE: [PATCH v2 08/12] test: dm: simplify SCMI unit test on sandbox
2023-07-26 8:38 ` [PATCH v2 08/12] test: dm: simplify SCMI unit test " AKASHI Takahiro
@ 2023-08-03 10:23 ` Etienne CARRIERE
0 siblings, 0 replies; 40+ messages in thread
From: Etienne CARRIERE @ 2023-08-03 10:23 UTC (permalink / raw)
To: AKASHI Takahiro, trini@konsulko.com, sjg@chromium.org
Cc: u-boot@lists.denx.de
> From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> Sent: Wednesday, July 26, 2023 10:38
>
> Adding SCMI base protocol makes it inconvenient to hold the agent instance
> (udevice) locally since the agent device will be re-created per each test.
> Just remove it and simplify the test flows.
> The test scenario is not changed at all.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> ---
Reviewed-by: Etienne Carriere <etienne.carriere@foss.st.com>
> arch/sandbox/include/asm/scmi_test.h | 7 ++-
> drivers/firmware/scmi/sandbox-scmi_agent.c | 20 +------
> drivers/firmware/scmi/scmi_agent-uclass.c | 3 -
> test/dm/scmi.c | 64 +++++++---------------
> 4 files changed, 26 insertions(+), 68 deletions(-)
>
> diff --git a/arch/sandbox/include/asm/scmi_test.h b/arch/sandbox/include/asm/scmi_test.h
> index c72ec1e1cb25..2718336a9a50 100644
> --- a/arch/sandbox/include/asm/scmi_test.h
> +++ b/arch/sandbox/include/asm/scmi_test.h
> @@ -89,10 +89,11 @@ struct sandbox_scmi_devices {
>
> #ifdef CONFIG_SCMI_FIRMWARE
> /**
> - * sandbox_scmi_service_ctx - Get the simulated SCMI services context
> + * sandbox_scmi_agent_ctx - Get the simulated SCMI agent context
> + * @dev: Reference to the test agent
> * @return: Reference to backend simulated resources state
> */
> -struct sandbox_scmi_service *sandbox_scmi_service_ctx(void);
> +struct sandbox_scmi_agent *sandbox_scmi_agent_ctx(struct udevice *dev);
>
> /**
> * sandbox_scmi_devices_ctx - Get references to devices accessed through SCMI
> @@ -101,7 +102,7 @@ struct sandbox_scmi_service *sandbox_scmi_service_ctx(void);
> */
> struct sandbox_scmi_devices *sandbox_scmi_devices_ctx(struct udevice *dev);
> #else
> -static inline struct sandbox_scmi_service *sandbox_scmi_service_ctx(void)
> +static struct sandbox_scmi_agent *sandbox_scmi_agent_ctx(struct udevice *dev)
> {
> return NULL;
> }
> diff --git a/drivers/firmware/scmi/sandbox-scmi_agent.c b/drivers/firmware/scmi/sandbox-scmi_agent.c
> index 1f0261ea5c94..ab8afb01de40 100644
> --- a/drivers/firmware/scmi/sandbox-scmi_agent.c
> +++ b/drivers/firmware/scmi/sandbox-scmi_agent.c
> @@ -66,11 +66,9 @@ static struct sandbox_scmi_voltd scmi_voltd[] = {
> { .id = 1, .voltage_uv = 1800000 },
> };
>
> -static struct sandbox_scmi_service sandbox_scmi_service_state;
> -
> -struct sandbox_scmi_service *sandbox_scmi_service_ctx(void)
> +struct sandbox_scmi_agent *sandbox_scmi_agent_ctx(struct udevice *dev)
> {
> - return &sandbox_scmi_service_state;
> + return dev_get_priv(dev);
> }
>
> static void debug_print_agent_state(struct udevice *dev, char *str)
> @@ -898,16 +896,8 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev,
>
> static int sandbox_scmi_test_remove(struct udevice *dev)
> {
> - struct sandbox_scmi_agent *agent = dev_get_priv(dev);
> -
> - if (agent != sandbox_scmi_service_ctx()->agent)
> - return -EINVAL;
> -
> debug_print_agent_state(dev, "removed");
>
> - /* We only need to dereference the agent in the context */
> - sandbox_scmi_service_ctx()->agent = NULL;
> -
> return 0;
> }
>
> @@ -915,9 +905,6 @@ static int sandbox_scmi_test_probe(struct udevice *dev)
> {
> struct sandbox_scmi_agent *agent = dev_get_priv(dev);
>
> - if (sandbox_scmi_service_ctx()->agent)
> - return -EINVAL;
> -
> *agent = (struct sandbox_scmi_agent){
> .clk = scmi_clk,
> .clk_count = ARRAY_SIZE(scmi_clk),
> @@ -929,9 +916,6 @@ static int sandbox_scmi_test_probe(struct udevice *dev)
>
> debug_print_agent_state(dev, "probed");
>
> - /* Save reference for tests purpose */
> - sandbox_scmi_service_ctx()->agent = agent;
> -
> return 0;
> };
>
> diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c
> index 279c2c218913..91cb172f3005 100644
> --- a/drivers/firmware/scmi/scmi_agent-uclass.c
> +++ b/drivers/firmware/scmi/scmi_agent-uclass.c
> @@ -412,9 +412,6 @@ static int scmi_bind_protocols(struct udevice *dev)
> }
> }
>
> - if (!ret)
> - scmi_agent = dev;
> -
> return ret;
> }
>
> diff --git a/test/dm/scmi.c b/test/dm/scmi.c
> index d87e2731ce42..881be3171b7c 100644
> --- a/test/dm/scmi.c
> +++ b/test/dm/scmi.c
> @@ -23,22 +23,11 @@
> #include <power/regulator.h>
> #include <test/ut.h>
>
> -static int ut_assert_scmi_state_preprobe(struct unit_test_state *uts)
> -{
> - struct sandbox_scmi_service *scmi_ctx = sandbox_scmi_service_ctx();
> -
> - ut_assertnonnull(scmi_ctx);
> - ut_assertnull(scmi_ctx->agent);
> -
> - return 0;
> -}
> -
> static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts,
> + struct sandbox_scmi_agent *agent,
> struct udevice *dev)
> {
> struct sandbox_scmi_devices *scmi_devices;
> - struct sandbox_scmi_service *scmi_ctx;
> - struct sandbox_scmi_agent *agent;
>
> /* Device references to check context against test sequence */
> scmi_devices = sandbox_scmi_devices_ctx(dev);
> @@ -48,10 +37,6 @@ static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts,
> ut_asserteq(2, scmi_devices->regul_count);
>
> /* State of the simulated SCMI server exposed */
> - scmi_ctx = sandbox_scmi_service_ctx();
> - ut_assertnonnull(scmi_ctx);
> - agent = scmi_ctx->agent;
> - ut_assertnonnull(agent);
> ut_asserteq(3, agent->clk_count);
> ut_assertnonnull(agent->clk);
> ut_asserteq(1, agent->reset_count);
> @@ -63,27 +48,32 @@ static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts,
> }
>
> static int load_sandbox_scmi_test_devices(struct unit_test_state *uts,
> + struct sandbox_scmi_agent **ctx,
> struct udevice **dev)
> {
> - int ret;
> + struct udevice *agent_dev;
>
> - ret = ut_assert_scmi_state_preprobe(uts);
> - if (ret)
> - return ret;
> + ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi",
> + &agent_dev));
> + ut_assertnonnull(agent_dev);
> +
> + *ctx = sandbox_scmi_agent_ctx(agent_dev);
> + ut_assertnonnull(*ctx);
>
> + /* probe */
> ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "sandbox_scmi",
> dev));
> ut_assertnonnull(*dev);
>
> - return ut_assert_scmi_state_postprobe(uts, *dev);
> + return ut_assert_scmi_state_postprobe(uts, *ctx, *dev);
> }
>
> static int release_sandbox_scmi_test_devices(struct unit_test_state *uts,
> struct udevice *dev)
> {
> + /* un-probe */
> ut_assertok(device_remove(dev, DM_REMOVE_NORMAL));
>
> - /* Not sure test devices are fully removed, agent may not be visible */
> return 0;
> }
>
> @@ -93,10 +83,11 @@ static int release_sandbox_scmi_test_devices(struct unit_test_state *uts,
> */
> static int dm_test_scmi_sandbox_agent(struct unit_test_state *uts)
> {
> + struct sandbox_scmi_agent *ctx;
> struct udevice *dev = NULL;
> int ret;
>
> - ret = load_sandbox_scmi_test_devices(uts, &dev);
> + ret = load_sandbox_scmi_test_devices(uts, &ctx, &dev);
> if (!ret)
> ret = release_sandbox_scmi_test_devices(uts, dev);
>
> @@ -106,23 +97,18 @@ DM_TEST(dm_test_scmi_sandbox_agent, UT_TESTF_SCAN_FDT);
>
> static int dm_test_scmi_clocks(struct unit_test_state *uts)
> {
> - struct sandbox_scmi_devices *scmi_devices;
> - struct sandbox_scmi_service *scmi_ctx;
> struct sandbox_scmi_agent *agent;
> + struct sandbox_scmi_devices *scmi_devices;
> struct udevice *dev;
> int ret_dev;
> int ret;
>
> - ret = load_sandbox_scmi_test_devices(uts, &dev);
> + ret = load_sandbox_scmi_test_devices(uts, &agent, &dev);
> if (ret)
> return ret;
>
> scmi_devices = sandbox_scmi_devices_ctx(dev);
> ut_assertnonnull(scmi_devices);
> - scmi_ctx = sandbox_scmi_service_ctx();
> - ut_assertnonnull(scmi_ctx);
> - agent = scmi_ctx->agent;
> - ut_assertnonnull(agent);
>
> /* Test SCMI clocks rate manipulation */
> ut_asserteq(333, agent->clk[0].rate);
> @@ -169,22 +155,17 @@ DM_TEST(dm_test_scmi_clocks, UT_TESTF_SCAN_FDT);
>
> static int dm_test_scmi_resets(struct unit_test_state *uts)
> {
> - struct sandbox_scmi_devices *scmi_devices;
> - struct sandbox_scmi_service *scmi_ctx;
> struct sandbox_scmi_agent *agent;
> + struct sandbox_scmi_devices *scmi_devices;
> struct udevice *dev = NULL;
> int ret;
>
> - ret = load_sandbox_scmi_test_devices(uts, &dev);
> + ret = load_sandbox_scmi_test_devices(uts, &agent, &dev);
> if (ret)
> return ret;
>
> scmi_devices = sandbox_scmi_devices_ctx(dev);
> ut_assertnonnull(scmi_devices);
> - scmi_ctx = sandbox_scmi_service_ctx();
> - ut_assertnonnull(scmi_ctx);
> - agent = scmi_ctx->agent;
> - ut_assertnonnull(agent);
>
> /* Test SCMI resect controller manipulation */
> ut_assert(!agent->reset[0].asserted);
> @@ -201,21 +182,16 @@ DM_TEST(dm_test_scmi_resets, UT_TESTF_SCAN_FDT);
>
> static int dm_test_scmi_voltage_domains(struct unit_test_state *uts)
> {
> - struct sandbox_scmi_devices *scmi_devices;
> - struct sandbox_scmi_service *scmi_ctx;
> struct sandbox_scmi_agent *agent;
> + struct sandbox_scmi_devices *scmi_devices;
> struct dm_regulator_uclass_plat *uc_pdata;
> struct udevice *dev;
> struct udevice *regul0_dev;
>
> - ut_assertok(load_sandbox_scmi_test_devices(uts, &dev));
> + ut_assertok(load_sandbox_scmi_test_devices(uts, &agent, &dev));
>
> scmi_devices = sandbox_scmi_devices_ctx(dev);
> ut_assertnonnull(scmi_devices);
> - scmi_ctx = sandbox_scmi_service_ctx();
> - ut_assertnonnull(scmi_ctx);
> - agent = scmi_ctx->agent;
> - ut_assertnonnull(agent);
>
> /* Set/Get an SCMI voltage domain level */
> regul0_dev = scmi_devices->regul[0];
> --
> 2.41.0
>
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v2 09/12] test: dm: add SCMI base protocol test
2023-07-26 8:37 [PATCH v2 00/12] firmware: scmi: add SCMI base protocol support AKASHI Takahiro
` (7 preceding siblings ...)
2023-07-26 8:38 ` [PATCH v2 08/12] test: dm: simplify SCMI unit test " AKASHI Takahiro
@ 2023-07-26 8:38 ` AKASHI Takahiro
2023-07-27 0:53 ` Simon Glass
2023-08-03 10:25 ` Etienne CARRIERE
2023-07-26 8:38 ` [PATCH v2 10/12] cmd: add scmi command for SCMI firmware AKASHI Takahiro
` (2 subsequent siblings)
11 siblings, 2 replies; 40+ messages in thread
From: AKASHI Takahiro @ 2023-07-26 8:38 UTC (permalink / raw)
To: trini, sjg; +Cc: etienne.carriere, u-boot, AKASHI Takahiro
Added is a new unit test for SCMI base protocol, which will exercise all
the commands provided by the protocol, except SCMI_BASE_NOTIFY_ERRORS.
$ ut dm scmi_base
It is assumed that test.dtb is used as sandbox's device tree.
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
v2
* use helper functions, removing direct uses of ops
---
test/dm/scmi.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 109 insertions(+)
diff --git a/test/dm/scmi.c b/test/dm/scmi.c
index 881be3171b7c..41d46548f7fd 100644
--- a/test/dm/scmi.c
+++ b/test/dm/scmi.c
@@ -16,6 +16,9 @@
#include <clk.h>
#include <dm.h>
#include <reset.h>
+#include <scmi_agent.h>
+#include <scmi_agent-uclass.h>
+#include <scmi_protocols.h>
#include <asm/scmi_test.h>
#include <dm/device-internal.h>
#include <dm/test.h>
@@ -95,6 +98,112 @@ static int dm_test_scmi_sandbox_agent(struct unit_test_state *uts)
}
DM_TEST(dm_test_scmi_sandbox_agent, UT_TESTF_SCAN_FDT);
+static int dm_test_scmi_base(struct unit_test_state *uts)
+{
+ struct udevice *agent_dev, *base;
+ struct scmi_agent_priv *priv;
+ u32 version, num_agents, num_protocols, impl_version;
+ u32 attributes, agent_id;
+ char vendor[SCMI_BASE_NAME_LENGTH_MAX],
+ agent_name[SCMI_BASE_NAME_LENGTH_MAX];
+ u8 *protocols;
+ int ret;
+
+ /* preparation */
+ ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi",
+ &agent_dev));
+ ut_assertnonnull(agent_dev);
+ ut_assertnonnull(priv = dev_get_uclass_plat(agent_dev));
+ ut_assertnonnull(base = scmi_get_protocol(agent_dev,
+ SCMI_PROTOCOL_ID_BASE));
+
+ /* version */
+ ret = scmi_base_protocol_version(base, &version);
+ ut_assertok(ret);
+ ut_asserteq(priv->version, version);
+
+ /* protocol attributes */
+ ret = scmi_base_protocol_attrs(base, &num_agents, &num_protocols);
+ ut_assertok(ret);
+ ut_asserteq(priv->num_agents, num_agents);
+ ut_asserteq(priv->num_protocols, num_protocols);
+
+ /* discover vendor */
+ ret = scmi_base_discover_vendor(base, vendor);
+ ut_assertok(ret);
+ ut_asserteq_str(priv->vendor, vendor);
+
+ /* message attributes */
+ ret = scmi_protocol_message_attrs(base,
+ SCMI_BASE_DISCOVER_SUB_VENDOR,
+ &attributes);
+ ut_assertok(ret);
+ ut_assertok(attributes);
+
+ /* discover sub vendor */
+ ret = scmi_base_discover_sub_vendor(base, vendor);
+ ut_assertok(ret);
+ ut_asserteq_str(priv->sub_vendor, vendor);
+
+ /* impl version */
+ ret = scmi_base_discover_impl_version(base, &impl_version);
+ ut_assertok(ret);
+ ut_asserteq(priv->impl_version, impl_version);
+
+ /* discover agent (my self) */
+ ret = scmi_base_discover_agent(base, 0xffffffff, &agent_id, agent_name);
+ ut_assertok(ret);
+ ut_asserteq(priv->agent_id, agent_id);
+ ut_asserteq_str(priv->agent_name, agent_name);
+
+ /* discover protocols */
+ ret = scmi_base_discover_list_protocols(base, &protocols);
+ ut_asserteq(num_protocols, ret);
+ ut_asserteq_mem(priv->protocols, protocols, sizeof(u8) * num_protocols);
+ free(protocols);
+
+ /*
+ * NOTE: Sandbox SCMI driver handles device-0 only. It supports setting
+ * access and protocol permissions, but doesn't allow unsetting them nor
+ * resetting the configurations.
+ */
+ /* set device permissions */
+ ret = scmi_base_set_device_permissions(base, agent_id, 0,
+ SCMI_BASE_SET_DEVICE_PERMISSIONS_ACCESS);
+ ut_assertok(ret); /* SCMI_SUCCESS */
+ ret = scmi_base_set_device_permissions(base, agent_id, 1,
+ SCMI_BASE_SET_DEVICE_PERMISSIONS_ACCESS);
+ ut_asserteq(-ENOENT, ret); /* SCMI_NOT_FOUND */
+ ret = scmi_base_set_device_permissions(base, agent_id, 0, 0);
+ ut_asserteq(-EACCES, ret); /* SCMI_DENIED */
+
+ /* set protocol permissions */
+ ret = scmi_base_set_protocol_permissions(base, agent_id, 0,
+ SCMI_PROTOCOL_ID_CLOCK,
+ SCMI_BASE_SET_PROTOCOL_PERMISSIONS_ACCESS);
+ ut_assertok(ret); /* SCMI_SUCCESS */
+ ret = scmi_base_set_protocol_permissions(base, agent_id, 1,
+ SCMI_PROTOCOL_ID_CLOCK,
+ SCMI_BASE_SET_PROTOCOL_PERMISSIONS_ACCESS);
+ ut_asserteq(-ENOENT, ret); /* SCMI_NOT_FOUND */
+ ret = scmi_base_set_protocol_permissions(base, agent_id, 0,
+ SCMI_PROTOCOL_ID_CLOCK, 0);
+ ut_asserteq(-EACCES, ret); /* SCMI_DENIED */
+
+ /* reset agent configuration */
+ ret = scmi_base_reset_agent_configuration(base, agent_id, 0);
+ ut_asserteq(-EACCES, ret); /* SCMI_DENIED */
+ ret = scmi_base_reset_agent_configuration(base, agent_id,
+ SCMI_BASE_RESET_ALL_ACCESS_PERMISSIONS);
+ ut_asserteq(-EACCES, ret); /* SCMI_DENIED */
+ ret = scmi_base_reset_agent_configuration(base, agent_id, 0);
+ ut_asserteq(-EACCES, ret); /* SCMI_DENIED */
+
+ return 0;
+}
+
+DM_TEST(dm_test_scmi_base, UT_TESTF_SCAN_FDT);
+
static int dm_test_scmi_clocks(struct unit_test_state *uts)
{
struct sandbox_scmi_agent *agent;
--
2.41.0
^ permalink raw reply related [flat|nested] 40+ messages in thread* Re: [PATCH v2 09/12] test: dm: add SCMI base protocol test
2023-07-26 8:38 ` [PATCH v2 09/12] test: dm: add SCMI base protocol test AKASHI Takahiro
@ 2023-07-27 0:53 ` Simon Glass
2023-08-03 10:25 ` Etienne CARRIERE
1 sibling, 0 replies; 40+ messages in thread
From: Simon Glass @ 2023-07-27 0:53 UTC (permalink / raw)
To: AKASHI Takahiro; +Cc: trini, etienne.carriere, u-boot
\On Wed, 26 Jul 2023 at 02:39, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> Added is a new unit test for SCMI base protocol, which will exercise all
> the commands provided by the protocol, except SCMI_BASE_NOTIFY_ERRORS.
> $ ut dm scmi_base
> It is assumed that test.dtb is used as sandbox's device tree.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
> v2
> * use helper functions, removing direct uses of ops
> ---
> test/dm/scmi.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 109 insertions(+)
Reviewed-by: Simon Glass <sjg@chromium.org>
^ permalink raw reply [flat|nested] 40+ messages in thread
* RE: [PATCH v2 09/12] test: dm: add SCMI base protocol test
2023-07-26 8:38 ` [PATCH v2 09/12] test: dm: add SCMI base protocol test AKASHI Takahiro
2023-07-27 0:53 ` Simon Glass
@ 2023-08-03 10:25 ` Etienne CARRIERE
1 sibling, 0 replies; 40+ messages in thread
From: Etienne CARRIERE @ 2023-08-03 10:25 UTC (permalink / raw)
To: AKASHI Takahiro, trini@konsulko.com, sjg@chromium.org
Cc: u-boot@lists.denx.de
> From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> Sent: Wednesday, July 26, 2023 10:38
>
> Added is a new unit test for SCMI base protocol, which will exercise all
> the commands provided by the protocol, except SCMI_BASE_NOTIFY_ERRORS.
> $ ut dm scmi_base
> It is assumed that test.dtb is used as sandbox's device tree.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
> v2
> * use helper functions, removing direct uses of ops
> ---
Reviewed-by: Etienne Carriere <etienne.carriere@foss.st.com>
with reported issue fixed.
> test/dm/scmi.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 109 insertions(+)
>
> diff --git a/test/dm/scmi.c b/test/dm/scmi.c
> index 881be3171b7c..41d46548f7fd 100644
> --- a/test/dm/scmi.c
> +++ b/test/dm/scmi.c
> @@ -16,6 +16,9 @@
> #include <clk.h>
> #include <dm.h>
> #include <reset.h>
> +#include <scmi_agent.h>
> +#include <scmi_agent-uclass.h>
> +#include <scmi_protocols.h>
> #include <asm/scmi_test.h>
> #include <dm/device-internal.h>
> #include <dm/test.h>
> @@ -95,6 +98,112 @@ static int dm_test_scmi_sandbox_agent(struct unit_test_state *uts)
> }
> DM_TEST(dm_test_scmi_sandbox_agent, UT_TESTF_SCAN_FDT);
>
> +static int dm_test_scmi_base(struct unit_test_state *uts)
> +{
> + struct udevice *agent_dev, *base;
> + struct scmi_agent_priv *priv;
> + u32 version, num_agents, num_protocols, impl_version;
> + u32 attributes, agent_id;
> + char vendor[SCMI_BASE_NAME_LENGTH_MAX],
> + agent_name[SCMI_BASE_NAME_LENGTH_MAX];
> + u8 *protocols;
> + int ret;
> +
> + /* preparation */
> + ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi",
> + &agent_dev));
> + ut_assertnonnull(agent_dev);
> + ut_assertnonnull(priv = dev_get_uclass_plat(agent_dev));
> + ut_assertnonnull(base = scmi_get_protocol(agent_dev,
> + SCMI_PROTOCOL_ID_BASE));
> +
> + /* version */
> + ret = scmi_base_protocol_version(base, &version);
> + ut_assertok(ret);
> + ut_asserteq(priv->version, version);
> +
> + /* protocol attributes */
> + ret = scmi_base_protocol_attrs(base, &num_agents, &num_protocols);
Typo: s/scmi_base_protocol_attrs/scmi_base_protocol_message_attrs/
This issue is fixed in patch 12/12 but should be squashed here to
prevent a build error.
BR,
etienne
> + ut_assertok(ret);
> + ut_asserteq(priv->num_agents, num_agents);
> + ut_asserteq(priv->num_protocols, num_protocols);
> +
> + /* discover vendor */
> + ret = scmi_base_discover_vendor(base, vendor);
> + ut_assertok(ret);
> + ut_asserteq_str(priv->vendor, vendor);
> +
> + /* message attributes */
> + ret = scmi_protocol_message_attrs(base,
> + SCMI_BASE_DISCOVER_SUB_VENDOR,
> + &attributes);
> + ut_assertok(ret);
> + ut_assertok(attributes);
> +
> + /* discover sub vendor */
> + ret = scmi_base_discover_sub_vendor(base, vendor);
> + ut_assertok(ret);
> + ut_asserteq_str(priv->sub_vendor, vendor);
> +
> + /* impl version */
> + ret = scmi_base_discover_impl_version(base, &impl_version);
> + ut_assertok(ret);
> + ut_asserteq(priv->impl_version, impl_version);
> +
> + /* discover agent (my self) */
> + ret = scmi_base_discover_agent(base, 0xffffffff, &agent_id, agent_name);
> + ut_assertok(ret);
> + ut_asserteq(priv->agent_id, agent_id);
> + ut_asserteq_str(priv->agent_name, agent_name);
> +
> + /* discover protocols */
> + ret = scmi_base_discover_list_protocols(base, &protocols);
> + ut_asserteq(num_protocols, ret);
> + ut_asserteq_mem(priv->protocols, protocols, sizeof(u8) * num_protocols);
> + free(protocols);
> +
> + /*
> + * NOTE: Sandbox SCMI driver handles device-0 only. It supports setting
> + * access and protocol permissions, but doesn't allow unsetting them nor
> + * resetting the configurations.
> + */
> + /* set device permissions */
> + ret = scmi_base_set_device_permissions(base, agent_id, 0,
> + SCMI_BASE_SET_DEVICE_PERMISSIONS_ACCESS);
> + ut_assertok(ret); /* SCMI_SUCCESS */
> + ret = scmi_base_set_device_permissions(base, agent_id, 1,
> + SCMI_BASE_SET_DEVICE_PERMISSIONS_ACCESS);
> + ut_asserteq(-ENOENT, ret); /* SCMI_NOT_FOUND */
> + ret = scmi_base_set_device_permissions(base, agent_id, 0, 0);
> + ut_asserteq(-EACCES, ret); /* SCMI_DENIED */
> +
> + /* set protocol permissions */
> + ret = scmi_base_set_protocol_permissions(base, agent_id, 0,
> + SCMI_PROTOCOL_ID_CLOCK,
> + SCMI_BASE_SET_PROTOCOL_PERMISSIONS_ACCESS);
> + ut_assertok(ret); /* SCMI_SUCCESS */
> + ret = scmi_base_set_protocol_permissions(base, agent_id, 1,
> + SCMI_PROTOCOL_ID_CLOCK,
> + SCMI_BASE_SET_PROTOCOL_PERMISSIONS_ACCESS);
> + ut_asserteq(-ENOENT, ret); /* SCMI_NOT_FOUND */
> + ret = scmi_base_set_protocol_permissions(base, agent_id, 0,
> + SCMI_PROTOCOL_ID_CLOCK, 0);
> + ut_asserteq(-EACCES, ret); /* SCMI_DENIED */
> +
> + /* reset agent configuration */
> + ret = scmi_base_reset_agent_configuration(base, agent_id, 0);
> + ut_asserteq(-EACCES, ret); /* SCMI_DENIED */
> + ret = scmi_base_reset_agent_configuration(base, agent_id,
> + SCMI_BASE_RESET_ALL_ACCESS_PERMISSIONS);
> + ut_asserteq(-EACCES, ret); /* SCMI_DENIED */
> + ret = scmi_base_reset_agent_configuration(base, agent_id, 0);
> + ut_asserteq(-EACCES, ret); /* SCMI_DENIED */
> +
> + return 0;
> +}
> +
> +DM_TEST(dm_test_scmi_base, UT_TESTF_SCAN_FDT);
> +
> static int dm_test_scmi_clocks(struct unit_test_state *uts)
> {
> struct sandbox_scmi_agent *agent;
> --
> 2.41.0
>
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v2 10/12] cmd: add scmi command for SCMI firmware
2023-07-26 8:37 [PATCH v2 00/12] firmware: scmi: add SCMI base protocol support AKASHI Takahiro
` (8 preceding siblings ...)
2023-07-26 8:38 ` [PATCH v2 09/12] test: dm: add SCMI base protocol test AKASHI Takahiro
@ 2023-07-26 8:38 ` AKASHI Takahiro
2023-07-27 0:53 ` Simon Glass
2023-08-03 10:28 ` Etienne CARRIERE
2023-07-26 8:38 ` [PATCH v2 11/12] doc: cmd: add documentation for scmi AKASHI Takahiro
2023-07-26 8:38 ` [PATCH v2 12/12] test: dm: add scmi command test AKASHI Takahiro
11 siblings, 2 replies; 40+ messages in thread
From: AKASHI Takahiro @ 2023-07-26 8:38 UTC (permalink / raw)
To: trini, sjg; +Cc: etienne.carriere, u-boot, AKASHI Takahiro
This command, "scmi", may provide a command line interface to various SCMI
protocols. It supports at least initially SCMI base protocol and is
intended mainly for debug purpose.
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
v2
* remove sub command category, 'scmi base', for simplicity
---
cmd/Kconfig | 9 ++
cmd/Makefile | 1 +
cmd/scmi.c | 334 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 344 insertions(+)
create mode 100644 cmd/scmi.c
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 02e54f1e50fe..15d1d7b9863f 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2504,6 +2504,15 @@ config CMD_CROS_EC
a number of sub-commands for performing EC tasks such as
updating its flash, accessing a small saved context area
and talking to the I2C bus behind the EC (if there is one).
+
+config CMD_SCMI
+ bool "Enable scmi command"
+ depends on SCMI_FIRMWARE
+ default n
+ help
+ This command provides user interfaces to several SCMI (System
+ Control and Management Interface) protocols available on Arm
+ platforms to manage system resources.
endmenu
menu "Filesystem commands"
diff --git a/cmd/Makefile b/cmd/Makefile
index 6c37521b4e2b..826e0b74b587 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -156,6 +156,7 @@ obj-$(CONFIG_CMD_SATA) += sata.o
obj-$(CONFIG_CMD_NVME) += nvme.o
obj-$(CONFIG_SANDBOX) += sb.o
obj-$(CONFIG_CMD_SF) += sf.o
+obj-$(CONFIG_CMD_SCMI) += scmi.o
obj-$(CONFIG_CMD_SCSI) += scsi.o disk.o
obj-$(CONFIG_CMD_SHA1SUM) += sha1sum.o
obj-$(CONFIG_CMD_SEAMA) += seama.o
diff --git a/cmd/scmi.c b/cmd/scmi.c
new file mode 100644
index 000000000000..5ecd9051b48d
--- /dev/null
+++ b/cmd/scmi.c
@@ -0,0 +1,334 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * SCMI (System Control and Management Interface) utility command
+ *
+ * Copyright (c) 2023 Linaro Limited
+ * Author: AKASHI Takahiro
+ */
+
+#include <common.h>
+#include <command.h>
+#include <exports.h>
+#include <scmi_agent.h>
+#include <scmi_agent-uclass.h>
+#include <asm/types.h>
+#include <dm/device.h>
+#include <dm/uclass.h> /* uclass_get_device */
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+
+static struct udevice *agent;
+static struct udevice *base_proto;
+
+struct {
+ enum scmi_std_protocol id;
+ const char *name;
+} protocol_name[] = {
+ {SCMI_PROTOCOL_ID_BASE, "Base"},
+ {SCMI_PROTOCOL_ID_POWER_DOMAIN, "Power domain management"},
+ {SCMI_PROTOCOL_ID_SYSTEM, "System power management"},
+ {SCMI_PROTOCOL_ID_PERF, "Performance domain management"},
+ {SCMI_PROTOCOL_ID_CLOCK, "Clock management"},
+ {SCMI_PROTOCOL_ID_SENSOR, "Sensor management"},
+ {SCMI_PROTOCOL_ID_RESET_DOMAIN, "Reset domain management"},
+ {SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN, "Voltage domain management"},
+};
+
+/**
+ * get_proto_name() - get the name of SCMI protocol
+ *
+ * @id: SCMI Protocol ID
+ *
+ * Get the printable name of the protocol, @id
+ *
+ * Return: Name string on success, NULL on failure
+ */
+static const char *get_proto_name(enum scmi_std_protocol id)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(protocol_name); i++)
+ if (id == protocol_name[i].id)
+ return protocol_name[i].name;
+
+ return NULL;
+}
+
+/**
+ * do_scmi_info() - get the information of SCMI services
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ *
+ * Get the information of SCMI services using various interfaces
+ * provided by the Base protocol.
+ *
+ * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
+ */
+static int do_scmi_info(struct cmd_tbl *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ u32 agent_id, num_protocols;
+ u8 agent_name[SCMI_BASE_NAME_LENGTH_MAX], *protocols;
+ int i, ret;
+
+ if (argc != 1)
+ return CMD_RET_USAGE;
+
+ printf("SCMI device: %s\n", agent->name);
+ printf(" protocol version: 0x%x\n", scmi_version(agent));
+ printf(" # of agents: %d\n", scmi_num_agents(agent));
+ for (i = 0; i < scmi_num_agents(agent); i++) {
+ ret = scmi_base_discover_agent(base_proto, i, &agent_id,
+ agent_name);
+ if (ret) {
+ if (ret != -EOPNOTSUPP)
+ printf("base_discover_agent() failed for id: %d (%d)\n",
+ i, ret);
+ break;
+ }
+ printf(" %c%2d: %s\n", i == scmi_agent_id(agent) ? '>' : ' ',
+ i, agent_name);
+ }
+ printf(" # of protocols: %d\n", scmi_num_protocols(agent));
+ num_protocols = scmi_num_protocols(agent);
+ protocols = scmi_protocols(agent);
+ if (protocols)
+ for (i = 0; i < num_protocols; i++)
+ printf(" %s\n", get_proto_name(protocols[i]));
+ printf(" vendor: %s\n", scmi_vendor(agent));
+ printf(" sub vendor: %s\n", scmi_sub_vendor(agent));
+ printf(" impl version: 0x%x\n", scmi_impl_version(agent));
+
+ return CMD_RET_SUCCESS;
+}
+
+/**
+ * do_scmi_set_dev() - set access permission to device
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ *
+ * Set access permission to device with SCMI_BASE_SET_DEVICE_PERMISSIONS
+ *
+ * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
+ */
+static int do_scmi_set_dev(struct cmd_tbl *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ u32 agent_id, device_id, flags, attributes;
+ char *end;
+ int ret;
+
+ if (argc != 4)
+ return CMD_RET_USAGE;
+
+ agent_id = simple_strtoul(argv[1], &end, 16);
+ if (*end != '\0')
+ return CMD_RET_USAGE;
+
+ device_id = simple_strtoul(argv[2], &end, 16);
+ if (*end != '\0')
+ return CMD_RET_USAGE;
+
+ flags = simple_strtoul(argv[3], &end, 16);
+ if (*end != '\0')
+ return CMD_RET_USAGE;
+
+ ret = scmi_base_protocol_message_attrs(base_proto,
+ SCMI_BASE_SET_DEVICE_PERMISSIONS,
+ &attributes);
+ if (ret) {
+ printf("This operation is not supported\n");
+ return CMD_RET_FAILURE;
+ }
+
+ ret = scmi_base_set_device_permissions(base_proto, agent_id,
+ device_id, flags);
+ if (ret) {
+ printf("%s access to device:%u failed (%d)\n",
+ flags ? "Allowing" : "Denying", device_id, ret);
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+/**
+ * do_scmi_set_proto() - set protocol permission to device
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ *
+ * Set protocol permission to device with SCMI_BASE_SET_PROTOCOL_PERMISSIONS
+ *
+ * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
+ */
+static int do_scmi_set_proto(struct cmd_tbl *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ u32 agent_id, device_id, protocol_id, flags, attributes;
+ char *end;
+ int ret;
+
+ if (argc != 5)
+ return CMD_RET_USAGE;
+
+ agent_id = simple_strtoul(argv[1], &end, 16);
+ if (*end != '\0')
+ return CMD_RET_USAGE;
+
+ device_id = simple_strtoul(argv[2], &end, 16);
+ if (*end != '\0')
+ return CMD_RET_USAGE;
+
+ protocol_id = simple_strtoul(argv[3], &end, 16);
+ if (*end != '\0')
+ return CMD_RET_USAGE;
+
+ flags = simple_strtoul(argv[4], &end, 16);
+ if (*end != '\0')
+ return CMD_RET_USAGE;
+
+ ret = scmi_base_protocol_message_attrs(base_proto,
+ SCMI_BASE_SET_PROTOCOL_PERMISSIONS,
+ &attributes);
+ if (ret) {
+ printf("This operation is not supported\n");
+ return CMD_RET_FAILURE;
+ }
+
+ ret = scmi_base_set_protocol_permissions(base_proto, agent_id,
+ device_id, protocol_id,
+ flags);
+ if (ret) {
+ printf("%s access to protocol:0x%x on device:%u failed (%d)\n",
+ flags ? "Allowing" : "Denying", protocol_id, device_id,
+ ret);
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+/**
+ * do_scmi_reset() - reset platform resource settings
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ *
+ * Reset platform resource settings with BASE_RESET_AGENT_CONFIGURATION
+ *
+ * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
+ */
+static int do_scmi_reset(struct cmd_tbl *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ u32 agent_id, flags, attributes;
+ char *end;
+ int ret;
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ agent_id = simple_strtoul(argv[1], &end, 16);
+ if (*end != '\0')
+ return CMD_RET_USAGE;
+
+ flags = simple_strtoul(argv[2], &end, 16);
+ if (*end != '\0')
+ return CMD_RET_USAGE;
+
+ ret = scmi_base_protocol_message_attrs(base_proto,
+ SCMI_BASE_RESET_AGENT_CONFIGURATION,
+ &attributes);
+ if (ret) {
+ printf("Reset is not supported\n");
+ return CMD_RET_FAILURE;
+ }
+
+ ret = scmi_base_reset_agent_configuration(base_proto, agent_id, flags);
+ if (ret) {
+ printf("Reset failed (%d)\n", ret);
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static struct cmd_tbl cmd_scmi_sub[] = {
+ U_BOOT_CMD_MKENT(info, CONFIG_SYS_MAXARGS, 1,
+ do_scmi_info, "", ""),
+ U_BOOT_CMD_MKENT(perm_dev, CONFIG_SYS_MAXARGS, 1,
+ do_scmi_set_dev, "", ""),
+ U_BOOT_CMD_MKENT(perm_proto, CONFIG_SYS_MAXARGS, 1,
+ do_scmi_set_proto, "", ""),
+ U_BOOT_CMD_MKENT(reset, CONFIG_SYS_MAXARGS, 1,
+ do_scmi_reset, "", ""),
+};
+
+/**
+ * do_scmi() - SCMI utility
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ *
+ * Provide user interfaces to SCMI protocols.
+ *
+ * Return: CMD_RET_SUCCESS on success,
+ * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
+ */
+static int do_scmi(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct cmd_tbl *cp;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ argc--; argv++;
+
+ if (!agent) {
+ if (uclass_get_device(UCLASS_SCMI_AGENT, 0, &agent)) {
+ printf("Cannot find any SCMI agent\n");
+ return CMD_RET_FAILURE;
+ }
+ }
+
+ if (!base_proto)
+ base_proto = scmi_get_protocol(agent, SCMI_PROTOCOL_ID_BASE);
+ if (!base_proto) {
+ printf("SCMI base protocol not found\n");
+ return CMD_RET_FAILURE;
+ }
+
+ cp = find_cmd_tbl(argv[0], cmd_scmi_sub, ARRAY_SIZE(cmd_scmi_sub));
+ if (!cp)
+ return CMD_RET_USAGE;
+
+ return cp->cmd(cmdtp, flag, argc, argv);
+}
+
+static char scmi_help_text[] =
+ " - SCMI utility\n"
+ " info - get the info of SCMI services\n"
+ " perm_dev <agent id> <device id> <flags>\n"
+ " - set access permission to device\n"
+ " perm_proto <agent id> <device id> <protocol id> <flags>\n"
+ " - set protocol permission to device\n"
+ " reset <agent id> <flags>\n"
+ " - reset platform resource settings\n"
+ "";
+
+U_BOOT_CMD(scmi, CONFIG_SYS_MAXARGS, 0, do_scmi, "SCMI utility",
+ scmi_help_text);
--
2.41.0
^ permalink raw reply related [flat|nested] 40+ messages in thread* Re: [PATCH v2 10/12] cmd: add scmi command for SCMI firmware
2023-07-26 8:38 ` [PATCH v2 10/12] cmd: add scmi command for SCMI firmware AKASHI Takahiro
@ 2023-07-27 0:53 ` Simon Glass
2023-08-03 10:28 ` Etienne CARRIERE
1 sibling, 0 replies; 40+ messages in thread
From: Simon Glass @ 2023-07-27 0:53 UTC (permalink / raw)
To: AKASHI Takahiro; +Cc: trini, etienne.carriere, u-boot
On Wed, 26 Jul 2023 at 02:40, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> This command, "scmi", may provide a command line interface to various SCMI
> protocols. It supports at least initially SCMI base protocol and is
> intended mainly for debug purpose.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
> v2
> * remove sub command category, 'scmi base', for simplicity
> ---
> cmd/Kconfig | 9 ++
> cmd/Makefile | 1 +
> cmd/scmi.c | 334 +++++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 344 insertions(+)
> create mode 100644 cmd/scmi.c
>
Reviewed-by: Simon Glass <sjg@chromium.org>
^ permalink raw reply [flat|nested] 40+ messages in thread
* RE: [PATCH v2 10/12] cmd: add scmi command for SCMI firmware
2023-07-26 8:38 ` [PATCH v2 10/12] cmd: add scmi command for SCMI firmware AKASHI Takahiro
2023-07-27 0:53 ` Simon Glass
@ 2023-08-03 10:28 ` Etienne CARRIERE
1 sibling, 0 replies; 40+ messages in thread
From: Etienne CARRIERE @ 2023-08-03 10:28 UTC (permalink / raw)
To: AKASHI Takahiro, trini@konsulko.com, sjg@chromium.org
Cc: u-boot@lists.denx.de
> From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> Sent: Wednesday, July 26, 2023 10:38
>
> This command, "scmi", may provide a command line interface to various SCMI
> protocols. It supports at least initially SCMI base protocol and is
> intended mainly for debug purpose.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
> v2
> * remove sub command category, 'scmi base', for simplicity
Reviewed-by: Etienne Carriere <etienne.carriere@foss.st.com>
> ---
> cmd/Kconfig | 9 ++
> cmd/Makefile | 1 +
> cmd/scmi.c | 334 +++++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 344 insertions(+)
> create mode 100644 cmd/scmi.c
>
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index 02e54f1e50fe..15d1d7b9863f 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -2504,6 +2504,15 @@ config CMD_CROS_EC
> a number of sub-commands for performing EC tasks such as
> updating its flash, accessing a small saved context area
> and talking to the I2C bus behind the EC (if there is one).
> +
> +config CMD_SCMI
> + bool "Enable scmi command"
> + depends on SCMI_FIRMWARE
> + default n
> + help
> + This command provides user interfaces to several SCMI (System
> + Control and Management Interface) protocols available on Arm
> + platforms to manage system resources.
> endmenu
>
> menu "Filesystem commands"
> diff --git a/cmd/Makefile b/cmd/Makefile
> index 6c37521b4e2b..826e0b74b587 100644
> --- a/cmd/Makefile
> +++ b/cmd/Makefile
> @@ -156,6 +156,7 @@ obj-$(CONFIG_CMD_SATA) += sata.o
> obj-$(CONFIG_CMD_NVME) += nvme.o
> obj-$(CONFIG_SANDBOX) += sb.o
> obj-$(CONFIG_CMD_SF) += sf.o
> +obj-$(CONFIG_CMD_SCMI) += scmi.o
> obj-$(CONFIG_CMD_SCSI) += scsi.o disk.o
> obj-$(CONFIG_CMD_SHA1SUM) += sha1sum.o
> obj-$(CONFIG_CMD_SEAMA) += seama.o
> diff --git a/cmd/scmi.c b/cmd/scmi.c
> new file mode 100644
> index 000000000000..5ecd9051b48d
> --- /dev/null
> +++ b/cmd/scmi.c
> @@ -0,0 +1,334 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * SCMI (System Control and Management Interface) utility command
> + *
> + * Copyright (c) 2023 Linaro Limited
> + * Author: AKASHI Takahiro
> + */
> +
> +#include <common.h>
> +#include <command.h>
> +#include <exports.h>
> +#include <scmi_agent.h>
> +#include <scmi_agent-uclass.h>
> +#include <asm/types.h>
> +#include <dm/device.h>
> +#include <dm/uclass.h> /* uclass_get_device */
> +#include <linux/bitfield.h>
> +#include <linux/bitops.h>
> +
> +static struct udevice *agent;
> +static struct udevice *base_proto;
> +
> +struct {
> + enum scmi_std_protocol id;
> + const char *name;
> +} protocol_name[] = {
> + {SCMI_PROTOCOL_ID_BASE, "Base"},
> + {SCMI_PROTOCOL_ID_POWER_DOMAIN, "Power domain management"},
> + {SCMI_PROTOCOL_ID_SYSTEM, "System power management"},
> + {SCMI_PROTOCOL_ID_PERF, "Performance domain management"},
> + {SCMI_PROTOCOL_ID_CLOCK, "Clock management"},
> + {SCMI_PROTOCOL_ID_SENSOR, "Sensor management"},
> + {SCMI_PROTOCOL_ID_RESET_DOMAIN, "Reset domain management"},
> + {SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN, "Voltage domain management"},
> +};
> +
> +/**
> + * get_proto_name() - get the name of SCMI protocol
> + *
> + * @id: SCMI Protocol ID
> + *
> + * Get the printable name of the protocol, @id
> + *
> + * Return: Name string on success, NULL on failure
> + */
> +static const char *get_proto_name(enum scmi_std_protocol id)
> +{
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(protocol_name); i++)
> + if (id == protocol_name[i].id)
> + return protocol_name[i].name;
> +
> + return NULL;
> +}
> +
> +/**
> + * do_scmi_info() - get the information of SCMI services
> + *
> + * @cmdtp: Command table
> + * @flag: Command flag
> + * @argc: Number of arguments
> + * @argv: Argument array
> + *
> + * Get the information of SCMI services using various interfaces
> + * provided by the Base protocol.
> + *
> + * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
> + */
> +static int do_scmi_info(struct cmd_tbl *cmdtp, int flag, int argc,
> + char * const argv[])
> +{
> + u32 agent_id, num_protocols;
> + u8 agent_name[SCMI_BASE_NAME_LENGTH_MAX], *protocols;
> + int i, ret;
> +
> + if (argc != 1)
> + return CMD_RET_USAGE;
> +
> + printf("SCMI device: %s\n", agent->name);
> + printf(" protocol version: 0x%x\n", scmi_version(agent));
> + printf(" # of agents: %d\n", scmi_num_agents(agent));
> + for (i = 0; i < scmi_num_agents(agent); i++) {
> + ret = scmi_base_discover_agent(base_proto, i, &agent_id,
> + agent_name);
> + if (ret) {
> + if (ret != -EOPNOTSUPP)
> + printf("base_discover_agent() failed for id: %d (%d)\n",
> + i, ret);
> + break;
> + }
> + printf(" %c%2d: %s\n", i == scmi_agent_id(agent) ? '>' : ' ',
> + i, agent_name);
> + }
> + printf(" # of protocols: %d\n", scmi_num_protocols(agent));
> + num_protocols = scmi_num_protocols(agent);
> + protocols = scmi_protocols(agent);
> + if (protocols)
> + for (i = 0; i < num_protocols; i++)
> + printf(" %s\n", get_proto_name(protocols[i]));
> + printf(" vendor: %s\n", scmi_vendor(agent));
> + printf(" sub vendor: %s\n", scmi_sub_vendor(agent));
> + printf(" impl version: 0x%x\n", scmi_impl_version(agent));
> +
> + return CMD_RET_SUCCESS;
> +}
> +
> +/**
> + * do_scmi_set_dev() - set access permission to device
> + *
> + * @cmdtp: Command table
> + * @flag: Command flag
> + * @argc: Number of arguments
> + * @argv: Argument array
> + *
> + * Set access permission to device with SCMI_BASE_SET_DEVICE_PERMISSIONS
> + *
> + * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
> + */
> +static int do_scmi_set_dev(struct cmd_tbl *cmdtp, int flag, int argc,
> + char * const argv[])
> +{
> + u32 agent_id, device_id, flags, attributes;
> + char *end;
> + int ret;
> +
> + if (argc != 4)
> + return CMD_RET_USAGE;
> +
> + agent_id = simple_strtoul(argv[1], &end, 16);
> + if (*end != '\0')
> + return CMD_RET_USAGE;
> +
> + device_id = simple_strtoul(argv[2], &end, 16);
> + if (*end != '\0')
> + return CMD_RET_USAGE;
> +
> + flags = simple_strtoul(argv[3], &end, 16);
> + if (*end != '\0')
> + return CMD_RET_USAGE;
> +
> + ret = scmi_base_protocol_message_attrs(base_proto,
> + SCMI_BASE_SET_DEVICE_PERMISSIONS,
> + &attributes);
> + if (ret) {
> + printf("This operation is not supported\n");
> + return CMD_RET_FAILURE;
> + }
> +
> + ret = scmi_base_set_device_permissions(base_proto, agent_id,
> + device_id, flags);
> + if (ret) {
> + printf("%s access to device:%u failed (%d)\n",
> + flags ? "Allowing" : "Denying", device_id, ret);
> + return CMD_RET_FAILURE;
> + }
> +
> + return CMD_RET_SUCCESS;
> +}
> +
> +/**
> + * do_scmi_set_proto() - set protocol permission to device
> + *
> + * @cmdtp: Command table
> + * @flag: Command flag
> + * @argc: Number of arguments
> + * @argv: Argument array
> + *
> + * Set protocol permission to device with SCMI_BASE_SET_PROTOCOL_PERMISSIONS
> + *
> + * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
> + */
> +static int do_scmi_set_proto(struct cmd_tbl *cmdtp, int flag, int argc,
> + char * const argv[])
> +{
> + u32 agent_id, device_id, protocol_id, flags, attributes;
> + char *end;
> + int ret;
> +
> + if (argc != 5)
> + return CMD_RET_USAGE;
> +
> + agent_id = simple_strtoul(argv[1], &end, 16);
> + if (*end != '\0')
> + return CMD_RET_USAGE;
> +
> + device_id = simple_strtoul(argv[2], &end, 16);
> + if (*end != '\0')
> + return CMD_RET_USAGE;
> +
> + protocol_id = simple_strtoul(argv[3], &end, 16);
> + if (*end != '\0')
> + return CMD_RET_USAGE;
> +
> + flags = simple_strtoul(argv[4], &end, 16);
> + if (*end != '\0')
> + return CMD_RET_USAGE;
> +
> + ret = scmi_base_protocol_message_attrs(base_proto,
> + SCMI_BASE_SET_PROTOCOL_PERMISSIONS,
> + &attributes);
> + if (ret) {
> + printf("This operation is not supported\n");
> + return CMD_RET_FAILURE;
> + }
> +
> + ret = scmi_base_set_protocol_permissions(base_proto, agent_id,
> + device_id, protocol_id,
> + flags);
> + if (ret) {
> + printf("%s access to protocol:0x%x on device:%u failed (%d)\n",
> + flags ? "Allowing" : "Denying", protocol_id, device_id,
> + ret);
> + return CMD_RET_FAILURE;
> + }
> +
> + return CMD_RET_SUCCESS;
> +}
> +
> +/**
> + * do_scmi_reset() - reset platform resource settings
> + *
> + * @cmdtp: Command table
> + * @flag: Command flag
> + * @argc: Number of arguments
> + * @argv: Argument array
> + *
> + * Reset platform resource settings with BASE_RESET_AGENT_CONFIGURATION
> + *
> + * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
> + */
> +static int do_scmi_reset(struct cmd_tbl *cmdtp, int flag, int argc,
> + char * const argv[])
> +{
> + u32 agent_id, flags, attributes;
> + char *end;
> + int ret;
> +
> + if (argc != 3)
> + return CMD_RET_USAGE;
> +
> + agent_id = simple_strtoul(argv[1], &end, 16);
> + if (*end != '\0')
> + return CMD_RET_USAGE;
> +
> + flags = simple_strtoul(argv[2], &end, 16);
> + if (*end != '\0')
> + return CMD_RET_USAGE;
> +
> + ret = scmi_base_protocol_message_attrs(base_proto,
> + SCMI_BASE_RESET_AGENT_CONFIGURATION,
> + &attributes);
> + if (ret) {
> + printf("Reset is not supported\n");
> + return CMD_RET_FAILURE;
> + }
> +
> + ret = scmi_base_reset_agent_configuration(base_proto, agent_id, flags);
> + if (ret) {
> + printf("Reset failed (%d)\n", ret);
> + return CMD_RET_FAILURE;
> + }
> +
> + return CMD_RET_SUCCESS;
> +}
> +
> +static struct cmd_tbl cmd_scmi_sub[] = {
> + U_BOOT_CMD_MKENT(info, CONFIG_SYS_MAXARGS, 1,
> + do_scmi_info, "", ""),
> + U_BOOT_CMD_MKENT(perm_dev, CONFIG_SYS_MAXARGS, 1,
> + do_scmi_set_dev, "", ""),
> + U_BOOT_CMD_MKENT(perm_proto, CONFIG_SYS_MAXARGS, 1,
> + do_scmi_set_proto, "", ""),
> + U_BOOT_CMD_MKENT(reset, CONFIG_SYS_MAXARGS, 1,
> + do_scmi_reset, "", ""),
> +};
> +
> +/**
> + * do_scmi() - SCMI utility
> + *
> + * @cmdtp: Command table
> + * @flag: Command flag
> + * @argc: Number of arguments
> + * @argv: Argument array
> + *
> + * Provide user interfaces to SCMI protocols.
> + *
> + * Return: CMD_RET_SUCCESS on success,
> + * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
> + */
> +static int do_scmi(struct cmd_tbl *cmdtp, int flag,
> + int argc, char *const argv[])
> +{
> + struct cmd_tbl *cp;
> +
> + if (argc < 2)
> + return CMD_RET_USAGE;
> +
> + argc--; argv++;
> +
> + if (!agent) {
> + if (uclass_get_device(UCLASS_SCMI_AGENT, 0, &agent)) {
> + printf("Cannot find any SCMI agent\n");
> + return CMD_RET_FAILURE;
> + }
> + }
> +
> + if (!base_proto)
> + base_proto = scmi_get_protocol(agent, SCMI_PROTOCOL_ID_BASE);
> + if (!base_proto) {
> + printf("SCMI base protocol not found\n");
> + return CMD_RET_FAILURE;
> + }
> +
> + cp = find_cmd_tbl(argv[0], cmd_scmi_sub, ARRAY_SIZE(cmd_scmi_sub));
> + if (!cp)
> + return CMD_RET_USAGE;
> +
> + return cp->cmd(cmdtp, flag, argc, argv);
> +}
> +
> +static char scmi_help_text[] =
> + " - SCMI utility\n"
> + " info - get the info of SCMI services\n"
> + " perm_dev <agent id> <device id> <flags>\n"
> + " - set access permission to device\n"
> + " perm_proto <agent id> <device id> <protocol id> <flags>\n"
> + " - set protocol permission to device\n"
> + " reset <agent id> <flags>\n"
> + " - reset platform resource settings\n"
> + "";
> +
> +U_BOOT_CMD(scmi, CONFIG_SYS_MAXARGS, 0, do_scmi, "SCMI utility",
> + scmi_help_text);
> --
> 2.41.0
>
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v2 11/12] doc: cmd: add documentation for scmi
2023-07-26 8:37 [PATCH v2 00/12] firmware: scmi: add SCMI base protocol support AKASHI Takahiro
` (9 preceding siblings ...)
2023-07-26 8:38 ` [PATCH v2 10/12] cmd: add scmi command for SCMI firmware AKASHI Takahiro
@ 2023-07-26 8:38 ` AKASHI Takahiro
2023-07-27 0:53 ` Simon Glass
2023-08-03 10:31 ` Etienne CARRIERE
2023-07-26 8:38 ` [PATCH v2 12/12] test: dm: add scmi command test AKASHI Takahiro
11 siblings, 2 replies; 40+ messages in thread
From: AKASHI Takahiro @ 2023-07-26 8:38 UTC (permalink / raw)
To: trini, sjg; +Cc: etienne.carriere, u-boot, AKASHI Takahiro
This is a help text for scmi command.
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
v2
* add more descriptions about SCMI
---
doc/usage/cmd/scmi.rst | 126 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 126 insertions(+)
create mode 100644 doc/usage/cmd/scmi.rst
diff --git a/doc/usage/cmd/scmi.rst b/doc/usage/cmd/scmi.rst
new file mode 100644
index 000000000000..aebcfe95101d
--- /dev/null
+++ b/doc/usage/cmd/scmi.rst
@@ -0,0 +1,126 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+scmi command
+============
+
+Synopsis
+--------
+
+::
+
+ scmi info
+ scmi perm_dev <agent id> <device id> <flags>
+ scmi perm_proto <agent id> <device id> <protocol id> <flags>
+ scmi reset <agent id> <flags>
+
+Description
+-----------
+
+Arm System Control and Management Interface (SCMI hereafter) is a set of
+standardised interfaces to manage system resources, like clocks, power
+domains, pin controls, reset and so on, in a system-wide manner.
+
+An entity which provides those services is called a SCMI firmware (or
+SCMI server if you like) may be placed/implemented by EL3 software or
+by a dedicated system control processor (SCP) or else.
+
+A user of SCMI interfaces, including U-Boot, is called a SCMI agent and
+may issues commands, which are defined in each protocol for specific system
+resources, to SCMI server via a communication channel, called a transport.
+Those interfaces are independent from the server's implementation thanks to
+a tranport layer.
+
+For more details, see the `SCMI specification`_.
+
+While most of system resources managed under SCMI protocols are implemented
+and handled as standard U-Boot devices, for example clk_scmi, scmi command
+provides additional management functionality against SCMI server.
+
+scmi info
+~~~~~~~~~
+ Show base information about SCMI server and supported protocols
+
+scmi perm_dev
+~~~~~~~~~~~~~
+ Allow or deny access permission to the device
+
+scmi perm_proto
+~~~~~~~~~~~~~~~
+ Allow or deny access to the protocol on the device
+
+scmi reset
+~~~~~~~~~~
+ Reset the already-configured permissions against the device
+
+Parameters are used as follows:
+
+<agent id>
+ SCMI Agent ID, hex value
+
+<device id>
+ SCMI Device ID, hex value
+
+ Please note that what a device means is not defined
+ in the specification.
+
+<protocol id>
+ SCMI Protocol ID, hex value
+
+ It must not be 0x10 (base protocol)
+
+<flags>
+ Flags to control the action, hex value
+
+ 0 to deny, 1 to allow. The other values are reserved and allowed
+ values may depend on the implemented version of SCMI server in
+ the future. See SCMI specification for more details.
+
+Example
+-------
+
+Obtain basic information about SCMI server:
+
+::
+
+ => scmi info
+ SCMI device: scmi
+ protocol version: 0x20000
+ # of agents: 3
+ 0: platform
+ > 1: OSPM
+ 2: PSCI
+ # of protocols: 4
+ Power domain management
+ Performance domain management
+ Clock management
+ Sensor management
+ vendor: Linaro
+ sub vendor: PMWG
+ impl version: 0x20b0000
+
+Ask for access permission to device#0:
+
+::
+
+ => scmi perm_dev 1 0 1
+
+Reset configurations with all access permission settings retained:
+
+::
+
+ => scmi reset 1 0
+
+Configuration
+-------------
+
+The scmi command is only available if CONFIG_CMD_SCMI=y.
+Default n because this command is mainly for debug purpose.
+
+Return value
+------------
+
+The return value ($?) is set to 0 if the operation succeeded,
+1 if the operation failed or -1 if the operation failed due to
+a syntax error.
+
+.. _`SCMI specification`: https://developer.arm.com/documentation/den0056/e/?lang=en
--
2.41.0
^ permalink raw reply related [flat|nested] 40+ messages in thread* Re: [PATCH v2 11/12] doc: cmd: add documentation for scmi
2023-07-26 8:38 ` [PATCH v2 11/12] doc: cmd: add documentation for scmi AKASHI Takahiro
@ 2023-07-27 0:53 ` Simon Glass
2023-08-03 10:31 ` Etienne CARRIERE
1 sibling, 0 replies; 40+ messages in thread
From: Simon Glass @ 2023-07-27 0:53 UTC (permalink / raw)
To: AKASHI Takahiro; +Cc: trini, etienne.carriere, u-boot
On Wed, 26 Jul 2023 at 02:40, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> This is a help text for scmi command.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
> v2
> * add more descriptions about SCMI
> ---
> doc/usage/cmd/scmi.rst | 126 +++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 126 insertions(+)
> create mode 100644 doc/usage/cmd/scmi.rst
Reviewed-by: Simon Glass <sjg@chromium.org>
^ permalink raw reply [flat|nested] 40+ messages in thread
* RE: [PATCH v2 11/12] doc: cmd: add documentation for scmi
2023-07-26 8:38 ` [PATCH v2 11/12] doc: cmd: add documentation for scmi AKASHI Takahiro
2023-07-27 0:53 ` Simon Glass
@ 2023-08-03 10:31 ` Etienne CARRIERE
1 sibling, 0 replies; 40+ messages in thread
From: Etienne CARRIERE @ 2023-08-03 10:31 UTC (permalink / raw)
To: AKASHI Takahiro, trini@konsulko.com, sjg@chromium.org
Cc: u-boot@lists.denx.de
> From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> Sent: Wednesday, July 26, 2023 10:38
>
> This is a help text for scmi command.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
> v2
> * add more descriptions about SCMI
Reviewed-by: Etienne Carriere <etienne.carriere@foss.st.com>
> ---
> doc/usage/cmd/scmi.rst | 126 +++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 126 insertions(+)
> create mode 100644 doc/usage/cmd/scmi.rst
>
> diff --git a/doc/usage/cmd/scmi.rst b/doc/usage/cmd/scmi.rst
> new file mode 100644
> index 000000000000..aebcfe95101d
> --- /dev/null
> +++ b/doc/usage/cmd/scmi.rst
> @@ -0,0 +1,126 @@
> +.. SPDX-License-Identifier: GPL-2.0+:
> +
> +scmi command
> +============
> +
> +Synopsis
> +--------
> +
> +::
> +
> + scmi info
> + scmi perm_dev <agent id> <device id> <flags>
> + scmi perm_proto <agent id> <device id> <protocol id> <flags>
> + scmi reset <agent id> <flags>
> +
> +Description
> +-----------
> +
> +Arm System Control and Management Interface (SCMI hereafter) is a set of
> +standardised interfaces to manage system resources, like clocks, power
> +domains, pin controls, reset and so on, in a system-wide manner.
> +
> +An entity which provides those services is called a SCMI firmware (or
> +SCMI server if you like) may be placed/implemented by EL3 software or
> +by a dedicated system control processor (SCP) or else.
> +
> +A user of SCMI interfaces, including U-Boot, is called a SCMI agent and
> +may issues commands, which are defined in each protocol for specific system
> +resources, to SCMI server via a communication channel, called a transport.
> +Those interfaces are independent from the server's implementation thanks to
> +a tranport layer.
> +
> +For more details, see the `SCMI specification`_.
> +
> +While most of system resources managed under SCMI protocols are implemented
> +and handled as standard U-Boot devices, for example clk_scmi, scmi command
> +provides additional management functionality against SCMI server.
> +
> +scmi info
> +~~~~~~~~~
> + Show base information about SCMI server and supported protocols
> +
> +scmi perm_dev
> +~~~~~~~~~~~~~
> + Allow or deny access permission to the device
> +
> +scmi perm_proto
> +~~~~~~~~~~~~~~~
> + Allow or deny access to the protocol on the device
> +
> +scmi reset
> +~~~~~~~~~~
> + Reset the already-configured permissions against the device
> +
> +Parameters are used as follows:
> +
> +<agent id>
> + SCMI Agent ID, hex value
By the way, this documentation states hexadecimal value are awaited
but not the embedded doc (patch v2 10/12). Would it be worth it?
> +
> +<device id>
> + SCMI Device ID, hex value
> +
> + Please note that what a device means is not defined
> + in the specification.
> +
> +<protocol id>
> + SCMI Protocol ID, hex value
> +
> + It must not be 0x10 (base protocol)
> +
> +<flags>
> + Flags to control the action, hex value
> +
> + 0 to deny, 1 to allow. The other values are reserved and allowed
> + values may depend on the implemented version of SCMI server in
> + the future. See SCMI specification for more details.
> +
> +Example
> +-------
> +
> +Obtain basic information about SCMI server:
> +
> +::
> +
> + => scmi info
> + SCMI device: scmi
> + protocol version: 0x20000
> + # of agents: 3
> + 0: platform
> + > 1: OSPM
> + 2: PSCI
> + # of protocols: 4
> + Power domain management
> + Performance domain management
> + Clock management
> + Sensor management
> + vendor: Linaro
> + sub vendor: PMWG
> + impl version: 0x20b0000
> +
> +Ask for access permission to device#0:
> +
> +::
> +
> + => scmi perm_dev 1 0 1
> +
> +Reset configurations with all access permission settings retained:
> +
> +::
> +
> + => scmi reset 1 0
> +
> +Configuration
> +-------------
> +
> +The scmi command is only available if CONFIG_CMD_SCMI=y.
> +Default n because this command is mainly for debug purpose.
> +
> +Return value
> +------------
> +
> +The return value ($?) is set to 0 if the operation succeeded,
> +1 if the operation failed or -1 if the operation failed due to
> +a syntax error.
> +
> +.. _`SCMI specification`: https://developer.arm.com/documentation/den0056/e/?lang=en
> --
> 2.41.0
>
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v2 12/12] test: dm: add scmi command test
2023-07-26 8:37 [PATCH v2 00/12] firmware: scmi: add SCMI base protocol support AKASHI Takahiro
` (10 preceding siblings ...)
2023-07-26 8:38 ` [PATCH v2 11/12] doc: cmd: add documentation for scmi AKASHI Takahiro
@ 2023-07-26 8:38 ` AKASHI Takahiro
2023-07-27 0:53 ` Simon Glass
2023-08-03 11:36 ` Etienne CARRIERE
11 siblings, 2 replies; 40+ messages in thread
From: AKASHI Takahiro @ 2023-07-26 8:38 UTC (permalink / raw)
To: trini, sjg; +Cc: etienne.carriere, u-boot, AKASHI Takahiro
In this test, "scmi" command is tested against different sub-commands.
Please note that scmi command is for debug purpose and is not intended
in production system.
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
v2
* use helper functions, removing direct uses of ops
---
test/dm/scmi.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 56 insertions(+), 3 deletions(-)
diff --git a/test/dm/scmi.c b/test/dm/scmi.c
index 41d46548f7fd..a3e61355088a 100644
--- a/test/dm/scmi.c
+++ b/test/dm/scmi.c
@@ -134,9 +134,9 @@ static int dm_test_scmi_base(struct unit_test_state *uts)
ut_asserteq_str(priv->vendor, vendor);
/* message attributes */
- ret = scmi_protocol_message_attrs(base,
- SCMI_BASE_DISCOVER_SUB_VENDOR,
- &attributes);
+ ret = scmi_base_protocol_message_attrs(base,
+ SCMI_BASE_DISCOVER_SUB_VENDOR,
+ &attributes);
ut_assertok(ret);
ut_assertok(attributes);
@@ -204,6 +204,59 @@ static int dm_test_scmi_base(struct unit_test_state *uts)
DM_TEST(dm_test_scmi_base, UT_TESTF_SCAN_FDT);
+static int dm_test_scmi_cmd(struct unit_test_state *uts)
+{
+ struct udevice *agent_dev;
+
+ /* preparation */
+ ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi",
+ &agent_dev));
+ ut_assertnonnull(agent_dev);
+
+ /* scmi info */
+ ut_assertok(run_command("scmi info", 0));
+
+ ut_assert_nextline("SCMI device: scmi");
+ ut_assert_nextline(" protocol version: 0x20000");
+ ut_assert_nextline(" # of agents: 2");
+ ut_assert_nextline(" 0: platform");
+ ut_assert_nextline(" > 1: OSPM");
+ ut_assert_nextline(" # of protocols: 3");
+ ut_assert_nextline(" Clock management");
+ ut_assert_nextline(" Reset domain management");
+ ut_assert_nextline(" Voltage domain management");
+ ut_assert_nextline(" vendor: U-Boot");
+ ut_assert_nextline(" sub vendor: Sandbox");
+ ut_assert_nextline(" impl version: 0x1");
+
+ ut_assert_console_end();
+
+ /* scmi perm_dev */
+ ut_assertok(run_command("scmi perm_dev 1 0 1", 0));
+ ut_assert_console_end();
+
+ ut_assert(run_command("scmi perm_dev 1 0 0", 0));
+ ut_assert_nextline("Denying access to device:0 failed (-13)");
+ ut_assert_console_end();
+
+ /* scmi perm_proto */
+ ut_assertok(run_command("scmi perm_proto 1 0 14 1", 0));
+ ut_assert_console_end();
+
+ ut_assert(run_command("scmi perm_proto 1 0 14 0", 0));
+ ut_assert_nextline("Denying access to protocol:0x14 on device:0 failed (-13)");
+ ut_assert_console_end();
+
+ /* scmi reset */
+ ut_assert(run_command("scmi reset 1 1", 0));
+ ut_assert_nextline("Reset failed (-13)");
+ ut_assert_console_end();
+
+ return 0;
+}
+
+DM_TEST(dm_test_scmi_cmd, UT_TESTF_SCAN_FDT);
+
static int dm_test_scmi_clocks(struct unit_test_state *uts)
{
struct sandbox_scmi_agent *agent;
--
2.41.0
^ permalink raw reply related [flat|nested] 40+ messages in thread* Re: [PATCH v2 12/12] test: dm: add scmi command test
2023-07-26 8:38 ` [PATCH v2 12/12] test: dm: add scmi command test AKASHI Takahiro
@ 2023-07-27 0:53 ` Simon Glass
2023-08-03 11:36 ` Etienne CARRIERE
1 sibling, 0 replies; 40+ messages in thread
From: Simon Glass @ 2023-07-27 0:53 UTC (permalink / raw)
To: AKASHI Takahiro; +Cc: trini, etienne.carriere, u-boot
On Wed, 26 Jul 2023 at 02:40, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> In this test, "scmi" command is tested against different sub-commands.
> Please note that scmi command is for debug purpose and is not intended
> in production system.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> ---
> v2
> * use helper functions, removing direct uses of ops
> ---
> test/dm/scmi.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 56 insertions(+), 3 deletions(-)
>
Reviewed-by: Simon Glass <sjg@chromium.org>
^ permalink raw reply [flat|nested] 40+ messages in thread
* RE: [PATCH v2 12/12] test: dm: add scmi command test
2023-07-26 8:38 ` [PATCH v2 12/12] test: dm: add scmi command test AKASHI Takahiro
2023-07-27 0:53 ` Simon Glass
@ 2023-08-03 11:36 ` Etienne CARRIERE
1 sibling, 0 replies; 40+ messages in thread
From: Etienne CARRIERE @ 2023-08-03 11:36 UTC (permalink / raw)
To: AKASHI Takahiro, trini@konsulko.com, sjg@chromium.org
Cc: u-boot@lists.denx.de
> From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> Sent: Wednesday, July 26, 2023 10:38
>
> In this test, "scmi" command is tested against different sub-commands.
> Please note that scmi command is for debug purpose and is not intended
> in production system.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> ---
> v2
> * use helper functions, removing direct uses of ops
Reviewed-by: Etienne Carriere <etienne.carriere@foss.st.com>
with patch on dm_test_scmi_base() squashed in patch 9/12.
> ---
> test/dm/scmi.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 56 insertions(+), 3 deletions(-)
>
> diff --git a/test/dm/scmi.c b/test/dm/scmi.c
> index 41d46548f7fd..a3e61355088a 100644
> --- a/test/dm/scmi.c
> +++ b/test/dm/scmi.c
> @@ -134,9 +134,9 @@ static int dm_test_scmi_base(struct unit_test_state *uts)
> ut_asserteq_str(priv->vendor, vendor);
>
> /* message attributes */
> - ret = scmi_protocol_message_attrs(base,
> - SCMI_BASE_DISCOVER_SUB_VENDOR,
> - &attributes);
> + ret = scmi_base_protocol_message_attrs(base,
> + SCMI_BASE_DISCOVER_SUB_VENDOR,
> + &attributes);
> ut_assertok(ret);
> ut_assertok(attributes);
>
> @@ -204,6 +204,59 @@ static int dm_test_scmi_base(struct unit_test_state *uts)
>
> DM_TEST(dm_test_scmi_base, UT_TESTF_SCAN_FDT);
>
> +static int dm_test_scmi_cmd(struct unit_test_state *uts)
> +{
> + struct udevice *agent_dev;
> +
> + /* preparation */
> + ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi",
> + &agent_dev));
> + ut_assertnonnull(agent_dev);
> +
> + /* scmi info */
> + ut_assertok(run_command("scmi info", 0));
> +
> + ut_assert_nextline("SCMI device: scmi");
> + ut_assert_nextline(" protocol version: 0x20000");
> + ut_assert_nextline(" # of agents: 2");
> + ut_assert_nextline(" 0: platform");
> + ut_assert_nextline(" > 1: OSPM");
> + ut_assert_nextline(" # of protocols: 3");
> + ut_assert_nextline(" Clock management");
> + ut_assert_nextline(" Reset domain management");
> + ut_assert_nextline(" Voltage domain management");
> + ut_assert_nextline(" vendor: U-Boot");
> + ut_assert_nextline(" sub vendor: Sandbox");
> + ut_assert_nextline(" impl version: 0x1");
> +
> + ut_assert_console_end();
> +
> + /* scmi perm_dev */
> + ut_assertok(run_command("scmi perm_dev 1 0 1", 0));
> + ut_assert_console_end();
> +
> + ut_assert(run_command("scmi perm_dev 1 0 0", 0));
> + ut_assert_nextline("Denying access to device:0 failed (-13)");
> + ut_assert_console_end();
> +
> + /* scmi perm_proto */
> + ut_assertok(run_command("scmi perm_proto 1 0 14 1", 0));
> + ut_assert_console_end();
> +
> + ut_assert(run_command("scmi perm_proto 1 0 14 0", 0));
> + ut_assert_nextline("Denying access to protocol:0x14 on device:0 failed (-13)");
> + ut_assert_console_end();
> +
> + /* scmi reset */
> + ut_assert(run_command("scmi reset 1 1", 0));
> + ut_assert_nextline("Reset failed (-13)");
> + ut_assert_console_end();
> +
> + return 0;
> +}
> +
> +DM_TEST(dm_test_scmi_cmd, UT_TESTF_SCAN_FDT);
> +
> static int dm_test_scmi_clocks(struct unit_test_state *uts)
> {
> struct sandbox_scmi_agent *agent;
> --
> 2.41.0
>
^ permalink raw reply [flat|nested] 40+ messages in thread