Commit 11e756cc authored by Guiting Shen's avatar Guiting Shen Committed by Mark Brown

ASoC: tlv320aic32x4: Fix the divide by zero

The value of register(NDAC,MDAC,NADC,MADC,BCLKN) maybe zero lead to
divide by zero in clk_aic32x4_div_recalc_rate().And the rate should be
divide by 128 if the value was zero in this function according to the
datasheet.

Add the macro AIC32X4_DIV_MAX to present the 128 and return 0 if failing
to read the value of register.
Signed-off-by: default avatarGuiting Shen <aarongt.shen@gmail.com>
Link: https://lore.kernel.org/r/20230813125520.11067-1-aarongt.shen@gmail.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent b39eee27
...@@ -321,7 +321,7 @@ static int clk_aic32x4_div_set_rate(struct clk_hw *hw, unsigned long rate, ...@@ -321,7 +321,7 @@ static int clk_aic32x4_div_set_rate(struct clk_hw *hw, unsigned long rate,
u8 divisor; u8 divisor;
divisor = DIV_ROUND_UP(parent_rate, rate); divisor = DIV_ROUND_UP(parent_rate, rate);
if (divisor > 128) if (divisor > AIC32X4_DIV_MAX)
return -EINVAL; return -EINVAL;
return regmap_update_bits(div->regmap, div->reg, return regmap_update_bits(div->regmap, div->reg,
...@@ -334,7 +334,7 @@ static int clk_aic32x4_div_determine_rate(struct clk_hw *hw, ...@@ -334,7 +334,7 @@ static int clk_aic32x4_div_determine_rate(struct clk_hw *hw,
unsigned long divisor; unsigned long divisor;
divisor = DIV_ROUND_UP(req->best_parent_rate, req->rate); divisor = DIV_ROUND_UP(req->best_parent_rate, req->rate);
if (divisor > 128) if (divisor > AIC32X4_DIV_MAX)
return -EINVAL; return -EINVAL;
req->rate = DIV_ROUND_UP(req->best_parent_rate, divisor); req->rate = DIV_ROUND_UP(req->best_parent_rate, divisor);
...@@ -345,12 +345,18 @@ static unsigned long clk_aic32x4_div_recalc_rate(struct clk_hw *hw, ...@@ -345,12 +345,18 @@ static unsigned long clk_aic32x4_div_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate) unsigned long parent_rate)
{ {
struct clk_aic32x4 *div = to_clk_aic32x4(hw); struct clk_aic32x4 *div = to_clk_aic32x4(hw);
unsigned int val; unsigned int val;
int err;
err = regmap_read(div->regmap, div->reg, &val);
if (err)
return 0;
regmap_read(div->regmap, div->reg, &val); val &= AIC32X4_DIV_MASK;
if (!val)
val = AIC32X4_DIV_MAX;
return DIV_ROUND_UP(parent_rate, val & AIC32X4_DIV_MASK); return DIV_ROUND_UP(parent_rate, val);
} }
static const struct clk_ops aic32x4_div_ops = { static const struct clk_ops aic32x4_div_ops = {
......
...@@ -223,8 +223,9 @@ int aic32x4_register_clocks(struct device *dev, const char *mclk_name); ...@@ -223,8 +223,9 @@ int aic32x4_register_clocks(struct device *dev, const char *mclk_name);
#define AIC32X4_REFPOWERUP_120MS 0x07 #define AIC32X4_REFPOWERUP_120MS 0x07
/* Common mask and enable for all of the dividers */ /* Common mask and enable for all of the dividers */
#define AIC32X4_DIVEN BIT(7) #define AIC32X4_DIVEN BIT(7)
#define AIC32X4_DIV_MASK GENMASK(6, 0) #define AIC32X4_DIV_MASK GENMASK(6, 0)
#define AIC32X4_DIV_MAX 128
/* Clock Limits */ /* Clock Limits */
#define AIC32X4_MAX_DOSR_FREQ 6200000 #define AIC32X4_MAX_DOSR_FREQ 6200000
......
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