diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-02-07 17:05:49 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-02-07 17:05:49 -0500 |
| commit | abaaf3e12c74ef39c8ba185c485f63274264cb0f (patch) | |
| tree | 72851a2095cadb38473c1460a31942403daa2e4b | |
| parent | 71ea4efe4fc3319ab577be00d1bbcb76d3ffaf63 (diff) | |
| parent | 2bd05db718cf452fe235c7c08083b2e60f787f3a (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6:
mfd: Avoid twl6040-codec PLL reconfiguration when not needed
mfd: Store twl6040-codec mclk configuration
| -rw-r--r-- | drivers/mfd/twl6040-core.c | 128 | ||||
| -rw-r--r-- | include/linux/mfd/twl6040.h | 2 |
2 files changed, 79 insertions, 51 deletions
diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c index dda86293dc9f..b2d8e512d3cb 100644 --- a/drivers/mfd/twl6040-core.c +++ b/drivers/mfd/twl6040-core.c | |||
| @@ -282,6 +282,7 @@ int twl6040_power(struct twl6040 *twl6040, int on) | |||
| 282 | /* Default PLL configuration after power up */ | 282 | /* Default PLL configuration after power up */ |
| 283 | twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL; | 283 | twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL; |
| 284 | twl6040->sysclk = 19200000; | 284 | twl6040->sysclk = 19200000; |
| 285 | twl6040->mclk = 32768; | ||
| 285 | } else { | 286 | } else { |
| 286 | /* already powered-down */ | 287 | /* already powered-down */ |
| 287 | if (!twl6040->power_count) { | 288 | if (!twl6040->power_count) { |
| @@ -305,6 +306,7 @@ int twl6040_power(struct twl6040 *twl6040, int on) | |||
| 305 | twl6040_power_down(twl6040); | 306 | twl6040_power_down(twl6040); |
| 306 | } | 307 | } |
| 307 | twl6040->sysclk = 0; | 308 | twl6040->sysclk = 0; |
| 309 | twl6040->mclk = 0; | ||
| 308 | } | 310 | } |
| 309 | 311 | ||
| 310 | out: | 312 | out: |
| @@ -324,23 +326,38 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, | |||
| 324 | hppllctl = twl6040_reg_read(twl6040, TWL6040_REG_HPPLLCTL); | 326 | hppllctl = twl6040_reg_read(twl6040, TWL6040_REG_HPPLLCTL); |
| 325 | lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL); | 327 | lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL); |
| 326 | 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 | |||
| 327 | switch (pll_id) { | 335 | switch (pll_id) { |
| 328 | case TWL6040_SYSCLK_SEL_LPPLL: | 336 | case TWL6040_SYSCLK_SEL_LPPLL: |
| 329 | /* low-power PLL divider */ | 337 | /* low-power PLL divider */ |
| 330 | switch (freq_out) { | 338 | /* Change the sysclk configuration only if it has been canged */ |
| 331 | case 17640000: | 339 | if (twl6040->sysclk != freq_out) { |
| 332 | lppllctl |= TWL6040_LPLLFIN; | 340 | switch (freq_out) { |
| 333 | break; | 341 | case 17640000: |
| 334 | case 19200000: | 342 | lppllctl |= TWL6040_LPLLFIN; |
| 335 | lppllctl &= ~TWL6040_LPLLFIN; | 343 | break; |
| 336 | break; | 344 | case 19200000: |
| 337 | default: | 345 | lppllctl &= ~TWL6040_LPLLFIN; |
| 338 | dev_err(twl6040->dev, | 346 | break; |
| 339 | "freq_out %d not supported\n", freq_out); | 347 | default: |
| 340 | ret = -EINVAL; | 348 | dev_err(twl6040->dev, |
| 341 | 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); | ||
| 342 | } | 356 | } |
| 343 | 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; | ||
| 344 | 361 | ||
| 345 | switch (freq_in) { | 362 | switch (freq_in) { |
| 346 | case 32768: | 363 | case 32768: |
| @@ -371,48 +388,56 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, | |||
| 371 | goto pll_out; | 388 | goto pll_out; |
| 372 | } | 389 | } |
| 373 | 390 | ||
| 374 | 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 | } | ||
| 375 | 424 | ||
| 376 | switch (freq_in) { | ||
| 377 | case 12000000: | ||
| 378 | /* PLL enabled, active mode */ | ||
| 379 | hppllctl |= TWL6040_MCLK_12000KHZ | | ||
| 380 | TWL6040_HPLLENA; | ||
| 381 | break; | ||
| 382 | case 19200000: | ||
| 383 | /* | 425 | /* |
| 384 | * PLL disabled | 426 | * enable clock slicer to ensure input waveform is |
| 385 | * (enable PLL if MCLK jitter quality | 427 | * square |
| 386 | * doesn't meet specification) | ||
| 387 | */ | 428 | */ |
| 388 | hppllctl |= TWL6040_MCLK_19200KHZ; | 429 | hppllctl |= TWL6040_HPLLSQRENA; |
| 389 | break; | ||
| 390 | case 26000000: | ||
| 391 | /* PLL enabled, active mode */ | ||
| 392 | hppllctl |= TWL6040_MCLK_26000KHZ | | ||
| 393 | TWL6040_HPLLENA; | ||
| 394 | break; | ||
| 395 | case 38400000: | ||
| 396 | /* PLL enabled, active mode */ | ||
| 397 | hppllctl |= TWL6040_MCLK_38400KHZ | | ||
| 398 | TWL6040_HPLLENA; | ||
| 399 | break; | ||
| 400 | default: | ||
| 401 | dev_err(twl6040->dev, | ||
| 402 | "freq_in %d not supported\n", freq_in); | ||
| 403 | ret = -EINVAL; | ||
| 404 | goto pll_out; | ||
| 405 | } | ||
| 406 | 430 | ||
| 407 | /* enable clock slicer to ensure input waveform is square */ | 431 | twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL, |
| 408 | hppllctl |= TWL6040_HPLLSQRENA; | 432 | hppllctl); |
| 409 | 433 | usleep_range(500, 700); | |
| 410 | twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL, hppllctl); | 434 | lppllctl |= TWL6040_HPLLSEL; |
| 411 | usleep_range(500, 700); | 435 | twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, |
| 412 | lppllctl |= TWL6040_HPLLSEL; | 436 | lppllctl); |
| 413 | twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); | 437 | lppllctl &= ~TWL6040_LPLLENA; |
| 414 | lppllctl &= ~TWL6040_LPLLENA; | 438 | twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, |
| 415 | twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); | 439 | lppllctl); |
| 440 | } | ||
| 416 | break; | 441 | break; |
| 417 | default: | 442 | default: |
| 418 | dev_err(twl6040->dev, "unknown pll id %d\n", pll_id); | 443 | dev_err(twl6040->dev, "unknown pll id %d\n", pll_id); |
| @@ -421,6 +446,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, | |||
| 421 | } | 446 | } |
| 422 | 447 | ||
| 423 | twl6040->sysclk = freq_out; | 448 | twl6040->sysclk = freq_out; |
| 449 | twl6040->mclk = freq_in; | ||
| 424 | twl6040->pll = pll_id; | 450 | twl6040->pll = pll_id; |
| 425 | 451 | ||
| 426 | pll_out: | 452 | pll_out: |
diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h index 2463c2619596..9bc9ac651dad 100644 --- a/include/linux/mfd/twl6040.h +++ b/include/linux/mfd/twl6040.h | |||
| @@ -187,8 +187,10 @@ struct twl6040 { | |||
| 187 | int rev; | 187 | int rev; |
| 188 | u8 vibra_ctrl_cache[2]; | 188 | u8 vibra_ctrl_cache[2]; |
| 189 | 189 | ||
| 190 | /* PLL configuration */ | ||
| 190 | int pll; | 191 | int pll; |
| 191 | unsigned int sysclk; | 192 | unsigned int sysclk; |
| 193 | unsigned int mclk; | ||
| 192 | 194 | ||
| 193 | unsigned int irq; | 195 | unsigned int irq; |
| 194 | unsigned int irq_base; | 196 | unsigned int irq_base; |
