clk: Introduce clk_hw_set_spread_spectrum

Add clk_hw_set_spread_spectrum to configure a clock to enable spread
spectrum feature. set_spread_spectrum ops is added for clk drivers to
have their own hardware specific implementation.

Reviewed-by: Brian Masney <bmasney@redhat.com>
Reviewed-by: Sebin Francis <sebin.francis@ti.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
Signed-off-by: Brian Masney <bmasney@redhat.com>
This commit is contained in:
Peng Fan 2026-06-12 16:46:24 +08:00 committed by Brian Masney
parent ae794aa6e8
commit c86814e703
2 changed files with 58 additions and 0 deletions

View File

@ -2774,6 +2774,33 @@ int clk_set_max_rate(struct clk *clk, unsigned long rate)
}
EXPORT_SYMBOL_GPL(clk_set_max_rate);
int clk_hw_set_spread_spectrum(struct clk_hw *hw, const struct clk_spread_spectrum *ss_conf)
{
struct clk_core *core;
int ret;
if (!hw)
return 0;
core = hw->core;
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, ss_conf);
clk_pm_runtime_put(core);
fail:
clk_prepare_unlock();
return ret;
}
EXPORT_SYMBOL_GPL(clk_hw_set_spread_spectrum);
/**
* clk_get_parent - return the parent of a clk
* @clk: the clk whose parent gets returned

View File

@ -6,6 +6,7 @@
#ifndef __LINUX_CLK_PROVIDER_H
#define __LINUX_CLK_PROVIDER_H
#include <dt-bindings/clock/clock.h>
#include <linux/of.h>
#include <linux/of_clk.h>
@ -84,6 +85,26 @@ struct clk_duty {
unsigned int den;
};
enum clk_ssc_method {
CLK_SPREAD_NO = CLK_SSC_NO_SPREAD,
CLK_SPREAD_CENTER = CLK_SSC_CENTER_SPREAD,
CLK_SPREAD_UP = CLK_SSC_UP_SPREAD,
CLK_SPREAD_DOWN = CLK_SSC_DOWN_SPREAD,
};
/**
* struct clk_spread_spectrum - Structure encoding spread spectrum of a clock
*
* @modfreq_hz: Modulation frequency
* @spread_bp: Modulation percent in permyriad
* @method: Modulation method
*/
struct clk_spread_spectrum {
u32 modfreq_hz;
u32 spread_bp;
enum clk_ssc_method method;
};
/**
* struct clk_ops - Callback operations for hardware clocks; these are to
* be provided by the clock implementation, and will be called by drivers
@ -174,6 +195,12 @@ struct clk_duty {
* separately via calls to .set_parent and .set_rate.
* Returns 0 on success, -EERROR otherwise.
*
* @set_spread_spectrum: Optional callback used to configure the spread
* spectrum modulation frequency, percentage, and method
* to reduce EMI by spreading the clock frequency over a
* wider range.
* Returns 0 on success, -EERROR otherwise.
*
* @recalc_accuracy: Recalculate the accuracy of this clock. The clock accuracy
* is expressed in ppb (parts per billion). The parent accuracy is
* an input parameter.
@ -249,6 +276,8 @@ struct clk_ops {
int (*set_rate_and_parent)(struct clk_hw *hw,
unsigned long rate,
unsigned long parent_rate, u8 index);
int (*set_spread_spectrum)(struct clk_hw *hw,
const struct clk_spread_spectrum *ss_conf);
unsigned long (*recalc_accuracy)(struct clk_hw *hw,
unsigned long parent_accuracy);
int (*get_phase)(struct clk_hw *hw);
@ -1436,6 +1465,8 @@ void clk_hw_get_rate_range(struct clk_hw *hw, unsigned long *min_rate,
unsigned long *max_rate);
void clk_hw_set_rate_range(struct clk_hw *hw, unsigned long min_rate,
unsigned long max_rate);
int clk_hw_set_spread_spectrum(struct clk_hw *hw,
const struct clk_spread_spectrum *ss_conf);
static inline void __clk_hw_set_clk(struct clk_hw *dst, struct clk_hw *src)
{