diff options
| -rw-r--r-- | drivers/clk/zynqmp/divider.c | 46 | 
1 files changed, 46 insertions, 0 deletions
| diff --git a/drivers/clk/zynqmp/divider.c b/drivers/clk/zynqmp/divider.c index da6903197fc7..c6af0c454997 100644 --- a/drivers/clk/zynqmp/divider.c +++ b/drivers/clk/zynqmp/divider.c @@ -89,6 +89,42 @@ static unsigned long zynqmp_clk_divider_recalc_rate(struct clk_hw *hw,  	return DIV_ROUND_UP_ULL(parent_rate, value);  } +static void zynqmp_get_divider2_val(struct clk_hw *hw, +				    unsigned long rate, +				    unsigned long parent_rate, +				    struct zynqmp_clk_divider *divider, +				    int *bestdiv) +{ +	int div1; +	int div2; +	long error = LONG_MAX; +	struct clk_hw *parent_hw = clk_hw_get_parent(hw); +	struct zynqmp_clk_divider *pdivider = to_zynqmp_clk_divider(parent_hw); + +	if (!pdivider) +		return; + +	*bestdiv = 1; +	for (div1 = 1; div1 <= pdivider->max_div;) { +		for (div2 = 1; div2 <= divider->max_div;) { +			long new_error = ((parent_rate / div1) / div2) - rate; + +			if (abs(new_error) < abs(error)) { +				*bestdiv = div2; +				error = new_error; +			} +			if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) +				div2 = div2 << 1; +			else +				div2++; +		} +		if (pdivider->flags & CLK_DIVIDER_POWER_OF_TWO) +			div1 = div1 << 1; +		else +			div1++; +	} +} +  /**   * zynqmp_clk_divider_round_rate() - Round rate of divider clock   * @hw:			handle between common and hardware-specific interfaces @@ -126,6 +162,16 @@ static long zynqmp_clk_divider_round_rate(struct clk_hw *hw,  	bestdiv = zynqmp_divider_get_val(*prate, rate); +	/* +	 * In case of two divisors, compute best divider values and return +	 * divider2 value based on compute value. div1 will  be automatically +	 * set to optimum based on required total divider value. +	 */ +	if (div_type == TYPE_DIV2 && +	    (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) { +		zynqmp_get_divider2_val(hw, rate, *prate, divider, &bestdiv); +	} +  	if ((clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) && divider->is_frac)  		bestdiv = rate % *prate ? 1 : bestdiv;  	*prate = rate * bestdiv; | 
