clk: qcom: mdss: split the DSI PLL driver based on PLL mode

Re-organize the DSI PLL driver code and split it based on
the DSI PLL HPM/LPM mode. Add a common PLL util file to use
the APIs which are common for both PLLs. Update the DSI PLL
enable sequence with the recommended settings for LPM mode.

Change-Id: I3f86554522e16579d5c2eccab976136c7afb0dd2
Signed-off-by: Padmanabhan Komanduru <pkomandu@codeaurora.org>
Signed-off-by: Narendra Muppalla <narendram@codeaurora.org>
diff --git a/drivers/clk/qcom/mdss/Makefile b/drivers/clk/qcom/mdss/Makefile
index 25fb1d1..f18ee98 100644
--- a/drivers/clk/qcom/mdss/Makefile
+++ b/drivers/clk/qcom/mdss/Makefile
@@ -1,5 +1,7 @@
 obj-$(CONFIG_MSM_MDSS_PLL) += mdss-pll-util.o
 obj-$(CONFIG_MSM_MDSS_PLL) += mdss-pll.o
+obj-$(CONFIG_MSM_MDSS_PLL) += mdss-dsi-pll-util.o
 obj-$(CONFIG_MSM_MDSS_PLL) += mdss-dsi-pll-28hpm.o
+obj-$(CONFIG_MSM_MDSS_PLL) += mdss-dsi-pll-28lpm.o
 obj-$(CONFIG_MSM_MDSS_PLL) += mdss-edp-pll-28hpm.o
 obj-$(CONFIG_MSM_MDSS_PLL) += mdss-hdmi-pll-28hpm.o
diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-28hpm.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-28hpm.c
index 03c1107..61c49c2 100644
--- a/drivers/clk/qcom/mdss/mdss-dsi-pll-28hpm.c
+++ b/drivers/clk/qcom/mdss/mdss-dsi-pll-28hpm.c
@@ -15,64 +15,16 @@
 
 #include <linux/kernel.h>
 #include <linux/err.h>
-#include <linux/iopoll.h>
 #include <linux/delay.h>
 #include <linux/clk/msm-clk-provider.h>
 #include <linux/clk/msm-clk.h>
 #include <linux/clk/msm-clock-generic.h>
-
 #include <dt-bindings/clock/msm-clocks-8974.h>
-#include <dt-bindings/clock/msm-clocks-8916.h>
 
 #include "mdss-pll.h"
 #include "mdss-dsi-pll.h"
 
-#define DSI_PHY_PLL_UNIPHY_PLL_REFCLK_CFG	(0x0)
-#define DSI_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG	(0x0004)
-#define DSI_PHY_PLL_UNIPHY_PLL_CHGPUMP_CFG	(0x0008)
-#define DSI_PHY_PLL_UNIPHY_PLL_VCOLPF_CFG	(0x000C)
-#define DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG		(0x0010)
-#define DSI_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG	(0x0014)
-#define DSI_PHY_PLL_UNIPHY_PLL_DMUX_CFG		(0x0018)
-#define DSI_PHY_PLL_UNIPHY_PLL_AMUX_CFG		(0x001C)
-#define DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG		(0x0020)
-#define DSI_PHY_PLL_UNIPHY_PLL_POSTDIV2_CFG	(0x0024)
-#define DSI_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG	(0x0028)
-#define DSI_PHY_PLL_UNIPHY_PLL_LPFR_CFG		(0x002C)
-#define DSI_PHY_PLL_UNIPHY_PLL_LPFC1_CFG	(0x0030)
-#define DSI_PHY_PLL_UNIPHY_PLL_LPFC2_CFG	(0x0034)
-#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0		(0x0038)
-#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG1		(0x003C)
-#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG2		(0x0040)
-#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG3		(0x0044)
-#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG4		(0x0048)
-#define DSI_PHY_PLL_UNIPHY_PLL_SSC_CFG0		(0x004C)
-#define DSI_PHY_PLL_UNIPHY_PLL_SSC_CFG1		(0x0050)
-#define DSI_PHY_PLL_UNIPHY_PLL_SSC_CFG2		(0x0054)
-#define DSI_PHY_PLL_UNIPHY_PLL_SSC_CFG3		(0x0058)
-#define DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG0	(0x005C)
-#define DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG1	(0x0060)
-#define DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2	(0x0064)
-#define DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG		(0x0068)
-#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG0		(0x006C)
-#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG1		(0x0070)
-#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG2		(0x0074)
-#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG3		(0x0078)
-#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG4		(0x007C)
-#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG5		(0x0080)
-#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG6		(0x0084)
-#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG7		(0x0088)
-#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG8		(0x008C)
-#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG9		(0x0090)
-#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG10	(0x0094)
-#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG11	(0x0098)
-#define DSI_PHY_PLL_UNIPHY_PLL_EFUSE_CFG	(0x009C)
-#define DSI_PHY_PLL_UNIPHY_PLL_STATUS		(0x00C0)
-
-
-#define DSI_PLL_POLL_MAX_READS			10
-#define DSI_PLL_POLL_TIMEOUT_US			50
-#define DSI_PLL_SEQ_M_MAX_COUNTER	7
+#define VCO_DELAY_USEC		1
 
 static struct clk_div_ops fixed_2div_ops;
 static const struct clk_ops byte_mux_clk_ops;
@@ -92,211 +44,6 @@
 	{750000000, 11},
 };
 
