msm: clock-dss-8960: Fix HDMI PLL power up/down sequence
Fix HDMI PLL power up/down sequence along with proper control
of HDMI PHY registers to avoid PLL lock detect failures
CRs-Fixed: 328366
Change-Id: Ic8a791f62b1e695bd70081c11156d57191a66de3
Signed-off-by: Ravishangar Kalyanam <rkalya@codeaurora.org>
diff --git a/arch/arm/mach-msm/clock-dss-8960.c b/arch/arm/mach-msm/clock-dss-8960.c
index 7374f92..8331899 100644
--- a/arch/arm/mach-msm/clock-dss-8960.c
+++ b/arch/arm/mach-msm/clock-dss-8960.c
@@ -102,16 +102,38 @@
ahb_enabled = ahb_en_reg & BIT(4);
if (!ahb_enabled) {
writel_relaxed(ahb_en_reg | BIT(4), AHB_EN_REG);
+ /* Make sure iface clock is enabled before register access */
mb();
}
+ /* Assert PLL S/W reset */
+ writel_relaxed(0x8D, HDMI_PHY_PLL_LOCKDET_CFG2);
+ writel_relaxed(0x10, HDMI_PHY_PLL_LOCKDET_CFG0);
+ writel_relaxed(0x1A, HDMI_PHY_PLL_LOCKDET_CFG1);
+ /* De-assert PLL S/W reset */
+ writel_relaxed(0x0D, HDMI_PHY_PLL_LOCKDET_CFG2);
+
+ val = readl_relaxed(HDMI_PHY_REG_12);
+ val |= BIT(5);
+ /* Assert PHY S/W reset */
+ writel_relaxed(val, HDMI_PHY_REG_12);
+ val &= ~BIT(5);
+ /* De-assert PHY S/W reset */
+ writel_relaxed(val, HDMI_PHY_REG_12);
+ writel_relaxed(0x3f, HDMI_PHY_REG_2);
+
+ val = readl_relaxed(HDMI_PHY_REG_12);
+ val |= PWRDN_B;
+ writel_relaxed(val, HDMI_PHY_REG_12);
+ /* Wait 10 us for enabling global power for PHY */
+ mb();
+ udelay(10);
+
val = readl_relaxed(HDMI_PHY_PLL_PWRDN_B);
val |= PLL_PWRDN_B;
- writel_relaxed(val, HDMI_PHY_PLL_PWRDN_B);
- mb();
val &= ~PD_PLL;
writel_relaxed(val, HDMI_PHY_PLL_PWRDN_B);
- mb();
+ writel_relaxed(0x80, HDMI_PHY_REG_2);
while (!(readl_relaxed(HDMI_PHY_PLL_STATUS0) & BIT(0)))
cpu_relax();
@@ -134,13 +156,15 @@
mb();
}
+ val = readl_relaxed(HDMI_PHY_REG_12);
+ val &= (~PWRDN_B);
+ writel_relaxed(val, HDMI_PHY_REG_12);
+
val = readl_relaxed(HDMI_PHY_PLL_PWRDN_B);
val |= PD_PLL;
+ val &= (~PLL_PWRDN_B);
writel_relaxed(val, HDMI_PHY_PLL_PWRDN_B);
- mb();
-
- val = val & (~PLL_PWRDN_B);
- writel_relaxed(val, HDMI_PHY_PLL_PWRDN_B);
+ /* Make sure HDMI PHY/PLL are powered down */
mb();
if (!ahb_enabled)
@@ -156,25 +180,15 @@
int hdmi_pll_set_rate(unsigned rate)
{
unsigned int set_power_dwn = 0;
- unsigned int val;
u32 ahb_en_reg = readl_relaxed(AHB_EN_REG);
u32 ahb_enabled = ahb_en_reg & BIT(4);
if (!ahb_enabled) {
writel_relaxed(ahb_en_reg | BIT(4), AHB_EN_REG);
+ /* Make sure iface clock is enabled before register access */
mb();
}
- writel_relaxed(0x7f, HDMI_PHY_REG_2);
- writel_relaxed(0x3f, HDMI_PHY_REG_2);
- writel_relaxed(0x1f, HDMI_PHY_REG_2);
-
- val = readl_relaxed(HDMI_PHY_REG_12);
- val |= PWRDN_B;
- writel_relaxed(val, HDMI_PHY_REG_12);
- mb();
-
- writel_relaxed(0x81, HDMI_PHY_REG_2);
if (hdmi_pll_on) {
hdmi_pll_disable();
set_power_dwn = 1;
@@ -198,9 +212,6 @@
writel_relaxed(0x00, HDMI_PHY_PLL_SSC_CFG1);
writel_relaxed(0x00, HDMI_PHY_PLL_SSC_CFG2);
writel_relaxed(0x00, HDMI_PHY_PLL_SSC_CFG3);
- writel_relaxed(0x10, HDMI_PHY_PLL_LOCKDET_CFG0);
- writel_relaxed(0x1A, HDMI_PHY_PLL_LOCKDET_CFG1);
- writel_relaxed(0x0D, HDMI_PHY_PLL_LOCKDET_CFG2);
writel_relaxed(0x2A, HDMI_PHY_PLL_VCOCAL_CFG0);
writel_relaxed(0x03, HDMI_PHY_PLL_VCOCAL_CFG1);
writel_relaxed(0x2B, HDMI_PHY_PLL_VCOCAL_CFG2);
@@ -228,9 +239,6 @@
writel_relaxed(0x00, HDMI_PHY_PLL_SSC_CFG1);
writel_relaxed(0x00, HDMI_PHY_PLL_SSC_CFG2);
writel_relaxed(0x20, HDMI_PHY_PLL_SSC_CFG3);
- writel_relaxed(0x10, HDMI_PHY_PLL_LOCKDET_CFG0);
- writel_relaxed(0x1A, HDMI_PHY_PLL_LOCKDET_CFG1);
- writel_relaxed(0x0D, HDMI_PHY_PLL_LOCKDET_CFG2);
writel_relaxed(0xF4, HDMI_PHY_PLL_VCOCAL_CFG0);
writel_relaxed(0x02, HDMI_PHY_PLL_VCOCAL_CFG1);
writel_relaxed(0x2B, HDMI_PHY_PLL_VCOCAL_CFG2);
@@ -258,9 +266,6 @@
writel_relaxed(0x00, HDMI_PHY_PLL_SSC_CFG1);
writel_relaxed(0x00, HDMI_PHY_PLL_SSC_CFG2);
writel_relaxed(0x00, HDMI_PHY_PLL_SSC_CFG3);
- writel_relaxed(0x10, HDMI_PHY_PLL_LOCKDET_CFG0);
- writel_relaxed(0x1A, HDMI_PHY_PLL_LOCKDET_CFG1);
- writel_relaxed(0x0D, HDMI_PHY_PLL_LOCKDET_CFG2);
writel_relaxed(0x2a, HDMI_PHY_PLL_VCOCAL_CFG0);
writel_relaxed(0x03, HDMI_PHY_PLL_VCOCAL_CFG1);
writel_relaxed(0x2B, HDMI_PHY_PLL_VCOCAL_CFG2);
@@ -300,9 +305,6 @@
writel_relaxed(0x00, HDMI_PHY_PLL_SSC_CFG1);
writel_relaxed(0x00, HDMI_PHY_PLL_SSC_CFG2);
writel_relaxed(0x00, HDMI_PHY_PLL_SSC_CFG3);
- writel_relaxed(0x10, HDMI_PHY_PLL_LOCKDET_CFG0);
- writel_relaxed(0x1A, HDMI_PHY_PLL_LOCKDET_CFG1);
- writel_relaxed(0x0D, HDMI_PHY_PLL_LOCKDET_CFG2);
writel_relaxed(0xe6, HDMI_PHY_PLL_VCOCAL_CFG0);
writel_relaxed(0x02, HDMI_PHY_PLL_VCOCAL_CFG1);
writel_relaxed(0x2B, HDMI_PHY_PLL_VCOCAL_CFG2);
@@ -311,10 +313,10 @@
writel_relaxed(0x00, HDMI_PHY_PLL_VCOCAL_CFG5);
writel_relaxed(0x33, HDMI_PHY_PLL_VCOCAL_CFG6);
writel_relaxed(0x00, HDMI_PHY_PLL_VCOCAL_CFG7);
- writel_relaxed(0x0D, HDMI_PHY_PLL_LOCKDET_CFG2);
break;
}
+ /* Make sure writes complete before disabling iface clock */
mb();
if (set_power_dwn)