Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7001ec56 authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Stephen Boyd
Browse files

clk: vt8500: don't return possibly uninitialized data



The clk-vt8500.c driver would previously enter an endless loop
when invalid settings got requested, this was now fixed. However,
the driver will now return uninitialized data for a subset of those
cases instead, as the gcc correctly warns:

clk/clk-vt8500.c: In function 'wm8650_find_pll_bits':
clk/clk-vt8500.c:423:12: error: 'best_div2' may be used uninitialized in this function [-Werror=maybe-uninitialized]
  *divisor2 = best_div2;
            ^
clk/clk-vt8500.c:422:12: error: 'best_div1' may be used uninitialized in this function [-Werror=maybe-uninitialized]
  *divisor1 = best_div1;
            ^
clk/clk-vt8500.c:421:14: error: 'best_mul' may be used uninitialized in this function [-Werror=maybe-uninitialized]
  *multiplier = best_mul;

This reworks the error handling in the driver so we now return
-EINVAL from clk_round_rate() and clk_set_rate() when we get
impossible inputs.

Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
Fixes: 090341b0 ("clk: vt8500: fix sign of possible PLL values")
Signed-off-by: default avatarStephen Boyd <sboyd@codeaurora.org>
parent e8f0e68e
Loading
Loading
Loading
Loading
+65 −26
Original line number Diff line number Diff line
@@ -355,7 +355,7 @@ CLK_OF_DECLARE(vt8500_device, "via,vt8500-device-clock", vtwm_device_clk_init);
#define WM8850_BITS_TO_VAL(m, d1, d2)					\
		((((m / 2) - 1) << 16) | ((d1 - 1) << 8) | d2)

static void vt8500_find_pll_bits(unsigned long rate, unsigned long parent_rate,
static int vt8500_find_pll_bits(unsigned long rate, unsigned long parent_rate,
				u32 *multiplier, u32 *prediv)
{
	unsigned long tclk;
@@ -365,7 +365,7 @@ static void vt8500_find_pll_bits(unsigned long rate, unsigned long parent_rate,
		pr_err("%s: requested rate out of range\n", __func__);
		*multiplier = 0;
		*prediv = 1;
		return;
		return -EINVAL;
	}
	if (rate <= parent_rate * 31)
		/* use the prediv to double the resolution */
@@ -379,9 +379,11 @@ static void vt8500_find_pll_bits(unsigned long rate, unsigned long parent_rate,
	if (tclk != rate)
		pr_warn("%s: requested rate %lu, found rate %lu\n", __func__,
								rate, tclk);

	return 0;
}

static void wm8650_find_pll_bits(unsigned long rate, unsigned long parent_rate,
static int wm8650_find_pll_bits(unsigned long rate, unsigned long parent_rate,
				u32 *multiplier, u32 *divisor1, u32 *divisor2)
{
	u32 mul, div1;
@@ -404,7 +406,7 @@ static void wm8650_find_pll_bits(unsigned long rate, unsigned long parent_rate,
					*multiplier = mul;
					*divisor1 = div1;
					*divisor2 = div2;
					return;
					return 0;
				}

				if (rate_err < best_err) {
@@ -415,12 +417,19 @@ static void wm8650_find_pll_bits(unsigned long rate, unsigned long parent_rate,
				}
			}

	if (best_err == (unsigned long)-1) {
		pr_warn("%s: impossible rate %lu\n", __func__, rate);
		return -EINVAL;
	}

	/* if we got here, it wasn't an exact match */
	pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate,
							rate - best_err);
	*multiplier = best_mul;
	*divisor1 = best_div1;
	*divisor2 = best_div2;

	return 0;
}

static u32 wm8750_get_filter(u32 parent_rate, u32 divisor1)
@@ -450,7 +459,7 @@ static u32 wm8750_get_filter(u32 parent_rate, u32 divisor1)
	return 0;
}

static void wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate,
static int wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate,
				u32 *filter, u32 *multiplier, u32 *divisor1, u32 *divisor2)
{
	u32 mul;
@@ -474,7 +483,7 @@ static void wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate,
					*multiplier = mul;
					*divisor1 = div1;
					*divisor2 = div2;
					return;
					return 0;
				}

				if (rate_err < best_err) {
@@ -485,6 +494,11 @@ static void wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate,
				}
			}

	if (best_err == (unsigned long)-1) {
		pr_warn("%s: impossible rate %lu\n", __func__, rate);
		return -EINVAL;
	}

	/* if we got here, it wasn't an exact match */
	pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate,
							rate - best_err);
@@ -493,9 +507,11 @@ static void wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate,
	*multiplier = best_mul;
	*divisor1 = best_div1;
	*divisor2 = best_div2;

	return 0;
}

