From 9d6b51ff1a11b47879e44a83a14c7b49c1893852 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Lothar=20Wa=C3=9Fmann?= Date: Wed, 13 Apr 2016 12:03:10 +0200 Subject: [PATCH] mx6: clock: take 'num' and 'denom' regs into account when calculating audio/video PLL frequency --- arch/arm/cpu/armv7/mx6/clock.c | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c index 2f5af3e25b..d3860fcf29 100644 --- a/arch/arm/cpu/armv7/mx6/clock.c +++ b/arch/arm/cpu/armv7/mx6/clock.c @@ -306,6 +306,8 @@ int enable_spi_clk(unsigned char enable, unsigned spi_num) static u32 decode_pll(enum pll_clocks pll, u32 infreq) { u32 div, post_div; + u32 pll_num, pll_denom; + u64 freq; switch (pll) { case PLL_ARM: @@ -332,24 +334,46 @@ static u32 decode_pll(enum pll_clocks pll, u32 infreq) return infreq * (20 + div * 2); case PLL_AUDIO: div = __raw_readl(&anatop->pll_audio); + /* BM_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC is ignored */ if (div & BM_ANADIG_PLL_AUDIO_BYPASS) return infreq; + + pll_num = __raw_readl(&anatop->pll_audio_num); + pll_denom = __raw_readl(&anatop->pll_audio_denom); + post_div = (div & BM_ANADIG_PLL_AUDIO_POST_DIV_SELECT) >> BP_ANADIG_PLL_AUDIO_POST_DIV_SELECT; + if (post_div == 3) { + printf("Invalid post divider value for PLL_AUDIO\n"); + return 0; + } post_div = 1 << (2 - post_div); div &= BM_ANADIG_PLL_AUDIO_DIV_SELECT; - return lldiv((u64)infreq * div, post_div); + freq = (u64)infreq * pll_num / pll_denom; + freq += infreq * div; + return lldiv(freq, post_div); case PLL_VIDEO: div = __raw_readl(&anatop->pll_video); + /* BM_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC is ignored */ if (div & BM_ANADIG_PLL_VIDEO_BYPASS) return infreq; + + pll_num = __raw_readl(&anatop->pll_video_num); + pll_denom = __raw_readl(&anatop->pll_video_denom); + post_div = (div & BM_ANADIG_PLL_VIDEO_POST_DIV_SELECT) >> BP_ANADIG_PLL_VIDEO_POST_DIV_SELECT; + if (post_div == 3) { + printf("Invalid post divider value for PLL_VIDEO\n"); + return 0; + } post_div = 1 << (2 - post_div); div &= BM_ANADIG_PLL_VIDEO_DIV_SELECT; - return lldiv((u64)infreq * div, post_div); + freq = (u64)infreq * pll_num / pll_denom; + freq += infreq * div; + return lldiv(freq, post_div); case PLL_ENET: div = __raw_readl(&anatop->pll_enet); if (div & BM_ANADIG_PLL_ENET_BYPASS) @@ -368,10 +392,11 @@ static u32 decode_pll(enum pll_clocks pll, u32 infreq) div = __raw_readl(&anatop->pll_mlb); if (div & BM_ANADIG_PLL_MLB_BYPASS) return infreq; - /* unknown external clock provided on MLB_CLK pin */ + /* fallthru: unknown external clock provided on MLB_CLK pin */ + default: return 0; } - return 0; + /* NOTREACHED */ } static u32 mxc_get_pll_pfd(enum pll_clocks pll, int pfd_num) -- 2.39.2