These functions will be used in the incoming STM32MP13 clock driver support. Signed-off-by: Ahmad Fatoum <a.fatoum@xxxxxxxxxxxxxx> --- drivers/clk/clk-divider.c | 35 ++++++++++++++++++++++++++++++++++- include/linux/clk-provider.h | 21 +++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 150b1fe60fd4..ccab70aecca2 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -7,7 +7,7 @@ #include <common.h> #include <io.h> #include <malloc.h> -#include <linux/clk.h> +#include <linux/clk-provider.h> #include <linux/err.h> #include <linux/log2.h> #include <linux/math64.h> @@ -240,6 +240,39 @@ long divider_round_rate(struct clk *clk, unsigned long rate, return DIV_ROUND_UP(*prate, div); } +long divider_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent, + unsigned long rate, unsigned long *prate, + const struct clk_div_table *table, + u8 width, unsigned long flags) +{ + int div; + + div = clk_divider_bestdiv(&hw->clk, rate, prate, table, width, flags); + + return DIV_ROUND_UP_ULL((u64)*prate, div); +} +EXPORT_SYMBOL_GPL(divider_round_rate_parent); + +long divider_ro_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent, + unsigned long rate, unsigned long *prate, + const struct clk_div_table *table, u8 width, + unsigned long flags, unsigned int val) +{ + int div; + + div = _get_div(table, val, flags, width); + + /* Even a read-only clock can propagate a rate change */ + if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) { + if (!*prate) + return -EINVAL; + + *prate = clk_hw_round_rate(clk_hw_get_parent(hw), rate * div); + } + + return DIV_ROUND_UP_ULL((u64)*prate, div); +} + static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 207f3b205dab..6d781fbfcc2e 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -8,6 +8,27 @@ #include <linux/clk.h> +long divider_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent, + unsigned long rate, unsigned long *prate, + const struct clk_div_table *table, + u8 width, unsigned long flags); + +long divider_ro_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent, + unsigned long rate, unsigned long *prate, + const struct clk_div_table *table, u8 width, + unsigned long flags, unsigned int val); + +static inline long divider_ro_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate, + const struct clk_div_table *table, + u8 width, unsigned long flags, + unsigned int val) +{ + return divider_ro_round_rate_parent(hw, clk_hw_get_parent(hw), + rate, prate, table, width, flags, + val); +} + #define CLK_HW_INIT(_name, _parent, _ops, _flags) \ (&(struct clk_init_data) { \ .flags = _flags, \ -- 2.39.2