static void wm8850_find_pll_bits(unsigned long rate, unsigned long parent_rate,
static int wm8850_find_pll_bits(unsigned long rate, unsigned long parent_rate,
				u32 *multiplier, u32 *divisor1, u32 *divisor2)
{
	u32 mul;
@@ -519,7 +535,7 @@ static void wm8850_find_pll_bits(unsigned long rate, unsigned long parent_rate,
					*multiplier = mul;
					*divisor1 = div1;
					*divisor2 = div2;
					return;
					return 0;
				}

				if (rate_err < best_err) {
@@ -530,6 +546,11 @@ static void wm8850_find_pll_bits(unsigned long rate, unsigned long parent_rate,
				}
			}

	if (best_err == (unsigned long)-1) {
		pr_warn("%s: impossible rate %lu\n", __func__, rate);
		return -EINVAL;
	}

	/* if we got here, it wasn't an exact match */
	pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate,
							rate - best_err);
@@ -537,6 +558,8 @@ static void wm8850_find_pll_bits(unsigned long rate, unsigned long parent_rate,
	*multiplier = best_mul;
	*divisor1 = best_div1;
	*divisor2 = best_div2;

	return 0;
}

static int vtwm_pll_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -546,31 +569,39 @@ static int vtwm_pll_set_rate(struct clk_hw *hw, unsigned long rate,
	u32 filter, mul, div1, div2;
	u32 pll_val;
	unsigned long flags = 0;
	int ret;

	/* sanity check */

	switch (pll->type) {
	case PLL_TYPE_VT8500:
		vt8500_find_pll_bits(rate, parent_rate, &mul, &div1);
		ret = vt8500_find_pll_bits(rate, parent_rate, &mul, &div1);
		if (!ret)
			pll_val = VT8500_BITS_TO_VAL(mul, div1);
		break;
	case PLL_TYPE_WM8650:
		wm8650_find_pll_bits(rate, parent_rate, &mul, &div1, &div2);
		ret = wm8650_find_pll_bits(rate, parent_rate, &mul, &div1, &div2);
		if (!ret)
			pll_val = WM8650_BITS_TO_VAL(mul, div1, div2);
		break;
	case PLL_TYPE_WM8750:
		wm8750_find_pll_bits(rate, parent_rate, &filter, &mul, &div1, &div2);
		ret = wm8750_find_pll_bits(rate, parent_rate, &filter, &mul, &div1, &div2);
		if (!ret)
			pll_val = WM8750_BITS_TO_VAL(filter, mul, div1, div2);
		break;
	case PLL_TYPE_WM8850:
		wm8850_find_pll_bits(rate, parent_rate, &mul, &div1, &div2);
		ret = wm8850_find_pll_bits(rate, parent_rate, &mul, &div1, &div2);
		if (!ret)
			pll_val = WM8850_BITS_TO_VAL(mul, div1, div2);
		break;
	default:
		pr_err("%s: invalid pll type\n", __func__);
		return 0;
		ret = -EINVAL;
	}

	if (ret)
		return ret;

	spin_lock_irqsave(pll->lock, flags);

	vt8500_pmc_wait_busy();
@@ -588,28 +619,36 @@ static long vtwm_pll_round_rate(struct clk_hw *hw, unsigned long rate,
	struct clk_pll *pll = to_clk_pll(hw);
	u32 filter, mul, div1, div2;
	long round_rate;
	int ret;

	switch (pll->type) {
	case PLL_TYPE_VT8500:
		vt8500_find_pll_bits(rate, *prate, &mul, &div1);
		ret = vt8500_find_pll_bits(rate, *prate, &mul, &div1);
		if (!ret)
			round_rate = VT8500_BITS_TO_FREQ(*prate, mul, div1);
		break;
	case PLL_TYPE_WM8650:
		wm8650_find_pll_bits(rate, *prate, &mul, &div1, &div2);
		ret = wm8650_find_pll_bits(rate, *prate, &mul, &div1, &div2);
		if (!ret)
			round_rate = WM8650_BITS_TO_FREQ(*prate, mul, div1, div2);
		break;
	case PLL_TYPE_WM8750:
		wm8750_find_pll_bits(rate, *prate, &filter, &mul, &div1, &div2);
		ret = wm8750_find_pll_bits(rate, *prate, &filter, &mul, &div1, &div2);
		if (!ret)
			round_rate = WM8750_BITS_TO_FREQ(*prate, mul, div1, div2);
		break;
	case PLL_TYPE_WM8850:
		wm8850_find_pll_bits(rate, *prate, &mul, &div1, &div2);
		ret = wm8850_find_pll_bits(rate, *prate, &mul, &div1, &div2);
		if (!ret)
			round_rate = WM8850_BITS_TO_FREQ(*prate, mul, div1, div2);
		break;
	default:
		round_rate = 0;
		ret = -EINVAL;
	}

	if (ret)
		return ret;

	return round_rate;
}