Modify OMAP PLL rate rounding function to round to the exact rate requested

or the next one below it.  This is intended to resolve some DSS problems.
 
 Basic build, boot, and PM test results are available here:
 
 http://www.pwsan.com/omap/testlogs/clock-b-v3.17/20140725061121/
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJT0lK2AAoJEMePsQ0LvSpLUkEQAKpqkh9UYUixXBaeIQnoFcwH
 uW7/cjYPfTY1ogFgMaFJN14cTmat+Xm97Es8hgEIZYyY5OmRNYqcdBXmfQ5Mls8b
 mtxZu9FAPRfFZkfNst7Y1i969GoyTnOyOG3Ea7PlAzQacnjq7HVACLMKIDEOmGhG
 rzDSj1eFaJWTUdY0yGFQAkwd5LvuNIfuXIwQ9DlHm84/tpKEpi32tmRJBPzLaKz1
 Cu88ZiW1pfMR8BRw247wlJ9v2DJmhnrluhKhM6UFGJR6X31kw/s7wqbTi3+yNXqL
 BToTQs1xVwMnnOAntM7sc39UFg3pgZBqWFemQCHtshGqhgo1MJ8nznIvxyPXAcAp
 cLHMxMdBbs4Ds9vbJKTNVzntoam8PGO8mff0wMePqAPAuE/m/JMxBTPc5vZijI7f
 SmjirUEhK47BEtUBRQNTVX/B1ABvmodaU93ous8gbKagjH358DkrIlCwP2rerJWc
 eg9UxYNNRvK0iUsjl19vfr/qfT7vXnkp3YGfkJlR22KBJOQd1+M3X/NIBrU0fV2e
 00H9O2YdScBGzFMLvbnT0LkH4/VgilR3667Kx6LkK/r62LrG1z296kTpnfwLtivH
 1jfmhMyt1MfgOylPx/5Dh39xKqUqKeUVoBCFUr/45y3nFbEFZkILiNEuPzRNFUPK
 AgSz5lyNGFfd4mb144hM
 =fXvM
 -----END PGP SIGNATURE-----

Merge tag 'for-v3.17/omap-clock-b' of git://git.kernel.org/pub/scm/linux/kernel/git/pjw/omap-pending into omap-for-v3.17/soc

Modify OMAP PLL rate rounding function to round to the exact rate requested
or the next one below it.  This is intended to resolve some DSS problems.

Basic build, boot, and PM test results are available here:

http://www.pwsan.com/omap/testlogs/clock-b-v3.17/20140725061121/
This commit is contained in:
Tony Lindgren 2014-07-29 04:03:30 -07:00
commit d40dbcd57b
2 changed files with 32 additions and 9 deletions

View File

@ -285,10 +285,13 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
{
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
int m, n, r, scaled_max_m;
int min_delta_m = INT_MAX, min_delta_n = INT_MAX;
unsigned long scaled_rt_rp;
unsigned long new_rate = 0;
struct dpll_data *dd;
unsigned long ref_rate;
long delta;
long prev_min_delta = LONG_MAX;
const char *clk_name;
if (!clk || !clk->dpll_data)
@ -334,23 +337,34 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
if (r == DPLL_MULT_UNDERFLOW)
continue;
/* skip rates above our target rate */
delta = target_rate - new_rate;
if (delta < 0)
continue;
if (delta < prev_min_delta) {
prev_min_delta = delta;
min_delta_m = m;
min_delta_n = n;
}
pr_debug("clock: %s: m = %d: n = %d: new_rate = %lu\n",
clk_name, m, n, new_rate);
if (target_rate == new_rate) {
dd->last_rounded_m = m;
dd->last_rounded_n = n;
dd->last_rounded_rate = target_rate;
if (delta == 0)
break;
}
}
if (target_rate != new_rate) {
if (prev_min_delta == LONG_MAX) {
pr_debug("clock: %s: cannot round to rate %lu\n",
clk_name, target_rate);
return ~0;
}
return target_rate;
dd->last_rounded_m = min_delta_m;
dd->last_rounded_n = min_delta_n;
dd->last_rounded_rate = target_rate - prev_min_delta;
return dd->last_rounded_rate;
}

View File

@ -475,6 +475,7 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
{
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
struct clk *new_parent = NULL;
unsigned long rrate;
u16 freqsel = 0;
struct dpll_data *dd;
int ret;
@ -502,8 +503,16 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
__clk_prepare(dd->clk_ref);
clk_enable(dd->clk_ref);
if (dd->last_rounded_rate != rate)
rate = __clk_round_rate(hw->clk, rate);
/* XXX this check is probably pointless in the CCF context */
if (dd->last_rounded_rate != rate) {
rrate = __clk_round_rate(hw->clk, rate);
if (rrate != rate) {
pr_warn("%s: %s: final rate %lu does not match desired rate %lu\n",
__func__, __clk_get_name(hw->clk),
rrate, rate);
rate = rrate;
}
}
if (dd->last_rounded_rate == 0)
return -EINVAL;