|
@@ -323,8 +323,7 @@ int twl6040_power(struct twl6040 *twl6040, int on)
|
|
|
|
|
|
/* Default PLL configuration after power up */
|
|
|
twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL;
|
|
|
- twl6040->sysclk = 19200000;
|
|
|
- twl6040->mclk = 32768;
|
|
|
+ twl6040->sysclk_rate = 19200000;
|
|
|
} else {
|
|
|
/* already powered-down */
|
|
|
if (!twl6040->power_count) {
|
|
@@ -352,8 +351,12 @@ int twl6040_power(struct twl6040 *twl6040, int on)
|
|
|
regcache_cache_only(twl6040->regmap, true);
|
|
|
regcache_mark_dirty(twl6040->regmap);
|
|
|
|
|
|
- twl6040->sysclk = 0;
|
|
|
- twl6040->mclk = 0;
|
|
|
+ twl6040->sysclk_rate = 0;
|
|
|
+
|
|
|
+ if (twl6040->pll == TWL6040_SYSCLK_SEL_HPPLL) {
|
|
|
+ clk_disable_unprepare(twl6040->mclk);
|
|
|
+ twl6040->mclk_rate = 0;
|
|
|
+ }
|
|
|
|
|
|
clk_disable_unprepare(twl6040->clk32k);
|
|
|
}
|
|
@@ -377,15 +380,15 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
|
|
|
|
|
|
/* Force full reconfiguration when switching between PLL */
|
|
|
if (pll_id != twl6040->pll) {
|
|
|
- twl6040->sysclk = 0;
|
|
|
- twl6040->mclk = 0;
|
|
|
+ twl6040->sysclk_rate = 0;
|
|
|
+ twl6040->mclk_rate = 0;
|
|
|
}
|
|
|
|
|
|
switch (pll_id) {
|
|
|
case TWL6040_SYSCLK_SEL_LPPLL:
|
|
|
/* low-power PLL divider */
|
|
|
/* Change the sysclk configuration only if it has been canged */
|
|
|
- if (twl6040->sysclk != freq_out) {
|
|
|
+ if (twl6040->sysclk_rate != freq_out) {
|
|
|
switch (freq_out) {
|
|
|
case 17640000:
|
|
|
lppllctl |= TWL6040_LPLLFIN;
|
|
@@ -427,6 +430,8 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
|
|
|
ret = -EINVAL;
|
|
|
goto pll_out;
|
|
|
}
|
|
|
+
|
|
|
+ clk_disable_unprepare(twl6040->mclk);
|
|
|
break;
|
|
|
case TWL6040_SYSCLK_SEL_HPPLL:
|
|
|
/* high-performance PLL can provide only 19.2 MHz */
|
|
@@ -437,7 +442,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
|
|
|
goto pll_out;
|
|
|
}
|
|
|
|
|
|
- if (twl6040->mclk != freq_in) {
|
|
|
+ if (twl6040->mclk_rate != freq_in) {
|
|
|
hppllctl &= ~TWL6040_MCLK_MSK;
|
|
|
|
|
|
switch (freq_in) {
|
|
@@ -468,6 +473,9 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
|
|
|
goto pll_out;
|
|
|
}
|
|
|
|
|
|
+ /* When switching to HPPLL, enable the mclk first */
|
|
|
+ if (pll_id != twl6040->pll)
|
|
|
+ clk_prepare_enable(twl6040->mclk);
|
|
|
/*
|
|
|
* enable clock slicer to ensure input waveform is
|
|
|
* square
|
|
@@ -483,6 +491,8 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
|
|
|
lppllctl &= ~TWL6040_LPLLENA;
|
|
|
twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
|
|
|
lppllctl);
|
|
|
+
|
|
|
+ twl6040->mclk_rate = freq_in;
|
|
|
}
|
|
|
break;
|
|
|
default:
|
|
@@ -491,8 +501,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
|
|
|
goto pll_out;
|
|
|
}
|
|
|
|
|
|
- twl6040->sysclk = freq_out;
|
|
|
- twl6040->mclk = freq_in;
|
|
|
+ twl6040->sysclk_rate = freq_out;
|
|
|
twl6040->pll = pll_id;
|
|
|
|
|
|
pll_out:
|
|
@@ -512,7 +521,7 @@ EXPORT_SYMBOL(twl6040_get_pll);
|
|
|
|
|
|
unsigned int twl6040_get_sysclk(struct twl6040 *twl6040)
|
|
|
{
|
|
|
- return twl6040->sysclk;
|
|
|
+ return twl6040->sysclk_rate;
|
|
|
}
|
|
|
EXPORT_SYMBOL(twl6040_get_sysclk);
|
|
|
|
|
@@ -655,10 +664,18 @@ static int twl6040_probe(struct i2c_client *client,
|
|
|
if (IS_ERR(twl6040->clk32k)) {
|
|
|
if (PTR_ERR(twl6040->clk32k) == -EPROBE_DEFER)
|
|
|
return -EPROBE_DEFER;
|
|
|
- dev_info(&client->dev, "clk32k is not handled\n");
|
|
|
+ dev_dbg(&client->dev, "clk32k is not handled\n");
|
|
|
twl6040->clk32k = NULL;
|
|
|
}
|
|
|
|
|
|
+ twl6040->mclk = devm_clk_get(&client->dev, "mclk");
|
|
|
+ if (IS_ERR(twl6040->mclk)) {
|
|
|
+ if (PTR_ERR(twl6040->mclk) == -EPROBE_DEFER)
|
|
|
+ return -EPROBE_DEFER;
|
|
|
+ dev_dbg(&client->dev, "mclk is not handled\n");
|
|
|
+ twl6040->mclk = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
twl6040->supplies[0].supply = "vio";
|
|
|
twl6040->supplies[1].supply = "v2v1";
|
|
|
ret = devm_regulator_bulk_get(&client->dev, TWL6040_NUM_SUPPLIES,
|