-int set_byte_mux_sel(struct mux_clk *clk, int sel)
-{
-	struct mdss_pll_resources *dsi_pll_res = clk->priv;
-
-	pr_debug("byte mux set to %s mode\n", sel ? "indirect" : "direct");
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-				DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG, (sel << 1));
-
-	return 0;
-}
-
-int get_byte_mux_sel(struct mux_clk *clk)
-{
-	int mux_mode, rc;
-	struct mdss_pll_resources *dsi_pll_res = clk->priv;
-
-	rc = mdss_pll_resource_enable(dsi_pll_res, true);
-	if (rc) {
-		pr_err("Failed to enable mdss dsi pll resources\n");
-		return rc;
-	}
-
-	mux_mode = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
-				DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG) & BIT(1);
-
-	pr_debug("byte mux mode = %s", mux_mode ? "indirect" : "direct");
-	mdss_pll_resource_enable(dsi_pll_res, false);
-
-	return !!mux_mode;
-}
-
-static inline struct dsi_pll_vco_clk *to_vco_clk(struct clk *clk)
-{
-	return container_of(clk, struct dsi_pll_vco_clk, c);
-}
-
-int dsi_pll_div_prepare(struct clk *c)
-{
-	struct div_clk *div = to_div_clk(c);
-	/* Restore the divider's value */
-	return div->ops->set_div(div, div->data.div);
-}
-
-int dsi_pll_mux_prepare(struct clk *c)
-{
-	struct mux_clk *mux = to_mux_clk(c);
-	int i, rc, sel = 0;
-	struct mdss_pll_resources *dsi_pll_res = mux->priv;
-
-	rc = mdss_pll_resource_enable(dsi_pll_res, true);
-	if (rc) {
-		pr_err("Failed to enable mdss dsi pll resources\n");
-		return rc;
-	}
-
-	for (i = 0; i < mux->num_parents; i++)
-		if (mux->parents[i].src == c->parent) {
-			sel = mux->parents[i].sel;
-			break;
-		}
-
-	if (i == mux->num_parents) {
-		pr_err("Failed to select the parent clock\n");
-		rc = -EINVAL;
-		goto error;
-	}
-
-	/* Restore the mux source select value */
-	rc = mux->ops->set_mux_sel(mux, sel);
-
-error:
-	mdss_pll_resource_enable(dsi_pll_res, false);
-	return rc;
-}
-
-static int fixed_4div_set_div(struct div_clk *clk, int div)
-{
-	int rc;
-	struct mdss_pll_resources *dsi_pll_res = clk->priv;
-
-	rc = mdss_pll_resource_enable(dsi_pll_res, true);
-	if (rc) {
-		pr_err("Failed to enable mdss dsi pll resources\n");
-		return rc;
-	}
-
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-				DSI_PHY_PLL_UNIPHY_PLL_POSTDIV2_CFG, (div - 1));
-
-	mdss_pll_resource_enable(dsi_pll_res, false);
-	return rc;
-}
-
-static int fixed_4div_get_div(struct div_clk *clk)
-{
-	int div = 0, rc;
-	struct mdss_pll_resources *dsi_pll_res = clk->priv;
-
-	rc = mdss_pll_resource_enable(dsi_pll_res, true);
-	if (rc) {
-		pr_err("Failed to enable mdss dsi pll resources\n");
-		return rc;
-	}
-
-	div = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
-				DSI_PHY_PLL_UNIPHY_PLL_POSTDIV2_CFG);
-
-	mdss_pll_resource_enable(dsi_pll_res, false);
-	return div + 1;
-}
-
-static int digital_set_div(struct div_clk *clk, int div)
-{
-	int rc;
-	struct mdss_pll_resources *dsi_pll_res = clk->priv;
-
-	rc = mdss_pll_resource_enable(dsi_pll_res, true);
-	if (rc) {
-		pr_err("Failed to enable mdss dsi pll resources\n");
-		return rc;
-	}
-
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-				DSI_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG, (div - 1));
-
-	mdss_pll_resource_enable(dsi_pll_res, false);
-	return rc;
-}
-
-static int digital_get_div(struct div_clk *clk)
-{
-	int div = 0, rc;
-	struct mdss_pll_resources *dsi_pll_res = clk->priv;
-
-	rc = mdss_pll_resource_enable(dsi_pll_res, true);
-	if (rc) {
-		pr_err("Failed to enable mdss dsi pll resources\n");
-		return rc;
-	}
-
-	div = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
-					DSI_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG);
-
-	mdss_pll_resource_enable(dsi_pll_res, false);
-	return div + 1;
-}
-
-static int analog_set_div(struct div_clk *clk, int div)
-{
-	int rc;
-	struct mdss_pll_resources *dsi_pll_res = clk->priv;
-
-	rc = mdss_pll_resource_enable(dsi_pll_res, true);
-	if (rc) {
-		pr_err("Failed to enable mdss dsi pll resources\n");
-		return rc;
-	}
-
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-				DSI_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG, div - 1);
-
-	mdss_pll_resource_enable(dsi_pll_res, false);
-	return rc;
-}
-
-static int analog_get_div(struct div_clk *clk)
-{
-	int div = 0, rc;
-	struct mdss_pll_resources *dsi_pll_res = clk->priv;
-
-	rc = mdss_pll_resource_enable(clk->priv, true);
-	if (rc) {
-		pr_err("Failed to enable mdss dsi pll resources\n");
-		return rc;
-	}
-
-	div = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
-		DSI_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG) + 1;
-
-	mdss_pll_resource_enable(dsi_pll_res, false);
-
-	return div;
-}
-
-static int dsi_pll_lock_status(struct mdss_pll_resources *dsi_pll_res)
-{
-	u32 status;
-	int pll_locked;
-
-	/* poll for PLL ready status */
-	if (readl_poll_timeout_noirq((dsi_pll_res->pll_base +
-			DSI_PHY_PLL_UNIPHY_PLL_STATUS),
-			status,
-			((status & BIT(0)) == 1),
-			DSI_PLL_POLL_MAX_READS,
-			DSI_PLL_POLL_TIMEOUT_US)) {
-		pr_debug("DSI PLL status=%x failed to Lock\n", status);
-		pll_locked = 0;
-	} else {
-		pll_locked = 1;
-	}
-
-	return pll_locked;
-}
-
 static void dsi_pll_software_reset(struct mdss_pll_resources *dsi_pll_res)
 {
 	/*
@@ -311,21 +58,27 @@
 	udelay(1);
 }
 
-static void dsi_pll_toggle_lock_detect(struct mdss_pll_resources *dsi_pll_res)
+static int vco_set_rate_hpm(struct clk *c, unsigned long rate)
 {
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base, DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
-		0x0d);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base, DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
-		0x0c);
-	udelay(1);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base, DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
-		0x0d);
+	int rc;
+	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
+	struct mdss_pll_resources *dsi_pll_res = vco->priv;
+
+	rc = mdss_pll_resource_enable(dsi_pll_res, true);
+	if (rc) {
+		pr_err("Failed to enable mdss dsi pll resources\n");
+		return rc;
+	}
+
+	rc = vco_set_rate(vco, rate);
+
+	mdss_pll_resource_enable(dsi_pll_res, false);
+	return rc;
 }
 
 static int dsi_pll_enable_seq_8974(struct mdss_pll_resources *dsi_pll_res)
 {
 	int i, rc = 0;
-	u32 max_reads, timeout_us;
 	int pll_locked;
 
 	dsi_pll_software_reset(dsi_pll_res);
@@ -355,9 +108,6 @@
 		udelay(100);
 		MDSS_PLL_REG_W(dsi_pll_res->pll_base,
 				DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x0d);
-		/* poll for PLL ready status */
-		max_reads = 5;
-		timeout_us = 100;
 
 		pll_locked = dsi_pll_lock_status(dsi_pll_res);
 		if (pll_locked)
@@ -399,522 +149,10 @@
 	return rc;
 }
 
