aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorPeter Ujfalusi <peter.ujfalusi@ti.com>2012-01-14 14:58:44 -0500
committerSamuel Ortiz <sameo@linux.intel.com>2012-02-03 13:03:50 -0500
commit2bd05db718cf452fe235c7c08083b2e60f787f3a (patch)
treeb733153a25641ff8672fd608d92f65affe834dfd /drivers/mfd
parentf8447d6c213273b444c81eaa2449f55510229d4f (diff)
mfd: Avoid twl6040-codec PLL reconfiguration when not needed
Do not reconfigure the PLL in case it has been configured already with the requested parameters. In case of different PLL configuration do only the needed changes. This can save considerable amount of time since we can avoid the defined protocol (with delays) for the PLL configuration. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/twl6040-core.c125
1 files changed, 74 insertions, 51 deletions
diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c
index c2088f4c4547..b2d8e512d3cb 100644
--- a/drivers/mfd/twl6040-core.c
+++ b/drivers/mfd/twl6040-core.c
@@ -326,23 +326,38 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
326 hppllctl = twl6040_reg_read(twl6040, TWL6040_REG_HPPLLCTL); 326 hppllctl = twl6040_reg_read(twl6040, TWL6040_REG_HPPLLCTL);
327 lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL); 327 lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL);
328 328
329 /* Force full reconfiguration when switching between PLL */
330 if (pll_id != twl6040->pll) {
331 twl6040->sysclk = 0;
332 twl6040->mclk = 0;
333 }
334
329 switch (pll_id) { 335 switch (pll_id) {
330 case TWL6040_SYSCLK_SEL_LPPLL: 336 case TWL6040_SYSCLK_SEL_LPPLL:
331 /* low-power PLL divider */ 337 /* low-power PLL divider */
332 switch (freq_out) { 338 /* Change the sysclk configuration only if it has been canged */
333 case 17640000: 339 if (twl6040->sysclk != freq_out) {
334 lppllctl |= TWL6040_LPLLFIN; 340 switch (freq_out) {
335 break; 341 case 17640000:
336 case 19200000: 342 lppllctl |= TWL6040_LPLLFIN;
337 lppllctl &= ~TWL6040_LPLLFIN; 343 break;
338 break; 344 case 19200000:
339 default: 345 lppllctl &= ~TWL6040_LPLLFIN;
340 dev_err(twl6040->dev, 346 break;
341 "freq_out %d not supported\n", freq_out); 347 default:
342 ret = -EINVAL; 348 dev_err(twl6040->dev,
343 goto pll_out; 349 "freq_out %d not supported\n",
350 freq_out);
351 ret = -EINVAL;
352 goto pll_out;
353 }
354 twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
355 lppllctl);
344 } 356 }
345 twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); 357
358 /* The PLL in use has not been change, we can exit */
359 if (twl6040->pll == pll_id)
360 break;
346 361
347 switch (freq_in) { 362 switch (freq_in) {
348 case 32768: 363 case 32768:
@@ -373,48 +388,56 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
373 goto pll_out; 388 goto pll_out;
374 } 389 }
375 390
376 hppllctl &= ~TWL6040_MCLK_MSK; 391 if (twl6040->mclk != freq_in) {
392 hppllctl &= ~TWL6040_MCLK_MSK;
393
394 switch (freq_in) {
395 case 12000000:
396 /* PLL enabled, active mode */
397 hppllctl |= TWL6040_MCLK_12000KHZ |
398 TWL6040_HPLLENA;
399 break;
400 case 19200000:
401 /*
402 * PLL disabled
403 * (enable PLL if MCLK jitter quality
404 * doesn't meet specification)
405 */
406 hppllctl |= TWL6040_MCLK_19200KHZ;
407 break;
408 case 26000000:
409 /* PLL enabled, active mode */
410 hppllctl |= TWL6040_MCLK_26000KHZ |
411 TWL6040_HPLLENA;
412 break;
413 case 38400000:
414 /* PLL enabled, active mode */
415 hppllctl |= TWL6040_MCLK_38400KHZ |
416 TWL6040_HPLLENA;
417 break;
418 default:
419 dev_err(twl6040->dev,
420 "freq_in %d not supported\n", freq_in);
421 ret = -EINVAL;
422 goto pll_out;
423 }
377 424
378 switch (freq_in) {
379 case 12000000:
380 /* PLL enabled, active mode */
381 hppllctl |= TWL6040_MCLK_12000KHZ |
382 TWL6040_HPLLENA;
383 break;
384 case 19200000:
385 /* 425 /*
386 * PLL disabled 426 * enable clock slicer to ensure input waveform is
387 * (enable PLL if MCLK jitter quality 427 * square
388 * doesn't meet specification)
389 */ 428 */
390 hppllctl |= TWL6040_MCLK_19200KHZ; 429 hppllctl |= TWL6040_HPLLSQRENA;
391 break;
392 case 26000000:
393 /* PLL enabled, active mode */
394 hppllctl |= TWL6040_MCLK_26000KHZ |
395 TWL6040_HPLLENA;
396 break;
397 case 38400000:
398 /* PLL enabled, active mode */
399 hppllctl |= TWL6040_MCLK_38400KHZ |
400 TWL6040_HPLLENA;
401 break;
402 default:
403 dev_err(twl6040->dev,
404 "freq_in %d not supported\n", freq_in);
405 ret = -EINVAL;
406 goto pll_out;
407 }
408 430
409 /* enable clock slicer to ensure input waveform is square */ 431 twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL,
410 hppllctl |= TWL6040_HPLLSQRENA; 432 hppllctl);
411 433 usleep_range(500, 700);
412 twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL, hppllctl); 434 lppllctl |= TWL6040_HPLLSEL;
413 usleep_range(500, 700); 435 twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
414 lppllctl |= TWL6040_HPLLSEL; 436 lppllctl);
415 twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); 437 lppllctl &= ~TWL6040_LPLLENA;
416 lppllctl &= ~TWL6040_LPLLENA; 438 twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
417 twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); 439 lppllctl);
440 }
418 break; 441 break;
419 default: 442 default:
420 dev_err(twl6040->dev, "unknown pll id %d\n", pll_id); 443 dev_err(twl6040->dev, "unknown pll id %d\n", pll_id);