Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+79 -51
+77 -51
drivers/mfd/twl6040-core.c
··· 282 282 /* Default PLL configuration after power up */ 283 283 twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL; 284 284 twl6040->sysclk = 19200000; 285 + twl6040->mclk = 32768; 285 286 } else { 286 287 /* already powered-down */ 287 288 if (!twl6040->power_count) { ··· 306 305 twl6040_power_down(twl6040); 307 306 } 308 307 twl6040->sysclk = 0; 308 + twl6040->mclk = 0; 309 309 } 310 310 311 311 out: ··· 326 324 hppllctl = twl6040_reg_read(twl6040, TWL6040_REG_HPPLLCTL); 327 325 lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL); 328 326 327 + /* Force full reconfiguration when switching between PLL */ 328 + if (pll_id != twl6040->pll) { 329 + twl6040->sysclk = 0; 330 + twl6040->mclk = 0; 331 + } 332 + 329 333 switch (pll_id) { 330 334 case TWL6040_SYSCLK_SEL_LPPLL: 331 335 /* low-power PLL divider */ 332 - switch (freq_out) { 333 - case 17640000: 334 - lppllctl |= TWL6040_LPLLFIN; 335 - break; 336 - case 19200000: 337 - lppllctl &= ~TWL6040_LPLLFIN; 338 - break; 339 - default: 340 - dev_err(twl6040->dev, 341 - "freq_out %d not supported\n", freq_out); 342 - ret = -EINVAL; 343 - goto pll_out; 336 + /* Change the sysclk configuration only if it has been canged */ 337 + if (twl6040->sysclk != freq_out) { 338 + switch (freq_out) { 339 + case 17640000: 340 + lppllctl |= TWL6040_LPLLFIN; 341 + break; 342 + case 19200000: 343 + lppllctl &= ~TWL6040_LPLLFIN; 344 + break; 345 + default: 346 + dev_err(twl6040->dev, 347 + "freq_out %d not supported\n", 348 + freq_out); 349 + ret = -EINVAL; 350 + goto pll_out; 351 + } 352 + twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, 353 + lppllctl); 344 354 } 345 - twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); 355 + 356 + /* The PLL in use has not been change, we can exit */ 357 + if (twl6040->pll == pll_id) 358 + break; 346 359 347 360 switch (freq_in) { 348 361 case 32768: ··· 388 371 goto pll_out; 389 372 } 390 373 391 - hppllctl &= ~TWL6040_MCLK_MSK; 374 + if (twl6040->mclk != freq_in) { 375 + hppllctl &= ~TWL6040_MCLK_MSK; 392 376 393 - switch (freq_in) { 394 - case 12000000: 395 - /* PLL enabled, active mode */ 396 - hppllctl |= TWL6040_MCLK_12000KHZ | 397 - TWL6040_HPLLENA; 398 - break; 399 - case 19200000: 377 + switch (freq_in) { 378 + case 12000000: 379 + /* PLL enabled, active mode */ 380 + hppllctl |= TWL6040_MCLK_12000KHZ | 381 + TWL6040_HPLLENA; 382 + break; 383 + case 19200000: 384 + /* 385 + * PLL disabled 386 + * (enable PLL if MCLK jitter quality 387 + * doesn't meet specification) 388 + */ 389 + hppllctl |= TWL6040_MCLK_19200KHZ; 390 + break; 391 + case 26000000: 392 + /* PLL enabled, active mode */ 393 + hppllctl |= TWL6040_MCLK_26000KHZ | 394 + TWL6040_HPLLENA; 395 + break; 396 + case 38400000: 397 + /* PLL enabled, active mode */ 398 + hppllctl |= TWL6040_MCLK_38400KHZ | 399 + TWL6040_HPLLENA; 400 + break; 401 + default: 402 + dev_err(twl6040->dev, 403 + "freq_in %d not supported\n", freq_in); 404 + ret = -EINVAL; 405 + goto pll_out; 406 + } 407 + 400 408 /* 401 - * PLL disabled 402 - * (enable PLL if MCLK jitter quality 403 - * doesn't meet specification) 409 + * enable clock slicer to ensure input waveform is 410 + * square 404 411 */ 405 - hppllctl |= TWL6040_MCLK_19200KHZ; 406 - break; 407 - case 26000000: 408 - /* PLL enabled, active mode */ 409 - hppllctl |= TWL6040_MCLK_26000KHZ | 410 - TWL6040_HPLLENA; 411 - break; 412 - case 38400000: 413 - /* PLL enabled, active mode */ 414 - hppllctl |= TWL6040_MCLK_38400KHZ | 415 - TWL6040_HPLLENA; 416 - break; 417 - default: 418 - dev_err(twl6040->dev, 419 - "freq_in %d not supported\n", freq_in); 420 - ret = -EINVAL; 421 - goto pll_out; 412 + hppllctl |= TWL6040_HPLLSQRENA; 413 + 414 + twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL, 415 + hppllctl); 416 + usleep_range(500, 700); 417 + lppllctl |= TWL6040_HPLLSEL; 418 + twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, 419 + lppllctl); 420 + lppllctl &= ~TWL6040_LPLLENA; 421 + twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, 422 + lppllctl); 422 423 } 423 - 424 - /* enable clock slicer to ensure input waveform is square */ 425 - hppllctl |= TWL6040_HPLLSQRENA; 426 - 427 - twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL, hppllctl); 428 - usleep_range(500, 700); 429 - lppllctl |= TWL6040_HPLLSEL; 430 - twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); 431 - lppllctl &= ~TWL6040_LPLLENA; 432 - twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); 433 424 break; 434 425 default: 435 426 dev_err(twl6040->dev, "unknown pll id %d\n", pll_id); ··· 446 421 } 447 422 448 423 twl6040->sysclk = freq_out; 424 + twl6040->mclk = freq_in; 449 425 twl6040->pll = pll_id; 450 426 451 427 pll_out:
+2
include/linux/mfd/twl6040.h
··· 187 187 int rev; 188 188 u8 vibra_ctrl_cache[2]; 189 189 190 + /* PLL configuration */ 190 191 int pll; 191 192 unsigned int sysclk; 193 + unsigned int mclk; 192 194 193 195 unsigned int irq; 194 196 unsigned int irq_base;