提交 78f6f406 编写于 作者: R Robert Hancock 提交者: Stephen Boyd

clk: si5341: Avoid divide errors due to bogus register contents

If the Si5341 is being initially programmed and has no stored NVM
configuration, some of the register contents may contain unexpected
values, such as zeros, which could cause divide by zero errors during
driver initialization. Trap errors caused by zero registers or zero clock
rates which could result in divide errors later in the code.

Fixes: 3044a860 ("clk: Add Si5341/Si5340 driver")
Signed-off-by: NRobert Hancock <robert.hancock@calian.com>
Link: https://lore.kernel.org/r/20210325192643.2190069-4-robert.hancock@calian.comSigned-off-by: NStephen Boyd <sboyd@kernel.org>
上级 6e7d2de1
...@@ -624,6 +624,9 @@ static unsigned long si5341_synth_clk_recalc_rate(struct clk_hw *hw, ...@@ -624,6 +624,9 @@ static unsigned long si5341_synth_clk_recalc_rate(struct clk_hw *hw,
SI5341_SYNTH_N_NUM(synth->index), &n_num, &n_den); SI5341_SYNTH_N_NUM(synth->index), &n_num, &n_den);
if (err < 0) if (err < 0)
return err; return err;
/* Check for bogus/uninitialized settings */
if (!n_num || !n_den)
return 0;
/* /*
* n_num and n_den are shifted left as much as possible, so to prevent * n_num and n_den are shifted left as much as possible, so to prevent
...@@ -807,6 +810,9 @@ static long si5341_output_clk_round_rate(struct clk_hw *hw, unsigned long rate, ...@@ -807,6 +810,9 @@ static long si5341_output_clk_round_rate(struct clk_hw *hw, unsigned long rate,
{ {
unsigned long r; unsigned long r;
if (!rate)
return 0;
r = *parent_rate >> 1; r = *parent_rate >> 1;
/* If rate is an even divisor, no changes to parent required */ /* If rate is an even divisor, no changes to parent required */
...@@ -835,11 +841,16 @@ static int si5341_output_clk_set_rate(struct clk_hw *hw, unsigned long rate, ...@@ -835,11 +841,16 @@ static int si5341_output_clk_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate) unsigned long parent_rate)
{ {
struct clk_si5341_output *output = to_clk_si5341_output(hw); struct clk_si5341_output *output = to_clk_si5341_output(hw);
/* Frequency divider is (r_div + 1) * 2 */ u32 r_div;
u32 r_div = (parent_rate / rate) >> 1;
int err; int err;
u8 r[3]; u8 r[3];
if (!rate)
return -EINVAL;
/* Frequency divider is (r_div + 1) * 2 */
r_div = (parent_rate / rate) >> 1;
if (r_div <= 1) if (r_div <= 1)
r_div = 0; r_div = 0;
else if (r_div >= BIT(24)) else if (r_div >= BIT(24))
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册