123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- From 15a02c1f6dd7c2bb150c61d00ffb33f584ff2288 Mon Sep 17 00:00:00 2001
- From: Stephen Boyd <sboyd@codeaurora.org>
- Date: Mon, 19 Jan 2015 18:05:28 -0800
- Subject: [PATCH] clk: Add __clk_mux_determine_rate_closest
- Some clock drivers want to find the closest rate on the input of
- a mux instead of a rate that's less than or equal to the desired
- rate. Add a generic mux function to support this.
- Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
- Tested-by: Kenneth Westfield <kwestfie@codeaurora.org>
- Signed-off-by: Michael Turquette <mturquette@linaro.org>
- ---
- drivers/clk/clk.c | 47 +++++++++++++++++++++++++++++++++++---------
- include/linux/clk-provider.h | 8 +++++++-
- 2 files changed, 45 insertions(+), 10 deletions(-)
- --- a/drivers/clk/clk.c
- +++ b/drivers/clk/clk.c
- @@ -695,14 +695,20 @@ struct clk *__clk_lookup(const char *nam
- return NULL;
- }
-
- -/*
- - * Helper for finding best parent to provide a given frequency. This can be used
- - * directly as a determine_rate callback (e.g. for a mux), or from a more
- - * complex clock that may combine a mux with other operations.
- - */
- -long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
- - unsigned long *best_parent_rate,
- - struct clk **best_parent_p)
- +static bool mux_is_better_rate(unsigned long rate, unsigned long now,
- + unsigned long best, unsigned long flags)
- +{
- + if (flags & CLK_MUX_ROUND_CLOSEST)
- + return abs(now - rate) < abs(best - rate);
- +
- + return now <= rate && now > best;
- +}
- +
- +static long
- +clk_mux_determine_rate_flags(struct clk_hw *hw, unsigned long rate,
- + unsigned long *best_parent_rate,
- + struct clk **best_parent_p,
- + unsigned long flags)
- {
- struct clk *clk = hw->clk, *parent, *best_parent = NULL;
- int i, num_parents;
- @@ -730,7 +736,7 @@ long __clk_mux_determine_rate(struct clk
- parent_rate = __clk_round_rate(parent, rate);
- else
- parent_rate = __clk_get_rate(parent);
- - if (parent_rate <= rate && parent_rate > best) {
- + if (mux_is_better_rate(rate, parent_rate, best, flags)) {
- best_parent = parent;
- best = parent_rate;
- }
- @@ -743,8 +749,31 @@ out:
-
- return best;
- }
- +
- +/*
- + * Helper for finding best parent to provide a given frequency. This can be used
- + * directly as a determine_rate callback (e.g. for a mux), or from a more
- + * complex clock that may combine a mux with other operations.
- + */
- +long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
- + unsigned long *best_parent_rate,
- + struct clk **best_parent_p)
- +{
- + return clk_mux_determine_rate_flags(hw, rate, best_parent_rate,
- + best_parent_p, 0);
- +}
- EXPORT_SYMBOL_GPL(__clk_mux_determine_rate);
-
- +long __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long rate,
- + unsigned long *best_parent_rate,
- + struct clk **best_parent_p)
- +{
- + return clk_mux_determine_rate_flags(hw, rate, best_parent_rate,
- + best_parent_p,
- + CLK_MUX_ROUND_CLOSEST);
- +}
- +EXPORT_SYMBOL_GPL(__clk_mux_determine_rate_closest);
- +
- /*** clk api ***/
-
- void __clk_unprepare(struct clk *clk)
- --- a/include/linux/clk-provider.h
- +++ b/include/linux/clk-provider.h
- @@ -382,6 +382,8 @@ struct clk *clk_register_divider_table(s
- * register, and mask of mux bits are in higher 16-bit of this register.
- * While setting the mux bits, higher 16-bit should also be updated to
- * indicate changing mux bits.
- + * CLK_MUX_ROUND_CLOSEST - Use the parent rate that is closest to the desired
- + * frequency.
- */
- struct clk_mux {
- struct clk_hw hw;
- @@ -396,7 +398,8 @@ struct clk_mux {
- #define CLK_MUX_INDEX_ONE BIT(0)
- #define CLK_MUX_INDEX_BIT BIT(1)
- #define CLK_MUX_HIWORD_MASK BIT(2)
- -#define CLK_MUX_READ_ONLY BIT(3) /* mux setting cannot be changed */
- +#define CLK_MUX_READ_ONLY BIT(3) /* mux can't be changed */
- +#define CLK_MUX_ROUND_CLOSEST BIT(4)
-
- extern const struct clk_ops clk_mux_ops;
- extern const struct clk_ops clk_mux_ro_ops;
- @@ -554,6 +557,9 @@ struct clk *__clk_lookup(const char *nam
- long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *best_parent_rate,
- struct clk **best_parent_p);
- +long __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long rate,
- + unsigned long *best_parent_rate,
- + struct clk **best_parent_p);
-
- /*
- * FIXME clock api without lock protection
|