-static int dsi_pll_enable_seq_m(struct mdss_pll_resources *dsi_pll_res)
-{
-	int i = 0;
-	int pll_locked = 0;
-
-	dsi_pll_software_reset(dsi_pll_res);
-
-	/*
-	 * Add hardware recommended delays between register writes for
-	 * the updates to take effect. These delays are necessary for the
-	 * PLL to successfully lock
-	 */
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG1, 0x34);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
-	udelay(200);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
-	udelay(200);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
-	udelay(600);
-
-	dsi_pll_toggle_lock_detect(dsi_pll_res);
-	pll_locked = dsi_pll_lock_status(dsi_pll_res);
-	for (i = 0; (i < DSI_PLL_SEQ_M_MAX_COUNTER) && !pll_locked; i++) {
-		MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG, 0x00);
-		udelay(50);
-		MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-				DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
-		udelay(100);
-		MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-				DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
-		udelay(600);
-		dsi_pll_toggle_lock_detect(dsi_pll_res);
-		pll_locked = dsi_pll_lock_status(dsi_pll_res);
-	}
-
-	if (pll_locked)
-		pr_debug("PLL Locked at attempt #%d\n", i);
-	else
-		pr_debug("PLL failed to lock after %d attempt(s)\n", i);
-
-	return pll_locked ? 0 : -EINVAL;
-}
-
-static int dsi_pll_enable_seq_d(struct mdss_pll_resources *dsi_pll_res)
-{
-	int pll_locked = 0;
-
-	dsi_pll_software_reset(dsi_pll_res);
-
-	/*
-	 * Add hardware recommended delays between register writes for
-	 * the updates to take effect. These delays are necessary for the
-	 * PLL to successfully lock
-	 */
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG, 0x00);
-	udelay(50);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
-	udelay(200);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
-	udelay(200);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x07);
-	udelay(200);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
-	udelay(200);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x07);
-	udelay(200);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
-	udelay(600);
-
-	dsi_pll_toggle_lock_detect(dsi_pll_res);
-	pll_locked = dsi_pll_lock_status(dsi_pll_res);
-	pr_debug("PLL status = %s\n", pll_locked ? "Locked" : "Unlocked");
-
-	return pll_locked ? 0 : -EINVAL;
-}
-
-static int dsi_pll_enable_seq_f1(struct mdss_pll_resources *dsi_pll_res)
-{
-	int pll_locked = 0;
-
-	dsi_pll_software_reset(dsi_pll_res);
-
-	/*
-	 * Add hardware recommended delays between register writes for
-	 * the updates to take effect. These delays are necessary for the
-	 * PLL to successfully lock
-	 */
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG, 0x00);
-	udelay(50);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
-	udelay(200);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
-	udelay(200);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
-	udelay(200);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0d);
-	udelay(200);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
-	udelay(600);
-
-	dsi_pll_toggle_lock_detect(dsi_pll_res);
-	pll_locked = dsi_pll_lock_status(dsi_pll_res);
-	pr_debug("PLL status = %s\n", pll_locked ? "Locked" : "Unlocked");
-
-	return pll_locked ? 0 : -EINVAL;
-}
-
-static int dsi_pll_enable_seq_c(struct mdss_pll_resources *dsi_pll_res)
-{
-	int pll_locked = 0;
-
-	dsi_pll_software_reset(dsi_pll_res);
-
-	/*
-	 * Add hardware recommended delays between register writes for
-	 * the updates to take effect. These delays are necessary for the
-	 * PLL to successfully lock
-	 */
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG, 0x00);
-	udelay(50);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
-	udelay(200);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
-	udelay(200);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
-	udelay(600);
-
-	dsi_pll_toggle_lock_detect(dsi_pll_res);
-	pll_locked = dsi_pll_lock_status(dsi_pll_res);
-	pr_debug("PLL status = %s\n", pll_locked ? "Locked" : "Unlocked");
-
-	return pll_locked ? 0 : -EINVAL;
-}
-
-static int dsi_pll_enable_seq_e(struct mdss_pll_resources *dsi_pll_res)
-{
-	int pll_locked = 0;
-
-	dsi_pll_software_reset(dsi_pll_res);
-
-	/*
-	 * Add hardware recommended delays between register writes for
-	 * the updates to take effect. These delays are necessary for the
-	 * PLL to successfully lock
-	 */
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG, 0x00);
-	udelay(50);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
-	udelay(200);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
-	udelay(200);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0d);
-	udelay(1);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
-	udelay(600);
-
-	dsi_pll_toggle_lock_detect(dsi_pll_res);
-	pll_locked = dsi_pll_lock_status(dsi_pll_res);
-	pr_debug("PLL status = %s\n", pll_locked ? "Locked" : "Unlocked");
-
-	return pll_locked ? 0 : -EINVAL;
-}
-
-static int dsi_pll_enable(struct clk *c)
-{
-	int i, rc;
-	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
-	struct mdss_pll_resources *dsi_pll_res = vco->priv;
-
-	rc = mdss_pll_resource_enable(dsi_pll_res, true);
-	if (rc) {
-		pr_err("Failed to enable mdss dsi pll resources\n");
-		return rc;
-	}
-
-	/* Try all enable sequences until one succeeds */
-	for (i = 0; i < vco->pll_en_seq_cnt; i++) {
-		rc = vco->pll_enable_seqs[i](dsi_pll_res);
-		pr_debug("DSI PLL %s after sequence #%d\n",
-			rc ? "unlocked" : "locked", i + 1);
-		if (!rc)
-			break;
-	}
-
-	if (rc) {
-		mdss_pll_resource_enable(dsi_pll_res, false);
-		pr_err("DSI PLL failed to lock\n");
-	}
-	dsi_pll_res->pll_on = true;
-
-	return rc;
-}
-
-static void dsi_pll_disable(struct clk *c)
-{
-	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
-	struct mdss_pll_resources *dsi_pll_res = vco->priv;
-
-	if (!dsi_pll_res->pll_on &&
-		mdss_pll_resource_enable(dsi_pll_res, true)) {
-		pr_err("Failed to enable mdss dsi pll resources\n");
-		return;
-	}
-
-	dsi_pll_res->handoff_resources = false;
-
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-				DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x00);
-
-	mdss_pll_resource_enable(dsi_pll_res, false);
-	dsi_pll_res->pll_on = false;
-
-	pr_debug("DSI PLL Disabled\n");
-}
-
-static int vco_set_rate(struct clk *c, unsigned long rate)
-{
-	s64 vco_clk_rate = rate;
-	s32 rem;
-	s64 refclk_cfg, frac_n_mode, ref_doubler_en_b;
-	s64 ref_clk_to_pll, div_fbx1000, frac_n_value;
-	s64 sdm_cfg0, sdm_cfg1, sdm_cfg2, sdm_cfg3;
-	s64 gen_vco_clk, cal_cfg10, cal_cfg11;
-	u32 res;
-	int i, rc;
-	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
-	struct mdss_pll_resources *dsi_pll_res = vco->priv;
-
-	rc = mdss_pll_resource_enable(dsi_pll_res, true);
-	if (rc) {
-		pr_err("Failed to enable mdss dsi pll resources\n");
-		return rc;
-	}
-
-	/* Configure the Loop filter resistance */
-	for (i = 0; i < vco->lpfr_lut_size; i++)
-		if (vco_clk_rate <= vco->lpfr_lut[i].vco_rate)
-			break;
-	if (i == vco->lpfr_lut_size) {
-		pr_err("unable to get loop filter resistance. vco=%ld\n", rate);
-		rc = -EINVAL;
-		goto error;
-	}
-	res = vco->lpfr_lut[i].r;
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-				DSI_PHY_PLL_UNIPHY_PLL_LPFR_CFG, res);
-
-	/* Loop filter capacitance values : c1 and c2 */
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-				DSI_PHY_PLL_UNIPHY_PLL_LPFC1_CFG, 0x70);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-				DSI_PHY_PLL_UNIPHY_PLL_LPFC2_CFG, 0x15);
-
-	div_s64_rem(vco_clk_rate, vco->ref_clk_rate, &rem);
-	if (rem) {
-		refclk_cfg = 0x1;
-		frac_n_mode = 1;
-		ref_doubler_en_b = 0;
-	} else {
-		refclk_cfg = 0x0;
-		frac_n_mode = 0;
-		ref_doubler_en_b = 1;
-	}
-
-	pr_debug("refclk_cfg = %lld\n", refclk_cfg);
-
-	ref_clk_to_pll = ((vco->ref_clk_rate * 2 * (refclk_cfg))
-			  + (ref_doubler_en_b * vco->ref_clk_rate));
-	div_fbx1000 = div_s64((vco_clk_rate * 1000), ref_clk_to_pll);
-
-	div_s64_rem(div_fbx1000, 1000, &rem);
-	frac_n_value = div_s64((rem * (1 << 16)), 1000);
-	gen_vco_clk = div_s64(div_fbx1000 * ref_clk_to_pll, 1000);
-
-	pr_debug("ref_clk_to_pll = %lld\n", ref_clk_to_pll);
-	pr_debug("div_fb = %lld\n", div_fbx1000);
-	pr_debug("frac_n_value = %lld\n", frac_n_value);
-
-	pr_debug("Generated VCO Clock: %lld\n", gen_vco_clk);
-	rem = 0;
-	if (frac_n_mode) {
-		sdm_cfg0 = (0x0 << 5);
-		sdm_cfg0 |= (0x0 & 0x3f);
-		sdm_cfg1 = (div_s64(div_fbx1000, 1000) & 0x3f) - 1;
-		sdm_cfg3 = div_s64_rem(frac_n_value, 256, &rem);
-		sdm_cfg2 = rem;
-	} else {
-		sdm_cfg0 = (0x1 << 5);
-		sdm_cfg0 |= (div_s64(div_fbx1000, 1000) & 0x3f) - 1;
-		sdm_cfg1 = (0x0 & 0x3f);
-		sdm_cfg2 = 0;
-		sdm_cfg3 = 0;
-	}
-
-	pr_debug("sdm_cfg0=%lld\n", sdm_cfg0);
-	pr_debug("sdm_cfg1=%lld\n", sdm_cfg1);
-	pr_debug("sdm_cfg2=%lld\n", sdm_cfg2);
-	pr_debug("sdm_cfg3=%lld\n", sdm_cfg3);
-
-	cal_cfg11 = div_s64_rem(gen_vco_clk, 256 * 1000000, &rem);
-	cal_cfg10 = rem / 1000000;
-	pr_debug("cal_cfg10=%lld, cal_cfg11=%lld\n", cal_cfg10, cal_cfg11);
-
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_CHGPUMP_CFG, 0x02);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG3, 0x2b);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG4, 0x66);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x0d);
-
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-		DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG1, (u32)(sdm_cfg1 & 0xff));
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-		DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG2, (u32)(sdm_cfg2 & 0xff));
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-		DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG3, (u32)(sdm_cfg3 & 0xff));
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-				DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG4, 0x00);
-
-	/* Add hardware recommended delay for correct PLL configuration */
-	udelay(1);
-
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_REFCLK_CFG, (u32)refclk_cfg);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG, 0x00);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_VCOLPF_CFG, 0x71);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0, (u32)sdm_cfg0);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG0, 0x12);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG6, 0x30);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG7, 0x00);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG8, 0x60);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG9, 0x00);
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-		DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG10, (u32)(cal_cfg10 & 0xff));
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-		DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG11, (u32)(cal_cfg11 & 0xff));
-	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_EFUSE_CFG, 0x20);
-
-error:
-	mdss_pll_resource_enable(dsi_pll_res, false);
-	return rc;
-}
-
-static long vco_round_rate(struct clk *c, unsigned long rate)
-{
-	unsigned long rrate = rate;
-	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
-
-	if (rate < vco->min_rate)
-		rrate = vco->min_rate;
-	if (rate > vco->max_rate)
-		rrate = vco->max_rate;
-
-	return rrate;
-}
-
-static unsigned long vco_get_rate(struct clk *c)
-{
-	u32 sdm0, doubler, sdm_byp_div;
-	u64 vco_rate;
-	u32 sdm_dc_off, sdm_freq_seed, sdm2, sdm3;
-	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
-	u64 ref_clk = vco->ref_clk_rate;
-	int rc;
-	struct mdss_pll_resources *dsi_pll_res = vco->priv;
-
-	rc = mdss_pll_resource_enable(dsi_pll_res, true);
-	if (rc) {
-		pr_err("Failed to enable mdss dsi pll resources\n");
-		return rc;
-	}
-
-	/* Check to see if the ref clk doubler is enabled */
-	doubler = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
-				 DSI_PHY_PLL_UNIPHY_PLL_REFCLK_CFG) & BIT(0);
-	ref_clk += (doubler * vco->ref_clk_rate);
-
-	/* see if it is integer mode or sdm mode */
-	sdm0 = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
-					DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0);
-	if (sdm0 & BIT(6)) {
-		/* integer mode */
-		sdm_byp_div = (MDSS_PLL_REG_R(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0) & 0x3f) + 1;
-		vco_rate = ref_clk * sdm_byp_div;
-	} else {
-		/* sdm mode */
-		sdm_dc_off = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG1) & 0xFF;
-		pr_debug("sdm_dc_off = %d\n", sdm_dc_off);
-		sdm2 = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG2) & 0xFF;
-		sdm3 = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
-			DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG3) & 0xFF;
-		sdm_freq_seed = (sdm3 << 8) | sdm2;
-		pr_debug("sdm_freq_seed = %d\n", sdm_freq_seed);
-
-		vco_rate = (ref_clk * (sdm_dc_off + 1)) +
-			mult_frac(ref_clk, sdm_freq_seed, BIT(16));
-		pr_debug("vco rate = %lld", vco_rate);
-	}
-
-	pr_debug("returning vco rate = %lu\n", (unsigned long)vco_rate);
-
-	mdss_pll_resource_enable(dsi_pll_res, false);
-
-	return (unsigned long)vco_rate;
-}
-
-static enum handoff vco_handoff(struct clk *c)
-{
-	int rc;
-	enum handoff ret = HANDOFF_DISABLED_CLK;
-	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
-	struct mdss_pll_resources *dsi_pll_res = vco->priv;
-
-	rc = mdss_pll_resource_enable(dsi_pll_res, true);
-	if (rc) {
-		pr_err("Failed to enable mdss dsi pll resources\n");
-		return ret;
-	}
-
-	if (dsi_pll_lock_status(dsi_pll_res)) {
-		dsi_pll_res->handoff_resources = true;
-		dsi_pll_res->pll_on = true;
-		c->rate = vco_get_rate(c);
-		ret = HANDOFF_ENABLED_CLK;
-	} else {
-		mdss_pll_resource_enable(dsi_pll_res, false);
-	}
-
-	return ret;
-}
-
-static int vco_prepare(struct clk *c)
-{
-	int rc = 0;
-	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
-	struct mdss_pll_resources *dsi_pll_res = vco->priv;
-
-	if (!dsi_pll_res) {
-		pr_err("Dsi pll resources are not available\n");
-		return -EINVAL;
-	}
-
-	if ((dsi_pll_res->vco_cached_rate != 0)
-	    && (dsi_pll_res->vco_cached_rate == c->rate)) {
-		rc = vco_set_rate(c, dsi_pll_res->vco_cached_rate);
-		if (rc) {
-			pr_err("vco_set_rate failed. rc=%d\n", rc);
-			goto error;
-		}
-	}
-
-	rc = dsi_pll_enable(c);
-
-error:
-	return rc;
-}
-
-static void vco_unprepare(struct clk *c)
-{
-	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
-	struct mdss_pll_resources *dsi_pll_res = vco->priv;
-
-	if (!dsi_pll_res) {
-		pr_err("Dsi pll resources are not available\n");
-		return;
-	}
-
-	dsi_pll_res->vco_cached_rate = c->rate;
-	dsi_pll_disable(c);
-}
-
 /* Op structures */
 
 static const struct clk_ops clk_ops_dsi_vco = {
-	.set_rate = vco_set_rate,
+	.set_rate = vco_set_rate_hpm,
 	.round_rate = vco_round_rate,
 	.handoff = vco_handoff,
 	.prepare = vco_prepare,
@@ -959,7 +197,7 @@
 	},
 };
 
