From 1008f7a86f470914e78a54a2a75cf8bbc8b8f9db Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 15 Apr 2022 14:17:41 +0200 Subject: [PATCH] clk: Add clk_get_rate_range With the recent introduction of clock drivers that will force their clock rate to either the minimum or maximum boundaries, it becomes harder for clock users to discover either boundary of their clock. Indeed, the best way to do that previously was to call clk_round_rate() on either 0 or ULONG_MAX and count on the driver to clamp the rate to the current boundary, but that won't work anymore. Since any other alternative (calling clk_set_rate_range() and looking at the returned value, calling clk_round_rate() still, or just doing nothing) depends on how the driver will behaves, we actually are punching a hole through the abstraction provided by the clock framework. In order to avoid any abstraction violation, let's create a bunch of accessors that will return the current minimum and maximum for a given clock. Signed-off-by: Maxime Ripard --- drivers/clk/clk.c | 18 ++++++++++++++ include/linux/clk.h | 59 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2586,6 +2586,24 @@ int clk_set_max_rate(struct clk *clk, un EXPORT_SYMBOL_GPL(clk_set_max_rate); /** + * clk_get_rate_range - returns the clock rate range for a clock source + * @clk: clock source + * @min: Pointer to the variable that will hold the minimum + * @max: Pointer to the variable that will hold the maximum + * + * Fills the @min and @max variables with the minimum and maximum that + * the clock source can reach. + */ +void clk_get_rate_range(struct clk *clk, unsigned long *min, unsigned long *max) +{ + if (!clk || !min || !max) + return; + + clk_core_get_boundaries(clk->core, min, max); +} +EXPORT_SYMBOL_GPL(clk_get_rate_range); + +/** * clk_get_parent - return the parent of a clk * @clk: the clk whose parent gets returned * --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -807,6 +807,17 @@ bool clk_has_parent(struct clk *clk, str int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max); /** + * clk_get_rate_range - returns the clock rate range for a clock source + * @clk: clock source + * @min: Pointer to the variable that will hold the minimum + * @max: Pointer to the variable that will hold the maximum + * + * Fills the @min and @max variables with the minimum and maximum that + * the clock source can reach. + */ +void clk_get_rate_range(struct clk *clk, unsigned long *min, unsigned long *max); + +/** * clk_set_min_rate - set a minimum clock rate for a clock source * @clk: clock source * @rate: desired minimum clock rate in Hz, inclusive @@ -1018,6 +1029,16 @@ static inline int clk_set_rate_range(str return 0; } +static inline void clk_get_rate_range(struct clk *clk, unsigned long *min, + unsigned long *max) +{ + if (!min || !max) + return; + + *min = 0; + *max = ULONG_MAX; +} + static inline int clk_set_min_rate(struct clk *clk, unsigned long rate) { return 0; @@ -1108,6 +1129,44 @@ static inline int clk_drop_range(struct } /** + * clk_get_min_rate - returns the minimum clock rate for a clock source + * @clk: clock source + * + * Returns either the minimum clock rate in Hz that clock source can + * reach, or 0 on error. + */ +static inline unsigned long clk_get_min_rate(struct clk *clk) +{ + unsigned long min, max; + + if (!clk) + return 0; + + clk_get_rate_range(clk, &min, &max); + + return min; +} + +/** + * clk_get_max_rate - returns the maximum clock rate for a clock source + * @clk: clock source + * + * Returns either the maximum clock rate in Hz that clock source can + * reach, or 0 on error. + */ +static inline unsigned long clk_get_max_rate(struct clk *clk) +{ + unsigned long min, max; + + if (!clk) + return 0; + + clk_get_rate_range(clk, &min, &max); + + return max; +} + +/** * clk_get_optional - lookup and obtain a reference to an optional clock * producer. * @dev: device for clock "consumer"