aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);