diff options
author | Liu Ying <Ying.Liu@freescale.com> | 2013-06-28 12:31:45 +0800 |
---|---|---|
committer | Liu Ying <Ying.Liu@freescale.com> | 2013-06-28 14:22:38 +0800 |
commit | 54884f45c7495cb0c12922b3b79d29c4ba2068be (patch) | |
tree | 6de4a4f4cf7d39d41c87db21bac3312667621cda | |
parent | 083c14b333dbf756dcf380ab08953337614b99a3 (diff) |
ENGR00268893 mx6q/sdl clock:Correct emi_clk set/get rate in aclk_podf
The read/write values of aclk_podf[20:22] field in register 'CCM Serial
Clock Multiplexer Register 1' do not match with each other. The read/
write/divider values have the relationship described by the following
table:
============================================================
write value read value description
3b'000 3b'110 divided by 7
3b'001 3b'111 divided by 8
3b'010 3b'100 divided by 5
3b'011 3b'101 divided by 6
3b'100 3b'010 divided by 3
3b'101 3b'011 divided by 4
3b'110 3b'000 divided by 1
3b'111 3b'001 divided by 2(default)
============================================================
This patch corrects the emi_clk set/get rate functions according to
the above table. On i.MX6Q, emi_clk is used by MIPI CSI2 module as
ccm_pixel_clk, while on i.MX6SDL, it is not used by any module.
The patch may resolve the 1080P30 MIPI camera preview blur issue
indirectly by increasing ccm_pixel_clk for i.MX6Q.
Signed-off-by: Liu Ying <Ying.Liu@freescale.com>
-rw-r--r-- | arch/arm/mach-mx6/clock.c | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/arch/arm/mach-mx6/clock.c b/arch/arm/mach-mx6/clock.c index 4480d774751d..43003ddf3d9e 100644 --- a/arch/arm/mach-mx6/clock.c +++ b/arch/arm/mach-mx6/clock.c @@ -3933,9 +3933,10 @@ static unsigned long _clk_emi_get_rate(struct clk *clk) { u32 reg, div; + /* ACLK_EMI_PODF read value matches with real divider value */ reg = __raw_readl(MXC_CCM_CSCMR1); - div = (((reg & MXC_CCM_CSCMR1_ACLK_EMI_PODF_MASK) >> - MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET)^0x6) + 1; + div = ((reg & MXC_CCM_CSCMR1_ACLK_EMI_PODF_MASK) >> + MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET) + 1; return clk_get_rate(clk->parent) / div; } @@ -3951,9 +3952,26 @@ static int _clk_emi_set_rate(struct clk *clk, unsigned long rate) if (((parent_rate / div) != rate) || (div > 8)) return -EINVAL; + /* + * This is a software workaround for ACLK_EMI_PODF SoC + * implementation bug. The write/read/divider values + * have the relationship described by the following table: + * + * write value read value description + * 3b'000 3b'110 divided by 7 + * 3b'001 3b'111 divided by 8 + * 3b'010 3b'100 divided by 5 + * 3b'011 3b'101 divided by 6 + * 3b'100 3b'010 divided by 3 + * 3b'101 3b'011 divided by 4 + * 3b'110 3b'000 divided by 1 + * 3b'111 3b'001 divided by 2(default) + * + * That's why we do the xor operation below. + */ reg = __raw_readl(MXC_CCM_CSCMR1); reg &= ~MXC_CCM_CSCMR1_ACLK_EMI_PODF_MASK; - reg |= (div - 1) << MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET; + reg |= ((div - 1)^0x6) << MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET; __raw_writel(reg, MXC_CCM_CSCMR1); return 0; |