|  | @@ -199,3 +199,116 @@ static u32 _divisor_to_clksel(struct clk_hw_omap *clk, u32 div)
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  static u32 _read_divisor(struct clk_hw_omap *clk)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | +	u32 v;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (!clk->clksel || !clk->clksel_mask)
 | 
	
		
			
				|  |  | +		return 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	v = __raw_readl(clk->clksel_reg);
 | 
	
		
			
				|  |  | +	v &= clk->clksel_mask;
 | 
	
		
			
				|  |  | +	v >>= __ffs(clk->clksel_mask);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return _clksel_to_divisor(clk, v);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/* Public functions */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * omap2_clksel_round_rate_div() - find divisor for the given clock and rate
 | 
	
		
			
				|  |  | + * @clk: OMAP struct clk to use
 | 
	
		
			
				|  |  | + * @target_rate: desired clock rate
 | 
	
		
			
				|  |  | + * @new_div: ptr to where we should store the divisor
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * Finds 'best' divider value in an array based on the source and target
 | 
	
		
			
				|  |  | + * rates.  The divider array must be sorted with smallest divider first.
 | 
	
		
			
				|  |  | + * This function is also used by the DPLL3 M2 divider code.
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * Returns the rounded clock rate or returns 0xffffffff on error.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +u32 omap2_clksel_round_rate_div(struct clk_hw_omap *clk,
 | 
	
		
			
				|  |  | +						 unsigned long target_rate,
 | 
	
		
			
				|  |  | +				u32 *new_div)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	unsigned long test_rate;
 | 
	
		
			
				|  |  | +	const struct clksel *clks;
 | 
	
		
			
				|  |  | +	const struct clksel_rate *clkr;
 | 
	
		
			
				|  |  | +	u32 last_div = 0;
 | 
	
		
			
				|  |  | +	struct clk *parent;
 | 
	
		
			
				|  |  | +	unsigned long parent_rate;
 | 
	
		
			
				|  |  | +	const char *clk_name;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	parent = __clk_get_parent(clk->hw.clk);
 | 
	
		
			
				|  |  | +	clk_name = __clk_get_name(clk->hw.clk);
 | 
	
		
			
				|  |  | +	parent_rate = __clk_get_rate(parent);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (!clk->clksel || !clk->clksel_mask)
 | 
	
		
			
				|  |  | +		return ~0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	pr_debug("clock: clksel_round_rate_div: %s target_rate %ld\n",
 | 
	
		
			
				|  |  | +		 clk_name, target_rate);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	*new_div = 1;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	clks = _get_clksel_by_parent(clk, parent);
 | 
	
		
			
				|  |  | +	if (!clks)
 | 
	
		
			
				|  |  | +		return ~0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	for (clkr = clks->rates; clkr->div; clkr++) {
 | 
	
		
			
				|  |  | +		if (!(clkr->flags & cpu_mask))
 | 
	
		
			
				|  |  | +			continue;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		/* Sanity check */
 | 
	
		
			
				|  |  | +		if (clkr->div <= last_div)
 | 
	
		
			
				|  |  | +			pr_err("clock: %s: clksel_rate table not sorted\n",
 | 
	
		
			
				|  |  | +			       clk_name);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		last_div = clkr->div;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		test_rate = parent_rate / clkr->div;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		if (test_rate <= target_rate)
 | 
	
		
			
				|  |  | +			break; /* found it */
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (!clkr->div) {
 | 
	
		
			
				|  |  | +		pr_err("clock: %s: could not find divisor for target rate %ld for parent %s\n",
 | 
	
		
			
				|  |  | +		       clk_name, target_rate, __clk_get_name(parent));
 | 
	
		
			
				|  |  | +		return ~0;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	*new_div = clkr->div;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	pr_debug("clock: new_div = %d, new_rate = %ld\n", *new_div,
 | 
	
		
			
				|  |  | +		 (parent_rate / clkr->div));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return parent_rate / clkr->div;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + * Clocktype interface functions to the OMAP clock code
 | 
	
		
			
				|  |  | + * (i.e., those used in struct clk field function pointers, etc.)
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * omap2_clksel_find_parent_index() - return the array index of the current
 | 
	
		
			
				|  |  | + * hardware parent of @hw
 | 
	
		
			
				|  |  | + * @hw: struct clk_hw * to find the current hardware parent of
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * Given a struct clk_hw pointer @hw to the 'hw' member of a struct
 | 
	
		
			
				|  |  | + * clk_hw_omap record representing a source-selectable hardware clock,
 | 
	
		
			
				|  |  | + * read the hardware register and determine what its parent is
 | 
	
		
			
				|  |  | + * currently set to.  Intended to be called only by the common clock
 | 
	
		
			
				|  |  | + * framework struct clk_hw_ops.get_parent function pointer.  Return
 | 
	
		
			
				|  |  | + * the array index of this parent clock upon success -- there is no
 | 
	
		
			
				|  |  | + * way to return an error, so if we encounter an error, just WARN()
 | 
	
		
			
				|  |  | + * and pretend that we know that we're doing.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +u8 omap2_clksel_find_parent_index(struct clk_hw *hw)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 | 
	
		
			
				|  |  | +	const struct clksel *clks;
 | 
	
		
			
				|  |  | +	const struct clksel_rate *clkr;
 | 
	
		
			
				|  |  | +	u32 r, found = 0;
 | 
	
		
			
				|  |  | +	struct clk *parent;
 | 
	
		
			
				|  |  | +	const char *clk_name;
 | 
	
		
			
				|  |  | +	int ret = 0, f = 0;
 |