-static struct div_clk analog_postdiv_clk = {
+static struct div_clk analog_postdiv_clk_8974 = {
 	.data = {
 		.max_div = 255,
 		.min_div = 1,
@@ -970,11 +208,11 @@
 		.dbg_name = "analog_postdiv_clk",
 		.ops = &analog_postdiv_clk_ops,
 		.flags = CLKFLAG_NO_RATE_CACHE,
-		CLK_INIT(analog_postdiv_clk.c),
+		CLK_INIT(analog_postdiv_clk_8974.c),
 	},
 };
 
-static struct div_clk indirect_path_div2_clk = {
+static struct div_clk indirect_path_div2_clk_8974 = {
 	.ops = &fixed_2div_ops,
 	.data = {
 		.div = 2,
@@ -982,15 +220,15 @@
 		.max_div = 2,
 	},
 	.c = {
-		.parent = &analog_postdiv_clk.c,
+		.parent = &analog_postdiv_clk_8974.c,
 		.dbg_name = "indirect_path_div2_clk",
 		.ops = &clk_ops_div,
 		.flags = CLKFLAG_NO_RATE_CACHE,
-		CLK_INIT(indirect_path_div2_clk.c),
+		CLK_INIT(indirect_path_div2_clk_8974.c),
 	},
 };
 
-struct div_clk pixel_clk_src = {
+static struct div_clk pixel_clk_src_8974 = {
 	.data = {
 		.max_div = 255,
 		.min_div = 1,
@@ -998,105 +236,72 @@
 	.ops = &digital_postdiv_ops,
 	.c = {
 		.parent = &dsi_vco_clk_8974.c,
-		.dbg_name = "pixel_clk_src",
+		.dbg_name = "pixel_clk_src_8974",
 		.ops = &pixel_clk_src_ops,
 		.flags = CLKFLAG_NO_RATE_CACHE,
-		CLK_INIT(pixel_clk_src.c),
+		CLK_INIT(pixel_clk_src_8974.c),
 	},
 };
 
-struct mux_clk byte_mux = {
+static struct mux_clk byte_mux_8974 = {
 	.num_parents = 2,
 	.parents = (struct clk_src[]){
 		{&dsi_vco_clk_8974.c, 0},
-		{&indirect_path_div2_clk.c, 1},
+		{&indirect_path_div2_clk_8974.c, 1},
 	},
 	.ops = &byte_mux_ops,
 	.c = {
 		.parent = &dsi_vco_clk_8974.c,
-		.dbg_name = "byte_mux",
+		.dbg_name = "byte_mux_8974",
 		.ops = &byte_mux_clk_ops,
-		CLK_INIT(byte_mux.c),
+		CLK_INIT(byte_mux_8974.c),
 	},
 };
 
-struct div_clk byte_clk_src = {
+static struct div_clk byte_clk_src_8974 = {
 	.ops = &fixed_4div_ops,
 	.data = {
 		.min_div = 4,
 		.max_div = 4,
 	},
 	.c = {
-		.parent = &byte_mux.c,
-		.dbg_name = "byte_clk_src",
+		.parent = &byte_mux_8974.c,
+		.dbg_name = "byte_clk_src_8974",
 		.ops = &byte_clk_src_ops,
-		CLK_INIT(byte_clk_src.c),
-	},
-};
-
-struct dsi_pll_vco_clk dsi_vco_clk_8916 = {
-	.ref_clk_rate = 19200000,
-	.min_rate = 350000000,
-	.max_rate = 750000000,
-	.pll_en_seq_cnt = 7,
-	.pll_enable_seqs[0] = dsi_pll_enable_seq_m,
-	.pll_enable_seqs[1] = dsi_pll_enable_seq_m,
-	.pll_enable_seqs[2] = dsi_pll_enable_seq_d,
-	.pll_enable_seqs[3] = dsi_pll_enable_seq_d,
-	.pll_enable_seqs[4] = dsi_pll_enable_seq_f1,
-	.pll_enable_seqs[5] = dsi_pll_enable_seq_c,
-	.pll_enable_seqs[6] = dsi_pll_enable_seq_e,
-	.lpfr_lut_size = 10,
-	.lpfr_lut = lpfr_lut_struct,
-	.c = {
-		.dbg_name = "dsi_vco_clk_8916",
-		.ops = &clk_ops_dsi_vco,
-		CLK_INIT(dsi_vco_clk_8916.c),
+		CLK_INIT(byte_clk_src_8974.c),
 	},
 };
 
 static struct clk_lookup mdss_dsi_pllcc_8974[] = {
-	CLK_LOOKUP_OF("pixel_src", pixel_clk_src,
+	CLK_LOOKUP_OF("pixel_src", pixel_clk_src_8974,
 						"fd8c0000.qcom,mmsscc-mdss"),
-	CLK_LOOKUP_OF("byte_src", byte_clk_src,
+	CLK_LOOKUP_OF("byte_src", byte_clk_src_8974,
 						"fd8c0000.qcom,mmsscc-mdss"),
 };
 
-static struct clk_lookup mdss_dsi_pllcc_8916[] = {
-	CLK_LIST(pixel_clk_src),
-	CLK_LIST(byte_clk_src),
-};
-
-int dsi_pll_clock_register(struct platform_device *pdev,
+int dsi_pll_clock_register_hpm(struct platform_device *pdev,
 				struct mdss_pll_resources *pll_res)
 {
 	int rc;
-	const char *compatible_stream = NULL;
-	int compat_len = 0;
 
-	if (!pdev || !pll_res || !pdev->dev.of_node) {
+	if (!pdev || !pdev->dev.of_node) {
 		pr_err("Invalid input parameters\n");
 		return -EINVAL;
 	}
 
-	compatible_stream = of_get_property(pdev->dev.of_node, "compatible",
-								&compat_len);
-	if (!compatible_stream || (compat_len <= 0)) {
-		pr_err("Invalid compatible string\n");
-		return -EINVAL;
-	}
-
 	if (!pll_res || !pll_res->pll_base) {
-		pr_err("Invalid input parameters\n");
+		pr_err("Invalid PLL resources\n");
 		return -EPROBE_DEFER;
 	}
 
 	/* Set client data to mux, div and vco clocks */
-	byte_clk_src.priv = pll_res;
-	pixel_clk_src.priv = pll_res;
-	byte_mux.priv = pll_res;
-	indirect_path_div2_clk.priv = pll_res;
-	analog_postdiv_clk.priv = pll_res;
+	byte_clk_src_8974.priv = pll_res;
+	pixel_clk_src_8974.priv = pll_res;
+	byte_mux_8974.priv = pll_res;
+	indirect_path_div2_clk_8974.priv = pll_res;
+	analog_postdiv_clk_8974.priv = pll_res;
+	dsi_vco_clk_8974.priv = pll_res;
+	pll_res->vco_delay = VCO_DELAY_USEC;
 
 	/* Set clock source operations */
 	pixel_clk_src_ops = clk_ops_slave_div;
@@ -1111,20 +316,7 @@
 	byte_mux_clk_ops = clk_ops_gen_mux;
 	byte_mux_clk_ops.prepare = dsi_pll_mux_prepare;
 
-	if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_8916")) {
-		dsi_vco_clk_8916.priv = pll_res;
-		analog_postdiv_clk.c.parent = &dsi_vco_clk_8916.c;
-		byte_mux.parents[0] = (struct clk_src) {&dsi_vco_clk_8916.c, 0};
-		byte_mux.c.parent = &dsi_vco_clk_8916.c;
-		pixel_clk_src.c.parent = &dsi_vco_clk_8916.c;
-		rc = of_msm_clock_register(pdev->dev.of_node,
-			mdss_dsi_pllcc_8916, ARRAY_SIZE(mdss_dsi_pllcc_8916));
-		if (rc) {
-			pr_err("Clock register failed\n");
-			rc = -EPROBE_DEFER;
-		}
-	} else if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_8974")) {
-		dsi_vco_clk_8974.priv = pll_res;
+	if (pll_res->target_id == MDSS_PLL_TARGET_8974) {
 		rc = of_msm_clock_register(pdev->dev.of_node,
 			mdss_dsi_pllcc_8974, ARRAY_SIZE(mdss_dsi_pllcc_8974));
 		if (rc) {
@@ -1132,7 +324,7 @@
 			rc = -EPROBE_DEFER;
 		}
 	} else {
-		pr_err("Invalid compatible string\n");
+		pr_err("Invalid target ID\n");
 		rc = -EINVAL;
 	}
 
diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-28lpm.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-28lpm.c
new file mode 100644
index 0000000..0f6ded0
--- /dev/null
+++ b/drivers/clk/qcom/mdss/mdss-dsi-pll-28lpm.c
@@ -0,0 +1,304 @@
+/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(fmt)	"%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/clk/msm-clk.h>
+#include <linux/clk/msm-clock-generic.h>
+#include <linux/clk/msm-clk-provider.h>
+#include <dt-bindings/clock/msm-clocks-8916.h>
+
+#include "mdss-pll.h"
+#include "mdss-dsi-pll.h"
+
+#define VCO_DELAY_USEC			1000
+
+static struct clk_div_ops fixed_2div_ops;
+static const struct clk_ops byte_mux_clk_ops;
+static const struct clk_ops pixel_clk_src_ops;
+static const struct clk_ops byte_clk_src_ops;
+static const struct clk_ops analog_postdiv_clk_ops;
+static struct lpfr_cfg lpfr_lut_struct[] = {
+	{479500000, 8},
+	{480000000, 11},
+	{575500000, 8},
+	{576000000, 12},
+	{610500000, 8},
+	{659500000, 9},
+	{671500000, 10},
+	{672000000, 14},
+	{708500000, 10},
+	{750000000, 11},
+};
+
+static int vco_set_rate_lpm(struct clk *c, unsigned long rate)
+{
+	int rc;
+	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
+	struct mdss_pll_resources *dsi_pll_res = vco->priv;
+
+	rc = mdss_pll_resource_enable(dsi_pll_res, true);
+	if (rc) {
+		pr_err("Failed to enable mdss dsi pll resources\n");
+		return rc;
+	}
+
+	/*
+	 * DSI PLL software reset. Add HW recommended delays after toggling
+	 * the software reset bit off and back on.
+	 */
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x01);
+	udelay(1000);
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x00);
+	udelay(1000);
+
+	rc = vco_set_rate(vco, rate);
+
+	mdss_pll_resource_enable(dsi_pll_res, false);
+	return rc;
+}
+
+static int dsi_pll_enable_seq_8916(struct mdss_pll_resources *dsi_pll_res)
+{
+	int pll_locked = 0;
+
+	/*
+	 * DSI PLL software reset. Add HW recommended delays after toggling
+	 * the software reset bit off and back on.
+	 */
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x01);
+	ndelay(500);
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x00);
+
+	/*
+	 * PLL power up sequence.
+	 * Add necessary delays recommended by hardware.
+	 */
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG1, 0x34);
+	ndelay(500);
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
+	ndelay(500);
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
+	ndelay(500);
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
+	ndelay(500);
+
+	/* DSI PLL toggle lock detect setting */
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x04);
+	ndelay(500);
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x05);
+	udelay(512);
+
+	pll_locked = dsi_pll_lock_status(dsi_pll_res);
+
+	if (pll_locked)
+		pr_debug("PLL Locked\n");
+	else
+		pr_err("PLL failed to lock\n");
+
+	return pll_locked ? 0 : -EINVAL;
+}
+
+/* Op structures */
+
+static const struct clk_ops clk_ops_dsi_vco = {
+	.set_rate = vco_set_rate_lpm,
+	.round_rate = vco_round_rate,
+	.handoff = vco_handoff,
+	.prepare = vco_prepare,
+	.unprepare = vco_unprepare,
+};
+
+
+static struct clk_div_ops fixed_4div_ops = {
+	.set_div = fixed_4div_set_div,
+	.get_div = fixed_4div_get_div,
+};
+
+static struct clk_div_ops analog_postdiv_ops = {
+	.set_div = analog_set_div,
+	.get_div = analog_get_div,
+};
+
+static struct clk_div_ops digital_postdiv_ops = {
+	.set_div = digital_set_div,
+	.get_div = digital_get_div,
+};
+
+static struct clk_mux_ops byte_mux_ops = {
+	.set_mux_sel = set_byte_mux_sel,
+	.get_mux_sel = get_byte_mux_sel,
+};
+
+static struct dsi_pll_vco_clk dsi_vco_clk_8916 = {
+	.ref_clk_rate = 19200000,
+	.min_rate = 350000000,
+	.max_rate = 750000000,
+	.pll_en_seq_cnt = 1,
+	.pll_enable_seqs[0] = dsi_pll_enable_seq_8916,
+	.lpfr_lut_size = 10,
+	.lpfr_lut = lpfr_lut_struct,
+	.c = {
+		.dbg_name = "dsi_vco_clk_8916",
+		.ops = &clk_ops_dsi_vco,
+		CLK_INIT(dsi_vco_clk_8916.c),
+	},
+};
+
+static struct div_clk analog_postdiv_clk_8916 = {
+	.data = {
+		.max_div = 255,
+		.min_div = 1,
+	},
+	.ops = &analog_postdiv_ops,
+	.c = {
+		.parent = &dsi_vco_clk_8916.c,
+		.dbg_name = "analog_postdiv_clk",
+		.ops = &analog_postdiv_clk_ops,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(analog_postdiv_clk_8916.c),
+	},
+};
+
+static struct div_clk indirect_path_div2_clk_8916 = {
+	.ops = &fixed_2div_ops,
+	.data = {
+		.div = 2,
+		.min_div = 2,
+		.max_div = 2,
+	},
+	.c = {
+		.parent = &analog_postdiv_clk_8916.c,
+		.dbg_name = "indirect_path_div2_clk",
+		.ops = &clk_ops_div,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(indirect_path_div2_clk_8916.c),
+	},
+};
+
+static struct div_clk pixel_clk_src = {
+	.data = {
+		.max_div = 255,
+		.min_div = 1,
+	},
+	.ops = &digital_postdiv_ops,
+	.c = {
+		.parent = &dsi_vco_clk_8916.c,
+		.dbg_name = "pixel_clk_src_8916",
+		.ops = &pixel_clk_src_ops,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(pixel_clk_src.c),
+	},
+};
+
+static struct mux_clk byte_mux_8916 = {
+	.num_parents = 2,
+	.parents = (struct clk_src[]){
+		{&dsi_vco_clk_8916.c, 0},
+		{&indirect_path_div2_clk_8916.c, 1},
+	},
+	.ops = &byte_mux_ops,
+	.c = {
+		.parent = &dsi_vco_clk_8916.c,
+		.dbg_name = "byte_mux_8916",
+		.ops = &byte_mux_clk_ops,
+		CLK_INIT(byte_mux_8916.c),
+	},
+};
+
+static struct div_clk byte_clk_src = {
+	.ops = &fixed_4div_ops,
+	.data = {
+		.min_div = 4,
+		.max_div = 4,
+	},
+	.c = {
+		.parent = &byte_mux_8916.c,
+		.dbg_name = "byte_clk_src_8916",
+		.ops = &byte_clk_src_ops,
+		CLK_INIT(byte_clk_src.c),
+	},
+};
+
+static struct clk_lookup mdss_dsi_pllcc_8916[] = {
+	CLK_LIST(pixel_clk_src),
+	CLK_LIST(byte_clk_src),
+};
+
+int dsi_pll_clock_register_lpm(struct platform_device *pdev,
+				struct mdss_pll_resources *pll_res)
+{
+	int rc;
+
+	if (!pdev || !pdev->dev.of_node) {
+		pr_err("Invalid input parameters\n");
+		return -EINVAL;
+	}
+
+	if (!pll_res || !pll_res->pll_base) {
+		pr_err("Invalid PLL resources\n");
+		return -EPROBE_DEFER;
+	}
+
+	/* Set client data to mux, div and vco clocks */
+	byte_clk_src.priv = pll_res;
+	pixel_clk_src.priv = pll_res;
+	byte_mux_8916.priv = pll_res;
+	indirect_path_div2_clk_8916.priv = pll_res;
+	analog_postdiv_clk_8916.priv = pll_res;
+	dsi_vco_clk_8916.priv = pll_res;
+	pll_res->vco_delay = VCO_DELAY_USEC;
+
+	/* Set clock source operations */
+	pixel_clk_src_ops = clk_ops_slave_div;
+	pixel_clk_src_ops.prepare = dsi_pll_div_prepare;
+
+	analog_postdiv_clk_ops = clk_ops_div;
+	analog_postdiv_clk_ops.prepare = dsi_pll_div_prepare;
+
+	byte_clk_src_ops = clk_ops_div;
+	byte_clk_src_ops.prepare = dsi_pll_div_prepare;
+
+	byte_mux_clk_ops = clk_ops_gen_mux;
+	byte_mux_clk_ops.prepare = dsi_pll_mux_prepare;
+
+	if (pll_res->target_id == MDSS_PLL_TARGET_8916) {
+		rc = of_msm_clock_register(pdev->dev.of_node,
+			mdss_dsi_pllcc_8916, ARRAY_SIZE(mdss_dsi_pllcc_8916));
+		if (rc) {
+			pr_err("Clock register failed\n");
+			rc = -EPROBE_DEFER;
+		}
+	} else {
+		pr_err("Invalid target ID\n");
+		rc = -EINVAL;
+	}
+
+	if (!rc)
+		pr_info("Registered DSI PLL clocks successfully\n");
+
+	return rc;
+}
diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-util.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-util.c
new file mode 100644
index 0000000..fd27117
--- /dev/null
+++ b/drivers/clk/qcom/mdss/mdss-dsi-pll-util.c
@@ -0,0 +1,569 @@
+/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt)	"%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/iopoll.h>
+#include <linux/delay.h>
+#include <linux/clk/msm-clock-generic.h>
+
+#include "mdss-pll.h"
+#include "mdss-dsi-pll.h"
+
+#define DSI_PHY_PLL_UNIPHY_PLL_REFCLK_CFG	(0x0)
+#define DSI_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG	(0x0004)
+#define DSI_PHY_PLL_UNIPHY_PLL_CHGPUMP_CFG	(0x0008)
+#define DSI_PHY_PLL_UNIPHY_PLL_VCOLPF_CFG	(0x000C)
+#define DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG		(0x0010)
+#define DSI_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG	(0x0014)
+#define DSI_PHY_PLL_UNIPHY_PLL_POSTDIV2_CFG	(0x0024)
+#define DSI_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG	(0x0028)
+#define DSI_PHY_PLL_UNIPHY_PLL_LPFR_CFG		(0x002C)
+#define DSI_PHY_PLL_UNIPHY_PLL_LPFC1_CFG	(0x0030)
+#define DSI_PHY_PLL_UNIPHY_PLL_LPFC2_CFG	(0x0034)
+#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0		(0x0038)
+#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG1		(0x003C)
+#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG2		(0x0040)
+#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG3		(0x0044)
+#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG4		(0x0048)
+#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG0		(0x006C)
+#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG2		(0x0074)
+#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG3		(0x0078)
+#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG4		(0x007C)
+#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG5		(0x0080)
+#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG6		(0x0084)
+#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG7		(0x0088)
+#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG8		(0x008C)
+#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG9		(0x0090)
+#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG10	(0x0094)
+#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG11	(0x0098)
+#define DSI_PHY_PLL_UNIPHY_PLL_EFUSE_CFG	(0x009C)
+#define DSI_PHY_PLL_UNIPHY_PLL_STATUS		(0x00C0)
+
+#define DSI_PLL_POLL_MAX_READS			10
+#define DSI_PLL_POLL_TIMEOUT_US			50
+
+int set_byte_mux_sel(struct mux_clk *clk, int sel)
+{
+	struct mdss_pll_resources *dsi_pll_res = clk->priv;
+
+	pr_debug("byte mux set to %s mode\n", sel ? "indirect" : "direct");
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+				DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG, (sel << 1));
+
+	return 0;
+}
+
+int get_byte_mux_sel(struct mux_clk *clk)
+{
+	int mux_mode, rc;
+	struct mdss_pll_resources *dsi_pll_res = clk->priv;
+
+	rc = mdss_pll_resource_enable(dsi_pll_res, true);
+	if (rc) {
+		pr_err("Failed to enable mdss dsi pll resources\n");
+		return rc;
+	}
+
+	mux_mode = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
+				DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG) & BIT(1);
+
+	pr_debug("byte mux mode = %s", mux_mode ? "indirect" : "direct");
+	mdss_pll_resource_enable(dsi_pll_res, false);
+
+	return !!mux_mode;
+}
+
+int dsi_pll_div_prepare(struct clk *c)
+{
+	struct div_clk *div = to_div_clk(c);
+	/* Restore the divider's value */
+	return div->ops->set_div(div, div->data.div);
+}
+
+int dsi_pll_mux_prepare(struct clk *c)
+{
+	struct mux_clk *mux = to_mux_clk(c);
+	int i, rc, sel = 0;
+	struct mdss_pll_resources *dsi_pll_res = mux->priv;
+
+	rc = mdss_pll_resource_enable(dsi_pll_res, true);
+	if (rc) {
+		pr_err("Failed to enable mdss dsi pll resources\n");
+		return rc;
+	}
+
+	for (i = 0; i < mux->num_parents; i++)
+		if (mux->parents[i].src == c->parent) {
+			sel = mux->parents[i].sel;
+			break;
+		}
+
+	if (i == mux->num_parents) {
+		pr_err("Failed to select the parent clock\n");
+		rc = -EINVAL;
+		goto error;
+	}
+
+	/* Restore the mux source select value */
+	rc = mux->ops->set_mux_sel(mux, sel);
+
+error:
+	mdss_pll_resource_enable(dsi_pll_res, false);
+	return rc;
+}
+
+int fixed_4div_set_div(struct div_clk *clk, int div)
+{
+	int rc;
+	struct mdss_pll_resources *dsi_pll_res = clk->priv;
+
+	rc = mdss_pll_resource_enable(dsi_pll_res, true);
+	if (rc) {
+		pr_err("Failed to enable mdss dsi pll resources\n");
+		return rc;
+	}
+
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+				DSI_PHY_PLL_UNIPHY_PLL_POSTDIV2_CFG, (div - 1));
+
+	mdss_pll_resource_enable(dsi_pll_res, false);
+	return rc;
+}
+
+int fixed_4div_get_div(struct div_clk *clk)
+{
+	int div = 0, rc;
+	struct mdss_pll_resources *dsi_pll_res = clk->priv;
+
+	rc = mdss_pll_resource_enable(dsi_pll_res, true);
+	if (rc) {
+		pr_err("Failed to enable mdss dsi pll resources\n");
+		return rc;
+	}
+
+	div = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
+				DSI_PHY_PLL_UNIPHY_PLL_POSTDIV2_CFG);
+
+	mdss_pll_resource_enable(dsi_pll_res, false);
+	return div + 1;
+}
+
+int digital_set_div(struct div_clk *clk, int div)
+{
+	int rc;
+	struct mdss_pll_resources *dsi_pll_res = clk->priv;
+
+	rc = mdss_pll_resource_enable(dsi_pll_res, true);
+	if (rc) {
+		pr_err("Failed to enable mdss dsi pll resources\n");
+		return rc;
+	}
+
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+				DSI_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG, (div - 1));
+
+	mdss_pll_resource_enable(dsi_pll_res, false);
+	return rc;
+}
+
+int digital_get_div(struct div_clk *clk)
+{
+	int div = 0, rc;
+	struct mdss_pll_resources *dsi_pll_res = clk->priv;
+
+	rc = mdss_pll_resource_enable(dsi_pll_res, true);
+	if (rc) {
+		pr_err("Failed to enable mdss dsi pll resources\n");
+		return rc;
+	}
+
+	div = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
+					DSI_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG);
+
+	mdss_pll_resource_enable(dsi_pll_res, false);
+	return div + 1;
+}
+
+int analog_set_div(struct div_clk *clk, int div)
+{
+	int rc;
+	struct mdss_pll_resources *dsi_pll_res = clk->priv;
+
+	rc = mdss_pll_resource_enable(dsi_pll_res, true);
+	if (rc) {
+		pr_err("Failed to enable mdss dsi pll resources\n");
+		return rc;
+	}
+
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+				DSI_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG, div - 1);
+
+	mdss_pll_resource_enable(dsi_pll_res, false);
+	return rc;
+}
+
+int analog_get_div(struct div_clk *clk)
+{
+	int div = 0, rc;
+	struct mdss_pll_resources *dsi_pll_res = clk->priv;
+
+	rc = mdss_pll_resource_enable(clk->priv, true);
+	if (rc) {
+		pr_err("Failed to enable mdss dsi pll resources\n");
+		return rc;
+	}
+
+	div = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
+		DSI_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG) + 1;
+
+	mdss_pll_resource_enable(dsi_pll_res, false);
+
+	return div;
+}
+
+int dsi_pll_lock_status(struct mdss_pll_resources *dsi_pll_res)
+{
+	u32 status;
+	int pll_locked;
+
+	/* poll for PLL ready status */
+	if (readl_poll_timeout_noirq((dsi_pll_res->pll_base +
+			DSI_PHY_PLL_UNIPHY_PLL_STATUS),
+			status,
+			((status & BIT(0)) == 1),
+			DSI_PLL_POLL_MAX_READS,
+			DSI_PLL_POLL_TIMEOUT_US)) {
+		pr_debug("DSI PLL status=%x failed to Lock\n", status);
+		pll_locked = 0;
+	} else {
+		pll_locked = 1;
+	}
+
+	return pll_locked;
+}
+
+int vco_set_rate(struct dsi_pll_vco_clk *vco, unsigned long rate)
+{
+	s64 vco_clk_rate = rate;
+	s32 rem;
+	s64 refclk_cfg, frac_n_mode, ref_doubler_en_b;
+	s64 ref_clk_to_pll, div_fbx1000, frac_n_value;
+	s64 sdm_cfg0, sdm_cfg1, sdm_cfg2, sdm_cfg3;
+	s64 gen_vco_clk, cal_cfg10, cal_cfg11;
+	u32 res;
+	int i;
+	struct mdss_pll_resources *dsi_pll_res = vco->priv;
+
+	/* Configure the Loop filter resistance */
+	for (i = 0; i < vco->lpfr_lut_size; i++)
+		if (vco_clk_rate <= vco->lpfr_lut[i].vco_rate)
+			break;
+	if (i == vco->lpfr_lut_size) {
+		pr_err("unable to get loop filter resistance. vco=%ld\n", rate);
+		return -EINVAL;
+	}
+	res = vco->lpfr_lut[i].r;
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+				DSI_PHY_PLL_UNIPHY_PLL_LPFR_CFG, res);
+
+	/* Loop filter capacitance values : c1 and c2 */
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+				DSI_PHY_PLL_UNIPHY_PLL_LPFC1_CFG, 0x70);
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+				DSI_PHY_PLL_UNIPHY_PLL_LPFC2_CFG, 0x15);
+
+	div_s64_rem(vco_clk_rate, vco->ref_clk_rate, &rem);
+	if (rem) {
+		refclk_cfg = 0x1;
+		frac_n_mode = 1;
+		ref_doubler_en_b = 0;
+	} else {
+		refclk_cfg = 0x0;
+		frac_n_mode = 0;
+		ref_doubler_en_b = 1;
+	}
+
+	pr_debug("refclk_cfg = %lld\n", refclk_cfg);
+
+	ref_clk_to_pll = ((vco->ref_clk_rate * 2 * (refclk_cfg))
+			  + (ref_doubler_en_b * vco->ref_clk_rate));
+	div_fbx1000 = div_s64((vco_clk_rate * 1000), ref_clk_to_pll);
+
+	div_s64_rem(div_fbx1000, 1000, &rem);
+	frac_n_value = div_s64((rem * (1 << 16)), 1000);
+	gen_vco_clk = div_s64(div_fbx1000 * ref_clk_to_pll, 1000);
+
+	pr_debug("ref_clk_to_pll = %lld\n", ref_clk_to_pll);
+	pr_debug("div_fb = %lld\n", div_fbx1000);
+	pr_debug("frac_n_value = %lld\n", frac_n_value);
+
+	pr_debug("Generated VCO Clock: %lld\n", gen_vco_clk);
+	rem = 0;
+	if (frac_n_mode) {
+		sdm_cfg0 = (0x0 << 5);
+		sdm_cfg0 |= (0x0 & 0x3f);
+		sdm_cfg1 = (div_s64(div_fbx1000, 1000) & 0x3f) - 1;
+		sdm_cfg3 = div_s64_rem(frac_n_value, 256, &rem);
+		sdm_cfg2 = rem;
+	} else {
+		sdm_cfg0 = (0x1 << 5);
+		sdm_cfg0 |= (div_s64(div_fbx1000, 1000) & 0x3f) - 1;
+		sdm_cfg1 = (0x0 & 0x3f);
+		sdm_cfg2 = 0;
+		sdm_cfg3 = 0;
+	}
+
+	pr_debug("sdm_cfg0=%lld\n", sdm_cfg0);
+	pr_debug("sdm_cfg1=%lld\n", sdm_cfg1);
+	pr_debug("sdm_cfg2=%lld\n", sdm_cfg2);
+	pr_debug("sdm_cfg3=%lld\n", sdm_cfg3);
+
+	cal_cfg11 = div_s64_rem(gen_vco_clk, 256 * 1000000, &rem);
+	cal_cfg10 = rem / 1000000;
+	pr_debug("cal_cfg10=%lld, cal_cfg11=%lld\n", cal_cfg10, cal_cfg11);
+
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_CHGPUMP_CFG, 0x02);
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG3, 0x2b);
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG4, 0x66);
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x0d);
+
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+		DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG1, (u32)(sdm_cfg1 & 0xff));
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+		DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG2, (u32)(sdm_cfg2 & 0xff));
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+		DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG3, (u32)(sdm_cfg3 & 0xff));
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+				DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG4, 0x00);
+
+	/* Add hardware recommended delay for correct PLL configuration */
+	if (dsi_pll_res->vco_delay)
+		udelay(dsi_pll_res->vco_delay);
+
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_REFCLK_CFG, (u32)refclk_cfg);
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG, 0x00);
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_VCOLPF_CFG, 0x71);
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0, (u32)sdm_cfg0);
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG0, 0x12);
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG6, 0x30);
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG7, 0x00);
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG8, 0x60);
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG9, 0x00);
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+		DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG10, (u32)(cal_cfg10 & 0xff));
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+		DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG11, (u32)(cal_cfg11 & 0xff));
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_EFUSE_CFG, 0x20);
+
+	return 0;
+}
+
+unsigned long vco_get_rate(struct clk *c)
+{
+	u32 sdm0, doubler, sdm_byp_div;
+	u64 vco_rate;
+	u32 sdm_dc_off, sdm_freq_seed, sdm2, sdm3;
+	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
+	u64 ref_clk = vco->ref_clk_rate;
+	int rc;
+	struct mdss_pll_resources *dsi_pll_res = vco->priv;
+
+	rc = mdss_pll_resource_enable(dsi_pll_res, true);
+	if (rc) {
+		pr_err("Failed to enable mdss dsi pll resources\n");
+		return rc;
+	}
+
+	/* Check to see if the ref clk doubler is enabled */
+	doubler = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
+				 DSI_PHY_PLL_UNIPHY_PLL_REFCLK_CFG) & BIT(0);
+	ref_clk += (doubler * vco->ref_clk_rate);
+
+	/* see if it is integer mode or sdm mode */
+	sdm0 = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
+					DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0);
+	if (sdm0 & BIT(6)) {
+		/* integer mode */
+		sdm_byp_div = (MDSS_PLL_REG_R(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0) & 0x3f) + 1;
+		vco_rate = ref_clk * sdm_byp_div;
+	} else {
+		/* sdm mode */
+		sdm_dc_off = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG1) & 0xFF;
+		pr_debug("sdm_dc_off = %d\n", sdm_dc_off);
+		sdm2 = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG2) & 0xFF;
+		sdm3 = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
+			DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG3) & 0xFF;
+		sdm_freq_seed = (sdm3 << 8) | sdm2;
+		pr_debug("sdm_freq_seed = %d\n", sdm_freq_seed);
+
+		vco_rate = (ref_clk * (sdm_dc_off + 1)) +
+			mult_frac(ref_clk, sdm_freq_seed, BIT(16));
+		pr_debug("vco rate = %lld", vco_rate);
+	}
+
+	pr_debug("returning vco rate = %lu\n", (unsigned long)vco_rate);
+
+	mdss_pll_resource_enable(dsi_pll_res, false);
+
+	return (unsigned long)vco_rate;
+}
+
+static int dsi_pll_enable(struct clk *c)
+{
+	int i, rc;
+	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
+	struct mdss_pll_resources *dsi_pll_res = vco->priv;
+
+	rc = mdss_pll_resource_enable(dsi_pll_res, true);
+	if (rc) {
+		pr_err("Failed to enable mdss dsi pll resources\n");
+		return rc;
+	}
+
+	/* Try all enable sequences until one succeeds */
+	for (i = 0; i < vco->pll_en_seq_cnt; i++) {
+		rc = vco->pll_enable_seqs[i](dsi_pll_res);
+		pr_debug("DSI PLL %s after sequence #%d\n",
+			rc ? "unlocked" : "locked", i + 1);
+		if (!rc)
+			break;
+	}
+
+	if (rc) {
+		mdss_pll_resource_enable(dsi_pll_res, false);
+		pr_err("DSI PLL failed to lock\n");
+	}
+	dsi_pll_res->pll_on = true;
+
+	return rc;
+}
+
+static void dsi_pll_disable(struct clk *c)
+{
+	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
+	struct mdss_pll_resources *dsi_pll_res = vco->priv;
+
+	if (!dsi_pll_res->pll_on &&
+		mdss_pll_resource_enable(dsi_pll_res, true)) {
+		pr_err("Failed to enable mdss dsi pll resources\n");
+		return;
+	}
+
+	dsi_pll_res->handoff_resources = false;
+
+	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
+				DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x00);
+
+	mdss_pll_resource_enable(dsi_pll_res, false);
+	dsi_pll_res->pll_on = false;
+
+	pr_debug("DSI PLL Disabled\n");
+}
+
+long vco_round_rate(struct clk *c, unsigned long rate)
+{
+	unsigned long rrate = rate;
+	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
+
+	if (rate < vco->min_rate)
+		rrate = vco->min_rate;
+	if (rate > vco->max_rate)
+		rrate = vco->max_rate;
+
+	return rrate;
+}
+
+enum handoff vco_handoff(struct clk *c)
+{
+	int rc;
+	enum handoff ret = HANDOFF_DISABLED_CLK;
+	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
+	struct mdss_pll_resources *dsi_pll_res = vco->priv;
+
+	rc = mdss_pll_resource_enable(dsi_pll_res, true);
+	if (rc) {
+		pr_err("Failed to enable mdss dsi pll resources\n");
+		return ret;
+	}
+
+	if (dsi_pll_lock_status(dsi_pll_res)) {
+		dsi_pll_res->handoff_resources = true;
+		dsi_pll_res->pll_on = true;
+		c->rate = vco_get_rate(c);
+		ret = HANDOFF_ENABLED_CLK;
+	} else {
+		mdss_pll_resource_enable(dsi_pll_res, false);
+	}
+
+	return ret;
+}
+
+int vco_prepare(struct clk *c)
+{
+	int rc = 0;
+	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
+	struct mdss_pll_resources *dsi_pll_res = vco->priv;
+
+	if (!dsi_pll_res) {
+		pr_err("Dsi pll resources are not available\n");
+		return -EINVAL;
+	}
+
+	if ((dsi_pll_res->vco_cached_rate != 0)
+	    && (dsi_pll_res->vco_cached_rate == c->rate)) {
+		rc = c->ops->set_rate(c, dsi_pll_res->vco_cached_rate);
+		if (rc) {
+			pr_err("vco_set_rate failed. rc=%d\n", rc);
+			goto error;
+		}
+	}
+
+	rc = dsi_pll_enable(c);
+
+error:
+	return rc;
+}
+
+void vco_unprepare(struct clk *c)
+{
+	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
+	struct mdss_pll_resources *dsi_pll_res = vco->priv;
+
+	if (!dsi_pll_res) {
+		pr_err("Dsi pll resources are not available\n");
+		return;
+	}
+
+	dsi_pll_res->vco_cached_rate = c->rate;
+	dsi_pll_disable(c);
+}
+
diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll.h b/drivers/clk/qcom/mdss/mdss-dsi-pll.h
index 15ca2fb..53a6afa 100644
--- a/drivers/clk/qcom/mdss/mdss-dsi-pll.h
+++ b/drivers/clk/qcom/mdss/mdss-dsi-pll.h
@@ -15,6 +15,11 @@
 
 #define MAX_DSI_PLL_EN_SEQS	10
 
