From: Paul Cercueil paul@crapouillou.net
stable inclusion form stable-v5.10.82 commit 03bc8ea0ae957e5b7c3dc94816ed6a5caed52646 bugzilla: 185877 https://gitee.com/openeuler/kernel/issues/I4QU6V
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
[ Upstream commit ed84ef1cd7eddf933d4ffce2caa8161d6f947245 ]
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: 4afe2d1a6ed5 ("clk: ingenic: Allow divider value to be divided") Co-developed-by: Artur Rojek contact@artur-rojek.eu Signed-off-by: Artur Rojek contact@artur-rojek.eu Signed-off-by: Paul Cercueil paul@crapouillou.net Link: https://lore.kernel.org/r/20211001172033.122329-1-paul@crapouillou.net Signed-off-by: Stephen Boyd sboyd@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Chen Jun chenjun102@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/clk/ingenic/cgu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c index c8e9cb6c8e39..2b9bb7d55efc 100644 --- a/drivers/clk/ingenic/cgu.c +++ b/drivers/clk/ingenic/cgu.c @@ -425,15 +425,15 @@ ingenic_clk_calc_div(const struct ingenic_cgu_clk_info *clk_info, }
/* 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;