summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorLiu Ying <Ying.Liu@freescale.com>2013-06-28 12:31:45 +0800
committerLiu Ying <Ying.Liu@freescale.com>2013-06-28 14:22:38 +0800
commit54884f45c7495cb0c12922b3b79d29c4ba2068be (patch)
tree6de4a4f4cf7d39d41c87db21bac3312667621cda /arch
parent083c14b333dbf756dcf380ab08953337614b99a3 (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>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-mx6/clock.c24
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;