summaryrefslogtreecommitdiff
path: root/drivers/clk/meson/clk-pll.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/meson/clk-pll.c')
-rw-r--r--drivers/clk/meson/clk-pll.c47
1 files changed, 40 insertions, 7 deletions
diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
index afefeba6e458..8fef90bf962f 100644
--- a/drivers/clk/meson/clk-pll.c
+++ b/drivers/clk/meson/clk-pll.c
@@ -295,10 +295,14 @@ static int meson_clk_pll_init(struct clk_hw *hw)
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
if (pll->init_count) {
- meson_parm_write(clk->map, &pll->rst, 1);
+ if (MESON_PARM_APPLICABLE(&pll->rst))
+ meson_parm_write(clk->map, &pll->rst, 1);
+
regmap_multi_reg_write(clk->map, pll->init_regs,
pll->init_count);
- meson_parm_write(clk->map, &pll->rst, 0);
+
+ if (MESON_PARM_APPLICABLE(&pll->rst))
+ meson_parm_write(clk->map, &pll->rst, 0);
}
return 0;
@@ -309,8 +313,11 @@ static int meson_clk_pll_is_enabled(struct clk_hw *hw)
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
- if (meson_parm_read(clk->map, &pll->rst) ||
- !meson_parm_read(clk->map, &pll->en) ||
+ if (MESON_PARM_APPLICABLE(&pll->rst) &&
+ meson_parm_read(clk->map, &pll->rst))
+ return 0;
+
+ if (!meson_parm_read(clk->map, &pll->en) ||
!meson_parm_read(clk->map, &pll->l))
return 0;
@@ -341,13 +348,34 @@ static int meson_clk_pll_enable(struct clk_hw *hw)
return 0;
/* Make sure the pll is in reset */
- meson_parm_write(clk->map, &pll->rst, 1);
+ if (MESON_PARM_APPLICABLE(&pll->rst))
+ meson_parm_write(clk->map, &pll->rst, 1);
/* Enable the pll */
meson_parm_write(clk->map, &pll->en, 1);
/* Take the pll out reset */
- meson_parm_write(clk->map, &pll->rst, 0);
+ if (MESON_PARM_APPLICABLE(&pll->rst))
+ meson_parm_write(clk->map, &pll->rst, 0);
+
+ /*
+ * Compared with the previous SoCs, self-adaption current module
+ * is newly added for A1, keep the new power-on sequence to enable the
+ * PLL. The sequence is:
+ * 1. enable the pll, delay for 10us
+ * 2. enable the pll self-adaption current module, delay for 40us
+ * 3. enable the lock detect module
+ */
+ if (MESON_PARM_APPLICABLE(&pll->current_en)) {
+ usleep_range(10, 20);
+ meson_parm_write(clk->map, &pll->current_en, 1);
+ usleep_range(40, 50);
+ }
+
+ if (MESON_PARM_APPLICABLE(&pll->l_detect)) {
+ meson_parm_write(clk->map, &pll->l_detect, 1);
+ meson_parm_write(clk->map, &pll->l_detect, 0);
+ }
if (meson_clk_pll_wait_lock(hw))
return -EIO;
@@ -361,10 +389,15 @@ static void meson_clk_pll_disable(struct clk_hw *hw)
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
/* Put the pll is in reset */
- meson_parm_write(clk->map, &pll->rst, 1);
+ if (MESON_PARM_APPLICABLE(&pll->rst))
+ meson_parm_write(clk->map, &pll->rst, 1);
/* Disable the pll */
meson_parm_write(clk->map, &pll->en, 0);
+
+ /* Disable PLL internal self-adaption current module */
+ if (MESON_PARM_APPLICABLE(&pll->current_en))
+ meson_parm_write(clk->map, &pll->current_en, 0);
}
static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,