summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2025-11-10 21:52:28 -0600
committerTom Rini <[email protected]>2025-11-10 21:52:28 -0600
commitc7e33aae35bf841f9b8573e6f37dfab71f0e5171 (patch)
tree1f514b6bb6c154615d23d9f9efd68f058f9d4766
parent365a7079fb918643da0f0709660a7d8ea76dd6f3 (diff)
parent3547e315c188cdbb24312543d67d132b113eb01e (diff)
Merge tag 'scmi-master-2025-11-11' of https://source.denx.de/u-boot/custodians/u-boot-fsl-qoriq
CI: https://source.denx.de/u-boot/custodians/u-boot-fsl-qoriq/-/pipelines/28272 - Support scmi v3.2 CONFIG_SET for clock protocol - A patchset from Marek to optimize the scmi clk booting time - Fix scmi clk set_parent in non-CCF case - Drop mmu_set_region_dcache_behaviour in firmware scmi
-rw-r--r--arch/arm/mach-imx/imx9/scmi/clock_scmi.c2
-rw-r--r--drivers/clk/clk_scmi.c160
-rw-r--r--drivers/firmware/scmi/sandbox-scmi_agent.c4
-rw-r--r--drivers/firmware/scmi/smt.c14
-rw-r--r--include/scmi_protocols.h37
5 files changed, 125 insertions, 92 deletions
diff --git a/arch/arm/mach-imx/imx9/scmi/clock_scmi.c b/arch/arm/mach-imx/imx9/scmi/clock_scmi.c
index b6be20ec674..9030dbf600d 100644
--- a/arch/arm/mach-imx/imx9/scmi/clock_scmi.c
+++ b/arch/arm/mach-imx/imx9/scmi/clock_scmi.c
@@ -10,7 +10,7 @@
int imx_clk_scmi_enable(u32 clock_id, bool enable)
{
- struct scmi_clk_state_in in = {
+ struct scmi_clk_state_in_v1 in = {
.clock_id = clock_id,
.attributes = !!enable,
};
diff --git a/drivers/clk/clk_scmi.c b/drivers/clk/clk_scmi.c
index a7d89f32cd7..683ac822a01 100644
--- a/drivers/clk/clk_scmi.c
+++ b/drivers/clk/clk_scmi.c
@@ -8,6 +8,7 @@
#include <clk-uclass.h>
#include <dm.h>
#include <dm/device_compat.h>
+#include <dm/device-internal.h>
#include <scmi_agent.h>
#include <scmi_agent-uclass.h>
#include <scmi_protocols.h>
@@ -16,7 +17,9 @@
struct clk_scmi {
struct clk clk;
+ char name[SCMI_CLOCK_NAME_LENGTH_MAX];
u32 ctrl_flags;
+ bool attrs_resolved;
};
struct scmi_clock_priv {
@@ -84,7 +87,7 @@ static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks)
return 0;
}
-static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name,
+static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char *name,
u32 *attr)
{
struct scmi_clock_priv *priv = dev_get_priv(dev);
@@ -108,7 +111,7 @@ static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name,
if (ret)
return ret;
- *name = strdup(out.clock_name);
+ strncpy(name, out.clock_name, SCMI_CLOCK_NAME_LENGTH_MAX);
*attr = out.attributes;
} else {
struct scmi_clk_attribute_out out;
@@ -125,7 +128,7 @@ static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name,
if (ret)
return ret;
- *name = strdup(out.clock_name);
+ strncpy(name, out.clock_name, SCMI_CLOCK_NAME_LENGTH_MAX);
*attr = out.attributes;
}
@@ -134,39 +137,93 @@ 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_state_in in = {
+ struct scmi_clock_priv *priv = dev_get_parent_priv(clk->dev);
+ struct scmi_clk_state_in_v1 in_v1 = {
+ .clock_id = clk_get_id(clk),
+ .attributes = enable,
+ };
+ /* Valid only from SCMI clock v2.1 */
+ struct scmi_clk_state_in_v2 in_v2 = {
.clock_id = clk_get_id(clk),
.attributes = enable,
};
struct scmi_clk_state_out out;
- struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK,
- SCMI_CLOCK_CONFIG_SET,
- in, out);
+ struct scmi_msg msg_v1 = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK,
+ SCMI_CLOCK_CONFIG_SET,
+ in_v1, out);
+ struct scmi_msg msg_v2 = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK,
+ SCMI_CLOCK_CONFIG_SET,
+ in_v2, out);
int ret;
- ret = devm_scmi_process_msg(clk->dev, &msg);
+ ret = devm_scmi_process_msg(clk->dev,
+ (priv->version < CLOCK_PROTOCOL_VERSION_2_1) ?
+ &msg_v1 : &msg_v2);
if (ret)
return ret;
return scmi_to_linux_errno(out.status);
}
-static int scmi_clk_enable(struct clk *clk)
+static int scmi_clk_get_ctrl_flags(struct clk *clk, u32 *ctrl_flags)
{
struct clk_scmi *clkscmi;
+ struct udevice *dev;
+ u32 attributes;
struct clk *c;
int ret;
- if (!CONFIG_IS_ENABLED(CLK_CCF))
- return scmi_clk_gate(clk, 1);
-
ret = clk_get_by_id(clk->id, &c);
if (ret)
return ret;
+ dev = c->dev->parent;
+
clkscmi = container_of(c, struct clk_scmi, clk);
- if (clkscmi->ctrl_flags & SUPPORT_CLK_STAT_CONTROL)
+ if (!clkscmi->attrs_resolved) {
+ char name[SCMI_CLOCK_NAME_LENGTH_MAX];
+ ret = scmi_clk_get_attibute(dev, clk->id & CLK_ID_MSK,
+ name, &attributes);
+ if (ret)
+ return ret;
+
+ strncpy(clkscmi->name, name, SCMI_CLOCK_NAME_LENGTH_MAX);
+ if (CLK_HAS_RESTRICTIONS(attributes)) {
+ u32 perm;
+
+ ret = scmi_clk_get_permissions(dev, clk->id & CLK_ID_MSK, &perm);
+ if (ret < 0)
+ clkscmi->ctrl_flags = 0;
+ else
+ clkscmi->ctrl_flags = perm;
+ } else {
+ clkscmi->ctrl_flags = SUPPORT_CLK_STAT_CONTROL |
+ SUPPORT_CLK_PARENT_CONTROL |
+ SUPPORT_CLK_RATE_CONTROL;
+ }
+
+ clkscmi->attrs_resolved = true;
+ }
+
+ *ctrl_flags = clkscmi->ctrl_flags;
+
+ return 0;
+}
+
+static int scmi_clk_enable(struct clk *clk)
+{
+ u32 ctrl_flags;
+ int ret;
+
+ if (!CONFIG_IS_ENABLED(CLK_CCF))
+ return scmi_clk_gate(clk, 1);
+
+ ret = scmi_clk_get_ctrl_flags(clk, &ctrl_flags);
+ if (ret)
+ return ret;
+
+ if (ctrl_flags & SUPPORT_CLK_STAT_CONTROL)
return scmi_clk_gate(clk, 1);
/* Following Linux drivers/clk/clk-scmi.c, directly return 0 if agent has no permission. */
@@ -176,20 +233,17 @@ static int scmi_clk_enable(struct clk *clk)
static int scmi_clk_disable(struct clk *clk)
{
- struct clk_scmi *clkscmi;
- struct clk *c;
+ u32 ctrl_flags;
int ret;
if (!CONFIG_IS_ENABLED(CLK_CCF))
return scmi_clk_gate(clk, 0);
- ret = clk_get_by_id(clk->id, &c);
+ ret = scmi_clk_get_ctrl_flags(clk, &ctrl_flags);
if (ret)
return ret;
- clkscmi = container_of(c, struct clk_scmi, clk);
-
- if (clkscmi->ctrl_flags & SUPPORT_CLK_STAT_CONTROL)
+ if (ctrl_flags & SUPPORT_CLK_STAT_CONTROL)
return scmi_clk_gate(clk, 0);
/* Following Linux drivers/clk/clk-scmi.c, directly return 0 if agent has no permission. */
@@ -247,20 +301,17 @@ static ulong __scmi_clk_set_rate(struct clk *clk, ulong rate)
static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
{
- struct clk_scmi *clkscmi;
- struct clk *c;
+ u32 ctrl_flags;
int ret;
if (!CONFIG_IS_ENABLED(CLK_CCF))
return __scmi_clk_set_rate(clk, rate);
- ret = clk_get_by_id(clk->id, &c);
+ ret = scmi_clk_get_ctrl_flags(clk, &ctrl_flags);
if (ret)
return ret;
- clkscmi = container_of(c, struct clk_scmi, clk);
-
- if (clkscmi->ctrl_flags & SUPPORT_CLK_RATE_CONTROL)
+ if (ctrl_flags & SUPPORT_CLK_RATE_CONTROL)
return __scmi_clk_set_rate(clk, rate);
/* Following Linux drivers/clk/clk-scmi.c, directly return 0 if agent has no permission. */
@@ -271,7 +322,7 @@ static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
static int scmi_clk_probe(struct udevice *dev)
{
- struct clk_scmi *clk_scmi;
+ struct clk_scmi *clk_scmi_bulk, *clk_scmi;
struct scmi_clock_priv *priv = dev_get_priv(dev);
size_t num_clocks, i;
int ret;
@@ -300,39 +351,23 @@ static int scmi_clk_probe(struct udevice *dev)
return ret;
}
+ clk_scmi_bulk = kzalloc(num_clocks * sizeof(*clk_scmi), GFP_KERNEL);
+ if (!clk_scmi_bulk)
+ return -ENOMEM;
+
for (i = 0; i < num_clocks; i++) {
- char *clock_name;
- u32 attributes;
+ clk_scmi = clk_scmi_bulk + i;
+ char *clock_name = clk_scmi->name;
- if (!scmi_clk_get_attibute(dev, i, &clock_name, &attributes)) {
- clk_scmi = kzalloc(sizeof(*clk_scmi), GFP_KERNEL);
- if (!clk_scmi || !clock_name)
- ret = -ENOMEM;
- else
- ret = clk_register(&clk_scmi->clk, dev->driver->name,
- clock_name, dev->name);
-
- if (ret) {
- free(clk_scmi);
- free(clock_name);
- return ret;
- }
-
- dev_clk_dm(dev, i, &clk_scmi->clk);
-
- if (CLK_HAS_RESTRICTIONS(attributes)) {
- u32 perm;
-
- ret = scmi_clk_get_permissions(dev, i, &perm);
- if (ret < 0)
- clk_scmi->ctrl_flags = 0;
- else
- clk_scmi->ctrl_flags = perm;
- } else {
- clk_scmi->ctrl_flags = SUPPORT_CLK_STAT_CONTROL | SUPPORT_CLK_PARENT_CONTROL |
- SUPPORT_CLK_RATE_CONTROL;
- }
- }
+ snprintf(clock_name, SCMI_CLOCK_NAME_LENGTH_MAX, "scmi-%zu", i);
+
+ ret = clk_register(&clk_scmi->clk, dev->driver->name,
+ clock_name, dev->name);
+ if (ret)
+ return ret;
+
+ dev_clk_dm(dev, i, &clk_scmi->clk);
+ dev_set_parent_priv(clk_scmi->clk.dev, priv);
}
return 0;
@@ -359,20 +394,17 @@ static int __scmi_clk_set_parent(struct clk *clk, struct clk *parent)
static int scmi_clk_set_parent(struct clk *clk, struct clk *parent)
{
- struct clk_scmi *clkscmi;
- struct clk *c;
+ u32 ctrl_flags;
int ret;
if (!CONFIG_IS_ENABLED(CLK_CCF))
- return -ENOTSUPP;
+ return __scmi_clk_set_parent(clk, parent);
- ret = clk_get_by_id(clk->id, &c);
+ ret = scmi_clk_get_ctrl_flags(clk, &ctrl_flags);
if (ret)
return ret;
- clkscmi = container_of(c, struct clk_scmi, clk);
-
- if (clkscmi->ctrl_flags & SUPPORT_CLK_PARENT_CONTROL)
+ if (ctrl_flags & SUPPORT_CLK_PARENT_CONTROL)
return __scmi_clk_set_parent(clk, parent);
/* Following Linux drivers/clk/clk-scmi.c, directly return 0 if agent has no permission. */
diff --git a/drivers/firmware/scmi/sandbox-scmi_agent.c b/drivers/firmware/scmi/sandbox-scmi_agent.c
index 74a87832dcb..5b242a039c2 100644
--- a/drivers/firmware/scmi/sandbox-scmi_agent.c
+++ b/drivers/firmware/scmi/sandbox-scmi_agent.c
@@ -828,7 +828,7 @@ static int sandbox_scmi_clock_rate_get(struct udevice *dev,
static int sandbox_scmi_clock_gate(struct udevice *dev, struct scmi_msg *msg)
{
- struct scmi_clk_state_in *in = NULL;
+ struct scmi_clk_state_in_v1 *in = NULL;
struct scmi_clk_state_out *out = NULL;
struct sandbox_scmi_clk *clk_state = NULL;
@@ -836,7 +836,7 @@ static int sandbox_scmi_clock_gate(struct udevice *dev, struct scmi_msg *msg)
!msg->out_msg || msg->out_msg_sz < sizeof(*out))
return -EINVAL;
- in = (struct scmi_clk_state_in *)msg->in_msg;
+ in = (struct scmi_clk_state_in_v1 *)msg->in_msg;
out = (struct scmi_clk_state_out *)msg->out_msg;
clk_state = get_scmi_clk_state(in->clock_id);
diff --git a/drivers/firmware/scmi/smt.c b/drivers/firmware/scmi/smt.c
index 237871559f0..cd1c0801f72 100644
--- a/drivers/firmware/scmi/smt.c
+++ b/drivers/firmware/scmi/smt.c
@@ -61,20 +61,6 @@ int scmi_dt_get_smt_buffer(struct udevice *dev, struct scmi_smt *smt)
if (device_is_compatible(dev, "arm,scmi") && ofnode_has_property(dev_ofnode(dev), "mboxes"))
scmi_smt_enable_intr(smt, true);
-#ifdef CONFIG_ARM
- if (dcache_status()) {
- u32 align_size;
-
- if (IS_ENABLED(CONFIG_ARM64))
- align_size = PAGE_SIZE;
- else
- align_size = MMU_SECTION_SIZE;
-
- mmu_set_region_dcache_behaviour(ALIGN_DOWN((uintptr_t)smt->buf, align_size),
- ALIGN(smt->size, align_size), DCACHE_OFF);
- }
-#endif
-
return 0;
}
diff --git a/include/scmi_protocols.h b/include/scmi_protocols.h
index bb74a57f79a..ecab021b472 100644
--- a/include/scmi_protocols.h
+++ b/include/scmi_protocols.h
@@ -399,7 +399,7 @@ int scmi_generic_protocol_version(struct udevice *dev,
int scmi_base_protocol_version(struct udevice *dev, u32 *version);
/**
- * scmi_protocol_attrs - get protocol attributes
+ * scmi_base_protocol_attrs - get protocol attributes
* @dev: SCMI protocol device
* @num_agents: Number of SCMI agents
* @num_protocols: Number of SCMI protocols
@@ -414,7 +414,7 @@ int scmi_base_protocol_attrs(struct udevice *dev, u32 *num_agents,
u32 *num_protocols);
/**
- * scmi_protocol_message_attrs - get message-specific attributes
+ * scmi_base_protocol_message_attrs - get message-specific attributes
* @dev: SCMI protocol device
* @message_id: SCMI message ID
* @attributes: Message-specific attributes
@@ -733,6 +733,7 @@ int scmi_pwd_name_get(struct udevice *dev, u32 domain_id, u8 **name);
/*
* SCMI Clock Protocol
*/
+#define CLOCK_PROTOCOL_VERSION_2_1 0x20001
#define CLOCK_PROTOCOL_VERSION_3_0 0x30000
enum scmi_clock_message_id {
@@ -754,7 +755,7 @@ enum scmi_clock_message_id {
#define SCMI_CLOCK_NAME_LENGTH_MAX 16
/**
- * struct scmi_clk_get_nb_out - Response for SCMI_PROTOCOL_ATTRIBUTES command
+ * struct scmi_clk_protocol_attr_out - Response for SCMI_PROTOCOL_ATTRIBUTES command
* @status: SCMI command status
* @attributes: Attributes of the clock protocol, mainly number of clocks exposed
*/
@@ -772,7 +773,7 @@ struct scmi_clk_attribute_in {
};
/**
- * struct scmi_clk_get_nb_out - Response payload for SCMI_CLOCK_ATTRIBUTES command
+ * struct scmi_clk_attribute_out - Response payload for SCMI_CLOCK_ATTRIBUTES command
* @status: SCMI command status
* @attributes: clock attributes
* @clock_name: name of the clock
@@ -785,7 +786,7 @@ struct scmi_clk_attribute_out {
};
/**
- * struct scmi_clk_get_nb_out_v2 - Response payload for SCMI_CLOCK_ATTRIBUTES command
+ * struct scmi_clk_attribute_out_v2 - Response payload for SCMI_CLOCK_ATTRIBUTES command
* Clock management Protocol 2.0
* @status: SCMI command status
* @attributes: clock attributes
@@ -800,16 +801,28 @@ struct scmi_clk_attribute_out_v2 {
};
/**
- * struct scmi_clk_state_in - Message payload for CLOCK_CONFIG_SET command
+ * struct scmi_clk_state_in_v1 - Message payload for CLOCK_CONFIG_SET command for protocol < 2.1
* @clock_id: SCMI clock ID
* @attributes: Attributes of the targets clock state
*/
-struct scmi_clk_state_in {
+struct scmi_clk_state_in_v1 {
u32 clock_id;
u32 attributes;
};
/**
+ * struct scmi_clk_state_in_v2 - Message payload for CLOCK_CONFIG_SET command for protocol >= 2.1
+ * @clock_id: SCMI clock ID
+ * @attributes: Attributes of the targets clock state
+ * @extended_config_val: Extended and OEM specific configuration
+ */
+struct scmi_clk_state_in_v2 {
+ u32 clock_id;
+ u32 attributes;
+ u32 extended_config_val;
+};
+
+/**
* struct scmi_clk_state_out - Response payload for CLOCK_CONFIG_SET command
* @status: SCMI command status
*/
@@ -818,7 +831,7 @@ struct scmi_clk_state_out {
};
/**
- * struct scmi_clk_state_in - Message payload for CLOCK_RATE_GET command
+ * struct scmi_clk_rate_get_in - Message payload for CLOCK_RATE_GET command
* @clock_id: SCMI clock ID
* @attributes: Attributes of the targets clock state
*/
@@ -839,7 +852,7 @@ struct scmi_clk_rate_get_out {
};
/**
- * struct scmi_clk_state_in - Message payload for CLOCK_RATE_SET command
+ * struct scmi_clk_rate_set_in - Message payload for CLOCK_RATE_SET command
* @flags: Flags for the clock rate set request
* @clock_id: SCMI clock ID
* @rate_lsb: 32bit LSB of the clock rate in Hertz
@@ -861,7 +874,7 @@ struct scmi_clk_rate_set_out {
};
/**
- * struct scmi_clk_parent_state_in - Message payload for CLOCK_PARENT_SET command
+ * struct scmi_clk_parent_set_in - Message payload for CLOCK_PARENT_SET command
* @clock_id: SCMI clock ID
* @parent_clk: SCMI clock ID
*/
@@ -879,6 +892,7 @@ struct scmi_clk_parent_set_out {
};
/**
+ * struct scmi_clk_get_permissions_in - Message payload for CLOCK_GET_PERMISSIONS command
* @clock_id: Identifier for the clock device.
*/
struct scmi_clk_get_permissions_in {
@@ -886,6 +900,7 @@ struct scmi_clk_get_permissions_in {
};
/**
+ * struct scmi_clk_get_permissions_out - Response payload for CLOCK_GET_PERMISSIONS command
* @status: Negative 32-bit integers are used to return error status codes.
* @permissions: Bit[31] Clock state control, Bit[30] Clock parent control,
* Bit[29] Clock rate control, Bits[28:0] Reserved, must be zero.
@@ -1082,7 +1097,7 @@ struct scmi_pin_config {
};
/**
- * struct scmi_pad_config_set_in - Message payload for PAD_CONFIG_SET command
+ * struct scmi_pinctrl_config_set_in - Message payload for PAD_CONFIG_SET command
* @identifier: Identifier for the pin or group.
* @function_id: Identifier for the function selected to be enabled
* for the selected pin or group. This field is set to