+#define DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG		(0x0020)
+#define DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2	(0x0064)
+#define DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG		(0x0068)
+#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG1		(0x0070)
+
 struct lpfr_cfg {
 	unsigned long vco_rate;
 	u32 r;
@@ -35,6 +40,31 @@
 			(struct mdss_pll_resources *dsi_pll_Res);
 };
 
-int dsi_pll_clock_register(struct platform_device *pdev,
+static inline struct dsi_pll_vco_clk *to_vco_clk(struct clk *clk)
+{
+	return container_of(clk, struct dsi_pll_vco_clk, c);
+}
+
+int dsi_pll_clock_register_hpm(struct platform_device *pdev,
 				struct mdss_pll_resources *pll_res);
+int dsi_pll_clock_register_lpm(struct platform_device *pdev,
+				struct mdss_pll_resources *pll_res);
+
+int set_byte_mux_sel(struct mux_clk *clk, int sel);
+int get_byte_mux_sel(struct mux_clk *clk);
+int dsi_pll_div_prepare(struct clk *c);
+int dsi_pll_mux_prepare(struct clk *c);
+int fixed_4div_set_div(struct div_clk *clk, int div);
+int fixed_4div_get_div(struct div_clk *clk);
+int digital_set_div(struct div_clk *clk, int div);
+int digital_get_div(struct div_clk *clk);
+int analog_set_div(struct div_clk *clk, int div);
+int analog_get_div(struct div_clk *clk);
+int dsi_pll_lock_status(struct mdss_pll_resources *dsi_pll_res);
+int vco_set_rate(struct dsi_pll_vco_clk *vco, unsigned long rate);
+unsigned long vco_get_rate(struct clk *c);
+long vco_round_rate(struct clk *c, unsigned long rate);
+enum handoff vco_handoff(struct clk *c);
+int vco_prepare(struct clk *c);
+void vco_unprepare(struct clk *c);
 #endif
diff --git a/drivers/clk/qcom/mdss/mdss-pll.c b/drivers/clk/qcom/mdss/mdss-pll.c
index 0e51bbc..e17ca55 100644
--- a/drivers/clk/qcom/mdss/mdss-pll.c
+++ b/drivers/clk/qcom/mdss/mdss-pll.c
@@ -111,15 +111,19 @@
 		goto err;
 	}
 
