Instead of resolving clock control flags using SCMI_CLOCK_ATTRIBUTES during probe for each and every clock, resolve the clock control flags using SCMI_CLOCK_ATTRIBUTES when the clock control flags are first used. Because most clock are never used by U-Boot, this allows reducing the amount of SCMI_CLOCK_ATTRIBUTES considerably, and this improve probe time of the scmi clock driver and U-Boot start up time.
On Renesas X5H, with 1700+ SCMI clock, the boot time improved by 1.7s . Signed-off-by: Marek Vasut <[email protected]> --- Cc: Alice Guo <[email protected]> Cc: Patrice Chotard <[email protected]> Cc: Patrick Delaunay <[email protected]> Cc: Peng Fan <[email protected]> Cc: Sean Anderson <[email protected]> Cc: Tom Rini <[email protected]> Cc: Valentin Caron <[email protected]> Cc: Vinh Nguyen <[email protected]> Cc: [email protected] --- drivers/clk/clk_scmi.c | 50 ++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/drivers/clk/clk_scmi.c b/drivers/clk/clk_scmi.c index afaeb84e65d..005968e8b75 100644 --- a/drivers/clk/clk_scmi.c +++ b/drivers/clk/clk_scmi.c @@ -18,6 +18,7 @@ struct clk_scmi { struct clk clk; char name[SCMI_CLOCK_NAME_LENGTH_MAX]; u32 ctrl_flags; + bool attrs_resolved; }; struct scmi_clock_priv { @@ -85,7 +86,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); @@ -109,7 +110,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; @@ -126,7 +127,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; } @@ -166,7 +167,9 @@ static int scmi_clk_gate(struct clk *clk, int enable) static int scmi_clk_get_ctrl_flags(struct clk *clk, u32 *ctrl_flags) { + struct udevice *dev = clk->dev->parent; struct clk_scmi *clkscmi; + u32 attributes; struct clk *c; int ret; @@ -176,6 +179,31 @@ static int scmi_clk_get_ctrl_flags(struct clk *clk, u32 *ctrl_flags) clkscmi = container_of(c, struct clk_scmi, clk); + 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; @@ -328,7 +356,6 @@ static int scmi_clk_probe(struct udevice *dev) for (i = 0; i < num_clocks; i++) { clk_scmi = clk_scmi_bulk + i; char *clock_name = clk_scmi->name; - u32 attributes; snprintf(clock_name, SCMI_CLOCK_NAME_LENGTH_MAX, "scmi-%zu", i); @@ -338,21 +365,6 @@ static int scmi_clk_probe(struct udevice *dev) return ret; dev_clk_dm(dev, i, &clk_scmi->clk); - - if (!scmi_clk_get_attibute(dev, i, &clock_name, &attributes)) { - 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; - } - } } return 0; -- 2.51.0

