diff options
| author | Tom Rini <[email protected]> | 2025-11-10 21:52:28 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2025-11-10 21:52:28 -0600 |
| commit | c7e33aae35bf841f9b8573e6f37dfab71f0e5171 (patch) | |
| tree | 1f514b6bb6c154615d23d9f9efd68f058f9d4766 /drivers | |
| parent | 365a7079fb918643da0f0709660a7d8ea76dd6f3 (diff) | |
| parent | 3547e315c188cdbb24312543d67d132b113eb01e (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
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/clk/clk_scmi.c | 160 | ||||
| -rw-r--r-- | drivers/firmware/scmi/sandbox-scmi_agent.c | 4 | ||||
| -rw-r--r-- | drivers/firmware/scmi/smt.c | 14 |
3 files changed, 98 insertions, 80 deletions
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; } |
