diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c
index baa3f78d..12cc900 100644
--- a/drivers/phy/phy-ti-pipe3.c
+++ b/drivers/phy/phy-ti-pipe3.c
@@ -47,7 +47,8 @@
 #define	PLL_SD_MASK		0x0003FC00
 #define	PLL_SD_SHIFT		10
 #define	SET_PLL_GO		0x1
-#define	PLL_TICOPWDN		0x10000
+#define PLL_LDOPWDN		BIT(15)
+#define PLL_TICOPWDN		BIT(16)
 #define	PLL_LOCK		0x2
 #define	PLL_IDLE		0x1
 
@@ -56,7 +57,8 @@
  * value required for the PIPE3PHY_PLL_CONFIGURATION2.PLL_IDLE status
  * to be correctly reflected in the PIPE3PHY_PLL_STATUS register.
  */
-# define PLL_IDLE_TIME  100;
+#define PLL_IDLE_TIME	100	/* in milliseconds */
+#define PLL_LOCK_TIME	100	/* in milliseconds */
 
 struct pipe3_dpll_params {
 	u16	m;
@@ -132,24 +134,6 @@ static struct pipe3_dpll_params *ti_pipe3_get_dpll_params(struct ti_pipe3 *phy)
 static int ti_pipe3_power_off(struct phy *x)
 {
 	struct ti_pipe3 *phy = phy_get_drvdata(x);
-	int val;
-	int timeout = PLL_IDLE_TIME;
-
-	val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
-	val |= PLL_IDLE;
-	ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
-
-	do {
-		val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
-		if (val & PLL_TICOPWDN)
-			break;
-		udelay(5);
-	} while (--timeout);
-
-	if (!timeout) {
-		dev_err(phy->dev, "power off failed\n");
-		return -EBUSY;
-	}
 
 	omap_control_phy_power(phy->control_dev, 0);
 
@@ -159,44 +143,34 @@ static int ti_pipe3_power_off(struct phy *x)
 static int ti_pipe3_power_on(struct phy *x)
 {
 	struct ti_pipe3 *phy = phy_get_drvdata(x);
-	int val;
-	int timeout = PLL_IDLE_TIME;
-
-	val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
-	val &= ~PLL_IDLE;
-	ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
 
-	do {
-		val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
-		if (!(val & PLL_TICOPWDN))
-			break;
-		udelay(5);
-	} while (--timeout);
-
-	if (!timeout) {
-		dev_err(phy->dev, "power on failed\n");
-		return -EBUSY;
-	}
+	omap_control_phy_power(phy->control_dev, 1);
 
 	return 0;
 }
 
-static void ti_pipe3_dpll_relock(struct ti_pipe3 *phy)
+static int ti_pipe3_dpll_wait_lock(struct ti_pipe3 *phy)
 {
 	u32		val;
 	unsigned long	timeout;
 
-	ti_pipe3_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);
-
-	timeout = jiffies + msecs_to_jiffies(20);
+	timeout = jiffies + msecs_to_jiffies(PLL_LOCK_TIME);
 	do {
+		cpu_relax();
 		val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
 		if (val & PLL_LOCK)
 			break;
-	} while (!WARN_ON(time_after(jiffies, timeout)));
+	} while (!time_after(jiffies, timeout));
+
+	if (!(val & PLL_LOCK)) {
+		dev_err(phy->dev, "DPLL failed to lock\n");
+		return -EBUSY;
+	}
+
+	return 0;
 }
 
-static int ti_pipe3_dpll_lock(struct ti_pipe3 *phy)
+static int ti_pipe3_dpll_program(struct ti_pipe3 *phy)
 {
 	u32			val;
 	struct pipe3_dpll_params *dpll_params;
@@ -230,27 +204,65 @@ static int ti_pipe3_dpll_lock(struct ti_pipe3 *phy)
 	val |= dpll_params->sd << PLL_SD_SHIFT;
 	ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);
 
-	ti_pipe3_dpll_relock(phy);
+	ti_pipe3_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);
 
-	return 0;
+	return ti_pipe3_dpll_wait_lock(phy);
 }
 
 static int ti_pipe3_init(struct phy *x)
 {
 	struct ti_pipe3 *phy = phy_get_drvdata(x);
-	int ret;
+	u32 val;
+	int ret = 0;
 
-	ret = ti_pipe3_dpll_lock(phy);
-	if (ret)
-		return ret;
+	/* Bring it out of IDLE if it is IDLE */
+	val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
+	if (val & PLL_IDLE) {
+		val &= ~PLL_IDLE;
+		ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
+		ret = ti_pipe3_dpll_wait_lock(phy);
+	}
 
-	omap_control_phy_power(phy->control_dev, 1);
+	/* Program the DPLL only if not locked */
+	val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
+	if (!(val & PLL_LOCK))
+		if (ti_pipe3_dpll_program(phy))
+			return -EINVAL;
 
-	return 0;
+	return ret;
 }
 
+static int ti_pipe3_exit(struct phy *x)
+{
+	struct ti_pipe3 *phy = phy_get_drvdata(x);
+	u32 val;
+	unsigned long timeout;
+
+	/* Put DPLL in IDLE mode */
+	val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
+	val |= PLL_IDLE;
+	ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
+
+	/* wait for LDO and Oscillator to power down */
+	timeout = jiffies + msecs_to_jiffies(PLL_IDLE_TIME);
+	do {
+		cpu_relax();
+		val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
+		if ((val & PLL_TICOPWDN) && (val & PLL_LDOPWDN))
+			break;
+	} while (!time_after(jiffies, timeout));
+
+	if (!(val & PLL_TICOPWDN) || !(val & PLL_LDOPWDN)) {
+		dev_err(phy->dev, "Failed to power down: PLL_STATUS 0x%x\n",
+			val);
+		return -EBUSY;
+	}
+
+	return 0;
+}
 static struct phy_ops ops = {
 	.init		= ti_pipe3_init,
+	.exit		= ti_pipe3_exit,
 	.power_on	= ti_pipe3_power_on,
 	.power_off	= ti_pipe3_power_off,
 	.owner		= THIS_MODULE,
