mirror of
https://github.com/torvalds/linux.git
synced 2024-11-01 09:41:44 +00:00
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>
This commit is contained in:
parent
52bba9809a
commit
15a02c1f6d
@ -690,14 +690,20 @@ struct clk *__clk_lookup(const char *name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static bool mux_is_better_rate(unsigned long rate, unsigned long now,
|
||||||
* Helper for finding best parent to provide a given frequency. This can be used
|
unsigned long best, unsigned long flags)
|
||||||
* 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.
|
if (flags & CLK_MUX_ROUND_CLOSEST)
|
||||||
*/
|
return abs(now - rate) < abs(best - rate);
|
||||||
long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
|
|
||||||
unsigned long *best_parent_rate,
|
return now <= rate && now > best;
|
||||||
struct clk_hw **best_parent_p)
|
}
|
||||||
|
|
||||||
|
static long
|
||||||
|
clk_mux_determine_rate_flags(struct clk_hw *hw, unsigned long rate,
|
||||||
|
unsigned long *best_parent_rate,
|
||||||
|
struct clk_hw **best_parent_p,
|
||||||
|
unsigned long flags)
|
||||||
{
|
{
|
||||||
struct clk *clk = hw->clk, *parent, *best_parent = NULL;
|
struct clk *clk = hw->clk, *parent, *best_parent = NULL;
|
||||||
int i, num_parents;
|
int i, num_parents;
|
||||||
@ -725,7 +731,7 @@ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
|
|||||||
parent_rate = __clk_round_rate(parent, rate);
|
parent_rate = __clk_round_rate(parent, rate);
|
||||||
else
|
else
|
||||||
parent_rate = __clk_get_rate(parent);
|
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 = parent;
|
||||||
best = parent_rate;
|
best = parent_rate;
|
||||||
}
|
}
|
||||||
@ -738,8 +744,31 @@ out:
|
|||||||
|
|
||||||
return best;
|
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_hw **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);
|
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_hw **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 ***/
|
/*** clk api ***/
|
||||||
|
|
||||||
void __clk_unprepare(struct clk *clk)
|
void __clk_unprepare(struct clk *clk)
|
||||||
|
@ -384,6 +384,8 @@ void clk_unregister_divider(struct clk *clk);
|
|||||||
* register, and mask of mux bits are in higher 16-bit of this register.
|
* 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
|
* While setting the mux bits, higher 16-bit should also be updated to
|
||||||
* indicate changing mux bits.
|
* indicate changing mux bits.
|
||||||
|
* CLK_MUX_ROUND_CLOSEST - Use the parent rate that is closest to the desired
|
||||||
|
* frequency.
|
||||||
*/
|
*/
|
||||||
struct clk_mux {
|
struct clk_mux {
|
||||||
struct clk_hw hw;
|
struct clk_hw hw;
|
||||||
@ -398,7 +400,8 @@ struct clk_mux {
|
|||||||
#define CLK_MUX_INDEX_ONE BIT(0)
|
#define CLK_MUX_INDEX_ONE BIT(0)
|
||||||
#define CLK_MUX_INDEX_BIT BIT(1)
|
#define CLK_MUX_INDEX_BIT BIT(1)
|
||||||
#define CLK_MUX_HIWORD_MASK BIT(2)
|
#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_ops;
|
||||||
extern const struct clk_ops clk_mux_ro_ops;
|
extern const struct clk_ops clk_mux_ro_ops;
|
||||||
@ -556,6 +559,9 @@ struct clk *__clk_lookup(const char *name);
|
|||||||
long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
|
long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
unsigned long *best_parent_rate,
|
unsigned long *best_parent_rate,
|
||||||
struct clk_hw **best_parent_p);
|
struct clk_hw **best_parent_p);
|
||||||
|
long __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long rate,
|
||||||
|
unsigned long *best_parent_rate,
|
||||||
|
struct clk_hw **best_parent_p);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FIXME clock api without lock protection
|
* FIXME clock api without lock protection
|
||||||
|
Loading…
Reference in New Issue
Block a user