diff options
author | Boris Brezillon <boris.brezillon@free-electrons.com> | 2015-07-07 18:48:08 (GMT) |
---|---|---|
committer | Stephen Boyd <sboyd@codeaurora.org> | 2015-07-28 01:12:01 (GMT) |
commit | 0817b62cc037a56c5e4238c7eb7522299ea27aef (patch) | |
tree | e49a8eaceb710fd2873c93c86ef71bf4ff502902 /include | |
parent | d770e558e21961ad6cfdf0ff7df0eb5d7d4f0754 (diff) | |
download | linux-0817b62cc037a56c5e4238c7eb7522299ea27aef.tar.xz |
clk: change clk_ops' ->determine_rate() prototype
Clock rates are stored in an unsigned long field, but ->determine_rate()
(which returns a rounded rate from a requested one) returns a long
value (errors are reported using negative error codes), which can lead
to long overflow if the clock rate exceed 2Ghz.
Change ->determine_rate() prototype to return 0 or an error code, and pass
a pointer to a clk_rate_request structure containing the expected target
rate and the rate constraints imposed by clk users.
The clk_rate_request structure might be extended in the future to contain
other kind of constraints like the rounding policy, the maximum clock
inaccuracy or other things that are not yet supported by the CCF
(power consumption constraints ?).
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
CC: Jonathan Corbet <corbet@lwn.net>
CC: Tony Lindgren <tony@atomide.com>
CC: Ralf Baechle <ralf@linux-mips.org>
CC: "Emilio López" <emilio@elopez.com.ar>
CC: Maxime Ripard <maxime.ripard@free-electrons.com>
Acked-by: Tero Kristo <t-kristo@ti.com>
CC: Peter De Schrijver <pdeschrijver@nvidia.com>
CC: Prashant Gaikwad <pgaikwad@nvidia.com>
CC: Stephen Warren <swarren@wwwdotorg.org>
CC: Thierry Reding <thierry.reding@gmail.com>
CC: Alexandre Courbot <gnurou@gmail.com>
CC: linux-doc@vger.kernel.org
CC: linux-kernel@vger.kernel.org
CC: linux-arm-kernel@lists.infradead.org
CC: linux-omap@vger.kernel.org
CC: linux-mips@linux-mips.org
CC: linux-tegra@vger.kernel.org
[sboyd@codeaurora.org: Fix parent dereference problem in
__clk_determine_rate()]
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Tested-by: Romain Perier <romain.perier@gmail.com>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
[sboyd@codeaurora.org: Folded in fix from Heiko for fixed-rate
clocks without parents or a rate determining op]
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/clk-provider.h | 49 | ||||
-rw-r--r-- | include/linux/clk/ti.h | 16 |
2 files changed, 33 insertions, 32 deletions
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 78842f4..14998f0 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -38,6 +38,28 @@ struct clk_core; struct dentry; /** + * struct clk_rate_request - Structure encoding the clk constraints that + * a clock user might require. + * + * @rate: Requested clock rate. This field will be adjusted by + * clock drivers according to hardware capabilities. + * @min_rate: Minimum rate imposed by clk users. + * @max_rate: Maximum rate a imposed by clk users. + * @best_parent_rate: The best parent rate a parent can provide to fulfill the + * requested constraints. + * @best_parent_hw: The most appropriate parent clock that fulfills the + * requested constraints. + * + */ +struct clk_rate_request { + unsigned long rate; + unsigned long min_rate; + unsigned long max_rate; + unsigned long best_parent_rate; + struct clk_hw *best_parent_hw; +}; + +/** * struct clk_ops - Callback operations for hardware clocks; these are to * be provided by the clock implementation, and will be called by drivers * through the clk_* api. @@ -176,12 +198,8 @@ struct clk_ops { unsigned long parent_rate); long (*round_rate)(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate); - long (*determine_rate)(struct clk_hw *hw, - unsigned long rate, - unsigned long min_rate, - unsigned long max_rate, - unsigned long *best_parent_rate, - struct clk_hw **best_parent_hw); + int (*determine_rate)(struct clk_hw *hw, + struct clk_rate_request *req); int (*set_parent)(struct clk_hw *hw, u8 index); u8 (*get_parent)(struct clk_hw *hw); int (*set_rate)(struct clk_hw *hw, unsigned long rate, @@ -578,20 +596,11 @@ unsigned long __clk_get_flags(struct clk *clk); bool __clk_is_prepared(struct clk *clk); bool __clk_is_enabled(struct clk *clk); struct clk *__clk_lookup(const char *name); -long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate, - unsigned long min_rate, - unsigned long max_rate, - unsigned long *best_parent_rate, - struct clk_hw **best_parent_p); -unsigned long __clk_determine_rate(struct clk_hw *core, - unsigned long rate, - unsigned long min_rate, - unsigned long max_rate); -long __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long rate, - unsigned long min_rate, - unsigned long max_rate, - unsigned long *best_parent_rate, - struct clk_hw **best_parent_p); +int __clk_mux_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req); +int __clk_determine_rate(struct clk_hw *core, struct clk_rate_request *req); +int __clk_mux_determine_rate_closest(struct clk_hw *hw, + struct clk_rate_request *req); void clk_hw_reparent(struct clk_hw *hw, struct clk_hw *new_parent); static inline void __clk_hw_set_clk(struct clk_hw *dst, struct clk_hw *src) diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h index 79b76e1..448b4f8 100644 --- a/include/linux/clk/ti.h +++ b/include/linux/clk/ti.h @@ -269,23 +269,15 @@ int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate, u8 index); -long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, - unsigned long rate, - unsigned long min_rate, - unsigned long max_rate, - unsigned long *best_parent_rate, - struct clk_hw **best_parent_clk); +int omap3_noncore_dpll_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req); unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw, unsigned long parent_rate); long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw, unsigned long target_rate, unsigned long *parent_rate); -long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, - unsigned long rate, - unsigned long min_rate, - unsigned long max_rate, - unsigned long *best_parent_rate, - struct clk_hw **best_parent_clk); +int omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req); u8 omap2_init_dpll_parent(struct clk_hw *hw); unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate); long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, |