diff options
| author | Owen Chen <owen.chen@mediatek.com> | 2019-03-05 00:05:38 -0500 |
|---|---|---|
| committer | Stephen Boyd <sboyd@kernel.org> | 2019-04-11 16:09:17 -0400 |
| commit | be17ca6ac76a5cfd07cc3a0397dd05d6929fcbbb (patch) | |
| tree | e023d9e521b7565640d18eb0425cc51ac1a88bb5 | |
| parent | 9e98c678c2d6ae3a17cb2de55d17f69dddaa231b (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.c | 48 |
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 | ||
| 91 | static 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 | |||
| 104 | static 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 | |||
| 91 | static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw, | 117 | static 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; |
