msm: clock-pll: SR2 Pll enable function for 8226

The SR2 plls in 8226 have a bit which indicates they have finished
changing frequencies. Poll this bit to verify PLL 'lock' before
returning.

Change-Id: Ifb1b8a0b920a0e6055a4eb6355bb67645e7e9f8e
Signed-off-by: Patrick Daly <pdaly@codeaurora.org>
diff --git a/arch/arm/mach-msm/clock-pll.c b/arch/arm/mach-msm/clock-pll.c
index 8e11d37..cd4ead1 100644
--- a/arch/arm/mach-msm/clock-pll.c
+++ b/arch/arm/mach-msm/clock-pll.c
@@ -54,6 +54,7 @@
 static DEFINE_SPINLOCK(pll_reg_lock);
 
 #define ENABLE_WAIT_MAX_LOOPS 200
+#define PLL_LOCKED_BIT BIT(16)
 
 static int pll_vote_clk_enable(struct clk *c)
 {
@@ -148,6 +149,51 @@
 	writel_relaxed(regval, pll_config);
 }
 
+static int sr2_pll_clk_enable(struct clk *c)
+{
+	unsigned long flags;
+	struct pll_clk *pll = to_pll_clk(c);
+	int ret = 0, count;
+	u32 mode = readl_relaxed(PLL_MODE_REG(pll));
+
+	spin_lock_irqsave(&pll_reg_lock, flags);
+
+	/* Disable PLL bypass mode. */
+	mode |= PLL_BYPASSNL;
+	writel_relaxed(mode, PLL_MODE_REG(pll));
+
+	/*
+	 * H/W requires a 5us delay between disabling the bypass and
+	 * de-asserting the reset. Delay 10us just to be safe.
+	 */
+	mb();
+	udelay(10);
+
+	/* De-assert active-low PLL reset. */
+	mode |= PLL_RESET_N;
+	writel_relaxed(mode, PLL_MODE_REG(pll));
+
+	/* Wait for pll to lock. */
+	for (count = ENABLE_WAIT_MAX_LOOPS; count > 0; count--) {
+		if (readl_relaxed(PLL_STATUS_REG(pll)) & PLL_LOCKED_BIT)
+			break;
+		udelay(1);
+	}
+
+	if (!(readl_relaxed(PLL_STATUS_REG(pll)) & PLL_LOCKED_BIT))
+		pr_err("PLL %s didn't lock after enabling it!\n", c->dbg_name);
+
+	/* Enable PLL output. */
+	mode |= PLL_OUTCTRL;
+	writel_relaxed(mode, PLL_MODE_REG(pll));
+
+	/* Ensure that the write above goes through before returning. */
+	mb();
+
+	spin_unlock_irqrestore(&pll_reg_lock, flags);
+	return ret;
+}
+
 static void __pll_clk_enable_reg(void __iomem *mode_reg)
 {
 	u32 mode = readl_relaxed(mode_reg);
@@ -290,8 +336,6 @@
 	return 0;
 }
 
-#define PLL_LOCKED_BIT BIT(16)
-
 int sr_hpm_lp_pll_clk_enable(struct clk *c)
 {
 	unsigned long flags;
@@ -337,6 +381,13 @@
 	.handoff = local_pll_clk_handoff,
 };
 
+struct clk_ops clk_ops_sr2_pll = {
+	.enable = sr2_pll_clk_enable,
+	.disable = local_pll_clk_disable,
+	.set_rate = local_pll_clk_set_rate,
+	.handoff = local_pll_clk_handoff,
+};
+
 struct pll_rate {
 	unsigned int lvalue;
 	unsigned long rate;