RE: [PATCH v2 1/4] clk: Introduce clk_hw_set_spread_spectrum
From: Peng Fan <peng.fan@nxp.com>
Date: 2025-02-06 00:38:46
Also in:
arm-scmi, imx, linux-clk, lkml
Subject: Re: [PATCH v2 1/4] clk: Introduce clk_hw_set_spread_spectrum Hi Peng, On 25-02-05, Peng Fan (OSS) wrote:quoted
From: Peng Fan <peng.fan@nxp.com> Add clk_hw_set_spread_spectrum to configure a clock to enablespreadquoted
spectrum feature. set_spread_spectrum ops is added for clk drivers to have their own hardware specific implementation. Signed-off-by: Peng Fan <peng.fan@nxp.com> --- drivers/clk/clk.c | 34 ++++++++++++++++++++++++++++++++++ include/linux/clk-provider.h | 32++++++++++++++++++++++++++++++++quoted
include/linux/clk.h | 22 ++++++++++++++++++++++ 3 files changed, 88 insertions(+)diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c indexcf7720b9172ff223d86227aad144e15375ddfd86..e11f9615e683af52c7 19d4c8419bquoted
d30f369f301b 100644--- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c@@ -2790,6 +2790,40 @@ int clk_set_max_rate(struct clk *clk,unsignedquoted
long rate) } EXPORT_SYMBOL_GPL(clk_set_max_rate); +int clk_hw_set_spread_spectrum(struct clk_hw *hw, unsigned intmodfreq,quoted
+ unsigned int spreaddepth, enumclk_ssc_method method,quoted
+ bool enable) +{ + struct clk_spread_spectrum clk_ss; + struct clk_core *core; + int ret; + + if (!hw) + return 0; + + core = hw->core; + + clk_ss.modfreq = modfreq; + clk_ss.spreaddepth = spreaddepth; + clk_ss.method = method; + clk_ss.enable = enable; + + clk_prepare_lock(); + + ret = clk_pm_runtime_get(core); + if (ret) + goto fail; + + if (core->ops->set_spread_spectrum) + ret = core->ops->set_spread_spectrum(hw, &clk_ss); + + clk_pm_runtime_put(core); + +fail: + clk_prepare_unlock(); + return ret; +} + /** * clk_get_parent - return the parent of a clk * @clk: the clk whose parent gets returned diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index2e6e603b749342931c0d0693c3e72b62c000791b..ac0270cc9ec13395 4b1f8dcffed0quoted
15723bd1ff5d 100644--- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h@@ -84,6 +84,28 @@ struct clk_duty { unsigned int den; }; +/* Aligned with dtschema/schemas/clock/clock.yaml */ enum +clk_ssc_method { + CLK_SSC_CENTER_SPREAD, + CLK_SSC_UP_SPREAD, + CLK_SSC_DOWN_SPREAD, +}; + +/** + * struct clk_spread_spectrum - Structure encoding spread spectrumofquoted
+a clock + * + * @modfreq: Modulation frequency + * @spreadpercent: Modulation percent + * @method: Modulation method + * @enable: Modulation enable or disable + */ +struct clk_spread_spectrum { + unsigned int modfreq; + unsigned int spreaddepth;Please use per mil as unit since I noticed that 0.x% is a common value too.
I use " The modulation depth in permyriad " in dt-schema, since Dario said ST chips has permyriad. So change it to moddepth_per_myriad? Thanks, Peng.
Regards, Marcoquoted
+ enum clk_ssc_method method; + bool enable; +}; + /** * struct clk_ops - Callback operations for hardware clocks; these aretoquoted
* be provided by the clock implementation, and will be called by drivers @@ -178,6 +200,11 @@ struct clk_duty { * separately via calls to .set_parent and .set_rate. * Returns 0 on success, -EERROR otherwise. * + * @set_spread_spectrum: Configure the modulation frequency,modulation percentagequoted
+ * and method. This callback is optional for clocks thatdoes notquoted
+ * support spread spectrum feature or no need to enablethis feature.quoted
+ * Returns 0 on success, -EERROR otherwise. + * * @recalc_accuracy: Recalculate the accuracy of this clock. Theclock accuracyquoted
* is expressed in ppb (parts per billion). The parentaccuracy isquoted
* an input parameter.@@ -255,6 +282,8 @@ struct clk_ops { int (*set_rate_and_parent)(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate, u8index);quoted
+ int (*set_spread_spectrum)(struct clk_hw *hw, + structclk_spread_spectrum *clk_ss);quoted
unsigned long (*recalc_accuracy)(struct clk_hw *hw, unsigned longparent_accuracy);quoted
int (*get_phase)(struct clk_hw *hw);@@ -1404,6 +1433,9 @@ void clk_hw_get_rate_range(struct clk_hw*hw, unsigned long *min_rate,quoted
unsigned long *max_rate); void clk_hw_set_rate_range(struct clk_hw *hw, unsigned longmin_rate,quoted
unsigned long max_rate); +int clk_hw_set_spread_spectrum(struct clk_hw *hw, unsigned intmodfreq,quoted
+ unsigned int spreaddepth, enumclk_ssc_method method,quoted
+ bool enable); static inline void __clk_hw_set_clk(struct clk_hw *dst, struct clk_hw *src) { diff --git a/include/linux/clk.h b/include/linux/clk.h indexb607482ca77e987b9344c38f25ebb5c8d35c1d39..49a7f7eb8b03233e 11cd3b927688quoted
96c4e45c4e7c 100644--- a/include/linux/clk.h +++ b/include/linux/clk.h@@ -858,6 +858,21 @@ int clk_set_rate(struct clk *clk, unsignedlong rate);quoted
*/ int clk_set_rate_exclusive(struct clk *clk, unsigned long rate); +/** + * clk_set_spread_spectrum - set the spread spectrum for a clock + * @clk: clock source + * @modfreq: modulation freq + * @spreadpercent: modulation percentage + * @method: down spread, up spread, center spread or else + * @enable: enable or disable + * + * Configure the spread spectrum parameters for a clock. + * + * Returns success (0) or negative errno. + */ +int clk_set_spread_spectrum(struct clk *clk, unsigned int modfreq, + unsigned int spreadpercent, unsigned intmethod,quoted
+ bool enable); /** * clk_has_parent - check if a clock is a possible parent for another * @clk: clock source@@ -1088,6 +1103,13 @@ static inline intclk_set_rate_exclusive(struct clk *clk, unsigned long rate)quoted
return 0; } +static inline int clk_set_spread_spectrum(struct clk *clk, unsignedint modfreq,quoted
+ unsigned int spreadpercent, + unsigned int method, boolenable) {quoted
+ return 0; +} + static inline long clk_round_rate(struct clk *clk, unsigned long rate) { return 0; -- 2.37.1