
Hi Peng,
On 01/03/2016 11:10 PM, Peng Fan wrote:
Check "Figure 19-5. BUS clock generation" of i.MX 6SoloX Applications Processor Reference Manual and "Figure 18-5. BUS clock generation" of i.MX 6UltraLite Applications Processor Reference Manual. If mmdc clk sources from pll4_main_clk(pll_audio), the calculation is wrong.
Fix mmdc_ch0 clk calculation. Also add PLL_AUDIO/VIDEO support for decode_pll.
Signed-off-by: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de
arch/arm/cpu/armv7/mx6/clock.c | 63 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 4 deletions(-)
diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c index 64514b1..1506c04 100644 --- a/arch/arm/cpu/armv7/mx6/clock.c +++ b/arch/arm/cpu/armv7/mx6/clock.c @@ -18,6 +18,8 @@ enum pll_clocks { PLL_BUS, /* System Bus PLL*/ PLL_USBOTG, /* OTG USB PLL */ PLL_ENET, /* ENET PLL */
- PLL_AUDIO, /* AUDIO PLL */
- PLL_VIDEO, /* AUDIO PLL */
};
struct mxc_ccm_reg *imx_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; @@ -204,7 +206,7 @@ int enable_spi_clk(unsigned char enable, unsigned spi_num) } static u32 decode_pll(enum pll_clocks pll, u32 infreq) {
- u32 div;
u32 div, test_div, pll_num, pll_denom;
switch (pll) { case PLL_SYS:
@@ -227,6 +229,44 @@ static u32 decode_pll(enum pll_clocks pll, u32 infreq) div &= BM_ANADIG_PLL_ENET_DIV_SELECT;
return 25000000 * (div + (div >> 1) + 1);
- case PLL_AUDIO:
div = __raw_readl(&imx_ccm->analog_pll_audio);
if (!(div & BM_ANADIG_PLL_AUDIO_ENABLE))
return 0;
/* BM_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC is ignored */
if (div & BM_ANADIG_PLL_AUDIO_BYPASS)
return MXC_HCLK;
pll_num = __raw_readl(&imx_ccm->analog_pll_audio_num);
pll_denom = __raw_readl(&imx_ccm->analog_pll_audio_denom);
test_div = (div & BM_ANADIG_PLL_AUDIO_TEST_DIV_SELECT) >>
BP_ANADIG_PLL_AUDIO_TEST_DIV_SELECT;
div &= BM_ANADIG_PLL_AUDIO_DIV_SELECT;
if (test_div == 3) {
debug("Error test_div\n");
return 0;
}
test_div = 1 << (2 - test_div);
return infreq * (div + pll_num / pll_denom) / test_div;
- case PLL_VIDEO:
div = __raw_readl(&imx_ccm->analog_pll_video);
if (!(div & BM_ANADIG_PLL_VIDEO_ENABLE))
return 0;
/* BM_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC is ignored */
if (div & BM_ANADIG_PLL_VIDEO_BYPASS)
return MXC_HCLK;
pll_num = __raw_readl(&imx_ccm->analog_pll_video_num);
pll_denom = __raw_readl(&imx_ccm->analog_pll_video_denom);
test_div = (div & BM_ANADIG_PLL_VIDEO_POST_DIV_SELECT) >>
BP_ANADIG_PLL_VIDEO_POST_DIV_SELECT;
div &= BM_ANADIG_PLL_VIDEO_DIV_SELECT;
if (test_div == 3) {
debug("Error test_div\n");
return 0;
}
test_div = 1 << (2 - test_div);
default: return 0; }return infreq * (div + pll_num / pll_denom) / test_div;
@@ -437,7 +477,7 @@ static u32 get_mmdc_ch0_clk(void) u32 cbcmr = __raw_readl(&imx_ccm->cbcmr); u32 cbcdr = __raw_readl(&imx_ccm->cbcdr);
- u32 freq, podf, per2_clk2_podf;
u32 freq, podf, per2_clk2_podf, misc2_audio_div;
if (is_cpu_type(MXC_CPU_MX6SX) || is_cpu_type(MXC_CPU_MX6UL) || is_cpu_type(MXC_CPU_MX6SL)) {
@@ -472,9 +512,24 @@ static u32 get_mmdc_ch0_clk(void) freq = mxc_get_pll_pfd(PLL_BUS, 0); break; case 3:
/* static / 2 divider */
freq = mxc_get_pll_pfd(PLL_BUS, 2) / 2;
Your indentation is off here (1 tab too shallow):
Finding the register would also have been easier if this were named pmu_misc2.
misc2_audio_div = ((__raw_readl(&imx_ccm->ana_misc2)
>> 22) & 2) |
((__raw_readl(&imx_ccm->ana_misc2)
>> 15) & 1);
switch (misc2_audio_div) {
case 0:
case 2:
misc2_audio_div = 1;
break;
case 1:
misc2_audio_div = 2; break;
case 3:
misc2_audio_div = 4;
break;
}
freq = decode_pll(PLL_AUDIO, MXC_HCLK) / misc2_audio_div;
} return freq / (podf + 1) / (per2_clk2_podf + 1);break; }