Commit ed84ef1c authored by Paul Cercueil's avatar Paul Cercueil Committed by Stephen Boyd

clk: ingenic: Fix bugs with divided dividers

Two fixes in one:

- In the "impose hardware constraints" block, the "logical" divider
  value (aka. not translated to the hardware) was clamped to fit in the
  register area, but this totally ignored the fact that the divider
  value can itself have a fixed divider.

- The code that made sure that the divider value returned by the
  function was a multiple of its own fixed divider could result in a
  wrong value being calculated, because it was rounded down instead of
  rounded up.

Fixes: 4afe2d1a ("clk: ingenic: Allow divider value to be divided")
Co-developed-by: default avatarArtur Rojek <contact@artur-rojek.eu>
Signed-off-by: default avatarArtur Rojek <contact@artur-rojek.eu>
Signed-off-by: default avatarPaul Cercueil <paul@crapouillou.net>
Link: https://lore.kernel.org/r/20211001172033.122329-1-paul@crapouillou.netSigned-off-by: default avatarStephen Boyd <sboyd@kernel.org>
parent e2ceaa86
......@@ -453,15 +453,15 @@ ingenic_clk_calc_div(struct clk_hw *hw,
}
/* Impose hardware constraints */
div = min_t(unsigned, div, 1 << clk_info->div.bits);
div = max_t(unsigned, div, 1);
div = clamp_t(unsigned int, div, clk_info->div.div,
clk_info->div.div << clk_info->div.bits);
/*
* If the divider value itself must be divided before being written to
* the divider register, we must ensure we don't have any bits set that
* would be lost as a result of doing so.
*/
div /= clk_info->div.div;
div = DIV_ROUND_UP(div, clk_info->div.div);
div *= clk_info->div.div;
return div;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment