[PATCH 02/20] clk: multiplier: Prevent the multiplier from under / over flowing
Michael Turquette
mturquette at baylibre.com
Mon Jun 20 13:50:30 PDT 2016
Quoting Maxime Ripard (2016-05-16 05:47:02)
> In the current multiplier base clock implementation, if the
> CLK_SET_RATE_PARENT flag isn't set, the code will not make sure that the
> multiplier computed remains within the boundaries of our clock.
>
> This means that if the clock we want to reach is below the parent rate,
> or if the multiplier is above the maximum that we can reach, we will end up
> with a completely bogus one that the clock cannot achieve.
>
> Fixes: f2e0a53271a4 ("clk: Add a basic multiplier clock")
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
Applied.
Regards,
Mike
> ---
> drivers/clk/clk-multiplier.c | 20 +++++++++++++++++---
> 1 file changed, 17 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/clk/clk-multiplier.c b/drivers/clk/clk-multiplier.c
> index 9e449c7b751c..dc037c957acd 100644
> --- a/drivers/clk/clk-multiplier.c
> +++ b/drivers/clk/clk-multiplier.c
> @@ -52,14 +52,28 @@ static unsigned long __bestmult(struct clk_hw *hw, unsigned long rate,
> unsigned long *best_parent_rate,
> u8 width, unsigned long flags)
> {
> + struct clk_multiplier *mult = to_clk_multiplier(hw);
> unsigned long orig_parent_rate = *best_parent_rate;
> unsigned long parent_rate, current_rate, best_rate = ~0;
> unsigned int i, bestmult = 0;
> + unsigned int maxmult = (1 << width) - 1;
> +
> + if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
> + bestmult = rate / orig_parent_rate;
> +
> + /* Make sure we don't end up with a 0 multiplier */
> + if ((bestmult == 0) &&
> + !(mult->flags & CLK_MULTIPLIER_ZERO_BYPASS))
> + bestmult = 1;
>
> - if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT))
> - return rate / *best_parent_rate;
> + /* Make sure we don't overflow the multiplier */
> + if (bestmult > maxmult)
> + bestmult = maxmult;
> +
> + return bestmult;
> + }
>
> - for (i = 1; i < ((1 << width) - 1); i++) {
> + for (i = 1; i < maxmult; i++) {
> if (rate == orig_parent_rate * i) {
> /*
> * This is the best case for us if we have a
> --
> 2.8.2
>
More information about the linux-arm-kernel
mailing list