| From be17ca6ac76a5cfd07cc3a0397dd05d6929fcbbb Mon Sep 17 00:00:00 2001 |
| From: Owen Chen <owen.chen@mediatek.com> |
| Date: Tue, 5 Mar 2019 13:05:38 +0800 |
| Subject: clk: mediatek: Disable tuner_en before change PLL rate |
| |
| From: Owen Chen <owen.chen@mediatek.com> |
| |
| commit be17ca6ac76a5cfd07cc3a0397dd05d6929fcbbb upstream. |
| |
| 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> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/clk/mediatek/clk-pll.c | 48 +++++++++++++++++++++++++++++------------ |
| 1 file changed, 34 insertions(+), 14 deletions(-) |
| |
| --- a/drivers/clk/mediatek/clk-pll.c |
| +++ b/drivers/clk/mediatek/clk-pll.c |
| @@ -88,6 +88,32 @@ static unsigned long __mtk_pll_recalc_ra |
| return ((unsigned long)vco + postdiv - 1) / postdiv; |
| } |
| |
| +static void __mtk_pll_tuner_enable(struct mtk_clk_pll *pll) |
| +{ |
| + u32 r; |
| + |
| + if (pll->tuner_en_addr) { |
| + r = readl(pll->tuner_en_addr) | BIT(pll->data->tuner_en_bit); |
| + writel(r, pll->tuner_en_addr); |
| + } else if (pll->tuner_addr) { |
| + r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN; |
| + writel(r, pll->tuner_addr); |
| + } |
| +} |
| + |
| +static void __mtk_pll_tuner_disable(struct mtk_clk_pll *pll) |
| +{ |
| + u32 r; |
| + |
| + if (pll->tuner_en_addr) { |
| + r = readl(pll->tuner_en_addr) & ~BIT(pll->data->tuner_en_bit); |
| + writel(r, pll->tuner_en_addr); |
| + } else if (pll->tuner_addr) { |
| + r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN; |
| + writel(r, pll->tuner_addr); |
| + } |
| +} |
| + |
| static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw, |
| int postdiv) |
| { |
| @@ -96,6 +122,9 @@ static void mtk_pll_set_rate_regs(struct |
| |
| pll_en = readl(pll->base_addr + REG_CON0) & CON0_BASE_EN; |
| |
| + /* disable tuner */ |
| + __mtk_pll_tuner_disable(pll); |
| + |
| /* set postdiv */ |
| val = readl(pll->pd_addr); |
| val &= ~(POSTDIV_MASK << pll->data->pd_shift); |
| @@ -122,6 +151,9 @@ static void mtk_pll_set_rate_regs(struct |
| if (pll->tuner_addr) |
| writel(con1 + 1, pll->tuner_addr); |
| |
| + /* restore tuner_en */ |
| + __mtk_pll_tuner_enable(pll); |
| + |
| if (pll_en) |
| udelay(20); |
| } |
| @@ -228,13 +260,7 @@ static int mtk_pll_prepare(struct clk_hw |
| r |= pll->data->en_mask; |
| writel(r, pll->base_addr + REG_CON0); |
| |
| - if (pll->tuner_en_addr) { |
| - r = readl(pll->tuner_en_addr) | BIT(pll->data->tuner_en_bit); |
| - writel(r, pll->tuner_en_addr); |
| - } else if (pll->tuner_addr) { |
| - r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN; |
| - writel(r, pll->tuner_addr); |
| - } |
| + __mtk_pll_tuner_enable(pll); |
| |
| udelay(20); |
| |
| @@ -258,13 +284,7 @@ static void mtk_pll_unprepare(struct clk |
| writel(r, pll->base_addr + REG_CON0); |
| } |
| |
| - if (pll->tuner_en_addr) { |
| - r = readl(pll->tuner_en_addr) & ~BIT(pll->data->tuner_en_bit); |
| - writel(r, pll->tuner_en_addr); |
| - } else if (pll->tuner_addr) { |
| - r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN; |
| - writel(r, pll->tuner_addr); |
| - } |
| + __mtk_pll_tuner_disable(pll); |
| |
| r = readl(pll->base_addr + REG_CON0); |
| r &= ~CON0_BASE_EN; |