-	if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_8916") ||
-		!strcmp(compatible_stream, "qcom,mdss_dsi_pll_8974"))
-		pll_res->pll_interface_type = MDSS_DSI_PLL;
-	else if (!strcmp(compatible_stream, "qcom,mdss_edp_pll"))
+	if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_8916")) {
+		pll_res->pll_interface_type = MDSS_DSI_PLL_LPM;
+		pll_res->target_id = MDSS_PLL_TARGET_8916;
+	} else if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_8974")) {
+		pll_res->pll_interface_type = MDSS_DSI_PLL_HPM;
+		pll_res->target_id = MDSS_PLL_TARGET_8974;
+	} else if (!strcmp(compatible_stream, "qcom,mdss_edp_pll")) {
 		pll_res->pll_interface_type = MDSS_EDP_PLL;
-	else if (!strcmp(compatible_stream, "qcom,mdss_hdmi_pll"))
+	} else if (!strcmp(compatible_stream, "qcom,mdss_hdmi_pll")) {
 		pll_res->pll_interface_type = MDSS_HDMI_PLL;
-	else
+	} else {
 		goto err;
+	}
 
 	return rc;
 
@@ -140,8 +144,11 @@
 	}
 
 	switch (pll_res->pll_interface_type) {
-	case MDSS_DSI_PLL:
-		rc = dsi_pll_clock_register(pdev, pll_res);
+	case MDSS_DSI_PLL_LPM:
+		rc = dsi_pll_clock_register_lpm(pdev, pll_res);
+		break;
+	case MDSS_DSI_PLL_HPM:
+		rc = dsi_pll_clock_register_hpm(pdev, pll_res);
 		break;
 	case MDSS_EDP_PLL:
 		rc = edp_pll_clock_register(pdev, pll_res);
diff --git a/drivers/clk/qcom/mdss/mdss-pll.h b/drivers/clk/qcom/mdss/mdss-pll.h
index 27b7b4f..9da57f7 100644
--- a/drivers/clk/qcom/mdss/mdss-pll.h
+++ b/drivers/clk/qcom/mdss/mdss-pll.h
@@ -21,12 +21,18 @@
 #define MDSS_PLL_REG_R(base, offset)		readl_relaxed((base) + (offset))
 
 enum {
-	MDSS_DSI_PLL,
+	MDSS_DSI_PLL_LPM,
+	MDSS_DSI_PLL_HPM,
 	MDSS_EDP_PLL,
 	MDSS_HDMI_PLL,
 	MDSS_UNKNOWN_PLL,
 };
 
+enum {
+	MDSS_PLL_TARGET_8974,
+	MDSS_PLL_TARGET_8916,
+};
+
 struct mdss_pll_resources {
 
 	/* Pll specific resources like GPIO, power supply, clocks, etc*/
@@ -46,6 +52,15 @@
 	u32		pll_interface_type;
 
 	/*
+	 * Target ID. Used in pll_register API for valid target check before
+	 * registering the PLL clocks.
+	 */
+	u32		target_id;
+
+	/* HW recommended delay during configuration of vco clock rate */
+	u32		vco_delay;
+
+	/*
 	 * Keep track to resource status to avoid updating same status for the
 	 * pll from different paths
 	 */