Commit abaaf3e1 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 71ea4efe 2bd05db7
...@@ -282,6 +282,7 @@ int twl6040_power(struct twl6040 *twl6040, int on) ...@@ -282,6 +282,7 @@ int twl6040_power(struct twl6040 *twl6040, int on)
/* Default PLL configuration after power up */ /* Default PLL configuration after power up */
twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL; twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL;
twl6040->sysclk = 19200000; twl6040->sysclk = 19200000;
twl6040->mclk = 32768;
} else { } else {
/* already powered-down */ /* already powered-down */
if (!twl6040->power_count) { if (!twl6040->power_count) {
...@@ -305,6 +306,7 @@ int twl6040_power(struct twl6040 *twl6040, int on) ...@@ -305,6 +306,7 @@ int twl6040_power(struct twl6040 *twl6040, int on)
twl6040_power_down(twl6040); twl6040_power_down(twl6040);
} }
twl6040->sysclk = 0; twl6040->sysclk = 0;
twl6040->mclk = 0;
} }
out: out:
...@@ -324,23 +326,38 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, ...@@ -324,23 +326,38 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
hppllctl = twl6040_reg_read(twl6040, TWL6040_REG_HPPLLCTL); hppllctl = twl6040_reg_read(twl6040, TWL6040_REG_HPPLLCTL);
lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL); lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL);
/* Force full reconfiguration when switching between PLL */
if (pll_id != twl6040->pll) {
twl6040->sysclk = 0;
twl6040->mclk = 0;
}
switch (pll_id) { switch (pll_id) {
case TWL6040_SYSCLK_SEL_LPPLL: case TWL6040_SYSCLK_SEL_LPPLL:
/* low-power PLL divider */ /* low-power PLL divider */
switch (freq_out) { /* Change the sysclk configuration only if it has been canged */
case 17640000: if (twl6040->sysclk != freq_out) {
lppllctl |= TWL6040_LPLLFIN; switch (freq_out) {
break; case 17640000:
case 19200000: lppllctl |= TWL6040_LPLLFIN;
lppllctl &= ~TWL6040_LPLLFIN; break;
break; case 19200000:
default: lppllctl &= ~TWL6040_LPLLFIN;
dev_err(twl6040->dev, break;
"freq_out %d not supported\n", freq_out); default:
ret = -EINVAL; dev_err(twl6040->dev,
goto pll_out; "freq_out %d not supported\n",
freq_out);
ret = -EINVAL;
goto pll_out;
}
twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
lppllctl);
} }
twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
/* The PLL in use has not been change, we can exit */
if (twl6040->pll == pll_id)
break;
switch (freq_in) { switch (freq_in) {
case 32768: case 32768:
...@@ -371,48 +388,56 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, ...@@ -371,48 +388,56 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
goto pll_out; goto pll_out;
} }
hppllctl &= ~TWL6040_MCLK_MSK; if (twl6040->mclk != freq_in) {
hppllctl &= ~TWL6040_MCLK_MSK;
switch (freq_in) {
case 12000000:
/* PLL enabled, active mode */
hppllctl |= TWL6040_MCLK_12000KHZ |
TWL6040_HPLLENA;
break;
case 19200000:
/*
* PLL disabled
* (enable PLL if MCLK jitter quality
* doesn't meet specification)
*/
hppllctl |= TWL6040_MCLK_19200KHZ;
break;
case 26000000:
/* PLL enabled, active mode */
hppllctl |= TWL6040_MCLK_26000KHZ |
TWL6040_HPLLENA;
break;
case 38400000:
/* PLL enabled, active mode */
hppllctl |= TWL6040_MCLK_38400KHZ |
TWL6040_HPLLENA;
break;
default:
dev_err(twl6040->dev,
"freq_in %d not supported\n", freq_in);
ret = -EINVAL;
goto pll_out;
}
switch (freq_in) {
case 12000000:
/* PLL enabled, active mode */
hppllctl |= TWL6040_MCLK_12000KHZ |
TWL6040_HPLLENA;
break;
case 19200000:
/* /*
* PLL disabled * enable clock slicer to ensure input waveform is
* (enable PLL if MCLK jitter quality * square
* doesn't meet specification)
*/ */
hppllctl |= TWL6040_MCLK_19200KHZ; hppllctl |= TWL6040_HPLLSQRENA;
break;
case 26000000:
/* PLL enabled, active mode */
hppllctl |= TWL6040_MCLK_26000KHZ |
TWL6040_HPLLENA;
break;
case 38400000:
/* PLL enabled, active mode */
hppllctl |= TWL6040_MCLK_38400KHZ |
TWL6040_HPLLENA;
break;
default:
dev_err(twl6040->dev,
"freq_in %d not supported\n", freq_in);
ret = -EINVAL;
goto pll_out;
}
/* enable clock slicer to ensure input waveform is square */ twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL,
hppllctl |= TWL6040_HPLLSQRENA; hppllctl);
usleep_range(500, 700);
twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL, hppllctl); lppllctl |= TWL6040_HPLLSEL;
usleep_range(500, 700); twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
lppllctl |= TWL6040_HPLLSEL; lppllctl);
twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); lppllctl &= ~TWL6040_LPLLENA;
lppllctl &= ~TWL6040_LPLLENA; twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); lppllctl);
}
break; break;
default: default:
dev_err(twl6040->dev, "unknown pll id %d\n", pll_id); 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,6 +446,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
} }
twl6040->sysclk = freq_out; twl6040->sysclk = freq_out;
twl6040->mclk = freq_in;
twl6040->pll = pll_id; twl6040->pll = pll_id;
pll_out: pll_out:
......
...@@ -187,8 +187,10 @@ struct twl6040 { ...@@ -187,8 +187,10 @@ struct twl6040 {
int rev; int rev;
u8 vibra_ctrl_cache[2]; u8 vibra_ctrl_cache[2];
/* PLL configuration */
int pll; int pll;
unsigned int sysclk; unsigned int sysclk;
unsigned int mclk;
unsigned int irq; unsigned int irq;
unsigned int irq_base; unsigned int irq_base;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment