aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOwen Chen <owen.chen@mediatek.com>2019-03-05 00:05:38 -0500
committerStephen Boyd <sboyd@kernel.org>2019-04-11 16:09:17 -0400
commitbe17ca6ac76a5cfd07cc3a0397dd05d6929fcbbb (patch)
treee023d9e521b7565640d18eb0425cc51ac1a88bb5
parent9e98c678c2d6ae3a17cb2de55d17f69dddaa231b (diff)
clk: mediatek: Disable tuner_en before change PLL rate
PLLs with tuner_en bit, such as APLL1, need to disable tuner_en before apply new frequency settings, or the new frequency settings (pcw) will not be applied. The tuner_en bit will be disabled during changing PLL rate and be restored after new settings applied. Fixes: e2f744a82d725 (clk: mediatek: Add MT2712 clock support) Cc: <stable@vger.kernel.org> Signed-off-by: Owen Chen <owen.chen@mediatek.com> Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com> Reviewed-by: James Liao <jamesjj.liao@mediatek.com> Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com> Signed-off-by: Stephen Boyd <sboyd@kernel.org>
-rw-r--r--drivers/clk/mediatek/clk-pll.c48
1 files changed, 34 insertions, 14 deletions
diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
index f54e4015b0b1..18842d660317 100644
--- a/drivers/clk/mediatek/clk-pll.c
+++ b/drivers/clk/mediatek/clk-pll.c
@@ -88,6 +88,32 @@ static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin,
88 return ((unsigned long)vco + postdiv - 1) / postdiv; 88 return ((unsigned long)vco + postdiv - 1) / postdiv;
89} 89}
90 90
91static void __mtk_pll_tuner_enable(struct mtk_clk_pll *pll)
92{
93 u32 r;
94
95 if (pll->tuner_en_addr) {
96 r = readl(pll->tuner_en_addr) | BIT(pll->data->tuner_en_bit);
97 writel(r, pll->tuner_en_addr);
98 } else if (pll->tuner_addr) {
99 r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN;
100 writel(r, pll->tuner_addr);
101 }
102}
103
104static void __mtk_pll_tuner_disable(struct mtk_clk_pll *pll)
105{
106 u32 r;
107
108 if (pll->tuner_en_addr) {
109 r = readl(pll->tuner_en_addr) & ~BIT(pll->data->tuner_en_bit);
110 writel(r, pll->tuner_en_addr);
111 } else if (pll->tuner_addr) {
112 r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN;
113 writel(r, pll->tuner_addr);
114 }
115}
116
91static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw, 117static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw,
92 int postdiv) 118 int postdiv)
93{ 119{
@@ -96,6 +122,9 @@ static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw,
96 122
97 pll_en = readl(pll->base_addr + REG_CON0) & CON0_BASE_EN; 123 pll_en = readl(pll->base_addr + REG_CON0) & CON0_BASE_EN;
98 124
125 /* disable tuner */
126 __mtk_pll_tuner_disable(pll);
127
99 /* set postdiv */ 128 /* set postdiv */
100 val = readl(pll->pd_addr); 129 val = readl(pll->pd_addr);
101 val &= ~(POSTDIV_MASK << pll->data->pd_shift); 130 val &= ~(POSTDIV_MASK << pll->data->pd_shift);
@@ -122,6 +151,9 @@ static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw,
122 if (pll->tuner_addr) 151 if (pll->tuner_addr)
123 writel(con1 + 1, pll->tuner_addr); 152 writel(con1 + 1, pll->tuner_addr);
124 153
154 /* restore tuner_en */
155 __mtk_pll_tuner_enable(pll);
156
125 if (pll_en) 157 if (pll_en)
126 udelay(20); 158 udelay(20);
127} 159}
@@ -228,13 +260,7 @@ static int mtk_pll_prepare(struct clk_hw *hw)
228 r |= pll->data->en_mask; 260 r |= pll->data->en_mask;
229 writel(r, pll->base_addr + REG_CON0); 261 writel(r, pll->base_addr + REG_CON0);
230 262
231 if (pll->tuner_en_addr) { 263 __mtk_pll_tuner_enable(pll);
232 r = readl(pll->tuner_en_addr) | BIT(pll->data->tuner_en_bit);
233 writel(r, pll->tuner_en_addr);
234 } else if (pll->tuner_addr) {
235 r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN;
236 writel(r, pll->tuner_addr);
237 }
238 264
239 udelay(20); 265 udelay(20);
240 266
@@ -258,13 +284,7 @@ static void mtk_pll_unprepare(struct clk_hw *hw)
258 writel(r, pll->base_addr + REG_CON0); 284 writel(r, pll->base_addr + REG_CON0);
259 } 285 }
260 286
261 if (pll->tuner_en_addr) { 287 __mtk_pll_tuner_disable(pll);
262 r = readl(pll->tuner_en_addr) & ~BIT(pll->data->tuner_en_bit);
263 writel(r, pll->tuner_en_addr);
264 } else if (pll->tuner_addr) {
265 r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN;
266 writel(r, pll->tuner_addr);
267 }
268 288
269 r = readl(pll->base_addr + REG_CON0); 289 r = readl(pll->base_addr + REG_CON0);
270 r &= ~CON0_BASE_EN; 290 r &= ~CON0_BASE_EN;