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

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.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent b39eee27
Loading
Loading
Loading
Loading
+11 −5
Original line number Diff line number Diff line
@@ -321,7 +321,7 @@ static int clk_aic32x4_div_set_rate(struct clk_hw *hw, unsigned long rate,
	u8 divisor;

	divisor = DIV_ROUND_UP(parent_rate, rate);
	if (divisor > 128)
	if (divisor > AIC32X4_DIV_MAX)
		return -EINVAL;

	return regmap_update_bits(div->regmap, div->reg,
@@ -334,7 +334,7 @@ static int clk_aic32x4_div_determine_rate(struct clk_hw *hw,
	unsigned long divisor;

	divisor = DIV_ROUND_UP(req->best_parent_rate, req->rate);
	if (divisor > 128)
	if (divisor > AIC32X4_DIV_MAX)
		return -EINVAL;

	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,
						unsigned long parent_rate)
{
	struct clk_aic32x4 *div = to_clk_aic32x4(hw);

	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 = {
+3 −2
Original line number Diff line number Diff line
@@ -225,6 +225,7 @@ int aic32x4_register_clocks(struct device *dev, const char *mclk_name);
/* Common mask and enable for all of the dividers */
#define AIC32X4_DIVEN			BIT(7)
#define AIC32X4_DIV_MASK		GENMASK(6, 0)
#define AIC32X4_DIV_MAX			128

/* Clock Limits */
#define AIC32X4_MAX_DOSR_FREQ		6200000