mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02: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
					
				
					 2 changed files with 45 additions and 10 deletions
				
			
		| 
						 | 
				
			
			@ -690,14 +690,20 @@ struct clk *__clk_lookup(const char *name)
 | 
			
		|||
	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_hw **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_hw **best_parent_p,
 | 
			
		||||
			     unsigned long flags)
 | 
			
		||||
{
 | 
			
		||||
	struct clk *clk = hw->clk, *parent, *best_parent = NULL;
 | 
			
		||||
	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);
 | 
			
		||||
		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;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -738,8 +744,31 @@ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
 | 
			
		|||
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
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        ***/
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
 *	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;
 | 
			
		||||
| 
						 | 
				
			
			@ -398,7 +400,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;
 | 
			
		||||
| 
						 | 
				
			
			@ -556,6 +559,9 @@ struct clk *__clk_lookup(const char *name);
 | 
			
		|||
long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
 | 
			
		||||
			      unsigned long *best_parent_rate,
 | 
			
		||||
			      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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue