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

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
......@@ -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);
pll_val = VT8500_BITS_TO_VAL(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);
pll_val = WM8650_BITS_TO_VAL(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);
pll_val = WM8750_BITS_TO_VAL(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);
pll_val = WM8850_BITS_TO_VAL(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);
round_rate = VT8500_BITS_TO_FREQ(*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);
round_rate = WM8650_BITS_TO_FREQ(*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);
round_rate = WM8750_BITS_TO_FREQ(*prate, 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);
round_rate = WM8850_BITS_TO_FREQ(*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;
}
......
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