Commit 3863857d authored by Charles Keepax's avatar Charles Keepax Committed by Mark Brown

ASoC: madera: Enable clocks for input pins when used for the FLL

When one of the MCLK pins is used to supply the FLL enable that clock
source.
Signed-off-by: default avatarCharles Keepax <ckeepax@opensource.cirrus.com>
Link: https://lore.kernel.org/r/20191230143517.21005-2-ckeepax@opensource.cirrus.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 1094af11
...@@ -3858,11 +3858,75 @@ static bool madera_set_fll_phase_integrator(struct madera_fll *fll, ...@@ -3858,11 +3858,75 @@ static bool madera_set_fll_phase_integrator(struct madera_fll *fll,
return reg_change; return reg_change;
} }
static int madera_set_fll_clks_reg(struct madera_fll *fll, bool ena,
unsigned int reg, unsigned int mask,
unsigned int shift)
{
struct madera *madera = fll->madera;
unsigned int src;
struct clk *clk;
int ret;
ret = regmap_read(madera->regmap, reg, &src);
if (ret != 0) {
madera_fll_err(fll, "Failed to read current source: %d\n",
ret);
return ret;
}
src = (src & mask) >> shift;
switch (src) {
case MADERA_FLL_SRC_MCLK1:
clk = madera->mclk[MADERA_MCLK1].clk;
break;
case MADERA_FLL_SRC_MCLK2:
clk = madera->mclk[MADERA_MCLK2].clk;
break;
case MADERA_FLL_SRC_MCLK3:
clk = madera->mclk[MADERA_MCLK3].clk;
break;
default:
return 0;
}
if (ena) {
return clk_prepare_enable(clk);
} else {
clk_disable_unprepare(clk);
return 0;
}
}
static inline int madera_set_fll_clks(struct madera_fll *fll, int base, bool ena)
{
return madera_set_fll_clks_reg(fll, ena,
base + MADERA_FLL_CONTROL_6_OFFS,
MADERA_FLL1_REFCLK_SRC_MASK,
MADERA_FLL1_REFCLK_DIV_SHIFT);
}
static inline int madera_set_fllao_clks(struct madera_fll *fll, int base, bool ena)
{
return madera_set_fll_clks_reg(fll, ena,
base + MADERA_FLLAO_CONTROL_6_OFFS,
MADERA_FLL_AO_REFCLK_SRC_MASK,
MADERA_FLL_AO_REFCLK_SRC_SHIFT);
}
static inline int madera_set_fllhj_clks(struct madera_fll *fll, int base, bool ena)
{
return madera_set_fll_clks_reg(fll, ena,
base + MADERA_FLL_CONTROL_1_OFFS,
CS47L92_FLL1_REFCLK_SRC_MASK,
CS47L92_FLL1_REFCLK_SRC_SHIFT);
}
static void madera_disable_fll(struct madera_fll *fll) static void madera_disable_fll(struct madera_fll *fll)
{ {
struct madera *madera = fll->madera; struct madera *madera = fll->madera;
unsigned int sync_base; unsigned int sync_base;
bool change; bool ref_change, sync_change;
switch (madera->type) { switch (madera->type) {
case CS47L35: case CS47L35:
...@@ -3880,18 +3944,23 @@ static void madera_disable_fll(struct madera_fll *fll) ...@@ -3880,18 +3944,23 @@ static void madera_disable_fll(struct madera_fll *fll)
MADERA_FLL1_FREERUN, MADERA_FLL1_FREERUN); MADERA_FLL1_FREERUN, MADERA_FLL1_FREERUN);
regmap_update_bits_check(madera->regmap, regmap_update_bits_check(madera->regmap,
fll->base + MADERA_FLL_CONTROL_1_OFFS, fll->base + MADERA_FLL_CONTROL_1_OFFS,
MADERA_FLL1_ENA, 0, &change); MADERA_FLL1_ENA, 0, &ref_change);
regmap_update_bits(madera->regmap, regmap_update_bits_check(madera->regmap,
sync_base + MADERA_FLL_SYNCHRONISER_1_OFFS, sync_base + MADERA_FLL_SYNCHRONISER_1_OFFS,
MADERA_FLL1_SYNC_ENA, 0); MADERA_FLL1_SYNC_ENA, 0, &sync_change);
regmap_update_bits(madera->regmap, regmap_update_bits(madera->regmap,
fll->base + MADERA_FLL_CONTROL_1_OFFS, fll->base + MADERA_FLL_CONTROL_1_OFFS,
MADERA_FLL1_FREERUN, 0); MADERA_FLL1_FREERUN, 0);
madera_wait_for_fll(fll, false); madera_wait_for_fll(fll, false);
if (change) if (sync_change)
madera_set_fll_clks(fll, sync_base, false);
if (ref_change) {
madera_set_fll_clks(fll, fll->base, false);
pm_runtime_put_autosuspend(madera->dev); pm_runtime_put_autosuspend(madera->dev);
}
} }
static int madera_enable_fll(struct madera_fll *fll) static int madera_enable_fll(struct madera_fll *fll)
...@@ -3947,6 +4016,10 @@ static int madera_enable_fll(struct madera_fll *fll) ...@@ -3947,6 +4016,10 @@ static int madera_enable_fll(struct madera_fll *fll)
regmap_update_bits(fll->madera->regmap, regmap_update_bits(fll->madera->regmap,
fll->base + MADERA_FLL_CONTROL_7_OFFS, fll->base + MADERA_FLL_CONTROL_7_OFFS,
MADERA_FLL1_GAIN_MASK, 0); MADERA_FLL1_GAIN_MASK, 0);
if (sync_enabled > 0)
madera_set_fll_clks(fll, sync_base, false);
madera_set_fll_clks(fll, fll->base, false);
} }
/* Apply SYNCCLK setting */ /* Apply SYNCCLK setting */
...@@ -4025,11 +4098,15 @@ static int madera_enable_fll(struct madera_fll *fll) ...@@ -4025,11 +4098,15 @@ static int madera_enable_fll(struct madera_fll *fll)
if (!already_enabled) if (!already_enabled)
pm_runtime_get_sync(madera->dev); pm_runtime_get_sync(madera->dev);
if (have_sync) if (have_sync) {
madera_set_fll_clks(fll, sync_base, true);
regmap_update_bits(madera->regmap, regmap_update_bits(madera->regmap,
sync_base + MADERA_FLL_SYNCHRONISER_1_OFFS, sync_base + MADERA_FLL_SYNCHRONISER_1_OFFS,
MADERA_FLL1_SYNC_ENA, MADERA_FLL1_SYNC_ENA,
MADERA_FLL1_SYNC_ENA); MADERA_FLL1_SYNC_ENA);
}
madera_set_fll_clks(fll, fll->base, true);
regmap_update_bits(madera->regmap, regmap_update_bits(madera->regmap,
fll->base + MADERA_FLL_CONTROL_1_OFFS, fll->base + MADERA_FLL_CONTROL_1_OFFS,
MADERA_FLL1_ENA, MADERA_FLL1_ENA); MADERA_FLL1_ENA, MADERA_FLL1_ENA);
...@@ -4201,6 +4278,9 @@ static int madera_enable_fll_ao(struct madera_fll *fll, ...@@ -4201,6 +4278,9 @@ static int madera_enable_fll_ao(struct madera_fll *fll,
fll->base + MADERA_FLLAO_CONTROL_1_OFFS, fll->base + MADERA_FLLAO_CONTROL_1_OFFS,
MADERA_FLL_AO_HOLD, MADERA_FLL_AO_HOLD); MADERA_FLL_AO_HOLD, MADERA_FLL_AO_HOLD);
if (already_enabled)
madera_set_fllao_clks(fll, fll->base, false);
for (i = 0; i < patch_size; i++) { for (i = 0; i < patch_size; i++) {
val = patch[i].def; val = patch[i].def;
...@@ -4214,6 +4294,8 @@ static int madera_enable_fll_ao(struct madera_fll *fll, ...@@ -4214,6 +4294,8 @@ static int madera_enable_fll_ao(struct madera_fll *fll,
regmap_write(madera->regmap, patch[i].reg, val); regmap_write(madera->regmap, patch[i].reg, val);
} }
madera_set_fllao_clks(fll, fll->base, true);
regmap_update_bits(madera->regmap, regmap_update_bits(madera->regmap,
fll->base + MADERA_FLLAO_CONTROL_1_OFFS, fll->base + MADERA_FLLAO_CONTROL_1_OFFS,
MADERA_FLL_AO_ENA, MADERA_FLL_AO_ENA); MADERA_FLL_AO_ENA, MADERA_FLL_AO_ENA);
...@@ -4257,8 +4339,10 @@ static int madera_disable_fll_ao(struct madera_fll *fll) ...@@ -4257,8 +4339,10 @@ static int madera_disable_fll_ao(struct madera_fll *fll)
fll->base + MADERA_FLLAO_CONTROL_2_OFFS, fll->base + MADERA_FLLAO_CONTROL_2_OFFS,
MADERA_FLL_AO_CTRL_UPD_MASK, 0); MADERA_FLL_AO_CTRL_UPD_MASK, 0);
if (change) if (change) {
madera_set_fllao_clks(fll, fll->base, false);
pm_runtime_put_autosuspend(madera->dev); pm_runtime_put_autosuspend(madera->dev);
}
return 0; return 0;
} }
...@@ -4344,8 +4428,10 @@ static int madera_fllhj_disable(struct madera_fll *fll) ...@@ -4344,8 +4428,10 @@ static int madera_fllhj_disable(struct madera_fll *fll)
fll->base + MADERA_FLL_CONTROL_2_OFFS, fll->base + MADERA_FLL_CONTROL_2_OFFS,
MADERA_FLL1_CTRL_UPD_MASK, 0); MADERA_FLL1_CTRL_UPD_MASK, 0);
if (change) if (change) {
madera_set_fllhj_clks(fll, fll->base, false);
pm_runtime_put_autosuspend(madera->dev); pm_runtime_put_autosuspend(madera->dev);
}
return 0; return 0;
} }
...@@ -4517,6 +4603,9 @@ static int madera_fllhj_enable(struct madera_fll *fll) ...@@ -4517,6 +4603,9 @@ static int madera_fllhj_enable(struct madera_fll *fll)
MADERA_FLL1_HOLD_MASK, MADERA_FLL1_HOLD_MASK,
MADERA_FLL1_HOLD_MASK); MADERA_FLL1_HOLD_MASK);
if (already_enabled)
madera_set_fllhj_clks(fll, fll->base, false);
/* Apply refclk */ /* Apply refclk */
ret = madera_fllhj_apply(fll, fll->ref_freq); ret = madera_fllhj_apply(fll, fll->ref_freq);
if (ret) { if (ret) {
...@@ -4528,6 +4617,8 @@ static int madera_fllhj_enable(struct madera_fll *fll) ...@@ -4528,6 +4617,8 @@ static int madera_fllhj_enable(struct madera_fll *fll)
CS47L92_FLL1_REFCLK_SRC_MASK, CS47L92_FLL1_REFCLK_SRC_MASK,
fll->ref_src << CS47L92_FLL1_REFCLK_SRC_SHIFT); fll->ref_src << CS47L92_FLL1_REFCLK_SRC_SHIFT);
madera_set_fllhj_clks(fll, fll->base, true);
regmap_update_bits(madera->regmap, regmap_update_bits(madera->regmap,
fll->base + MADERA_FLL_CONTROL_1_OFFS, fll->base + MADERA_FLL_CONTROL_1_OFFS,
MADERA_FLL1_ENA_MASK, MADERA_FLL1_ENA_MASK,
......
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