[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250901-clk-ssc-version1-v2-2-1d0a486dffe6@nxp.com>
Date: Mon, 01 Sep 2025 11:51:46 +0800
From: Peng Fan <peng.fan@....com>
To: Michael Turquette <mturquette@...libre.com>,
Stephen Boyd <sboyd@...nel.org>, Sudeep Holla <sudeep.holla@....com>,
Cristian Marussi <cristian.marussi@....com>,
Marco Felsch <m.felsch@...gutronix.de>
Cc: Brian Masney <bmasney@...hat.com>,
Dan Carpenter <dan.carpenter@...aro.org>,
Geert Uytterhoeven <geert@...ux-m68k.org>, linux-clk@...r.kernel.org,
linux-kernel@...r.kernel.org, arm-scmi@...r.kernel.org,
linux-arm-kernel@...ts.infradead.org, Peng Fan <peng.fan@....com>
Subject: [PATCH v2 2/3] clk: conf: Support assigned-clock-sscs
Parse the Spread Spectrum Configuration(SSC) from device tree and configure
them before using the clock.
Each SSC is three u32 elements which means '<modfreq spreaddepth
modmethod>', so assigned-clock-sscs is an array of multiple three u32
elements.
Signed-off-by: Peng Fan <peng.fan@....com>
---
drivers/clk/clk-conf.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 69 insertions(+)
diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
index 303a0bb26e54a95655ce094a35b989c97ebc6fd8..dd6083597db3f8f27d86abf5640dfc3fb39a9b88 100644
--- a/drivers/clk/clk-conf.c
+++ b/drivers/clk/clk-conf.c
@@ -155,6 +155,71 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
return 0;
}
+static int __set_clk_spread_spectrum(struct device_node *node, bool clk_supplier)
+{
+ struct clk_spread_spectrum *sscs __free(kfree) = NULL;
+ u32 elem_size = sizeof(struct clk_spread_spectrum);
+ struct of_phandle_args clkspec;
+ int rc, count, index;
+ struct clk *clk;
+
+ /* modfreq, spreadPercent, modmethod */
+ count = of_property_count_elems_of_size(node, "assigned-clock-sscs", elem_size);
+ if (count <= 0)
+ return 0;
+
+ sscs = kcalloc(count, elem_size, GFP_KERNEL);
+ if (!sscs)
+ return -ENOMEM;
+
+ rc = of_property_read_u32_array(node, "assigned-clock-sscs", (u32 *)sscs,
+ count * 3);
+ if (rc)
+ return rc;
+
+ for (index = 0; index < count; index++) {
+ struct clk_spread_spectrum *conf = &sscs[index];
+ struct clk_hw *hw;
+
+ if (!conf->modfreq_hz && !conf->spread_bp && !conf->method)
+ continue;
+
+ rc = of_parse_phandle_with_args(node, "assigned-clocks", "#clock-cells",
+ index, &clkspec);
+ if (rc < 0) {
+ /* skip empty (null) phandles */
+ if (rc == -ENOENT)
+ continue;
+ else
+ return rc;
+ }
+
+ if (clkspec.np == node && !clk_supplier) {
+ of_node_put(clkspec.np);
+ return 0;
+ }
+
+ clk = of_clk_get_from_provider(&clkspec);
+ of_node_put(clkspec.np);
+ if (IS_ERR(clk)) {
+ if (PTR_ERR(clk) != -EPROBE_DEFER)
+ pr_warn("clk: couldn't get clock %d for %pOF\n",
+ index, node);
+ return PTR_ERR(clk);
+ }
+
+ hw = __clk_get_hw(clk);
+ rc = clk_hw_set_spread_spectrum(hw, conf);
+ if (rc < 0)
+ pr_err("clk: couldn't set %s clk spread spectrum %u %u %u: %d\n",
+ __clk_get_name(clk), conf->modfreq_hz, conf->spread_bp,
+ conf->method, rc);
+ clk_put(clk);
+ }
+
+ return 0;
+}
+
/**
* of_clk_set_defaults() - parse and set assigned clocks configuration
* @node: device node to apply clock settings for
@@ -174,6 +239,10 @@ int of_clk_set_defaults(struct device_node *node, bool clk_supplier)
if (!node)
return 0;
+ rc = __set_clk_spread_spectrum(node, clk_supplier);
+ if (rc < 0)
+ return rc;
+
rc = __set_clk_parents(node, clk_supplier);
if (rc < 0)
return rc;
--
2.37.1
Powered by blists - more mailing lists