[v2,05/28] drm/msm/dsi: fuse dsi_pll_* code into dsi_phy_* code

Message ID 20210324151846.2774204-6-dmitry.baryshkov@linaro.org
State Superseded
Headers show
Series
  • drm/msm/dsi: refactor MSM DSI PHY/PLL drivers
Related show

Commit Message

Dmitry Baryshkov March 24, 2021, 3:18 p.m.
Each phy version is tightly coupled with the corresponding PLL code,
there is no need to keep them separate. Fuse source files together in
order to simplify DSI code.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>

---
 drivers/gpu/drm/msm/Makefile                  |    9 +-
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c    |  873 +++++++++++++
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c    | 1089 ++++++++++++++++
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c    |  637 ++++++++++
 .../gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c   |  519 ++++++++
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c     |  905 ++++++++++++++
 .../gpu/drm/msm/dsi/{pll => phy}/dsi_pll.c    |    0
 .../gpu/drm/msm/dsi/{pll => phy}/dsi_pll.h    |    0
 drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c    |  881 -------------
 drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c    | 1096 -----------------
 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c    |  643 ----------
 .../gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c   |  526 --------
 drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c     |  913 --------------
 13 files changed, 4024 insertions(+), 4067 deletions(-)
 rename drivers/gpu/drm/msm/dsi/{pll => phy}/dsi_pll.c (100%)
 rename drivers/gpu/drm/msm/dsi/{pll => phy}/dsi_pll.h (100%)
 delete mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c
 delete mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c
 delete mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c
 delete mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c
 delete mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c

-- 
2.30.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Comments

Abhinav Kumar March 26, 2021, 5:48 p.m. | #1
On 2021-03-24 08:18, Dmitry Baryshkov wrote:
> Each phy version is tightly coupled with the corresponding PLL code,

> there is no need to keep them separate. Fuse source files together in

> order to simplify DSI code.

> 

> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>

Reviewed-by: Abhinav Kumar <abhinavk@codeaurora.org>

> ---

>  drivers/gpu/drm/msm/Makefile                  |    9 +-

>  drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c    |  873 +++++++++++++

>  drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c    | 1089 ++++++++++++++++

>  drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c    |  637 ++++++++++

>  .../gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c   |  519 ++++++++

>  drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c     |  905 ++++++++++++++

>  .../gpu/drm/msm/dsi/{pll => phy}/dsi_pll.c    |    0

>  .../gpu/drm/msm/dsi/{pll => phy}/dsi_pll.h    |    0

>  drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c    |  881 -------------

>  drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c    | 1096 -----------------

>  drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c    |  643 ----------

>  .../gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c   |  526 --------

>  drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c     |  913 --------------

>  13 files changed, 4024 insertions(+), 4067 deletions(-)

>  rename drivers/gpu/drm/msm/dsi/{pll => phy}/dsi_pll.c (100%)

>  rename drivers/gpu/drm/msm/dsi/{pll => phy}/dsi_pll.h (100%)

>  delete mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c

>  delete mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c

>  delete mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c

>  delete mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c

>  delete mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c

> 

> diff --git a/drivers/gpu/drm/msm/Makefile 

> b/drivers/gpu/drm/msm/Makefile

> index 3cc906121fb3..1be6996b80b7 100644

> --- a/drivers/gpu/drm/msm/Makefile

> +++ b/drivers/gpu/drm/msm/Makefile

> @@ -136,13 +136,6 @@ msm-$(CONFIG_DRM_MSM_DSI_14NM_PHY) +=

> dsi/phy/dsi_phy_14nm.o

>  msm-$(CONFIG_DRM_MSM_DSI_10NM_PHY) += dsi/phy/dsi_phy_10nm.o

>  msm-$(CONFIG_DRM_MSM_DSI_7NM_PHY) += dsi/phy/dsi_phy_7nm.o

> 

> -ifeq ($(CONFIG_DRM_MSM_DSI_PLL),y)

> -msm-y += dsi/pll/dsi_pll.o

> -msm-$(CONFIG_DRM_MSM_DSI_28NM_PHY) += dsi/pll/dsi_pll_28nm.o

> -msm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/pll/dsi_pll_28nm_8960.o

> -msm-$(CONFIG_DRM_MSM_DSI_14NM_PHY) += dsi/pll/dsi_pll_14nm.o

> -msm-$(CONFIG_DRM_MSM_DSI_10NM_PHY) += dsi/pll/dsi_pll_10nm.o

> -msm-$(CONFIG_DRM_MSM_DSI_7NM_PHY) += dsi/pll/dsi_pll_7nm.o

> -endif

> +msm-$(CONFIG_DRM_MSM_DSI_PLL) += dsi/phy/dsi_pll.o

> 

>  obj-$(CONFIG_DRM_MSM)	+= msm.o

> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c

> b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c

> index 655fa17a0452..5da369b5c475 100644

> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c

> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c

> @@ -3,11 +3,884 @@

>   * Copyright (c) 2018, The Linux Foundation

>   */

> 

> +#include <linux/clk.h>

> +#include <linux/clk-provider.h>

>  #include <linux/iopoll.h>

> 

> +#include "dsi_pll.h"

>  #include "dsi_phy.h"

>  #include "dsi.xml.h"

> 

> +/*

> + * DSI PLL 10nm - clock diagram (eg: DSI0):

> + *

> + *           dsi0_pll_out_div_clk  dsi0_pll_bit_clk

> + *                              |                |

> + *                              |                |

> + *                 +---------+  |  +----------+  |  +----+

> + *  dsi0vco_clk ---| out_div |--o--| divl_3_0 |--o--| /8 |--

> dsi0_phy_pll_out_byteclk

> + *                 +---------+  |  +----------+  |  +----+

> + *                              |                |

> + *                              |                |

> dsi0_pll_by_2_bit_clk

> + *                              |                |          |

> + *                              |                |  +----+  |  |\

> dsi0_pclk_mux

> + *                              |                |--| /2 |--o--| \   |

> + *                              |                |  +----+     |  \

> |  +---------+

> + *                              |                --------------|

> |--o--| div_7_4 |-- dsi0_phy_pll_out_dsiclk

> + *                              |------------------------------|  /

>   +---------+

> + *                              |          +-----+             | /

> + *                              -----------| /4? |--o----------|/

> + *                                         +-----+  |           |

> + *                                                  |           

> |dsiclk_sel

> + *                                                  |

> + *                                                  

> dsi0_pll_post_out_div_clk

> + */

> +

> +#define DSI_BYTE_PLL_CLK		0

> +#define DSI_PIXEL_PLL_CLK		1

> +#define NUM_PROVIDED_CLKS		2

> +

> +#define VCO_REF_CLK_RATE		19200000

> +

> +struct dsi_pll_regs {

> +	u32 pll_prop_gain_rate;

> +	u32 pll_lockdet_rate;

> +	u32 decimal_div_start;

> +	u32 frac_div_start_low;

> +	u32 frac_div_start_mid;

> +	u32 frac_div_start_high;

> +	u32 pll_clock_inverters;

> +	u32 ssc_stepsize_low;

> +	u32 ssc_stepsize_high;

> +	u32 ssc_div_per_low;

> +	u32 ssc_div_per_high;

> +	u32 ssc_adjper_low;

> +	u32 ssc_adjper_high;

> +	u32 ssc_control;

> +};

> +

> +struct dsi_pll_config {

> +	u32 ref_freq;

> +	bool div_override;

> +	u32 output_div;

> +	bool ignore_frac;

> +	bool disable_prescaler;

> +	bool enable_ssc;

> +	bool ssc_center;

> +	u32 dec_bits;

> +	u32 frac_bits;

> +	u32 lock_timer;

> +	u32 ssc_freq;

> +	u32 ssc_offset;

> +	u32 ssc_adj_per;

> +	u32 thresh_cycles;

> +	u32 refclk_cycles;

> +};

> +

> +struct pll_10nm_cached_state {

> +	unsigned long vco_rate;

> +	u8 bit_clk_div;

> +	u8 pix_clk_div;

> +	u8 pll_out_div;

> +	u8 pll_mux;

> +};

> +

> +struct dsi_pll_10nm {

> +	struct msm_dsi_pll base;

> +

> +	int id;

> +	struct platform_device *pdev;

> +

> +	void __iomem *phy_cmn_mmio;

> +	void __iomem *mmio;

> +

> +	u64 vco_ref_clk_rate;

> +	u64 vco_current_rate;

> +

> +	/* protects REG_DSI_10nm_PHY_CMN_CLK_CFG0 register */

> +	spinlock_t postdiv_lock;

> +

> +	int vco_delay;

> +	struct dsi_pll_config pll_configuration;

> +	struct dsi_pll_regs reg_setup;

> +

> +	/* private clocks: */

> +	struct clk_hw *out_div_clk_hw;

> +	struct clk_hw *bit_clk_hw;

> +	struct clk_hw *byte_clk_hw;

> +	struct clk_hw *by_2_bit_clk_hw;

> +	struct clk_hw *post_out_div_clk_hw;

> +	struct clk_hw *pclk_mux_hw;

> +	struct clk_hw *out_dsiclk_hw;

> +

> +	/* clock-provider: */

> +	struct clk_hw_onecell_data *hw_data;

> +

> +	struct pll_10nm_cached_state cached_state;

> +

> +	enum msm_dsi_phy_usecase uc;

> +	struct dsi_pll_10nm *slave;

> +};

> +

> +#define to_pll_10nm(x)	container_of(x, struct dsi_pll_10nm, base)

> +

> +/*

> + * Global list of private DSI PLL struct pointers. We need this for 

> Dual DSI

> + * mode, where the master PLL's clk_ops needs access the slave's 

> private data

> + */

> +static struct dsi_pll_10nm *pll_10nm_list[DSI_MAX];

> +

> +static void dsi_pll_setup_config(struct dsi_pll_10nm *pll)

> +{

> +	struct dsi_pll_config *config = &pll->pll_configuration;

> +

> +	config->ref_freq = pll->vco_ref_clk_rate;

> +	config->output_div = 1;

> +	config->dec_bits = 8;

> +	config->frac_bits = 18;

> +	config->lock_timer = 64;

> +	config->ssc_freq = 31500;

> +	config->ssc_offset = 5000;

> +	config->ssc_adj_per = 2;

> +	config->thresh_cycles = 32;

> +	config->refclk_cycles = 256;

> +

> +	config->div_override = false;

> +	config->ignore_frac = false;

> +	config->disable_prescaler = false;

> +

> +	config->enable_ssc = false;

> +	config->ssc_center = 0;

> +}

> +

> +static void dsi_pll_calc_dec_frac(struct dsi_pll_10nm *pll)

> +{

> +	struct dsi_pll_config *config = &pll->pll_configuration;

> +	struct dsi_pll_regs *regs = &pll->reg_setup;

> +	u64 fref = pll->vco_ref_clk_rate;

> +	u64 pll_freq;

> +	u64 divider;

> +	u64 dec, dec_multiple;

> +	u32 frac;

> +	u64 multiplier;

> +

> +	pll_freq = pll->vco_current_rate;

> +

> +	if (config->disable_prescaler)

> +		divider = fref;

> +	else

> +		divider = fref * 2;

> +

> +	multiplier = 1 << config->frac_bits;

> +	dec_multiple = div_u64(pll_freq * multiplier, divider);

> +	dec = div_u64_rem(dec_multiple, multiplier, &frac);

> +

> +	if (pll_freq <= 1900000000UL)

> +		regs->pll_prop_gain_rate = 8;

> +	else if (pll_freq <= 3000000000UL)

> +		regs->pll_prop_gain_rate = 10;

> +	else

> +		regs->pll_prop_gain_rate = 12;

> +	if (pll_freq < 1100000000UL)

> +		regs->pll_clock_inverters = 8;

> +	else

> +		regs->pll_clock_inverters = 0;

> +

> +	regs->pll_lockdet_rate = config->lock_timer;

> +	regs->decimal_div_start = dec;

> +	regs->frac_div_start_low = (frac & 0xff);

> +	regs->frac_div_start_mid = (frac & 0xff00) >> 8;

> +	regs->frac_div_start_high = (frac & 0x30000) >> 16;

> +}

> +

> +#define SSC_CENTER		BIT(0)

> +#define SSC_EN			BIT(1)

> +

> +static void dsi_pll_calc_ssc(struct dsi_pll_10nm *pll)

> +{

> +	struct dsi_pll_config *config = &pll->pll_configuration;

> +	struct dsi_pll_regs *regs = &pll->reg_setup;

> +	u32 ssc_per;

> +	u32 ssc_mod;

> +	u64 ssc_step_size;

> +	u64 frac;

> +

> +	if (!config->enable_ssc) {

> +		DBG("SSC not enabled\n");

> +		return;

> +	}

> +

> +	ssc_per = DIV_ROUND_CLOSEST(config->ref_freq, config->ssc_freq) / 2 - 

> 1;

> +	ssc_mod = (ssc_per + 1) % (config->ssc_adj_per + 1);

> +	ssc_per -= ssc_mod;

> +

> +	frac = regs->frac_div_start_low |

> +			(regs->frac_div_start_mid << 8) |

> +			(regs->frac_div_start_high << 16);

> +	ssc_step_size = regs->decimal_div_start;

> +	ssc_step_size *= (1 << config->frac_bits);

> +	ssc_step_size += frac;

> +	ssc_step_size *= config->ssc_offset;

> +	ssc_step_size *= (config->ssc_adj_per + 1);

> +	ssc_step_size = div_u64(ssc_step_size, (ssc_per + 1));

> +	ssc_step_size = DIV_ROUND_CLOSEST_ULL(ssc_step_size, 1000000);

> +

> +	regs->ssc_div_per_low = ssc_per & 0xFF;

> +	regs->ssc_div_per_high = (ssc_per & 0xFF00) >> 8;

> +	regs->ssc_stepsize_low = (u32)(ssc_step_size & 0xFF);

> +	regs->ssc_stepsize_high = (u32)((ssc_step_size & 0xFF00) >> 8);

> +	regs->ssc_adjper_low = config->ssc_adj_per & 0xFF;

> +	regs->ssc_adjper_high = (config->ssc_adj_per & 0xFF00) >> 8;

> +

> +	regs->ssc_control = config->ssc_center ? SSC_CENTER : 0;

> +

> +	pr_debug("SCC: Dec:%d, frac:%llu, frac_bits:%d\n",

> +		 regs->decimal_div_start, frac, config->frac_bits);

> +	pr_debug("SSC: div_per:0x%X, stepsize:0x%X, adjper:0x%X\n",

> +		 ssc_per, (u32)ssc_step_size, config->ssc_adj_per);

> +}

> +

> +static void dsi_pll_ssc_commit(struct dsi_pll_10nm *pll)

> +{

> +	void __iomem *base = pll->mmio;

> +	struct dsi_pll_regs *regs = &pll->reg_setup;

> +

> +	if (pll->pll_configuration.enable_ssc) {

> +		pr_debug("SSC is enabled\n");

> +

> +		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_STEPSIZE_LOW_1,

> +			  regs->ssc_stepsize_low);

> +		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_STEPSIZE_HIGH_1,

> +			  regs->ssc_stepsize_high);

> +		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_DIV_PER_LOW_1,

> +			  regs->ssc_div_per_low);

> +		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_DIV_PER_HIGH_1,

> +			  regs->ssc_div_per_high);

> +		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_DIV_ADJPER_LOW_1,

> +			  regs->ssc_adjper_low);

> +		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_DIV_ADJPER_HIGH_1,

> +			  regs->ssc_adjper_high);

> +		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_CONTROL,

> +			  SSC_EN | regs->ssc_control);

> +	}

> +}

> +

> +static void dsi_pll_config_hzindep_reg(struct dsi_pll_10nm *pll)

> +{

> +	void __iomem *base = pll->mmio;

> +

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_ANALOG_CONTROLS_ONE, 0x80);

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_ANALOG_CONTROLS_TWO, 0x03);

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_ANALOG_CONTROLS_THREE, 0x00);

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_DSM_DIVIDER, 0x00);

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_FEEDBACK_DIVIDER, 0x4e);

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_CALIBRATION_SETTINGS, 0x40);

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_BAND_SEL_CAL_SETTINGS_THREE,

> +		  0xba);

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_FREQ_DETECT_SETTINGS_ONE, 

> 0x0c);

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_OUTDIV, 0x00);

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_CORE_OVERRIDE, 0x00);

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_DIGITAL_TIMERS_TWO, 0x08);

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_PROP_GAIN_RATE_1, 0x08);

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_BAND_SET_RATE_1, 0xc0);

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_1, 

> 0xfa);

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_FL_INT_GAIN_PFILT_BAND_1,

> +		  0x4c);

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_LOCK_OVERRIDE, 0x80);

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_PFILT, 0x29);

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_IFILT, 0x3f);

> +}

> +

> +static void dsi_pll_commit(struct dsi_pll_10nm *pll)

> +{

> +	void __iomem *base = pll->mmio;

> +	struct dsi_pll_regs *reg = &pll->reg_setup;

> +

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_CORE_INPUT_OVERRIDE, 0x12);

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_DECIMAL_DIV_START_1,

> +		  reg->decimal_div_start);

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_LOW_1,

> +		  reg->frac_div_start_low);

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_MID_1,

> +		  reg->frac_div_start_mid);

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_HIGH_1,

> +		  reg->frac_div_start_high);

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_LOCKDET_RATE_1,

> +		  reg->pll_lockdet_rate);

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_LOCK_DELAY, 0x06);

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_CMODE, 0x10);

> +	pll_write(base + REG_DSI_10nm_PHY_PLL_CLOCK_INVERTERS,

> +		  reg->pll_clock_inverters);

> +}

> +

> +static int dsi_pll_10nm_vco_set_rate(struct clk_hw *hw, unsigned long 

> rate,

> +				     unsigned long parent_rate)

> +{

> +	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> +	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);

> +

> +	DBG("DSI PLL%d rate=%lu, parent's=%lu", pll_10nm->id, rate,

> +	    parent_rate);

> +

> +	pll_10nm->vco_current_rate = rate;

> +	pll_10nm->vco_ref_clk_rate = VCO_REF_CLK_RATE;

> +

> +	dsi_pll_setup_config(pll_10nm);

> +

> +	dsi_pll_calc_dec_frac(pll_10nm);

> +

> +	dsi_pll_calc_ssc(pll_10nm);

> +

> +	dsi_pll_commit(pll_10nm);

> +

> +	dsi_pll_config_hzindep_reg(pll_10nm);

> +

> +	dsi_pll_ssc_commit(pll_10nm);

> +

> +	/* flush, ensure all register writes are done*/

> +	wmb();

> +

> +	return 0;

> +}

> +

> +static int dsi_pll_10nm_lock_status(struct dsi_pll_10nm *pll)

> +{

> +	struct device *dev = &pll->pdev->dev;

> +	int rc;

> +	u32 status = 0;

> +	u32 const delay_us = 100;

> +	u32 const timeout_us = 5000;

> +

> +	rc = readl_poll_timeout_atomic(pll->mmio +

> +				       REG_DSI_10nm_PHY_PLL_COMMON_STATUS_ONE,

> +				       status,

> +				       ((status & BIT(0)) > 0),

> +				       delay_us,

> +				       timeout_us);

> +	if (rc)

> +		DRM_DEV_ERROR(dev, "DSI PLL(%d) lock failed, status=0x%08x\n",

> +			      pll->id, status);

> +

> +	return rc;

> +}

> +

> +static void dsi_pll_disable_pll_bias(struct dsi_pll_10nm *pll)

> +{

> +	u32 data = pll_read(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CTRL_0);

> +

> +	pll_write(pll->mmio + REG_DSI_10nm_PHY_PLL_SYSTEM_MUXES, 0);

> +	pll_write(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CTRL_0,

> +		  data & ~BIT(5));

> +	ndelay(250);

> +}

> +

> +static void dsi_pll_enable_pll_bias(struct dsi_pll_10nm *pll)

> +{

> +	u32 data = pll_read(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CTRL_0);

> +

> +	pll_write(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CTRL_0,

> +		  data | BIT(5));

> +	pll_write(pll->mmio + REG_DSI_10nm_PHY_PLL_SYSTEM_MUXES, 0xc0);

> +	ndelay(250);

> +}

> +

> +static void dsi_pll_disable_global_clk(struct dsi_pll_10nm *pll)

> +{

> +	u32 data;

> +

> +	data = pll_read(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CLK_CFG1);

> +	pll_write(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CLK_CFG1,

> +		  data & ~BIT(5));

> +}

> +

> +static void dsi_pll_enable_global_clk(struct dsi_pll_10nm *pll)

> +{

> +	u32 data;

> +

> +	data = pll_read(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CLK_CFG1);

> +	pll_write(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CLK_CFG1,

> +		  data | BIT(5));

> +}

> +

> +static int dsi_pll_10nm_vco_prepare(struct clk_hw *hw)

> +{

> +	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> +	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);

> +	struct device *dev = &pll_10nm->pdev->dev;

> +	int rc;

> +

> +	dsi_pll_enable_pll_bias(pll_10nm);

> +	if (pll_10nm->slave)

> +		dsi_pll_enable_pll_bias(pll_10nm->slave);

> +

> +	rc = dsi_pll_10nm_vco_set_rate(hw,pll_10nm->vco_current_rate, 0);

> +	if (rc) {

> +		DRM_DEV_ERROR(dev, "vco_set_rate failed, rc=%d\n", rc);

> +		return rc;

> +	}

> +

> +	/* Start PLL */

> +	pll_write(pll_10nm->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_PLL_CNTRL,

> +		  0x01);

> +

> +	/*

> +	 * ensure all PLL configurations are written prior to checking

> +	 * for PLL lock.

> +	 */

> +	wmb();

> +

> +	/* Check for PLL lock */

> +	rc = dsi_pll_10nm_lock_status(pll_10nm);

> +	if (rc) {

> +		DRM_DEV_ERROR(dev, "PLL(%d) lock failed\n", pll_10nm->id);

> +		goto error;

> +	}

> +

> +	pll->pll_on = true;

> +

> +	dsi_pll_enable_global_clk(pll_10nm);

> +	if (pll_10nm->slave)

> +		dsi_pll_enable_global_clk(pll_10nm->slave);

> +

> +	pll_write(pll_10nm->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_RBUF_CTRL,

> +		  0x01);

> +	if (pll_10nm->slave)

> +		pll_write(pll_10nm->slave->phy_cmn_mmio +

> +			  REG_DSI_10nm_PHY_CMN_RBUF_CTRL, 0x01);

> +

> +error:

> +	return rc;

> +}

> +

> +static void dsi_pll_disable_sub(struct dsi_pll_10nm *pll)

> +{

> +	pll_write(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_RBUF_CTRL, 0);

> +	dsi_pll_disable_pll_bias(pll);

> +}

> +

> +static void dsi_pll_10nm_vco_unprepare(struct clk_hw *hw)

> +{

> +	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> +	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);

> +

> +	/*

> +	 * To avoid any stray glitches while abruptly powering down the PLL

> +	 * make sure to gate the clock using the clock enable bit before

> +	 * powering down the PLL

> +	 */

> +	dsi_pll_disable_global_clk(pll_10nm);

> +	pll_write(pll_10nm->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_PLL_CNTRL, 

> 0);

> +	dsi_pll_disable_sub(pll_10nm);

> +	if (pll_10nm->slave) {

> +		dsi_pll_disable_global_clk(pll_10nm->slave);

> +		dsi_pll_disable_sub(pll_10nm->slave);

> +	}

> +	/* flush, ensure all register writes are done */

> +	wmb();

> +	pll->pll_on = false;

> +}

> +

> +static unsigned long dsi_pll_10nm_vco_recalc_rate(struct clk_hw *hw,

> +						  unsigned long parent_rate)

> +{

> +	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> +	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);

> +	struct dsi_pll_config *config = &pll_10nm->pll_configuration;

> +	void __iomem *base = pll_10nm->mmio;

> +	u64 ref_clk = pll_10nm->vco_ref_clk_rate;

> +	u64 vco_rate = 0x0;

> +	u64 multiplier;

> +	u32 frac;

> +	u32 dec;

> +	u64 pll_freq, tmp64;

> +

> +	dec = pll_read(base + REG_DSI_10nm_PHY_PLL_DECIMAL_DIV_START_1);

> +	dec &= 0xff;

> +

> +	frac = pll_read(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_LOW_1);

> +	frac |= ((pll_read(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_MID_1) 

> &

> +		  0xff) << 8);

> +	frac |= ((pll_read(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_HIGH_1) 

> &

> +		  0x3) << 16);

> +

> +	/*

> +	 * TODO:

> +	 *	1. Assumes prescaler is disabled

> +	 */

> +	multiplier = 1 << config->frac_bits;

> +	pll_freq = dec * (ref_clk * 2);

> +	tmp64 = (ref_clk * 2 * frac);

> +	pll_freq += div_u64(tmp64, multiplier);

> +

> +	vco_rate = pll_freq;

> +

> +	DBG("DSI PLL%d returning vco rate = %lu, dec = %x, frac = %x",

> +	    pll_10nm->id, (unsigned long)vco_rate, dec, frac);

> +

> +	return (unsigned long)vco_rate;

> +}

> +

> +static const struct clk_ops clk_ops_dsi_pll_10nm_vco = {

> +	.round_rate = msm_dsi_pll_helper_clk_round_rate,

> +	.set_rate = dsi_pll_10nm_vco_set_rate,

> +	.recalc_rate = dsi_pll_10nm_vco_recalc_rate,

> +	.prepare = dsi_pll_10nm_vco_prepare,

> +	.unprepare = dsi_pll_10nm_vco_unprepare,

> +};

> +

> +/*

> + * PLL Callbacks

> + */

> +

> +static void dsi_pll_10nm_save_state(struct msm_dsi_pll *pll)

> +{

> +	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);

> +	struct pll_10nm_cached_state *cached = &pll_10nm->cached_state;

> +	void __iomem *phy_base = pll_10nm->phy_cmn_mmio;

> +	u32 cmn_clk_cfg0, cmn_clk_cfg1;

> +

> +	cached->pll_out_div = pll_read(pll_10nm->mmio +

> +				       REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE);

> +	cached->pll_out_div &= 0x3;

> +

> +	cmn_clk_cfg0 = pll_read(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG0);

> +	cached->bit_clk_div = cmn_clk_cfg0 & 0xf;

> +	cached->pix_clk_div = (cmn_clk_cfg0 & 0xf0) >> 4;

> +

> +	cmn_clk_cfg1 = pll_read(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG1);

> +	cached->pll_mux = cmn_clk_cfg1 & 0x3;

> +

> +	DBG("DSI PLL%d outdiv %x bit_clk_div %x pix_clk_div %x pll_mux %x",

> +	    pll_10nm->id, cached->pll_out_div, cached->bit_clk_div,

> +	    cached->pix_clk_div, cached->pll_mux);

> +}

> +

> +static int dsi_pll_10nm_restore_state(struct msm_dsi_pll *pll)

> +{

> +	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);

> +	struct pll_10nm_cached_state *cached = &pll_10nm->cached_state;

> +	void __iomem *phy_base = pll_10nm->phy_cmn_mmio;

> +	u32 val;

> +	int ret;

> +

> +	val = pll_read(pll_10nm->mmio + 

> REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE);

> +	val &= ~0x3;

> +	val |= cached->pll_out_div;

> +	pll_write(pll_10nm->mmio + REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE, 

> val);

> +

> +	pll_write(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG0,

> +		  cached->bit_clk_div | (cached->pix_clk_div << 4));

> +

> +	val = pll_read(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG1);

> +	val &= ~0x3;

> +	val |= cached->pll_mux;

> +	pll_write(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG1, val);

> +

> +	ret = dsi_pll_10nm_vco_set_rate(&pll->clk_hw,

> pll_10nm->vco_current_rate, pll_10nm->vco_ref_clk_rate);

> +	if (ret) {

> +		DRM_DEV_ERROR(&pll_10nm->pdev->dev,

> +			"restore vco rate failed. ret=%d\n", ret);

> +		return ret;

> +	}

> +

> +	DBG("DSI PLL%d", pll_10nm->id);

> +

> +	return 0;

> +}

> +

> +static int dsi_pll_10nm_set_usecase(struct msm_dsi_pll *pll,

> +				    enum msm_dsi_phy_usecase uc)

> +{

> +	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);

> +	void __iomem *base = pll_10nm->phy_cmn_mmio;

> +	u32 data = 0x0;	/* internal PLL */

> +

> +	DBG("DSI PLL%d", pll_10nm->id);

> +

> +	switch (uc) {

> +	case MSM_DSI_PHY_STANDALONE:

> +		break;

> +	case MSM_DSI_PHY_MASTER:

> +		pll_10nm->slave = pll_10nm_list[(pll_10nm->id + 1) % DSI_MAX];

> +		break;

> +	case MSM_DSI_PHY_SLAVE:

> +		data = 0x1; /* external PLL */

> +		break;

> +	default:

> +		return -EINVAL;

> +	}

> +

> +	/* set PLL src */

> +	pll_write(base + REG_DSI_10nm_PHY_CMN_CLK_CFG1, (data << 2));

> +

> +	pll_10nm->uc = uc;

> +

> +	return 0;

> +}

> +

> +static int dsi_pll_10nm_get_provider(struct msm_dsi_pll *pll,

> +				     struct clk **byte_clk_provider,

> +				     struct clk **pixel_clk_provider)

> +{

> +	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);

> +	struct clk_hw_onecell_data *hw_data = pll_10nm->hw_data;

> +

> +	DBG("DSI PLL%d", pll_10nm->id);

> +

> +	if (byte_clk_provider)

> +		*byte_clk_provider = hw_data->hws[DSI_BYTE_PLL_CLK]->clk;

> +	if (pixel_clk_provider)

> +		*pixel_clk_provider = hw_data->hws[DSI_PIXEL_PLL_CLK]->clk;

> +

> +	return 0;

> +}

> +

> +static void dsi_pll_10nm_destroy(struct msm_dsi_pll *pll)

> +{

> +	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);

> +	struct device *dev = &pll_10nm->pdev->dev;

> +

> +	DBG("DSI PLL%d", pll_10nm->id);

> +	of_clk_del_provider(dev->of_node);

> +

> +	clk_hw_unregister_divider(pll_10nm->out_dsiclk_hw);

> +	clk_hw_unregister_mux(pll_10nm->pclk_mux_hw);

> +	clk_hw_unregister_fixed_factor(pll_10nm->post_out_div_clk_hw);

> +	clk_hw_unregister_fixed_factor(pll_10nm->by_2_bit_clk_hw);

> +	clk_hw_unregister_fixed_factor(pll_10nm->byte_clk_hw);

> +	clk_hw_unregister_divider(pll_10nm->bit_clk_hw);

> +	clk_hw_unregister_divider(pll_10nm->out_div_clk_hw);

> +	clk_hw_unregister(&pll_10nm->base.clk_hw);

> +}

> +

> +/*

> + * The post dividers and mux clocks are created using the standard 

> divider and

> + * mux API. Unlike the 14nm PHY, the slave PLL doesn't need its 

> dividers/mux

> + * state to follow the master PLL's divider/mux state. Therefore, we 

> don't

> + * require special clock ops that also configure the slave PLL 

> registers

> + */

> +static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm)

> +{

> +	char clk_name[32], parent[32], vco_name[32];

> +	char parent2[32], parent3[32], parent4[32];

> +	struct clk_init_data vco_init = {

> +		.parent_names = (const char *[]){ "xo" },

> +		.num_parents = 1,

> +		.name = vco_name,

> +		.flags = CLK_IGNORE_UNUSED,

> +		.ops = &clk_ops_dsi_pll_10nm_vco,

> +	};

> +	struct device *dev = &pll_10nm->pdev->dev;

> +	struct clk_hw_onecell_data *hw_data;

> +	struct clk_hw *hw;

> +	int ret;

> +

> +	DBG("DSI%d", pll_10nm->id);

> +

> +	hw_data = devm_kzalloc(dev, sizeof(*hw_data) +

> +			       NUM_PROVIDED_CLKS * sizeof(struct clk_hw *),

> +			       GFP_KERNEL);

> +	if (!hw_data)

> +		return -ENOMEM;

> +

> +	snprintf(vco_name, 32, "dsi%dvco_clk", pll_10nm->id);

> +	pll_10nm->base.clk_hw.init = &vco_init;

> +

> +	ret = clk_hw_register(dev, &pll_10nm->base.clk_hw);

> +	if (ret)

> +		return ret;

> +

> +	snprintf(clk_name, 32, "dsi%d_pll_out_div_clk", pll_10nm->id);

> +	snprintf(parent, 32, "dsi%dvco_clk", pll_10nm->id);

> +

> +	hw = clk_hw_register_divider(dev, clk_name,

> +				     parent, CLK_SET_RATE_PARENT,

> +				     pll_10nm->mmio +

> +				     REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE,

> +				     0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL);

> +	if (IS_ERR(hw)) {

> +		ret = PTR_ERR(hw);

> +		goto err_base_clk_hw;

> +	}

> +

> +	pll_10nm->out_div_clk_hw = hw;

> +

> +	snprintf(clk_name, 32, "dsi%d_pll_bit_clk", pll_10nm->id);

> +	snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_10nm->id);

> +

> +	/* BIT CLK: DIV_CTRL_3_0 */

> +	hw = clk_hw_register_divider(dev, clk_name, parent,

> +				     CLK_SET_RATE_PARENT,

> +				     pll_10nm->phy_cmn_mmio +

> +				     REG_DSI_10nm_PHY_CMN_CLK_CFG0,

> +				     0, 4, CLK_DIVIDER_ONE_BASED,

> +				     &pll_10nm->postdiv_lock);

> +	if (IS_ERR(hw)) {

> +		ret = PTR_ERR(hw);

> +		goto err_out_div_clk_hw;

> +	}

> +

> +	pll_10nm->bit_clk_hw = hw;

> +

> +	snprintf(clk_name, 32, "dsi%d_phy_pll_out_byteclk", pll_10nm->id);

> +	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_10nm->id);

> +

> +	/* DSI Byte clock = VCO_CLK / OUT_DIV / BIT_DIV / 8 */

> +	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,

> +					  CLK_SET_RATE_PARENT, 1, 8);

> +	if (IS_ERR(hw)) {

> +		ret = PTR_ERR(hw);

> +		goto err_bit_clk_hw;

> +	}

> +

> +	pll_10nm->byte_clk_hw = hw;

> +	hw_data->hws[DSI_BYTE_PLL_CLK] = hw;

> +

> +	snprintf(clk_name, 32, "dsi%d_pll_by_2_bit_clk", pll_10nm->id);

> +	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_10nm->id);

> +

> +	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,

> +					  0, 1, 2);

> +	if (IS_ERR(hw)) {

> +		ret = PTR_ERR(hw);

> +		goto err_byte_clk_hw;

> +	}

> +

> +	pll_10nm->by_2_bit_clk_hw = hw;

> +

> +	snprintf(clk_name, 32, "dsi%d_pll_post_out_div_clk", pll_10nm->id);

> +	snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_10nm->id);

> +

> +	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,

> +					  0, 1, 4);

> +	if (IS_ERR(hw)) {

> +		ret = PTR_ERR(hw);

> +		goto err_by_2_bit_clk_hw;

> +	}

> +

> +	pll_10nm->post_out_div_clk_hw = hw;

> +

> +	snprintf(clk_name, 32, "dsi%d_pclk_mux", pll_10nm->id);

> +	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_10nm->id);

> +	snprintf(parent2, 32, "dsi%d_pll_by_2_bit_clk", pll_10nm->id);

> +	snprintf(parent3, 32, "dsi%d_pll_out_div_clk", pll_10nm->id);

> +	snprintf(parent4, 32, "dsi%d_pll_post_out_div_clk", pll_10nm->id);

> +

> +	hw = clk_hw_register_mux(dev, clk_name,

> +				 ((const char *[]){

> +				 parent, parent2, parent3, parent4

> +				 }), 4, 0, pll_10nm->phy_cmn_mmio +

> +				 REG_DSI_10nm_PHY_CMN_CLK_CFG1,

> +				 0, 2, 0, NULL);

> +	if (IS_ERR(hw)) {

> +		ret = PTR_ERR(hw);

> +		goto err_post_out_div_clk_hw;

> +	}

> +

> +	pll_10nm->pclk_mux_hw = hw;

> +

> +	snprintf(clk_name, 32, "dsi%d_phy_pll_out_dsiclk", pll_10nm->id);

> +	snprintf(parent, 32, "dsi%d_pclk_mux", pll_10nm->id);

> +

> +	/* PIX CLK DIV : DIV_CTRL_7_4*/

> +	hw = clk_hw_register_divider(dev, clk_name, parent,

> +				     0, pll_10nm->phy_cmn_mmio +

> +					REG_DSI_10nm_PHY_CMN_CLK_CFG0,

> +				     4, 4, CLK_DIVIDER_ONE_BASED,

> +				     &pll_10nm->postdiv_lock);

> +	if (IS_ERR(hw)) {

> +		ret = PTR_ERR(hw);

> +		goto err_pclk_mux_hw;

> +	}

> +

> +	pll_10nm->out_dsiclk_hw = hw;

> +	hw_data->hws[DSI_PIXEL_PLL_CLK] = hw;

> +

> +	hw_data->num = NUM_PROVIDED_CLKS;

> +	pll_10nm->hw_data = hw_data;

> +

> +	ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,

> +				     pll_10nm->hw_data);

> +	if (ret) {

> +		DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret);

> +		goto err_dsiclk_hw;

> +	}

> +

> +	return 0;

> +

> +err_dsiclk_hw:

> +	clk_hw_unregister_divider(pll_10nm->out_dsiclk_hw);

> +err_pclk_mux_hw:

> +	clk_hw_unregister_mux(pll_10nm->pclk_mux_hw);

> +err_post_out_div_clk_hw:

> +	clk_hw_unregister_fixed_factor(pll_10nm->post_out_div_clk_hw);

> +err_by_2_bit_clk_hw:

> +	clk_hw_unregister_fixed_factor(pll_10nm->by_2_bit_clk_hw);

> +err_byte_clk_hw:

> +	clk_hw_unregister_fixed_factor(pll_10nm->byte_clk_hw);

> +err_bit_clk_hw:

> +	clk_hw_unregister_divider(pll_10nm->bit_clk_hw);

> +err_out_div_clk_hw:

> +	clk_hw_unregister_divider(pll_10nm->out_div_clk_hw);

> +err_base_clk_hw:

> +	clk_hw_unregister(&pll_10nm->base.clk_hw);

> +

> +	return ret;

> +}

> +

> +struct msm_dsi_pll *msm_dsi_pll_10nm_init(struct platform_device 

> *pdev, int id)

> +{

> +	struct dsi_pll_10nm *pll_10nm;

> +	struct msm_dsi_pll *pll;

> +	int ret;

> +

> +	pll_10nm = devm_kzalloc(&pdev->dev, sizeof(*pll_10nm), GFP_KERNEL);

> +	if (!pll_10nm)

> +		return ERR_PTR(-ENOMEM);

> +

> +	DBG("DSI PLL%d", id);

> +

> +	pll_10nm->pdev = pdev;

> +	pll_10nm->id = id;

> +	pll_10nm_list[id] = pll_10nm;

> +

> +	pll_10nm->phy_cmn_mmio = msm_ioremap(pdev, "dsi_phy", "DSI_PHY");

> +	if (IS_ERR_OR_NULL(pll_10nm->phy_cmn_mmio)) {

> +		DRM_DEV_ERROR(&pdev->dev, "failed to map CMN PHY base\n");

> +		return ERR_PTR(-ENOMEM);

> +	}

> +

> +	pll_10nm->mmio = msm_ioremap(pdev, "dsi_pll", "DSI_PLL");

> +	if (IS_ERR_OR_NULL(pll_10nm->mmio)) {

> +		DRM_DEV_ERROR(&pdev->dev, "failed to map PLL base\n");

> +		return ERR_PTR(-ENOMEM);

> +	}

> +

> +	spin_lock_init(&pll_10nm->postdiv_lock);

> +

> +	pll = &pll_10nm->base;

> +	pll->min_rate = 1000000000UL;

> +	pll->max_rate = 3500000000UL;

> +	pll->get_provider = dsi_pll_10nm_get_provider;

> +	pll->destroy = dsi_pll_10nm_destroy;

> +	pll->save_state = dsi_pll_10nm_save_state;

> +	pll->restore_state = dsi_pll_10nm_restore_state;

> +	pll->set_usecase = dsi_pll_10nm_set_usecase;

> +

> +	pll_10nm->vco_delay = 1;

> +

> +	ret = pll_10nm_register(pll_10nm);

> +	if (ret) {

> +		DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret);

> +		return ERR_PTR(ret);

> +	}

> +

> +	/* TODO: Remove this when we have proper display handover support */

> +	msm_dsi_pll_save_state(pll);

> +

> +	return pll;

> +}

> +

>  static int dsi_phy_hw_v3_0_is_pll_on(struct msm_dsi_phy *phy)

>  {

>  	void __iomem *base = phy->base;

> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c

> b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c

> index 6989730b5fbd..6a63901da7a4 100644

> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c

> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c

> @@ -3,13 +3,1102 @@

>   * Copyright (c) 2016, The Linux Foundation. All rights reserved.

>   */

> 

> +#include <linux/clk.h>

> +#include <linux/clk-provider.h>

>  #include <linux/delay.h>

> 

>  #include "dsi_phy.h"

> +#include "dsi_pll.h"

>  #include "dsi.xml.h"

> 

>  #define PHY_14NM_CKLN_IDX	4

> 

> +/*

> + * DSI PLL 14nm - clock diagram (eg: DSI0):

> + *

> + *         dsi0n1_postdiv_clk

> + *                         |

> + *                         |

> + *                 +----+  |  +----+

> + *  dsi0vco_clk ---| n1 |--o--| /8 |-- dsi0pllbyte

> + *                 +----+  |  +----+

> + *                         |           dsi0n1_postdivby2_clk

> + *                         |   +----+  |

> + *                         o---| /2 |--o--|\

> + *                         |   +----+     | \   +----+

> + *                         |              |  |--| n2 |-- dsi0pll

> + *                         o--------------| /   +----+

> + *                                        |/

> + */

> +

> +#define POLL_MAX_READS			15

> +#define POLL_TIMEOUT_US			1000

> +

> +#define NUM_PROVIDED_CLKS		2

> +

> +#define VCO_REF_CLK_RATE		19200000

> +#define VCO_MIN_RATE			1300000000UL

> +#define VCO_MAX_RATE			2600000000UL

> +

> +#define DSI_BYTE_PLL_CLK		0

> +#define DSI_PIXEL_PLL_CLK		1

> +

> +#define DSI_PLL_DEFAULT_VCO_POSTDIV	1

> +

> +struct dsi_pll_input {

> +	u32 fref;	/* reference clk */

> +	u32 fdata;	/* bit clock rate */

> +	u32 dsiclk_sel; /* Mux configuration (see diagram) */

> +	u32 ssc_en;	/* SSC enable/disable */

> +	u32 ldo_en;

> +

> +	/* fixed params */

> +	u32 refclk_dbler_en;

> +	u32 vco_measure_time;

> +	u32 kvco_measure_time;

> +	u32 bandgap_timer;

> +	u32 pll_wakeup_timer;

> +	u32 plllock_cnt;

> +	u32 plllock_rng;

> +	u32 ssc_center;

> +	u32 ssc_adj_period;

> +	u32 ssc_spread;

> +	u32 ssc_freq;

> +	u32 pll_ie_trim;

> +	u32 pll_ip_trim;

> +	u32 pll_iptat_trim;

> +	u32 pll_cpcset_cur;

> +	u32 pll_cpmset_cur;

> +

> +	u32 pll_icpmset;

> +	u32 pll_icpcset;

> +

> +	u32 pll_icpmset_p;

> +	u32 pll_icpmset_m;

> +

> +	u32 pll_icpcset_p;

> +	u32 pll_icpcset_m;

> +

> +	u32 pll_lpf_res1;

> +	u32 pll_lpf_cap1;

> +	u32 pll_lpf_cap2;

> +	u32 pll_c3ctrl;

> +	u32 pll_r3ctrl;

> +};

> +

> +struct dsi_pll_output {

> +	u32 pll_txclk_en;

> +	u32 dec_start;

> +	u32 div_frac_start;

> +	u32 ssc_period;

> +	u32 ssc_step_size;

> +	u32 plllock_cmp;

> +	u32 pll_vco_div_ref;

> +	u32 pll_vco_count;

> +	u32 pll_kvco_div_ref;

> +	u32 pll_kvco_count;

> +	u32 pll_misc1;

> +	u32 pll_lpf2_postdiv;

> +	u32 pll_resetsm_cntrl;

> +	u32 pll_resetsm_cntrl2;

> +	u32 pll_resetsm_cntrl5;

> +	u32 pll_kvco_code;

> +

> +	u32 cmn_clk_cfg0;

> +	u32 cmn_clk_cfg1;

> +	u32 cmn_ldo_cntrl;

> +

> +	u32 pll_postdiv;

> +	u32 fcvo;

> +};

> +

> +struct pll_14nm_cached_state {

> +	unsigned long vco_rate;

> +	u8 n2postdiv;

> +	u8 n1postdiv;

> +};

> +

> +struct dsi_pll_14nm {

> +	struct msm_dsi_pll base;

> +

> +	int id;

> +	struct platform_device *pdev;

> +

> +	void __iomem *phy_cmn_mmio;

> +	void __iomem *mmio;

> +

> +	int vco_delay;

> +

> +	struct dsi_pll_input in;

> +	struct dsi_pll_output out;

> +

> +	/* protects REG_DSI_14nm_PHY_CMN_CLK_CFG0 register */

> +	spinlock_t postdiv_lock;

> +

> +	u64 vco_current_rate;

> +	u64 vco_ref_clk_rate;

> +

> +	/* private clocks: */

> +	struct clk_hw *hws[NUM_DSI_CLOCKS_MAX];

> +	u32 num_hws;

> +

> +	/* clock-provider: */

> +	struct clk_hw_onecell_data *hw_data;

> +

> +	struct pll_14nm_cached_state cached_state;

> +

> +	enum msm_dsi_phy_usecase uc;

> +	struct dsi_pll_14nm *slave;

> +};

> +

> +#define to_pll_14nm(x)	container_of(x, struct dsi_pll_14nm, base)

> +

> +/*

> + * Private struct for N1/N2 post-divider clocks. These clocks are 

> similar to

> + * the generic clk_divider class of clocks. The only difference is 

> that it

> + * also sets the slave DSI PLL's post-dividers if in Dual DSI mode

> + */

> +struct dsi_pll_14nm_postdiv {

> +	struct clk_hw hw;

> +

> +	/* divider params */

> +	u8 shift;

> +	u8 width;

> +	u8 flags; /* same flags as used by clk_divider struct */

> +

> +	struct dsi_pll_14nm *pll;

> +};

> +

> +#define to_pll_14nm_postdiv(_hw) container_of(_hw, struct

> dsi_pll_14nm_postdiv, hw)

> +

> +/*

> + * Global list of private DSI PLL struct pointers. We need this for 

> Dual DSI

> + * mode, where the master PLL's clk_ops needs access the slave's 

> private data

> + */

> +static struct dsi_pll_14nm *pll_14nm_list[DSI_MAX];

> +

> +static bool pll_14nm_poll_for_ready(struct dsi_pll_14nm *pll_14nm,

> +				    u32 nb_tries, u32 timeout_us)

> +{

> +	bool pll_locked = false;

> +	void __iomem *base = pll_14nm->mmio;

> +	u32 tries, val;

> +

> +	tries = nb_tries;

> +	while (tries--) {

> +		val = pll_read(base +

> +			       REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS);

> +		pll_locked = !!(val & BIT(5));

> +

> +		if (pll_locked)

> +			break;

> +

> +		udelay(timeout_us);

> +	}

> +

> +	if (!pll_locked) {

> +		tries = nb_tries;

> +		while (tries--) {

> +			val = pll_read(base +

> +				REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS);

> +			pll_locked = !!(val & BIT(0));

> +

> +			if (pll_locked)

> +				break;

> +

> +			udelay(timeout_us);

> +		}

> +	}

> +

> +	DBG("DSI PLL is %slocked", pll_locked ? "" : "*not* ");

> +

> +	return pll_locked;

> +}

> +

> +static void dsi_pll_14nm_input_init(struct dsi_pll_14nm *pll)

> +{

> +	pll->in.fref = pll->vco_ref_clk_rate;

> +	pll->in.fdata = 0;

> +	pll->in.dsiclk_sel = 1;	/* Use the /2 path in Mux */

> +	pll->in.ldo_en = 0;	/* disabled for now */

> +

> +	/* fixed input */

> +	pll->in.refclk_dbler_en = 0;

> +	pll->in.vco_measure_time = 5;

> +	pll->in.kvco_measure_time = 5;

> +	pll->in.bandgap_timer = 4;

> +	pll->in.pll_wakeup_timer = 5;

> +	pll->in.plllock_cnt = 1;

> +	pll->in.plllock_rng = 0;

> +

> +	/*

> +	 * SSC is enabled by default. We might need DT props for configuring

> +	 * some SSC params like PPM and center/down spread etc.

> +	 */

> +	pll->in.ssc_en = 1;

> +	pll->in.ssc_center = 0;		/* down spread by default */

> +	pll->in.ssc_spread = 5;		/* PPM / 1000 */

> +	pll->in.ssc_freq = 31500;	/* default recommended */

> +	pll->in.ssc_adj_period = 37;

> +

> +	pll->in.pll_ie_trim = 4;

> +	pll->in.pll_ip_trim = 4;

> +	pll->in.pll_cpcset_cur = 1;

> +	pll->in.pll_cpmset_cur = 1;

> +	pll->in.pll_icpmset = 4;

> +	pll->in.pll_icpcset = 4;

> +	pll->in.pll_icpmset_p = 0;

> +	pll->in.pll_icpmset_m = 0;

> +	pll->in.pll_icpcset_p = 0;

> +	pll->in.pll_icpcset_m = 0;

> +	pll->in.pll_lpf_res1 = 3;

> +	pll->in.pll_lpf_cap1 = 11;

> +	pll->in.pll_lpf_cap2 = 1;

> +	pll->in.pll_iptat_trim = 7;

> +	pll->in.pll_c3ctrl = 2;

> +	pll->in.pll_r3ctrl = 1;

> +}

> +

> +#define CEIL(x, y)		(((x) + ((y) - 1)) / (y))

> +

> +static void pll_14nm_ssc_calc(struct dsi_pll_14nm *pll)

> +{

> +	u32 period, ssc_period;

> +	u32 ref, rem;

> +	u64 step_size;

> +

> +	DBG("vco=%lld ref=%lld", pll->vco_current_rate, 

> pll->vco_ref_clk_rate);

> +

> +	ssc_period = pll->in.ssc_freq / 500;

> +	period = (u32)pll->vco_ref_clk_rate / 1000;

> +	ssc_period  = CEIL(period, ssc_period);

> +	ssc_period -= 1;

> +	pll->out.ssc_period = ssc_period;

> +

> +	DBG("ssc freq=%d spread=%d period=%d", pll->in.ssc_freq,

> +	    pll->in.ssc_spread, pll->out.ssc_period);

> +

> +	step_size = (u32)pll->vco_current_rate;

> +	ref = pll->vco_ref_clk_rate;

> +	ref /= 1000;

> +	step_size = div_u64(step_size, ref);

> +	step_size <<= 20;

> +	step_size = div_u64(step_size, 1000);

> +	step_size *= pll->in.ssc_spread;

> +	step_size = div_u64(step_size, 1000);

> +	step_size *= (pll->in.ssc_adj_period + 1);

> +

> +	rem = 0;

> +	step_size = div_u64_rem(step_size, ssc_period + 1, &rem);

> +	if (rem)

> +		step_size++;

> +

> +	DBG("step_size=%lld", step_size);

> +

> +	step_size &= 0x0ffff;	/* take lower 16 bits */

> +

> +	pll->out.ssc_step_size = step_size;

> +}

> +

> +static void pll_14nm_dec_frac_calc(struct dsi_pll_14nm *pll)

> +{

> +	struct dsi_pll_input *pin = &pll->in;

> +	struct dsi_pll_output *pout = &pll->out;

> +	u64 multiplier = BIT(20);

> +	u64 dec_start_multiple, dec_start, pll_comp_val;

> +	u32 duration, div_frac_start;

> +	u64 vco_clk_rate = pll->vco_current_rate;

> +	u64 fref = pll->vco_ref_clk_rate;

> +

> +	DBG("vco_clk_rate=%lld ref_clk_rate=%lld", vco_clk_rate, fref);

> +

> +	dec_start_multiple = div_u64(vco_clk_rate * multiplier, fref);

> +	div_u64_rem(dec_start_multiple, multiplier, &div_frac_start);

> +

> +	dec_start = div_u64(dec_start_multiple, multiplier);

> +

> +	pout->dec_start = (u32)dec_start;

> +	pout->div_frac_start = div_frac_start;

> +

> +	if (pin->plllock_cnt == 0)

> +		duration = 1024;

> +	else if (pin->plllock_cnt == 1)

> +		duration = 256;

> +	else if (pin->plllock_cnt == 2)

> +		duration = 128;

> +	else

> +		duration = 32;

> +

> +	pll_comp_val = duration * dec_start_multiple;

> +	pll_comp_val = div_u64(pll_comp_val, multiplier);

> +	do_div(pll_comp_val, 10);

> +

> +	pout->plllock_cmp = (u32)pll_comp_val;

> +

> +	pout->pll_txclk_en = 1;

> +	pout->cmn_ldo_cntrl = 0x3c;

> +}

> +

> +static u32 pll_14nm_kvco_slop(u32 vrate)

> +{

> +	u32 slop = 0;

> +

> +	if (vrate > VCO_MIN_RATE && vrate <= 1800000000UL)

> +		slop =  600;

> +	else if (vrate > 1800000000UL && vrate < 2300000000UL)

> +		slop = 400;

> +	else if (vrate > 2300000000UL && vrate < VCO_MAX_RATE)

> +		slop = 280;

> +

> +	return slop;

> +}

> +

> +static void pll_14nm_calc_vco_count(struct dsi_pll_14nm *pll)

> +{

> +	struct dsi_pll_input *pin = &pll->in;

> +	struct dsi_pll_output *pout = &pll->out;

> +	u64 vco_clk_rate = pll->vco_current_rate;

> +	u64 fref = pll->vco_ref_clk_rate;

> +	u64 data;

> +	u32 cnt;

> +

> +	data = fref * pin->vco_measure_time;

> +	do_div(data, 1000000);

> +	data &= 0x03ff;	/* 10 bits */

> +	data -= 2;

> +	pout->pll_vco_div_ref = data;

> +

> +	data = div_u64(vco_clk_rate, 1000000);	/* unit is Mhz */

> +	data *= pin->vco_measure_time;

> +	do_div(data, 10);

> +	pout->pll_vco_count = data;

> +

> +	data = fref * pin->kvco_measure_time;

> +	do_div(data, 1000000);

> +	data &= 0x03ff;	/* 10 bits */

> +	data -= 1;

> +	pout->pll_kvco_div_ref = data;

> +

> +	cnt = pll_14nm_kvco_slop(vco_clk_rate);

> +	cnt *= 2;

> +	cnt /= 100;

> +	cnt *= pin->kvco_measure_time;

> +	pout->pll_kvco_count = cnt;

> +

> +	pout->pll_misc1 = 16;

> +	pout->pll_resetsm_cntrl = 48;

> +	pout->pll_resetsm_cntrl2 = pin->bandgap_timer << 3;

> +	pout->pll_resetsm_cntrl5 = pin->pll_wakeup_timer;

> +	pout->pll_kvco_code = 0;

> +}

> +

> +static void pll_db_commit_ssc(struct dsi_pll_14nm *pll)

> +{

> +	void __iomem *base = pll->mmio;

> +	struct dsi_pll_input *pin = &pll->in;

> +	struct dsi_pll_output *pout = &pll->out;

> +	u8 data;

> +

> +	data = pin->ssc_adj_period;

> +	data &= 0x0ff;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_ADJ_PER1, data);

> +	data = (pin->ssc_adj_period >> 8);

> +	data &= 0x03;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_ADJ_PER2, data);

> +

> +	data = pout->ssc_period;

> +	data &= 0x0ff;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_PER1, data);

> +	data = (pout->ssc_period >> 8);

> +	data &= 0x0ff;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_PER2, data);

> +

> +	data = pout->ssc_step_size;

> +	data &= 0x0ff;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_STEP_SIZE1, data);

> +	data = (pout->ssc_step_size >> 8);

> +	data &= 0x0ff;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_STEP_SIZE2, data);

> +

> +	data = (pin->ssc_center & 0x01);

> +	data <<= 1;

> +	data |= 0x01; /* enable */

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_EN_CENTER, data);

> +

> +	wmb();	/* make sure register committed */

> +}

> +

> +static void pll_db_commit_common(struct dsi_pll_14nm *pll,

> +				 struct dsi_pll_input *pin,

> +				 struct dsi_pll_output *pout)

> +{

> +	void __iomem *base = pll->mmio;

> +	u8 data;

> +

> +	/* confgiure the non frequency dependent pll registers */

> +	data = 0;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_SYSCLK_EN_RESET, data);

> +

> +	data = pout->pll_txclk_en;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_TXCLK_EN, data);

> +

> +	data = pout->pll_resetsm_cntrl;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL, data);

> +	data = pout->pll_resetsm_cntrl2;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL2, data);

> +	data = pout->pll_resetsm_cntrl5;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL5, data);

> +

> +	data = pout->pll_vco_div_ref & 0xff;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_VCO_DIV_REF1, data);

> +	data = (pout->pll_vco_div_ref >> 8) & 0x3;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_VCO_DIV_REF2, data);

> +

> +	data = pout->pll_kvco_div_ref & 0xff;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_KVCO_DIV_REF1, data);

> +	data = (pout->pll_kvco_div_ref >> 8) & 0x3;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_KVCO_DIV_REF2, data);

> +

> +	data = pout->pll_misc1;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_MISC1, data);

> +

> +	data = pin->pll_ie_trim;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_IE_TRIM, data);

> +

> +	data = pin->pll_ip_trim;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_IP_TRIM, data);

> +

> +	data = pin->pll_cpmset_cur << 3 | pin->pll_cpcset_cur;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_CP_SET_CUR, data);

> +

> +	data = pin->pll_icpcset_p << 3 | pin->pll_icpcset_m;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_ICPCSET, data);

> +

> +	data = pin->pll_icpmset_p << 3 | pin->pll_icpcset_m;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_ICPMSET, data);

> +

> +	data = pin->pll_icpmset << 3 | pin->pll_icpcset;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_ICP_SET, data);

> +

> +	data = pin->pll_lpf_cap2 << 4 | pin->pll_lpf_cap1;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_LPF1, data);

> +

> +	data = pin->pll_iptat_trim;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_IPTAT_TRIM, data);

> +

> +	data = pin->pll_c3ctrl | pin->pll_r3ctrl << 4;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_CRCTRL, data);

> +}

> +

> +static void pll_14nm_software_reset(struct dsi_pll_14nm *pll_14nm)

> +{

> +	void __iomem *cmn_base = pll_14nm->phy_cmn_mmio;

> +

> +	/* de assert pll start and apply pll sw reset */

> +

> +	/* stop pll */

> +	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL, 0);

> +

> +	/* pll sw reset */

> +	pll_write_udelay(cmn_base + REG_DSI_14nm_PHY_CMN_CTRL_1, 0x20, 10);

> +	wmb();	/* make sure register committed */

> +

> +	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_CTRL_1, 0);

> +	wmb();	/* make sure register committed */

> +}

> +

> +static void pll_db_commit_14nm(struct dsi_pll_14nm *pll,

> +			       struct dsi_pll_input *pin,

> +			       struct dsi_pll_output *pout)

> +{

> +	void __iomem *base = pll->mmio;

> +	void __iomem *cmn_base = pll->phy_cmn_mmio;

> +	u8 data;

> +

> +	DBG("DSI%d PLL", pll->id);

> +

> +	data = pout->cmn_ldo_cntrl;

> +	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_LDO_CNTRL, data);

> +

> +	pll_db_commit_common(pll, pin, pout);

> +

> +	pll_14nm_software_reset(pll);

> +

> +	data = pin->dsiclk_sel; /* set dsiclk_sel = 1  */

> +	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_CLK_CFG1, data);

> +

> +	data = 0xff; /* data, clk, pll normal operation */

> +	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_CTRL_0, data);

> +

> +	/* configure the frequency dependent pll registers */

> +	data = pout->dec_start;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_DEC_START, data);

> +

> +	data = pout->div_frac_start & 0xff;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START1, data);

> +	data = (pout->div_frac_start >> 8) & 0xff;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START2, data);

> +	data = (pout->div_frac_start >> 16) & 0xf;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START3, data);

> +

> +	data = pout->plllock_cmp & 0xff;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP1, data);

> +

> +	data = (pout->plllock_cmp >> 8) & 0xff;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP2, data);

> +

> +	data = (pout->plllock_cmp >> 16) & 0x3;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP3, data);

> +

> +	data = pin->plllock_cnt << 1 | pin->plllock_rng << 3;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP_EN, data);

> +

> +	data = pout->pll_vco_count & 0xff;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_VCO_COUNT1, data);

> +	data = (pout->pll_vco_count >> 8) & 0xff;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_VCO_COUNT2, data);

> +

> +	data = pout->pll_kvco_count & 0xff;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_KVCO_COUNT1, data);

> +	data = (pout->pll_kvco_count >> 8) & 0x3;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_KVCO_COUNT2, data);

> +

> +	data = (pout->pll_postdiv - 1) << 4 | pin->pll_lpf_res1;

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_LPF2_POSTDIV, data);

> +

> +	if (pin->ssc_en)

> +		pll_db_commit_ssc(pll);

> +

> +	wmb();	/* make sure register committed */

> +}

> +

> +/*

> + * VCO clock Callbacks

> + */

> +static int dsi_pll_14nm_vco_set_rate(struct clk_hw *hw, unsigned long 

> rate,

> +				     unsigned long parent_rate)

> +{

> +	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> +	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);

> +	struct dsi_pll_input *pin = &pll_14nm->in;

> +	struct dsi_pll_output *pout = &pll_14nm->out;

> +

> +	DBG("DSI PLL%d rate=%lu, parent's=%lu", pll_14nm->id, rate,

> +	    parent_rate);

> +

> +	pll_14nm->vco_current_rate = rate;

> +	pll_14nm->vco_ref_clk_rate = VCO_REF_CLK_RATE;

> +

> +	dsi_pll_14nm_input_init(pll_14nm);

> +

> +	/*

> +	 * This configures the post divider internal to the VCO. It's

> +	 * fixed to divide by 1 for now.

> +	 *

> +	 * tx_band = pll_postdiv.

> +	 * 0: divided by 1

> +	 * 1: divided by 2

> +	 * 2: divided by 4

> +	 * 3: divided by 8

> +	 */

> +	pout->pll_postdiv = DSI_PLL_DEFAULT_VCO_POSTDIV;

> +

> +	pll_14nm_dec_frac_calc(pll_14nm);

> +

> +	if (pin->ssc_en)

> +		pll_14nm_ssc_calc(pll_14nm);

> +

> +	pll_14nm_calc_vco_count(pll_14nm);

> +

> +	/* commit the slave DSI PLL registers if we're master. Note that we

> +	 * don't lock the slave PLL. We just ensure that the PLL/PHY 

> registers

> +	 * of the master and slave are identical

> +	 */

> +	if (pll_14nm->uc == MSM_DSI_PHY_MASTER) {

> +		struct dsi_pll_14nm *pll_14nm_slave = pll_14nm->slave;

> +

> +		pll_db_commit_14nm(pll_14nm_slave, pin, pout);

> +	}

> +

> +	pll_db_commit_14nm(pll_14nm, pin, pout);

> +

> +	return 0;

> +}

> +

> +static unsigned long dsi_pll_14nm_vco_recalc_rate(struct clk_hw *hw,

> +						  unsigned long parent_rate)

> +{

> +	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> +	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);

> +	void __iomem *base = pll_14nm->mmio;

> +	u64 vco_rate, multiplier = BIT(20);

> +	u32 div_frac_start;

> +	u32 dec_start;

> +	u64 ref_clk = parent_rate;

> +

> +	dec_start = pll_read(base + REG_DSI_14nm_PHY_PLL_DEC_START);

> +	dec_start &= 0x0ff;

> +

> +	DBG("dec_start = %x", dec_start);

> +

> +	div_frac_start = (pll_read(base + 

> REG_DSI_14nm_PHY_PLL_DIV_FRAC_START3)

> +				& 0xf) << 16;

> +	div_frac_start |= (pll_read(base + 

> REG_DSI_14nm_PHY_PLL_DIV_FRAC_START2)

> +				& 0xff) << 8;

> +	div_frac_start |= pll_read(base + 

> REG_DSI_14nm_PHY_PLL_DIV_FRAC_START1)

> +				& 0xff;

> +

> +	DBG("div_frac_start = %x", div_frac_start);

> +

> +	vco_rate = ref_clk * dec_start;

> +

> +	vco_rate += ((ref_clk * div_frac_start) / multiplier);

> +

> +	/*

> +	 * Recalculating the rate from dec_start and frac_start doesn't end 

> up

> +	 * the rate we originally set. Convert the freq to KHz, round it up 

> and

> +	 * convert it back to MHz.

> +	 */

> +	vco_rate = DIV_ROUND_UP_ULL(vco_rate, 1000) * 1000;

> +

> +	DBG("returning vco rate = %lu", (unsigned long)vco_rate);

> +

> +	return (unsigned long)vco_rate;

> +}

> +

> +static const struct clk_ops clk_ops_dsi_pll_14nm_vco = {

> +	.round_rate = msm_dsi_pll_helper_clk_round_rate,

> +	.set_rate = dsi_pll_14nm_vco_set_rate,

> +	.recalc_rate = dsi_pll_14nm_vco_recalc_rate,

> +	.prepare = msm_dsi_pll_helper_clk_prepare,

> +	.unprepare = msm_dsi_pll_helper_clk_unprepare,

> +};

> +

> +/*

> + * N1 and N2 post-divider clock callbacks

> + */

> +#define div_mask(width)	((1 << (width)) - 1)

> +static unsigned long dsi_pll_14nm_postdiv_recalc_rate(struct clk_hw 

> *hw,

> +						      unsigned long parent_rate)

> +{

> +	struct dsi_pll_14nm_postdiv *postdiv = to_pll_14nm_postdiv(hw);

> +	struct dsi_pll_14nm *pll_14nm = postdiv->pll;

> +	void __iomem *base = pll_14nm->phy_cmn_mmio;

> +	u8 shift = postdiv->shift;

> +	u8 width = postdiv->width;

> +	u32 val;

> +

> +	DBG("DSI%d PLL parent rate=%lu", pll_14nm->id, parent_rate);

> +

> +	val = pll_read(base + REG_DSI_14nm_PHY_CMN_CLK_CFG0) >> shift;

> +	val &= div_mask(width);

> +

> +	return divider_recalc_rate(hw, parent_rate, val, NULL,

> +				   postdiv->flags, width);

> +}

> +

> +static long dsi_pll_14nm_postdiv_round_rate(struct clk_hw *hw,

> +					    unsigned long rate,

> +					    unsigned long *prate)

> +{

> +	struct dsi_pll_14nm_postdiv *postdiv = to_pll_14nm_postdiv(hw);

> +	struct dsi_pll_14nm *pll_14nm = postdiv->pll;

> +

> +	DBG("DSI%d PLL parent rate=%lu", pll_14nm->id, rate);

> +

> +	return divider_round_rate(hw, rate, prate, NULL,

> +				  postdiv->width,

> +				  postdiv->flags);

> +}

> +

> +static int dsi_pll_14nm_postdiv_set_rate(struct clk_hw *hw, unsigned 

> long rate,

> +					 unsigned long parent_rate)

> +{

> +	struct dsi_pll_14nm_postdiv *postdiv = to_pll_14nm_postdiv(hw);

> +	struct dsi_pll_14nm *pll_14nm = postdiv->pll;

> +	void __iomem *base = pll_14nm->phy_cmn_mmio;

> +	spinlock_t *lock = &pll_14nm->postdiv_lock;

> +	u8 shift = postdiv->shift;

> +	u8 width = postdiv->width;

> +	unsigned int value;

> +	unsigned long flags = 0;

> +	u32 val;

> +

> +	DBG("DSI%d PLL parent rate=%lu parent rate %lu", pll_14nm->id, rate,

> +	    parent_rate);

> +

> +	value = divider_get_val(rate, parent_rate, NULL, postdiv->width,

> +				postdiv->flags);

> +

> +	spin_lock_irqsave(lock, flags);

> +

> +	val = pll_read(base + REG_DSI_14nm_PHY_CMN_CLK_CFG0);

> +	val &= ~(div_mask(width) << shift);

> +

> +	val |= value << shift;

> +	pll_write(base + REG_DSI_14nm_PHY_CMN_CLK_CFG0, val);

> +

> +	/* If we're master in dual DSI mode, then the slave PLL's 

> post-dividers

> +	 * follow the master's post dividers

> +	 */

> +	if (pll_14nm->uc == MSM_DSI_PHY_MASTER) {

> +		struct dsi_pll_14nm *pll_14nm_slave = pll_14nm->slave;

> +		void __iomem *slave_base = pll_14nm_slave->phy_cmn_mmio;

> +

> +		pll_write(slave_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0, val);

> +	}

> +

> +	spin_unlock_irqrestore(lock, flags);

> +

> +	return 0;

> +}

> +

> +static const struct clk_ops clk_ops_dsi_pll_14nm_postdiv = {

> +	.recalc_rate = dsi_pll_14nm_postdiv_recalc_rate,

> +	.round_rate = dsi_pll_14nm_postdiv_round_rate,

> +	.set_rate = dsi_pll_14nm_postdiv_set_rate,

> +};

> +

> +/*

> + * PLL Callbacks

> + */

> +

> +static int dsi_pll_14nm_enable_seq(struct msm_dsi_pll *pll)

> +{

> +	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);

> +	void __iomem *base = pll_14nm->mmio;

> +	void __iomem *cmn_base = pll_14nm->phy_cmn_mmio;

> +	bool locked;

> +

> +	DBG("");

> +

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_VREF_CFG1, 0x10);

> +	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL, 1);

> +

> +	locked = pll_14nm_poll_for_ready(pll_14nm, POLL_MAX_READS,

> +					 POLL_TIMEOUT_US);

> +

> +	if (unlikely(!locked))

> +		DRM_DEV_ERROR(&pll_14nm->pdev->dev, "DSI PLL lock failed\n");

> +	else

> +		DBG("DSI PLL lock success");

> +

> +	return locked ? 0 : -EINVAL;

> +}

> +

> +static void dsi_pll_14nm_disable_seq(struct msm_dsi_pll *pll)

> +{

> +	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);

> +	void __iomem *cmn_base = pll_14nm->phy_cmn_mmio;

> +

> +	DBG("");

> +

> +	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL, 0);

> +}

> +

> +static void dsi_pll_14nm_save_state(struct msm_dsi_pll *pll)

> +{

> +	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);

> +	struct pll_14nm_cached_state *cached_state = &pll_14nm->cached_state;

> +	void __iomem *cmn_base = pll_14nm->phy_cmn_mmio;

> +	u32 data;

> +

> +	data = pll_read(cmn_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0);

> +

> +	cached_state->n1postdiv = data & 0xf;

> +	cached_state->n2postdiv = (data >> 4) & 0xf;

> +

> +	DBG("DSI%d PLL save state %x %x", pll_14nm->id,

> +	    cached_state->n1postdiv, cached_state->n2postdiv);

> +

> +	cached_state->vco_rate = clk_hw_get_rate(&pll->clk_hw);

> +}

> +

> +static int dsi_pll_14nm_restore_state(struct msm_dsi_pll *pll)

> +{

> +	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);

> +	struct pll_14nm_cached_state *cached_state = &pll_14nm->cached_state;

> +	void __iomem *cmn_base = pll_14nm->phy_cmn_mmio;

> +	u32 data;

> +	int ret;

> +

> +	ret = dsi_pll_14nm_vco_set_rate(&pll->clk_hw,

> +					cached_state->vco_rate, 0);

> +	if (ret) {

> +		DRM_DEV_ERROR(&pll_14nm->pdev->dev,

> +			"restore vco rate failed. ret=%d\n", ret);

> +		return ret;

> +	}

> +

> +	data = cached_state->n1postdiv | (cached_state->n2postdiv << 4);

> +

> +	DBG("DSI%d PLL restore state %x %x", pll_14nm->id,

> +	    cached_state->n1postdiv, cached_state->n2postdiv);

> +

> +	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0, data);

> +

> +	/* also restore post-dividers for slave DSI PLL */

> +	if (pll_14nm->uc == MSM_DSI_PHY_MASTER) {

> +		struct dsi_pll_14nm *pll_14nm_slave = pll_14nm->slave;

> +		void __iomem *slave_base = pll_14nm_slave->phy_cmn_mmio;

> +

> +		pll_write(slave_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0, data);

> +	}

> +

> +	return 0;

> +}

> +

> +static int dsi_pll_14nm_set_usecase(struct msm_dsi_pll *pll,

> +				    enum msm_dsi_phy_usecase uc)

> +{

> +	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);

> +	void __iomem *base = pll_14nm->mmio;

> +	u32 clkbuflr_en, bandgap = 0;

> +

> +	switch (uc) {

> +	case MSM_DSI_PHY_STANDALONE:

> +		clkbuflr_en = 0x1;

> +		break;

> +	case MSM_DSI_PHY_MASTER:

> +		clkbuflr_en = 0x3;

> +		pll_14nm->slave = pll_14nm_list[(pll_14nm->id + 1) % DSI_MAX];

> +		break;

> +	case MSM_DSI_PHY_SLAVE:

> +		clkbuflr_en = 0x0;

> +		bandgap = 0x3;

> +		break;

> +	default:

> +		return -EINVAL;

> +	}

> +

> +	pll_write(base + REG_DSI_14nm_PHY_PLL_CLKBUFLR_EN, clkbuflr_en);

> +	if (bandgap)

> +		pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_BANDGAP, bandgap);

> +

> +	pll_14nm->uc = uc;

> +

> +	return 0;

> +}

> +

> +static int dsi_pll_14nm_get_provider(struct msm_dsi_pll *pll,

> +				     struct clk **byte_clk_provider,

> +				     struct clk **pixel_clk_provider)

> +{

> +	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);

> +	struct clk_hw_onecell_data *hw_data = pll_14nm->hw_data;

> +

> +	if (byte_clk_provider)

> +		*byte_clk_provider = hw_data->hws[DSI_BYTE_PLL_CLK]->clk;

> +	if (pixel_clk_provider)

> +		*pixel_clk_provider = hw_data->hws[DSI_PIXEL_PLL_CLK]->clk;

> +

> +	return 0;

> +}

> +

> +static void dsi_pll_14nm_destroy(struct msm_dsi_pll *pll)

> +{

> +	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);

> +	struct platform_device *pdev = pll_14nm->pdev;

> +	int num_hws = pll_14nm->num_hws;

> +

> +	of_clk_del_provider(pdev->dev.of_node);

> +

> +	while (num_hws--)

> +		clk_hw_unregister(pll_14nm->hws[num_hws]);

> +}

> +

> +static struct clk_hw *pll_14nm_postdiv_register(struct dsi_pll_14nm 

> *pll_14nm,

> +						const char *name,

> +						const char *parent_name,

> +						unsigned long flags,

> +						u8 shift)

> +{

> +	struct dsi_pll_14nm_postdiv *pll_postdiv;

> +	struct device *dev = &pll_14nm->pdev->dev;

> +	struct clk_init_data postdiv_init = {

> +		.parent_names = (const char *[]) { parent_name },

> +		.num_parents = 1,

> +		.name = name,

> +		.flags = flags,

> +		.ops = &clk_ops_dsi_pll_14nm_postdiv,

> +	};

> +	int ret;

> +

> +	pll_postdiv = devm_kzalloc(dev, sizeof(*pll_postdiv), GFP_KERNEL);

> +	if (!pll_postdiv)

> +		return ERR_PTR(-ENOMEM);

> +

> +	pll_postdiv->pll = pll_14nm;

> +	pll_postdiv->shift = shift;

> +	/* both N1 and N2 postdividers are 4 bits wide */

> +	pll_postdiv->width = 4;

> +	/* range of each divider is from 1 to 15 */

> +	pll_postdiv->flags = CLK_DIVIDER_ONE_BASED;

> +	pll_postdiv->hw.init = &postdiv_init;

> +

> +	ret = clk_hw_register(dev, &pll_postdiv->hw);

> +	if (ret)

> +		return ERR_PTR(ret);

> +

> +	return &pll_postdiv->hw;

> +}

> +

> +static int pll_14nm_register(struct dsi_pll_14nm *pll_14nm)

> +{

> +	char clk_name[32], parent[32], vco_name[32];

> +	struct clk_init_data vco_init = {

> +		.parent_names = (const char *[]){ "xo" },

> +		.num_parents = 1,

> +		.name = vco_name,

> +		.flags = CLK_IGNORE_UNUSED,

> +		.ops = &clk_ops_dsi_pll_14nm_vco,

> +	};

> +	struct device *dev = &pll_14nm->pdev->dev;

> +	struct clk_hw **hws = pll_14nm->hws;

> +	struct clk_hw_onecell_data *hw_data;

> +	struct clk_hw *hw;

> +	int num = 0;

> +	int ret;

> +

> +	DBG("DSI%d", pll_14nm->id);

> +

> +	hw_data = devm_kzalloc(dev, sizeof(*hw_data) +

> +			       NUM_PROVIDED_CLKS * sizeof(struct clk_hw *),

> +			       GFP_KERNEL);

> +	if (!hw_data)

> +		return -ENOMEM;

> +

> +	snprintf(vco_name, 32, "dsi%dvco_clk", pll_14nm->id);

> +	pll_14nm->base.clk_hw.init = &vco_init;

> +

> +	ret = clk_hw_register(dev, &pll_14nm->base.clk_hw);

> +	if (ret)

> +		return ret;

> +

> +	hws[num++] = &pll_14nm->base.clk_hw;

> +

> +	snprintf(clk_name, 32, "dsi%dn1_postdiv_clk", pll_14nm->id);

> +	snprintf(parent, 32, "dsi%dvco_clk", pll_14nm->id);

> +

> +	/* N1 postdiv, bits 0-3 in REG_DSI_14nm_PHY_CMN_CLK_CFG0 */

> +	hw = pll_14nm_postdiv_register(pll_14nm, clk_name, parent,

> +				       CLK_SET_RATE_PARENT, 0);

> +	if (IS_ERR(hw))

> +		return PTR_ERR(hw);

> +

> +	hws[num++] = hw;

> +

> +	snprintf(clk_name, 32, "dsi%dpllbyte", pll_14nm->id);

> +	snprintf(parent, 32, "dsi%dn1_postdiv_clk", pll_14nm->id);

> +

> +	/* DSI Byte clock = VCO_CLK / N1 / 8 */

> +	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,

> +					  CLK_SET_RATE_PARENT, 1, 8);

> +	if (IS_ERR(hw))

> +		return PTR_ERR(hw);

> +

> +	hws[num++] = hw;

> +	hw_data->hws[DSI_BYTE_PLL_CLK] = hw;

> +

> +	snprintf(clk_name, 32, "dsi%dn1_postdivby2_clk", pll_14nm->id);

> +	snprintf(parent, 32, "dsi%dn1_postdiv_clk", pll_14nm->id);

> +

> +	/*

> +	 * Skip the mux for now, force DSICLK_SEL to 1, Add a /2 divider

> +	 * on the way. Don't let it set parent.

> +	 */

> +	hw = clk_hw_register_fixed_factor(dev, clk_name, parent, 0, 1, 2);

> +	if (IS_ERR(hw))

> +		return PTR_ERR(hw);

> +

> +	hws[num++] = hw;

> +

> +	snprintf(clk_name, 32, "dsi%dpll", pll_14nm->id);

> +	snprintf(parent, 32, "dsi%dn1_postdivby2_clk", pll_14nm->id);

> +

> +	/* DSI pixel clock = VCO_CLK / N1 / 2 / N2

> +	 * This is the output of N2 post-divider, bits 4-7 in

> +	 * REG_DSI_14nm_PHY_CMN_CLK_CFG0. Don't let it set parent.

> +	 */

> +	hw = pll_14nm_postdiv_register(pll_14nm, clk_name, parent, 0, 4);

> +	if (IS_ERR(hw))

> +		return PTR_ERR(hw);

> +

> +	hws[num++] = hw;

> +	hw_data->hws[DSI_PIXEL_PLL_CLK]	= hw;

> +

> +	pll_14nm->num_hws = num;

> +

> +	hw_data->num = NUM_PROVIDED_CLKS;

> +	pll_14nm->hw_data = hw_data;

> +

> +	ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,

> +				     pll_14nm->hw_data);

> +	if (ret) {

> +		DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret);

> +		return ret;

> +	}

> +

> +	return 0;

> +}

> +

> +struct msm_dsi_pll *msm_dsi_pll_14nm_init(struct platform_device 

> *pdev, int id)

> +{

> +	struct dsi_pll_14nm *pll_14nm;

> +	struct msm_dsi_pll *pll;

> +	int ret;

> +

> +	if (!pdev)

> +		return ERR_PTR(-ENODEV);

> +

> +	pll_14nm = devm_kzalloc(&pdev->dev, sizeof(*pll_14nm), GFP_KERNEL);

> +	if (!pll_14nm)

> +		return ERR_PTR(-ENOMEM);

> +

> +	DBG("PLL%d", id);

> +

> +	pll_14nm->pdev = pdev;

> +	pll_14nm->id = id;

> +	pll_14nm_list[id] = pll_14nm;

> +

> +	pll_14nm->phy_cmn_mmio = msm_ioremap(pdev, "dsi_phy", "DSI_PHY");

> +	if (IS_ERR_OR_NULL(pll_14nm->phy_cmn_mmio)) {

> +		DRM_DEV_ERROR(&pdev->dev, "failed to map CMN PHY base\n");

> +		return ERR_PTR(-ENOMEM);

> +	}

> +

> +	pll_14nm->mmio = msm_ioremap(pdev, "dsi_pll", "DSI_PLL");

> +	if (IS_ERR_OR_NULL(pll_14nm->mmio)) {

> +		DRM_DEV_ERROR(&pdev->dev, "failed to map PLL base\n");

> +		return ERR_PTR(-ENOMEM);

> +	}

> +

> +	spin_lock_init(&pll_14nm->postdiv_lock);

> +

> +	pll = &pll_14nm->base;

> +	pll->min_rate = VCO_MIN_RATE;

> +	pll->max_rate = VCO_MAX_RATE;

> +	pll->get_provider = dsi_pll_14nm_get_provider;

> +	pll->destroy = dsi_pll_14nm_destroy;

> +	pll->disable_seq = dsi_pll_14nm_disable_seq;

> +	pll->save_state = dsi_pll_14nm_save_state;

> +	pll->restore_state = dsi_pll_14nm_restore_state;

> +	pll->set_usecase = dsi_pll_14nm_set_usecase;

> +

> +	pll_14nm->vco_delay = 1;

> +

> +	pll->en_seq_cnt = 1;

> +	pll->enable_seqs[0] = dsi_pll_14nm_enable_seq;

> +

> +	ret = pll_14nm_register(pll_14nm);

> +	if (ret) {

> +		DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret);

> +		return ERR_PTR(ret);

> +	}

> +

> +	return pll;

> +}

> +

>  static void dsi_14nm_dphy_set_timing(struct msm_dsi_phy *phy,

>  				     struct msm_dsi_dphy_timing *timing,

>  				     int lane_idx)

> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c

> b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c

> index 5bf79de0da67..2f502efa4dd5 100644

> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c

> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c

> @@ -3,9 +3,646 @@

>   * Copyright (c) 2015, The Linux Foundation. All rights reserved.

>   */

> 

> +#include <linux/clk.h>

> +#include <linux/clk-provider.h>

> +

>  #include "dsi_phy.h"

> +#include "dsi_pll.h"

>  #include "dsi.xml.h"

> 

> +/*

> + * DSI PLL 28nm - clock diagram (eg: DSI0):

> + *

> + *         dsi0analog_postdiv_clk

> + *                             |         dsi0indirect_path_div2_clk

> + *                             |          |

> + *                   +------+  |  +----+  |  |\   dsi0byte_mux

> + *  dsi0vco_clk --o--| DIV1 |--o--| /2 |--o--| \   |

> + *                |  +------+     +----+     | m|  |  +----+

> + *                |                          | u|--o--| /4 |-- 

> dsi0pllbyte

> + *                |                          | x|     +----+

> + *                o--------------------------| /

> + *                |                          |/

> + *                |          +------+

> + *                o----------| DIV3 |------------------------- dsi0pll

> + *                           +------+

> + */

> +

> +#define POLL_MAX_READS			10

> +#define POLL_TIMEOUT_US		50

> +

> +#define NUM_PROVIDED_CLKS		2

> +

> +#define VCO_REF_CLK_RATE		19200000

> +#define VCO_MIN_RATE			350000000

> +#define VCO_MAX_RATE			750000000

> +

> +#define DSI_BYTE_PLL_CLK		0

> +#define DSI_PIXEL_PLL_CLK		1

> +

> +#define LPFR_LUT_SIZE			10

> +struct lpfr_cfg {

> +	unsigned long vco_rate;

> +	u32 resistance;

> +};

> +

> +/* Loop filter resistance: */

> +static const struct lpfr_cfg lpfr_lut[LPFR_LUT_SIZE] = {

> +	{ 479500000,  8 },

> +	{ 480000000, 11 },

> +	{ 575500000,  8 },

> +	{ 576000000, 12 },

> +	{ 610500000,  8 },

> +	{ 659500000,  9 },

> +	{ 671500000, 10 },

> +	{ 672000000, 14 },

> +	{ 708500000, 10 },

> +	{ 750000000, 11 },

> +};

> +

> +struct pll_28nm_cached_state {

> +	unsigned long vco_rate;

> +	u8 postdiv3;

> +	u8 postdiv1;

> +	u8 byte_mux;

> +};

> +

> +struct dsi_pll_28nm {

> +	struct msm_dsi_pll base;

> +

> +	int id;

> +	struct platform_device *pdev;

> +	void __iomem *mmio;

> +

> +	int vco_delay;

> +

> +	/* private clocks: */

> +	struct clk *clks[NUM_DSI_CLOCKS_MAX];

> +	u32 num_clks;

> +

> +	/* clock-provider: */

> +	struct clk *provided_clks[NUM_PROVIDED_CLKS];

> +	struct clk_onecell_data clk_data;

> +

> +	struct pll_28nm_cached_state cached_state;

> +};

> +

> +#define to_pll_28nm(x)	container_of(x, struct dsi_pll_28nm, base)

> +

> +static bool pll_28nm_poll_for_ready(struct dsi_pll_28nm *pll_28nm,

> +				u32 nb_tries, u32 timeout_us)

> +{

> +	bool pll_locked = false;

> +	u32 val;

> +

> +	while (nb_tries--) {

> +		val = pll_read(pll_28nm->mmio + REG_DSI_28nm_PHY_PLL_STATUS);

> +		pll_locked = !!(val & DSI_28nm_PHY_PLL_STATUS_PLL_RDY);

> +

> +		if (pll_locked)

> +			break;

> +

> +		udelay(timeout_us);

> +	}

> +	DBG("DSI PLL is %slocked", pll_locked ? "" : "*not* ");

> +

> +	return pll_locked;

> +}

> +

> +static void pll_28nm_software_reset(struct dsi_pll_28nm *pll_28nm)

> +{

> +	void __iomem *base = pll_28nm->mmio;

> +

> +	/*

> +	 * Add HW recommended delays after toggling the software

> +	 * reset bit off and back on.

> +	 */

> +	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_TEST_CFG,

> +			DSI_28nm_PHY_PLL_TEST_CFG_PLL_SW_RESET, 1);

> +	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_TEST_CFG, 0x00, 1);

> +}

> +

> +/*

> + * Clock Callbacks

> + */

> +static int dsi_pll_28nm_clk_set_rate(struct clk_hw *hw, unsigned long 

> rate,

> +		unsigned long parent_rate)

> +{

> +	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> +	struct device *dev = &pll_28nm->pdev->dev;

> +	void __iomem *base = pll_28nm->mmio;

> +	unsigned long div_fbx1000, gen_vco_clk;

> +	u32 refclk_cfg, frac_n_mode, frac_n_value;

> +	u32 sdm_cfg0, sdm_cfg1, sdm_cfg2, sdm_cfg3;

> +	u32 cal_cfg10, cal_cfg11;

> +	u32 rem;

> +	int i;

> +

> +	VERB("rate=%lu, parent's=%lu", rate, parent_rate);

> +

> +	/* Force postdiv2 to be div-4 */

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV2_CFG, 3);

> +

> +	/* Configure the Loop filter resistance */

> +	for (i = 0; i < LPFR_LUT_SIZE; i++)

> +		if (rate <= lpfr_lut[i].vco_rate)

> +			break;

> +	if (i == LPFR_LUT_SIZE) {

> +		DRM_DEV_ERROR(dev, "unable to get loop filter resistance. 

> vco=%lu\n",

> +				rate);

> +		return -EINVAL;

> +	}

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_LPFR_CFG, 

> lpfr_lut[i].resistance);

> +

> +	/* Loop filter capacitance values : c1 and c2 */

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_LPFC1_CFG, 0x70);

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_LPFC2_CFG, 0x15);

> +

> +	rem = rate % VCO_REF_CLK_RATE;

> +	if (rem) {

> +		refclk_cfg = DSI_28nm_PHY_PLL_REFCLK_CFG_DBLR;

> +		frac_n_mode = 1;

> +		div_fbx1000 = rate / (VCO_REF_CLK_RATE / 500);

> +		gen_vco_clk = div_fbx1000 * (VCO_REF_CLK_RATE / 500);

> +	} else {

> +		refclk_cfg = 0x0;

> +		frac_n_mode = 0;

> +		div_fbx1000 = rate / (VCO_REF_CLK_RATE / 1000);

> +		gen_vco_clk = div_fbx1000 * (VCO_REF_CLK_RATE / 1000);

> +	}

> +

> +	DBG("refclk_cfg = %d", refclk_cfg);

> +

> +	rem = div_fbx1000 % 1000;

> +	frac_n_value = (rem << 16) / 1000;

> +

> +	DBG("div_fb = %lu", div_fbx1000);

> +	DBG("frac_n_value = %d", frac_n_value);

> +

> +	DBG("Generated VCO Clock: %lu", gen_vco_clk);

> +	rem = 0;

> +	sdm_cfg1 = pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1);

> +	sdm_cfg1 &= ~DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET__MASK;

> +	if (frac_n_mode) {

> +		sdm_cfg0 = 0x0;

> +		sdm_cfg0 |= DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV(0);

> +		sdm_cfg1 |= DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET(

> +				(u32)(((div_fbx1000 / 1000) & 0x3f) - 1));

> +		sdm_cfg3 = frac_n_value >> 8;

> +		sdm_cfg2 = frac_n_value & 0xff;

> +	} else {

> +		sdm_cfg0 = DSI_28nm_PHY_PLL_SDM_CFG0_BYP;

> +		sdm_cfg0 |= DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV(

> +				(u32)(((div_fbx1000 / 1000) & 0x3f) - 1));

> +		sdm_cfg1 |= DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET(0);

> +		sdm_cfg2 = 0;

> +		sdm_cfg3 = 0;

> +	}

> +

> +	DBG("sdm_cfg0=%d", sdm_cfg0);

> +	DBG("sdm_cfg1=%d", sdm_cfg1);

> +	DBG("sdm_cfg2=%d", sdm_cfg2);

> +	DBG("sdm_cfg3=%d", sdm_cfg3);

> +

> +	cal_cfg11 = (u32)(gen_vco_clk / (256 * 1000000));

> +	cal_cfg10 = (u32)((gen_vco_clk % (256 * 1000000)) / 1000000);

> +	DBG("cal_cfg10=%d, cal_cfg11=%d", cal_cfg10, cal_cfg11);

> +

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_CHGPUMP_CFG, 0x02);

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG3,    0x2b);

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG4,    0x06);

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2,  0x0d);

> +

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1, sdm_cfg1);

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG2,

> +		DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0(sdm_cfg2));

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG3,

> +		DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8(sdm_cfg3));

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG4, 0x00);

> +

> +	/* Add hardware recommended delay for correct PLL configuration */

> +	if (pll_28nm->vco_delay)

> +		udelay(pll_28nm->vco_delay);

> +

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_REFCLK_CFG, refclk_cfg);

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_PWRGEN_CFG, 0x00);

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_VCOLPF_CFG, 0x31);

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0,   sdm_cfg0);

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG0,   0x12);

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG6,   0x30);

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG7,   0x00);

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG8,   0x60);

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG9,   0x00);

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG10,  cal_cfg10 & 0xff);

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG11,  cal_cfg11 & 0xff);

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_EFUSE_CFG,  0x20);

> +

> +	return 0;

> +}

> +

> +static int dsi_pll_28nm_clk_is_enabled(struct clk_hw *hw)

> +{

> +	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> +

> +	return pll_28nm_poll_for_ready(pll_28nm, POLL_MAX_READS,

> +					POLL_TIMEOUT_US);

> +}

> +

> +static unsigned long dsi_pll_28nm_clk_recalc_rate(struct clk_hw *hw,

> +		unsigned long parent_rate)

> +{

> +	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> +	void __iomem *base = pll_28nm->mmio;

> +	u32 sdm0, doubler, sdm_byp_div;

> +	u32 sdm_dc_off, sdm_freq_seed, sdm2, sdm3;

> +	u32 ref_clk = VCO_REF_CLK_RATE;

> +	unsigned long vco_rate;

> +

> +	VERB("parent_rate=%lu", parent_rate);

> +

> +	/* Check to see if the ref clk doubler is enabled */

> +	doubler = pll_read(base + REG_DSI_28nm_PHY_PLL_REFCLK_CFG) &

> +			DSI_28nm_PHY_PLL_REFCLK_CFG_DBLR;

> +	ref_clk += (doubler * VCO_REF_CLK_RATE);

> +

> +	/* see if it is integer mode or sdm mode */

> +	sdm0 = pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0);

> +	if (sdm0 & DSI_28nm_PHY_PLL_SDM_CFG0_BYP) {

> +		/* integer mode */

> +		sdm_byp_div = FIELD(

> +				pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0),

> +				DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV) + 1;

> +		vco_rate = ref_clk * sdm_byp_div;

> +	} else {

> +		/* sdm mode */

> +		sdm_dc_off = FIELD(

> +				pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1),

> +				DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET);

> +		DBG("sdm_dc_off = %d", sdm_dc_off);

> +		sdm2 = FIELD(pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG2),

> +				DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0);

> +		sdm3 = FIELD(pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG3),

> +				DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8);

> +		sdm_freq_seed = (sdm3 << 8) | sdm2;

> +		DBG("sdm_freq_seed = %d", sdm_freq_seed);

> +

> +		vco_rate = (ref_clk * (sdm_dc_off + 1)) +

> +			mult_frac(ref_clk, sdm_freq_seed, BIT(16));

> +		DBG("vco rate = %lu", vco_rate);

> +	}

> +

> +	DBG("returning vco rate = %lu", vco_rate);

> +

> +	return vco_rate;

> +}

> +

> +static const struct clk_ops clk_ops_dsi_pll_28nm_vco = {

> +	.round_rate = msm_dsi_pll_helper_clk_round_rate,

> +	.set_rate = dsi_pll_28nm_clk_set_rate,

> +	.recalc_rate = dsi_pll_28nm_clk_recalc_rate,

> +	.prepare = msm_dsi_pll_helper_clk_prepare,

> +	.unprepare = msm_dsi_pll_helper_clk_unprepare,

> +	.is_enabled = dsi_pll_28nm_clk_is_enabled,

> +};

> +

> +/*

> + * PLL Callbacks

> + */

> +static int dsi_pll_28nm_enable_seq_hpm(struct msm_dsi_pll *pll)

> +{

> +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> +	struct device *dev = &pll_28nm->pdev->dev;

> +	void __iomem *base = pll_28nm->mmio;

> +	u32 max_reads = 5, timeout_us = 100;

> +	bool locked;

> +	u32 val;

> +	int i;

> +

> +	DBG("id=%d", pll_28nm->id);

> +

> +	pll_28nm_software_reset(pll_28nm);

> +

> +	/*

> +	 * PLL power up sequence.

> +	 * Add necessary delays recommended by hardware.

> +	 */

> +	val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;

> +	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 1);

> +

> +	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;

> +	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);

> +

> +	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;

> +	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);

> +

> +	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;

> +	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 600);

> +

> +	for (i = 0; i < 2; i++) {

> +		/* DSI Uniphy lock detect setting */

> +		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2,

> +				0x0c, 100);

> +		pll_write(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x0d);

> +

> +		/* poll for PLL ready status */

> +		locked = pll_28nm_poll_for_ready(pll_28nm,

> +						max_reads, timeout_us);

> +		if (locked)

> +			break;

> +

> +		pll_28nm_software_reset(pll_28nm);

> +

> +		/*

> +		 * PLL power up sequence.

> +		 * Add necessary delays recommended by hardware.

> +		 */

> +		val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;

> +		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 1);

> +

> +		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;

> +		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);

> +

> +		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;

> +		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 250);

> +

> +		val &= ~DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;

> +		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);

> +

> +		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;

> +		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);

> +

> +		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;

> +		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 600);

> +	}

> +

> +	if (unlikely(!locked))

> +		DRM_DEV_ERROR(dev, "DSI PLL lock failed\n");

> +	else

> +		DBG("DSI PLL Lock success");

> +

> +	return locked ? 0 : -EINVAL;

> +}

> +

> +static int dsi_pll_28nm_enable_seq_lp(struct msm_dsi_pll *pll)

> +{

> +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> +	struct device *dev = &pll_28nm->pdev->dev;

> +	void __iomem *base = pll_28nm->mmio;

> +	bool locked;

> +	u32 max_reads = 10, timeout_us = 50;

> +	u32 val;

> +

> +	DBG("id=%d", pll_28nm->id);

> +

> +	pll_28nm_software_reset(pll_28nm);

> +

> +	/*

> +	 * PLL power up sequence.

> +	 * Add necessary delays recommended by hardware.

> +	 */

> +	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_CAL_CFG1, 0x34, 500);

> +

> +	val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;

> +	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);

> +

> +	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;

> +	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);

> +

> +	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B |

> +		DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;

> +	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);

> +

> +	/* DSI PLL toggle lock detect setting */

> +	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x04, 500);

> +	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x05, 512);

> +

> +	locked = pll_28nm_poll_for_ready(pll_28nm, max_reads, timeout_us);

> +

> +	if (unlikely(!locked))

> +		DRM_DEV_ERROR(dev, "DSI PLL lock failed\n");

> +	else

> +		DBG("DSI PLL lock success");

> +

> +	return locked ? 0 : -EINVAL;

> +}

> +

> +static void dsi_pll_28nm_disable_seq(struct msm_dsi_pll *pll)

> +{

> +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> +

> +	DBG("id=%d", pll_28nm->id);

> +	pll_write(pll_28nm->mmio + REG_DSI_28nm_PHY_PLL_GLB_CFG, 0x00);

> +}

> +

> +static void dsi_pll_28nm_save_state(struct msm_dsi_pll *pll)

> +{

> +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> +	struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;

> +	void __iomem *base = pll_28nm->mmio;

> +

> +	cached_state->postdiv3 =

> +			pll_read(base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG);

> +	cached_state->postdiv1 =

> +			pll_read(base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG);

> +	cached_state->byte_mux = pll_read(base + 

> REG_DSI_28nm_PHY_PLL_VREG_CFG);

> +	if (dsi_pll_28nm_clk_is_enabled(&pll->clk_hw))

> +		cached_state->vco_rate = clk_hw_get_rate(&pll->clk_hw);

> +	else

> +		cached_state->vco_rate = 0;

> +}

> +

> +static int dsi_pll_28nm_restore_state(struct msm_dsi_pll *pll)

> +{

> +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> +	struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;

> +	void __iomem *base = pll_28nm->mmio;

> +	int ret;

> +

> +	ret = dsi_pll_28nm_clk_set_rate(&pll->clk_hw,

> +					cached_state->vco_rate, 0);

> +	if (ret) {

> +		DRM_DEV_ERROR(&pll_28nm->pdev->dev,

> +			"restore vco rate failed. ret=%d\n", ret);

> +		return ret;

> +	}

> +

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG,

> +			cached_state->postdiv3);

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG,

> +			cached_state->postdiv1);

> +	pll_write(base + REG_DSI_28nm_PHY_PLL_VREG_CFG,

> +			cached_state->byte_mux);

> +

> +	return 0;

> +}

> +

> +static int dsi_pll_28nm_get_provider(struct msm_dsi_pll *pll,

> +				struct clk **byte_clk_provider,

> +				struct clk **pixel_clk_provider)

> +{

> +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> +

> +	if (byte_clk_provider)

> +		*byte_clk_provider = pll_28nm->provided_clks[DSI_BYTE_PLL_CLK];

> +	if (pixel_clk_provider)

> +		*pixel_clk_provider =

> +				pll_28nm->provided_clks[DSI_PIXEL_PLL_CLK];

> +

> +	return 0;

> +}

> +

> +static void dsi_pll_28nm_destroy(struct msm_dsi_pll *pll)

> +{

> +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> +	int i;

> +

> +	msm_dsi_pll_helper_unregister_clks(pll_28nm->pdev,

> +					pll_28nm->clks, pll_28nm->num_clks);

> +

> +	for (i = 0; i < NUM_PROVIDED_CLKS; i++)

> +		pll_28nm->provided_clks[i] = NULL;

> +

> +	pll_28nm->num_clks = 0;

> +	pll_28nm->clk_data.clks = NULL;

> +	pll_28nm->clk_data.clk_num = 0;

> +}

> +

> +static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm)

> +{

> +	char clk_name[32], parent1[32], parent2[32], vco_name[32];

> +	struct clk_init_data vco_init = {

> +		.parent_names = (const char *[]){ "xo" },

> +		.num_parents = 1,

> +		.name = vco_name,

> +		.flags = CLK_IGNORE_UNUSED,

> +		.ops = &clk_ops_dsi_pll_28nm_vco,

> +	};

> +	struct device *dev = &pll_28nm->pdev->dev;

> +	struct clk **clks = pll_28nm->clks;

> +	struct clk **provided_clks = pll_28nm->provided_clks;

> +	int num = 0;

> +	int ret;

> +

> +	DBG("%d", pll_28nm->id);

> +

> +	snprintf(vco_name, 32, "dsi%dvco_clk", pll_28nm->id);

> +	pll_28nm->base.clk_hw.init = &vco_init;

> +	clks[num++] = clk_register(dev, &pll_28nm->base.clk_hw);

> +

> +	snprintf(clk_name, 32, "dsi%danalog_postdiv_clk", pll_28nm->id);

> +	snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->id);

> +	clks[num++] = clk_register_divider(dev, clk_name,

> +			parent1, CLK_SET_RATE_PARENT,

> +			pll_28nm->mmio +

> +			REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG,

> +			0, 4, 0, NULL);

> +

> +	snprintf(clk_name, 32, "dsi%dindirect_path_div2_clk", pll_28nm->id);

> +	snprintf(parent1, 32, "dsi%danalog_postdiv_clk", pll_28nm->id);

> +	clks[num++] = clk_register_fixed_factor(dev, clk_name,

> +			parent1, CLK_SET_RATE_PARENT,

> +			1, 2);

> +

> +	snprintf(clk_name, 32, "dsi%dpll", pll_28nm->id);

> +	snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->id);

> +	clks[num++] = provided_clks[DSI_PIXEL_PLL_CLK] =

> +			clk_register_divider(dev, clk_name,

> +				parent1, 0, pll_28nm->mmio +

> +				REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG,

> +				0, 8, 0, NULL);

> +

> +	snprintf(clk_name, 32, "dsi%dbyte_mux", pll_28nm->id);

> +	snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->id);

> +	snprintf(parent2, 32, "dsi%dindirect_path_div2_clk", pll_28nm->id);

> +	clks[num++] = clk_register_mux(dev, clk_name,

> +			((const char *[]){

> +				parent1, parent2

> +			}), 2, CLK_SET_RATE_PARENT, pll_28nm->mmio +

> +			REG_DSI_28nm_PHY_PLL_VREG_CFG, 1, 1, 0, NULL);

> +

> +	snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->id);

> +	snprintf(parent1, 32, "dsi%dbyte_mux", pll_28nm->id);

> +	clks[num++] = provided_clks[DSI_BYTE_PLL_CLK] =

> +			clk_register_fixed_factor(dev, clk_name,

> +				parent1, CLK_SET_RATE_PARENT, 1, 4);

> +

> +	pll_28nm->num_clks = num;

> +

> +	pll_28nm->clk_data.clk_num = NUM_PROVIDED_CLKS;

> +	pll_28nm->clk_data.clks = provided_clks;

> +

> +	ret = of_clk_add_provider(dev->of_node,

> +			of_clk_src_onecell_get, &pll_28nm->clk_data);

> +	if (ret) {

> +		DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret);

> +		return ret;

> +	}

> +

> +	return 0;

> +}

> +

> +struct msm_dsi_pll *msm_dsi_pll_28nm_init(struct platform_device 

> *pdev,

> +					enum msm_dsi_phy_type type, int id)

> +{

> +	struct dsi_pll_28nm *pll_28nm;

> +	struct msm_dsi_pll *pll;

> +	int ret;

> +

> +	if (!pdev)

> +		return ERR_PTR(-ENODEV);

> +

> +	pll_28nm = devm_kzalloc(&pdev->dev, sizeof(*pll_28nm), GFP_KERNEL);

> +	if (!pll_28nm)

> +		return ERR_PTR(-ENOMEM);

> +

> +	pll_28nm->pdev = pdev;

> +	pll_28nm->id = id;

> +

> +	pll_28nm->mmio = msm_ioremap(pdev, "dsi_pll", "DSI_PLL");

> +	if (IS_ERR_OR_NULL(pll_28nm->mmio)) {

> +		DRM_DEV_ERROR(&pdev->dev, "%s: failed to map pll base\n", __func__);

> +		return ERR_PTR(-ENOMEM);

> +	}

> +

> +	pll = &pll_28nm->base;

> +	pll->min_rate = VCO_MIN_RATE;

> +	pll->max_rate = VCO_MAX_RATE;

> +	pll->get_provider = dsi_pll_28nm_get_provider;

> +	pll->destroy = dsi_pll_28nm_destroy;

> +	pll->disable_seq = dsi_pll_28nm_disable_seq;

> +	pll->save_state = dsi_pll_28nm_save_state;

> +	pll->restore_state = dsi_pll_28nm_restore_state;

> +

> +	if (type == MSM_DSI_PHY_28NM_HPM) {

> +		pll_28nm->vco_delay = 1;

> +

> +		pll->en_seq_cnt = 3;

> +		pll->enable_seqs[0] = dsi_pll_28nm_enable_seq_hpm;

> +		pll->enable_seqs[1] = dsi_pll_28nm_enable_seq_hpm;

> +		pll->enable_seqs[2] = dsi_pll_28nm_enable_seq_hpm;

> +	} else if (type == MSM_DSI_PHY_28NM_LP) {

> +		pll_28nm->vco_delay = 1000;

> +

> +		pll->en_seq_cnt = 1;

> +		pll->enable_seqs[0] = dsi_pll_28nm_enable_seq_lp;

> +	} else {

> +		DRM_DEV_ERROR(&pdev->dev, "phy type (%d) is not 28nm\n", type);

> +		return ERR_PTR(-EINVAL);

> +	}

> +

> +	ret = pll_28nm_register(pll_28nm);

> +	if (ret) {

> +		DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret);

> +		return ERR_PTR(ret);

> +	}

> +

> +	return pll;

> +}

> +

> +

>  static void dsi_28nm_dphy_set_timing(struct msm_dsi_phy *phy,

>  		struct msm_dsi_dphy_timing *timing)

>  {

> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c

> b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c

> index 5d33de27a0f4..4a40513057e8 100644

> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c

> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c

> @@ -3,11 +3,530 @@

>   * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.

>   */

> 

> +#include <linux/clk-provider.h>

>  #include <linux/delay.h>

> 

>  #include "dsi_phy.h"

> +#include "dsi_pll.h"

>  #include "dsi.xml.h"

> 

> +/*

> + * DSI PLL 28nm (8960/A family) - clock diagram (eg: DSI1):

> + *

> + *

> + *                        +------+

> + *  dsi1vco_clk ----o-----| DIV1 |---dsi1pllbit (not exposed as clock)

> + *  F * byte_clk    |     +------+

> + *                  | bit clock divider (F / 8)

> + *                  |

> + *                  |     +------+

> + *                  o-----| DIV2 |---dsi0pllbyte---o---> To byte RCG

> + *                  |     +------+                 | (sets parent 

> rate)

> + *                  | byte clock divider (F)       |

> + *                  |                              |

> + *                  |                              o---> To esc RCG

> + *                  |                                (doesn't set 

> parent rate)

> + *                  |

> + *                  |     +------+

> + *                  o-----| DIV3 |----dsi0pll------o---> To dsi RCG

> + *                        +------+                 | (sets parent 

> rate)

> + *                  dsi clock divider (F * magic)  |

> + *                                                 |

> + *                                                 o---> To pixel rcg

> + *                                                  (doesn't set 

> parent rate)

> + */

> +

> +#define POLL_MAX_READS		8000

> +#define POLL_TIMEOUT_US		1

> +

> +#define NUM_PROVIDED_CLKS	2

> +

> +#define VCO_REF_CLK_RATE	27000000

> +#define VCO_MIN_RATE		600000000

> +#define VCO_MAX_RATE		1200000000

> +

> +#define DSI_BYTE_PLL_CLK	0

> +#define DSI_PIXEL_PLL_CLK	1

> +

> +#define VCO_PREF_DIV_RATIO	27

> +

> +struct pll_28nm_cached_state {

> +	unsigned long vco_rate;

> +	u8 postdiv3;

> +	u8 postdiv2;

> +	u8 postdiv1;

> +};

> +

> +struct clk_bytediv {

> +	struct clk_hw hw;

> +	void __iomem *reg;

> +};

> +

> +struct dsi_pll_28nm {

> +	struct msm_dsi_pll base;

> +

> +	int id;

> +	struct platform_device *pdev;

> +	void __iomem *mmio;

> +

> +	/* custom byte clock divider */

> +	struct clk_bytediv *bytediv;

> +

> +	/* private clocks: */

> +	struct clk *clks[NUM_DSI_CLOCKS_MAX];

> +	u32 num_clks;

> +

> +	/* clock-provider: */

> +	struct clk *provided_clks[NUM_PROVIDED_CLKS];

> +	struct clk_onecell_data clk_data;

> +

> +	struct pll_28nm_cached_state cached_state;

> +};

> +

> +#define to_pll_28nm(x)	container_of(x, struct dsi_pll_28nm, base)

> +

> +static bool pll_28nm_poll_for_ready(struct dsi_pll_28nm *pll_28nm,

> +				    int nb_tries, int timeout_us)

> +{

> +	bool pll_locked = false;

> +	u32 val;

> +

> +	while (nb_tries--) {

> +		val = pll_read(pll_28nm->mmio + REG_DSI_28nm_8960_PHY_PLL_RDY);

> +		pll_locked = !!(val & DSI_28nm_8960_PHY_PLL_RDY_PLL_RDY);

> +

> +		if (pll_locked)

> +			break;

> +

> +		udelay(timeout_us);

> +	}

> +	DBG("DSI PLL is %slocked", pll_locked ? "" : "*not* ");

> +

> +	return pll_locked;

> +}

> +

> +/*

> + * Clock Callbacks

> + */

> +static int dsi_pll_28nm_clk_set_rate(struct clk_hw *hw, unsigned long 

> rate,

> +				     unsigned long parent_rate)

> +{

> +	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> +	void __iomem *base = pll_28nm->mmio;

> +	u32 val, temp, fb_divider;

> +

> +	DBG("rate=%lu, parent's=%lu", rate, parent_rate);

> +

> +	temp = rate / 10;

> +	val = VCO_REF_CLK_RATE / 10;

> +	fb_divider = (temp * VCO_PREF_DIV_RATIO) / val;

> +	fb_divider = fb_divider / 2 - 1;

> +	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_1,

> +			fb_divider & 0xff);

> +

> +	val = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2);

> +

> +	val |= (fb_divider >> 8) & 0x07;

> +

> +	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2,

> +			val);

> +

> +	val = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3);

> +

> +	val |= (VCO_PREF_DIV_RATIO - 1) & 0x3f;

> +

> +	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3,

> +			val);

> +

> +	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_6,

> +			0xf);

> +

> +	val = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);

> +	val |= 0x7 << 4;

> +	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8,

> +			val);

> +

> +	return 0;

> +}

> +

> +static int dsi_pll_28nm_clk_is_enabled(struct clk_hw *hw)

> +{

> +	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> +

> +	return pll_28nm_poll_for_ready(pll_28nm, POLL_MAX_READS,

> +					POLL_TIMEOUT_US);

> +}

> +

> +static unsigned long dsi_pll_28nm_clk_recalc_rate(struct clk_hw *hw,

> +						  unsigned long parent_rate)

> +{

> +	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> +	void __iomem *base = pll_28nm->mmio;

> +	unsigned long vco_rate;

> +	u32 status, fb_divider, temp, ref_divider;

> +

> +	VERB("parent_rate=%lu", parent_rate);

> +

> +	status = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_0);

> +

> +	if (status & DSI_28nm_8960_PHY_PLL_CTRL_0_ENABLE) {

> +		fb_divider = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_1);

> +		fb_divider &= 0xff;

> +		temp = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2) & 0x07;

> +		fb_divider = (temp << 8) | fb_divider;

> +		fb_divider += 1;

> +

> +		ref_divider = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3);

> +		ref_divider &= 0x3f;

> +		ref_divider += 1;

> +

> +		/* multiply by 2 */

> +		vco_rate = (parent_rate / ref_divider) * fb_divider * 2;

> +	} else {

> +		vco_rate = 0;

> +	}

> +

> +	DBG("returning vco rate = %lu", vco_rate);

> +

> +	return vco_rate;

> +}

> +

> +static const struct clk_ops clk_ops_dsi_pll_28nm_vco = {

> +	.round_rate = msm_dsi_pll_helper_clk_round_rate,

> +	.set_rate = dsi_pll_28nm_clk_set_rate,

> +	.recalc_rate = dsi_pll_28nm_clk_recalc_rate,

> +	.prepare = msm_dsi_pll_helper_clk_prepare,

> +	.unprepare = msm_dsi_pll_helper_clk_unprepare,

> +	.is_enabled = dsi_pll_28nm_clk_is_enabled,

> +};

> +

> +/*

> + * Custom byte clock divier clk_ops

> + *

> + * This clock is the entry point to configuring the PLL. The user (dsi 

> host)

> + * will set this clock's rate to the desired byte clock rate. The VCO 

> lock

> + * frequency is a multiple of the byte clock rate. The multiplication 

> factor

> + * (shown as F in the diagram above) is a function of the byte clock 

> rate.

> + *

> + * This custom divider clock ensures that its parent (VCO) is set to 

> the

> + * desired rate, and that the byte clock postdivider (POSTDIV2) is 

> configured

> + * accordingly

> + */

> +#define to_clk_bytediv(_hw) container_of(_hw, struct clk_bytediv, hw)

> +

> +static unsigned long clk_bytediv_recalc_rate(struct clk_hw *hw,

> +		unsigned long parent_rate)

> +{

> +	struct clk_bytediv *bytediv = to_clk_bytediv(hw);

> +	unsigned int div;

> +

> +	div = pll_read(bytediv->reg) & 0xff;

> +

> +	return parent_rate / (div + 1);

> +}

> +

> +/* find multiplication factor(wrt byte clock) at which the VCO should 

> be set */

> +static unsigned int get_vco_mul_factor(unsigned long byte_clk_rate)

> +{

> +	unsigned long bit_mhz;

> +

> +	/* convert to bit clock in Mhz */

> +	bit_mhz = (byte_clk_rate * 8) / 1000000;

> +

> +	if (bit_mhz < 125)

> +		return 64;

> +	else if (bit_mhz < 250)

> +		return 32;

> +	else if (bit_mhz < 600)

> +		return 16;

> +	else

> +		return 8;

> +}

> +

> +static long clk_bytediv_round_rate(struct clk_hw *hw, unsigned long 

> rate,

> +				   unsigned long *prate)

> +{

> +	unsigned long best_parent;

> +	unsigned int factor;

> +

> +	factor = get_vco_mul_factor(rate);

> +

> +	best_parent = rate * factor;

> +	*prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);

> +

> +	return *prate / factor;

> +}

> +

> +static int clk_bytediv_set_rate(struct clk_hw *hw, unsigned long rate,

> +				unsigned long parent_rate)

> +{

> +	struct clk_bytediv *bytediv = to_clk_bytediv(hw);

> +	u32 val;

> +	unsigned int factor;

> +

> +	factor = get_vco_mul_factor(rate);

> +

> +	val = pll_read(bytediv->reg);

> +	val |= (factor - 1) & 0xff;

> +	pll_write(bytediv->reg, val);

> +

> +	return 0;

> +}

> +

> +/* Our special byte clock divider ops */

> +static const struct clk_ops clk_bytediv_ops = {

> +	.round_rate = clk_bytediv_round_rate,

> +	.set_rate = clk_bytediv_set_rate,

> +	.recalc_rate = clk_bytediv_recalc_rate,

> +};

> +

> +/*

> + * PLL Callbacks

> + */

> +static int dsi_pll_28nm_enable_seq(struct msm_dsi_pll *pll)

> +{

> +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> +	struct device *dev = &pll_28nm->pdev->dev;

> +	void __iomem *base = pll_28nm->mmio;

> +	bool locked;

> +	unsigned int bit_div, byte_div;

> +	int max_reads = 1000, timeout_us = 100;

> +	u32 val;

> +

> +	DBG("id=%d", pll_28nm->id);

> +

> +	/*

> +	 * before enabling the PLL, configure the bit clock divider since we

> +	 * don't expose it as a clock to the outside world

> +	 * 1: read back the byte clock divider that should already be set

> +	 * 2: divide by 8 to get bit clock divider

> +	 * 3: write it to POSTDIV1

> +	 */

> +	val = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9);

> +	byte_div = val + 1;

> +	bit_div = byte_div / 8;

> +

> +	val = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);

> +	val &= ~0xf;

> +	val |= (bit_div - 1);

> +	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8, val);

> +

> +	/* enable the PLL */

> +	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_0,

> +			DSI_28nm_8960_PHY_PLL_CTRL_0_ENABLE);

> +

> +	locked = pll_28nm_poll_for_ready(pll_28nm, max_reads, timeout_us);

> +

> +	if (unlikely(!locked))

> +		DRM_DEV_ERROR(dev, "DSI PLL lock failed\n");

> +	else

> +		DBG("DSI PLL lock success");

> +

> +	return locked ? 0 : -EINVAL;

> +}

> +

> +static void dsi_pll_28nm_disable_seq(struct msm_dsi_pll *pll)

> +{

> +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> +

> +	DBG("id=%d", pll_28nm->id);

> +	pll_write(pll_28nm->mmio + REG_DSI_28nm_8960_PHY_PLL_CTRL_0, 0x00);

> +}

> +

> +static void dsi_pll_28nm_save_state(struct msm_dsi_pll *pll)

> +{

> +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> +	struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;

> +	void __iomem *base = pll_28nm->mmio;

> +

> +	cached_state->postdiv3 =

> +			pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_10);

> +	cached_state->postdiv2 =

> +			pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9);

> +	cached_state->postdiv1 =

> +			pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);

> +

> +	cached_state->vco_rate = clk_hw_get_rate(&pll->clk_hw);

> +}

> +

> +static int dsi_pll_28nm_restore_state(struct msm_dsi_pll *pll)

> +{

> +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> +	struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;

> +	void __iomem *base = pll_28nm->mmio;

> +	int ret;

> +

> +	ret = dsi_pll_28nm_clk_set_rate(&pll->clk_hw,

> +					cached_state->vco_rate, 0);

> +	if (ret) {

> +		DRM_DEV_ERROR(&pll_28nm->pdev->dev,

> +			"restore vco rate failed. ret=%d\n", ret);

> +		return ret;

> +	}

> +

> +	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_10,

> +			cached_state->postdiv3);

> +	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9,

> +			cached_state->postdiv2);

> +	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8,

> +			cached_state->postdiv1);

> +

> +	return 0;

> +}

> +

> +static int dsi_pll_28nm_get_provider(struct msm_dsi_pll *pll,

> +				struct clk **byte_clk_provider,

> +				struct clk **pixel_clk_provider)

> +{

> +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> +

> +	if (byte_clk_provider)

> +		*byte_clk_provider = pll_28nm->provided_clks[DSI_BYTE_PLL_CLK];

> +	if (pixel_clk_provider)

> +		*pixel_clk_provider =

> +				pll_28nm->provided_clks[DSI_PIXEL_PLL_CLK];

> +

> +	return 0;

> +}

> +

> +static void dsi_pll_28nm_destroy(struct msm_dsi_pll *pll)

> +{

> +	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> +

> +	msm_dsi_pll_helper_unregister_clks(pll_28nm->pdev,

> +					pll_28nm->clks, pll_28nm->num_clks);

> +}

> +

> +static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm)

> +{

> +	char *clk_name, *parent_name, *vco_name;

> +	struct clk_init_data vco_init = {

> +		.parent_names = (const char *[]){ "pxo" },

> +		.num_parents = 1,

> +		.flags = CLK_IGNORE_UNUSED,

> +		.ops = &clk_ops_dsi_pll_28nm_vco,

> +	};

> +	struct device *dev = &pll_28nm->pdev->dev;

> +	struct clk **clks = pll_28nm->clks;

> +	struct clk **provided_clks = pll_28nm->provided_clks;

> +	struct clk_bytediv *bytediv;

> +	struct clk_init_data bytediv_init = { };

> +	int ret, num = 0;

> +

> +	DBG("%d", pll_28nm->id);

> +

> +	bytediv = devm_kzalloc(dev, sizeof(*bytediv), GFP_KERNEL);

> +	if (!bytediv)

> +		return -ENOMEM;

> +

> +	vco_name = devm_kzalloc(dev, 32, GFP_KERNEL);

> +	if (!vco_name)

> +		return -ENOMEM;

> +

> +	parent_name = devm_kzalloc(dev, 32, GFP_KERNEL);

> +	if (!parent_name)

> +		return -ENOMEM;

> +

> +	clk_name = devm_kzalloc(dev, 32, GFP_KERNEL);

> +	if (!clk_name)

> +		return -ENOMEM;

> +

> +	pll_28nm->bytediv = bytediv;

> +

> +	snprintf(vco_name, 32, "dsi%dvco_clk", pll_28nm->id);

> +	vco_init.name = vco_name;

> +

> +	pll_28nm->base.clk_hw.init = &vco_init;

> +

> +	clks[num++] = clk_register(dev, &pll_28nm->base.clk_hw);

> +

> +	/* prepare and register bytediv */

> +	bytediv->hw.init = &bytediv_init;

> +	bytediv->reg = pll_28nm->mmio + REG_DSI_28nm_8960_PHY_PLL_CTRL_9;

> +

> +	snprintf(parent_name, 32, "dsi%dvco_clk", pll_28nm->id);

> +	snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->id);

> +

> +	bytediv_init.name = clk_name;

> +	bytediv_init.ops = &clk_bytediv_ops;

> +	bytediv_init.flags = CLK_SET_RATE_PARENT;

> +	bytediv_init.parent_names = (const char * const *) &parent_name;

> +	bytediv_init.num_parents = 1;

> +

> +	/* DIV2 */

> +	clks[num++] = provided_clks[DSI_BYTE_PLL_CLK] =

> +			clk_register(dev, &bytediv->hw);

> +

> +	snprintf(clk_name, 32, "dsi%dpll", pll_28nm->id);

> +	/* DIV3 */

> +	clks[num++] = provided_clks[DSI_PIXEL_PLL_CLK] =

> +			clk_register_divider(dev, clk_name,

> +				parent_name, 0, pll_28nm->mmio +

> +				REG_DSI_28nm_8960_PHY_PLL_CTRL_10,

> +				0, 8, 0, NULL);

> +

> +	pll_28nm->num_clks = num;

> +

> +	pll_28nm->clk_data.clk_num = NUM_PROVIDED_CLKS;

> +	pll_28nm->clk_data.clks = provided_clks;

> +

> +	ret = of_clk_add_provider(dev->of_node,

> +			of_clk_src_onecell_get, &pll_28nm->clk_data);

> +	if (ret) {

> +		DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret);

> +		return ret;

> +	}

> +

> +	return 0;

> +}

> +

> +struct msm_dsi_pll *msm_dsi_pll_28nm_8960_init(struct platform_device 

> *pdev,

> +					       int id)

> +{

> +	struct dsi_pll_28nm *pll_28nm;

> +	struct msm_dsi_pll *pll;

> +	int ret;

> +

> +	if (!pdev)

> +		return ERR_PTR(-ENODEV);

> +

> +	pll_28nm = devm_kzalloc(&pdev->dev, sizeof(*pll_28nm), GFP_KERNEL);

> +	if (!pll_28nm)

> +		return ERR_PTR(-ENOMEM);

> +

> +	pll_28nm->pdev = pdev;

> +	pll_28nm->id = id + 1;

> +

> +	pll_28nm->mmio = msm_ioremap(pdev, "dsi_pll", "DSI_PLL");

> +	if (IS_ERR_OR_NULL(pll_28nm->mmio)) {

> +		DRM_DEV_ERROR(&pdev->dev, "%s: failed to map pll base\n", __func__);

> +		return ERR_PTR(-ENOMEM);

> +	}

> +

> +	pll = &pll_28nm->base;

> +	pll->min_rate = VCO_MIN_RATE;

> +	pll->max_rate = VCO_MAX_RATE;

> +	pll->get_provider = dsi_pll_28nm_get_provider;

> +	pll->destroy = dsi_pll_28nm_destroy;

> +	pll->disable_seq = dsi_pll_28nm_disable_seq;

> +	pll->save_state = dsi_pll_28nm_save_state;

> +	pll->restore_state = dsi_pll_28nm_restore_state;

> +

> +	pll->en_seq_cnt = 1;

> +	pll->enable_seqs[0] = dsi_pll_28nm_enable_seq;

> +

> +	ret = pll_28nm_register(pll_28nm);

> +	if (ret) {

> +		DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret);

> +		return ERR_PTR(ret);

> +	}

> +

> +	return pll;

> +}

> +

>  static void dsi_28nm_dphy_set_timing(struct msm_dsi_phy *phy,

>  		struct msm_dsi_dphy_timing *timing)

>  {

> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c

> b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c

> index cbfeec860e69..f9af9d70b56a 100644

> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c

> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c

> @@ -3,11 +3,916 @@

>   * Copyright (c) 2018, The Linux Foundation

>   */

> 

> +#include <linux/clk.h>

> +#include <linux/clk-provider.h>

>  #include <linux/iopoll.h>

> 

> +#include "dsi_pll.h"

>  #include "dsi_phy.h"

>  #include "dsi.xml.h"

> 

> +/*

> + * DSI PLL 7nm - clock diagram (eg: DSI0): TODO: updated CPHY diagram

> + *

> + *           dsi0_pll_out_div_clk  dsi0_pll_bit_clk

> + *                              |                |

> + *                              |                |

> + *                 +---------+  |  +----------+  |  +----+

> + *  dsi0vco_clk ---| out_div |--o--| divl_3_0 |--o--| /8 |--

> dsi0_phy_pll_out_byteclk

> + *                 +---------+  |  +----------+  |  +----+

> + *                              |                |

> + *                              |                |

> dsi0_pll_by_2_bit_clk

> + *                              |                |          |

> + *                              |                |  +----+  |  |\

> dsi0_pclk_mux

> + *                              |                |--| /2 |--o--| \   |

> + *                              |                |  +----+     |  \

> |  +---------+

> + *                              |                --------------|

> |--o--| div_7_4 |-- dsi0_phy_pll_out_dsiclk

> + *                              |------------------------------|  /

>   +---------+

> + *                              |          +-----+             | /

> + *                              -----------| /4? |--o----------|/

> + *                                         +-----+  |           |

> + *                                                  |           

> |dsiclk_sel

> + *                                                  |

> + *                                                  

> dsi0_pll_post_out_div_clk

> + */

> +

> +#define DSI_BYTE_PLL_CLK		0

> +#define DSI_PIXEL_PLL_CLK		1

> +#define NUM_PROVIDED_CLKS		2

> +

> +#define VCO_REF_CLK_RATE		19200000

> +

> +struct dsi_pll_regs {

> +	u32 pll_prop_gain_rate;

> +	u32 pll_lockdet_rate;

> +	u32 decimal_div_start;

> +	u32 frac_div_start_low;

> +	u32 frac_div_start_mid;

> +	u32 frac_div_start_high;

> +	u32 pll_clock_inverters;

> +	u32 ssc_stepsize_low;

> +	u32 ssc_stepsize_high;

> +	u32 ssc_div_per_low;

> +	u32 ssc_div_per_high;

> +	u32 ssc_adjper_low;

> +	u32 ssc_adjper_high;

> +	u32 ssc_control;

> +};

> +

> +struct dsi_pll_config {

> +	u32 ref_freq;

> +	bool div_override;

> +	u32 output_div;

> +	bool ignore_frac;

> +	bool disable_prescaler;

> +	bool enable_ssc;

> +	bool ssc_center;

> +	u32 dec_bits;

> +	u32 frac_bits;

> +	u32 lock_timer;

> +	u32 ssc_freq;

> +	u32 ssc_offset;

> +	u32 ssc_adj_per;

> +	u32 thresh_cycles;

> +	u32 refclk_cycles;

> +};

> +

> +struct pll_7nm_cached_state {

> +	unsigned long vco_rate;

> +	u8 bit_clk_div;

> +	u8 pix_clk_div;

> +	u8 pll_out_div;

> +	u8 pll_mux;

> +};

> +

> +struct dsi_pll_7nm {

> +	struct msm_dsi_pll base;

> +

> +	int id;

> +	struct platform_device *pdev;

> +

> +	void __iomem *phy_cmn_mmio;

> +	void __iomem *mmio;

> +

> +	u64 vco_ref_clk_rate;

> +	u64 vco_current_rate;

> +

> +	/* protects REG_DSI_7nm_PHY_CMN_CLK_CFG0 register */

> +	spinlock_t postdiv_lock;

> +

> +	int vco_delay;

> +	struct dsi_pll_config pll_configuration;

> +	struct dsi_pll_regs reg_setup;

> +

> +	/* private clocks: */

> +	struct clk_hw *out_div_clk_hw;

> +	struct clk_hw *bit_clk_hw;

> +	struct clk_hw *byte_clk_hw;

> +	struct clk_hw *by_2_bit_clk_hw;

> +	struct clk_hw *post_out_div_clk_hw;

> +	struct clk_hw *pclk_mux_hw;

> +	struct clk_hw *out_dsiclk_hw;

> +

> +	/* clock-provider: */

> +	struct clk_hw_onecell_data *hw_data;

> +

> +	struct pll_7nm_cached_state cached_state;

> +

> +	enum msm_dsi_phy_usecase uc;

> +	struct dsi_pll_7nm *slave;

> +};

> +

> +#define to_pll_7nm(x)	container_of(x, struct dsi_pll_7nm, base)

> +

> +/*

> + * Global list of private DSI PLL struct pointers. We need this for 

> Dual DSI

> + * mode, where the master PLL's clk_ops needs access the slave's 

> private data

> + */

> +static struct dsi_pll_7nm *pll_7nm_list[DSI_MAX];

> +

> +static void dsi_pll_setup_config(struct dsi_pll_7nm *pll)

> +{

> +	struct dsi_pll_config *config = &pll->pll_configuration;

> +

> +	config->ref_freq = pll->vco_ref_clk_rate;

> +	config->output_div = 1;

> +	config->dec_bits = 8;

> +	config->frac_bits = 18;

> +	config->lock_timer = 64;

> +	config->ssc_freq = 31500;

> +	config->ssc_offset = 4800;

> +	config->ssc_adj_per = 2;

> +	config->thresh_cycles = 32;

> +	config->refclk_cycles = 256;

> +

> +	config->div_override = false;

> +	config->ignore_frac = false;

> +	config->disable_prescaler = false;

> +

> +	/* TODO: ssc enable */

> +	config->enable_ssc = false;

> +	config->ssc_center = 0;

> +}

> +

> +static void dsi_pll_calc_dec_frac(struct dsi_pll_7nm *pll)

> +{

> +	struct dsi_pll_config *config = &pll->pll_configuration;

> +	struct dsi_pll_regs *regs = &pll->reg_setup;

> +	u64 fref = pll->vco_ref_clk_rate;

> +	u64 pll_freq;

> +	u64 divider;

> +	u64 dec, dec_multiple;

> +	u32 frac;

> +	u64 multiplier;

> +

> +	pll_freq = pll->vco_current_rate;

> +

> +	if (config->disable_prescaler)

> +		divider = fref;

> +	else

> +		divider = fref * 2;

> +

> +	multiplier = 1 << config->frac_bits;

> +	dec_multiple = div_u64(pll_freq * multiplier, divider);

> +	div_u64_rem(dec_multiple, multiplier, &frac);

> +

> +	dec = div_u64(dec_multiple, multiplier);

> +

> +	if (pll->base.type != MSM_DSI_PHY_7NM_V4_1)

> +		regs->pll_clock_inverters = 0x28;

> +	else if (pll_freq <= 1000000000ULL)

> +		regs->pll_clock_inverters = 0xa0;

> +	else if (pll_freq <= 2500000000ULL)

> +		regs->pll_clock_inverters = 0x20;

> +	else if (pll_freq <= 3020000000ULL)

> +		regs->pll_clock_inverters = 0x00;

> +	else

> +		regs->pll_clock_inverters = 0x40;

> +

> +	regs->pll_lockdet_rate = config->lock_timer;

> +	regs->decimal_div_start = dec;

> +	regs->frac_div_start_low = (frac & 0xff);

> +	regs->frac_div_start_mid = (frac & 0xff00) >> 8;

> +	regs->frac_div_start_high = (frac & 0x30000) >> 16;

> +}

> +

> +#define SSC_CENTER		BIT(0)

> +#define SSC_EN			BIT(1)

> +

> +static void dsi_pll_calc_ssc(struct dsi_pll_7nm *pll)

> +{

> +	struct dsi_pll_config *config = &pll->pll_configuration;

> +	struct dsi_pll_regs *regs = &pll->reg_setup;

> +	u32 ssc_per;

> +	u32 ssc_mod;

> +	u64 ssc_step_size;

> +	u64 frac;

> +

> +	if (!config->enable_ssc) {

> +		DBG("SSC not enabled\n");

> +		return;

> +	}

> +

> +	ssc_per = DIV_ROUND_CLOSEST(config->ref_freq, config->ssc_freq) / 2 - 

> 1;

> +	ssc_mod = (ssc_per + 1) % (config->ssc_adj_per + 1);

> +	ssc_per -= ssc_mod;

> +

> +	frac = regs->frac_div_start_low |

> +			(regs->frac_div_start_mid << 8) |

> +			(regs->frac_div_start_high << 16);

> +	ssc_step_size = regs->decimal_div_start;

> +	ssc_step_size *= (1 << config->frac_bits);

> +	ssc_step_size += frac;

> +	ssc_step_size *= config->ssc_offset;

> +	ssc_step_size *= (config->ssc_adj_per + 1);

> +	ssc_step_size = div_u64(ssc_step_size, (ssc_per + 1));

> +	ssc_step_size = DIV_ROUND_CLOSEST_ULL(ssc_step_size, 1000000);

> +

> +	regs->ssc_div_per_low = ssc_per & 0xFF;

> +	regs->ssc_div_per_high = (ssc_per & 0xFF00) >> 8;

> +	regs->ssc_stepsize_low = (u32)(ssc_step_size & 0xFF);

> +	regs->ssc_stepsize_high = (u32)((ssc_step_size & 0xFF00) >> 8);

> +	regs->ssc_adjper_low = config->ssc_adj_per & 0xFF;

> +	regs->ssc_adjper_high = (config->ssc_adj_per & 0xFF00) >> 8;

> +

> +	regs->ssc_control = config->ssc_center ? SSC_CENTER : 0;

> +

> +	pr_debug("SCC: Dec:%d, frac:%llu, frac_bits:%d\n",

> +		 regs->decimal_div_start, frac, config->frac_bits);

> +	pr_debug("SSC: div_per:0x%X, stepsize:0x%X, adjper:0x%X\n",

> +		 ssc_per, (u32)ssc_step_size, config->ssc_adj_per);

> +}

> +

> +static void dsi_pll_ssc_commit(struct dsi_pll_7nm *pll)

> +{

> +	void __iomem *base = pll->mmio;

> +	struct dsi_pll_regs *regs = &pll->reg_setup;

> +

> +	if (pll->pll_configuration.enable_ssc) {

> +		pr_debug("SSC is enabled\n");

> +

> +		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_STEPSIZE_LOW_1,

> +			  regs->ssc_stepsize_low);

> +		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_STEPSIZE_HIGH_1,

> +			  regs->ssc_stepsize_high);

> +		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_DIV_PER_LOW_1,

> +			  regs->ssc_div_per_low);

> +		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_DIV_PER_HIGH_1,

> +			  regs->ssc_div_per_high);

> +		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_ADJPER_LOW_1,

> +			  regs->ssc_adjper_low);

> +		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_ADJPER_HIGH_1,

> +			  regs->ssc_adjper_high);

> +		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_CONTROL,

> +			  SSC_EN | regs->ssc_control);

> +	}

> +}

> +

> +static void dsi_pll_config_hzindep_reg(struct dsi_pll_7nm *pll)

> +{

> +	void __iomem *base = pll->mmio;

> +	u8 analog_controls_five_1 = 0x01, vco_config_1 = 0x00;

> +

> +	if (pll->base.type == MSM_DSI_PHY_7NM_V4_1) {

> +		if (pll->vco_current_rate >= 3100000000ULL)

> +			analog_controls_five_1 = 0x03;

> +

> +		if (pll->vco_current_rate < 1520000000ULL)

> +			vco_config_1 = 0x08;

> +		else if (pll->vco_current_rate < 2990000000ULL)

> +			vco_config_1 = 0x01;

> +	}

> +

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_FIVE_1,

> +		  analog_controls_five_1);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_VCO_CONFIG_1, vco_config_1);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_FIVE, 0x01);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_TWO, 0x03);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_THREE, 0x00);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_DSM_DIVIDER, 0x00);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_FEEDBACK_DIVIDER, 0x4e);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_CALIBRATION_SETTINGS, 0x40);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_BAND_SEL_CAL_SETTINGS_THREE, 

> 0xba);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_FREQ_DETECT_SETTINGS_ONE, 0x0c);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_OUTDIV, 0x00);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_CORE_OVERRIDE, 0x00);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_DIGITAL_TIMERS_TWO, 0x08);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_PROP_GAIN_RATE_1, 0x0a);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_BAND_SEL_RATE_1, 0xc0);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_1, 

> 0x84);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_1, 

> 0x82);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_FL_INT_GAIN_PFILT_BAND_1, 

> 0x4c);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCK_OVERRIDE, 0x80);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_PFILT, 0x29);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_PFILT, 0x2f);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_IFILT, 0x2a);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_IFILT,

> +		  pll->base.type == MSM_DSI_PHY_7NM_V4_1 ? 0x3f : 0x22);

> +

> +	if (pll->base.type == MSM_DSI_PHY_7NM_V4_1) {

> +		pll_write(base + REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE, 0x22);

> +		if (pll->slave)

> +			pll_write(pll->slave->mmio + REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE, 

> 0x22);

> +	}

> +}

> +

> +static void dsi_pll_commit(struct dsi_pll_7nm *pll)

> +{

> +	void __iomem *base = pll->mmio;

> +	struct dsi_pll_regs *reg = &pll->reg_setup;

> +

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_CORE_INPUT_OVERRIDE, 0x12);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_DECIMAL_DIV_START_1,

> reg->decimal_div_start);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_LOW_1,

> reg->frac_div_start_low);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_MID_1,

> reg->frac_div_start_mid);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_HIGH_1,

> reg->frac_div_start_high);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCKDET_RATE_1,

> reg->pll_lockdet_rate);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCK_DELAY, 0x06);

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_CMODE_1, 0x10); /* TODO: 0x00 

> for CPHY */

> +	pll_write(base + REG_DSI_7nm_PHY_PLL_CLOCK_INVERTERS,

> reg->pll_clock_inverters);

> +}

> +

> +static int dsi_pll_7nm_vco_set_rate(struct clk_hw *hw, unsigned long 

> rate,

> +				     unsigned long parent_rate)

> +{

> +	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> +	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);

> +

> +	DBG("DSI PLL%d rate=%lu, parent's=%lu", pll_7nm->id, rate,

> +	    parent_rate);

> +

> +	pll_7nm->vco_current_rate = rate;

> +	pll_7nm->vco_ref_clk_rate = VCO_REF_CLK_RATE;

> +

> +	dsi_pll_setup_config(pll_7nm);

> +

> +	dsi_pll_calc_dec_frac(pll_7nm);

> +

> +	dsi_pll_calc_ssc(pll_7nm);

> +

> +	dsi_pll_commit(pll_7nm);

> +

> +	dsi_pll_config_hzindep_reg(pll_7nm);

> +

> +	dsi_pll_ssc_commit(pll_7nm);

> +

> +	/* flush, ensure all register writes are done*/

> +	wmb();

> +

> +	return 0;

> +}

> +

> +static int dsi_pll_7nm_lock_status(struct dsi_pll_7nm *pll)

> +{

> +	int rc;

> +	u32 status = 0;

> +	u32 const delay_us = 100;

> +	u32 const timeout_us = 5000;

> +

> +	rc = readl_poll_timeout_atomic(pll->mmio +

> +				       REG_DSI_7nm_PHY_PLL_COMMON_STATUS_ONE,

> +				       status,

> +				       ((status & BIT(0)) > 0),

> +				       delay_us,

> +				       timeout_us);

> +	if (rc)

> +		pr_err("DSI PLL(%d) lock failed, status=0x%08x\n",

> +		       pll->id, status);

> +

> +	return rc;

> +}

> +

> +static void dsi_pll_disable_pll_bias(struct dsi_pll_7nm *pll)

> +{

> +	u32 data = pll_read(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CTRL_0);

> +

> +	pll_write(pll->mmio + REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES, 0);

> +	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CTRL_0, data & 

> ~BIT(5));

> +	ndelay(250);

> +}

> +

> +static void dsi_pll_enable_pll_bias(struct dsi_pll_7nm *pll)

> +{

> +	u32 data = pll_read(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CTRL_0);

> +

> +	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CTRL_0, data | 

> BIT(5));

> +	pll_write(pll->mmio + REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES, 0xc0);

> +	ndelay(250);

> +}

> +

> +static void dsi_pll_disable_global_clk(struct dsi_pll_7nm *pll)

> +{

> +	u32 data;

> +

> +	data = pll_read(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CLK_CFG1);

> +	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CLK_CFG1, data & 

> ~BIT(5));

> +}

> +

> +static void dsi_pll_enable_global_clk(struct dsi_pll_7nm *pll)

> +{

> +	u32 data;

> +

> +	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CTRL_3, 0x04);

> +

> +	data = pll_read(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CLK_CFG1);

> +	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CLK_CFG1,

> +		  data | BIT(5) | BIT(4));

> +}

> +

> +static void dsi_pll_phy_dig_reset(struct dsi_pll_7nm *pll)

> +{

> +	/*

> +	 * Reset the PHY digital domain. This would be needed when

> +	 * coming out of a CX or analog rail power collapse while

> +	 * ensuring that the pads maintain LP00 or LP11 state

> +	 */

> +	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE4, 

> BIT(0));

> +	wmb(); /* Ensure that the reset is deasserted */

> +	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE4, 

> 0x0);

> +	wmb(); /* Ensure that the reset is deasserted */

> +}

> +

> +static int dsi_pll_7nm_vco_prepare(struct clk_hw *hw)

> +{

> +	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> +	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);

> +	int rc;

> +

> +	dsi_pll_enable_pll_bias(pll_7nm);

> +	if (pll_7nm->slave)

> +		dsi_pll_enable_pll_bias(pll_7nm->slave);

> +

> +	/* Start PLL */

> +	pll_write(pll_7nm->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_PLL_CNTRL, 

> 0x01);

> +

> +	/*

> +	 * ensure all PLL configurations are written prior to checking

> +	 * for PLL lock.

> +	 */

> +	wmb();

> +

> +	/* Check for PLL lock */

> +	rc = dsi_pll_7nm_lock_status(pll_7nm);

> +	if (rc) {

> +		pr_err("PLL(%d) lock failed\n", pll_7nm->id);

> +		goto error;

> +	}

> +

> +	pll->pll_on = true;

> +

> +	/*

> +	 * assert power on reset for PHY digital in case the PLL is

> +	 * enabled after CX of analog domain power collapse. This needs

> +	 * to be done before enabling the global clk.

> +	 */

> +	dsi_pll_phy_dig_reset(pll_7nm);

> +	if (pll_7nm->slave)

> +		dsi_pll_phy_dig_reset(pll_7nm->slave);

> +

> +	dsi_pll_enable_global_clk(pll_7nm);

> +	if (pll_7nm->slave)

> +		dsi_pll_enable_global_clk(pll_7nm->slave);

> +

> +error:

> +	return rc;

> +}

> +

> +static void dsi_pll_disable_sub(struct dsi_pll_7nm *pll)

> +{

> +	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_RBUF_CTRL, 0);

> +	dsi_pll_disable_pll_bias(pll);

> +}

> +

> +static void dsi_pll_7nm_vco_unprepare(struct clk_hw *hw)

> +{

> +	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> +	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);

> +

> +	/*

> +	 * To avoid any stray glitches while abruptly powering down the PLL

> +	 * make sure to gate the clock using the clock enable bit before

> +	 * powering down the PLL

> +	 */

> +	dsi_pll_disable_global_clk(pll_7nm);

> +	pll_write(pll_7nm->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_PLL_CNTRL, 0);

> +	dsi_pll_disable_sub(pll_7nm);

> +	if (pll_7nm->slave) {

> +		dsi_pll_disable_global_clk(pll_7nm->slave);

> +		dsi_pll_disable_sub(pll_7nm->slave);

> +	}

> +	/* flush, ensure all register writes are done */

> +	wmb();

> +	pll->pll_on = false;

> +}

> +

> +static unsigned long dsi_pll_7nm_vco_recalc_rate(struct clk_hw *hw,

> +						  unsigned long parent_rate)

> +{

> +	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> +	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);

> +	struct dsi_pll_config *config = &pll_7nm->pll_configuration;

> +	void __iomem *base = pll_7nm->mmio;

> +	u64 ref_clk = pll_7nm->vco_ref_clk_rate;

> +	u64 vco_rate = 0x0;

> +	u64 multiplier;

> +	u32 frac;

> +	u32 dec;

> +	u64 pll_freq, tmp64;

> +

> +	dec = pll_read(base + REG_DSI_7nm_PHY_PLL_DECIMAL_DIV_START_1);

> +	dec &= 0xff;

> +

> +	frac = pll_read(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_LOW_1);

> +	frac |= ((pll_read(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_MID_1) &

> +		  0xff) << 8);

> +	frac |= ((pll_read(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_HIGH_1) 

> &

> +		  0x3) << 16);

> +

> +	/*

> +	 * TODO:

> +	 *	1. Assumes prescaler is disabled

> +	 */

> +	multiplier = 1 << config->frac_bits;

> +	pll_freq = dec * (ref_clk * 2);

> +	tmp64 = (ref_clk * 2 * frac);

> +	pll_freq += div_u64(tmp64, multiplier);

> +

> +	vco_rate = pll_freq;

> +

> +	DBG("DSI PLL%d returning vco rate = %lu, dec = %x, frac = %x",

> +	    pll_7nm->id, (unsigned long)vco_rate, dec, frac);

> +

> +	return (unsigned long)vco_rate;

> +}

> +

> +static const struct clk_ops clk_ops_dsi_pll_7nm_vco = {

> +	.round_rate = msm_dsi_pll_helper_clk_round_rate,

> +	.set_rate = dsi_pll_7nm_vco_set_rate,

> +	.recalc_rate = dsi_pll_7nm_vco_recalc_rate,

> +	.prepare = dsi_pll_7nm_vco_prepare,

> +	.unprepare = dsi_pll_7nm_vco_unprepare,

> +};

> +

> +/*

> + * PLL Callbacks

> + */

> +

> +static void dsi_pll_7nm_save_state(struct msm_dsi_pll *pll)

> +{

> +	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);

> +	struct pll_7nm_cached_state *cached = &pll_7nm->cached_state;

> +	void __iomem *phy_base = pll_7nm->phy_cmn_mmio;

> +	u32 cmn_clk_cfg0, cmn_clk_cfg1;

> +

> +	cached->pll_out_div = pll_read(pll_7nm->mmio +

> +				       REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE);

> +	cached->pll_out_div &= 0x3;

> +

> +	cmn_clk_cfg0 = pll_read(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0);

> +	cached->bit_clk_div = cmn_clk_cfg0 & 0xf;

> +	cached->pix_clk_div = (cmn_clk_cfg0 & 0xf0) >> 4;

> +

> +	cmn_clk_cfg1 = pll_read(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);

> +	cached->pll_mux = cmn_clk_cfg1 & 0x3;

> +

> +	DBG("DSI PLL%d outdiv %x bit_clk_div %x pix_clk_div %x pll_mux %x",

> +	    pll_7nm->id, cached->pll_out_div, cached->bit_clk_div,

> +	    cached->pix_clk_div, cached->pll_mux);

> +}

> +

> +static int dsi_pll_7nm_restore_state(struct msm_dsi_pll *pll)

> +{

> +	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);

> +	struct pll_7nm_cached_state *cached = &pll_7nm->cached_state;

> +	void __iomem *phy_base = pll_7nm->phy_cmn_mmio;

> +	u32 val;

> +	int ret;

> +

> +	val = pll_read(pll_7nm->mmio + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE);

> +	val &= ~0x3;

> +	val |= cached->pll_out_div;

> +	pll_write(pll_7nm->mmio + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE, val);

> +

> +	pll_write(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0,

> +		  cached->bit_clk_div | (cached->pix_clk_div << 4));

> +

> +	val = pll_read(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);

> +	val &= ~0x3;

> +	val |= cached->pll_mux;

> +	pll_write(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, val);

> +

> +	ret = dsi_pll_7nm_vco_set_rate(&pll->clk_hw,

> pll_7nm->vco_current_rate, pll_7nm->vco_ref_clk_rate);

> +	if (ret) {

> +		DRM_DEV_ERROR(&pll_7nm->pdev->dev,

> +			"restore vco rate failed. ret=%d\n", ret);

> +		return ret;

> +	}

> +

> +	DBG("DSI PLL%d", pll_7nm->id);

> +

> +	return 0;

> +}

> +

> +static int dsi_pll_7nm_set_usecase(struct msm_dsi_pll *pll,

> +				    enum msm_dsi_phy_usecase uc)

> +{

> +	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);

> +	void __iomem *base = pll_7nm->phy_cmn_mmio;

> +	u32 data = 0x0;	/* internal PLL */

> +

> +	DBG("DSI PLL%d", pll_7nm->id);

> +

> +	switch (uc) {

> +	case MSM_DSI_PHY_STANDALONE:

> +		break;

> +	case MSM_DSI_PHY_MASTER:

> +		pll_7nm->slave = pll_7nm_list[(pll_7nm->id + 1) % DSI_MAX];

> +		break;

> +	case MSM_DSI_PHY_SLAVE:

> +		data = 0x1; /* external PLL */

> +		break;

> +	default:

> +		return -EINVAL;

> +	}

> +

> +	/* set PLL src */

> +	pll_write(base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, (data << 2));

> +

> +	pll_7nm->uc = uc;

> +

> +	return 0;

> +}

> +

> +static int dsi_pll_7nm_get_provider(struct msm_dsi_pll *pll,

> +				     struct clk **byte_clk_provider,

> +				     struct clk **pixel_clk_provider)

> +{

> +	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);

> +	struct clk_hw_onecell_data *hw_data = pll_7nm->hw_data;

> +

> +	DBG("DSI PLL%d", pll_7nm->id);

> +

> +	if (byte_clk_provider)

> +		*byte_clk_provider = hw_data->hws[DSI_BYTE_PLL_CLK]->clk;

> +	if (pixel_clk_provider)

> +		*pixel_clk_provider = hw_data->hws[DSI_PIXEL_PLL_CLK]->clk;

> +

> +	return 0;

> +}

> +

> +static void dsi_pll_7nm_destroy(struct msm_dsi_pll *pll)

> +{

> +	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);

> +	struct device *dev = &pll_7nm->pdev->dev;

> +

> +	DBG("DSI PLL%d", pll_7nm->id);

> +	of_clk_del_provider(dev->of_node);

> +

> +	clk_hw_unregister_divider(pll_7nm->out_dsiclk_hw);

> +	clk_hw_unregister_mux(pll_7nm->pclk_mux_hw);

> +	clk_hw_unregister_fixed_factor(pll_7nm->post_out_div_clk_hw);

> +	clk_hw_unregister_fixed_factor(pll_7nm->by_2_bit_clk_hw);

> +	clk_hw_unregister_fixed_factor(pll_7nm->byte_clk_hw);

> +	clk_hw_unregister_divider(pll_7nm->bit_clk_hw);

> +	clk_hw_unregister_divider(pll_7nm->out_div_clk_hw);

> +	clk_hw_unregister(&pll_7nm->base.clk_hw);

> +}

> +

> +/*

> + * The post dividers and mux clocks are created using the standard 

> divider and

> + * mux API. Unlike the 14nm PHY, the slave PLL doesn't need its 

> dividers/mux

> + * state to follow the master PLL's divider/mux state. Therefore, we 

> don't

> + * require special clock ops that also configure the slave PLL 

> registers

> + */

> +static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm)

> +{

> +	char clk_name[32], parent[32], vco_name[32];

> +	char parent2[32], parent3[32], parent4[32];

> +	struct clk_init_data vco_init = {

> +		.parent_names = (const char *[]){ "bi_tcxo" },

> +		.num_parents = 1,

> +		.name = vco_name,

> +		.flags = CLK_IGNORE_UNUSED,

> +		.ops = &clk_ops_dsi_pll_7nm_vco,

> +	};

> +	struct device *dev = &pll_7nm->pdev->dev;

> +	struct clk_hw_onecell_data *hw_data;

> +	struct clk_hw *hw;

> +	int ret;

> +

> +	DBG("DSI%d", pll_7nm->id);

> +

> +	hw_data = devm_kzalloc(dev, sizeof(*hw_data) +

> +			       NUM_PROVIDED_CLKS * sizeof(struct clk_hw *),

> +			       GFP_KERNEL);

> +	if (!hw_data)

> +		return -ENOMEM;

> +

> +	snprintf(vco_name, 32, "dsi%dvco_clk", pll_7nm->id);

> +	pll_7nm->base.clk_hw.init = &vco_init;

> +

> +	ret = clk_hw_register(dev, &pll_7nm->base.clk_hw);

> +	if (ret)

> +		return ret;

> +

> +	snprintf(clk_name, 32, "dsi%d_pll_out_div_clk", pll_7nm->id);

> +	snprintf(parent, 32, "dsi%dvco_clk", pll_7nm->id);

> +

> +	hw = clk_hw_register_divider(dev, clk_name,

> +				     parent, CLK_SET_RATE_PARENT,

> +				     pll_7nm->mmio +

> +				     REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE,

> +				     0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL);

> +	if (IS_ERR(hw)) {

> +		ret = PTR_ERR(hw);

> +		goto err_base_clk_hw;

> +	}

> +

> +	pll_7nm->out_div_clk_hw = hw;

> +

> +	snprintf(clk_name, 32, "dsi%d_pll_bit_clk", pll_7nm->id);

> +	snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_7nm->id);

> +

> +	/* BIT CLK: DIV_CTRL_3_0 */

> +	hw = clk_hw_register_divider(dev, clk_name, parent,

> +				     CLK_SET_RATE_PARENT,

> +				     pll_7nm->phy_cmn_mmio +

> +				     REG_DSI_7nm_PHY_CMN_CLK_CFG0,

> +				     0, 4, CLK_DIVIDER_ONE_BASED,

> +				     &pll_7nm->postdiv_lock);

> +	if (IS_ERR(hw)) {

> +		ret = PTR_ERR(hw);

> +		goto err_out_div_clk_hw;

> +	}

> +

> +	pll_7nm->bit_clk_hw = hw;

> +

> +	snprintf(clk_name, 32, "dsi%d_phy_pll_out_byteclk", pll_7nm->id);

> +	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->id);

> +

> +	/* DSI Byte clock = VCO_CLK / OUT_DIV / BIT_DIV / 8 */

> +	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,

> +					  CLK_SET_RATE_PARENT, 1, 8);

> +	if (IS_ERR(hw)) {

> +		ret = PTR_ERR(hw);

> +		goto err_bit_clk_hw;

> +	}

> +

> +	pll_7nm->byte_clk_hw = hw;

> +	hw_data->hws[DSI_BYTE_PLL_CLK] = hw;

> +

> +	snprintf(clk_name, 32, "dsi%d_pll_by_2_bit_clk", pll_7nm->id);

> +	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->id);

> +

> +	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,

> +					  0, 1, 2);

> +	if (IS_ERR(hw)) {

> +		ret = PTR_ERR(hw);

> +		goto err_byte_clk_hw;

> +	}

> +

> +	pll_7nm->by_2_bit_clk_hw = hw;

> +

> +	snprintf(clk_name, 32, "dsi%d_pll_post_out_div_clk", pll_7nm->id);

> +	snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_7nm->id);

> +

> +	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,

> +					  0, 1, 4);

> +	if (IS_ERR(hw)) {

> +		ret = PTR_ERR(hw);

> +		goto err_by_2_bit_clk_hw;

> +	}

> +

> +	pll_7nm->post_out_div_clk_hw = hw;

> +

> +	snprintf(clk_name, 32, "dsi%d_pclk_mux", pll_7nm->id);

> +	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->id);

> +	snprintf(parent2, 32, "dsi%d_pll_by_2_bit_clk", pll_7nm->id);

> +	snprintf(parent3, 32, "dsi%d_pll_out_div_clk", pll_7nm->id);

> +	snprintf(parent4, 32, "dsi%d_pll_post_out_div_clk", pll_7nm->id);

> +

> +	hw = clk_hw_register_mux(dev, clk_name,

> +				 ((const char *[]){

> +				 parent, parent2, parent3, parent4

> +				 }), 4, 0, pll_7nm->phy_cmn_mmio +

> +				 REG_DSI_7nm_PHY_CMN_CLK_CFG1,

> +				 0, 2, 0, NULL);

> +	if (IS_ERR(hw)) {

> +		ret = PTR_ERR(hw);

> +		goto err_post_out_div_clk_hw;

> +	}

> +

> +	pll_7nm->pclk_mux_hw = hw;

> +

> +	snprintf(clk_name, 32, "dsi%d_phy_pll_out_dsiclk", pll_7nm->id);

> +	snprintf(parent, 32, "dsi%d_pclk_mux", pll_7nm->id);

> +

> +	/* PIX CLK DIV : DIV_CTRL_7_4*/

> +	hw = clk_hw_register_divider(dev, clk_name, parent,

> +				     0, pll_7nm->phy_cmn_mmio +

> +					REG_DSI_7nm_PHY_CMN_CLK_CFG0,

> +				     4, 4, CLK_DIVIDER_ONE_BASED,

> +				     &pll_7nm->postdiv_lock);

> +	if (IS_ERR(hw)) {

> +		ret = PTR_ERR(hw);

> +		goto err_pclk_mux_hw;

> +	}

> +

> +	pll_7nm->out_dsiclk_hw = hw;

> +	hw_data->hws[DSI_PIXEL_PLL_CLK] = hw;

> +

> +	hw_data->num = NUM_PROVIDED_CLKS;

> +	pll_7nm->hw_data = hw_data;

> +

> +	ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,

> +				     pll_7nm->hw_data);

> +	if (ret) {

> +		DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret);

> +		goto err_dsiclk_hw;

> +	}

> +

> +	return 0;

> +

> +err_dsiclk_hw:

> +	clk_hw_unregister_divider(pll_7nm->out_dsiclk_hw);

> +err_pclk_mux_hw:

> +	clk_hw_unregister_mux(pll_7nm->pclk_mux_hw);

> +err_post_out_div_clk_hw:

> +	clk_hw_unregister_fixed_factor(pll_7nm->post_out_div_clk_hw);

> +err_by_2_bit_clk_hw:

> +	clk_hw_unregister_fixed_factor(pll_7nm->by_2_bit_clk_hw);

> +err_byte_clk_hw:

> +	clk_hw_unregister_fixed_factor(pll_7nm->byte_clk_hw);

> +err_bit_clk_hw:

> +	clk_hw_unregister_divider(pll_7nm->bit_clk_hw);

> +err_out_div_clk_hw:

> +	clk_hw_unregister_divider(pll_7nm->out_div_clk_hw);

> +err_base_clk_hw:

> +	clk_hw_unregister(&pll_7nm->base.clk_hw);

> +

> +	return ret;

> +}

> +

> +struct msm_dsi_pll *msm_dsi_pll_7nm_init(struct platform_device *pdev,

> +					enum msm_dsi_phy_type type, int id)

> +{

> +	struct dsi_pll_7nm *pll_7nm;

> +	struct msm_dsi_pll *pll;

> +	int ret;

> +

> +	pll_7nm = devm_kzalloc(&pdev->dev, sizeof(*pll_7nm), GFP_KERNEL);

> +	if (!pll_7nm)

> +		return ERR_PTR(-ENOMEM);

> +

> +	DBG("DSI PLL%d", id);

> +

> +	pll_7nm->pdev = pdev;

> +	pll_7nm->id = id;

> +	pll_7nm_list[id] = pll_7nm;

> +

> +	pll_7nm->phy_cmn_mmio = msm_ioremap(pdev, "dsi_phy", "DSI_PHY");

> +	if (IS_ERR_OR_NULL(pll_7nm->phy_cmn_mmio)) {

> +		DRM_DEV_ERROR(&pdev->dev, "failed to map CMN PHY base\n");

> +		return ERR_PTR(-ENOMEM);

> +	}

> +

> +	pll_7nm->mmio = msm_ioremap(pdev, "dsi_pll", "DSI_PLL");

> +	if (IS_ERR_OR_NULL(pll_7nm->mmio)) {

> +		DRM_DEV_ERROR(&pdev->dev, "failed to map PLL base\n");

> +		return ERR_PTR(-ENOMEM);

> +	}

> +

> +	spin_lock_init(&pll_7nm->postdiv_lock);

> +

> +	pll = &pll_7nm->base;

> +	pll->min_rate = 1000000000UL;

> +	pll->max_rate = 3500000000UL;

> +	if (type == MSM_DSI_PHY_7NM_V4_1) {

> +		pll->min_rate = 600000000UL;

> +		pll->max_rate = (unsigned long)5000000000ULL;

> +		/* workaround for max rate overflowing on 32-bit builds: */

> +		pll->max_rate = max(pll->max_rate, 0xffffffffUL);

> +	}

> +	pll->get_provider = dsi_pll_7nm_get_provider;

> +	pll->destroy = dsi_pll_7nm_destroy;

> +	pll->save_state = dsi_pll_7nm_save_state;

> +	pll->restore_state = dsi_pll_7nm_restore_state;

> +	pll->set_usecase = dsi_pll_7nm_set_usecase;

> +

> +	pll_7nm->vco_delay = 1;

> +

> +	ret = pll_7nm_register(pll_7nm);

> +	if (ret) {

> +		DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret);

> +		return ERR_PTR(ret);

> +	}

> +

> +	/* TODO: Remove this when we have proper display handover support */

> +	msm_dsi_pll_save_state(pll);

> +

> +	return pll;

> +}

> +

>  static int dsi_phy_hw_v4_0_is_pll_on(struct msm_dsi_phy *phy)

>  {

>  	void __iomem *base = phy->base;

> diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c

> b/drivers/gpu/drm/msm/dsi/phy/dsi_pll.c

> similarity index 100%

> rename from drivers/gpu/drm/msm/dsi/pll/dsi_pll.c

> rename to drivers/gpu/drm/msm/dsi/phy/dsi_pll.c

> diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h

> b/drivers/gpu/drm/msm/dsi/phy/dsi_pll.h

> similarity index 100%

> rename from drivers/gpu/drm/msm/dsi/pll/dsi_pll.h

> rename to drivers/gpu/drm/msm/dsi/phy/dsi_pll.h

> diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c

> b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c

> deleted file mode 100644

> index de3b802ccd3d..000000000000

> --- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c

> +++ /dev/null

> @@ -1,881 +0,0 @@

> -/*

> - * SPDX-License-Identifier: GPL-2.0

> - * Copyright (c) 2018, The Linux Foundation

> - */

> -

> -#include <linux/clk.h>

> -#include <linux/clk-provider.h>

> -#include <linux/iopoll.h>

> -

> -#include "dsi_pll.h"

> -#include "dsi.xml.h"

> -

> -/*

> - * DSI PLL 10nm - clock diagram (eg: DSI0):

> - *

> - *           dsi0_pll_out_div_clk  dsi0_pll_bit_clk

> - *                              |                |

> - *                              |                |

> - *                 +---------+  |  +----------+  |  +----+

> - *  dsi0vco_clk ---| out_div |--o--| divl_3_0 |--o--| /8 |--

> dsi0_phy_pll_out_byteclk

> - *                 +---------+  |  +----------+  |  +----+

> - *                              |                |

> - *                              |                |

> dsi0_pll_by_2_bit_clk

> - *                              |                |          |

> - *                              |                |  +----+  |  |\

> dsi0_pclk_mux

> - *                              |                |--| /2 |--o--| \   |

> - *                              |                |  +----+     |  \

> |  +---------+

> - *                              |                --------------|

> |--o--| div_7_4 |-- dsi0_phy_pll_out_dsiclk

> - *                              |------------------------------|  /

>   +---------+

> - *                              |          +-----+             | /

> - *                              -----------| /4? |--o----------|/

> - *                                         +-----+  |           |

> - *                                                  |           

> |dsiclk_sel

> - *                                                  |

> - *                                                  

> dsi0_pll_post_out_div_clk

> - */

> -

> -#define DSI_BYTE_PLL_CLK		0

> -#define DSI_PIXEL_PLL_CLK		1

> -#define NUM_PROVIDED_CLKS		2

> -

> -#define VCO_REF_CLK_RATE		19200000

> -

> -struct dsi_pll_regs {

> -	u32 pll_prop_gain_rate;

> -	u32 pll_lockdet_rate;

> -	u32 decimal_div_start;

> -	u32 frac_div_start_low;

> -	u32 frac_div_start_mid;

> -	u32 frac_div_start_high;

> -	u32 pll_clock_inverters;

> -	u32 ssc_stepsize_low;

> -	u32 ssc_stepsize_high;

> -	u32 ssc_div_per_low;

> -	u32 ssc_div_per_high;

> -	u32 ssc_adjper_low;

> -	u32 ssc_adjper_high;

> -	u32 ssc_control;

> -};

> -

> -struct dsi_pll_config {

> -	u32 ref_freq;

> -	bool div_override;

> -	u32 output_div;

> -	bool ignore_frac;

> -	bool disable_prescaler;

> -	bool enable_ssc;

> -	bool ssc_center;

> -	u32 dec_bits;

> -	u32 frac_bits;

> -	u32 lock_timer;

> -	u32 ssc_freq;

> -	u32 ssc_offset;

> -	u32 ssc_adj_per;

> -	u32 thresh_cycles;

> -	u32 refclk_cycles;

> -};

> -

> -struct pll_10nm_cached_state {

> -	unsigned long vco_rate;

> -	u8 bit_clk_div;

> -	u8 pix_clk_div;

> -	u8 pll_out_div;

> -	u8 pll_mux;

> -};

> -

> -struct dsi_pll_10nm {

> -	struct msm_dsi_pll base;

> -

> -	int id;

> -	struct platform_device *pdev;

> -

> -	void __iomem *phy_cmn_mmio;

> -	void __iomem *mmio;

> -

> -	u64 vco_ref_clk_rate;

> -	u64 vco_current_rate;

> -

> -	/* protects REG_DSI_10nm_PHY_CMN_CLK_CFG0 register */

> -	spinlock_t postdiv_lock;

> -

> -	int vco_delay;

> -	struct dsi_pll_config pll_configuration;

> -	struct dsi_pll_regs reg_setup;

> -

> -	/* private clocks: */

> -	struct clk_hw *out_div_clk_hw;

> -	struct clk_hw *bit_clk_hw;

> -	struct clk_hw *byte_clk_hw;

> -	struct clk_hw *by_2_bit_clk_hw;

> -	struct clk_hw *post_out_div_clk_hw;

> -	struct clk_hw *pclk_mux_hw;

> -	struct clk_hw *out_dsiclk_hw;

> -

> -	/* clock-provider: */

> -	struct clk_hw_onecell_data *hw_data;

> -

> -	struct pll_10nm_cached_state cached_state;

> -

> -	enum msm_dsi_phy_usecase uc;

> -	struct dsi_pll_10nm *slave;

> -};

> -

> -#define to_pll_10nm(x)	container_of(x, struct dsi_pll_10nm, base)

> -

> -/*

> - * Global list of private DSI PLL struct pointers. We need this for 

> Dual DSI

> - * mode, where the master PLL's clk_ops needs access the slave's 

> private data

> - */

> -static struct dsi_pll_10nm *pll_10nm_list[DSI_MAX];

> -

> -static void dsi_pll_setup_config(struct dsi_pll_10nm *pll)

> -{

> -	struct dsi_pll_config *config = &pll->pll_configuration;

> -

> -	config->ref_freq = pll->vco_ref_clk_rate;

> -	config->output_div = 1;

> -	config->dec_bits = 8;

> -	config->frac_bits = 18;

> -	config->lock_timer = 64;

> -	config->ssc_freq = 31500;

> -	config->ssc_offset = 5000;

> -	config->ssc_adj_per = 2;

> -	config->thresh_cycles = 32;

> -	config->refclk_cycles = 256;

> -

> -	config->div_override = false;

> -	config->ignore_frac = false;

> -	config->disable_prescaler = false;

> -

> -	config->enable_ssc = false;

> -	config->ssc_center = 0;

> -}

> -

> -static void dsi_pll_calc_dec_frac(struct dsi_pll_10nm *pll)

> -{

> -	struct dsi_pll_config *config = &pll->pll_configuration;

> -	struct dsi_pll_regs *regs = &pll->reg_setup;

> -	u64 fref = pll->vco_ref_clk_rate;

> -	u64 pll_freq;

> -	u64 divider;

> -	u64 dec, dec_multiple;

> -	u32 frac;

> -	u64 multiplier;

> -

> -	pll_freq = pll->vco_current_rate;

> -

> -	if (config->disable_prescaler)

> -		divider = fref;

> -	else

> -		divider = fref * 2;

> -

> -	multiplier = 1 << config->frac_bits;

> -	dec_multiple = div_u64(pll_freq * multiplier, divider);

> -	dec = div_u64_rem(dec_multiple, multiplier, &frac);

> -

> -	if (pll_freq <= 1900000000UL)

> -		regs->pll_prop_gain_rate = 8;

> -	else if (pll_freq <= 3000000000UL)

> -		regs->pll_prop_gain_rate = 10;

> -	else

> -		regs->pll_prop_gain_rate = 12;

> -	if (pll_freq < 1100000000UL)

> -		regs->pll_clock_inverters = 8;

> -	else

> -		regs->pll_clock_inverters = 0;

> -

> -	regs->pll_lockdet_rate = config->lock_timer;

> -	regs->decimal_div_start = dec;

> -	regs->frac_div_start_low = (frac & 0xff);

> -	regs->frac_div_start_mid = (frac & 0xff00) >> 8;

> -	regs->frac_div_start_high = (frac & 0x30000) >> 16;

> -}

> -

> -#define SSC_CENTER		BIT(0)

> -#define SSC_EN			BIT(1)

> -

> -static void dsi_pll_calc_ssc(struct dsi_pll_10nm *pll)

> -{

> -	struct dsi_pll_config *config = &pll->pll_configuration;

> -	struct dsi_pll_regs *regs = &pll->reg_setup;

> -	u32 ssc_per;

> -	u32 ssc_mod;

> -	u64 ssc_step_size;

> -	u64 frac;

> -

> -	if (!config->enable_ssc) {

> -		DBG("SSC not enabled\n");

> -		return;

> -	}

> -

> -	ssc_per = DIV_ROUND_CLOSEST(config->ref_freq, config->ssc_freq) / 2 - 

> 1;

> -	ssc_mod = (ssc_per + 1) % (config->ssc_adj_per + 1);

> -	ssc_per -= ssc_mod;

> -

> -	frac = regs->frac_div_start_low |

> -			(regs->frac_div_start_mid << 8) |

> -			(regs->frac_div_start_high << 16);

> -	ssc_step_size = regs->decimal_div_start;

> -	ssc_step_size *= (1 << config->frac_bits);

> -	ssc_step_size += frac;

> -	ssc_step_size *= config->ssc_offset;

> -	ssc_step_size *= (config->ssc_adj_per + 1);

> -	ssc_step_size = div_u64(ssc_step_size, (ssc_per + 1));

> -	ssc_step_size = DIV_ROUND_CLOSEST_ULL(ssc_step_size, 1000000);

> -

> -	regs->ssc_div_per_low = ssc_per & 0xFF;

> -	regs->ssc_div_per_high = (ssc_per & 0xFF00) >> 8;

> -	regs->ssc_stepsize_low = (u32)(ssc_step_size & 0xFF);

> -	regs->ssc_stepsize_high = (u32)((ssc_step_size & 0xFF00) >> 8);

> -	regs->ssc_adjper_low = config->ssc_adj_per & 0xFF;

> -	regs->ssc_adjper_high = (config->ssc_adj_per & 0xFF00) >> 8;

> -

> -	regs->ssc_control = config->ssc_center ? SSC_CENTER : 0;

> -

> -	pr_debug("SCC: Dec:%d, frac:%llu, frac_bits:%d\n",

> -		 regs->decimal_div_start, frac, config->frac_bits);

> -	pr_debug("SSC: div_per:0x%X, stepsize:0x%X, adjper:0x%X\n",

> -		 ssc_per, (u32)ssc_step_size, config->ssc_adj_per);

> -}

> -

> -static void dsi_pll_ssc_commit(struct dsi_pll_10nm *pll)

> -{

> -	void __iomem *base = pll->mmio;

> -	struct dsi_pll_regs *regs = &pll->reg_setup;

> -

> -	if (pll->pll_configuration.enable_ssc) {

> -		pr_debug("SSC is enabled\n");

> -

> -		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_STEPSIZE_LOW_1,

> -			  regs->ssc_stepsize_low);

> -		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_STEPSIZE_HIGH_1,

> -			  regs->ssc_stepsize_high);

> -		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_DIV_PER_LOW_1,

> -			  regs->ssc_div_per_low);

> -		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_DIV_PER_HIGH_1,

> -			  regs->ssc_div_per_high);

> -		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_DIV_ADJPER_LOW_1,

> -			  regs->ssc_adjper_low);

> -		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_DIV_ADJPER_HIGH_1,

> -			  regs->ssc_adjper_high);

> -		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_CONTROL,

> -			  SSC_EN | regs->ssc_control);

> -	}

> -}

> -

> -static void dsi_pll_config_hzindep_reg(struct dsi_pll_10nm *pll)

> -{

> -	void __iomem *base = pll->mmio;

> -

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_ANALOG_CONTROLS_ONE, 0x80);

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_ANALOG_CONTROLS_TWO, 0x03);

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_ANALOG_CONTROLS_THREE, 0x00);

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_DSM_DIVIDER, 0x00);

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_FEEDBACK_DIVIDER, 0x4e);

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_CALIBRATION_SETTINGS, 0x40);

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_BAND_SEL_CAL_SETTINGS_THREE,

> -		  0xba);

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_FREQ_DETECT_SETTINGS_ONE, 

> 0x0c);

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_OUTDIV, 0x00);

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_CORE_OVERRIDE, 0x00);

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_DIGITAL_TIMERS_TWO, 0x08);

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_PROP_GAIN_RATE_1, 0x08);

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_BAND_SET_RATE_1, 0xc0);

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_1, 

> 0xfa);

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_FL_INT_GAIN_PFILT_BAND_1,

> -		  0x4c);

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_LOCK_OVERRIDE, 0x80);

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_PFILT, 0x29);

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_IFILT, 0x3f);

> -}

> -

> -static void dsi_pll_commit(struct dsi_pll_10nm *pll)

> -{

> -	void __iomem *base = pll->mmio;

> -	struct dsi_pll_regs *reg = &pll->reg_setup;

> -

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_CORE_INPUT_OVERRIDE, 0x12);

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_DECIMAL_DIV_START_1,

> -		  reg->decimal_div_start);

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_LOW_1,

> -		  reg->frac_div_start_low);

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_MID_1,

> -		  reg->frac_div_start_mid);

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_HIGH_1,

> -		  reg->frac_div_start_high);

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_LOCKDET_RATE_1,

> -		  reg->pll_lockdet_rate);

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_LOCK_DELAY, 0x06);

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_CMODE, 0x10);

> -	pll_write(base + REG_DSI_10nm_PHY_PLL_CLOCK_INVERTERS,

> -		  reg->pll_clock_inverters);

> -}

> -

> -static int dsi_pll_10nm_vco_set_rate(struct clk_hw *hw, unsigned long 

> rate,

> -				     unsigned long parent_rate)

> -{

> -	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> -	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);

> -

> -	DBG("DSI PLL%d rate=%lu, parent's=%lu", pll_10nm->id, rate,

> -	    parent_rate);

> -

> -	pll_10nm->vco_current_rate = rate;

> -	pll_10nm->vco_ref_clk_rate = VCO_REF_CLK_RATE;

> -

> -	dsi_pll_setup_config(pll_10nm);

> -

> -	dsi_pll_calc_dec_frac(pll_10nm);

> -

> -	dsi_pll_calc_ssc(pll_10nm);

> -

> -	dsi_pll_commit(pll_10nm);

> -

> -	dsi_pll_config_hzindep_reg(pll_10nm);

> -

> -	dsi_pll_ssc_commit(pll_10nm);

> -

> -	/* flush, ensure all register writes are done*/

> -	wmb();

> -

> -	return 0;

> -}

> -

> -static int dsi_pll_10nm_lock_status(struct dsi_pll_10nm *pll)

> -{

> -	struct device *dev = &pll->pdev->dev;

> -	int rc;

> -	u32 status = 0;

> -	u32 const delay_us = 100;

> -	u32 const timeout_us = 5000;

> -

> -	rc = readl_poll_timeout_atomic(pll->mmio +

> -				       REG_DSI_10nm_PHY_PLL_COMMON_STATUS_ONE,

> -				       status,

> -				       ((status & BIT(0)) > 0),

> -				       delay_us,

> -				       timeout_us);

> -	if (rc)

> -		DRM_DEV_ERROR(dev, "DSI PLL(%d) lock failed, status=0x%08x\n",

> -			      pll->id, status);

> -

> -	return rc;

> -}

> -

> -static void dsi_pll_disable_pll_bias(struct dsi_pll_10nm *pll)

> -{

> -	u32 data = pll_read(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CTRL_0);

> -

> -	pll_write(pll->mmio + REG_DSI_10nm_PHY_PLL_SYSTEM_MUXES, 0);

> -	pll_write(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CTRL_0,

> -		  data & ~BIT(5));

> -	ndelay(250);

> -}

> -

> -static void dsi_pll_enable_pll_bias(struct dsi_pll_10nm *pll)

> -{

> -	u32 data = pll_read(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CTRL_0);

> -

> -	pll_write(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CTRL_0,

> -		  data | BIT(5));

> -	pll_write(pll->mmio + REG_DSI_10nm_PHY_PLL_SYSTEM_MUXES, 0xc0);

> -	ndelay(250);

> -}

> -

> -static void dsi_pll_disable_global_clk(struct dsi_pll_10nm *pll)

> -{

> -	u32 data;

> -

> -	data = pll_read(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CLK_CFG1);

> -	pll_write(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CLK_CFG1,

> -		  data & ~BIT(5));

> -}

> -

> -static void dsi_pll_enable_global_clk(struct dsi_pll_10nm *pll)

> -{

> -	u32 data;

> -

> -	data = pll_read(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CLK_CFG1);

> -	pll_write(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CLK_CFG1,

> -		  data | BIT(5));

> -}

> -

> -static int dsi_pll_10nm_vco_prepare(struct clk_hw *hw)

> -{

> -	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> -	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);

> -	struct device *dev = &pll_10nm->pdev->dev;

> -	int rc;

> -

> -	dsi_pll_enable_pll_bias(pll_10nm);

> -	if (pll_10nm->slave)

> -		dsi_pll_enable_pll_bias(pll_10nm->slave);

> -

> -	rc = dsi_pll_10nm_vco_set_rate(hw,pll_10nm->vco_current_rate, 0);

> -	if (rc) {

> -		DRM_DEV_ERROR(dev, "vco_set_rate failed, rc=%d\n", rc);

> -		return rc;

> -	}

> -

> -	/* Start PLL */

> -	pll_write(pll_10nm->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_PLL_CNTRL,

> -		  0x01);

> -

> -	/*

> -	 * ensure all PLL configurations are written prior to checking

> -	 * for PLL lock.

> -	 */

> -	wmb();

> -

> -	/* Check for PLL lock */

> -	rc = dsi_pll_10nm_lock_status(pll_10nm);

> -	if (rc) {

> -		DRM_DEV_ERROR(dev, "PLL(%d) lock failed\n", pll_10nm->id);

> -		goto error;

> -	}

> -

> -	pll->pll_on = true;

> -

> -	dsi_pll_enable_global_clk(pll_10nm);

> -	if (pll_10nm->slave)

> -		dsi_pll_enable_global_clk(pll_10nm->slave);

> -

> -	pll_write(pll_10nm->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_RBUF_CTRL,

> -		  0x01);

> -	if (pll_10nm->slave)

> -		pll_write(pll_10nm->slave->phy_cmn_mmio +

> -			  REG_DSI_10nm_PHY_CMN_RBUF_CTRL, 0x01);

> -

> -error:

> -	return rc;

> -}

> -

> -static void dsi_pll_disable_sub(struct dsi_pll_10nm *pll)

> -{

> -	pll_write(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_RBUF_CTRL, 0);

> -	dsi_pll_disable_pll_bias(pll);

> -}

> -

> -static void dsi_pll_10nm_vco_unprepare(struct clk_hw *hw)

> -{

> -	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> -	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);

> -

> -	/*

> -	 * To avoid any stray glitches while abruptly powering down the PLL

> -	 * make sure to gate the clock using the clock enable bit before

> -	 * powering down the PLL

> -	 */

> -	dsi_pll_disable_global_clk(pll_10nm);

> -	pll_write(pll_10nm->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_PLL_CNTRL, 

> 0);

> -	dsi_pll_disable_sub(pll_10nm);

> -	if (pll_10nm->slave) {

> -		dsi_pll_disable_global_clk(pll_10nm->slave);

> -		dsi_pll_disable_sub(pll_10nm->slave);

> -	}

> -	/* flush, ensure all register writes are done */

> -	wmb();

> -	pll->pll_on = false;

> -}

> -

> -static unsigned long dsi_pll_10nm_vco_recalc_rate(struct clk_hw *hw,

> -						  unsigned long parent_rate)

> -{

> -	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> -	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);

> -	struct dsi_pll_config *config = &pll_10nm->pll_configuration;

> -	void __iomem *base = pll_10nm->mmio;

> -	u64 ref_clk = pll_10nm->vco_ref_clk_rate;

> -	u64 vco_rate = 0x0;

> -	u64 multiplier;

> -	u32 frac;

> -	u32 dec;

> -	u64 pll_freq, tmp64;

> -

> -	dec = pll_read(base + REG_DSI_10nm_PHY_PLL_DECIMAL_DIV_START_1);

> -	dec &= 0xff;

> -

> -	frac = pll_read(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_LOW_1);

> -	frac |= ((pll_read(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_MID_1) 

> &

> -		  0xff) << 8);

> -	frac |= ((pll_read(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_HIGH_1) 

> &

> -		  0x3) << 16);

> -

> -	/*

> -	 * TODO:

> -	 *	1. Assumes prescaler is disabled

> -	 */

> -	multiplier = 1 << config->frac_bits;

> -	pll_freq = dec * (ref_clk * 2);

> -	tmp64 = (ref_clk * 2 * frac);

> -	pll_freq += div_u64(tmp64, multiplier);

> -

> -	vco_rate = pll_freq;

> -

> -	DBG("DSI PLL%d returning vco rate = %lu, dec = %x, frac = %x",

> -	    pll_10nm->id, (unsigned long)vco_rate, dec, frac);

> -

> -	return (unsigned long)vco_rate;

> -}

> -

> -static const struct clk_ops clk_ops_dsi_pll_10nm_vco = {

> -	.round_rate = msm_dsi_pll_helper_clk_round_rate,

> -	.set_rate = dsi_pll_10nm_vco_set_rate,

> -	.recalc_rate = dsi_pll_10nm_vco_recalc_rate,

> -	.prepare = dsi_pll_10nm_vco_prepare,

> -	.unprepare = dsi_pll_10nm_vco_unprepare,

> -};

> -

> -/*

> - * PLL Callbacks

> - */

> -

> -static void dsi_pll_10nm_save_state(struct msm_dsi_pll *pll)

> -{

> -	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);

> -	struct pll_10nm_cached_state *cached = &pll_10nm->cached_state;

> -	void __iomem *phy_base = pll_10nm->phy_cmn_mmio;

> -	u32 cmn_clk_cfg0, cmn_clk_cfg1;

> -

> -	cached->pll_out_div = pll_read(pll_10nm->mmio +

> -				       REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE);

> -	cached->pll_out_div &= 0x3;

> -

> -	cmn_clk_cfg0 = pll_read(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG0);

> -	cached->bit_clk_div = cmn_clk_cfg0 & 0xf;

> -	cached->pix_clk_div = (cmn_clk_cfg0 & 0xf0) >> 4;

> -

> -	cmn_clk_cfg1 = pll_read(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG1);

> -	cached->pll_mux = cmn_clk_cfg1 & 0x3;

> -

> -	DBG("DSI PLL%d outdiv %x bit_clk_div %x pix_clk_div %x pll_mux %x",

> -	    pll_10nm->id, cached->pll_out_div, cached->bit_clk_div,

> -	    cached->pix_clk_div, cached->pll_mux);

> -}

> -

> -static int dsi_pll_10nm_restore_state(struct msm_dsi_pll *pll)

> -{

> -	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);

> -	struct pll_10nm_cached_state *cached = &pll_10nm->cached_state;

> -	void __iomem *phy_base = pll_10nm->phy_cmn_mmio;

> -	u32 val;

> -	int ret;

> -

> -	val = pll_read(pll_10nm->mmio + 

> REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE);

> -	val &= ~0x3;

> -	val |= cached->pll_out_div;

> -	pll_write(pll_10nm->mmio + REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE, 

> val);

> -

> -	pll_write(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG0,

> -		  cached->bit_clk_div | (cached->pix_clk_div << 4));

> -

> -	val = pll_read(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG1);

> -	val &= ~0x3;

> -	val |= cached->pll_mux;

> -	pll_write(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG1, val);

> -

> -	ret = dsi_pll_10nm_vco_set_rate(&pll->clk_hw,

> pll_10nm->vco_current_rate, pll_10nm->vco_ref_clk_rate);

> -	if (ret) {

> -		DRM_DEV_ERROR(&pll_10nm->pdev->dev,

> -			"restore vco rate failed. ret=%d\n", ret);

> -		return ret;

> -	}

> -

> -	DBG("DSI PLL%d", pll_10nm->id);

> -

> -	return 0;

> -}

> -

> -static int dsi_pll_10nm_set_usecase(struct msm_dsi_pll *pll,

> -				    enum msm_dsi_phy_usecase uc)

> -{

> -	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);

> -	void __iomem *base = pll_10nm->phy_cmn_mmio;

> -	u32 data = 0x0;	/* internal PLL */

> -

> -	DBG("DSI PLL%d", pll_10nm->id);

> -

> -	switch (uc) {

> -	case MSM_DSI_PHY_STANDALONE:

> -		break;

> -	case MSM_DSI_PHY_MASTER:

> -		pll_10nm->slave = pll_10nm_list[(pll_10nm->id + 1) % DSI_MAX];

> -		break;

> -	case MSM_DSI_PHY_SLAVE:

> -		data = 0x1; /* external PLL */

> -		break;

> -	default:

> -		return -EINVAL;

> -	}

> -

> -	/* set PLL src */

> -	pll_write(base + REG_DSI_10nm_PHY_CMN_CLK_CFG1, (data << 2));

> -

> -	pll_10nm->uc = uc;

> -

> -	return 0;

> -}

> -

> -static int dsi_pll_10nm_get_provider(struct msm_dsi_pll *pll,

> -				     struct clk **byte_clk_provider,

> -				     struct clk **pixel_clk_provider)

> -{

> -	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);

> -	struct clk_hw_onecell_data *hw_data = pll_10nm->hw_data;

> -

> -	DBG("DSI PLL%d", pll_10nm->id);

> -

> -	if (byte_clk_provider)

> -		*byte_clk_provider = hw_data->hws[DSI_BYTE_PLL_CLK]->clk;

> -	if (pixel_clk_provider)

> -		*pixel_clk_provider = hw_data->hws[DSI_PIXEL_PLL_CLK]->clk;

> -

> -	return 0;

> -}

> -

> -static void dsi_pll_10nm_destroy(struct msm_dsi_pll *pll)

> -{

> -	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);

> -	struct device *dev = &pll_10nm->pdev->dev;

> -

> -	DBG("DSI PLL%d", pll_10nm->id);

> -	of_clk_del_provider(dev->of_node);

> -

> -	clk_hw_unregister_divider(pll_10nm->out_dsiclk_hw);

> -	clk_hw_unregister_mux(pll_10nm->pclk_mux_hw);

> -	clk_hw_unregister_fixed_factor(pll_10nm->post_out_div_clk_hw);

> -	clk_hw_unregister_fixed_factor(pll_10nm->by_2_bit_clk_hw);

> -	clk_hw_unregister_fixed_factor(pll_10nm->byte_clk_hw);

> -	clk_hw_unregister_divider(pll_10nm->bit_clk_hw);

> -	clk_hw_unregister_divider(pll_10nm->out_div_clk_hw);

> -	clk_hw_unregister(&pll_10nm->base.clk_hw);

> -}

> -

> -/*

> - * The post dividers and mux clocks are created using the standard 

> divider and

> - * mux API. Unlike the 14nm PHY, the slave PLL doesn't need its 

> dividers/mux

> - * state to follow the master PLL's divider/mux state. Therefore, we 

> don't

> - * require special clock ops that also configure the slave PLL 

> registers

> - */

> -static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm)

> -{

> -	char clk_name[32], parent[32], vco_name[32];

> -	char parent2[32], parent3[32], parent4[32];

> -	struct clk_init_data vco_init = {

> -		.parent_names = (const char *[]){ "xo" },

> -		.num_parents = 1,

> -		.name = vco_name,

> -		.flags = CLK_IGNORE_UNUSED,

> -		.ops = &clk_ops_dsi_pll_10nm_vco,

> -	};

> -	struct device *dev = &pll_10nm->pdev->dev;

> -	struct clk_hw_onecell_data *hw_data;

> -	struct clk_hw *hw;

> -	int ret;

> -

> -	DBG("DSI%d", pll_10nm->id);

> -

> -	hw_data = devm_kzalloc(dev, sizeof(*hw_data) +

> -			       NUM_PROVIDED_CLKS * sizeof(struct clk_hw *),

> -			       GFP_KERNEL);

> -	if (!hw_data)

> -		return -ENOMEM;

> -

> -	snprintf(vco_name, 32, "dsi%dvco_clk", pll_10nm->id);

> -	pll_10nm->base.clk_hw.init = &vco_init;

> -

> -	ret = clk_hw_register(dev, &pll_10nm->base.clk_hw);

> -	if (ret)

> -		return ret;

> -

> -	snprintf(clk_name, 32, "dsi%d_pll_out_div_clk", pll_10nm->id);

> -	snprintf(parent, 32, "dsi%dvco_clk", pll_10nm->id);

> -

> -	hw = clk_hw_register_divider(dev, clk_name,

> -				     parent, CLK_SET_RATE_PARENT,

> -				     pll_10nm->mmio +

> -				     REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE,

> -				     0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL);

> -	if (IS_ERR(hw)) {

> -		ret = PTR_ERR(hw);

> -		goto err_base_clk_hw;

> -	}

> -

> -	pll_10nm->out_div_clk_hw = hw;

> -

> -	snprintf(clk_name, 32, "dsi%d_pll_bit_clk", pll_10nm->id);

> -	snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_10nm->id);

> -

> -	/* BIT CLK: DIV_CTRL_3_0 */

> -	hw = clk_hw_register_divider(dev, clk_name, parent,

> -				     CLK_SET_RATE_PARENT,

> -				     pll_10nm->phy_cmn_mmio +

> -				     REG_DSI_10nm_PHY_CMN_CLK_CFG0,

> -				     0, 4, CLK_DIVIDER_ONE_BASED,

> -				     &pll_10nm->postdiv_lock);

> -	if (IS_ERR(hw)) {

> -		ret = PTR_ERR(hw);

> -		goto err_out_div_clk_hw;

> -	}

> -

> -	pll_10nm->bit_clk_hw = hw;

> -

> -	snprintf(clk_name, 32, "dsi%d_phy_pll_out_byteclk", pll_10nm->id);

> -	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_10nm->id);

> -

> -	/* DSI Byte clock = VCO_CLK / OUT_DIV / BIT_DIV / 8 */

> -	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,

> -					  CLK_SET_RATE_PARENT, 1, 8);

> -	if (IS_ERR(hw)) {

> -		ret = PTR_ERR(hw);

> -		goto err_bit_clk_hw;

> -	}

> -

> -	pll_10nm->byte_clk_hw = hw;

> -	hw_data->hws[DSI_BYTE_PLL_CLK] = hw;

> -

> -	snprintf(clk_name, 32, "dsi%d_pll_by_2_bit_clk", pll_10nm->id);

> -	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_10nm->id);

> -

> -	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,

> -					  0, 1, 2);

> -	if (IS_ERR(hw)) {

> -		ret = PTR_ERR(hw);

> -		goto err_byte_clk_hw;

> -	}

> -

> -	pll_10nm->by_2_bit_clk_hw = hw;

> -

> -	snprintf(clk_name, 32, "dsi%d_pll_post_out_div_clk", pll_10nm->id);

> -	snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_10nm->id);

> -

> -	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,

> -					  0, 1, 4);

> -	if (IS_ERR(hw)) {

> -		ret = PTR_ERR(hw);

> -		goto err_by_2_bit_clk_hw;

> -	}

> -

> -	pll_10nm->post_out_div_clk_hw = hw;

> -

> -	snprintf(clk_name, 32, "dsi%d_pclk_mux", pll_10nm->id);

> -	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_10nm->id);

> -	snprintf(parent2, 32, "dsi%d_pll_by_2_bit_clk", pll_10nm->id);

> -	snprintf(parent3, 32, "dsi%d_pll_out_div_clk", pll_10nm->id);

> -	snprintf(parent4, 32, "dsi%d_pll_post_out_div_clk", pll_10nm->id);

> -

> -	hw = clk_hw_register_mux(dev, clk_name,

> -				 ((const char *[]){

> -				 parent, parent2, parent3, parent4

> -				 }), 4, 0, pll_10nm->phy_cmn_mmio +

> -				 REG_DSI_10nm_PHY_CMN_CLK_CFG1,

> -				 0, 2, 0, NULL);

> -	if (IS_ERR(hw)) {

> -		ret = PTR_ERR(hw);

> -		goto err_post_out_div_clk_hw;

> -	}

> -

> -	pll_10nm->pclk_mux_hw = hw;

> -

> -	snprintf(clk_name, 32, "dsi%d_phy_pll_out_dsiclk", pll_10nm->id);

> -	snprintf(parent, 32, "dsi%d_pclk_mux", pll_10nm->id);

> -

> -	/* PIX CLK DIV : DIV_CTRL_7_4*/

> -	hw = clk_hw_register_divider(dev, clk_name, parent,

> -				     0, pll_10nm->phy_cmn_mmio +

> -					REG_DSI_10nm_PHY_CMN_CLK_CFG0,

> -				     4, 4, CLK_DIVIDER_ONE_BASED,

> -				     &pll_10nm->postdiv_lock);

> -	if (IS_ERR(hw)) {

> -		ret = PTR_ERR(hw);

> -		goto err_pclk_mux_hw;

> -	}

> -

> -	pll_10nm->out_dsiclk_hw = hw;

> -	hw_data->hws[DSI_PIXEL_PLL_CLK] = hw;

> -

> -	hw_data->num = NUM_PROVIDED_CLKS;

> -	pll_10nm->hw_data = hw_data;

> -

> -	ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,

> -				     pll_10nm->hw_data);

> -	if (ret) {

> -		DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret);

> -		goto err_dsiclk_hw;

> -	}

> -

> -	return 0;

> -

> -err_dsiclk_hw:

> -	clk_hw_unregister_divider(pll_10nm->out_dsiclk_hw);

> -err_pclk_mux_hw:

> -	clk_hw_unregister_mux(pll_10nm->pclk_mux_hw);

> -err_post_out_div_clk_hw:

> -	clk_hw_unregister_fixed_factor(pll_10nm->post_out_div_clk_hw);

> -err_by_2_bit_clk_hw:

> -	clk_hw_unregister_fixed_factor(pll_10nm->by_2_bit_clk_hw);

> -err_byte_clk_hw:

> -	clk_hw_unregister_fixed_factor(pll_10nm->byte_clk_hw);

> -err_bit_clk_hw:

> -	clk_hw_unregister_divider(pll_10nm->bit_clk_hw);

> -err_out_div_clk_hw:

> -	clk_hw_unregister_divider(pll_10nm->out_div_clk_hw);

> -err_base_clk_hw:

> -	clk_hw_unregister(&pll_10nm->base.clk_hw);

> -

> -	return ret;

> -}

> -

> -struct msm_dsi_pll *msm_dsi_pll_10nm_init(struct platform_device 

> *pdev, int id)

> -{

> -	struct dsi_pll_10nm *pll_10nm;

> -	struct msm_dsi_pll *pll;

> -	int ret;

> -

> -	pll_10nm = devm_kzalloc(&pdev->dev, sizeof(*pll_10nm), GFP_KERNEL);

> -	if (!pll_10nm)

> -		return ERR_PTR(-ENOMEM);

> -

> -	DBG("DSI PLL%d", id);

> -

> -	pll_10nm->pdev = pdev;

> -	pll_10nm->id = id;

> -	pll_10nm_list[id] = pll_10nm;

> -

> -	pll_10nm->phy_cmn_mmio = msm_ioremap(pdev, "dsi_phy", "DSI_PHY");

> -	if (IS_ERR_OR_NULL(pll_10nm->phy_cmn_mmio)) {

> -		DRM_DEV_ERROR(&pdev->dev, "failed to map CMN PHY base\n");

> -		return ERR_PTR(-ENOMEM);

> -	}

> -

> -	pll_10nm->mmio = msm_ioremap(pdev, "dsi_pll", "DSI_PLL");

> -	if (IS_ERR_OR_NULL(pll_10nm->mmio)) {

> -		DRM_DEV_ERROR(&pdev->dev, "failed to map PLL base\n");

> -		return ERR_PTR(-ENOMEM);

> -	}

> -

> -	spin_lock_init(&pll_10nm->postdiv_lock);

> -

> -	pll = &pll_10nm->base;

> -	pll->min_rate = 1000000000UL;

> -	pll->max_rate = 3500000000UL;

> -	pll->get_provider = dsi_pll_10nm_get_provider;

> -	pll->destroy = dsi_pll_10nm_destroy;

> -	pll->save_state = dsi_pll_10nm_save_state;

> -	pll->restore_state = dsi_pll_10nm_restore_state;

> -	pll->set_usecase = dsi_pll_10nm_set_usecase;

> -

> -	pll_10nm->vco_delay = 1;

> -

> -	ret = pll_10nm_register(pll_10nm);

> -	if (ret) {

> -		DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret);

> -		return ERR_PTR(ret);

> -	}

> -

> -	/* TODO: Remove this when we have proper display handover support */

> -	msm_dsi_pll_save_state(pll);

> -

> -	return pll;

> -}

> diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c

> b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c

> deleted file mode 100644

> index f847376d501e..000000000000

> --- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c

> +++ /dev/null

> @@ -1,1096 +0,0 @@

> -// SPDX-License-Identifier: GPL-2.0-only

> -/*

> - * Copyright (c) 2016, The Linux Foundation. All rights reserved.

> - */

> -

> -#include <linux/clk.h>

> -#include <linux/clk-provider.h>

> -

> -#include "dsi_pll.h"

> -#include "dsi.xml.h"

> -

> -/*

> - * DSI PLL 14nm - clock diagram (eg: DSI0):

> - *

> - *         dsi0n1_postdiv_clk

> - *                         |

> - *                         |

> - *                 +----+  |  +----+

> - *  dsi0vco_clk ---| n1 |--o--| /8 |-- dsi0pllbyte

> - *                 +----+  |  +----+

> - *                         |           dsi0n1_postdivby2_clk

> - *                         |   +----+  |

> - *                         o---| /2 |--o--|\

> - *                         |   +----+     | \   +----+

> - *                         |              |  |--| n2 |-- dsi0pll

> - *                         o--------------| /   +----+

> - *                                        |/

> - */

> -

> -#define POLL_MAX_READS			15

> -#define POLL_TIMEOUT_US			1000

> -

> -#define NUM_PROVIDED_CLKS		2

> -

> -#define VCO_REF_CLK_RATE		19200000

> -#define VCO_MIN_RATE			1300000000UL

> -#define VCO_MAX_RATE			2600000000UL

> -

> -#define DSI_BYTE_PLL_CLK		0

> -#define DSI_PIXEL_PLL_CLK		1

> -

> -#define DSI_PLL_DEFAULT_VCO_POSTDIV	1

> -

> -struct dsi_pll_input {

> -	u32 fref;	/* reference clk */

> -	u32 fdata;	/* bit clock rate */

> -	u32 dsiclk_sel; /* Mux configuration (see diagram) */

> -	u32 ssc_en;	/* SSC enable/disable */

> -	u32 ldo_en;

> -

> -	/* fixed params */

> -	u32 refclk_dbler_en;

> -	u32 vco_measure_time;

> -	u32 kvco_measure_time;

> -	u32 bandgap_timer;

> -	u32 pll_wakeup_timer;

> -	u32 plllock_cnt;

> -	u32 plllock_rng;

> -	u32 ssc_center;

> -	u32 ssc_adj_period;

> -	u32 ssc_spread;

> -	u32 ssc_freq;

> -	u32 pll_ie_trim;

> -	u32 pll_ip_trim;

> -	u32 pll_iptat_trim;

> -	u32 pll_cpcset_cur;

> -	u32 pll_cpmset_cur;

> -

> -	u32 pll_icpmset;

> -	u32 pll_icpcset;

> -

> -	u32 pll_icpmset_p;

> -	u32 pll_icpmset_m;

> -

> -	u32 pll_icpcset_p;

> -	u32 pll_icpcset_m;

> -

> -	u32 pll_lpf_res1;

> -	u32 pll_lpf_cap1;

> -	u32 pll_lpf_cap2;

> -	u32 pll_c3ctrl;

> -	u32 pll_r3ctrl;

> -};

> -

> -struct dsi_pll_output {

> -	u32 pll_txclk_en;

> -	u32 dec_start;

> -	u32 div_frac_start;

> -	u32 ssc_period;

> -	u32 ssc_step_size;

> -	u32 plllock_cmp;

> -	u32 pll_vco_div_ref;

> -	u32 pll_vco_count;

> -	u32 pll_kvco_div_ref;

> -	u32 pll_kvco_count;

> -	u32 pll_misc1;

> -	u32 pll_lpf2_postdiv;

> -	u32 pll_resetsm_cntrl;

> -	u32 pll_resetsm_cntrl2;

> -	u32 pll_resetsm_cntrl5;

> -	u32 pll_kvco_code;

> -

> -	u32 cmn_clk_cfg0;

> -	u32 cmn_clk_cfg1;

> -	u32 cmn_ldo_cntrl;

> -

> -	u32 pll_postdiv;

> -	u32 fcvo;

> -};

> -

> -struct pll_14nm_cached_state {

> -	unsigned long vco_rate;

> -	u8 n2postdiv;

> -	u8 n1postdiv;

> -};

> -

> -struct dsi_pll_14nm {

> -	struct msm_dsi_pll base;

> -

> -	int id;

> -	struct platform_device *pdev;

> -

> -	void __iomem *phy_cmn_mmio;

> -	void __iomem *mmio;

> -

> -	int vco_delay;

> -

> -	struct dsi_pll_input in;

> -	struct dsi_pll_output out;

> -

> -	/* protects REG_DSI_14nm_PHY_CMN_CLK_CFG0 register */

> -	spinlock_t postdiv_lock;

> -

> -	u64 vco_current_rate;

> -	u64 vco_ref_clk_rate;

> -

> -	/* private clocks: */

> -	struct clk_hw *hws[NUM_DSI_CLOCKS_MAX];

> -	u32 num_hws;

> -

> -	/* clock-provider: */

> -	struct clk_hw_onecell_data *hw_data;

> -

> -	struct pll_14nm_cached_state cached_state;

> -

> -	enum msm_dsi_phy_usecase uc;

> -	struct dsi_pll_14nm *slave;

> -};

> -

> -#define to_pll_14nm(x)	container_of(x, struct dsi_pll_14nm, base)

> -

> -/*

> - * Private struct for N1/N2 post-divider clocks. These clocks are 

> similar to

> - * the generic clk_divider class of clocks. The only difference is 

> that it

> - * also sets the slave DSI PLL's post-dividers if in Dual DSI mode

> - */

> -struct dsi_pll_14nm_postdiv {

> -	struct clk_hw hw;

> -

> -	/* divider params */

> -	u8 shift;

> -	u8 width;

> -	u8 flags; /* same flags as used by clk_divider struct */

> -

> -	struct dsi_pll_14nm *pll;

> -};

> -

> -#define to_pll_14nm_postdiv(_hw) container_of(_hw, struct

> dsi_pll_14nm_postdiv, hw)

> -

> -/*

> - * Global list of private DSI PLL struct pointers. We need this for 

> Dual DSI

> - * mode, where the master PLL's clk_ops needs access the slave's 

> private data

> - */

> -static struct dsi_pll_14nm *pll_14nm_list[DSI_MAX];

> -

> -static bool pll_14nm_poll_for_ready(struct dsi_pll_14nm *pll_14nm,

> -				    u32 nb_tries, u32 timeout_us)

> -{

> -	bool pll_locked = false;

> -	void __iomem *base = pll_14nm->mmio;

> -	u32 tries, val;

> -

> -	tries = nb_tries;

> -	while (tries--) {

> -		val = pll_read(base +

> -			       REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS);

> -		pll_locked = !!(val & BIT(5));

> -

> -		if (pll_locked)

> -			break;

> -

> -		udelay(timeout_us);

> -	}

> -

> -	if (!pll_locked) {

> -		tries = nb_tries;

> -		while (tries--) {

> -			val = pll_read(base +

> -				REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS);

> -			pll_locked = !!(val & BIT(0));

> -

> -			if (pll_locked)

> -				break;

> -

> -			udelay(timeout_us);

> -		}

> -	}

> -

> -	DBG("DSI PLL is %slocked", pll_locked ? "" : "*not* ");

> -

> -	return pll_locked;

> -}

> -

> -static void dsi_pll_14nm_input_init(struct dsi_pll_14nm *pll)

> -{

> -	pll->in.fref = pll->vco_ref_clk_rate;

> -	pll->in.fdata = 0;

> -	pll->in.dsiclk_sel = 1;	/* Use the /2 path in Mux */

> -	pll->in.ldo_en = 0;	/* disabled for now */

> -

> -	/* fixed input */

> -	pll->in.refclk_dbler_en = 0;

> -	pll->in.vco_measure_time = 5;

> -	pll->in.kvco_measure_time = 5;

> -	pll->in.bandgap_timer = 4;

> -	pll->in.pll_wakeup_timer = 5;

> -	pll->in.plllock_cnt = 1;

> -	pll->in.plllock_rng = 0;

> -

> -	/*

> -	 * SSC is enabled by default. We might need DT props for configuring

> -	 * some SSC params like PPM and center/down spread etc.

> -	 */

> -	pll->in.ssc_en = 1;

> -	pll->in.ssc_center = 0;		/* down spread by default */

> -	pll->in.ssc_spread = 5;		/* PPM / 1000 */

> -	pll->in.ssc_freq = 31500;	/* default recommended */

> -	pll->in.ssc_adj_period = 37;

> -

> -	pll->in.pll_ie_trim = 4;

> -	pll->in.pll_ip_trim = 4;

> -	pll->in.pll_cpcset_cur = 1;

> -	pll->in.pll_cpmset_cur = 1;

> -	pll->in.pll_icpmset = 4;

> -	pll->in.pll_icpcset = 4;

> -	pll->in.pll_icpmset_p = 0;

> -	pll->in.pll_icpmset_m = 0;

> -	pll->in.pll_icpcset_p = 0;

> -	pll->in.pll_icpcset_m = 0;

> -	pll->in.pll_lpf_res1 = 3;

> -	pll->in.pll_lpf_cap1 = 11;

> -	pll->in.pll_lpf_cap2 = 1;

> -	pll->in.pll_iptat_trim = 7;

> -	pll->in.pll_c3ctrl = 2;

> -	pll->in.pll_r3ctrl = 1;

> -}

> -

> -#define CEIL(x, y)		(((x) + ((y) - 1)) / (y))

> -

> -static void pll_14nm_ssc_calc(struct dsi_pll_14nm *pll)

> -{

> -	u32 period, ssc_period;

> -	u32 ref, rem;

> -	u64 step_size;

> -

> -	DBG("vco=%lld ref=%lld", pll->vco_current_rate, 

> pll->vco_ref_clk_rate);

> -

> -	ssc_period = pll->in.ssc_freq / 500;

> -	period = (u32)pll->vco_ref_clk_rate / 1000;

> -	ssc_period  = CEIL(period, ssc_period);

> -	ssc_period -= 1;

> -	pll->out.ssc_period = ssc_period;

> -

> -	DBG("ssc freq=%d spread=%d period=%d", pll->in.ssc_freq,

> -	    pll->in.ssc_spread, pll->out.ssc_period);

> -

> -	step_size = (u32)pll->vco_current_rate;

> -	ref = pll->vco_ref_clk_rate;

> -	ref /= 1000;

> -	step_size = div_u64(step_size, ref);

> -	step_size <<= 20;

> -	step_size = div_u64(step_size, 1000);

> -	step_size *= pll->in.ssc_spread;

> -	step_size = div_u64(step_size, 1000);

> -	step_size *= (pll->in.ssc_adj_period + 1);

> -

> -	rem = 0;

> -	step_size = div_u64_rem(step_size, ssc_period + 1, &rem);

> -	if (rem)

> -		step_size++;

> -

> -	DBG("step_size=%lld", step_size);

> -

> -	step_size &= 0x0ffff;	/* take lower 16 bits */

> -

> -	pll->out.ssc_step_size = step_size;

> -}

> -

> -static void pll_14nm_dec_frac_calc(struct dsi_pll_14nm *pll)

> -{

> -	struct dsi_pll_input *pin = &pll->in;

> -	struct dsi_pll_output *pout = &pll->out;

> -	u64 multiplier = BIT(20);

> -	u64 dec_start_multiple, dec_start, pll_comp_val;

> -	u32 duration, div_frac_start;

> -	u64 vco_clk_rate = pll->vco_current_rate;

> -	u64 fref = pll->vco_ref_clk_rate;

> -

> -	DBG("vco_clk_rate=%lld ref_clk_rate=%lld", vco_clk_rate, fref);

> -

> -	dec_start_multiple = div_u64(vco_clk_rate * multiplier, fref);

> -	div_u64_rem(dec_start_multiple, multiplier, &div_frac_start);

> -

> -	dec_start = div_u64(dec_start_multiple, multiplier);

> -

> -	pout->dec_start = (u32)dec_start;

> -	pout->div_frac_start = div_frac_start;

> -

> -	if (pin->plllock_cnt == 0)

> -		duration = 1024;

> -	else if (pin->plllock_cnt == 1)

> -		duration = 256;

> -	else if (pin->plllock_cnt == 2)

> -		duration = 128;

> -	else

> -		duration = 32;

> -

> -	pll_comp_val = duration * dec_start_multiple;

> -	pll_comp_val = div_u64(pll_comp_val, multiplier);

> -	do_div(pll_comp_val, 10);

> -

> -	pout->plllock_cmp = (u32)pll_comp_val;

> -

> -	pout->pll_txclk_en = 1;

> -	pout->cmn_ldo_cntrl = 0x3c;

> -}

> -

> -static u32 pll_14nm_kvco_slop(u32 vrate)

> -{

> -	u32 slop = 0;

> -

> -	if (vrate > VCO_MIN_RATE && vrate <= 1800000000UL)

> -		slop =  600;

> -	else if (vrate > 1800000000UL && vrate < 2300000000UL)

> -		slop = 400;

> -	else if (vrate > 2300000000UL && vrate < VCO_MAX_RATE)

> -		slop = 280;

> -

> -	return slop;

> -}

> -

> -static void pll_14nm_calc_vco_count(struct dsi_pll_14nm *pll)

> -{

> -	struct dsi_pll_input *pin = &pll->in;

> -	struct dsi_pll_output *pout = &pll->out;

> -	u64 vco_clk_rate = pll->vco_current_rate;

> -	u64 fref = pll->vco_ref_clk_rate;

> -	u64 data;

> -	u32 cnt;

> -

> -	data = fref * pin->vco_measure_time;

> -	do_div(data, 1000000);

> -	data &= 0x03ff;	/* 10 bits */

> -	data -= 2;

> -	pout->pll_vco_div_ref = data;

> -

> -	data = div_u64(vco_clk_rate, 1000000);	/* unit is Mhz */

> -	data *= pin->vco_measure_time;

> -	do_div(data, 10);

> -	pout->pll_vco_count = data;

> -

> -	data = fref * pin->kvco_measure_time;

> -	do_div(data, 1000000);

> -	data &= 0x03ff;	/* 10 bits */

> -	data -= 1;

> -	pout->pll_kvco_div_ref = data;

> -

> -	cnt = pll_14nm_kvco_slop(vco_clk_rate);

> -	cnt *= 2;

> -	cnt /= 100;

> -	cnt *= pin->kvco_measure_time;

> -	pout->pll_kvco_count = cnt;

> -

> -	pout->pll_misc1 = 16;

> -	pout->pll_resetsm_cntrl = 48;

> -	pout->pll_resetsm_cntrl2 = pin->bandgap_timer << 3;

> -	pout->pll_resetsm_cntrl5 = pin->pll_wakeup_timer;

> -	pout->pll_kvco_code = 0;

> -}

> -

> -static void pll_db_commit_ssc(struct dsi_pll_14nm *pll)

> -{

> -	void __iomem *base = pll->mmio;

> -	struct dsi_pll_input *pin = &pll->in;

> -	struct dsi_pll_output *pout = &pll->out;

> -	u8 data;

> -

> -	data = pin->ssc_adj_period;

> -	data &= 0x0ff;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_ADJ_PER1, data);

> -	data = (pin->ssc_adj_period >> 8);

> -	data &= 0x03;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_ADJ_PER2, data);

> -

> -	data = pout->ssc_period;

> -	data &= 0x0ff;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_PER1, data);

> -	data = (pout->ssc_period >> 8);

> -	data &= 0x0ff;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_PER2, data);

> -

> -	data = pout->ssc_step_size;

> -	data &= 0x0ff;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_STEP_SIZE1, data);

> -	data = (pout->ssc_step_size >> 8);

> -	data &= 0x0ff;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_STEP_SIZE2, data);

> -

> -	data = (pin->ssc_center & 0x01);

> -	data <<= 1;

> -	data |= 0x01; /* enable */

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_EN_CENTER, data);

> -

> -	wmb();	/* make sure register committed */

> -}

> -

> -static void pll_db_commit_common(struct dsi_pll_14nm *pll,

> -				 struct dsi_pll_input *pin,

> -				 struct dsi_pll_output *pout)

> -{

> -	void __iomem *base = pll->mmio;

> -	u8 data;

> -

> -	/* confgiure the non frequency dependent pll registers */

> -	data = 0;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_SYSCLK_EN_RESET, data);

> -

> -	data = pout->pll_txclk_en;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_TXCLK_EN, data);

> -

> -	data = pout->pll_resetsm_cntrl;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL, data);

> -	data = pout->pll_resetsm_cntrl2;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL2, data);

> -	data = pout->pll_resetsm_cntrl5;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL5, data);

> -

> -	data = pout->pll_vco_div_ref & 0xff;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_VCO_DIV_REF1, data);

> -	data = (pout->pll_vco_div_ref >> 8) & 0x3;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_VCO_DIV_REF2, data);

> -

> -	data = pout->pll_kvco_div_ref & 0xff;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_KVCO_DIV_REF1, data);

> -	data = (pout->pll_kvco_div_ref >> 8) & 0x3;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_KVCO_DIV_REF2, data);

> -

> -	data = pout->pll_misc1;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_MISC1, data);

> -

> -	data = pin->pll_ie_trim;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_IE_TRIM, data);

> -

> -	data = pin->pll_ip_trim;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_IP_TRIM, data);

> -

> -	data = pin->pll_cpmset_cur << 3 | pin->pll_cpcset_cur;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_CP_SET_CUR, data);

> -

> -	data = pin->pll_icpcset_p << 3 | pin->pll_icpcset_m;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_ICPCSET, data);

> -

> -	data = pin->pll_icpmset_p << 3 | pin->pll_icpcset_m;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_ICPMSET, data);

> -

> -	data = pin->pll_icpmset << 3 | pin->pll_icpcset;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_ICP_SET, data);

> -

> -	data = pin->pll_lpf_cap2 << 4 | pin->pll_lpf_cap1;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_LPF1, data);

> -

> -	data = pin->pll_iptat_trim;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_IPTAT_TRIM, data);

> -

> -	data = pin->pll_c3ctrl | pin->pll_r3ctrl << 4;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_CRCTRL, data);

> -}

> -

> -static void pll_14nm_software_reset(struct dsi_pll_14nm *pll_14nm)

> -{

> -	void __iomem *cmn_base = pll_14nm->phy_cmn_mmio;

> -

> -	/* de assert pll start and apply pll sw reset */

> -

> -	/* stop pll */

> -	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL, 0);

> -

> -	/* pll sw reset */

> -	pll_write_udelay(cmn_base + REG_DSI_14nm_PHY_CMN_CTRL_1, 0x20, 10);

> -	wmb();	/* make sure register committed */

> -

> -	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_CTRL_1, 0);

> -	wmb();	/* make sure register committed */

> -}

> -

> -static void pll_db_commit_14nm(struct dsi_pll_14nm *pll,

> -			       struct dsi_pll_input *pin,

> -			       struct dsi_pll_output *pout)

> -{

> -	void __iomem *base = pll->mmio;

> -	void __iomem *cmn_base = pll->phy_cmn_mmio;

> -	u8 data;

> -

> -	DBG("DSI%d PLL", pll->id);

> -

> -	data = pout->cmn_ldo_cntrl;

> -	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_LDO_CNTRL, data);

> -

> -	pll_db_commit_common(pll, pin, pout);

> -

> -	pll_14nm_software_reset(pll);

> -

> -	data = pin->dsiclk_sel; /* set dsiclk_sel = 1  */

> -	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_CLK_CFG1, data);

> -

> -	data = 0xff; /* data, clk, pll normal operation */

> -	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_CTRL_0, data);

> -

> -	/* configure the frequency dependent pll registers */

> -	data = pout->dec_start;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_DEC_START, data);

> -

> -	data = pout->div_frac_start & 0xff;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START1, data);

> -	data = (pout->div_frac_start >> 8) & 0xff;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START2, data);

> -	data = (pout->div_frac_start >> 16) & 0xf;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START3, data);

> -

> -	data = pout->plllock_cmp & 0xff;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP1, data);

> -

> -	data = (pout->plllock_cmp >> 8) & 0xff;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP2, data);

> -

> -	data = (pout->plllock_cmp >> 16) & 0x3;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP3, data);

> -

> -	data = pin->plllock_cnt << 1 | pin->plllock_rng << 3;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP_EN, data);

> -

> -	data = pout->pll_vco_count & 0xff;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_VCO_COUNT1, data);

> -	data = (pout->pll_vco_count >> 8) & 0xff;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_VCO_COUNT2, data);

> -

> -	data = pout->pll_kvco_count & 0xff;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_KVCO_COUNT1, data);

> -	data = (pout->pll_kvco_count >> 8) & 0x3;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_KVCO_COUNT2, data);

> -

> -	data = (pout->pll_postdiv - 1) << 4 | pin->pll_lpf_res1;

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_LPF2_POSTDIV, data);

> -

> -	if (pin->ssc_en)

> -		pll_db_commit_ssc(pll);

> -

> -	wmb();	/* make sure register committed */

> -}

> -

> -/*

> - * VCO clock Callbacks

> - */

> -static int dsi_pll_14nm_vco_set_rate(struct clk_hw *hw, unsigned long 

> rate,

> -				     unsigned long parent_rate)

> -{

> -	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> -	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);

> -	struct dsi_pll_input *pin = &pll_14nm->in;

> -	struct dsi_pll_output *pout = &pll_14nm->out;

> -

> -	DBG("DSI PLL%d rate=%lu, parent's=%lu", pll_14nm->id, rate,

> -	    parent_rate);

> -

> -	pll_14nm->vco_current_rate = rate;

> -	pll_14nm->vco_ref_clk_rate = VCO_REF_CLK_RATE;

> -

> -	dsi_pll_14nm_input_init(pll_14nm);

> -

> -	/*

> -	 * This configures the post divider internal to the VCO. It's

> -	 * fixed to divide by 1 for now.

> -	 *

> -	 * tx_band = pll_postdiv.

> -	 * 0: divided by 1

> -	 * 1: divided by 2

> -	 * 2: divided by 4

> -	 * 3: divided by 8

> -	 */

> -	pout->pll_postdiv = DSI_PLL_DEFAULT_VCO_POSTDIV;

> -

> -	pll_14nm_dec_frac_calc(pll_14nm);

> -

> -	if (pin->ssc_en)

> -		pll_14nm_ssc_calc(pll_14nm);

> -

> -	pll_14nm_calc_vco_count(pll_14nm);

> -

> -	/* commit the slave DSI PLL registers if we're master. Note that we

> -	 * don't lock the slave PLL. We just ensure that the PLL/PHY 

> registers

> -	 * of the master and slave are identical

> -	 */

> -	if (pll_14nm->uc == MSM_DSI_PHY_MASTER) {

> -		struct dsi_pll_14nm *pll_14nm_slave = pll_14nm->slave;

> -

> -		pll_db_commit_14nm(pll_14nm_slave, pin, pout);

> -	}

> -

> -	pll_db_commit_14nm(pll_14nm, pin, pout);

> -

> -	return 0;

> -}

> -

> -static unsigned long dsi_pll_14nm_vco_recalc_rate(struct clk_hw *hw,

> -						  unsigned long parent_rate)

> -{

> -	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> -	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);

> -	void __iomem *base = pll_14nm->mmio;

> -	u64 vco_rate, multiplier = BIT(20);

> -	u32 div_frac_start;

> -	u32 dec_start;

> -	u64 ref_clk = parent_rate;

> -

> -	dec_start = pll_read(base + REG_DSI_14nm_PHY_PLL_DEC_START);

> -	dec_start &= 0x0ff;

> -

> -	DBG("dec_start = %x", dec_start);

> -

> -	div_frac_start = (pll_read(base + 

> REG_DSI_14nm_PHY_PLL_DIV_FRAC_START3)

> -				& 0xf) << 16;

> -	div_frac_start |= (pll_read(base + 

> REG_DSI_14nm_PHY_PLL_DIV_FRAC_START2)

> -				& 0xff) << 8;

> -	div_frac_start |= pll_read(base + 

> REG_DSI_14nm_PHY_PLL_DIV_FRAC_START1)

> -				& 0xff;

> -

> -	DBG("div_frac_start = %x", div_frac_start);

> -

> -	vco_rate = ref_clk * dec_start;

> -

> -	vco_rate += ((ref_clk * div_frac_start) / multiplier);

> -

> -	/*

> -	 * Recalculating the rate from dec_start and frac_start doesn't end 

> up

> -	 * the rate we originally set. Convert the freq to KHz, round it up 

> and

> -	 * convert it back to MHz.

> -	 */

> -	vco_rate = DIV_ROUND_UP_ULL(vco_rate, 1000) * 1000;

> -

> -	DBG("returning vco rate = %lu", (unsigned long)vco_rate);

> -

> -	return (unsigned long)vco_rate;

> -}

> -

> -static const struct clk_ops clk_ops_dsi_pll_14nm_vco = {

> -	.round_rate = msm_dsi_pll_helper_clk_round_rate,

> -	.set_rate = dsi_pll_14nm_vco_set_rate,

> -	.recalc_rate = dsi_pll_14nm_vco_recalc_rate,

> -	.prepare = msm_dsi_pll_helper_clk_prepare,

> -	.unprepare = msm_dsi_pll_helper_clk_unprepare,

> -};

> -

> -/*

> - * N1 and N2 post-divider clock callbacks

> - */

> -#define div_mask(width)	((1 << (width)) - 1)

> -static unsigned long dsi_pll_14nm_postdiv_recalc_rate(struct clk_hw 

> *hw,

> -						      unsigned long parent_rate)

> -{

> -	struct dsi_pll_14nm_postdiv *postdiv = to_pll_14nm_postdiv(hw);

> -	struct dsi_pll_14nm *pll_14nm = postdiv->pll;

> -	void __iomem *base = pll_14nm->phy_cmn_mmio;

> -	u8 shift = postdiv->shift;

> -	u8 width = postdiv->width;

> -	u32 val;

> -

> -	DBG("DSI%d PLL parent rate=%lu", pll_14nm->id, parent_rate);

> -

> -	val = pll_read(base + REG_DSI_14nm_PHY_CMN_CLK_CFG0) >> shift;

> -	val &= div_mask(width);

> -

> -	return divider_recalc_rate(hw, parent_rate, val, NULL,

> -				   postdiv->flags, width);

> -}

> -

> -static long dsi_pll_14nm_postdiv_round_rate(struct clk_hw *hw,

> -					    unsigned long rate,

> -					    unsigned long *prate)

> -{

> -	struct dsi_pll_14nm_postdiv *postdiv = to_pll_14nm_postdiv(hw);

> -	struct dsi_pll_14nm *pll_14nm = postdiv->pll;

> -

> -	DBG("DSI%d PLL parent rate=%lu", pll_14nm->id, rate);

> -

> -	return divider_round_rate(hw, rate, prate, NULL,

> -				  postdiv->width,

> -				  postdiv->flags);

> -}

> -

> -static int dsi_pll_14nm_postdiv_set_rate(struct clk_hw *hw, unsigned 

> long rate,

> -					 unsigned long parent_rate)

> -{

> -	struct dsi_pll_14nm_postdiv *postdiv = to_pll_14nm_postdiv(hw);

> -	struct dsi_pll_14nm *pll_14nm = postdiv->pll;

> -	void __iomem *base = pll_14nm->phy_cmn_mmio;

> -	spinlock_t *lock = &pll_14nm->postdiv_lock;

> -	u8 shift = postdiv->shift;

> -	u8 width = postdiv->width;

> -	unsigned int value;

> -	unsigned long flags = 0;

> -	u32 val;

> -

> -	DBG("DSI%d PLL parent rate=%lu parent rate %lu", pll_14nm->id, rate,

> -	    parent_rate);

> -

> -	value = divider_get_val(rate, parent_rate, NULL, postdiv->width,

> -				postdiv->flags);

> -

> -	spin_lock_irqsave(lock, flags);

> -

> -	val = pll_read(base + REG_DSI_14nm_PHY_CMN_CLK_CFG0);

> -	val &= ~(div_mask(width) << shift);

> -

> -	val |= value << shift;

> -	pll_write(base + REG_DSI_14nm_PHY_CMN_CLK_CFG0, val);

> -

> -	/* If we're master in dual DSI mode, then the slave PLL's 

> post-dividers

> -	 * follow the master's post dividers

> -	 */

> -	if (pll_14nm->uc == MSM_DSI_PHY_MASTER) {

> -		struct dsi_pll_14nm *pll_14nm_slave = pll_14nm->slave;

> -		void __iomem *slave_base = pll_14nm_slave->phy_cmn_mmio;

> -

> -		pll_write(slave_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0, val);

> -	}

> -

> -	spin_unlock_irqrestore(lock, flags);

> -

> -	return 0;

> -}

> -

> -static const struct clk_ops clk_ops_dsi_pll_14nm_postdiv = {

> -	.recalc_rate = dsi_pll_14nm_postdiv_recalc_rate,

> -	.round_rate = dsi_pll_14nm_postdiv_round_rate,

> -	.set_rate = dsi_pll_14nm_postdiv_set_rate,

> -};

> -

> -/*

> - * PLL Callbacks

> - */

> -

> -static int dsi_pll_14nm_enable_seq(struct msm_dsi_pll *pll)

> -{

> -	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);

> -	void __iomem *base = pll_14nm->mmio;

> -	void __iomem *cmn_base = pll_14nm->phy_cmn_mmio;

> -	bool locked;

> -

> -	DBG("");

> -

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_VREF_CFG1, 0x10);

> -	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL, 1);

> -

> -	locked = pll_14nm_poll_for_ready(pll_14nm, POLL_MAX_READS,

> -					 POLL_TIMEOUT_US);

> -

> -	if (unlikely(!locked))

> -		DRM_DEV_ERROR(&pll_14nm->pdev->dev, "DSI PLL lock failed\n");

> -	else

> -		DBG("DSI PLL lock success");

> -

> -	return locked ? 0 : -EINVAL;

> -}

> -

> -static void dsi_pll_14nm_disable_seq(struct msm_dsi_pll *pll)

> -{

> -	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);

> -	void __iomem *cmn_base = pll_14nm->phy_cmn_mmio;

> -

> -	DBG("");

> -

> -	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL, 0);

> -}

> -

> -static void dsi_pll_14nm_save_state(struct msm_dsi_pll *pll)

> -{

> -	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);

> -	struct pll_14nm_cached_state *cached_state = &pll_14nm->cached_state;

> -	void __iomem *cmn_base = pll_14nm->phy_cmn_mmio;

> -	u32 data;

> -

> -	data = pll_read(cmn_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0);

> -

> -	cached_state->n1postdiv = data & 0xf;

> -	cached_state->n2postdiv = (data >> 4) & 0xf;

> -

> -	DBG("DSI%d PLL save state %x %x", pll_14nm->id,

> -	    cached_state->n1postdiv, cached_state->n2postdiv);

> -

> -	cached_state->vco_rate = clk_hw_get_rate(&pll->clk_hw);

> -}

> -

> -static int dsi_pll_14nm_restore_state(struct msm_dsi_pll *pll)

> -{

> -	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);

> -	struct pll_14nm_cached_state *cached_state = &pll_14nm->cached_state;

> -	void __iomem *cmn_base = pll_14nm->phy_cmn_mmio;

> -	u32 data;

> -	int ret;

> -

> -	ret = dsi_pll_14nm_vco_set_rate(&pll->clk_hw,

> -					cached_state->vco_rate, 0);

> -	if (ret) {

> -		DRM_DEV_ERROR(&pll_14nm->pdev->dev,

> -			"restore vco rate failed. ret=%d\n", ret);

> -		return ret;

> -	}

> -

> -	data = cached_state->n1postdiv | (cached_state->n2postdiv << 4);

> -

> -	DBG("DSI%d PLL restore state %x %x", pll_14nm->id,

> -	    cached_state->n1postdiv, cached_state->n2postdiv);

> -

> -	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0, data);

> -

> -	/* also restore post-dividers for slave DSI PLL */

> -	if (pll_14nm->uc == MSM_DSI_PHY_MASTER) {

> -		struct dsi_pll_14nm *pll_14nm_slave = pll_14nm->slave;

> -		void __iomem *slave_base = pll_14nm_slave->phy_cmn_mmio;

> -

> -		pll_write(slave_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0, data);

> -	}

> -

> -	return 0;

> -}

> -

> -static int dsi_pll_14nm_set_usecase(struct msm_dsi_pll *pll,

> -				    enum msm_dsi_phy_usecase uc)

> -{

> -	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);

> -	void __iomem *base = pll_14nm->mmio;

> -	u32 clkbuflr_en, bandgap = 0;

> -

> -	switch (uc) {

> -	case MSM_DSI_PHY_STANDALONE:

> -		clkbuflr_en = 0x1;

> -		break;

> -	case MSM_DSI_PHY_MASTER:

> -		clkbuflr_en = 0x3;

> -		pll_14nm->slave = pll_14nm_list[(pll_14nm->id + 1) % DSI_MAX];

> -		break;

> -	case MSM_DSI_PHY_SLAVE:

> -		clkbuflr_en = 0x0;

> -		bandgap = 0x3;

> -		break;

> -	default:

> -		return -EINVAL;

> -	}

> -

> -	pll_write(base + REG_DSI_14nm_PHY_PLL_CLKBUFLR_EN, clkbuflr_en);

> -	if (bandgap)

> -		pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_BANDGAP, bandgap);

> -

> -	pll_14nm->uc = uc;

> -

> -	return 0;

> -}

> -

> -static int dsi_pll_14nm_get_provider(struct msm_dsi_pll *pll,

> -				     struct clk **byte_clk_provider,

> -				     struct clk **pixel_clk_provider)

> -{

> -	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);

> -	struct clk_hw_onecell_data *hw_data = pll_14nm->hw_data;

> -

> -	if (byte_clk_provider)

> -		*byte_clk_provider = hw_data->hws[DSI_BYTE_PLL_CLK]->clk;

> -	if (pixel_clk_provider)

> -		*pixel_clk_provider = hw_data->hws[DSI_PIXEL_PLL_CLK]->clk;

> -

> -	return 0;

> -}

> -

> -static void dsi_pll_14nm_destroy(struct msm_dsi_pll *pll)

> -{

> -	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);

> -	struct platform_device *pdev = pll_14nm->pdev;

> -	int num_hws = pll_14nm->num_hws;

> -

> -	of_clk_del_provider(pdev->dev.of_node);

> -

> -	while (num_hws--)

> -		clk_hw_unregister(pll_14nm->hws[num_hws]);

> -}

> -

> -static struct clk_hw *pll_14nm_postdiv_register(struct dsi_pll_14nm 

> *pll_14nm,

> -						const char *name,

> -						const char *parent_name,

> -						unsigned long flags,

> -						u8 shift)

> -{

> -	struct dsi_pll_14nm_postdiv *pll_postdiv;

> -	struct device *dev = &pll_14nm->pdev->dev;

> -	struct clk_init_data postdiv_init = {

> -		.parent_names = (const char *[]) { parent_name },

> -		.num_parents = 1,

> -		.name = name,

> -		.flags = flags,

> -		.ops = &clk_ops_dsi_pll_14nm_postdiv,

> -	};

> -	int ret;

> -

> -	pll_postdiv = devm_kzalloc(dev, sizeof(*pll_postdiv), GFP_KERNEL);

> -	if (!pll_postdiv)

> -		return ERR_PTR(-ENOMEM);

> -

> -	pll_postdiv->pll = pll_14nm;

> -	pll_postdiv->shift = shift;

> -	/* both N1 and N2 postdividers are 4 bits wide */

> -	pll_postdiv->width = 4;

> -	/* range of each divider is from 1 to 15 */

> -	pll_postdiv->flags = CLK_DIVIDER_ONE_BASED;

> -	pll_postdiv->hw.init = &postdiv_init;

> -

> -	ret = clk_hw_register(dev, &pll_postdiv->hw);

> -	if (ret)

> -		return ERR_PTR(ret);

> -

> -	return &pll_postdiv->hw;

> -}

> -

> -static int pll_14nm_register(struct dsi_pll_14nm *pll_14nm)

> -{

> -	char clk_name[32], parent[32], vco_name[32];

> -	struct clk_init_data vco_init = {

> -		.parent_names = (const char *[]){ "xo" },

> -		.num_parents = 1,

> -		.name = vco_name,

> -		.flags = CLK_IGNORE_UNUSED,

> -		.ops = &clk_ops_dsi_pll_14nm_vco,

> -	};

> -	struct device *dev = &pll_14nm->pdev->dev;

> -	struct clk_hw **hws = pll_14nm->hws;

> -	struct clk_hw_onecell_data *hw_data;

> -	struct clk_hw *hw;

> -	int num = 0;

> -	int ret;

> -

> -	DBG("DSI%d", pll_14nm->id);

> -

> -	hw_data = devm_kzalloc(dev, sizeof(*hw_data) +

> -			       NUM_PROVIDED_CLKS * sizeof(struct clk_hw *),

> -			       GFP_KERNEL);

> -	if (!hw_data)

> -		return -ENOMEM;

> -

> -	snprintf(vco_name, 32, "dsi%dvco_clk", pll_14nm->id);

> -	pll_14nm->base.clk_hw.init = &vco_init;

> -

> -	ret = clk_hw_register(dev, &pll_14nm->base.clk_hw);

> -	if (ret)

> -		return ret;

> -

> -	hws[num++] = &pll_14nm->base.clk_hw;

> -

> -	snprintf(clk_name, 32, "dsi%dn1_postdiv_clk", pll_14nm->id);

> -	snprintf(parent, 32, "dsi%dvco_clk", pll_14nm->id);

> -

> -	/* N1 postdiv, bits 0-3 in REG_DSI_14nm_PHY_CMN_CLK_CFG0 */

> -	hw = pll_14nm_postdiv_register(pll_14nm, clk_name, parent,

> -				       CLK_SET_RATE_PARENT, 0);

> -	if (IS_ERR(hw))

> -		return PTR_ERR(hw);

> -

> -	hws[num++] = hw;

> -

> -	snprintf(clk_name, 32, "dsi%dpllbyte", pll_14nm->id);

> -	snprintf(parent, 32, "dsi%dn1_postdiv_clk", pll_14nm->id);

> -

> -	/* DSI Byte clock = VCO_CLK / N1 / 8 */

> -	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,

> -					  CLK_SET_RATE_PARENT, 1, 8);

> -	if (IS_ERR(hw))

> -		return PTR_ERR(hw);

> -

> -	hws[num++] = hw;

> -	hw_data->hws[DSI_BYTE_PLL_CLK] = hw;

> -

> -	snprintf(clk_name, 32, "dsi%dn1_postdivby2_clk", pll_14nm->id);

> -	snprintf(parent, 32, "dsi%dn1_postdiv_clk", pll_14nm->id);

> -

> -	/*

> -	 * Skip the mux for now, force DSICLK_SEL to 1, Add a /2 divider

> -	 * on the way. Don't let it set parent.

> -	 */

> -	hw = clk_hw_register_fixed_factor(dev, clk_name, parent, 0, 1, 2);

> -	if (IS_ERR(hw))

> -		return PTR_ERR(hw);

> -

> -	hws[num++] = hw;

> -

> -	snprintf(clk_name, 32, "dsi%dpll", pll_14nm->id);

> -	snprintf(parent, 32, "dsi%dn1_postdivby2_clk", pll_14nm->id);

> -

> -	/* DSI pixel clock = VCO_CLK / N1 / 2 / N2

> -	 * This is the output of N2 post-divider, bits 4-7 in

> -	 * REG_DSI_14nm_PHY_CMN_CLK_CFG0. Don't let it set parent.

> -	 */

> -	hw = pll_14nm_postdiv_register(pll_14nm, clk_name, parent, 0, 4);

> -	if (IS_ERR(hw))

> -		return PTR_ERR(hw);

> -

> -	hws[num++] = hw;

> -	hw_data->hws[DSI_PIXEL_PLL_CLK]	= hw;

> -

> -	pll_14nm->num_hws = num;

> -

> -	hw_data->num = NUM_PROVIDED_CLKS;

> -	pll_14nm->hw_data = hw_data;

> -

> -	ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,

> -				     pll_14nm->hw_data);

> -	if (ret) {

> -		DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret);

> -		return ret;

> -	}

> -

> -	return 0;

> -}

> -

> -struct msm_dsi_pll *msm_dsi_pll_14nm_init(struct platform_device 

> *pdev, int id)

> -{

> -	struct dsi_pll_14nm *pll_14nm;

> -	struct msm_dsi_pll *pll;

> -	int ret;

> -

> -	if (!pdev)

> -		return ERR_PTR(-ENODEV);

> -

> -	pll_14nm = devm_kzalloc(&pdev->dev, sizeof(*pll_14nm), GFP_KERNEL);

> -	if (!pll_14nm)

> -		return ERR_PTR(-ENOMEM);

> -

> -	DBG("PLL%d", id);

> -

> -	pll_14nm->pdev = pdev;

> -	pll_14nm->id = id;

> -	pll_14nm_list[id] = pll_14nm;

> -

> -	pll_14nm->phy_cmn_mmio = msm_ioremap(pdev, "dsi_phy", "DSI_PHY");

> -	if (IS_ERR_OR_NULL(pll_14nm->phy_cmn_mmio)) {

> -		DRM_DEV_ERROR(&pdev->dev, "failed to map CMN PHY base\n");

> -		return ERR_PTR(-ENOMEM);

> -	}

> -

> -	pll_14nm->mmio = msm_ioremap(pdev, "dsi_pll", "DSI_PLL");

> -	if (IS_ERR_OR_NULL(pll_14nm->mmio)) {

> -		DRM_DEV_ERROR(&pdev->dev, "failed to map PLL base\n");

> -		return ERR_PTR(-ENOMEM);

> -	}

> -

> -	spin_lock_init(&pll_14nm->postdiv_lock);

> -

> -	pll = &pll_14nm->base;

> -	pll->min_rate = VCO_MIN_RATE;

> -	pll->max_rate = VCO_MAX_RATE;

> -	pll->get_provider = dsi_pll_14nm_get_provider;

> -	pll->destroy = dsi_pll_14nm_destroy;

> -	pll->disable_seq = dsi_pll_14nm_disable_seq;

> -	pll->save_state = dsi_pll_14nm_save_state;

> -	pll->restore_state = dsi_pll_14nm_restore_state;

> -	pll->set_usecase = dsi_pll_14nm_set_usecase;

> -

> -	pll_14nm->vco_delay = 1;

> -

> -	pll->en_seq_cnt = 1;

> -	pll->enable_seqs[0] = dsi_pll_14nm_enable_seq;

> -

> -	ret = pll_14nm_register(pll_14nm);

> -	if (ret) {

> -		DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret);

> -		return ERR_PTR(ret);

> -	}

> -

> -	return pll;

> -}

> diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c

> b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c

> deleted file mode 100644

> index 37a1f996a588..000000000000

> --- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c

> +++ /dev/null

> @@ -1,643 +0,0 @@

> -// SPDX-License-Identifier: GPL-2.0-only

> -/*

> - * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.

> - */

> -

> -#include <linux/clk.h>

> -#include <linux/clk-provider.h>

> -

> -#include "dsi_pll.h"

> -#include "dsi.xml.h"

> -

> -/*

> - * DSI PLL 28nm - clock diagram (eg: DSI0):

> - *

> - *         dsi0analog_postdiv_clk

> - *                             |         dsi0indirect_path_div2_clk

> - *                             |          |

> - *                   +------+  |  +----+  |  |\   dsi0byte_mux

> - *  dsi0vco_clk --o--| DIV1 |--o--| /2 |--o--| \   |

> - *                |  +------+     +----+     | m|  |  +----+

> - *                |                          | u|--o--| /4 |-- 

> dsi0pllbyte

> - *                |                          | x|     +----+

> - *                o--------------------------| /

> - *                |                          |/

> - *                |          +------+

> - *                o----------| DIV3 |------------------------- dsi0pll

> - *                           +------+

> - */

> -

> -#define POLL_MAX_READS			10

> -#define POLL_TIMEOUT_US		50

> -

> -#define NUM_PROVIDED_CLKS		2

> -

> -#define VCO_REF_CLK_RATE		19200000

> -#define VCO_MIN_RATE			350000000

> -#define VCO_MAX_RATE			750000000

> -

> -#define DSI_BYTE_PLL_CLK		0

> -#define DSI_PIXEL_PLL_CLK		1

> -

> -#define LPFR_LUT_SIZE			10

> -struct lpfr_cfg {

> -	unsigned long vco_rate;

> -	u32 resistance;

> -};

> -

> -/* Loop filter resistance: */

> -static const struct lpfr_cfg lpfr_lut[LPFR_LUT_SIZE] = {

> -	{ 479500000,  8 },

> -	{ 480000000, 11 },

> -	{ 575500000,  8 },

> -	{ 576000000, 12 },

> -	{ 610500000,  8 },

> -	{ 659500000,  9 },

> -	{ 671500000, 10 },

> -	{ 672000000, 14 },

> -	{ 708500000, 10 },

> -	{ 750000000, 11 },

> -};

> -

> -struct pll_28nm_cached_state {

> -	unsigned long vco_rate;

> -	u8 postdiv3;

> -	u8 postdiv1;

> -	u8 byte_mux;

> -};

> -

> -struct dsi_pll_28nm {

> -	struct msm_dsi_pll base;

> -

> -	int id;

> -	struct platform_device *pdev;

> -	void __iomem *mmio;

> -

> -	int vco_delay;

> -

> -	/* private clocks: */

> -	struct clk *clks[NUM_DSI_CLOCKS_MAX];

> -	u32 num_clks;

> -

> -	/* clock-provider: */

> -	struct clk *provided_clks[NUM_PROVIDED_CLKS];

> -	struct clk_onecell_data clk_data;

> -

> -	struct pll_28nm_cached_state cached_state;

> -};

> -

> -#define to_pll_28nm(x)	container_of(x, struct dsi_pll_28nm, base)

> -

> -static bool pll_28nm_poll_for_ready(struct dsi_pll_28nm *pll_28nm,

> -				u32 nb_tries, u32 timeout_us)

> -{

> -	bool pll_locked = false;

> -	u32 val;

> -

> -	while (nb_tries--) {

> -		val = pll_read(pll_28nm->mmio + REG_DSI_28nm_PHY_PLL_STATUS);

> -		pll_locked = !!(val & DSI_28nm_PHY_PLL_STATUS_PLL_RDY);

> -

> -		if (pll_locked)

> -			break;

> -

> -		udelay(timeout_us);

> -	}

> -	DBG("DSI PLL is %slocked", pll_locked ? "" : "*not* ");

> -

> -	return pll_locked;

> -}

> -

> -static void pll_28nm_software_reset(struct dsi_pll_28nm *pll_28nm)

> -{

> -	void __iomem *base = pll_28nm->mmio;

> -

> -	/*

> -	 * Add HW recommended delays after toggling the software

> -	 * reset bit off and back on.

> -	 */

> -	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_TEST_CFG,

> -			DSI_28nm_PHY_PLL_TEST_CFG_PLL_SW_RESET, 1);

> -	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_TEST_CFG, 0x00, 1);

> -}

> -

> -/*

> - * Clock Callbacks

> - */

> -static int dsi_pll_28nm_clk_set_rate(struct clk_hw *hw, unsigned long 

> rate,

> -		unsigned long parent_rate)

> -{

> -	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> -	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> -	struct device *dev = &pll_28nm->pdev->dev;

> -	void __iomem *base = pll_28nm->mmio;

> -	unsigned long div_fbx1000, gen_vco_clk;

> -	u32 refclk_cfg, frac_n_mode, frac_n_value;

> -	u32 sdm_cfg0, sdm_cfg1, sdm_cfg2, sdm_cfg3;

> -	u32 cal_cfg10, cal_cfg11;

> -	u32 rem;

> -	int i;

> -

> -	VERB("rate=%lu, parent's=%lu", rate, parent_rate);

> -

> -	/* Force postdiv2 to be div-4 */

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV2_CFG, 3);

> -

> -	/* Configure the Loop filter resistance */

> -	for (i = 0; i < LPFR_LUT_SIZE; i++)

> -		if (rate <= lpfr_lut[i].vco_rate)

> -			break;

> -	if (i == LPFR_LUT_SIZE) {

> -		DRM_DEV_ERROR(dev, "unable to get loop filter resistance. 

> vco=%lu\n",

> -				rate);

> -		return -EINVAL;

> -	}

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_LPFR_CFG, 

> lpfr_lut[i].resistance);

> -

> -	/* Loop filter capacitance values : c1 and c2 */

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_LPFC1_CFG, 0x70);

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_LPFC2_CFG, 0x15);

> -

> -	rem = rate % VCO_REF_CLK_RATE;

> -	if (rem) {

> -		refclk_cfg = DSI_28nm_PHY_PLL_REFCLK_CFG_DBLR;

> -		frac_n_mode = 1;

> -		div_fbx1000 = rate / (VCO_REF_CLK_RATE / 500);

> -		gen_vco_clk = div_fbx1000 * (VCO_REF_CLK_RATE / 500);

> -	} else {

> -		refclk_cfg = 0x0;

> -		frac_n_mode = 0;

> -		div_fbx1000 = rate / (VCO_REF_CLK_RATE / 1000);

> -		gen_vco_clk = div_fbx1000 * (VCO_REF_CLK_RATE / 1000);

> -	}

> -

> -	DBG("refclk_cfg = %d", refclk_cfg);

> -

> -	rem = div_fbx1000 % 1000;

> -	frac_n_value = (rem << 16) / 1000;

> -

> -	DBG("div_fb = %lu", div_fbx1000);

> -	DBG("frac_n_value = %d", frac_n_value);

> -

> -	DBG("Generated VCO Clock: %lu", gen_vco_clk);

> -	rem = 0;

> -	sdm_cfg1 = pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1);

> -	sdm_cfg1 &= ~DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET__MASK;

> -	if (frac_n_mode) {

> -		sdm_cfg0 = 0x0;

> -		sdm_cfg0 |= DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV(0);

> -		sdm_cfg1 |= DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET(

> -				(u32)(((div_fbx1000 / 1000) & 0x3f) - 1));

> -		sdm_cfg3 = frac_n_value >> 8;

> -		sdm_cfg2 = frac_n_value & 0xff;

> -	} else {

> -		sdm_cfg0 = DSI_28nm_PHY_PLL_SDM_CFG0_BYP;

> -		sdm_cfg0 |= DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV(

> -				(u32)(((div_fbx1000 / 1000) & 0x3f) - 1));

> -		sdm_cfg1 |= DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET(0);

> -		sdm_cfg2 = 0;

> -		sdm_cfg3 = 0;

> -	}

> -

> -	DBG("sdm_cfg0=%d", sdm_cfg0);

> -	DBG("sdm_cfg1=%d", sdm_cfg1);

> -	DBG("sdm_cfg2=%d", sdm_cfg2);

> -	DBG("sdm_cfg3=%d", sdm_cfg3);

> -

> -	cal_cfg11 = (u32)(gen_vco_clk / (256 * 1000000));

> -	cal_cfg10 = (u32)((gen_vco_clk % (256 * 1000000)) / 1000000);

> -	DBG("cal_cfg10=%d, cal_cfg11=%d", cal_cfg10, cal_cfg11);

> -

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_CHGPUMP_CFG, 0x02);

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG3,    0x2b);

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG4,    0x06);

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2,  0x0d);

> -

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1, sdm_cfg1);

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG2,

> -		DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0(sdm_cfg2));

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG3,

> -		DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8(sdm_cfg3));

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG4, 0x00);

> -

> -	/* Add hardware recommended delay for correct PLL configuration */

> -	if (pll_28nm->vco_delay)

> -		udelay(pll_28nm->vco_delay);

> -

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_REFCLK_CFG, refclk_cfg);

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_PWRGEN_CFG, 0x00);

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_VCOLPF_CFG, 0x31);

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0,   sdm_cfg0);

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG0,   0x12);

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG6,   0x30);

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG7,   0x00);

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG8,   0x60);

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG9,   0x00);

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG10,  cal_cfg10 & 0xff);

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG11,  cal_cfg11 & 0xff);

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_EFUSE_CFG,  0x20);

> -

> -	return 0;

> -}

> -

> -static int dsi_pll_28nm_clk_is_enabled(struct clk_hw *hw)

> -{

> -	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> -	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> -

> -	return pll_28nm_poll_for_ready(pll_28nm, POLL_MAX_READS,

> -					POLL_TIMEOUT_US);

> -}

> -

> -static unsigned long dsi_pll_28nm_clk_recalc_rate(struct clk_hw *hw,

> -		unsigned long parent_rate)

> -{

> -	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> -	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> -	void __iomem *base = pll_28nm->mmio;

> -	u32 sdm0, doubler, sdm_byp_div;

> -	u32 sdm_dc_off, sdm_freq_seed, sdm2, sdm3;

> -	u32 ref_clk = VCO_REF_CLK_RATE;

> -	unsigned long vco_rate;

> -

> -	VERB("parent_rate=%lu", parent_rate);

> -

> -	/* Check to see if the ref clk doubler is enabled */

> -	doubler = pll_read(base + REG_DSI_28nm_PHY_PLL_REFCLK_CFG) &

> -			DSI_28nm_PHY_PLL_REFCLK_CFG_DBLR;

> -	ref_clk += (doubler * VCO_REF_CLK_RATE);

> -

> -	/* see if it is integer mode or sdm mode */

> -	sdm0 = pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0);

> -	if (sdm0 & DSI_28nm_PHY_PLL_SDM_CFG0_BYP) {

> -		/* integer mode */

> -		sdm_byp_div = FIELD(

> -				pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0),

> -				DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV) + 1;

> -		vco_rate = ref_clk * sdm_byp_div;

> -	} else {

> -		/* sdm mode */

> -		sdm_dc_off = FIELD(

> -				pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1),

> -				DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET);

> -		DBG("sdm_dc_off = %d", sdm_dc_off);

> -		sdm2 = FIELD(pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG2),

> -				DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0);

> -		sdm3 = FIELD(pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG3),

> -				DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8);

> -		sdm_freq_seed = (sdm3 << 8) | sdm2;

> -		DBG("sdm_freq_seed = %d", sdm_freq_seed);

> -

> -		vco_rate = (ref_clk * (sdm_dc_off + 1)) +

> -			mult_frac(ref_clk, sdm_freq_seed, BIT(16));

> -		DBG("vco rate = %lu", vco_rate);

> -	}

> -

> -	DBG("returning vco rate = %lu", vco_rate);

> -

> -	return vco_rate;

> -}

> -

> -static const struct clk_ops clk_ops_dsi_pll_28nm_vco = {

> -	.round_rate = msm_dsi_pll_helper_clk_round_rate,

> -	.set_rate = dsi_pll_28nm_clk_set_rate,

> -	.recalc_rate = dsi_pll_28nm_clk_recalc_rate,

> -	.prepare = msm_dsi_pll_helper_clk_prepare,

> -	.unprepare = msm_dsi_pll_helper_clk_unprepare,

> -	.is_enabled = dsi_pll_28nm_clk_is_enabled,

> -};

> -

> -/*

> - * PLL Callbacks

> - */

> -static int dsi_pll_28nm_enable_seq_hpm(struct msm_dsi_pll *pll)

> -{

> -	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> -	struct device *dev = &pll_28nm->pdev->dev;

> -	void __iomem *base = pll_28nm->mmio;

> -	u32 max_reads = 5, timeout_us = 100;

> -	bool locked;

> -	u32 val;

> -	int i;

> -

> -	DBG("id=%d", pll_28nm->id);

> -

> -	pll_28nm_software_reset(pll_28nm);

> -

> -	/*

> -	 * PLL power up sequence.

> -	 * Add necessary delays recommended by hardware.

> -	 */

> -	val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;

> -	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 1);

> -

> -	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;

> -	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);

> -

> -	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;

> -	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);

> -

> -	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;

> -	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 600);

> -

> -	for (i = 0; i < 2; i++) {

> -		/* DSI Uniphy lock detect setting */

> -		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2,

> -				0x0c, 100);

> -		pll_write(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x0d);

> -

> -		/* poll for PLL ready status */

> -		locked = pll_28nm_poll_for_ready(pll_28nm,

> -						max_reads, timeout_us);

> -		if (locked)

> -			break;

> -

> -		pll_28nm_software_reset(pll_28nm);

> -

> -		/*

> -		 * PLL power up sequence.

> -		 * Add necessary delays recommended by hardware.

> -		 */

> -		val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;

> -		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 1);

> -

> -		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;

> -		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);

> -

> -		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;

> -		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 250);

> -

> -		val &= ~DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;

> -		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);

> -

> -		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;

> -		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);

> -

> -		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;

> -		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 600);

> -	}

> -

> -	if (unlikely(!locked))

> -		DRM_DEV_ERROR(dev, "DSI PLL lock failed\n");

> -	else

> -		DBG("DSI PLL Lock success");

> -

> -	return locked ? 0 : -EINVAL;

> -}

> -

> -static int dsi_pll_28nm_enable_seq_lp(struct msm_dsi_pll *pll)

> -{

> -	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> -	struct device *dev = &pll_28nm->pdev->dev;

> -	void __iomem *base = pll_28nm->mmio;

> -	bool locked;

> -	u32 max_reads = 10, timeout_us = 50;

> -	u32 val;

> -

> -	DBG("id=%d", pll_28nm->id);

> -

> -	pll_28nm_software_reset(pll_28nm);

> -

> -	/*

> -	 * PLL power up sequence.

> -	 * Add necessary delays recommended by hardware.

> -	 */

> -	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_CAL_CFG1, 0x34, 500);

> -

> -	val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;

> -	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);

> -

> -	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;

> -	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);

> -

> -	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B |

> -		DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;

> -	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);

> -

> -	/* DSI PLL toggle lock detect setting */

> -	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x04, 500);

> -	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x05, 512);

> -

> -	locked = pll_28nm_poll_for_ready(pll_28nm, max_reads, timeout_us);

> -

> -	if (unlikely(!locked))

> -		DRM_DEV_ERROR(dev, "DSI PLL lock failed\n");

> -	else

> -		DBG("DSI PLL lock success");

> -

> -	return locked ? 0 : -EINVAL;

> -}

> -

> -static void dsi_pll_28nm_disable_seq(struct msm_dsi_pll *pll)

> -{

> -	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> -

> -	DBG("id=%d", pll_28nm->id);

> -	pll_write(pll_28nm->mmio + REG_DSI_28nm_PHY_PLL_GLB_CFG, 0x00);

> -}

> -

> -static void dsi_pll_28nm_save_state(struct msm_dsi_pll *pll)

> -{

> -	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> -	struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;

> -	void __iomem *base = pll_28nm->mmio;

> -

> -	cached_state->postdiv3 =

> -			pll_read(base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG);

> -	cached_state->postdiv1 =

> -			pll_read(base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG);

> -	cached_state->byte_mux = pll_read(base + 

> REG_DSI_28nm_PHY_PLL_VREG_CFG);

> -	if (dsi_pll_28nm_clk_is_enabled(&pll->clk_hw))

> -		cached_state->vco_rate = clk_hw_get_rate(&pll->clk_hw);

> -	else

> -		cached_state->vco_rate = 0;

> -}

> -

> -static int dsi_pll_28nm_restore_state(struct msm_dsi_pll *pll)

> -{

> -	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> -	struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;

> -	void __iomem *base = pll_28nm->mmio;

> -	int ret;

> -

> -	ret = dsi_pll_28nm_clk_set_rate(&pll->clk_hw,

> -					cached_state->vco_rate, 0);

> -	if (ret) {

> -		DRM_DEV_ERROR(&pll_28nm->pdev->dev,

> -			"restore vco rate failed. ret=%d\n", ret);

> -		return ret;

> -	}

> -

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG,

> -			cached_state->postdiv3);

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG,

> -			cached_state->postdiv1);

> -	pll_write(base + REG_DSI_28nm_PHY_PLL_VREG_CFG,

> -			cached_state->byte_mux);

> -

> -	return 0;

> -}

> -

> -static int dsi_pll_28nm_get_provider(struct msm_dsi_pll *pll,

> -				struct clk **byte_clk_provider,

> -				struct clk **pixel_clk_provider)

> -{

> -	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> -

> -	if (byte_clk_provider)

> -		*byte_clk_provider = pll_28nm->provided_clks[DSI_BYTE_PLL_CLK];

> -	if (pixel_clk_provider)

> -		*pixel_clk_provider =

> -				pll_28nm->provided_clks[DSI_PIXEL_PLL_CLK];

> -

> -	return 0;

> -}

> -

> -static void dsi_pll_28nm_destroy(struct msm_dsi_pll *pll)

> -{

> -	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> -	int i;

> -

> -	msm_dsi_pll_helper_unregister_clks(pll_28nm->pdev,

> -					pll_28nm->clks, pll_28nm->num_clks);

> -

> -	for (i = 0; i < NUM_PROVIDED_CLKS; i++)

> -		pll_28nm->provided_clks[i] = NULL;

> -

> -	pll_28nm->num_clks = 0;

> -	pll_28nm->clk_data.clks = NULL;

> -	pll_28nm->clk_data.clk_num = 0;

> -}

> -

> -static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm)

> -{

> -	char clk_name[32], parent1[32], parent2[32], vco_name[32];

> -	struct clk_init_data vco_init = {

> -		.parent_names = (const char *[]){ "xo" },

> -		.num_parents = 1,

> -		.name = vco_name,

> -		.flags = CLK_IGNORE_UNUSED,

> -		.ops = &clk_ops_dsi_pll_28nm_vco,

> -	};

> -	struct device *dev = &pll_28nm->pdev->dev;

> -	struct clk **clks = pll_28nm->clks;

> -	struct clk **provided_clks = pll_28nm->provided_clks;

> -	int num = 0;

> -	int ret;

> -

> -	DBG("%d", pll_28nm->id);

> -

> -	snprintf(vco_name, 32, "dsi%dvco_clk", pll_28nm->id);

> -	pll_28nm->base.clk_hw.init = &vco_init;

> -	clks[num++] = clk_register(dev, &pll_28nm->base.clk_hw);

> -

> -	snprintf(clk_name, 32, "dsi%danalog_postdiv_clk", pll_28nm->id);

> -	snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->id);

> -	clks[num++] = clk_register_divider(dev, clk_name,

> -			parent1, CLK_SET_RATE_PARENT,

> -			pll_28nm->mmio +

> -			REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG,

> -			0, 4, 0, NULL);

> -

> -	snprintf(clk_name, 32, "dsi%dindirect_path_div2_clk", pll_28nm->id);

> -	snprintf(parent1, 32, "dsi%danalog_postdiv_clk", pll_28nm->id);

> -	clks[num++] = clk_register_fixed_factor(dev, clk_name,

> -			parent1, CLK_SET_RATE_PARENT,

> -			1, 2);

> -

> -	snprintf(clk_name, 32, "dsi%dpll", pll_28nm->id);

> -	snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->id);

> -	clks[num++] = provided_clks[DSI_PIXEL_PLL_CLK] =

> -			clk_register_divider(dev, clk_name,

> -				parent1, 0, pll_28nm->mmio +

> -				REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG,

> -				0, 8, 0, NULL);

> -

> -	snprintf(clk_name, 32, "dsi%dbyte_mux", pll_28nm->id);

> -	snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->id);

> -	snprintf(parent2, 32, "dsi%dindirect_path_div2_clk", pll_28nm->id);

> -	clks[num++] = clk_register_mux(dev, clk_name,

> -			((const char *[]){

> -				parent1, parent2

> -			}), 2, CLK_SET_RATE_PARENT, pll_28nm->mmio +

> -			REG_DSI_28nm_PHY_PLL_VREG_CFG, 1, 1, 0, NULL);

> -

> -	snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->id);

> -	snprintf(parent1, 32, "dsi%dbyte_mux", pll_28nm->id);

> -	clks[num++] = provided_clks[DSI_BYTE_PLL_CLK] =

> -			clk_register_fixed_factor(dev, clk_name,

> -				parent1, CLK_SET_RATE_PARENT, 1, 4);

> -

> -	pll_28nm->num_clks = num;

> -

> -	pll_28nm->clk_data.clk_num = NUM_PROVIDED_CLKS;

> -	pll_28nm->clk_data.clks = provided_clks;

> -

> -	ret = of_clk_add_provider(dev->of_node,

> -			of_clk_src_onecell_get, &pll_28nm->clk_data);

> -	if (ret) {

> -		DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret);

> -		return ret;

> -	}

> -

> -	return 0;

> -}

> -

> -struct msm_dsi_pll *msm_dsi_pll_28nm_init(struct platform_device 

> *pdev,

> -					enum msm_dsi_phy_type type, int id)

> -{

> -	struct dsi_pll_28nm *pll_28nm;

> -	struct msm_dsi_pll *pll;

> -	int ret;

> -

> -	if (!pdev)

> -		return ERR_PTR(-ENODEV);

> -

> -	pll_28nm = devm_kzalloc(&pdev->dev, sizeof(*pll_28nm), GFP_KERNEL);

> -	if (!pll_28nm)

> -		return ERR_PTR(-ENOMEM);

> -

> -	pll_28nm->pdev = pdev;

> -	pll_28nm->id = id;

> -

> -	pll_28nm->mmio = msm_ioremap(pdev, "dsi_pll", "DSI_PLL");

> -	if (IS_ERR_OR_NULL(pll_28nm->mmio)) {

> -		DRM_DEV_ERROR(&pdev->dev, "%s: failed to map pll base\n", __func__);

> -		return ERR_PTR(-ENOMEM);

> -	}

> -

> -	pll = &pll_28nm->base;

> -	pll->min_rate = VCO_MIN_RATE;

> -	pll->max_rate = VCO_MAX_RATE;

> -	pll->get_provider = dsi_pll_28nm_get_provider;

> -	pll->destroy = dsi_pll_28nm_destroy;

> -	pll->disable_seq = dsi_pll_28nm_disable_seq;

> -	pll->save_state = dsi_pll_28nm_save_state;

> -	pll->restore_state = dsi_pll_28nm_restore_state;

> -

> -	if (type == MSM_DSI_PHY_28NM_HPM) {

> -		pll_28nm->vco_delay = 1;

> -

> -		pll->en_seq_cnt = 3;

> -		pll->enable_seqs[0] = dsi_pll_28nm_enable_seq_hpm;

> -		pll->enable_seqs[1] = dsi_pll_28nm_enable_seq_hpm;

> -		pll->enable_seqs[2] = dsi_pll_28nm_enable_seq_hpm;

> -	} else if (type == MSM_DSI_PHY_28NM_LP) {

> -		pll_28nm->vco_delay = 1000;

> -

> -		pll->en_seq_cnt = 1;

> -		pll->enable_seqs[0] = dsi_pll_28nm_enable_seq_lp;

> -	} else {

> -		DRM_DEV_ERROR(&pdev->dev, "phy type (%d) is not 28nm\n", type);

> -		return ERR_PTR(-EINVAL);

> -	}

> -

> -	ret = pll_28nm_register(pll_28nm);

> -	if (ret) {

> -		DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret);

> -		return ERR_PTR(ret);

> -	}

> -

> -	return pll;

> -}

> -

> diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c

> b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c

> deleted file mode 100644

> index a6e7a2525fe0..000000000000

> --- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c

> +++ /dev/null

> @@ -1,526 +0,0 @@

> -// SPDX-License-Identifier: GPL-2.0-only

> -/*

> - * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.

> - */

> -

> -#include <linux/clk-provider.h>

> -

> -#include "dsi_pll.h"

> -#include "dsi.xml.h"

> -

> -/*

> - * DSI PLL 28nm (8960/A family) - clock diagram (eg: DSI1):

> - *

> - *

> - *                        +------+

> - *  dsi1vco_clk ----o-----| DIV1 |---dsi1pllbit (not exposed as clock)

> - *  F * byte_clk    |     +------+

> - *                  | bit clock divider (F / 8)

> - *                  |

> - *                  |     +------+

> - *                  o-----| DIV2 |---dsi0pllbyte---o---> To byte RCG

> - *                  |     +------+                 | (sets parent 

> rate)

> - *                  | byte clock divider (F)       |

> - *                  |                              |

> - *                  |                              o---> To esc RCG

> - *                  |                                (doesn't set 

> parent rate)

> - *                  |

> - *                  |     +------+

> - *                  o-----| DIV3 |----dsi0pll------o---> To dsi RCG

> - *                        +------+                 | (sets parent 

> rate)

> - *                  dsi clock divider (F * magic)  |

> - *                                                 |

> - *                                                 o---> To pixel rcg

> - *                                                  (doesn't set 

> parent rate)

> - */

> -

> -#define POLL_MAX_READS		8000

> -#define POLL_TIMEOUT_US		1

> -

> -#define NUM_PROVIDED_CLKS	2

> -

> -#define VCO_REF_CLK_RATE	27000000

> -#define VCO_MIN_RATE		600000000

> -#define VCO_MAX_RATE		1200000000

> -

> -#define DSI_BYTE_PLL_CLK	0

> -#define DSI_PIXEL_PLL_CLK	1

> -

> -#define VCO_PREF_DIV_RATIO	27

> -

> -struct pll_28nm_cached_state {

> -	unsigned long vco_rate;

> -	u8 postdiv3;

> -	u8 postdiv2;

> -	u8 postdiv1;

> -};

> -

> -struct clk_bytediv {

> -	struct clk_hw hw;

> -	void __iomem *reg;

> -};

> -

> -struct dsi_pll_28nm {

> -	struct msm_dsi_pll base;

> -

> -	int id;

> -	struct platform_device *pdev;

> -	void __iomem *mmio;

> -

> -	/* custom byte clock divider */

> -	struct clk_bytediv *bytediv;

> -

> -	/* private clocks: */

> -	struct clk *clks[NUM_DSI_CLOCKS_MAX];

> -	u32 num_clks;

> -

> -	/* clock-provider: */

> -	struct clk *provided_clks[NUM_PROVIDED_CLKS];

> -	struct clk_onecell_data clk_data;

> -

> -	struct pll_28nm_cached_state cached_state;

> -};

> -

> -#define to_pll_28nm(x)	container_of(x, struct dsi_pll_28nm, base)

> -

> -static bool pll_28nm_poll_for_ready(struct dsi_pll_28nm *pll_28nm,

> -				    int nb_tries, int timeout_us)

> -{

> -	bool pll_locked = false;

> -	u32 val;

> -

> -	while (nb_tries--) {

> -		val = pll_read(pll_28nm->mmio + REG_DSI_28nm_8960_PHY_PLL_RDY);

> -		pll_locked = !!(val & DSI_28nm_8960_PHY_PLL_RDY_PLL_RDY);

> -

> -		if (pll_locked)

> -			break;

> -

> -		udelay(timeout_us);

> -	}

> -	DBG("DSI PLL is %slocked", pll_locked ? "" : "*not* ");

> -

> -	return pll_locked;

> -}

> -

> -/*

> - * Clock Callbacks

> - */

> -static int dsi_pll_28nm_clk_set_rate(struct clk_hw *hw, unsigned long 

> rate,

> -				     unsigned long parent_rate)

> -{

> -	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> -	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> -	void __iomem *base = pll_28nm->mmio;

> -	u32 val, temp, fb_divider;

> -

> -	DBG("rate=%lu, parent's=%lu", rate, parent_rate);

> -

> -	temp = rate / 10;

> -	val = VCO_REF_CLK_RATE / 10;

> -	fb_divider = (temp * VCO_PREF_DIV_RATIO) / val;

> -	fb_divider = fb_divider / 2 - 1;

> -	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_1,

> -			fb_divider & 0xff);

> -

> -	val = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2);

> -

> -	val |= (fb_divider >> 8) & 0x07;

> -

> -	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2,

> -			val);

> -

> -	val = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3);

> -

> -	val |= (VCO_PREF_DIV_RATIO - 1) & 0x3f;

> -

> -	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3,

> -			val);

> -

> -	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_6,

> -			0xf);

> -

> -	val = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);

> -	val |= 0x7 << 4;

> -	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8,

> -			val);

> -

> -	return 0;

> -}

> -

> -static int dsi_pll_28nm_clk_is_enabled(struct clk_hw *hw)

> -{

> -	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> -	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> -

> -	return pll_28nm_poll_for_ready(pll_28nm, POLL_MAX_READS,

> -					POLL_TIMEOUT_US);

> -}

> -

> -static unsigned long dsi_pll_28nm_clk_recalc_rate(struct clk_hw *hw,

> -						  unsigned long parent_rate)

> -{

> -	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> -	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> -	void __iomem *base = pll_28nm->mmio;

> -	unsigned long vco_rate;

> -	u32 status, fb_divider, temp, ref_divider;

> -

> -	VERB("parent_rate=%lu", parent_rate);

> -

> -	status = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_0);

> -

> -	if (status & DSI_28nm_8960_PHY_PLL_CTRL_0_ENABLE) {

> -		fb_divider = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_1);

> -		fb_divider &= 0xff;

> -		temp = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2) & 0x07;

> -		fb_divider = (temp << 8) | fb_divider;

> -		fb_divider += 1;

> -

> -		ref_divider = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3);

> -		ref_divider &= 0x3f;

> -		ref_divider += 1;

> -

> -		/* multiply by 2 */

> -		vco_rate = (parent_rate / ref_divider) * fb_divider * 2;

> -	} else {

> -		vco_rate = 0;

> -	}

> -

> -	DBG("returning vco rate = %lu", vco_rate);

> -

> -	return vco_rate;

> -}

> -

> -static const struct clk_ops clk_ops_dsi_pll_28nm_vco = {

> -	.round_rate = msm_dsi_pll_helper_clk_round_rate,

> -	.set_rate = dsi_pll_28nm_clk_set_rate,

> -	.recalc_rate = dsi_pll_28nm_clk_recalc_rate,

> -	.prepare = msm_dsi_pll_helper_clk_prepare,

> -	.unprepare = msm_dsi_pll_helper_clk_unprepare,

> -	.is_enabled = dsi_pll_28nm_clk_is_enabled,

> -};

> -

> -/*

> - * Custom byte clock divier clk_ops

> - *

> - * This clock is the entry point to configuring the PLL. The user (dsi 

> host)

> - * will set this clock's rate to the desired byte clock rate. The VCO 

> lock

> - * frequency is a multiple of the byte clock rate. The multiplication 

> factor

> - * (shown as F in the diagram above) is a function of the byte clock 

> rate.

> - *

> - * This custom divider clock ensures that its parent (VCO) is set to 

> the

> - * desired rate, and that the byte clock postdivider (POSTDIV2) is 

> configured

> - * accordingly

> - */

> -#define to_clk_bytediv(_hw) container_of(_hw, struct clk_bytediv, hw)

> -

> -static unsigned long clk_bytediv_recalc_rate(struct clk_hw *hw,

> -		unsigned long parent_rate)

> -{

> -	struct clk_bytediv *bytediv = to_clk_bytediv(hw);

> -	unsigned int div;

> -

> -	div = pll_read(bytediv->reg) & 0xff;

> -

> -	return parent_rate / (div + 1);

> -}

> -

> -/* find multiplication factor(wrt byte clock) at which the VCO should 

> be set */

> -static unsigned int get_vco_mul_factor(unsigned long byte_clk_rate)

> -{

> -	unsigned long bit_mhz;

> -

> -	/* convert to bit clock in Mhz */

> -	bit_mhz = (byte_clk_rate * 8) / 1000000;

> -

> -	if (bit_mhz < 125)

> -		return 64;

> -	else if (bit_mhz < 250)

> -		return 32;

> -	else if (bit_mhz < 600)

> -		return 16;

> -	else

> -		return 8;

> -}

> -

> -static long clk_bytediv_round_rate(struct clk_hw *hw, unsigned long 

> rate,

> -				   unsigned long *prate)

> -{

> -	unsigned long best_parent;

> -	unsigned int factor;

> -

> -	factor = get_vco_mul_factor(rate);

> -

> -	best_parent = rate * factor;

> -	*prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);

> -

> -	return *prate / factor;

> -}

> -

> -static int clk_bytediv_set_rate(struct clk_hw *hw, unsigned long rate,

> -				unsigned long parent_rate)

> -{

> -	struct clk_bytediv *bytediv = to_clk_bytediv(hw);

> -	u32 val;

> -	unsigned int factor;

> -

> -	factor = get_vco_mul_factor(rate);

> -

> -	val = pll_read(bytediv->reg);

> -	val |= (factor - 1) & 0xff;

> -	pll_write(bytediv->reg, val);

> -

> -	return 0;

> -}

> -

> -/* Our special byte clock divider ops */

> -static const struct clk_ops clk_bytediv_ops = {

> -	.round_rate = clk_bytediv_round_rate,

> -	.set_rate = clk_bytediv_set_rate,

> -	.recalc_rate = clk_bytediv_recalc_rate,

> -};

> -

> -/*

> - * PLL Callbacks

> - */

> -static int dsi_pll_28nm_enable_seq(struct msm_dsi_pll *pll)

> -{

> -	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> -	struct device *dev = &pll_28nm->pdev->dev;

> -	void __iomem *base = pll_28nm->mmio;

> -	bool locked;

> -	unsigned int bit_div, byte_div;

> -	int max_reads = 1000, timeout_us = 100;

> -	u32 val;

> -

> -	DBG("id=%d", pll_28nm->id);

> -

> -	/*

> -	 * before enabling the PLL, configure the bit clock divider since we

> -	 * don't expose it as a clock to the outside world

> -	 * 1: read back the byte clock divider that should already be set

> -	 * 2: divide by 8 to get bit clock divider

> -	 * 3: write it to POSTDIV1

> -	 */

> -	val = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9);

> -	byte_div = val + 1;

> -	bit_div = byte_div / 8;

> -

> -	val = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);

> -	val &= ~0xf;

> -	val |= (bit_div - 1);

> -	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8, val);

> -

> -	/* enable the PLL */

> -	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_0,

> -			DSI_28nm_8960_PHY_PLL_CTRL_0_ENABLE);

> -

> -	locked = pll_28nm_poll_for_ready(pll_28nm, max_reads, timeout_us);

> -

> -	if (unlikely(!locked))

> -		DRM_DEV_ERROR(dev, "DSI PLL lock failed\n");

> -	else

> -		DBG("DSI PLL lock success");

> -

> -	return locked ? 0 : -EINVAL;

> -}

> -

> -static void dsi_pll_28nm_disable_seq(struct msm_dsi_pll *pll)

> -{

> -	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> -

> -	DBG("id=%d", pll_28nm->id);

> -	pll_write(pll_28nm->mmio + REG_DSI_28nm_8960_PHY_PLL_CTRL_0, 0x00);

> -}

> -

> -static void dsi_pll_28nm_save_state(struct msm_dsi_pll *pll)

> -{

> -	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> -	struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;

> -	void __iomem *base = pll_28nm->mmio;

> -

> -	cached_state->postdiv3 =

> -			pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_10);

> -	cached_state->postdiv2 =

> -			pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9);

> -	cached_state->postdiv1 =

> -			pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);

> -

> -	cached_state->vco_rate = clk_hw_get_rate(&pll->clk_hw);

> -}

> -

> -static int dsi_pll_28nm_restore_state(struct msm_dsi_pll *pll)

> -{

> -	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> -	struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;

> -	void __iomem *base = pll_28nm->mmio;

> -	int ret;

> -

> -	ret = dsi_pll_28nm_clk_set_rate(&pll->clk_hw,

> -					cached_state->vco_rate, 0);

> -	if (ret) {

> -		DRM_DEV_ERROR(&pll_28nm->pdev->dev,

> -			"restore vco rate failed. ret=%d\n", ret);

> -		return ret;

> -	}

> -

> -	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_10,

> -			cached_state->postdiv3);

> -	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9,

> -			cached_state->postdiv2);

> -	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8,

> -			cached_state->postdiv1);

> -

> -	return 0;

> -}

> -

> -static int dsi_pll_28nm_get_provider(struct msm_dsi_pll *pll,

> -				struct clk **byte_clk_provider,

> -				struct clk **pixel_clk_provider)

> -{

> -	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> -

> -	if (byte_clk_provider)

> -		*byte_clk_provider = pll_28nm->provided_clks[DSI_BYTE_PLL_CLK];

> -	if (pixel_clk_provider)

> -		*pixel_clk_provider =

> -				pll_28nm->provided_clks[DSI_PIXEL_PLL_CLK];

> -

> -	return 0;

> -}

> -

> -static void dsi_pll_28nm_destroy(struct msm_dsi_pll *pll)

> -{

> -	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);

> -

> -	msm_dsi_pll_helper_unregister_clks(pll_28nm->pdev,

> -					pll_28nm->clks, pll_28nm->num_clks);

> -}

> -

> -static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm)

> -{

> -	char *clk_name, *parent_name, *vco_name;

> -	struct clk_init_data vco_init = {

> -		.parent_names = (const char *[]){ "pxo" },

> -		.num_parents = 1,

> -		.flags = CLK_IGNORE_UNUSED,

> -		.ops = &clk_ops_dsi_pll_28nm_vco,

> -	};

> -	struct device *dev = &pll_28nm->pdev->dev;

> -	struct clk **clks = pll_28nm->clks;

> -	struct clk **provided_clks = pll_28nm->provided_clks;

> -	struct clk_bytediv *bytediv;

> -	struct clk_init_data bytediv_init = { };

> -	int ret, num = 0;

> -

> -	DBG("%d", pll_28nm->id);

> -

> -	bytediv = devm_kzalloc(dev, sizeof(*bytediv), GFP_KERNEL);

> -	if (!bytediv)

> -		return -ENOMEM;

> -

> -	vco_name = devm_kzalloc(dev, 32, GFP_KERNEL);

> -	if (!vco_name)

> -		return -ENOMEM;

> -

> -	parent_name = devm_kzalloc(dev, 32, GFP_KERNEL);

> -	if (!parent_name)

> -		return -ENOMEM;

> -

> -	clk_name = devm_kzalloc(dev, 32, GFP_KERNEL);

> -	if (!clk_name)

> -		return -ENOMEM;

> -

> -	pll_28nm->bytediv = bytediv;

> -

> -	snprintf(vco_name, 32, "dsi%dvco_clk", pll_28nm->id);

> -	vco_init.name = vco_name;

> -

> -	pll_28nm->base.clk_hw.init = &vco_init;

> -

> -	clks[num++] = clk_register(dev, &pll_28nm->base.clk_hw);

> -

> -	/* prepare and register bytediv */

> -	bytediv->hw.init = &bytediv_init;

> -	bytediv->reg = pll_28nm->mmio + REG_DSI_28nm_8960_PHY_PLL_CTRL_9;

> -

> -	snprintf(parent_name, 32, "dsi%dvco_clk", pll_28nm->id);

> -	snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->id);

> -

> -	bytediv_init.name = clk_name;

> -	bytediv_init.ops = &clk_bytediv_ops;

> -	bytediv_init.flags = CLK_SET_RATE_PARENT;

> -	bytediv_init.parent_names = (const char * const *) &parent_name;

> -	bytediv_init.num_parents = 1;

> -

> -	/* DIV2 */

> -	clks[num++] = provided_clks[DSI_BYTE_PLL_CLK] =

> -			clk_register(dev, &bytediv->hw);

> -

> -	snprintf(clk_name, 32, "dsi%dpll", pll_28nm->id);

> -	/* DIV3 */

> -	clks[num++] = provided_clks[DSI_PIXEL_PLL_CLK] =

> -			clk_register_divider(dev, clk_name,

> -				parent_name, 0, pll_28nm->mmio +

> -				REG_DSI_28nm_8960_PHY_PLL_CTRL_10,

> -				0, 8, 0, NULL);

> -

> -	pll_28nm->num_clks = num;

> -

> -	pll_28nm->clk_data.clk_num = NUM_PROVIDED_CLKS;

> -	pll_28nm->clk_data.clks = provided_clks;

> -

> -	ret = of_clk_add_provider(dev->of_node,

> -			of_clk_src_onecell_get, &pll_28nm->clk_data);

> -	if (ret) {

> -		DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret);

> -		return ret;

> -	}

> -

> -	return 0;

> -}

> -

> -struct msm_dsi_pll *msm_dsi_pll_28nm_8960_init(struct platform_device 

> *pdev,

> -					       int id)

> -{

> -	struct dsi_pll_28nm *pll_28nm;

> -	struct msm_dsi_pll *pll;

> -	int ret;

> -

> -	if (!pdev)

> -		return ERR_PTR(-ENODEV);

> -

> -	pll_28nm = devm_kzalloc(&pdev->dev, sizeof(*pll_28nm), GFP_KERNEL);

> -	if (!pll_28nm)

> -		return ERR_PTR(-ENOMEM);

> -

> -	pll_28nm->pdev = pdev;

> -	pll_28nm->id = id + 1;

> -

> -	pll_28nm->mmio = msm_ioremap(pdev, "dsi_pll", "DSI_PLL");

> -	if (IS_ERR_OR_NULL(pll_28nm->mmio)) {

> -		DRM_DEV_ERROR(&pdev->dev, "%s: failed to map pll base\n", __func__);

> -		return ERR_PTR(-ENOMEM);

> -	}

> -

> -	pll = &pll_28nm->base;

> -	pll->min_rate = VCO_MIN_RATE;

> -	pll->max_rate = VCO_MAX_RATE;

> -	pll->get_provider = dsi_pll_28nm_get_provider;

> -	pll->destroy = dsi_pll_28nm_destroy;

> -	pll->disable_seq = dsi_pll_28nm_disable_seq;

> -	pll->save_state = dsi_pll_28nm_save_state;

> -	pll->restore_state = dsi_pll_28nm_restore_state;

> -

> -	pll->en_seq_cnt = 1;

> -	pll->enable_seqs[0] = dsi_pll_28nm_enable_seq;

> -

> -	ret = pll_28nm_register(pll_28nm);

> -	if (ret) {

> -		DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret);

> -		return ERR_PTR(ret);

> -	}

> -

> -	return pll;

> -}

> diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c

> b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c

> deleted file mode 100644

> index e29b3bfd63d1..000000000000

> --- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c

> +++ /dev/null

> @@ -1,913 +0,0 @@

> -/*

> - * SPDX-License-Identifier: GPL-2.0

> - * Copyright (c) 2018, The Linux Foundation

> - */

> -

> -#include <linux/clk.h>

> -#include <linux/clk-provider.h>

> -#include <linux/iopoll.h>

> -

> -#include "dsi_pll.h"

> -#include "dsi.xml.h"

> -

> -/*

> - * DSI PLL 7nm - clock diagram (eg: DSI0): TODO: updated CPHY diagram

> - *

> - *           dsi0_pll_out_div_clk  dsi0_pll_bit_clk

> - *                              |                |

> - *                              |                |

> - *                 +---------+  |  +----------+  |  +----+

> - *  dsi0vco_clk ---| out_div |--o--| divl_3_0 |--o--| /8 |--

> dsi0_phy_pll_out_byteclk

> - *                 +---------+  |  +----------+  |  +----+

> - *                              |                |

> - *                              |                |

> dsi0_pll_by_2_bit_clk

> - *                              |                |          |

> - *                              |                |  +----+  |  |\

> dsi0_pclk_mux

> - *                              |                |--| /2 |--o--| \   |

> - *                              |                |  +----+     |  \

> |  +---------+

> - *                              |                --------------|

> |--o--| div_7_4 |-- dsi0_phy_pll_out_dsiclk

> - *                              |------------------------------|  /

>   +---------+

> - *                              |          +-----+             | /

> - *                              -----------| /4? |--o----------|/

> - *                                         +-----+  |           |

> - *                                                  |           

> |dsiclk_sel

> - *                                                  |

> - *                                                  

> dsi0_pll_post_out_div_clk

> - */

> -

> -#define DSI_BYTE_PLL_CLK		0

> -#define DSI_PIXEL_PLL_CLK		1

> -#define NUM_PROVIDED_CLKS		2

> -

> -#define VCO_REF_CLK_RATE		19200000

> -

> -struct dsi_pll_regs {

> -	u32 pll_prop_gain_rate;

> -	u32 pll_lockdet_rate;

> -	u32 decimal_div_start;

> -	u32 frac_div_start_low;

> -	u32 frac_div_start_mid;

> -	u32 frac_div_start_high;

> -	u32 pll_clock_inverters;

> -	u32 ssc_stepsize_low;

> -	u32 ssc_stepsize_high;

> -	u32 ssc_div_per_low;

> -	u32 ssc_div_per_high;

> -	u32 ssc_adjper_low;

> -	u32 ssc_adjper_high;

> -	u32 ssc_control;

> -};

> -

> -struct dsi_pll_config {

> -	u32 ref_freq;

> -	bool div_override;

> -	u32 output_div;

> -	bool ignore_frac;

> -	bool disable_prescaler;

> -	bool enable_ssc;

> -	bool ssc_center;

> -	u32 dec_bits;

> -	u32 frac_bits;

> -	u32 lock_timer;

> -	u32 ssc_freq;

> -	u32 ssc_offset;

> -	u32 ssc_adj_per;

> -	u32 thresh_cycles;

> -	u32 refclk_cycles;

> -};

> -

> -struct pll_7nm_cached_state {

> -	unsigned long vco_rate;

> -	u8 bit_clk_div;

> -	u8 pix_clk_div;

> -	u8 pll_out_div;

> -	u8 pll_mux;

> -};

> -

> -struct dsi_pll_7nm {

> -	struct msm_dsi_pll base;

> -

> -	int id;

> -	struct platform_device *pdev;

> -

> -	void __iomem *phy_cmn_mmio;

> -	void __iomem *mmio;

> -

> -	u64 vco_ref_clk_rate;

> -	u64 vco_current_rate;

> -

> -	/* protects REG_DSI_7nm_PHY_CMN_CLK_CFG0 register */

> -	spinlock_t postdiv_lock;

> -

> -	int vco_delay;

> -	struct dsi_pll_config pll_configuration;

> -	struct dsi_pll_regs reg_setup;

> -

> -	/* private clocks: */

> -	struct clk_hw *out_div_clk_hw;

> -	struct clk_hw *bit_clk_hw;

> -	struct clk_hw *byte_clk_hw;

> -	struct clk_hw *by_2_bit_clk_hw;

> -	struct clk_hw *post_out_div_clk_hw;

> -	struct clk_hw *pclk_mux_hw;

> -	struct clk_hw *out_dsiclk_hw;

> -

> -	/* clock-provider: */

> -	struct clk_hw_onecell_data *hw_data;

> -

> -	struct pll_7nm_cached_state cached_state;

> -

> -	enum msm_dsi_phy_usecase uc;

> -	struct dsi_pll_7nm *slave;

> -};

> -

> -#define to_pll_7nm(x)	container_of(x, struct dsi_pll_7nm, base)

> -

> -/*

> - * Global list of private DSI PLL struct pointers. We need this for 

> Dual DSI

> - * mode, where the master PLL's clk_ops needs access the slave's 

> private data

> - */

> -static struct dsi_pll_7nm *pll_7nm_list[DSI_MAX];

> -

> -static void dsi_pll_setup_config(struct dsi_pll_7nm *pll)

> -{

> -	struct dsi_pll_config *config = &pll->pll_configuration;

> -

> -	config->ref_freq = pll->vco_ref_clk_rate;

> -	config->output_div = 1;

> -	config->dec_bits = 8;

> -	config->frac_bits = 18;

> -	config->lock_timer = 64;

> -	config->ssc_freq = 31500;

> -	config->ssc_offset = 4800;

> -	config->ssc_adj_per = 2;

> -	config->thresh_cycles = 32;

> -	config->refclk_cycles = 256;

> -

> -	config->div_override = false;

> -	config->ignore_frac = false;

> -	config->disable_prescaler = false;

> -

> -	/* TODO: ssc enable */

> -	config->enable_ssc = false;

> -	config->ssc_center = 0;

> -}

> -

> -static void dsi_pll_calc_dec_frac(struct dsi_pll_7nm *pll)

> -{

> -	struct dsi_pll_config *config = &pll->pll_configuration;

> -	struct dsi_pll_regs *regs = &pll->reg_setup;

> -	u64 fref = pll->vco_ref_clk_rate;

> -	u64 pll_freq;

> -	u64 divider;

> -	u64 dec, dec_multiple;

> -	u32 frac;

> -	u64 multiplier;

> -

> -	pll_freq = pll->vco_current_rate;

> -

> -	if (config->disable_prescaler)

> -		divider = fref;

> -	else

> -		divider = fref * 2;

> -

> -	multiplier = 1 << config->frac_bits;

> -	dec_multiple = div_u64(pll_freq * multiplier, divider);

> -	div_u64_rem(dec_multiple, multiplier, &frac);

> -

> -	dec = div_u64(dec_multiple, multiplier);

> -

> -	if (pll->base.type != MSM_DSI_PHY_7NM_V4_1)

> -		regs->pll_clock_inverters = 0x28;

> -	else if (pll_freq <= 1000000000ULL)

> -		regs->pll_clock_inverters = 0xa0;

> -	else if (pll_freq <= 2500000000ULL)

> -		regs->pll_clock_inverters = 0x20;

> -	else if (pll_freq <= 3020000000ULL)

> -		regs->pll_clock_inverters = 0x00;

> -	else

> -		regs->pll_clock_inverters = 0x40;

> -

> -	regs->pll_lockdet_rate = config->lock_timer;

> -	regs->decimal_div_start = dec;

> -	regs->frac_div_start_low = (frac & 0xff);

> -	regs->frac_div_start_mid = (frac & 0xff00) >> 8;

> -	regs->frac_div_start_high = (frac & 0x30000) >> 16;

> -}

> -

> -#define SSC_CENTER		BIT(0)

> -#define SSC_EN			BIT(1)

> -

> -static void dsi_pll_calc_ssc(struct dsi_pll_7nm *pll)

> -{

> -	struct dsi_pll_config *config = &pll->pll_configuration;

> -	struct dsi_pll_regs *regs = &pll->reg_setup;

> -	u32 ssc_per;

> -	u32 ssc_mod;

> -	u64 ssc_step_size;

> -	u64 frac;

> -

> -	if (!config->enable_ssc) {

> -		DBG("SSC not enabled\n");

> -		return;

> -	}

> -

> -	ssc_per = DIV_ROUND_CLOSEST(config->ref_freq, config->ssc_freq) / 2 - 

> 1;

> -	ssc_mod = (ssc_per + 1) % (config->ssc_adj_per + 1);

> -	ssc_per -= ssc_mod;

> -

> -	frac = regs->frac_div_start_low |

> -			(regs->frac_div_start_mid << 8) |

> -			(regs->frac_div_start_high << 16);

> -	ssc_step_size = regs->decimal_div_start;

> -	ssc_step_size *= (1 << config->frac_bits);

> -	ssc_step_size += frac;

> -	ssc_step_size *= config->ssc_offset;

> -	ssc_step_size *= (config->ssc_adj_per + 1);

> -	ssc_step_size = div_u64(ssc_step_size, (ssc_per + 1));

> -	ssc_step_size = DIV_ROUND_CLOSEST_ULL(ssc_step_size, 1000000);

> -

> -	regs->ssc_div_per_low = ssc_per & 0xFF;

> -	regs->ssc_div_per_high = (ssc_per & 0xFF00) >> 8;

> -	regs->ssc_stepsize_low = (u32)(ssc_step_size & 0xFF);

> -	regs->ssc_stepsize_high = (u32)((ssc_step_size & 0xFF00) >> 8);

> -	regs->ssc_adjper_low = config->ssc_adj_per & 0xFF;

> -	regs->ssc_adjper_high = (config->ssc_adj_per & 0xFF00) >> 8;

> -

> -	regs->ssc_control = config->ssc_center ? SSC_CENTER : 0;

> -

> -	pr_debug("SCC: Dec:%d, frac:%llu, frac_bits:%d\n",

> -		 regs->decimal_div_start, frac, config->frac_bits);

> -	pr_debug("SSC: div_per:0x%X, stepsize:0x%X, adjper:0x%X\n",

> -		 ssc_per, (u32)ssc_step_size, config->ssc_adj_per);

> -}

> -

> -static void dsi_pll_ssc_commit(struct dsi_pll_7nm *pll)

> -{

> -	void __iomem *base = pll->mmio;

> -	struct dsi_pll_regs *regs = &pll->reg_setup;

> -

> -	if (pll->pll_configuration.enable_ssc) {

> -		pr_debug("SSC is enabled\n");

> -

> -		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_STEPSIZE_LOW_1,

> -			  regs->ssc_stepsize_low);

> -		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_STEPSIZE_HIGH_1,

> -			  regs->ssc_stepsize_high);

> -		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_DIV_PER_LOW_1,

> -			  regs->ssc_div_per_low);

> -		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_DIV_PER_HIGH_1,

> -			  regs->ssc_div_per_high);

> -		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_ADJPER_LOW_1,

> -			  regs->ssc_adjper_low);

> -		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_ADJPER_HIGH_1,

> -			  regs->ssc_adjper_high);

> -		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_CONTROL,

> -			  SSC_EN | regs->ssc_control);

> -	}

> -}

> -

> -static void dsi_pll_config_hzindep_reg(struct dsi_pll_7nm *pll)

> -{

> -	void __iomem *base = pll->mmio;

> -	u8 analog_controls_five_1 = 0x01, vco_config_1 = 0x00;

> -

> -	if (pll->base.type == MSM_DSI_PHY_7NM_V4_1) {

> -		if (pll->vco_current_rate >= 3100000000ULL)

> -			analog_controls_five_1 = 0x03;

> -

> -		if (pll->vco_current_rate < 1520000000ULL)

> -			vco_config_1 = 0x08;

> -		else if (pll->vco_current_rate < 2990000000ULL)

> -			vco_config_1 = 0x01;

> -	}

> -

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_FIVE_1,

> -		  analog_controls_five_1);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_VCO_CONFIG_1, vco_config_1);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_FIVE, 0x01);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_TWO, 0x03);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_THREE, 0x00);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_DSM_DIVIDER, 0x00);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_FEEDBACK_DIVIDER, 0x4e);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_CALIBRATION_SETTINGS, 0x40);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_BAND_SEL_CAL_SETTINGS_THREE, 

> 0xba);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_FREQ_DETECT_SETTINGS_ONE, 0x0c);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_OUTDIV, 0x00);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_CORE_OVERRIDE, 0x00);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_DIGITAL_TIMERS_TWO, 0x08);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_PROP_GAIN_RATE_1, 0x0a);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_BAND_SEL_RATE_1, 0xc0);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_1, 

> 0x84);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_1, 

> 0x82);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_FL_INT_GAIN_PFILT_BAND_1, 

> 0x4c);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCK_OVERRIDE, 0x80);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_PFILT, 0x29);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_PFILT, 0x2f);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_IFILT, 0x2a);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_IFILT,

> -		  pll->base.type == MSM_DSI_PHY_7NM_V4_1 ? 0x3f : 0x22);

> -

> -	if (pll->base.type == MSM_DSI_PHY_7NM_V4_1) {

> -		pll_write(base + REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE, 0x22);

> -		if (pll->slave)

> -			pll_write(pll->slave->mmio + REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE, 

> 0x22);

> -	}

> -}

> -

> -static void dsi_pll_commit(struct dsi_pll_7nm *pll)

> -{

> -	void __iomem *base = pll->mmio;

> -	struct dsi_pll_regs *reg = &pll->reg_setup;

> -

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_CORE_INPUT_OVERRIDE, 0x12);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_DECIMAL_DIV_START_1,

> reg->decimal_div_start);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_LOW_1,

> reg->frac_div_start_low);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_MID_1,

> reg->frac_div_start_mid);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_HIGH_1,

> reg->frac_div_start_high);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCKDET_RATE_1,

> reg->pll_lockdet_rate);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCK_DELAY, 0x06);

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_CMODE_1, 0x10); /* TODO: 0x00 

> for CPHY */

> -	pll_write(base + REG_DSI_7nm_PHY_PLL_CLOCK_INVERTERS,

> reg->pll_clock_inverters);

> -}

> -

> -static int dsi_pll_7nm_vco_set_rate(struct clk_hw *hw, unsigned long 

> rate,

> -				     unsigned long parent_rate)

> -{

> -	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> -	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);

> -

> -	DBG("DSI PLL%d rate=%lu, parent's=%lu", pll_7nm->id, rate,

> -	    parent_rate);

> -

> -	pll_7nm->vco_current_rate = rate;

> -	pll_7nm->vco_ref_clk_rate = VCO_REF_CLK_RATE;

> -

> -	dsi_pll_setup_config(pll_7nm);

> -

> -	dsi_pll_calc_dec_frac(pll_7nm);

> -

> -	dsi_pll_calc_ssc(pll_7nm);

> -

> -	dsi_pll_commit(pll_7nm);

> -

> -	dsi_pll_config_hzindep_reg(pll_7nm);

> -

> -	dsi_pll_ssc_commit(pll_7nm);

> -

> -	/* flush, ensure all register writes are done*/

> -	wmb();

> -

> -	return 0;

> -}

> -

> -static int dsi_pll_7nm_lock_status(struct dsi_pll_7nm *pll)

> -{

> -	int rc;

> -	u32 status = 0;

> -	u32 const delay_us = 100;

> -	u32 const timeout_us = 5000;

> -

> -	rc = readl_poll_timeout_atomic(pll->mmio +

> -				       REG_DSI_7nm_PHY_PLL_COMMON_STATUS_ONE,

> -				       status,

> -				       ((status & BIT(0)) > 0),

> -				       delay_us,

> -				       timeout_us);

> -	if (rc)

> -		pr_err("DSI PLL(%d) lock failed, status=0x%08x\n",

> -		       pll->id, status);

> -

> -	return rc;

> -}

> -

> -static void dsi_pll_disable_pll_bias(struct dsi_pll_7nm *pll)

> -{

> -	u32 data = pll_read(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CTRL_0);

> -

> -	pll_write(pll->mmio + REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES, 0);

> -	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CTRL_0, data & 

> ~BIT(5));

> -	ndelay(250);

> -}

> -

> -static void dsi_pll_enable_pll_bias(struct dsi_pll_7nm *pll)

> -{

> -	u32 data = pll_read(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CTRL_0);

> -

> -	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CTRL_0, data | 

> BIT(5));

> -	pll_write(pll->mmio + REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES, 0xc0);

> -	ndelay(250);

> -}

> -

> -static void dsi_pll_disable_global_clk(struct dsi_pll_7nm *pll)

> -{

> -	u32 data;

> -

> -	data = pll_read(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CLK_CFG1);

> -	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CLK_CFG1, data & 

> ~BIT(5));

> -}

> -

> -static void dsi_pll_enable_global_clk(struct dsi_pll_7nm *pll)

> -{

> -	u32 data;

> -

> -	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CTRL_3, 0x04);

> -

> -	data = pll_read(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CLK_CFG1);

> -	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CLK_CFG1,

> -		  data | BIT(5) | BIT(4));

> -}

> -

> -static void dsi_pll_phy_dig_reset(struct dsi_pll_7nm *pll)

> -{

> -	/*

> -	 * Reset the PHY digital domain. This would be needed when

> -	 * coming out of a CX or analog rail power collapse while

> -	 * ensuring that the pads maintain LP00 or LP11 state

> -	 */

> -	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE4, 

> BIT(0));

> -	wmb(); /* Ensure that the reset is deasserted */

> -	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE4, 

> 0x0);

> -	wmb(); /* Ensure that the reset is deasserted */

> -}

> -

> -static int dsi_pll_7nm_vco_prepare(struct clk_hw *hw)

> -{

> -	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> -	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);

> -	int rc;

> -

> -	dsi_pll_enable_pll_bias(pll_7nm);

> -	if (pll_7nm->slave)

> -		dsi_pll_enable_pll_bias(pll_7nm->slave);

> -

> -	/* Start PLL */

> -	pll_write(pll_7nm->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_PLL_CNTRL, 

> 0x01);

> -

> -	/*

> -	 * ensure all PLL configurations are written prior to checking

> -	 * for PLL lock.

> -	 */

> -	wmb();

> -

> -	/* Check for PLL lock */

> -	rc = dsi_pll_7nm_lock_status(pll_7nm);

> -	if (rc) {

> -		pr_err("PLL(%d) lock failed\n", pll_7nm->id);

> -		goto error;

> -	}

> -

> -	pll->pll_on = true;

> -

> -	/*

> -	 * assert power on reset for PHY digital in case the PLL is

> -	 * enabled after CX of analog domain power collapse. This needs

> -	 * to be done before enabling the global clk.

> -	 */

> -	dsi_pll_phy_dig_reset(pll_7nm);

> -	if (pll_7nm->slave)

> -		dsi_pll_phy_dig_reset(pll_7nm->slave);

> -

> -	dsi_pll_enable_global_clk(pll_7nm);

> -	if (pll_7nm->slave)

> -		dsi_pll_enable_global_clk(pll_7nm->slave);

> -

> -error:

> -	return rc;

> -}

> -

> -static void dsi_pll_disable_sub(struct dsi_pll_7nm *pll)

> -{

> -	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_RBUF_CTRL, 0);

> -	dsi_pll_disable_pll_bias(pll);

> -}

> -

> -static void dsi_pll_7nm_vco_unprepare(struct clk_hw *hw)

> -{

> -	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> -	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);

> -

> -	/*

> -	 * To avoid any stray glitches while abruptly powering down the PLL

> -	 * make sure to gate the clock using the clock enable bit before

> -	 * powering down the PLL

> -	 */

> -	dsi_pll_disable_global_clk(pll_7nm);

> -	pll_write(pll_7nm->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_PLL_CNTRL, 0);

> -	dsi_pll_disable_sub(pll_7nm);

> -	if (pll_7nm->slave) {

> -		dsi_pll_disable_global_clk(pll_7nm->slave);

> -		dsi_pll_disable_sub(pll_7nm->slave);

> -	}

> -	/* flush, ensure all register writes are done */

> -	wmb();

> -	pll->pll_on = false;

> -}

> -

> -static unsigned long dsi_pll_7nm_vco_recalc_rate(struct clk_hw *hw,

> -						  unsigned long parent_rate)

> -{

> -	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

> -	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);

> -	struct dsi_pll_config *config = &pll_7nm->pll_configuration;

> -	void __iomem *base = pll_7nm->mmio;

> -	u64 ref_clk = pll_7nm->vco_ref_clk_rate;

> -	u64 vco_rate = 0x0;

> -	u64 multiplier;

> -	u32 frac;

> -	u32 dec;

> -	u64 pll_freq, tmp64;

> -

> -	dec = pll_read(base + REG_DSI_7nm_PHY_PLL_DECIMAL_DIV_START_1);

> -	dec &= 0xff;

> -

> -	frac = pll_read(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_LOW_1);

> -	frac |= ((pll_read(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_MID_1) &

> -		  0xff) << 8);

> -	frac |= ((pll_read(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_HIGH_1) 

> &

> -		  0x3) << 16);

> -

> -	/*

> -	 * TODO:

> -	 *	1. Assumes prescaler is disabled

> -	 */

> -	multiplier = 1 << config->frac_bits;

> -	pll_freq = dec * (ref_clk * 2);

> -	tmp64 = (ref_clk * 2 * frac);

> -	pll_freq += div_u64(tmp64, multiplier);

> -

> -	vco_rate = pll_freq;

> -

> -	DBG("DSI PLL%d returning vco rate = %lu, dec = %x, frac = %x",

> -	    pll_7nm->id, (unsigned long)vco_rate, dec, frac);

> -

> -	return (unsigned long)vco_rate;

> -}

> -

> -static const struct clk_ops clk_ops_dsi_pll_7nm_vco = {

> -	.round_rate = msm_dsi_pll_helper_clk_round_rate,

> -	.set_rate = dsi_pll_7nm_vco_set_rate,

> -	.recalc_rate = dsi_pll_7nm_vco_recalc_rate,

> -	.prepare = dsi_pll_7nm_vco_prepare,

> -	.unprepare = dsi_pll_7nm_vco_unprepare,

> -};

> -

> -/*

> - * PLL Callbacks

> - */

> -

> -static void dsi_pll_7nm_save_state(struct msm_dsi_pll *pll)

> -{

> -	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);

> -	struct pll_7nm_cached_state *cached = &pll_7nm->cached_state;

> -	void __iomem *phy_base = pll_7nm->phy_cmn_mmio;

> -	u32 cmn_clk_cfg0, cmn_clk_cfg1;

> -

> -	cached->pll_out_div = pll_read(pll_7nm->mmio +

> -				       REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE);

> -	cached->pll_out_div &= 0x3;

> -

> -	cmn_clk_cfg0 = pll_read(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0);

> -	cached->bit_clk_div = cmn_clk_cfg0 & 0xf;

> -	cached->pix_clk_div = (cmn_clk_cfg0 & 0xf0) >> 4;

> -

> -	cmn_clk_cfg1 = pll_read(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);

> -	cached->pll_mux = cmn_clk_cfg1 & 0x3;

> -

> -	DBG("DSI PLL%d outdiv %x bit_clk_div %x pix_clk_div %x pll_mux %x",

> -	    pll_7nm->id, cached->pll_out_div, cached->bit_clk_div,

> -	    cached->pix_clk_div, cached->pll_mux);

> -}

> -

> -static int dsi_pll_7nm_restore_state(struct msm_dsi_pll *pll)

> -{

> -	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);

> -	struct pll_7nm_cached_state *cached = &pll_7nm->cached_state;

> -	void __iomem *phy_base = pll_7nm->phy_cmn_mmio;

> -	u32 val;

> -	int ret;

> -

> -	val = pll_read(pll_7nm->mmio + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE);

> -	val &= ~0x3;

> -	val |= cached->pll_out_div;

> -	pll_write(pll_7nm->mmio + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE, val);

> -

> -	pll_write(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0,

> -		  cached->bit_clk_div | (cached->pix_clk_div << 4));

> -

> -	val = pll_read(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);

> -	val &= ~0x3;

> -	val |= cached->pll_mux;

> -	pll_write(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, val);

> -

> -	ret = dsi_pll_7nm_vco_set_rate(&pll->clk_hw,

> pll_7nm->vco_current_rate, pll_7nm->vco_ref_clk_rate);

> -	if (ret) {

> -		DRM_DEV_ERROR(&pll_7nm->pdev->dev,

> -			"restore vco rate failed. ret=%d\n", ret);

> -		return ret;

> -	}

> -

> -	DBG("DSI PLL%d", pll_7nm->id);

> -

> -	return 0;

> -}

> -

> -static int dsi_pll_7nm_set_usecase(struct msm_dsi_pll *pll,

> -				    enum msm_dsi_phy_usecase uc)

> -{

> -	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);

> -	void __iomem *base = pll_7nm->phy_cmn_mmio;

> -	u32 data = 0x0;	/* internal PLL */

> -

> -	DBG("DSI PLL%d", pll_7nm->id);

> -

> -	switch (uc) {

> -	case MSM_DSI_PHY_STANDALONE:

> -		break;

> -	case MSM_DSI_PHY_MASTER:

> -		pll_7nm->slave = pll_7nm_list[(pll_7nm->id + 1) % DSI_MAX];

> -		break;

> -	case MSM_DSI_PHY_SLAVE:

> -		data = 0x1; /* external PLL */

> -		break;

> -	default:

> -		return -EINVAL;

> -	}

> -

> -	/* set PLL src */

> -	pll_write(base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, (data << 2));

> -

> -	pll_7nm->uc = uc;

> -

> -	return 0;

> -}

> -

> -static int dsi_pll_7nm_get_provider(struct msm_dsi_pll *pll,

> -				     struct clk **byte_clk_provider,

> -				     struct clk **pixel_clk_provider)

> -{

> -	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);

> -	struct clk_hw_onecell_data *hw_data = pll_7nm->hw_data;

> -

> -	DBG("DSI PLL%d", pll_7nm->id);

> -

> -	if (byte_clk_provider)

> -		*byte_clk_provider = hw_data->hws[DSI_BYTE_PLL_CLK]->clk;

> -	if (pixel_clk_provider)

> -		*pixel_clk_provider = hw_data->hws[DSI_PIXEL_PLL_CLK]->clk;

> -

> -	return 0;

> -}

> -

> -static void dsi_pll_7nm_destroy(struct msm_dsi_pll *pll)

> -{

> -	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);

> -	struct device *dev = &pll_7nm->pdev->dev;

> -

> -	DBG("DSI PLL%d", pll_7nm->id);

> -	of_clk_del_provider(dev->of_node);

> -

> -	clk_hw_unregister_divider(pll_7nm->out_dsiclk_hw);

> -	clk_hw_unregister_mux(pll_7nm->pclk_mux_hw);

> -	clk_hw_unregister_fixed_factor(pll_7nm->post_out_div_clk_hw);

> -	clk_hw_unregister_fixed_factor(pll_7nm->by_2_bit_clk_hw);

> -	clk_hw_unregister_fixed_factor(pll_7nm->byte_clk_hw);

> -	clk_hw_unregister_divider(pll_7nm->bit_clk_hw);

> -	clk_hw_unregister_divider(pll_7nm->out_div_clk_hw);

> -	clk_hw_unregister(&pll_7nm->base.clk_hw);

> -}

> -

> -/*

> - * The post dividers and mux clocks are created using the standard 

> divider and

> - * mux API. Unlike the 14nm PHY, the slave PLL doesn't need its 

> dividers/mux

> - * state to follow the master PLL's divider/mux state. Therefore, we 

> don't

> - * require special clock ops that also configure the slave PLL 

> registers

> - */

> -static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm)

> -{

> -	char clk_name[32], parent[32], vco_name[32];

> -	char parent2[32], parent3[32], parent4[32];

> -	struct clk_init_data vco_init = {

> -		.parent_names = (const char *[]){ "bi_tcxo" },

> -		.num_parents = 1,

> -		.name = vco_name,

> -		.flags = CLK_IGNORE_UNUSED,

> -		.ops = &clk_ops_dsi_pll_7nm_vco,

> -	};

> -	struct device *dev = &pll_7nm->pdev->dev;

> -	struct clk_hw_onecell_data *hw_data;

> -	struct clk_hw *hw;

> -	int ret;

> -

> -	DBG("DSI%d", pll_7nm->id);

> -

> -	hw_data = devm_kzalloc(dev, sizeof(*hw_data) +

> -			       NUM_PROVIDED_CLKS * sizeof(struct clk_hw *),

> -			       GFP_KERNEL);

> -	if (!hw_data)

> -		return -ENOMEM;

> -

> -	snprintf(vco_name, 32, "dsi%dvco_clk", pll_7nm->id);

> -	pll_7nm->base.clk_hw.init = &vco_init;

> -

> -	ret = clk_hw_register(dev, &pll_7nm->base.clk_hw);

> -	if (ret)

> -		return ret;

> -

> -	snprintf(clk_name, 32, "dsi%d_pll_out_div_clk", pll_7nm->id);

> -	snprintf(parent, 32, "dsi%dvco_clk", pll_7nm->id);

> -

> -	hw = clk_hw_register_divider(dev, clk_name,

> -				     parent, CLK_SET_RATE_PARENT,

> -				     pll_7nm->mmio +

> -				     REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE,

> -				     0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL);

> -	if (IS_ERR(hw)) {

> -		ret = PTR_ERR(hw);

> -		goto err_base_clk_hw;

> -	}

> -

> -	pll_7nm->out_div_clk_hw = hw;

> -

> -	snprintf(clk_name, 32, "dsi%d_pll_bit_clk", pll_7nm->id);

> -	snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_7nm->id);

> -

> -	/* BIT CLK: DIV_CTRL_3_0 */

> -	hw = clk_hw_register_divider(dev, clk_name, parent,

> -				     CLK_SET_RATE_PARENT,

> -				     pll_7nm->phy_cmn_mmio +

> -				     REG_DSI_7nm_PHY_CMN_CLK_CFG0,

> -				     0, 4, CLK_DIVIDER_ONE_BASED,

> -				     &pll_7nm->postdiv_lock);

> -	if (IS_ERR(hw)) {

> -		ret = PTR_ERR(hw);

> -		goto err_out_div_clk_hw;

> -	}

> -

> -	pll_7nm->bit_clk_hw = hw;

> -

> -	snprintf(clk_name, 32, "dsi%d_phy_pll_out_byteclk", pll_7nm->id);

> -	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->id);

> -

> -	/* DSI Byte clock = VCO_CLK / OUT_DIV / BIT_DIV / 8 */

> -	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,

> -					  CLK_SET_RATE_PARENT, 1, 8);

> -	if (IS_ERR(hw)) {

> -		ret = PTR_ERR(hw);

> -		goto err_bit_clk_hw;

> -	}

> -

> -	pll_7nm->byte_clk_hw = hw;

> -	hw_data->hws[DSI_BYTE_PLL_CLK] = hw;

> -

> -	snprintf(clk_name, 32, "dsi%d_pll_by_2_bit_clk", pll_7nm->id);

> -	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->id);

> -

> -	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,

> -					  0, 1, 2);

> -	if (IS_ERR(hw)) {

> -		ret = PTR_ERR(hw);

> -		goto err_byte_clk_hw;

> -	}

> -

> -	pll_7nm->by_2_bit_clk_hw = hw;

> -

> -	snprintf(clk_name, 32, "dsi%d_pll_post_out_div_clk", pll_7nm->id);

> -	snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_7nm->id);

> -

> -	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,

> -					  0, 1, 4);

> -	if (IS_ERR(hw)) {

> -		ret = PTR_ERR(hw);

> -		goto err_by_2_bit_clk_hw;

> -	}

> -

> -	pll_7nm->post_out_div_clk_hw = hw;

> -

> -	snprintf(clk_name, 32, "dsi%d_pclk_mux", pll_7nm->id);

> -	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->id);

> -	snprintf(parent2, 32, "dsi%d_pll_by_2_bit_clk", pll_7nm->id);

> -	snprintf(parent3, 32, "dsi%d_pll_out_div_clk", pll_7nm->id);

> -	snprintf(parent4, 32, "dsi%d_pll_post_out_div_clk", pll_7nm->id);

> -

> -	hw = clk_hw_register_mux(dev, clk_name,

> -				 ((const char *[]){

> -				 parent, parent2, parent3, parent4

> -				 }), 4, 0, pll_7nm->phy_cmn_mmio +

> -				 REG_DSI_7nm_PHY_CMN_CLK_CFG1,

> -				 0, 2, 0, NULL);

> -	if (IS_ERR(hw)) {

> -		ret = PTR_ERR(hw);

> -		goto err_post_out_div_clk_hw;

> -	}

> -

> -	pll_7nm->pclk_mux_hw = hw;

> -

> -	snprintf(clk_name, 32, "dsi%d_phy_pll_out_dsiclk", pll_7nm->id);

> -	snprintf(parent, 32, "dsi%d_pclk_mux", pll_7nm->id);

> -

> -	/* PIX CLK DIV : DIV_CTRL_7_4*/

> -	hw = clk_hw_register_divider(dev, clk_name, parent,

> -				     0, pll_7nm->phy_cmn_mmio +

> -					REG_DSI_7nm_PHY_CMN_CLK_CFG0,

> -				     4, 4, CLK_DIVIDER_ONE_BASED,

> -				     &pll_7nm->postdiv_lock);

> -	if (IS_ERR(hw)) {

> -		ret = PTR_ERR(hw);

> -		goto err_pclk_mux_hw;

> -	}

> -

> -	pll_7nm->out_dsiclk_hw = hw;

> -	hw_data->hws[DSI_PIXEL_PLL_CLK] = hw;

> -

> -	hw_data->num = NUM_PROVIDED_CLKS;

> -	pll_7nm->hw_data = hw_data;

> -

> -	ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,

> -				     pll_7nm->hw_data);

> -	if (ret) {

> -		DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret);

> -		goto err_dsiclk_hw;

> -	}

> -

> -	return 0;

> -

> -err_dsiclk_hw:

> -	clk_hw_unregister_divider(pll_7nm->out_dsiclk_hw);

> -err_pclk_mux_hw:

> -	clk_hw_unregister_mux(pll_7nm->pclk_mux_hw);

> -err_post_out_div_clk_hw:

> -	clk_hw_unregister_fixed_factor(pll_7nm->post_out_div_clk_hw);

> -err_by_2_bit_clk_hw:

> -	clk_hw_unregister_fixed_factor(pll_7nm->by_2_bit_clk_hw);

> -err_byte_clk_hw:

> -	clk_hw_unregister_fixed_factor(pll_7nm->byte_clk_hw);

> -err_bit_clk_hw:

> -	clk_hw_unregister_divider(pll_7nm->bit_clk_hw);

> -err_out_div_clk_hw:

> -	clk_hw_unregister_divider(pll_7nm->out_div_clk_hw);

> -err_base_clk_hw:

> -	clk_hw_unregister(&pll_7nm->base.clk_hw);

> -

> -	return ret;

> -}

> -

> -struct msm_dsi_pll *msm_dsi_pll_7nm_init(struct platform_device *pdev,

> -					enum msm_dsi_phy_type type, int id)

> -{

> -	struct dsi_pll_7nm *pll_7nm;

> -	struct msm_dsi_pll *pll;

> -	int ret;

> -

> -	pll_7nm = devm_kzalloc(&pdev->dev, sizeof(*pll_7nm), GFP_KERNEL);

> -	if (!pll_7nm)

> -		return ERR_PTR(-ENOMEM);

> -

> -	DBG("DSI PLL%d", id);

> -

> -	pll_7nm->pdev = pdev;

> -	pll_7nm->id = id;

> -	pll_7nm_list[id] = pll_7nm;

> -

> -	pll_7nm->phy_cmn_mmio = msm_ioremap(pdev, "dsi_phy", "DSI_PHY");

> -	if (IS_ERR_OR_NULL(pll_7nm->phy_cmn_mmio)) {

> -		DRM_DEV_ERROR(&pdev->dev, "failed to map CMN PHY base\n");

> -		return ERR_PTR(-ENOMEM);

> -	}

> -

> -	pll_7nm->mmio = msm_ioremap(pdev, "dsi_pll", "DSI_PLL");

> -	if (IS_ERR_OR_NULL(pll_7nm->mmio)) {

> -		DRM_DEV_ERROR(&pdev->dev, "failed to map PLL base\n");

> -		return ERR_PTR(-ENOMEM);

> -	}

> -

> -	spin_lock_init(&pll_7nm->postdiv_lock);

> -

> -	pll = &pll_7nm->base;

> -	pll->min_rate = 1000000000UL;

> -	pll->max_rate = 3500000000UL;

> -	if (type == MSM_DSI_PHY_7NM_V4_1) {

> -		pll->min_rate = 600000000UL;

> -		pll->max_rate = (unsigned long)5000000000ULL;

> -		/* workaround for max rate overflowing on 32-bit builds: */

> -		pll->max_rate = max(pll->max_rate, 0xffffffffUL);

> -	}

> -	pll->get_provider = dsi_pll_7nm_get_provider;

> -	pll->destroy = dsi_pll_7nm_destroy;

> -	pll->save_state = dsi_pll_7nm_save_state;

> -	pll->restore_state = dsi_pll_7nm_restore_state;

> -	pll->set_usecase = dsi_pll_7nm_set_usecase;

> -

> -	pll_7nm->vco_delay = 1;

> -

> -	ret = pll_7nm_register(pll_7nm);

> -	if (ret) {

> -		DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret);

> -		return ERR_PTR(ret);

> -	}

> -

> -	/* TODO: Remove this when we have proper display handover support */

> -	msm_dsi_pll_save_state(pll);

> -

> -	return pll;

> -}

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Patch

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 3cc906121fb3..1be6996b80b7 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -136,13 +136,6 @@  msm-$(CONFIG_DRM_MSM_DSI_14NM_PHY) += dsi/phy/dsi_phy_14nm.o
 msm-$(CONFIG_DRM_MSM_DSI_10NM_PHY) += dsi/phy/dsi_phy_10nm.o
 msm-$(CONFIG_DRM_MSM_DSI_7NM_PHY) += dsi/phy/dsi_phy_7nm.o
 
-ifeq ($(CONFIG_DRM_MSM_DSI_PLL),y)
-msm-y += dsi/pll/dsi_pll.o
-msm-$(CONFIG_DRM_MSM_DSI_28NM_PHY) += dsi/pll/dsi_pll_28nm.o
-msm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/pll/dsi_pll_28nm_8960.o
-msm-$(CONFIG_DRM_MSM_DSI_14NM_PHY) += dsi/pll/dsi_pll_14nm.o
-msm-$(CONFIG_DRM_MSM_DSI_10NM_PHY) += dsi/pll/dsi_pll_10nm.o
-msm-$(CONFIG_DRM_MSM_DSI_7NM_PHY) += dsi/pll/dsi_pll_7nm.o
-endif
+msm-$(CONFIG_DRM_MSM_DSI_PLL) += dsi/phy/dsi_pll.o
 
 obj-$(CONFIG_DRM_MSM)	+= msm.o
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c
index 655fa17a0452..5da369b5c475 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c
@@ -3,11 +3,884 @@ 
  * Copyright (c) 2018, The Linux Foundation
  */
 
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/iopoll.h>
 
+#include "dsi_pll.h"
 #include "dsi_phy.h"
 #include "dsi.xml.h"
 
+/*
+ * DSI PLL 10nm - clock diagram (eg: DSI0):
+ *
+ *           dsi0_pll_out_div_clk  dsi0_pll_bit_clk
+ *                              |                |
+ *                              |                |
+ *                 +---------+  |  +----------+  |  +----+
+ *  dsi0vco_clk ---| out_div |--o--| divl_3_0 |--o--| /8 |-- dsi0_phy_pll_out_byteclk
+ *                 +---------+  |  +----------+  |  +----+
+ *                              |                |
+ *                              |                |         dsi0_pll_by_2_bit_clk
+ *                              |                |          |
+ *                              |                |  +----+  |  |\  dsi0_pclk_mux
+ *                              |                |--| /2 |--o--| \   |
+ *                              |                |  +----+     |  \  |  +---------+
+ *                              |                --------------|  |--o--| div_7_4 |-- dsi0_phy_pll_out_dsiclk
+ *                              |------------------------------|  /     +---------+
+ *                              |          +-----+             | /
+ *                              -----------| /4? |--o----------|/
+ *                                         +-----+  |           |
+ *                                                  |           |dsiclk_sel
+ *                                                  |
+ *                                                  dsi0_pll_post_out_div_clk
+ */
+
+#define DSI_BYTE_PLL_CLK		0
+#define DSI_PIXEL_PLL_CLK		1
+#define NUM_PROVIDED_CLKS		2
+
+#define VCO_REF_CLK_RATE		19200000
+
+struct dsi_pll_regs {
+	u32 pll_prop_gain_rate;
+	u32 pll_lockdet_rate;
+	u32 decimal_div_start;
+	u32 frac_div_start_low;
+	u32 frac_div_start_mid;
+	u32 frac_div_start_high;
+	u32 pll_clock_inverters;
+	u32 ssc_stepsize_low;
+	u32 ssc_stepsize_high;
+	u32 ssc_div_per_low;
+	u32 ssc_div_per_high;
+	u32 ssc_adjper_low;
+	u32 ssc_adjper_high;
+	u32 ssc_control;
+};
+
+struct dsi_pll_config {
+	u32 ref_freq;
+	bool div_override;
+	u32 output_div;
+	bool ignore_frac;
+	bool disable_prescaler;
+	bool enable_ssc;
+	bool ssc_center;
+	u32 dec_bits;
+	u32 frac_bits;
+	u32 lock_timer;
+	u32 ssc_freq;
+	u32 ssc_offset;
+	u32 ssc_adj_per;
+	u32 thresh_cycles;
+	u32 refclk_cycles;
+};
+
+struct pll_10nm_cached_state {
+	unsigned long vco_rate;
+	u8 bit_clk_div;
+	u8 pix_clk_div;
+	u8 pll_out_div;
+	u8 pll_mux;
+};
+
+struct dsi_pll_10nm {
+	struct msm_dsi_pll base;
+
+	int id;
+	struct platform_device *pdev;
+
+	void __iomem *phy_cmn_mmio;
+	void __iomem *mmio;
+
+	u64 vco_ref_clk_rate;
+	u64 vco_current_rate;
+
+	/* protects REG_DSI_10nm_PHY_CMN_CLK_CFG0 register */
+	spinlock_t postdiv_lock;
+
+	int vco_delay;
+	struct dsi_pll_config pll_configuration;
+	struct dsi_pll_regs reg_setup;
+
+	/* private clocks: */
+	struct clk_hw *out_div_clk_hw;
+	struct clk_hw *bit_clk_hw;
+	struct clk_hw *byte_clk_hw;
+	struct clk_hw *by_2_bit_clk_hw;
+	struct clk_hw *post_out_div_clk_hw;
+	struct clk_hw *pclk_mux_hw;
+	struct clk_hw *out_dsiclk_hw;
+
+	/* clock-provider: */
+	struct clk_hw_onecell_data *hw_data;
+
+	struct pll_10nm_cached_state cached_state;
+
+	enum msm_dsi_phy_usecase uc;
+	struct dsi_pll_10nm *slave;
+};
+
+#define to_pll_10nm(x)	container_of(x, struct dsi_pll_10nm, base)
+
+/*
+ * Global list of private DSI PLL struct pointers. We need this for Dual DSI
+ * mode, where the master PLL's clk_ops needs access the slave's private data
+ */
+static struct dsi_pll_10nm *pll_10nm_list[DSI_MAX];
+
+static void dsi_pll_setup_config(struct dsi_pll_10nm *pll)
+{
+	struct dsi_pll_config *config = &pll->pll_configuration;
+
+	config->ref_freq = pll->vco_ref_clk_rate;
+	config->output_div = 1;
+	config->dec_bits = 8;
+	config->frac_bits = 18;
+	config->lock_timer = 64;
+	config->ssc_freq = 31500;
+	config->ssc_offset = 5000;
+	config->ssc_adj_per = 2;
+	config->thresh_cycles = 32;
+	config->refclk_cycles = 256;
+
+	config->div_override = false;
+	config->ignore_frac = false;
+	config->disable_prescaler = false;
+
+	config->enable_ssc = false;
+	config->ssc_center = 0;
+}
+
+static void dsi_pll_calc_dec_frac(struct dsi_pll_10nm *pll)
+{
+	struct dsi_pll_config *config = &pll->pll_configuration;
+	struct dsi_pll_regs *regs = &pll->reg_setup;
+	u64 fref = pll->vco_ref_clk_rate;
+	u64 pll_freq;
+	u64 divider;
+	u64 dec, dec_multiple;
+	u32 frac;
+	u64 multiplier;
+
+	pll_freq = pll->vco_current_rate;
+
+	if (config->disable_prescaler)
+		divider = fref;
+	else
+		divider = fref * 2;
+
+	multiplier = 1 << config->frac_bits;
+	dec_multiple = div_u64(pll_freq * multiplier, divider);
+	dec = div_u64_rem(dec_multiple, multiplier, &frac);
+
+	if (pll_freq <= 1900000000UL)
+		regs->pll_prop_gain_rate = 8;
+	else if (pll_freq <= 3000000000UL)
+		regs->pll_prop_gain_rate = 10;
+	else
+		regs->pll_prop_gain_rate = 12;
+	if (pll_freq < 1100000000UL)
+		regs->pll_clock_inverters = 8;
+	else
+		regs->pll_clock_inverters = 0;
+
+	regs->pll_lockdet_rate = config->lock_timer;
+	regs->decimal_div_start = dec;
+	regs->frac_div_start_low = (frac & 0xff);
+	regs->frac_div_start_mid = (frac & 0xff00) >> 8;
+	regs->frac_div_start_high = (frac & 0x30000) >> 16;
+}
+
+#define SSC_CENTER		BIT(0)
+#define SSC_EN			BIT(1)
+
+static void dsi_pll_calc_ssc(struct dsi_pll_10nm *pll)
+{
+	struct dsi_pll_config *config = &pll->pll_configuration;
+	struct dsi_pll_regs *regs = &pll->reg_setup;
+	u32 ssc_per;
+	u32 ssc_mod;
+	u64 ssc_step_size;
+	u64 frac;
+
+	if (!config->enable_ssc) {
+		DBG("SSC not enabled\n");
+		return;
+	}
+
+	ssc_per = DIV_ROUND_CLOSEST(config->ref_freq, config->ssc_freq) / 2 - 1;
+	ssc_mod = (ssc_per + 1) % (config->ssc_adj_per + 1);
+	ssc_per -= ssc_mod;
+
+	frac = regs->frac_div_start_low |
+			(regs->frac_div_start_mid << 8) |
+			(regs->frac_div_start_high << 16);
+	ssc_step_size = regs->decimal_div_start;
+	ssc_step_size *= (1 << config->frac_bits);
+	ssc_step_size += frac;
+	ssc_step_size *= config->ssc_offset;
+	ssc_step_size *= (config->ssc_adj_per + 1);
+	ssc_step_size = div_u64(ssc_step_size, (ssc_per + 1));
+	ssc_step_size = DIV_ROUND_CLOSEST_ULL(ssc_step_size, 1000000);
+
+	regs->ssc_div_per_low = ssc_per & 0xFF;
+	regs->ssc_div_per_high = (ssc_per & 0xFF00) >> 8;
+	regs->ssc_stepsize_low = (u32)(ssc_step_size & 0xFF);
+	regs->ssc_stepsize_high = (u32)((ssc_step_size & 0xFF00) >> 8);
+	regs->ssc_adjper_low = config->ssc_adj_per & 0xFF;
+	regs->ssc_adjper_high = (config->ssc_adj_per & 0xFF00) >> 8;
+
+	regs->ssc_control = config->ssc_center ? SSC_CENTER : 0;
+
+	pr_debug("SCC: Dec:%d, frac:%llu, frac_bits:%d\n",
+		 regs->decimal_div_start, frac, config->frac_bits);
+	pr_debug("SSC: div_per:0x%X, stepsize:0x%X, adjper:0x%X\n",
+		 ssc_per, (u32)ssc_step_size, config->ssc_adj_per);
+}
+
+static void dsi_pll_ssc_commit(struct dsi_pll_10nm *pll)
+{
+	void __iomem *base = pll->mmio;
+	struct dsi_pll_regs *regs = &pll->reg_setup;
+
+	if (pll->pll_configuration.enable_ssc) {
+		pr_debug("SSC is enabled\n");
+
+		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_STEPSIZE_LOW_1,
+			  regs->ssc_stepsize_low);
+		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_STEPSIZE_HIGH_1,
+			  regs->ssc_stepsize_high);
+		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_DIV_PER_LOW_1,
+			  regs->ssc_div_per_low);
+		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_DIV_PER_HIGH_1,
+			  regs->ssc_div_per_high);
+		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_DIV_ADJPER_LOW_1,
+			  regs->ssc_adjper_low);
+		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_DIV_ADJPER_HIGH_1,
+			  regs->ssc_adjper_high);
+		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_CONTROL,
+			  SSC_EN | regs->ssc_control);
+	}
+}
+
+static void dsi_pll_config_hzindep_reg(struct dsi_pll_10nm *pll)
+{
+	void __iomem *base = pll->mmio;
+
+	pll_write(base + REG_DSI_10nm_PHY_PLL_ANALOG_CONTROLS_ONE, 0x80);
+	pll_write(base + REG_DSI_10nm_PHY_PLL_ANALOG_CONTROLS_TWO, 0x03);
+	pll_write(base + REG_DSI_10nm_PHY_PLL_ANALOG_CONTROLS_THREE, 0x00);
+	pll_write(base + REG_DSI_10nm_PHY_PLL_DSM_DIVIDER, 0x00);
+	pll_write(base + REG_DSI_10nm_PHY_PLL_FEEDBACK_DIVIDER, 0x4e);
+	pll_write(base + REG_DSI_10nm_PHY_PLL_CALIBRATION_SETTINGS, 0x40);
+	pll_write(base + REG_DSI_10nm_PHY_PLL_BAND_SEL_CAL_SETTINGS_THREE,
+		  0xba);
+	pll_write(base + REG_DSI_10nm_PHY_PLL_FREQ_DETECT_SETTINGS_ONE, 0x0c);
+	pll_write(base + REG_DSI_10nm_PHY_PLL_OUTDIV, 0x00);
+	pll_write(base + REG_DSI_10nm_PHY_PLL_CORE_OVERRIDE, 0x00);
+	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_DIGITAL_TIMERS_TWO, 0x08);
+	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_PROP_GAIN_RATE_1, 0x08);
+	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_BAND_SET_RATE_1, 0xc0);
+	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_1, 0xfa);
+	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_FL_INT_GAIN_PFILT_BAND_1,
+		  0x4c);
+	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_LOCK_OVERRIDE, 0x80);
+	pll_write(base + REG_DSI_10nm_PHY_PLL_PFILT, 0x29);
+	pll_write(base + REG_DSI_10nm_PHY_PLL_IFILT, 0x3f);
+}
+
+static void dsi_pll_commit(struct dsi_pll_10nm *pll)
+{
+	void __iomem *base = pll->mmio;
+	struct dsi_pll_regs *reg = &pll->reg_setup;
+
+	pll_write(base + REG_DSI_10nm_PHY_PLL_CORE_INPUT_OVERRIDE, 0x12);
+	pll_write(base + REG_DSI_10nm_PHY_PLL_DECIMAL_DIV_START_1,
+		  reg->decimal_div_start);
+	pll_write(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_LOW_1,
+		  reg->frac_div_start_low);
+	pll_write(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_MID_1,
+		  reg->frac_div_start_mid);
+	pll_write(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_HIGH_1,
+		  reg->frac_div_start_high);
+	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_LOCKDET_RATE_1,
+		  reg->pll_lockdet_rate);
+	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_LOCK_DELAY, 0x06);
+	pll_write(base + REG_DSI_10nm_PHY_PLL_CMODE, 0x10);
+	pll_write(base + REG_DSI_10nm_PHY_PLL_CLOCK_INVERTERS,
+		  reg->pll_clock_inverters);
+}
+
+static int dsi_pll_10nm_vco_set_rate(struct clk_hw *hw, unsigned long rate,
+				     unsigned long parent_rate)
+{
+	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);
+
+	DBG("DSI PLL%d rate=%lu, parent's=%lu", pll_10nm->id, rate,
+	    parent_rate);
+
+	pll_10nm->vco_current_rate = rate;
+	pll_10nm->vco_ref_clk_rate = VCO_REF_CLK_RATE;
+
+	dsi_pll_setup_config(pll_10nm);
+
+	dsi_pll_calc_dec_frac(pll_10nm);
+
+	dsi_pll_calc_ssc(pll_10nm);
+
+	dsi_pll_commit(pll_10nm);
+
+	dsi_pll_config_hzindep_reg(pll_10nm);
+
+	dsi_pll_ssc_commit(pll_10nm);
+
+	/* flush, ensure all register writes are done*/
+	wmb();
+
+	return 0;
+}
+
+static int dsi_pll_10nm_lock_status(struct dsi_pll_10nm *pll)
+{
+	struct device *dev = &pll->pdev->dev;
+	int rc;
+	u32 status = 0;
+	u32 const delay_us = 100;
+	u32 const timeout_us = 5000;
+
+	rc = readl_poll_timeout_atomic(pll->mmio +
+				       REG_DSI_10nm_PHY_PLL_COMMON_STATUS_ONE,
+				       status,
+				       ((status & BIT(0)) > 0),
+				       delay_us,
+				       timeout_us);
+	if (rc)
+		DRM_DEV_ERROR(dev, "DSI PLL(%d) lock failed, status=0x%08x\n",
+			      pll->id, status);
+
+	return rc;
+}
+
+static void dsi_pll_disable_pll_bias(struct dsi_pll_10nm *pll)
+{
+	u32 data = pll_read(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CTRL_0);
+
+	pll_write(pll->mmio + REG_DSI_10nm_PHY_PLL_SYSTEM_MUXES, 0);
+	pll_write(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CTRL_0,
+		  data & ~BIT(5));
+	ndelay(250);
+}
+
+static void dsi_pll_enable_pll_bias(struct dsi_pll_10nm *pll)
+{
+	u32 data = pll_read(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CTRL_0);
+
+	pll_write(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CTRL_0,
+		  data | BIT(5));
+	pll_write(pll->mmio + REG_DSI_10nm_PHY_PLL_SYSTEM_MUXES, 0xc0);
+	ndelay(250);
+}
+
+static void dsi_pll_disable_global_clk(struct dsi_pll_10nm *pll)
+{
+	u32 data;
+
+	data = pll_read(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CLK_CFG1);
+	pll_write(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CLK_CFG1,
+		  data & ~BIT(5));
+}
+
+static void dsi_pll_enable_global_clk(struct dsi_pll_10nm *pll)
+{
+	u32 data;
+
+	data = pll_read(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CLK_CFG1);
+	pll_write(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CLK_CFG1,
+		  data | BIT(5));
+}
+
+static int dsi_pll_10nm_vco_prepare(struct clk_hw *hw)
+{
+	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);
+	struct device *dev = &pll_10nm->pdev->dev;
+	int rc;
+
+	dsi_pll_enable_pll_bias(pll_10nm);
+	if (pll_10nm->slave)
+		dsi_pll_enable_pll_bias(pll_10nm->slave);
+
+	rc = dsi_pll_10nm_vco_set_rate(hw,pll_10nm->vco_current_rate, 0);
+	if (rc) {
+		DRM_DEV_ERROR(dev, "vco_set_rate failed, rc=%d\n", rc);
+		return rc;
+	}
+
+	/* Start PLL */
+	pll_write(pll_10nm->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_PLL_CNTRL,
+		  0x01);
+
+	/*
+	 * ensure all PLL configurations are written prior to checking
+	 * for PLL lock.
+	 */
+	wmb();
+
+	/* Check for PLL lock */
+	rc = dsi_pll_10nm_lock_status(pll_10nm);
+	if (rc) {
+		DRM_DEV_ERROR(dev, "PLL(%d) lock failed\n", pll_10nm->id);
+		goto error;
+	}
+
+	pll->pll_on = true;
+
+	dsi_pll_enable_global_clk(pll_10nm);
+	if (pll_10nm->slave)
+		dsi_pll_enable_global_clk(pll_10nm->slave);
+
+	pll_write(pll_10nm->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_RBUF_CTRL,
+		  0x01);
+	if (pll_10nm->slave)
+		pll_write(pll_10nm->slave->phy_cmn_mmio +
+			  REG_DSI_10nm_PHY_CMN_RBUF_CTRL, 0x01);
+
+error:
+	return rc;
+}
+
+static void dsi_pll_disable_sub(struct dsi_pll_10nm *pll)
+{
+	pll_write(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_RBUF_CTRL, 0);
+	dsi_pll_disable_pll_bias(pll);
+}
+
+static void dsi_pll_10nm_vco_unprepare(struct clk_hw *hw)
+{
+	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);
+
+	/*
+	 * To avoid any stray glitches while abruptly powering down the PLL
+	 * make sure to gate the clock using the clock enable bit before
+	 * powering down the PLL
+	 */
+	dsi_pll_disable_global_clk(pll_10nm);
+	pll_write(pll_10nm->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_PLL_CNTRL, 0);
+	dsi_pll_disable_sub(pll_10nm);
+	if (pll_10nm->slave) {
+		dsi_pll_disable_global_clk(pll_10nm->slave);
+		dsi_pll_disable_sub(pll_10nm->slave);
+	}
+	/* flush, ensure all register writes are done */
+	wmb();
+	pll->pll_on = false;
+}
+
+static unsigned long dsi_pll_10nm_vco_recalc_rate(struct clk_hw *hw,
+						  unsigned long parent_rate)
+{
+	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);
+	struct dsi_pll_config *config = &pll_10nm->pll_configuration;
+	void __iomem *base = pll_10nm->mmio;
+	u64 ref_clk = pll_10nm->vco_ref_clk_rate;
+	u64 vco_rate = 0x0;
+	u64 multiplier;
+	u32 frac;
+	u32 dec;
+	u64 pll_freq, tmp64;
+
+	dec = pll_read(base + REG_DSI_10nm_PHY_PLL_DECIMAL_DIV_START_1);
+	dec &= 0xff;
+
+	frac = pll_read(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_LOW_1);
+	frac |= ((pll_read(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_MID_1) &
+		  0xff) << 8);
+	frac |= ((pll_read(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_HIGH_1) &
+		  0x3) << 16);
+
+	/*
+	 * TODO:
+	 *	1. Assumes prescaler is disabled
+	 */
+	multiplier = 1 << config->frac_bits;
+	pll_freq = dec * (ref_clk * 2);
+	tmp64 = (ref_clk * 2 * frac);
+	pll_freq += div_u64(tmp64, multiplier);
+
+	vco_rate = pll_freq;
+
+	DBG("DSI PLL%d returning vco rate = %lu, dec = %x, frac = %x",
+	    pll_10nm->id, (unsigned long)vco_rate, dec, frac);
+
+	return (unsigned long)vco_rate;
+}
+
+static const struct clk_ops clk_ops_dsi_pll_10nm_vco = {
+	.round_rate = msm_dsi_pll_helper_clk_round_rate,
+	.set_rate = dsi_pll_10nm_vco_set_rate,
+	.recalc_rate = dsi_pll_10nm_vco_recalc_rate,
+	.prepare = dsi_pll_10nm_vco_prepare,
+	.unprepare = dsi_pll_10nm_vco_unprepare,
+};
+
+/*
+ * PLL Callbacks
+ */
+
+static void dsi_pll_10nm_save_state(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);
+	struct pll_10nm_cached_state *cached = &pll_10nm->cached_state;
+	void __iomem *phy_base = pll_10nm->phy_cmn_mmio;
+	u32 cmn_clk_cfg0, cmn_clk_cfg1;
+
+	cached->pll_out_div = pll_read(pll_10nm->mmio +
+				       REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE);
+	cached->pll_out_div &= 0x3;
+
+	cmn_clk_cfg0 = pll_read(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG0);
+	cached->bit_clk_div = cmn_clk_cfg0 & 0xf;
+	cached->pix_clk_div = (cmn_clk_cfg0 & 0xf0) >> 4;
+
+	cmn_clk_cfg1 = pll_read(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG1);
+	cached->pll_mux = cmn_clk_cfg1 & 0x3;
+
+	DBG("DSI PLL%d outdiv %x bit_clk_div %x pix_clk_div %x pll_mux %x",
+	    pll_10nm->id, cached->pll_out_div, cached->bit_clk_div,
+	    cached->pix_clk_div, cached->pll_mux);
+}
+
+static int dsi_pll_10nm_restore_state(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);
+	struct pll_10nm_cached_state *cached = &pll_10nm->cached_state;
+	void __iomem *phy_base = pll_10nm->phy_cmn_mmio;
+	u32 val;
+	int ret;
+
+	val = pll_read(pll_10nm->mmio + REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE);
+	val &= ~0x3;
+	val |= cached->pll_out_div;
+	pll_write(pll_10nm->mmio + REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE, val);
+
+	pll_write(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG0,
+		  cached->bit_clk_div | (cached->pix_clk_div << 4));
+
+	val = pll_read(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG1);
+	val &= ~0x3;
+	val |= cached->pll_mux;
+	pll_write(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG1, val);
+
+	ret = dsi_pll_10nm_vco_set_rate(&pll->clk_hw, pll_10nm->vco_current_rate, pll_10nm->vco_ref_clk_rate);
+	if (ret) {
+		DRM_DEV_ERROR(&pll_10nm->pdev->dev,
+			"restore vco rate failed. ret=%d\n", ret);
+		return ret;
+	}
+
+	DBG("DSI PLL%d", pll_10nm->id);
+
+	return 0;
+}
+
+static int dsi_pll_10nm_set_usecase(struct msm_dsi_pll *pll,
+				    enum msm_dsi_phy_usecase uc)
+{
+	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);
+	void __iomem *base = pll_10nm->phy_cmn_mmio;
+	u32 data = 0x0;	/* internal PLL */
+
+	DBG("DSI PLL%d", pll_10nm->id);
+
+	switch (uc) {
+	case MSM_DSI_PHY_STANDALONE:
+		break;
+	case MSM_DSI_PHY_MASTER:
+		pll_10nm->slave = pll_10nm_list[(pll_10nm->id + 1) % DSI_MAX];
+		break;
+	case MSM_DSI_PHY_SLAVE:
+		data = 0x1; /* external PLL */
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* set PLL src */
+	pll_write(base + REG_DSI_10nm_PHY_CMN_CLK_CFG1, (data << 2));
+
+	pll_10nm->uc = uc;
+
+	return 0;
+}
+
+static int dsi_pll_10nm_get_provider(struct msm_dsi_pll *pll,
+				     struct clk **byte_clk_provider,
+				     struct clk **pixel_clk_provider)
+{
+	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);
+	struct clk_hw_onecell_data *hw_data = pll_10nm->hw_data;
+
+	DBG("DSI PLL%d", pll_10nm->id);
+
+	if (byte_clk_provider)
+		*byte_clk_provider = hw_data->hws[DSI_BYTE_PLL_CLK]->clk;
+	if (pixel_clk_provider)
+		*pixel_clk_provider = hw_data->hws[DSI_PIXEL_PLL_CLK]->clk;
+
+	return 0;
+}
+
+static void dsi_pll_10nm_destroy(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);
+	struct device *dev = &pll_10nm->pdev->dev;
+
+	DBG("DSI PLL%d", pll_10nm->id);
+	of_clk_del_provider(dev->of_node);
+
+	clk_hw_unregister_divider(pll_10nm->out_dsiclk_hw);
+	clk_hw_unregister_mux(pll_10nm->pclk_mux_hw);
+	clk_hw_unregister_fixed_factor(pll_10nm->post_out_div_clk_hw);
+	clk_hw_unregister_fixed_factor(pll_10nm->by_2_bit_clk_hw);
+	clk_hw_unregister_fixed_factor(pll_10nm->byte_clk_hw);
+	clk_hw_unregister_divider(pll_10nm->bit_clk_hw);
+	clk_hw_unregister_divider(pll_10nm->out_div_clk_hw);
+	clk_hw_unregister(&pll_10nm->base.clk_hw);
+}
+
+/*
+ * The post dividers and mux clocks are created using the standard divider and
+ * mux API. Unlike the 14nm PHY, the slave PLL doesn't need its dividers/mux
+ * state to follow the master PLL's divider/mux state. Therefore, we don't
+ * require special clock ops that also configure the slave PLL registers
+ */
+static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm)
+{
+	char clk_name[32], parent[32], vco_name[32];
+	char parent2[32], parent3[32], parent4[32];
+	struct clk_init_data vco_init = {
+		.parent_names = (const char *[]){ "xo" },
+		.num_parents = 1,
+		.name = vco_name,
+		.flags = CLK_IGNORE_UNUSED,
+		.ops = &clk_ops_dsi_pll_10nm_vco,
+	};
+	struct device *dev = &pll_10nm->pdev->dev;
+	struct clk_hw_onecell_data *hw_data;
+	struct clk_hw *hw;
+	int ret;
+
+	DBG("DSI%d", pll_10nm->id);
+
+	hw_data = devm_kzalloc(dev, sizeof(*hw_data) +
+			       NUM_PROVIDED_CLKS * sizeof(struct clk_hw *),
+			       GFP_KERNEL);
+	if (!hw_data)
+		return -ENOMEM;
+
+	snprintf(vco_name, 32, "dsi%dvco_clk", pll_10nm->id);
+	pll_10nm->base.clk_hw.init = &vco_init;
+
+	ret = clk_hw_register(dev, &pll_10nm->base.clk_hw);
+	if (ret)
+		return ret;
+
+	snprintf(clk_name, 32, "dsi%d_pll_out_div_clk", pll_10nm->id);
+	snprintf(parent, 32, "dsi%dvco_clk", pll_10nm->id);
+
+	hw = clk_hw_register_divider(dev, clk_name,
+				     parent, CLK_SET_RATE_PARENT,
+				     pll_10nm->mmio +
+				     REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE,
+				     0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL);
+	if (IS_ERR(hw)) {
+		ret = PTR_ERR(hw);
+		goto err_base_clk_hw;
+	}
+
+	pll_10nm->out_div_clk_hw = hw;
+
+	snprintf(clk_name, 32, "dsi%d_pll_bit_clk", pll_10nm->id);
+	snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_10nm->id);
+
+	/* BIT CLK: DIV_CTRL_3_0 */
+	hw = clk_hw_register_divider(dev, clk_name, parent,
+				     CLK_SET_RATE_PARENT,
+				     pll_10nm->phy_cmn_mmio +
+				     REG_DSI_10nm_PHY_CMN_CLK_CFG0,
+				     0, 4, CLK_DIVIDER_ONE_BASED,
+				     &pll_10nm->postdiv_lock);
+	if (IS_ERR(hw)) {
+		ret = PTR_ERR(hw);
+		goto err_out_div_clk_hw;
+	}
+
+	pll_10nm->bit_clk_hw = hw;
+
+	snprintf(clk_name, 32, "dsi%d_phy_pll_out_byteclk", pll_10nm->id);
+	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_10nm->id);
+
+	/* DSI Byte clock = VCO_CLK / OUT_DIV / BIT_DIV / 8 */
+	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,
+					  CLK_SET_RATE_PARENT, 1, 8);
+	if (IS_ERR(hw)) {
+		ret = PTR_ERR(hw);
+		goto err_bit_clk_hw;
+	}
+
+	pll_10nm->byte_clk_hw = hw;
+	hw_data->hws[DSI_BYTE_PLL_CLK] = hw;
+
+	snprintf(clk_name, 32, "dsi%d_pll_by_2_bit_clk", pll_10nm->id);
+	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_10nm->id);
+
+	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,
+					  0, 1, 2);
+	if (IS_ERR(hw)) {
+		ret = PTR_ERR(hw);
+		goto err_byte_clk_hw;
+	}
+
+	pll_10nm->by_2_bit_clk_hw = hw;
+
+	snprintf(clk_name, 32, "dsi%d_pll_post_out_div_clk", pll_10nm->id);
+	snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_10nm->id);
+
+	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,
+					  0, 1, 4);
+	if (IS_ERR(hw)) {
+		ret = PTR_ERR(hw);
+		goto err_by_2_bit_clk_hw;
+	}
+
+	pll_10nm->post_out_div_clk_hw = hw;
+
+	snprintf(clk_name, 32, "dsi%d_pclk_mux", pll_10nm->id);
+	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_10nm->id);
+	snprintf(parent2, 32, "dsi%d_pll_by_2_bit_clk", pll_10nm->id);
+	snprintf(parent3, 32, "dsi%d_pll_out_div_clk", pll_10nm->id);
+	snprintf(parent4, 32, "dsi%d_pll_post_out_div_clk", pll_10nm->id);
+
+	hw = clk_hw_register_mux(dev, clk_name,
+				 ((const char *[]){
+				 parent, parent2, parent3, parent4
+				 }), 4, 0, pll_10nm->phy_cmn_mmio +
+				 REG_DSI_10nm_PHY_CMN_CLK_CFG1,
+				 0, 2, 0, NULL);
+	if (IS_ERR(hw)) {
+		ret = PTR_ERR(hw);
+		goto err_post_out_div_clk_hw;
+	}
+
+	pll_10nm->pclk_mux_hw = hw;
+
+	snprintf(clk_name, 32, "dsi%d_phy_pll_out_dsiclk", pll_10nm->id);
+	snprintf(parent, 32, "dsi%d_pclk_mux", pll_10nm->id);
+
+	/* PIX CLK DIV : DIV_CTRL_7_4*/
+	hw = clk_hw_register_divider(dev, clk_name, parent,
+				     0, pll_10nm->phy_cmn_mmio +
+					REG_DSI_10nm_PHY_CMN_CLK_CFG0,
+				     4, 4, CLK_DIVIDER_ONE_BASED,
+				     &pll_10nm->postdiv_lock);
+	if (IS_ERR(hw)) {
+		ret = PTR_ERR(hw);
+		goto err_pclk_mux_hw;
+	}
+
+	pll_10nm->out_dsiclk_hw = hw;
+	hw_data->hws[DSI_PIXEL_PLL_CLK] = hw;
+
+	hw_data->num = NUM_PROVIDED_CLKS;
+	pll_10nm->hw_data = hw_data;
+
+	ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
+				     pll_10nm->hw_data);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret);
+		goto err_dsiclk_hw;
+	}
+
+	return 0;
+
+err_dsiclk_hw:
+	clk_hw_unregister_divider(pll_10nm->out_dsiclk_hw);
+err_pclk_mux_hw:
+	clk_hw_unregister_mux(pll_10nm->pclk_mux_hw);
+err_post_out_div_clk_hw:
+	clk_hw_unregister_fixed_factor(pll_10nm->post_out_div_clk_hw);
+err_by_2_bit_clk_hw:
+	clk_hw_unregister_fixed_factor(pll_10nm->by_2_bit_clk_hw);
+err_byte_clk_hw:
+	clk_hw_unregister_fixed_factor(pll_10nm->byte_clk_hw);
+err_bit_clk_hw:
+	clk_hw_unregister_divider(pll_10nm->bit_clk_hw);
+err_out_div_clk_hw:
+	clk_hw_unregister_divider(pll_10nm->out_div_clk_hw);
+err_base_clk_hw:
+	clk_hw_unregister(&pll_10nm->base.clk_hw);
+
+	return ret;
+}
+
+struct msm_dsi_pll *msm_dsi_pll_10nm_init(struct platform_device *pdev, int id)
+{
+	struct dsi_pll_10nm *pll_10nm;
+	struct msm_dsi_pll *pll;
+	int ret;
+
+	pll_10nm = devm_kzalloc(&pdev->dev, sizeof(*pll_10nm), GFP_KERNEL);
+	if (!pll_10nm)
+		return ERR_PTR(-ENOMEM);
+
+	DBG("DSI PLL%d", id);
+
+	pll_10nm->pdev = pdev;
+	pll_10nm->id = id;
+	pll_10nm_list[id] = pll_10nm;
+
+	pll_10nm->phy_cmn_mmio = msm_ioremap(pdev, "dsi_phy", "DSI_PHY");
+	if (IS_ERR_OR_NULL(pll_10nm->phy_cmn_mmio)) {
+		DRM_DEV_ERROR(&pdev->dev, "failed to map CMN PHY base\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	pll_10nm->mmio = msm_ioremap(pdev, "dsi_pll", "DSI_PLL");
+	if (IS_ERR_OR_NULL(pll_10nm->mmio)) {
+		DRM_DEV_ERROR(&pdev->dev, "failed to map PLL base\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	spin_lock_init(&pll_10nm->postdiv_lock);
+
+	pll = &pll_10nm->base;
+	pll->min_rate = 1000000000UL;
+	pll->max_rate = 3500000000UL;
+	pll->get_provider = dsi_pll_10nm_get_provider;
+	pll->destroy = dsi_pll_10nm_destroy;
+	pll->save_state = dsi_pll_10nm_save_state;
+	pll->restore_state = dsi_pll_10nm_restore_state;
+	pll->set_usecase = dsi_pll_10nm_set_usecase;
+
+	pll_10nm->vco_delay = 1;
+
+	ret = pll_10nm_register(pll_10nm);
+	if (ret) {
+		DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret);
+		return ERR_PTR(ret);
+	}
+
+	/* TODO: Remove this when we have proper display handover support */
+	msm_dsi_pll_save_state(pll);
+
+	return pll;
+}
+
 static int dsi_phy_hw_v3_0_is_pll_on(struct msm_dsi_phy *phy)
 {
 	void __iomem *base = phy->base;
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c
index 6989730b5fbd..6a63901da7a4 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c
@@ -3,13 +3,1102 @@ 
  * Copyright (c) 2016, The Linux Foundation. All rights reserved.
  */
 
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/delay.h>
 
 #include "dsi_phy.h"
+#include "dsi_pll.h"
 #include "dsi.xml.h"
 
 #define PHY_14NM_CKLN_IDX	4
 
+/*
+ * DSI PLL 14nm - clock diagram (eg: DSI0):
+ *
+ *         dsi0n1_postdiv_clk
+ *                         |
+ *                         |
+ *                 +----+  |  +----+
+ *  dsi0vco_clk ---| n1 |--o--| /8 |-- dsi0pllbyte
+ *                 +----+  |  +----+
+ *                         |           dsi0n1_postdivby2_clk
+ *                         |   +----+  |
+ *                         o---| /2 |--o--|\
+ *                         |   +----+     | \   +----+
+ *                         |              |  |--| n2 |-- dsi0pll
+ *                         o--------------| /   +----+
+ *                                        |/
+ */
+
+#define POLL_MAX_READS			15
+#define POLL_TIMEOUT_US			1000
+
+#define NUM_PROVIDED_CLKS		2
+
+#define VCO_REF_CLK_RATE		19200000
+#define VCO_MIN_RATE			1300000000UL
+#define VCO_MAX_RATE			2600000000UL
+
+#define DSI_BYTE_PLL_CLK		0
+#define DSI_PIXEL_PLL_CLK		1
+
+#define DSI_PLL_DEFAULT_VCO_POSTDIV	1
+
+struct dsi_pll_input {
+	u32 fref;	/* reference clk */
+	u32 fdata;	/* bit clock rate */
+	u32 dsiclk_sel; /* Mux configuration (see diagram) */
+	u32 ssc_en;	/* SSC enable/disable */
+	u32 ldo_en;
+
+	/* fixed params */
+	u32 refclk_dbler_en;
+	u32 vco_measure_time;
+	u32 kvco_measure_time;
+	u32 bandgap_timer;
+	u32 pll_wakeup_timer;
+	u32 plllock_cnt;
+	u32 plllock_rng;
+	u32 ssc_center;
+	u32 ssc_adj_period;
+	u32 ssc_spread;
+	u32 ssc_freq;
+	u32 pll_ie_trim;
+	u32 pll_ip_trim;
+	u32 pll_iptat_trim;
+	u32 pll_cpcset_cur;
+	u32 pll_cpmset_cur;
+
+	u32 pll_icpmset;
+	u32 pll_icpcset;
+
+	u32 pll_icpmset_p;
+	u32 pll_icpmset_m;
+
+	u32 pll_icpcset_p;
+	u32 pll_icpcset_m;
+
+	u32 pll_lpf_res1;
+	u32 pll_lpf_cap1;
+	u32 pll_lpf_cap2;
+	u32 pll_c3ctrl;
+	u32 pll_r3ctrl;
+};
+
+struct dsi_pll_output {
+	u32 pll_txclk_en;
+	u32 dec_start;
+	u32 div_frac_start;
+	u32 ssc_period;
+	u32 ssc_step_size;
+	u32 plllock_cmp;
+	u32 pll_vco_div_ref;
+	u32 pll_vco_count;
+	u32 pll_kvco_div_ref;
+	u32 pll_kvco_count;
+	u32 pll_misc1;
+	u32 pll_lpf2_postdiv;
+	u32 pll_resetsm_cntrl;
+	u32 pll_resetsm_cntrl2;
+	u32 pll_resetsm_cntrl5;
+	u32 pll_kvco_code;
+
+	u32 cmn_clk_cfg0;
+	u32 cmn_clk_cfg1;
+	u32 cmn_ldo_cntrl;
+
+	u32 pll_postdiv;
+	u32 fcvo;
+};
+
+struct pll_14nm_cached_state {
+	unsigned long vco_rate;
+	u8 n2postdiv;
+	u8 n1postdiv;
+};
+
+struct dsi_pll_14nm {
+	struct msm_dsi_pll base;
+
+	int id;
+	struct platform_device *pdev;
+
+	void __iomem *phy_cmn_mmio;
+	void __iomem *mmio;
+
+	int vco_delay;
+
+	struct dsi_pll_input in;
+	struct dsi_pll_output out;
+
+	/* protects REG_DSI_14nm_PHY_CMN_CLK_CFG0 register */
+	spinlock_t postdiv_lock;
+
+	u64 vco_current_rate;
+	u64 vco_ref_clk_rate;
+
+	/* private clocks: */
+	struct clk_hw *hws[NUM_DSI_CLOCKS_MAX];
+	u32 num_hws;
+
+	/* clock-provider: */
+	struct clk_hw_onecell_data *hw_data;
+
+	struct pll_14nm_cached_state cached_state;
+
+	enum msm_dsi_phy_usecase uc;
+	struct dsi_pll_14nm *slave;
+};
+
+#define to_pll_14nm(x)	container_of(x, struct dsi_pll_14nm, base)
+
+/*
+ * Private struct for N1/N2 post-divider clocks. These clocks are similar to
+ * the generic clk_divider class of clocks. The only difference is that it
+ * also sets the slave DSI PLL's post-dividers if in Dual DSI mode
+ */
+struct dsi_pll_14nm_postdiv {
+	struct clk_hw hw;
+
+	/* divider params */
+	u8 shift;
+	u8 width;
+	u8 flags; /* same flags as used by clk_divider struct */
+
+	struct dsi_pll_14nm *pll;
+};
+
+#define to_pll_14nm_postdiv(_hw) container_of(_hw, struct dsi_pll_14nm_postdiv, hw)
+
+/*
+ * Global list of private DSI PLL struct pointers. We need this for Dual DSI
+ * mode, where the master PLL's clk_ops needs access the slave's private data
+ */
+static struct dsi_pll_14nm *pll_14nm_list[DSI_MAX];
+
+static bool pll_14nm_poll_for_ready(struct dsi_pll_14nm *pll_14nm,
+				    u32 nb_tries, u32 timeout_us)
+{
+	bool pll_locked = false;
+	void __iomem *base = pll_14nm->mmio;
+	u32 tries, val;
+
+	tries = nb_tries;
+	while (tries--) {
+		val = pll_read(base +
+			       REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS);
+		pll_locked = !!(val & BIT(5));
+
+		if (pll_locked)
+			break;
+
+		udelay(timeout_us);
+	}
+
+	if (!pll_locked) {
+		tries = nb_tries;
+		while (tries--) {
+			val = pll_read(base +
+				REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS);
+			pll_locked = !!(val & BIT(0));
+
+			if (pll_locked)
+				break;
+
+			udelay(timeout_us);
+		}
+	}
+
+	DBG("DSI PLL is %slocked", pll_locked ? "" : "*not* ");
+
+	return pll_locked;
+}
+
+static void dsi_pll_14nm_input_init(struct dsi_pll_14nm *pll)
+{
+	pll->in.fref = pll->vco_ref_clk_rate;
+	pll->in.fdata = 0;
+	pll->in.dsiclk_sel = 1;	/* Use the /2 path in Mux */
+	pll->in.ldo_en = 0;	/* disabled for now */
+
+	/* fixed input */
+	pll->in.refclk_dbler_en = 0;
+	pll->in.vco_measure_time = 5;
+	pll->in.kvco_measure_time = 5;
+	pll->in.bandgap_timer = 4;
+	pll->in.pll_wakeup_timer = 5;
+	pll->in.plllock_cnt = 1;
+	pll->in.plllock_rng = 0;
+
+	/*
+	 * SSC is enabled by default. We might need DT props for configuring
+	 * some SSC params like PPM and center/down spread etc.
+	 */
+	pll->in.ssc_en = 1;
+	pll->in.ssc_center = 0;		/* down spread by default */
+	pll->in.ssc_spread = 5;		/* PPM / 1000 */
+	pll->in.ssc_freq = 31500;	/* default recommended */
+	pll->in.ssc_adj_period = 37;
+
+	pll->in.pll_ie_trim = 4;
+	pll->in.pll_ip_trim = 4;
+	pll->in.pll_cpcset_cur = 1;
+	pll->in.pll_cpmset_cur = 1;
+	pll->in.pll_icpmset = 4;
+	pll->in.pll_icpcset = 4;
+	pll->in.pll_icpmset_p = 0;
+	pll->in.pll_icpmset_m = 0;
+	pll->in.pll_icpcset_p = 0;
+	pll->in.pll_icpcset_m = 0;
+	pll->in.pll_lpf_res1 = 3;
+	pll->in.pll_lpf_cap1 = 11;
+	pll->in.pll_lpf_cap2 = 1;
+	pll->in.pll_iptat_trim = 7;
+	pll->in.pll_c3ctrl = 2;
+	pll->in.pll_r3ctrl = 1;
+}
+
+#define CEIL(x, y)		(((x) + ((y) - 1)) / (y))
+
+static void pll_14nm_ssc_calc(struct dsi_pll_14nm *pll)
+{
+	u32 period, ssc_period;
+	u32 ref, rem;
+	u64 step_size;
+
+	DBG("vco=%lld ref=%lld", pll->vco_current_rate, pll->vco_ref_clk_rate);
+
+	ssc_period = pll->in.ssc_freq / 500;
+	period = (u32)pll->vco_ref_clk_rate / 1000;
+	ssc_period  = CEIL(period, ssc_period);
+	ssc_period -= 1;
+	pll->out.ssc_period = ssc_period;
+
+	DBG("ssc freq=%d spread=%d period=%d", pll->in.ssc_freq,
+	    pll->in.ssc_spread, pll->out.ssc_period);
+
+	step_size = (u32)pll->vco_current_rate;
+	ref = pll->vco_ref_clk_rate;
+	ref /= 1000;
+	step_size = div_u64(step_size, ref);
+	step_size <<= 20;
+	step_size = div_u64(step_size, 1000);
+	step_size *= pll->in.ssc_spread;
+	step_size = div_u64(step_size, 1000);
+	step_size *= (pll->in.ssc_adj_period + 1);
+
+	rem = 0;
+	step_size = div_u64_rem(step_size, ssc_period + 1, &rem);
+	if (rem)
+		step_size++;
+
+	DBG("step_size=%lld", step_size);
+
+	step_size &= 0x0ffff;	/* take lower 16 bits */
+
+	pll->out.ssc_step_size = step_size;
+}
+
+static void pll_14nm_dec_frac_calc(struct dsi_pll_14nm *pll)
+{
+	struct dsi_pll_input *pin = &pll->in;
+	struct dsi_pll_output *pout = &pll->out;
+	u64 multiplier = BIT(20);
+	u64 dec_start_multiple, dec_start, pll_comp_val;
+	u32 duration, div_frac_start;
+	u64 vco_clk_rate = pll->vco_current_rate;
+	u64 fref = pll->vco_ref_clk_rate;
+
+	DBG("vco_clk_rate=%lld ref_clk_rate=%lld", vco_clk_rate, fref);
+
+	dec_start_multiple = div_u64(vco_clk_rate * multiplier, fref);
+	div_u64_rem(dec_start_multiple, multiplier, &div_frac_start);
+
+	dec_start = div_u64(dec_start_multiple, multiplier);
+
+	pout->dec_start = (u32)dec_start;
+	pout->div_frac_start = div_frac_start;
+
+	if (pin->plllock_cnt == 0)
+		duration = 1024;
+	else if (pin->plllock_cnt == 1)
+		duration = 256;
+	else if (pin->plllock_cnt == 2)
+		duration = 128;
+	else
+		duration = 32;
+
+	pll_comp_val = duration * dec_start_multiple;
+	pll_comp_val = div_u64(pll_comp_val, multiplier);
+	do_div(pll_comp_val, 10);
+
+	pout->plllock_cmp = (u32)pll_comp_val;
+
+	pout->pll_txclk_en = 1;
+	pout->cmn_ldo_cntrl = 0x3c;
+}
+
+static u32 pll_14nm_kvco_slop(u32 vrate)
+{
+	u32 slop = 0;
+
+	if (vrate > VCO_MIN_RATE && vrate <= 1800000000UL)
+		slop =  600;
+	else if (vrate > 1800000000UL && vrate < 2300000000UL)
+		slop = 400;
+	else if (vrate > 2300000000UL && vrate < VCO_MAX_RATE)
+		slop = 280;
+
+	return slop;
+}
+
+static void pll_14nm_calc_vco_count(struct dsi_pll_14nm *pll)
+{
+	struct dsi_pll_input *pin = &pll->in;
+	struct dsi_pll_output *pout = &pll->out;
+	u64 vco_clk_rate = pll->vco_current_rate;
+	u64 fref = pll->vco_ref_clk_rate;
+	u64 data;
+	u32 cnt;
+
+	data = fref * pin->vco_measure_time;
+	do_div(data, 1000000);
+	data &= 0x03ff;	/* 10 bits */
+	data -= 2;
+	pout->pll_vco_div_ref = data;
+
+	data = div_u64(vco_clk_rate, 1000000);	/* unit is Mhz */
+	data *= pin->vco_measure_time;
+	do_div(data, 10);
+	pout->pll_vco_count = data;
+
+	data = fref * pin->kvco_measure_time;
+	do_div(data, 1000000);
+	data &= 0x03ff;	/* 10 bits */
+	data -= 1;
+	pout->pll_kvco_div_ref = data;
+
+	cnt = pll_14nm_kvco_slop(vco_clk_rate);
+	cnt *= 2;
+	cnt /= 100;
+	cnt *= pin->kvco_measure_time;
+	pout->pll_kvco_count = cnt;
+
+	pout->pll_misc1 = 16;
+	pout->pll_resetsm_cntrl = 48;
+	pout->pll_resetsm_cntrl2 = pin->bandgap_timer << 3;
+	pout->pll_resetsm_cntrl5 = pin->pll_wakeup_timer;
+	pout->pll_kvco_code = 0;
+}
+
+static void pll_db_commit_ssc(struct dsi_pll_14nm *pll)
+{
+	void __iomem *base = pll->mmio;
+	struct dsi_pll_input *pin = &pll->in;
+	struct dsi_pll_output *pout = &pll->out;
+	u8 data;
+
+	data = pin->ssc_adj_period;
+	data &= 0x0ff;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_ADJ_PER1, data);
+	data = (pin->ssc_adj_period >> 8);
+	data &= 0x03;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_ADJ_PER2, data);
+
+	data = pout->ssc_period;
+	data &= 0x0ff;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_PER1, data);
+	data = (pout->ssc_period >> 8);
+	data &= 0x0ff;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_PER2, data);
+
+	data = pout->ssc_step_size;
+	data &= 0x0ff;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_STEP_SIZE1, data);
+	data = (pout->ssc_step_size >> 8);
+	data &= 0x0ff;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_STEP_SIZE2, data);
+
+	data = (pin->ssc_center & 0x01);
+	data <<= 1;
+	data |= 0x01; /* enable */
+	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_EN_CENTER, data);
+
+	wmb();	/* make sure register committed */
+}
+
+static void pll_db_commit_common(struct dsi_pll_14nm *pll,
+				 struct dsi_pll_input *pin,
+				 struct dsi_pll_output *pout)
+{
+	void __iomem *base = pll->mmio;
+	u8 data;
+
+	/* confgiure the non frequency dependent pll registers */
+	data = 0;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_SYSCLK_EN_RESET, data);
+
+	data = pout->pll_txclk_en;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_TXCLK_EN, data);
+
+	data = pout->pll_resetsm_cntrl;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL, data);
+	data = pout->pll_resetsm_cntrl2;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL2, data);
+	data = pout->pll_resetsm_cntrl5;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL5, data);
+
+	data = pout->pll_vco_div_ref & 0xff;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_VCO_DIV_REF1, data);
+	data = (pout->pll_vco_div_ref >> 8) & 0x3;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_VCO_DIV_REF2, data);
+
+	data = pout->pll_kvco_div_ref & 0xff;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_KVCO_DIV_REF1, data);
+	data = (pout->pll_kvco_div_ref >> 8) & 0x3;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_KVCO_DIV_REF2, data);
+
+	data = pout->pll_misc1;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_MISC1, data);
+
+	data = pin->pll_ie_trim;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_IE_TRIM, data);
+
+	data = pin->pll_ip_trim;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_IP_TRIM, data);
+
+	data = pin->pll_cpmset_cur << 3 | pin->pll_cpcset_cur;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_CP_SET_CUR, data);
+
+	data = pin->pll_icpcset_p << 3 | pin->pll_icpcset_m;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_ICPCSET, data);
+
+	data = pin->pll_icpmset_p << 3 | pin->pll_icpcset_m;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_ICPMSET, data);
+
+	data = pin->pll_icpmset << 3 | pin->pll_icpcset;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_ICP_SET, data);
+
+	data = pin->pll_lpf_cap2 << 4 | pin->pll_lpf_cap1;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_LPF1, data);
+
+	data = pin->pll_iptat_trim;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_IPTAT_TRIM, data);
+
+	data = pin->pll_c3ctrl | pin->pll_r3ctrl << 4;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_CRCTRL, data);
+}
+
+static void pll_14nm_software_reset(struct dsi_pll_14nm *pll_14nm)
+{
+	void __iomem *cmn_base = pll_14nm->phy_cmn_mmio;
+
+	/* de assert pll start and apply pll sw reset */
+
+	/* stop pll */
+	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL, 0);
+
+	/* pll sw reset */
+	pll_write_udelay(cmn_base + REG_DSI_14nm_PHY_CMN_CTRL_1, 0x20, 10);
+	wmb();	/* make sure register committed */
+
+	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_CTRL_1, 0);
+	wmb();	/* make sure register committed */
+}
+
+static void pll_db_commit_14nm(struct dsi_pll_14nm *pll,
+			       struct dsi_pll_input *pin,
+			       struct dsi_pll_output *pout)
+{
+	void __iomem *base = pll->mmio;
+	void __iomem *cmn_base = pll->phy_cmn_mmio;
+	u8 data;
+
+	DBG("DSI%d PLL", pll->id);
+
+	data = pout->cmn_ldo_cntrl;
+	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_LDO_CNTRL, data);
+
+	pll_db_commit_common(pll, pin, pout);
+
+	pll_14nm_software_reset(pll);
+
+	data = pin->dsiclk_sel; /* set dsiclk_sel = 1  */
+	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_CLK_CFG1, data);
+
+	data = 0xff; /* data, clk, pll normal operation */
+	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_CTRL_0, data);
+
+	/* configure the frequency dependent pll registers */
+	data = pout->dec_start;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_DEC_START, data);
+
+	data = pout->div_frac_start & 0xff;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START1, data);
+	data = (pout->div_frac_start >> 8) & 0xff;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START2, data);
+	data = (pout->div_frac_start >> 16) & 0xf;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START3, data);
+
+	data = pout->plllock_cmp & 0xff;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP1, data);
+
+	data = (pout->plllock_cmp >> 8) & 0xff;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP2, data);
+
+	data = (pout->plllock_cmp >> 16) & 0x3;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP3, data);
+
+	data = pin->plllock_cnt << 1 | pin->plllock_rng << 3;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP_EN, data);
+
+	data = pout->pll_vco_count & 0xff;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_VCO_COUNT1, data);
+	data = (pout->pll_vco_count >> 8) & 0xff;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_VCO_COUNT2, data);
+
+	data = pout->pll_kvco_count & 0xff;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_KVCO_COUNT1, data);
+	data = (pout->pll_kvco_count >> 8) & 0x3;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_KVCO_COUNT2, data);
+
+	data = (pout->pll_postdiv - 1) << 4 | pin->pll_lpf_res1;
+	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_LPF2_POSTDIV, data);
+
+	if (pin->ssc_en)
+		pll_db_commit_ssc(pll);
+
+	wmb();	/* make sure register committed */
+}
+
+/*
+ * VCO clock Callbacks
+ */
+static int dsi_pll_14nm_vco_set_rate(struct clk_hw *hw, unsigned long rate,
+				     unsigned long parent_rate)
+{
+	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);
+	struct dsi_pll_input *pin = &pll_14nm->in;
+	struct dsi_pll_output *pout = &pll_14nm->out;
+
+	DBG("DSI PLL%d rate=%lu, parent's=%lu", pll_14nm->id, rate,
+	    parent_rate);
+
+	pll_14nm->vco_current_rate = rate;
+	pll_14nm->vco_ref_clk_rate = VCO_REF_CLK_RATE;
+
+	dsi_pll_14nm_input_init(pll_14nm);
+
+	/*
+	 * This configures the post divider internal to the VCO. It's
+	 * fixed to divide by 1 for now.
+	 *
+	 * tx_band = pll_postdiv.
+	 * 0: divided by 1
+	 * 1: divided by 2
+	 * 2: divided by 4
+	 * 3: divided by 8
+	 */
+	pout->pll_postdiv = DSI_PLL_DEFAULT_VCO_POSTDIV;
+
+	pll_14nm_dec_frac_calc(pll_14nm);
+
+	if (pin->ssc_en)
+		pll_14nm_ssc_calc(pll_14nm);
+
+	pll_14nm_calc_vco_count(pll_14nm);
+
+	/* commit the slave DSI PLL registers if we're master. Note that we
+	 * don't lock the slave PLL. We just ensure that the PLL/PHY registers
+	 * of the master and slave are identical
+	 */
+	if (pll_14nm->uc == MSM_DSI_PHY_MASTER) {
+		struct dsi_pll_14nm *pll_14nm_slave = pll_14nm->slave;
+
+		pll_db_commit_14nm(pll_14nm_slave, pin, pout);
+	}
+
+	pll_db_commit_14nm(pll_14nm, pin, pout);
+
+	return 0;
+}
+
+static unsigned long dsi_pll_14nm_vco_recalc_rate(struct clk_hw *hw,
+						  unsigned long parent_rate)
+{
+	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);
+	void __iomem *base = pll_14nm->mmio;
+	u64 vco_rate, multiplier = BIT(20);
+	u32 div_frac_start;
+	u32 dec_start;
+	u64 ref_clk = parent_rate;
+
+	dec_start = pll_read(base + REG_DSI_14nm_PHY_PLL_DEC_START);
+	dec_start &= 0x0ff;
+
+	DBG("dec_start = %x", dec_start);
+
+	div_frac_start = (pll_read(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START3)
+				& 0xf) << 16;
+	div_frac_start |= (pll_read(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START2)
+				& 0xff) << 8;
+	div_frac_start |= pll_read(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START1)
+				& 0xff;
+
+	DBG("div_frac_start = %x", div_frac_start);
+
+	vco_rate = ref_clk * dec_start;
+
+	vco_rate += ((ref_clk * div_frac_start) / multiplier);
+
+	/*
+	 * Recalculating the rate from dec_start and frac_start doesn't end up
+	 * the rate we originally set. Convert the freq to KHz, round it up and
+	 * convert it back to MHz.
+	 */
+	vco_rate = DIV_ROUND_UP_ULL(vco_rate, 1000) * 1000;
+
+	DBG("returning vco rate = %lu", (unsigned long)vco_rate);
+
+	return (unsigned long)vco_rate;
+}
+
+static const struct clk_ops clk_ops_dsi_pll_14nm_vco = {
+	.round_rate = msm_dsi_pll_helper_clk_round_rate,
+	.set_rate = dsi_pll_14nm_vco_set_rate,
+	.recalc_rate = dsi_pll_14nm_vco_recalc_rate,
+	.prepare = msm_dsi_pll_helper_clk_prepare,
+	.unprepare = msm_dsi_pll_helper_clk_unprepare,
+};
+
+/*
+ * N1 and N2 post-divider clock callbacks
+ */
+#define div_mask(width)	((1 << (width)) - 1)
+static unsigned long dsi_pll_14nm_postdiv_recalc_rate(struct clk_hw *hw,
+						      unsigned long parent_rate)
+{
+	struct dsi_pll_14nm_postdiv *postdiv = to_pll_14nm_postdiv(hw);
+	struct dsi_pll_14nm *pll_14nm = postdiv->pll;
+	void __iomem *base = pll_14nm->phy_cmn_mmio;
+	u8 shift = postdiv->shift;
+	u8 width = postdiv->width;
+	u32 val;
+
+	DBG("DSI%d PLL parent rate=%lu", pll_14nm->id, parent_rate);
+
+	val = pll_read(base + REG_DSI_14nm_PHY_CMN_CLK_CFG0) >> shift;
+	val &= div_mask(width);
+
+	return divider_recalc_rate(hw, parent_rate, val, NULL,
+				   postdiv->flags, width);
+}
+
+static long dsi_pll_14nm_postdiv_round_rate(struct clk_hw *hw,
+					    unsigned long rate,
+					    unsigned long *prate)
+{
+	struct dsi_pll_14nm_postdiv *postdiv = to_pll_14nm_postdiv(hw);
+	struct dsi_pll_14nm *pll_14nm = postdiv->pll;
+
+	DBG("DSI%d PLL parent rate=%lu", pll_14nm->id, rate);
+
+	return divider_round_rate(hw, rate, prate, NULL,
+				  postdiv->width,
+				  postdiv->flags);
+}
+
+static int dsi_pll_14nm_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
+					 unsigned long parent_rate)
+{
+	struct dsi_pll_14nm_postdiv *postdiv = to_pll_14nm_postdiv(hw);
+	struct dsi_pll_14nm *pll_14nm = postdiv->pll;
+	void __iomem *base = pll_14nm->phy_cmn_mmio;
+	spinlock_t *lock = &pll_14nm->postdiv_lock;
+	u8 shift = postdiv->shift;
+	u8 width = postdiv->width;
+	unsigned int value;
+	unsigned long flags = 0;
+	u32 val;
+
+	DBG("DSI%d PLL parent rate=%lu parent rate %lu", pll_14nm->id, rate,
+	    parent_rate);
+
+	value = divider_get_val(rate, parent_rate, NULL, postdiv->width,
+				postdiv->flags);
+
+	spin_lock_irqsave(lock, flags);
+
+	val = pll_read(base + REG_DSI_14nm_PHY_CMN_CLK_CFG0);
+	val &= ~(div_mask(width) << shift);
+
+	val |= value << shift;
+	pll_write(base + REG_DSI_14nm_PHY_CMN_CLK_CFG0, val);
+
+	/* If we're master in dual DSI mode, then the slave PLL's post-dividers
+	 * follow the master's post dividers
+	 */
+	if (pll_14nm->uc == MSM_DSI_PHY_MASTER) {
+		struct dsi_pll_14nm *pll_14nm_slave = pll_14nm->slave;
+		void __iomem *slave_base = pll_14nm_slave->phy_cmn_mmio;
+
+		pll_write(slave_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0, val);
+	}
+
+	spin_unlock_irqrestore(lock, flags);
+
+	return 0;
+}
+
+static const struct clk_ops clk_ops_dsi_pll_14nm_postdiv = {
+	.recalc_rate = dsi_pll_14nm_postdiv_recalc_rate,
+	.round_rate = dsi_pll_14nm_postdiv_round_rate,
+	.set_rate = dsi_pll_14nm_postdiv_set_rate,
+};
+
+/*
+ * PLL Callbacks
+ */
+
+static int dsi_pll_14nm_enable_seq(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);
+	void __iomem *base = pll_14nm->mmio;
+	void __iomem *cmn_base = pll_14nm->phy_cmn_mmio;
+	bool locked;
+
+	DBG("");
+
+	pll_write(base + REG_DSI_14nm_PHY_PLL_VREF_CFG1, 0x10);
+	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL, 1);
+
+	locked = pll_14nm_poll_for_ready(pll_14nm, POLL_MAX_READS,
+					 POLL_TIMEOUT_US);
+
+	if (unlikely(!locked))
+		DRM_DEV_ERROR(&pll_14nm->pdev->dev, "DSI PLL lock failed\n");
+	else
+		DBG("DSI PLL lock success");
+
+	return locked ? 0 : -EINVAL;
+}
+
+static void dsi_pll_14nm_disable_seq(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);
+	void __iomem *cmn_base = pll_14nm->phy_cmn_mmio;
+
+	DBG("");
+
+	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL, 0);
+}
+
+static void dsi_pll_14nm_save_state(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);
+	struct pll_14nm_cached_state *cached_state = &pll_14nm->cached_state;
+	void __iomem *cmn_base = pll_14nm->phy_cmn_mmio;
+	u32 data;
+
+	data = pll_read(cmn_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0);
+
+	cached_state->n1postdiv = data & 0xf;
+	cached_state->n2postdiv = (data >> 4) & 0xf;
+
+	DBG("DSI%d PLL save state %x %x", pll_14nm->id,
+	    cached_state->n1postdiv, cached_state->n2postdiv);
+
+	cached_state->vco_rate = clk_hw_get_rate(&pll->clk_hw);
+}
+
+static int dsi_pll_14nm_restore_state(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);
+	struct pll_14nm_cached_state *cached_state = &pll_14nm->cached_state;
+	void __iomem *cmn_base = pll_14nm->phy_cmn_mmio;
+	u32 data;
+	int ret;
+
+	ret = dsi_pll_14nm_vco_set_rate(&pll->clk_hw,
+					cached_state->vco_rate, 0);
+	if (ret) {
+		DRM_DEV_ERROR(&pll_14nm->pdev->dev,
+			"restore vco rate failed. ret=%d\n", ret);
+		return ret;
+	}
+
+	data = cached_state->n1postdiv | (cached_state->n2postdiv << 4);
+
+	DBG("DSI%d PLL restore state %x %x", pll_14nm->id,
+	    cached_state->n1postdiv, cached_state->n2postdiv);
+
+	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0, data);
+
+	/* also restore post-dividers for slave DSI PLL */
+	if (pll_14nm->uc == MSM_DSI_PHY_MASTER) {
+		struct dsi_pll_14nm *pll_14nm_slave = pll_14nm->slave;
+		void __iomem *slave_base = pll_14nm_slave->phy_cmn_mmio;
+
+		pll_write(slave_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0, data);
+	}
+
+	return 0;
+}
+
+static int dsi_pll_14nm_set_usecase(struct msm_dsi_pll *pll,
+				    enum msm_dsi_phy_usecase uc)
+{
+	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);
+	void __iomem *base = pll_14nm->mmio;
+	u32 clkbuflr_en, bandgap = 0;
+
+	switch (uc) {
+	case MSM_DSI_PHY_STANDALONE:
+		clkbuflr_en = 0x1;
+		break;
+	case MSM_DSI_PHY_MASTER:
+		clkbuflr_en = 0x3;
+		pll_14nm->slave = pll_14nm_list[(pll_14nm->id + 1) % DSI_MAX];
+		break;
+	case MSM_DSI_PHY_SLAVE:
+		clkbuflr_en = 0x0;
+		bandgap = 0x3;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	pll_write(base + REG_DSI_14nm_PHY_PLL_CLKBUFLR_EN, clkbuflr_en);
+	if (bandgap)
+		pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_BANDGAP, bandgap);
+
+	pll_14nm->uc = uc;
+
+	return 0;
+}
+
+static int dsi_pll_14nm_get_provider(struct msm_dsi_pll *pll,
+				     struct clk **byte_clk_provider,
+				     struct clk **pixel_clk_provider)
+{
+	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);
+	struct clk_hw_onecell_data *hw_data = pll_14nm->hw_data;
+
+	if (byte_clk_provider)
+		*byte_clk_provider = hw_data->hws[DSI_BYTE_PLL_CLK]->clk;
+	if (pixel_clk_provider)
+		*pixel_clk_provider = hw_data->hws[DSI_PIXEL_PLL_CLK]->clk;
+
+	return 0;
+}
+
+static void dsi_pll_14nm_destroy(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);
+	struct platform_device *pdev = pll_14nm->pdev;
+	int num_hws = pll_14nm->num_hws;
+
+	of_clk_del_provider(pdev->dev.of_node);
+
+	while (num_hws--)
+		clk_hw_unregister(pll_14nm->hws[num_hws]);
+}
+
+static struct clk_hw *pll_14nm_postdiv_register(struct dsi_pll_14nm *pll_14nm,
+						const char *name,
+						const char *parent_name,
+						unsigned long flags,
+						u8 shift)
+{
+	struct dsi_pll_14nm_postdiv *pll_postdiv;
+	struct device *dev = &pll_14nm->pdev->dev;
+	struct clk_init_data postdiv_init = {
+		.parent_names = (const char *[]) { parent_name },
+		.num_parents = 1,
+		.name = name,
+		.flags = flags,
+		.ops = &clk_ops_dsi_pll_14nm_postdiv,
+	};
+	int ret;
+
+	pll_postdiv = devm_kzalloc(dev, sizeof(*pll_postdiv), GFP_KERNEL);
+	if (!pll_postdiv)
+		return ERR_PTR(-ENOMEM);
+
+	pll_postdiv->pll = pll_14nm;
+	pll_postdiv->shift = shift;
+	/* both N1 and N2 postdividers are 4 bits wide */
+	pll_postdiv->width = 4;
+	/* range of each divider is from 1 to 15 */
+	pll_postdiv->flags = CLK_DIVIDER_ONE_BASED;
+	pll_postdiv->hw.init = &postdiv_init;
+
+	ret = clk_hw_register(dev, &pll_postdiv->hw);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return &pll_postdiv->hw;
+}
+
+static int pll_14nm_register(struct dsi_pll_14nm *pll_14nm)
+{
+	char clk_name[32], parent[32], vco_name[32];
+	struct clk_init_data vco_init = {
+		.parent_names = (const char *[]){ "xo" },
+		.num_parents = 1,
+		.name = vco_name,
+		.flags = CLK_IGNORE_UNUSED,
+		.ops = &clk_ops_dsi_pll_14nm_vco,
+	};
+	struct device *dev = &pll_14nm->pdev->dev;
+	struct clk_hw **hws = pll_14nm->hws;
+	struct clk_hw_onecell_data *hw_data;
+	struct clk_hw *hw;
+	int num = 0;
+	int ret;
+
+	DBG("DSI%d", pll_14nm->id);
+
+	hw_data = devm_kzalloc(dev, sizeof(*hw_data) +
+			       NUM_PROVIDED_CLKS * sizeof(struct clk_hw *),
+			       GFP_KERNEL);
+	if (!hw_data)
+		return -ENOMEM;
+
+	snprintf(vco_name, 32, "dsi%dvco_clk", pll_14nm->id);
+	pll_14nm->base.clk_hw.init = &vco_init;
+
+	ret = clk_hw_register(dev, &pll_14nm->base.clk_hw);
+	if (ret)
+		return ret;
+
+	hws[num++] = &pll_14nm->base.clk_hw;
+
+	snprintf(clk_name, 32, "dsi%dn1_postdiv_clk", pll_14nm->id);
+	snprintf(parent, 32, "dsi%dvco_clk", pll_14nm->id);
+
+	/* N1 postdiv, bits 0-3 in REG_DSI_14nm_PHY_CMN_CLK_CFG0 */
+	hw = pll_14nm_postdiv_register(pll_14nm, clk_name, parent,
+				       CLK_SET_RATE_PARENT, 0);
+	if (IS_ERR(hw))
+		return PTR_ERR(hw);
+
+	hws[num++] = hw;
+
+	snprintf(clk_name, 32, "dsi%dpllbyte", pll_14nm->id);
+	snprintf(parent, 32, "dsi%dn1_postdiv_clk", pll_14nm->id);
+
+	/* DSI Byte clock = VCO_CLK / N1 / 8 */
+	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,
+					  CLK_SET_RATE_PARENT, 1, 8);
+	if (IS_ERR(hw))
+		return PTR_ERR(hw);
+
+	hws[num++] = hw;
+	hw_data->hws[DSI_BYTE_PLL_CLK] = hw;
+
+	snprintf(clk_name, 32, "dsi%dn1_postdivby2_clk", pll_14nm->id);
+	snprintf(parent, 32, "dsi%dn1_postdiv_clk", pll_14nm->id);
+
+	/*
+	 * Skip the mux for now, force DSICLK_SEL to 1, Add a /2 divider
+	 * on the way. Don't let it set parent.
+	 */
+	hw = clk_hw_register_fixed_factor(dev, clk_name, parent, 0, 1, 2);
+	if (IS_ERR(hw))
+		return PTR_ERR(hw);
+
+	hws[num++] = hw;
+
+	snprintf(clk_name, 32, "dsi%dpll", pll_14nm->id);
+	snprintf(parent, 32, "dsi%dn1_postdivby2_clk", pll_14nm->id);
+
+	/* DSI pixel clock = VCO_CLK / N1 / 2 / N2
+	 * This is the output of N2 post-divider, bits 4-7 in
+	 * REG_DSI_14nm_PHY_CMN_CLK_CFG0. Don't let it set parent.
+	 */
+	hw = pll_14nm_postdiv_register(pll_14nm, clk_name, parent, 0, 4);
+	if (IS_ERR(hw))
+		return PTR_ERR(hw);
+
+	hws[num++] = hw;
+	hw_data->hws[DSI_PIXEL_PLL_CLK]	= hw;
+
+	pll_14nm->num_hws = num;
+
+	hw_data->num = NUM_PROVIDED_CLKS;
+	pll_14nm->hw_data = hw_data;
+
+	ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
+				     pll_14nm->hw_data);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+struct msm_dsi_pll *msm_dsi_pll_14nm_init(struct platform_device *pdev, int id)
+{
+	struct dsi_pll_14nm *pll_14nm;
+	struct msm_dsi_pll *pll;
+	int ret;
+
+	if (!pdev)
+		return ERR_PTR(-ENODEV);
+
+	pll_14nm = devm_kzalloc(&pdev->dev, sizeof(*pll_14nm), GFP_KERNEL);
+	if (!pll_14nm)
+		return ERR_PTR(-ENOMEM);
+
+	DBG("PLL%d", id);
+
+	pll_14nm->pdev = pdev;
+	pll_14nm->id = id;
+	pll_14nm_list[id] = pll_14nm;
+
+	pll_14nm->phy_cmn_mmio = msm_ioremap(pdev, "dsi_phy", "DSI_PHY");
+	if (IS_ERR_OR_NULL(pll_14nm->phy_cmn_mmio)) {
+		DRM_DEV_ERROR(&pdev->dev, "failed to map CMN PHY base\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	pll_14nm->mmio = msm_ioremap(pdev, "dsi_pll", "DSI_PLL");
+	if (IS_ERR_OR_NULL(pll_14nm->mmio)) {
+		DRM_DEV_ERROR(&pdev->dev, "failed to map PLL base\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	spin_lock_init(&pll_14nm->postdiv_lock);
+
+	pll = &pll_14nm->base;
+	pll->min_rate = VCO_MIN_RATE;
+	pll->max_rate = VCO_MAX_RATE;
+	pll->get_provider = dsi_pll_14nm_get_provider;
+	pll->destroy = dsi_pll_14nm_destroy;
+	pll->disable_seq = dsi_pll_14nm_disable_seq;
+	pll->save_state = dsi_pll_14nm_save_state;
+	pll->restore_state = dsi_pll_14nm_restore_state;
+	pll->set_usecase = dsi_pll_14nm_set_usecase;
+
+	pll_14nm->vco_delay = 1;
+
+	pll->en_seq_cnt = 1;
+	pll->enable_seqs[0] = dsi_pll_14nm_enable_seq;
+
+	ret = pll_14nm_register(pll_14nm);
+	if (ret) {
+		DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret);
+		return ERR_PTR(ret);
+	}
+
+	return pll;
+}
+
 static void dsi_14nm_dphy_set_timing(struct msm_dsi_phy *phy,
 				     struct msm_dsi_dphy_timing *timing,
 				     int lane_idx)
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
index 5bf79de0da67..2f502efa4dd5 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
@@ -3,9 +3,646 @@ 
  * Copyright (c) 2015, The Linux Foundation. All rights reserved.
  */
 
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
 #include "dsi_phy.h"
+#include "dsi_pll.h"
 #include "dsi.xml.h"
 
+/*
+ * DSI PLL 28nm - clock diagram (eg: DSI0):
+ *
+ *         dsi0analog_postdiv_clk
+ *                             |         dsi0indirect_path_div2_clk
+ *                             |          |
+ *                   +------+  |  +----+  |  |\   dsi0byte_mux
+ *  dsi0vco_clk --o--| DIV1 |--o--| /2 |--o--| \   |
+ *                |  +------+     +----+     | m|  |  +----+
+ *                |                          | u|--o--| /4 |-- dsi0pllbyte
+ *                |                          | x|     +----+
+ *                o--------------------------| /
+ *                |                          |/
+ *                |          +------+
+ *                o----------| DIV3 |------------------------- dsi0pll
+ *                           +------+
+ */
+
+#define POLL_MAX_READS			10
+#define POLL_TIMEOUT_US		50
+
+#define NUM_PROVIDED_CLKS		2
+
+#define VCO_REF_CLK_RATE		19200000
+#define VCO_MIN_RATE			350000000
+#define VCO_MAX_RATE			750000000
+
+#define DSI_BYTE_PLL_CLK		0
+#define DSI_PIXEL_PLL_CLK		1
+
+#define LPFR_LUT_SIZE			10
+struct lpfr_cfg {
+	unsigned long vco_rate;
+	u32 resistance;
+};
+
+/* Loop filter resistance: */
+static const struct lpfr_cfg lpfr_lut[LPFR_LUT_SIZE] = {
+	{ 479500000,  8 },
+	{ 480000000, 11 },
+	{ 575500000,  8 },
+	{ 576000000, 12 },
+	{ 610500000,  8 },
+	{ 659500000,  9 },
+	{ 671500000, 10 },
+	{ 672000000, 14 },
+	{ 708500000, 10 },
+	{ 750000000, 11 },
+};
+
+struct pll_28nm_cached_state {
+	unsigned long vco_rate;
+	u8 postdiv3;
+	u8 postdiv1;
+	u8 byte_mux;
+};
+
+struct dsi_pll_28nm {
+	struct msm_dsi_pll base;
+
+	int id;
+	struct platform_device *pdev;
+	void __iomem *mmio;
+
+	int vco_delay;
+
+	/* private clocks: */
+	struct clk *clks[NUM_DSI_CLOCKS_MAX];
+	u32 num_clks;
+
+	/* clock-provider: */
+	struct clk *provided_clks[NUM_PROVIDED_CLKS];
+	struct clk_onecell_data clk_data;
+
+	struct pll_28nm_cached_state cached_state;
+};
+
+#define to_pll_28nm(x)	container_of(x, struct dsi_pll_28nm, base)
+
+static bool pll_28nm_poll_for_ready(struct dsi_pll_28nm *pll_28nm,
+				u32 nb_tries, u32 timeout_us)
+{
+	bool pll_locked = false;
+	u32 val;
+
+	while (nb_tries--) {
+		val = pll_read(pll_28nm->mmio + REG_DSI_28nm_PHY_PLL_STATUS);
+		pll_locked = !!(val & DSI_28nm_PHY_PLL_STATUS_PLL_RDY);
+
+		if (pll_locked)
+			break;
+
+		udelay(timeout_us);
+	}
+	DBG("DSI PLL is %slocked", pll_locked ? "" : "*not* ");
+
+	return pll_locked;
+}
+
+static void pll_28nm_software_reset(struct dsi_pll_28nm *pll_28nm)
+{
+	void __iomem *base = pll_28nm->mmio;
+
+	/*
+	 * Add HW recommended delays after toggling the software
+	 * reset bit off and back on.
+	 */
+	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_TEST_CFG,
+			DSI_28nm_PHY_PLL_TEST_CFG_PLL_SW_RESET, 1);
+	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_TEST_CFG, 0x00, 1);
+}
+
+/*
+ * Clock Callbacks
+ */
+static int dsi_pll_28nm_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+	struct device *dev = &pll_28nm->pdev->dev;
+	void __iomem *base = pll_28nm->mmio;
+	unsigned long div_fbx1000, gen_vco_clk;
+	u32 refclk_cfg, frac_n_mode, frac_n_value;
+	u32 sdm_cfg0, sdm_cfg1, sdm_cfg2, sdm_cfg3;
+	u32 cal_cfg10, cal_cfg11;
+	u32 rem;
+	int i;
+
+	VERB("rate=%lu, parent's=%lu", rate, parent_rate);
+
+	/* Force postdiv2 to be div-4 */
+	pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV2_CFG, 3);
+
+	/* Configure the Loop filter resistance */
+	for (i = 0; i < LPFR_LUT_SIZE; i++)
+		if (rate <= lpfr_lut[i].vco_rate)
+			break;
+	if (i == LPFR_LUT_SIZE) {
+		DRM_DEV_ERROR(dev, "unable to get loop filter resistance. vco=%lu\n",
+				rate);
+		return -EINVAL;
+	}
+	pll_write(base + REG_DSI_28nm_PHY_PLL_LPFR_CFG, lpfr_lut[i].resistance);
+
+	/* Loop filter capacitance values : c1 and c2 */
+	pll_write(base + REG_DSI_28nm_PHY_PLL_LPFC1_CFG, 0x70);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_LPFC2_CFG, 0x15);
+
+	rem = rate % VCO_REF_CLK_RATE;
+	if (rem) {
+		refclk_cfg = DSI_28nm_PHY_PLL_REFCLK_CFG_DBLR;
+		frac_n_mode = 1;
+		div_fbx1000 = rate / (VCO_REF_CLK_RATE / 500);
+		gen_vco_clk = div_fbx1000 * (VCO_REF_CLK_RATE / 500);
+	} else {
+		refclk_cfg = 0x0;
+		frac_n_mode = 0;
+		div_fbx1000 = rate / (VCO_REF_CLK_RATE / 1000);
+		gen_vco_clk = div_fbx1000 * (VCO_REF_CLK_RATE / 1000);
+	}
+
+	DBG("refclk_cfg = %d", refclk_cfg);
+
+	rem = div_fbx1000 % 1000;
+	frac_n_value = (rem << 16) / 1000;
+
+	DBG("div_fb = %lu", div_fbx1000);
+	DBG("frac_n_value = %d", frac_n_value);
+
+	DBG("Generated VCO Clock: %lu", gen_vco_clk);
+	rem = 0;
+	sdm_cfg1 = pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1);
+	sdm_cfg1 &= ~DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET__MASK;
+	if (frac_n_mode) {
+		sdm_cfg0 = 0x0;
+		sdm_cfg0 |= DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV(0);
+		sdm_cfg1 |= DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET(
+				(u32)(((div_fbx1000 / 1000) & 0x3f) - 1));
+		sdm_cfg3 = frac_n_value >> 8;
+		sdm_cfg2 = frac_n_value & 0xff;
+	} else {
+		sdm_cfg0 = DSI_28nm_PHY_PLL_SDM_CFG0_BYP;
+		sdm_cfg0 |= DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV(
+				(u32)(((div_fbx1000 / 1000) & 0x3f) - 1));
+		sdm_cfg1 |= DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET(0);
+		sdm_cfg2 = 0;
+		sdm_cfg3 = 0;
+	}
+
+	DBG("sdm_cfg0=%d", sdm_cfg0);
+	DBG("sdm_cfg1=%d", sdm_cfg1);
+	DBG("sdm_cfg2=%d", sdm_cfg2);
+	DBG("sdm_cfg3=%d", sdm_cfg3);
+
+	cal_cfg11 = (u32)(gen_vco_clk / (256 * 1000000));
+	cal_cfg10 = (u32)((gen_vco_clk % (256 * 1000000)) / 1000000);
+	DBG("cal_cfg10=%d, cal_cfg11=%d", cal_cfg10, cal_cfg11);
+
+	pll_write(base + REG_DSI_28nm_PHY_PLL_CHGPUMP_CFG, 0x02);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG3,    0x2b);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG4,    0x06);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2,  0x0d);
+
+	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1, sdm_cfg1);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG2,
+		DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0(sdm_cfg2));
+	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG3,
+		DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8(sdm_cfg3));
+	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG4, 0x00);
+
+	/* Add hardware recommended delay for correct PLL configuration */
+	if (pll_28nm->vco_delay)
+		udelay(pll_28nm->vco_delay);
+
+	pll_write(base + REG_DSI_28nm_PHY_PLL_REFCLK_CFG, refclk_cfg);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_PWRGEN_CFG, 0x00);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_VCOLPF_CFG, 0x31);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0,   sdm_cfg0);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG0,   0x12);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG6,   0x30);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG7,   0x00);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG8,   0x60);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG9,   0x00);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG10,  cal_cfg10 & 0xff);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG11,  cal_cfg11 & 0xff);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_EFUSE_CFG,  0x20);
+
+	return 0;
+}
+
+static int dsi_pll_28nm_clk_is_enabled(struct clk_hw *hw)
+{
+	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+
+	return pll_28nm_poll_for_ready(pll_28nm, POLL_MAX_READS,
+					POLL_TIMEOUT_US);
+}
+
+static unsigned long dsi_pll_28nm_clk_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+	void __iomem *base = pll_28nm->mmio;
+	u32 sdm0, doubler, sdm_byp_div;
+	u32 sdm_dc_off, sdm_freq_seed, sdm2, sdm3;
+	u32 ref_clk = VCO_REF_CLK_RATE;
+	unsigned long vco_rate;
+
+	VERB("parent_rate=%lu", parent_rate);
+
+	/* Check to see if the ref clk doubler is enabled */
+	doubler = pll_read(base + REG_DSI_28nm_PHY_PLL_REFCLK_CFG) &
+			DSI_28nm_PHY_PLL_REFCLK_CFG_DBLR;
+	ref_clk += (doubler * VCO_REF_CLK_RATE);
+
+	/* see if it is integer mode or sdm mode */
+	sdm0 = pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0);
+	if (sdm0 & DSI_28nm_PHY_PLL_SDM_CFG0_BYP) {
+		/* integer mode */
+		sdm_byp_div = FIELD(
+				pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0),
+				DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV) + 1;
+		vco_rate = ref_clk * sdm_byp_div;
+	} else {
+		/* sdm mode */
+		sdm_dc_off = FIELD(
+				pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1),
+				DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET);
+		DBG("sdm_dc_off = %d", sdm_dc_off);
+		sdm2 = FIELD(pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG2),
+				DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0);
+		sdm3 = FIELD(pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG3),
+				DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8);
+		sdm_freq_seed = (sdm3 << 8) | sdm2;
+		DBG("sdm_freq_seed = %d", sdm_freq_seed);
+
+		vco_rate = (ref_clk * (sdm_dc_off + 1)) +
+			mult_frac(ref_clk, sdm_freq_seed, BIT(16));
+		DBG("vco rate = %lu", vco_rate);
+	}
+
+	DBG("returning vco rate = %lu", vco_rate);
+
+	return vco_rate;
+}
+
+static const struct clk_ops clk_ops_dsi_pll_28nm_vco = {
+	.round_rate = msm_dsi_pll_helper_clk_round_rate,
+	.set_rate = dsi_pll_28nm_clk_set_rate,
+	.recalc_rate = dsi_pll_28nm_clk_recalc_rate,
+	.prepare = msm_dsi_pll_helper_clk_prepare,
+	.unprepare = msm_dsi_pll_helper_clk_unprepare,
+	.is_enabled = dsi_pll_28nm_clk_is_enabled,
+};
+
+/*
+ * PLL Callbacks
+ */
+static int dsi_pll_28nm_enable_seq_hpm(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+	struct device *dev = &pll_28nm->pdev->dev;
+	void __iomem *base = pll_28nm->mmio;
+	u32 max_reads = 5, timeout_us = 100;
+	bool locked;
+	u32 val;
+	int i;
+
+	DBG("id=%d", pll_28nm->id);
+
+	pll_28nm_software_reset(pll_28nm);
+
+	/*
+	 * PLL power up sequence.
+	 * Add necessary delays recommended by hardware.
+	 */
+	val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;
+	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 1);
+
+	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;
+	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);
+
+	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;
+	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);
+
+	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;
+	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 600);
+
+	for (i = 0; i < 2; i++) {
+		/* DSI Uniphy lock detect setting */
+		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2,
+				0x0c, 100);
+		pll_write(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x0d);
+
+		/* poll for PLL ready status */
+		locked = pll_28nm_poll_for_ready(pll_28nm,
+						max_reads, timeout_us);
+		if (locked)
+			break;
+
+		pll_28nm_software_reset(pll_28nm);
+
+		/*
+		 * PLL power up sequence.
+		 * Add necessary delays recommended by hardware.
+		 */
+		val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;
+		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 1);
+
+		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;
+		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);
+
+		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;
+		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 250);
+
+		val &= ~DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;
+		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);
+
+		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;
+		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);
+
+		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;
+		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 600);
+	}
+
+	if (unlikely(!locked))
+		DRM_DEV_ERROR(dev, "DSI PLL lock failed\n");
+	else
+		DBG("DSI PLL Lock success");
+
+	return locked ? 0 : -EINVAL;
+}
+
+static int dsi_pll_28nm_enable_seq_lp(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+	struct device *dev = &pll_28nm->pdev->dev;
+	void __iomem *base = pll_28nm->mmio;
+	bool locked;
+	u32 max_reads = 10, timeout_us = 50;
+	u32 val;
+
+	DBG("id=%d", pll_28nm->id);
+
+	pll_28nm_software_reset(pll_28nm);
+
+	/*
+	 * PLL power up sequence.
+	 * Add necessary delays recommended by hardware.
+	 */
+	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_CAL_CFG1, 0x34, 500);
+
+	val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;
+	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);
+
+	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;
+	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);
+
+	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B |
+		DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;
+	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);
+
+	/* DSI PLL toggle lock detect setting */
+	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x04, 500);
+	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x05, 512);
+
+	locked = pll_28nm_poll_for_ready(pll_28nm, max_reads, timeout_us);
+
+	if (unlikely(!locked))
+		DRM_DEV_ERROR(dev, "DSI PLL lock failed\n");
+	else
+		DBG("DSI PLL lock success");
+
+	return locked ? 0 : -EINVAL;
+}
+
+static void dsi_pll_28nm_disable_seq(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+
+	DBG("id=%d", pll_28nm->id);
+	pll_write(pll_28nm->mmio + REG_DSI_28nm_PHY_PLL_GLB_CFG, 0x00);
+}
+
+static void dsi_pll_28nm_save_state(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+	struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;
+	void __iomem *base = pll_28nm->mmio;
+
+	cached_state->postdiv3 =
+			pll_read(base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG);
+	cached_state->postdiv1 =
+			pll_read(base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG);
+	cached_state->byte_mux = pll_read(base + REG_DSI_28nm_PHY_PLL_VREG_CFG);
+	if (dsi_pll_28nm_clk_is_enabled(&pll->clk_hw))
+		cached_state->vco_rate = clk_hw_get_rate(&pll->clk_hw);
+	else
+		cached_state->vco_rate = 0;
+}
+
+static int dsi_pll_28nm_restore_state(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+	struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;
+	void __iomem *base = pll_28nm->mmio;
+	int ret;
+
+	ret = dsi_pll_28nm_clk_set_rate(&pll->clk_hw,
+					cached_state->vco_rate, 0);
+	if (ret) {
+		DRM_DEV_ERROR(&pll_28nm->pdev->dev,
+			"restore vco rate failed. ret=%d\n", ret);
+		return ret;
+	}
+
+	pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG,
+			cached_state->postdiv3);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG,
+			cached_state->postdiv1);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_VREG_CFG,
+			cached_state->byte_mux);
+
+	return 0;
+}
+
+static int dsi_pll_28nm_get_provider(struct msm_dsi_pll *pll,
+				struct clk **byte_clk_provider,
+				struct clk **pixel_clk_provider)
+{
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+
+	if (byte_clk_provider)
+		*byte_clk_provider = pll_28nm->provided_clks[DSI_BYTE_PLL_CLK];
+	if (pixel_clk_provider)
+		*pixel_clk_provider =
+				pll_28nm->provided_clks[DSI_PIXEL_PLL_CLK];
+
+	return 0;
+}
+
+static void dsi_pll_28nm_destroy(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+	int i;
+
+	msm_dsi_pll_helper_unregister_clks(pll_28nm->pdev,
+					pll_28nm->clks, pll_28nm->num_clks);
+
+	for (i = 0; i < NUM_PROVIDED_CLKS; i++)
+		pll_28nm->provided_clks[i] = NULL;
+
+	pll_28nm->num_clks = 0;
+	pll_28nm->clk_data.clks = NULL;
+	pll_28nm->clk_data.clk_num = 0;
+}
+
+static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm)
+{
+	char clk_name[32], parent1[32], parent2[32], vco_name[32];
+	struct clk_init_data vco_init = {
+		.parent_names = (const char *[]){ "xo" },
+		.num_parents = 1,
+		.name = vco_name,
+		.flags = CLK_IGNORE_UNUSED,
+		.ops = &clk_ops_dsi_pll_28nm_vco,
+	};
+	struct device *dev = &pll_28nm->pdev->dev;
+	struct clk **clks = pll_28nm->clks;
+	struct clk **provided_clks = pll_28nm->provided_clks;
+	int num = 0;
+	int ret;
+
+	DBG("%d", pll_28nm->id);
+
+	snprintf(vco_name, 32, "dsi%dvco_clk", pll_28nm->id);
+	pll_28nm->base.clk_hw.init = &vco_init;
+	clks[num++] = clk_register(dev, &pll_28nm->base.clk_hw);
+
+	snprintf(clk_name, 32, "dsi%danalog_postdiv_clk", pll_28nm->id);
+	snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->id);
+	clks[num++] = clk_register_divider(dev, clk_name,
+			parent1, CLK_SET_RATE_PARENT,
+			pll_28nm->mmio +
+			REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG,
+			0, 4, 0, NULL);
+
+	snprintf(clk_name, 32, "dsi%dindirect_path_div2_clk", pll_28nm->id);
+	snprintf(parent1, 32, "dsi%danalog_postdiv_clk", pll_28nm->id);
+	clks[num++] = clk_register_fixed_factor(dev, clk_name,
+			parent1, CLK_SET_RATE_PARENT,
+			1, 2);
+
+	snprintf(clk_name, 32, "dsi%dpll", pll_28nm->id);
+	snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->id);
+	clks[num++] = provided_clks[DSI_PIXEL_PLL_CLK] =
+			clk_register_divider(dev, clk_name,
+				parent1, 0, pll_28nm->mmio +
+				REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG,
+				0, 8, 0, NULL);
+
+	snprintf(clk_name, 32, "dsi%dbyte_mux", pll_28nm->id);
+	snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->id);
+	snprintf(parent2, 32, "dsi%dindirect_path_div2_clk", pll_28nm->id);
+	clks[num++] = clk_register_mux(dev, clk_name,
+			((const char *[]){
+				parent1, parent2
+			}), 2, CLK_SET_RATE_PARENT, pll_28nm->mmio +
+			REG_DSI_28nm_PHY_PLL_VREG_CFG, 1, 1, 0, NULL);
+
+	snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->id);
+	snprintf(parent1, 32, "dsi%dbyte_mux", pll_28nm->id);
+	clks[num++] = provided_clks[DSI_BYTE_PLL_CLK] =
+			clk_register_fixed_factor(dev, clk_name,
+				parent1, CLK_SET_RATE_PARENT, 1, 4);
+
+	pll_28nm->num_clks = num;
+
+	pll_28nm->clk_data.clk_num = NUM_PROVIDED_CLKS;
+	pll_28nm->clk_data.clks = provided_clks;
+
+	ret = of_clk_add_provider(dev->of_node,
+			of_clk_src_onecell_get, &pll_28nm->clk_data);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+struct msm_dsi_pll *msm_dsi_pll_28nm_init(struct platform_device *pdev,
+					enum msm_dsi_phy_type type, int id)
+{
+	struct dsi_pll_28nm *pll_28nm;
+	struct msm_dsi_pll *pll;
+	int ret;
+
+	if (!pdev)
+		return ERR_PTR(-ENODEV);
+
+	pll_28nm = devm_kzalloc(&pdev->dev, sizeof(*pll_28nm), GFP_KERNEL);
+	if (!pll_28nm)
+		return ERR_PTR(-ENOMEM);
+
+	pll_28nm->pdev = pdev;
+	pll_28nm->id = id;
+
+	pll_28nm->mmio = msm_ioremap(pdev, "dsi_pll", "DSI_PLL");
+	if (IS_ERR_OR_NULL(pll_28nm->mmio)) {
+		DRM_DEV_ERROR(&pdev->dev, "%s: failed to map pll base\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	pll = &pll_28nm->base;
+	pll->min_rate = VCO_MIN_RATE;
+	pll->max_rate = VCO_MAX_RATE;
+	pll->get_provider = dsi_pll_28nm_get_provider;
+	pll->destroy = dsi_pll_28nm_destroy;
+	pll->disable_seq = dsi_pll_28nm_disable_seq;
+	pll->save_state = dsi_pll_28nm_save_state;
+	pll->restore_state = dsi_pll_28nm_restore_state;
+
+	if (type == MSM_DSI_PHY_28NM_HPM) {
+		pll_28nm->vco_delay = 1;
+
+		pll->en_seq_cnt = 3;
+		pll->enable_seqs[0] = dsi_pll_28nm_enable_seq_hpm;
+		pll->enable_seqs[1] = dsi_pll_28nm_enable_seq_hpm;
+		pll->enable_seqs[2] = dsi_pll_28nm_enable_seq_hpm;
+	} else if (type == MSM_DSI_PHY_28NM_LP) {
+		pll_28nm->vco_delay = 1000;
+
+		pll->en_seq_cnt = 1;
+		pll->enable_seqs[0] = dsi_pll_28nm_enable_seq_lp;
+	} else {
+		DRM_DEV_ERROR(&pdev->dev, "phy type (%d) is not 28nm\n", type);
+		return ERR_PTR(-EINVAL);
+	}
+
+	ret = pll_28nm_register(pll_28nm);
+	if (ret) {
+		DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret);
+		return ERR_PTR(ret);
+	}
+
+	return pll;
+}
+
+
 static void dsi_28nm_dphy_set_timing(struct msm_dsi_phy *phy,
 		struct msm_dsi_dphy_timing *timing)
 {
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
index 5d33de27a0f4..4a40513057e8 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
@@ -3,11 +3,530 @@ 
  * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
  */
 
+#include <linux/clk-provider.h>
 #include <linux/delay.h>
 
 #include "dsi_phy.h"
+#include "dsi_pll.h"
 #include "dsi.xml.h"
 
+/*
+ * DSI PLL 28nm (8960/A family) - clock diagram (eg: DSI1):
+ *
+ *
+ *                        +------+
+ *  dsi1vco_clk ----o-----| DIV1 |---dsi1pllbit (not exposed as clock)
+ *  F * byte_clk    |     +------+
+ *                  | bit clock divider (F / 8)
+ *                  |
+ *                  |     +------+
+ *                  o-----| DIV2 |---dsi0pllbyte---o---> To byte RCG
+ *                  |     +------+                 | (sets parent rate)
+ *                  | byte clock divider (F)       |
+ *                  |                              |
+ *                  |                              o---> To esc RCG
+ *                  |                                (doesn't set parent rate)
+ *                  |
+ *                  |     +------+
+ *                  o-----| DIV3 |----dsi0pll------o---> To dsi RCG
+ *                        +------+                 | (sets parent rate)
+ *                  dsi clock divider (F * magic)  |
+ *                                                 |
+ *                                                 o---> To pixel rcg
+ *                                                  (doesn't set parent rate)
+ */
+
+#define POLL_MAX_READS		8000
+#define POLL_TIMEOUT_US		1
+
+#define NUM_PROVIDED_CLKS	2
+
+#define VCO_REF_CLK_RATE	27000000
+#define VCO_MIN_RATE		600000000
+#define VCO_MAX_RATE		1200000000
+
+#define DSI_BYTE_PLL_CLK	0
+#define DSI_PIXEL_PLL_CLK	1
+
+#define VCO_PREF_DIV_RATIO	27
+
+struct pll_28nm_cached_state {
+	unsigned long vco_rate;
+	u8 postdiv3;
+	u8 postdiv2;
+	u8 postdiv1;
+};
+
+struct clk_bytediv {
+	struct clk_hw hw;
+	void __iomem *reg;
+};
+
+struct dsi_pll_28nm {
+	struct msm_dsi_pll base;
+
+	int id;
+	struct platform_device *pdev;
+	void __iomem *mmio;
+
+	/* custom byte clock divider */
+	struct clk_bytediv *bytediv;
+
+	/* private clocks: */
+	struct clk *clks[NUM_DSI_CLOCKS_MAX];
+	u32 num_clks;
+
+	/* clock-provider: */
+	struct clk *provided_clks[NUM_PROVIDED_CLKS];
+	struct clk_onecell_data clk_data;
+
+	struct pll_28nm_cached_state cached_state;
+};
+
+#define to_pll_28nm(x)	container_of(x, struct dsi_pll_28nm, base)
+
+static bool pll_28nm_poll_for_ready(struct dsi_pll_28nm *pll_28nm,
+				    int nb_tries, int timeout_us)
+{
+	bool pll_locked = false;
+	u32 val;
+
+	while (nb_tries--) {
+		val = pll_read(pll_28nm->mmio + REG_DSI_28nm_8960_PHY_PLL_RDY);
+		pll_locked = !!(val & DSI_28nm_8960_PHY_PLL_RDY_PLL_RDY);
+
+		if (pll_locked)
+			break;
+
+		udelay(timeout_us);
+	}
+	DBG("DSI PLL is %slocked", pll_locked ? "" : "*not* ");
+
+	return pll_locked;
+}
+
+/*
+ * Clock Callbacks
+ */
+static int dsi_pll_28nm_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+				     unsigned long parent_rate)
+{
+	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+	void __iomem *base = pll_28nm->mmio;
+	u32 val, temp, fb_divider;
+
+	DBG("rate=%lu, parent's=%lu", rate, parent_rate);
+
+	temp = rate / 10;
+	val = VCO_REF_CLK_RATE / 10;
+	fb_divider = (temp * VCO_PREF_DIV_RATIO) / val;
+	fb_divider = fb_divider / 2 - 1;
+	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_1,
+			fb_divider & 0xff);
+
+	val = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2);
+
+	val |= (fb_divider >> 8) & 0x07;
+
+	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2,
+			val);
+
+	val = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3);
+
+	val |= (VCO_PREF_DIV_RATIO - 1) & 0x3f;
+
+	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3,
+			val);
+
+	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_6,
+			0xf);
+
+	val = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
+	val |= 0x7 << 4;
+	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8,
+			val);
+
+	return 0;
+}
+
+static int dsi_pll_28nm_clk_is_enabled(struct clk_hw *hw)
+{
+	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+
+	return pll_28nm_poll_for_ready(pll_28nm, POLL_MAX_READS,
+					POLL_TIMEOUT_US);
+}
+
+static unsigned long dsi_pll_28nm_clk_recalc_rate(struct clk_hw *hw,
+						  unsigned long parent_rate)
+{
+	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+	void __iomem *base = pll_28nm->mmio;
+	unsigned long vco_rate;
+	u32 status, fb_divider, temp, ref_divider;
+
+	VERB("parent_rate=%lu", parent_rate);
+
+	status = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_0);
+
+	if (status & DSI_28nm_8960_PHY_PLL_CTRL_0_ENABLE) {
+		fb_divider = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_1);
+		fb_divider &= 0xff;
+		temp = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2) & 0x07;
+		fb_divider = (temp << 8) | fb_divider;
+		fb_divider += 1;
+
+		ref_divider = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3);
+		ref_divider &= 0x3f;
+		ref_divider += 1;
+
+		/* multiply by 2 */
+		vco_rate = (parent_rate / ref_divider) * fb_divider * 2;
+	} else {
+		vco_rate = 0;
+	}
+
+	DBG("returning vco rate = %lu", vco_rate);
+
+	return vco_rate;
+}
+
+static const struct clk_ops clk_ops_dsi_pll_28nm_vco = {
+	.round_rate = msm_dsi_pll_helper_clk_round_rate,
+	.set_rate = dsi_pll_28nm_clk_set_rate,
+	.recalc_rate = dsi_pll_28nm_clk_recalc_rate,
+	.prepare = msm_dsi_pll_helper_clk_prepare,
+	.unprepare = msm_dsi_pll_helper_clk_unprepare,
+	.is_enabled = dsi_pll_28nm_clk_is_enabled,
+};
+
+/*
+ * Custom byte clock divier clk_ops
+ *
+ * This clock is the entry point to configuring the PLL. The user (dsi host)
+ * will set this clock's rate to the desired byte clock rate. The VCO lock
+ * frequency is a multiple of the byte clock rate. The multiplication factor
+ * (shown as F in the diagram above) is a function of the byte clock rate.
+ *
+ * This custom divider clock ensures that its parent (VCO) is set to the
+ * desired rate, and that the byte clock postdivider (POSTDIV2) is configured
+ * accordingly
+ */
+#define to_clk_bytediv(_hw) container_of(_hw, struct clk_bytediv, hw)
+
+static unsigned long clk_bytediv_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clk_bytediv *bytediv = to_clk_bytediv(hw);
+	unsigned int div;
+
+	div = pll_read(bytediv->reg) & 0xff;
+
+	return parent_rate / (div + 1);
+}
+
+/* find multiplication factor(wrt byte clock) at which the VCO should be set */
+static unsigned int get_vco_mul_factor(unsigned long byte_clk_rate)
+{
+	unsigned long bit_mhz;
+
+	/* convert to bit clock in Mhz */
+	bit_mhz = (byte_clk_rate * 8) / 1000000;
+
+	if (bit_mhz < 125)
+		return 64;
+	else if (bit_mhz < 250)
+		return 32;
+	else if (bit_mhz < 600)
+		return 16;
+	else
+		return 8;
+}
+
+static long clk_bytediv_round_rate(struct clk_hw *hw, unsigned long rate,
+				   unsigned long *prate)
+{
+	unsigned long best_parent;
+	unsigned int factor;
+
+	factor = get_vco_mul_factor(rate);
+
+	best_parent = rate * factor;
+	*prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
+
+	return *prate / factor;
+}
+
+static int clk_bytediv_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct clk_bytediv *bytediv = to_clk_bytediv(hw);
+	u32 val;
+	unsigned int factor;
+
+	factor = get_vco_mul_factor(rate);
+
+	val = pll_read(bytediv->reg);
+	val |= (factor - 1) & 0xff;
+	pll_write(bytediv->reg, val);
+
+	return 0;
+}
+
+/* Our special byte clock divider ops */
+static const struct clk_ops clk_bytediv_ops = {
+	.round_rate = clk_bytediv_round_rate,
+	.set_rate = clk_bytediv_set_rate,
+	.recalc_rate = clk_bytediv_recalc_rate,
+};
+
+/*
+ * PLL Callbacks
+ */
+static int dsi_pll_28nm_enable_seq(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+	struct device *dev = &pll_28nm->pdev->dev;
+	void __iomem *base = pll_28nm->mmio;
+	bool locked;
+	unsigned int bit_div, byte_div;
+	int max_reads = 1000, timeout_us = 100;
+	u32 val;
+
+	DBG("id=%d", pll_28nm->id);
+
+	/*
+	 * before enabling the PLL, configure the bit clock divider since we
+	 * don't expose it as a clock to the outside world
+	 * 1: read back the byte clock divider that should already be set
+	 * 2: divide by 8 to get bit clock divider
+	 * 3: write it to POSTDIV1
+	 */
+	val = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9);
+	byte_div = val + 1;
+	bit_div = byte_div / 8;
+
+	val = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
+	val &= ~0xf;
+	val |= (bit_div - 1);
+	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8, val);
+
+	/* enable the PLL */
+	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_0,
+			DSI_28nm_8960_PHY_PLL_CTRL_0_ENABLE);
+
+	locked = pll_28nm_poll_for_ready(pll_28nm, max_reads, timeout_us);
+
+	if (unlikely(!locked))
+		DRM_DEV_ERROR(dev, "DSI PLL lock failed\n");
+	else
+		DBG("DSI PLL lock success");
+
+	return locked ? 0 : -EINVAL;
+}
+
+static void dsi_pll_28nm_disable_seq(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+
+	DBG("id=%d", pll_28nm->id);
+	pll_write(pll_28nm->mmio + REG_DSI_28nm_8960_PHY_PLL_CTRL_0, 0x00);
+}
+
+static void dsi_pll_28nm_save_state(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+	struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;
+	void __iomem *base = pll_28nm->mmio;
+
+	cached_state->postdiv3 =
+			pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_10);
+	cached_state->postdiv2 =
+			pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9);
+	cached_state->postdiv1 =
+			pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
+
+	cached_state->vco_rate = clk_hw_get_rate(&pll->clk_hw);
+}
+
+static int dsi_pll_28nm_restore_state(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+	struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;
+	void __iomem *base = pll_28nm->mmio;
+	int ret;
+
+	ret = dsi_pll_28nm_clk_set_rate(&pll->clk_hw,
+					cached_state->vco_rate, 0);
+	if (ret) {
+		DRM_DEV_ERROR(&pll_28nm->pdev->dev,
+			"restore vco rate failed. ret=%d\n", ret);
+		return ret;
+	}
+
+	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_10,
+			cached_state->postdiv3);
+	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9,
+			cached_state->postdiv2);
+	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8,
+			cached_state->postdiv1);
+
+	return 0;
+}
+
+static int dsi_pll_28nm_get_provider(struct msm_dsi_pll *pll,
+				struct clk **byte_clk_provider,
+				struct clk **pixel_clk_provider)
+{
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+
+	if (byte_clk_provider)
+		*byte_clk_provider = pll_28nm->provided_clks[DSI_BYTE_PLL_CLK];
+	if (pixel_clk_provider)
+		*pixel_clk_provider =
+				pll_28nm->provided_clks[DSI_PIXEL_PLL_CLK];
+
+	return 0;
+}
+
+static void dsi_pll_28nm_destroy(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+
+	msm_dsi_pll_helper_unregister_clks(pll_28nm->pdev,
+					pll_28nm->clks, pll_28nm->num_clks);
+}
+
+static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm)
+{
+	char *clk_name, *parent_name, *vco_name;
+	struct clk_init_data vco_init = {
+		.parent_names = (const char *[]){ "pxo" },
+		.num_parents = 1,
+		.flags = CLK_IGNORE_UNUSED,
+		.ops = &clk_ops_dsi_pll_28nm_vco,
+	};
+	struct device *dev = &pll_28nm->pdev->dev;
+	struct clk **clks = pll_28nm->clks;
+	struct clk **provided_clks = pll_28nm->provided_clks;
+	struct clk_bytediv *bytediv;
+	struct clk_init_data bytediv_init = { };
+	int ret, num = 0;
+
+	DBG("%d", pll_28nm->id);
+
+	bytediv = devm_kzalloc(dev, sizeof(*bytediv), GFP_KERNEL);
+	if (!bytediv)
+		return -ENOMEM;
+
+	vco_name = devm_kzalloc(dev, 32, GFP_KERNEL);
+	if (!vco_name)
+		return -ENOMEM;
+
+	parent_name = devm_kzalloc(dev, 32, GFP_KERNEL);
+	if (!parent_name)
+		return -ENOMEM;
+
+	clk_name = devm_kzalloc(dev, 32, GFP_KERNEL);
+	if (!clk_name)
+		return -ENOMEM;
+
+	pll_28nm->bytediv = bytediv;
+
+	snprintf(vco_name, 32, "dsi%dvco_clk", pll_28nm->id);
+	vco_init.name = vco_name;
+
+	pll_28nm->base.clk_hw.init = &vco_init;
+
+	clks[num++] = clk_register(dev, &pll_28nm->base.clk_hw);
+
+	/* prepare and register bytediv */
+	bytediv->hw.init = &bytediv_init;
+	bytediv->reg = pll_28nm->mmio + REG_DSI_28nm_8960_PHY_PLL_CTRL_9;
+
+	snprintf(parent_name, 32, "dsi%dvco_clk", pll_28nm->id);
+	snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->id);
+
+	bytediv_init.name = clk_name;
+	bytediv_init.ops = &clk_bytediv_ops;
+	bytediv_init.flags = CLK_SET_RATE_PARENT;
+	bytediv_init.parent_names = (const char * const *) &parent_name;
+	bytediv_init.num_parents = 1;
+
+	/* DIV2 */
+	clks[num++] = provided_clks[DSI_BYTE_PLL_CLK] =
+			clk_register(dev, &bytediv->hw);
+
+	snprintf(clk_name, 32, "dsi%dpll", pll_28nm->id);
+	/* DIV3 */
+	clks[num++] = provided_clks[DSI_PIXEL_PLL_CLK] =
+			clk_register_divider(dev, clk_name,
+				parent_name, 0, pll_28nm->mmio +
+				REG_DSI_28nm_8960_PHY_PLL_CTRL_10,
+				0, 8, 0, NULL);
+
+	pll_28nm->num_clks = num;
+
+	pll_28nm->clk_data.clk_num = NUM_PROVIDED_CLKS;
+	pll_28nm->clk_data.clks = provided_clks;
+
+	ret = of_clk_add_provider(dev->of_node,
+			of_clk_src_onecell_get, &pll_28nm->clk_data);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+struct msm_dsi_pll *msm_dsi_pll_28nm_8960_init(struct platform_device *pdev,
+					       int id)
+{
+	struct dsi_pll_28nm *pll_28nm;
+	struct msm_dsi_pll *pll;
+	int ret;
+
+	if (!pdev)
+		return ERR_PTR(-ENODEV);
+
+	pll_28nm = devm_kzalloc(&pdev->dev, sizeof(*pll_28nm), GFP_KERNEL);
+	if (!pll_28nm)
+		return ERR_PTR(-ENOMEM);
+
+	pll_28nm->pdev = pdev;
+	pll_28nm->id = id + 1;
+
+	pll_28nm->mmio = msm_ioremap(pdev, "dsi_pll", "DSI_PLL");
+	if (IS_ERR_OR_NULL(pll_28nm->mmio)) {
+		DRM_DEV_ERROR(&pdev->dev, "%s: failed to map pll base\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	pll = &pll_28nm->base;
+	pll->min_rate = VCO_MIN_RATE;
+	pll->max_rate = VCO_MAX_RATE;
+	pll->get_provider = dsi_pll_28nm_get_provider;
+	pll->destroy = dsi_pll_28nm_destroy;
+	pll->disable_seq = dsi_pll_28nm_disable_seq;
+	pll->save_state = dsi_pll_28nm_save_state;
+	pll->restore_state = dsi_pll_28nm_restore_state;
+
+	pll->en_seq_cnt = 1;
+	pll->enable_seqs[0] = dsi_pll_28nm_enable_seq;
+
+	ret = pll_28nm_register(pll_28nm);
+	if (ret) {
+		DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret);
+		return ERR_PTR(ret);
+	}
+
+	return pll;
+}
+
 static void dsi_28nm_dphy_set_timing(struct msm_dsi_phy *phy,
 		struct msm_dsi_dphy_timing *timing)
 {
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
index cbfeec860e69..f9af9d70b56a 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
@@ -3,11 +3,916 @@ 
  * Copyright (c) 2018, The Linux Foundation
  */
 
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/iopoll.h>
 
+#include "dsi_pll.h"
 #include "dsi_phy.h"
 #include "dsi.xml.h"
 
+/*
+ * DSI PLL 7nm - clock diagram (eg: DSI0): TODO: updated CPHY diagram
+ *
+ *           dsi0_pll_out_div_clk  dsi0_pll_bit_clk
+ *                              |                |
+ *                              |                |
+ *                 +---------+  |  +----------+  |  +----+
+ *  dsi0vco_clk ---| out_div |--o--| divl_3_0 |--o--| /8 |-- dsi0_phy_pll_out_byteclk
+ *                 +---------+  |  +----------+  |  +----+
+ *                              |                |
+ *                              |                |         dsi0_pll_by_2_bit_clk
+ *                              |                |          |
+ *                              |                |  +----+  |  |\  dsi0_pclk_mux
+ *                              |                |--| /2 |--o--| \   |
+ *                              |                |  +----+     |  \  |  +---------+
+ *                              |                --------------|  |--o--| div_7_4 |-- dsi0_phy_pll_out_dsiclk
+ *                              |------------------------------|  /     +---------+
+ *                              |          +-----+             | /
+ *                              -----------| /4? |--o----------|/
+ *                                         +-----+  |           |
+ *                                                  |           |dsiclk_sel
+ *                                                  |
+ *                                                  dsi0_pll_post_out_div_clk
+ */
+
+#define DSI_BYTE_PLL_CLK		0
+#define DSI_PIXEL_PLL_CLK		1
+#define NUM_PROVIDED_CLKS		2
+
+#define VCO_REF_CLK_RATE		19200000
+
+struct dsi_pll_regs {
+	u32 pll_prop_gain_rate;
+	u32 pll_lockdet_rate;
+	u32 decimal_div_start;
+	u32 frac_div_start_low;
+	u32 frac_div_start_mid;
+	u32 frac_div_start_high;
+	u32 pll_clock_inverters;
+	u32 ssc_stepsize_low;
+	u32 ssc_stepsize_high;
+	u32 ssc_div_per_low;
+	u32 ssc_div_per_high;
+	u32 ssc_adjper_low;
+	u32 ssc_adjper_high;
+	u32 ssc_control;
+};
+
+struct dsi_pll_config {
+	u32 ref_freq;
+	bool div_override;
+	u32 output_div;
+	bool ignore_frac;
+	bool disable_prescaler;
+	bool enable_ssc;
+	bool ssc_center;
+	u32 dec_bits;
+	u32 frac_bits;
+	u32 lock_timer;
+	u32 ssc_freq;
+	u32 ssc_offset;
+	u32 ssc_adj_per;
+	u32 thresh_cycles;
+	u32 refclk_cycles;
+};
+
+struct pll_7nm_cached_state {
+	unsigned long vco_rate;
+	u8 bit_clk_div;
+	u8 pix_clk_div;
+	u8 pll_out_div;
+	u8 pll_mux;
+};
+
+struct dsi_pll_7nm {
+	struct msm_dsi_pll base;
+
+	int id;
+	struct platform_device *pdev;
+
+	void __iomem *phy_cmn_mmio;
+	void __iomem *mmio;
+
+	u64 vco_ref_clk_rate;
+	u64 vco_current_rate;
+
+	/* protects REG_DSI_7nm_PHY_CMN_CLK_CFG0 register */
+	spinlock_t postdiv_lock;
+
+	int vco_delay;
+	struct dsi_pll_config pll_configuration;
+	struct dsi_pll_regs reg_setup;
+
+	/* private clocks: */
+	struct clk_hw *out_div_clk_hw;
+	struct clk_hw *bit_clk_hw;
+	struct clk_hw *byte_clk_hw;
+	struct clk_hw *by_2_bit_clk_hw;
+	struct clk_hw *post_out_div_clk_hw;
+	struct clk_hw *pclk_mux_hw;
+	struct clk_hw *out_dsiclk_hw;
+
+	/* clock-provider: */
+	struct clk_hw_onecell_data *hw_data;
+
+	struct pll_7nm_cached_state cached_state;
+
+	enum msm_dsi_phy_usecase uc;
+	struct dsi_pll_7nm *slave;
+};
+
+#define to_pll_7nm(x)	container_of(x, struct dsi_pll_7nm, base)
+
+/*
+ * Global list of private DSI PLL struct pointers. We need this for Dual DSI
+ * mode, where the master PLL's clk_ops needs access the slave's private data
+ */
+static struct dsi_pll_7nm *pll_7nm_list[DSI_MAX];
+
+static void dsi_pll_setup_config(struct dsi_pll_7nm *pll)
+{
+	struct dsi_pll_config *config = &pll->pll_configuration;
+
+	config->ref_freq = pll->vco_ref_clk_rate;
+	config->output_div = 1;
+	config->dec_bits = 8;
+	config->frac_bits = 18;
+	config->lock_timer = 64;
+	config->ssc_freq = 31500;
+	config->ssc_offset = 4800;
+	config->ssc_adj_per = 2;
+	config->thresh_cycles = 32;
+	config->refclk_cycles = 256;
+
+	config->div_override = false;
+	config->ignore_frac = false;
+	config->disable_prescaler = false;
+
+	/* TODO: ssc enable */
+	config->enable_ssc = false;
+	config->ssc_center = 0;
+}
+
+static void dsi_pll_calc_dec_frac(struct dsi_pll_7nm *pll)
+{
+	struct dsi_pll_config *config = &pll->pll_configuration;
+	struct dsi_pll_regs *regs = &pll->reg_setup;
+	u64 fref = pll->vco_ref_clk_rate;
+	u64 pll_freq;
+	u64 divider;
+	u64 dec, dec_multiple;
+	u32 frac;
+	u64 multiplier;
+
+	pll_freq = pll->vco_current_rate;
+
+	if (config->disable_prescaler)
+		divider = fref;
+	else
+		divider = fref * 2;
+
+	multiplier = 1 << config->frac_bits;
+	dec_multiple = div_u64(pll_freq * multiplier, divider);
+	div_u64_rem(dec_multiple, multiplier, &frac);
+
+	dec = div_u64(dec_multiple, multiplier);
+
+	if (pll->base.type != MSM_DSI_PHY_7NM_V4_1)
+		regs->pll_clock_inverters = 0x28;
+	else if (pll_freq <= 1000000000ULL)
+		regs->pll_clock_inverters = 0xa0;
+	else if (pll_freq <= 2500000000ULL)
+		regs->pll_clock_inverters = 0x20;
+	else if (pll_freq <= 3020000000ULL)
+		regs->pll_clock_inverters = 0x00;
+	else
+		regs->pll_clock_inverters = 0x40;
+
+	regs->pll_lockdet_rate = config->lock_timer;
+	regs->decimal_div_start = dec;
+	regs->frac_div_start_low = (frac & 0xff);
+	regs->frac_div_start_mid = (frac & 0xff00) >> 8;
+	regs->frac_div_start_high = (frac & 0x30000) >> 16;
+}
+
+#define SSC_CENTER		BIT(0)
+#define SSC_EN			BIT(1)
+
+static void dsi_pll_calc_ssc(struct dsi_pll_7nm *pll)
+{
+	struct dsi_pll_config *config = &pll->pll_configuration;
+	struct dsi_pll_regs *regs = &pll->reg_setup;
+	u32 ssc_per;
+	u32 ssc_mod;
+	u64 ssc_step_size;
+	u64 frac;
+
+	if (!config->enable_ssc) {
+		DBG("SSC not enabled\n");
+		return;
+	}
+
+	ssc_per = DIV_ROUND_CLOSEST(config->ref_freq, config->ssc_freq) / 2 - 1;
+	ssc_mod = (ssc_per + 1) % (config->ssc_adj_per + 1);
+	ssc_per -= ssc_mod;
+
+	frac = regs->frac_div_start_low |
+			(regs->frac_div_start_mid << 8) |
+			(regs->frac_div_start_high << 16);
+	ssc_step_size = regs->decimal_div_start;
+	ssc_step_size *= (1 << config->frac_bits);
+	ssc_step_size += frac;
+	ssc_step_size *= config->ssc_offset;
+	ssc_step_size *= (config->ssc_adj_per + 1);
+	ssc_step_size = div_u64(ssc_step_size, (ssc_per + 1));
+	ssc_step_size = DIV_ROUND_CLOSEST_ULL(ssc_step_size, 1000000);
+
+	regs->ssc_div_per_low = ssc_per & 0xFF;
+	regs->ssc_div_per_high = (ssc_per & 0xFF00) >> 8;
+	regs->ssc_stepsize_low = (u32)(ssc_step_size & 0xFF);
+	regs->ssc_stepsize_high = (u32)((ssc_step_size & 0xFF00) >> 8);
+	regs->ssc_adjper_low = config->ssc_adj_per & 0xFF;
+	regs->ssc_adjper_high = (config->ssc_adj_per & 0xFF00) >> 8;
+
+	regs->ssc_control = config->ssc_center ? SSC_CENTER : 0;
+
+	pr_debug("SCC: Dec:%d, frac:%llu, frac_bits:%d\n",
+		 regs->decimal_div_start, frac, config->frac_bits);
+	pr_debug("SSC: div_per:0x%X, stepsize:0x%X, adjper:0x%X\n",
+		 ssc_per, (u32)ssc_step_size, config->ssc_adj_per);
+}
+
+static void dsi_pll_ssc_commit(struct dsi_pll_7nm *pll)
+{
+	void __iomem *base = pll->mmio;
+	struct dsi_pll_regs *regs = &pll->reg_setup;
+
+	if (pll->pll_configuration.enable_ssc) {
+		pr_debug("SSC is enabled\n");
+
+		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_STEPSIZE_LOW_1,
+			  regs->ssc_stepsize_low);
+		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_STEPSIZE_HIGH_1,
+			  regs->ssc_stepsize_high);
+		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_DIV_PER_LOW_1,
+			  regs->ssc_div_per_low);
+		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_DIV_PER_HIGH_1,
+			  regs->ssc_div_per_high);
+		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_ADJPER_LOW_1,
+			  regs->ssc_adjper_low);
+		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_ADJPER_HIGH_1,
+			  regs->ssc_adjper_high);
+		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_CONTROL,
+			  SSC_EN | regs->ssc_control);
+	}
+}
+
+static void dsi_pll_config_hzindep_reg(struct dsi_pll_7nm *pll)
+{
+	void __iomem *base = pll->mmio;
+	u8 analog_controls_five_1 = 0x01, vco_config_1 = 0x00;
+
+	if (pll->base.type == MSM_DSI_PHY_7NM_V4_1) {
+		if (pll->vco_current_rate >= 3100000000ULL)
+			analog_controls_five_1 = 0x03;
+
+		if (pll->vco_current_rate < 1520000000ULL)
+			vco_config_1 = 0x08;
+		else if (pll->vco_current_rate < 2990000000ULL)
+			vco_config_1 = 0x01;
+	}
+
+	pll_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_FIVE_1,
+		  analog_controls_five_1);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_VCO_CONFIG_1, vco_config_1);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_FIVE, 0x01);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_TWO, 0x03);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_THREE, 0x00);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_DSM_DIVIDER, 0x00);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_FEEDBACK_DIVIDER, 0x4e);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_CALIBRATION_SETTINGS, 0x40);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_BAND_SEL_CAL_SETTINGS_THREE, 0xba);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_FREQ_DETECT_SETTINGS_ONE, 0x0c);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_OUTDIV, 0x00);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_CORE_OVERRIDE, 0x00);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_DIGITAL_TIMERS_TWO, 0x08);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_PROP_GAIN_RATE_1, 0x0a);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_BAND_SEL_RATE_1, 0xc0);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_1, 0x84);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_1, 0x82);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_FL_INT_GAIN_PFILT_BAND_1, 0x4c);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCK_OVERRIDE, 0x80);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_PFILT, 0x29);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_PFILT, 0x2f);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_IFILT, 0x2a);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_IFILT,
+		  pll->base.type == MSM_DSI_PHY_7NM_V4_1 ? 0x3f : 0x22);
+
+	if (pll->base.type == MSM_DSI_PHY_7NM_V4_1) {
+		pll_write(base + REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE, 0x22);
+		if (pll->slave)
+			pll_write(pll->slave->mmio + REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE, 0x22);
+	}
+}
+
+static void dsi_pll_commit(struct dsi_pll_7nm *pll)
+{
+	void __iomem *base = pll->mmio;
+	struct dsi_pll_regs *reg = &pll->reg_setup;
+
+	pll_write(base + REG_DSI_7nm_PHY_PLL_CORE_INPUT_OVERRIDE, 0x12);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_DECIMAL_DIV_START_1, reg->decimal_div_start);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_LOW_1, reg->frac_div_start_low);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_MID_1, reg->frac_div_start_mid);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_HIGH_1, reg->frac_div_start_high);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCKDET_RATE_1, reg->pll_lockdet_rate);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCK_DELAY, 0x06);
+	pll_write(base + REG_DSI_7nm_PHY_PLL_CMODE_1, 0x10); /* TODO: 0x00 for CPHY */
+	pll_write(base + REG_DSI_7nm_PHY_PLL_CLOCK_INVERTERS, reg->pll_clock_inverters);
+}
+
+static int dsi_pll_7nm_vco_set_rate(struct clk_hw *hw, unsigned long rate,
+				     unsigned long parent_rate)
+{
+	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);
+
+	DBG("DSI PLL%d rate=%lu, parent's=%lu", pll_7nm->id, rate,
+	    parent_rate);
+
+	pll_7nm->vco_current_rate = rate;
+	pll_7nm->vco_ref_clk_rate = VCO_REF_CLK_RATE;
+
+	dsi_pll_setup_config(pll_7nm);
+
+	dsi_pll_calc_dec_frac(pll_7nm);
+
+	dsi_pll_calc_ssc(pll_7nm);
+
+	dsi_pll_commit(pll_7nm);
+
+	dsi_pll_config_hzindep_reg(pll_7nm);
+
+	dsi_pll_ssc_commit(pll_7nm);
+
+	/* flush, ensure all register writes are done*/
+	wmb();
+
+	return 0;
+}
+
+static int dsi_pll_7nm_lock_status(struct dsi_pll_7nm *pll)
+{
+	int rc;
+	u32 status = 0;
+	u32 const delay_us = 100;
+	u32 const timeout_us = 5000;
+
+	rc = readl_poll_timeout_atomic(pll->mmio +
+				       REG_DSI_7nm_PHY_PLL_COMMON_STATUS_ONE,
+				       status,
+				       ((status & BIT(0)) > 0),
+				       delay_us,
+				       timeout_us);
+	if (rc)
+		pr_err("DSI PLL(%d) lock failed, status=0x%08x\n",
+		       pll->id, status);
+
+	return rc;
+}
+
+static void dsi_pll_disable_pll_bias(struct dsi_pll_7nm *pll)
+{
+	u32 data = pll_read(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CTRL_0);
+
+	pll_write(pll->mmio + REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES, 0);
+	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CTRL_0, data & ~BIT(5));
+	ndelay(250);
+}
+
+static void dsi_pll_enable_pll_bias(struct dsi_pll_7nm *pll)
+{
+	u32 data = pll_read(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CTRL_0);
+
+	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CTRL_0, data | BIT(5));
+	pll_write(pll->mmio + REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES, 0xc0);
+	ndelay(250);
+}
+
+static void dsi_pll_disable_global_clk(struct dsi_pll_7nm *pll)
+{
+	u32 data;
+
+	data = pll_read(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
+	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CLK_CFG1, data & ~BIT(5));
+}
+
+static void dsi_pll_enable_global_clk(struct dsi_pll_7nm *pll)
+{
+	u32 data;
+
+	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CTRL_3, 0x04);
+
+	data = pll_read(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
+	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CLK_CFG1,
+		  data | BIT(5) | BIT(4));
+}
+
+static void dsi_pll_phy_dig_reset(struct dsi_pll_7nm *pll)
+{
+	/*
+	 * Reset the PHY digital domain. This would be needed when
+	 * coming out of a CX or analog rail power collapse while
+	 * ensuring that the pads maintain LP00 or LP11 state
+	 */
+	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE4, BIT(0));
+	wmb(); /* Ensure that the reset is deasserted */
+	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE4, 0x0);
+	wmb(); /* Ensure that the reset is deasserted */
+}
+
+static int dsi_pll_7nm_vco_prepare(struct clk_hw *hw)
+{
+	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);
+	int rc;
+
+	dsi_pll_enable_pll_bias(pll_7nm);
+	if (pll_7nm->slave)
+		dsi_pll_enable_pll_bias(pll_7nm->slave);
+
+	/* Start PLL */
+	pll_write(pll_7nm->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_PLL_CNTRL, 0x01);
+
+	/*
+	 * ensure all PLL configurations are written prior to checking
+	 * for PLL lock.
+	 */
+	wmb();
+
+	/* Check for PLL lock */
+	rc = dsi_pll_7nm_lock_status(pll_7nm);
+	if (rc) {
+		pr_err("PLL(%d) lock failed\n", pll_7nm->id);
+		goto error;
+	}
+
+	pll->pll_on = true;
+
+	/*
+	 * assert power on reset for PHY digital in case the PLL is
+	 * enabled after CX of analog domain power collapse. This needs
+	 * to be done before enabling the global clk.
+	 */
+	dsi_pll_phy_dig_reset(pll_7nm);
+	if (pll_7nm->slave)
+		dsi_pll_phy_dig_reset(pll_7nm->slave);
+
+	dsi_pll_enable_global_clk(pll_7nm);
+	if (pll_7nm->slave)
+		dsi_pll_enable_global_clk(pll_7nm->slave);
+
+error:
+	return rc;
+}
+
+static void dsi_pll_disable_sub(struct dsi_pll_7nm *pll)
+{
+	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_RBUF_CTRL, 0);
+	dsi_pll_disable_pll_bias(pll);
+}
+
+static void dsi_pll_7nm_vco_unprepare(struct clk_hw *hw)
+{
+	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);
+
+	/*
+	 * To avoid any stray glitches while abruptly powering down the PLL
+	 * make sure to gate the clock using the clock enable bit before
+	 * powering down the PLL
+	 */
+	dsi_pll_disable_global_clk(pll_7nm);
+	pll_write(pll_7nm->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_PLL_CNTRL, 0);
+	dsi_pll_disable_sub(pll_7nm);
+	if (pll_7nm->slave) {
+		dsi_pll_disable_global_clk(pll_7nm->slave);
+		dsi_pll_disable_sub(pll_7nm->slave);
+	}
+	/* flush, ensure all register writes are done */
+	wmb();
+	pll->pll_on = false;
+}
+
+static unsigned long dsi_pll_7nm_vco_recalc_rate(struct clk_hw *hw,
+						  unsigned long parent_rate)
+{
+	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);
+	struct dsi_pll_config *config = &pll_7nm->pll_configuration;
+	void __iomem *base = pll_7nm->mmio;
+	u64 ref_clk = pll_7nm->vco_ref_clk_rate;
+	u64 vco_rate = 0x0;
+	u64 multiplier;
+	u32 frac;
+	u32 dec;
+	u64 pll_freq, tmp64;
+
+	dec = pll_read(base + REG_DSI_7nm_PHY_PLL_DECIMAL_DIV_START_1);
+	dec &= 0xff;
+
+	frac = pll_read(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_LOW_1);
+	frac |= ((pll_read(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_MID_1) &
+		  0xff) << 8);
+	frac |= ((pll_read(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_HIGH_1) &
+		  0x3) << 16);
+
+	/*
+	 * TODO:
+	 *	1. Assumes prescaler is disabled
+	 */
+	multiplier = 1 << config->frac_bits;
+	pll_freq = dec * (ref_clk * 2);
+	tmp64 = (ref_clk * 2 * frac);
+	pll_freq += div_u64(tmp64, multiplier);
+
+	vco_rate = pll_freq;
+
+	DBG("DSI PLL%d returning vco rate = %lu, dec = %x, frac = %x",
+	    pll_7nm->id, (unsigned long)vco_rate, dec, frac);
+
+	return (unsigned long)vco_rate;
+}
+
+static const struct clk_ops clk_ops_dsi_pll_7nm_vco = {
+	.round_rate = msm_dsi_pll_helper_clk_round_rate,
+	.set_rate = dsi_pll_7nm_vco_set_rate,
+	.recalc_rate = dsi_pll_7nm_vco_recalc_rate,
+	.prepare = dsi_pll_7nm_vco_prepare,
+	.unprepare = dsi_pll_7nm_vco_unprepare,
+};
+
+/*
+ * PLL Callbacks
+ */
+
+static void dsi_pll_7nm_save_state(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);
+	struct pll_7nm_cached_state *cached = &pll_7nm->cached_state;
+	void __iomem *phy_base = pll_7nm->phy_cmn_mmio;
+	u32 cmn_clk_cfg0, cmn_clk_cfg1;
+
+	cached->pll_out_div = pll_read(pll_7nm->mmio +
+				       REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE);
+	cached->pll_out_div &= 0x3;
+
+	cmn_clk_cfg0 = pll_read(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0);
+	cached->bit_clk_div = cmn_clk_cfg0 & 0xf;
+	cached->pix_clk_div = (cmn_clk_cfg0 & 0xf0) >> 4;
+
+	cmn_clk_cfg1 = pll_read(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
+	cached->pll_mux = cmn_clk_cfg1 & 0x3;
+
+	DBG("DSI PLL%d outdiv %x bit_clk_div %x pix_clk_div %x pll_mux %x",
+	    pll_7nm->id, cached->pll_out_div, cached->bit_clk_div,
+	    cached->pix_clk_div, cached->pll_mux);
+}
+
+static int dsi_pll_7nm_restore_state(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);
+	struct pll_7nm_cached_state *cached = &pll_7nm->cached_state;
+	void __iomem *phy_base = pll_7nm->phy_cmn_mmio;
+	u32 val;
+	int ret;
+
+	val = pll_read(pll_7nm->mmio + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE);
+	val &= ~0x3;
+	val |= cached->pll_out_div;
+	pll_write(pll_7nm->mmio + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE, val);
+
+	pll_write(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0,
+		  cached->bit_clk_div | (cached->pix_clk_div << 4));
+
+	val = pll_read(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
+	val &= ~0x3;
+	val |= cached->pll_mux;
+	pll_write(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, val);
+
+	ret = dsi_pll_7nm_vco_set_rate(&pll->clk_hw, pll_7nm->vco_current_rate, pll_7nm->vco_ref_clk_rate);
+	if (ret) {
+		DRM_DEV_ERROR(&pll_7nm->pdev->dev,
+			"restore vco rate failed. ret=%d\n", ret);
+		return ret;
+	}
+
+	DBG("DSI PLL%d", pll_7nm->id);
+
+	return 0;
+}
+
+static int dsi_pll_7nm_set_usecase(struct msm_dsi_pll *pll,
+				    enum msm_dsi_phy_usecase uc)
+{
+	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);
+	void __iomem *base = pll_7nm->phy_cmn_mmio;
+	u32 data = 0x0;	/* internal PLL */
+
+	DBG("DSI PLL%d", pll_7nm->id);
+
+	switch (uc) {
+	case MSM_DSI_PHY_STANDALONE:
+		break;
+	case MSM_DSI_PHY_MASTER:
+		pll_7nm->slave = pll_7nm_list[(pll_7nm->id + 1) % DSI_MAX];
+		break;
+	case MSM_DSI_PHY_SLAVE:
+		data = 0x1; /* external PLL */
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* set PLL src */
+	pll_write(base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, (data << 2));
+
+	pll_7nm->uc = uc;
+
+	return 0;
+}
+
+static int dsi_pll_7nm_get_provider(struct msm_dsi_pll *pll,
+				     struct clk **byte_clk_provider,
+				     struct clk **pixel_clk_provider)
+{
+	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);
+	struct clk_hw_onecell_data *hw_data = pll_7nm->hw_data;
+
+	DBG("DSI PLL%d", pll_7nm->id);
+
+	if (byte_clk_provider)
+		*byte_clk_provider = hw_data->hws[DSI_BYTE_PLL_CLK]->clk;
+	if (pixel_clk_provider)
+		*pixel_clk_provider = hw_data->hws[DSI_PIXEL_PLL_CLK]->clk;
+
+	return 0;
+}
+
+static void dsi_pll_7nm_destroy(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);
+	struct device *dev = &pll_7nm->pdev->dev;
+
+	DBG("DSI PLL%d", pll_7nm->id);
+	of_clk_del_provider(dev->of_node);
+
+	clk_hw_unregister_divider(pll_7nm->out_dsiclk_hw);
+	clk_hw_unregister_mux(pll_7nm->pclk_mux_hw);
+	clk_hw_unregister_fixed_factor(pll_7nm->post_out_div_clk_hw);
+	clk_hw_unregister_fixed_factor(pll_7nm->by_2_bit_clk_hw);
+	clk_hw_unregister_fixed_factor(pll_7nm->byte_clk_hw);
+	clk_hw_unregister_divider(pll_7nm->bit_clk_hw);
+	clk_hw_unregister_divider(pll_7nm->out_div_clk_hw);
+	clk_hw_unregister(&pll_7nm->base.clk_hw);
+}
+
+/*
+ * The post dividers and mux clocks are created using the standard divider and
+ * mux API. Unlike the 14nm PHY, the slave PLL doesn't need its dividers/mux
+ * state to follow the master PLL's divider/mux state. Therefore, we don't
+ * require special clock ops that also configure the slave PLL registers
+ */
+static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm)
+{
+	char clk_name[32], parent[32], vco_name[32];
+	char parent2[32], parent3[32], parent4[32];
+	struct clk_init_data vco_init = {
+		.parent_names = (const char *[]){ "bi_tcxo" },
+		.num_parents = 1,
+		.name = vco_name,
+		.flags = CLK_IGNORE_UNUSED,
+		.ops = &clk_ops_dsi_pll_7nm_vco,
+	};
+	struct device *dev = &pll_7nm->pdev->dev;
+	struct clk_hw_onecell_data *hw_data;
+	struct clk_hw *hw;
+	int ret;
+
+	DBG("DSI%d", pll_7nm->id);
+
+	hw_data = devm_kzalloc(dev, sizeof(*hw_data) +
+			       NUM_PROVIDED_CLKS * sizeof(struct clk_hw *),
+			       GFP_KERNEL);
+	if (!hw_data)
+		return -ENOMEM;
+
+	snprintf(vco_name, 32, "dsi%dvco_clk", pll_7nm->id);
+	pll_7nm->base.clk_hw.init = &vco_init;
+
+	ret = clk_hw_register(dev, &pll_7nm->base.clk_hw);
+	if (ret)
+		return ret;
+
+	snprintf(clk_name, 32, "dsi%d_pll_out_div_clk", pll_7nm->id);
+	snprintf(parent, 32, "dsi%dvco_clk", pll_7nm->id);
+
+	hw = clk_hw_register_divider(dev, clk_name,
+				     parent, CLK_SET_RATE_PARENT,
+				     pll_7nm->mmio +
+				     REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE,
+				     0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL);
+	if (IS_ERR(hw)) {
+		ret = PTR_ERR(hw);
+		goto err_base_clk_hw;
+	}
+
+	pll_7nm->out_div_clk_hw = hw;
+
+	snprintf(clk_name, 32, "dsi%d_pll_bit_clk", pll_7nm->id);
+	snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_7nm->id);
+
+	/* BIT CLK: DIV_CTRL_3_0 */
+	hw = clk_hw_register_divider(dev, clk_name, parent,
+				     CLK_SET_RATE_PARENT,
+				     pll_7nm->phy_cmn_mmio +
+				     REG_DSI_7nm_PHY_CMN_CLK_CFG0,
+				     0, 4, CLK_DIVIDER_ONE_BASED,
+				     &pll_7nm->postdiv_lock);
+	if (IS_ERR(hw)) {
+		ret = PTR_ERR(hw);
+		goto err_out_div_clk_hw;
+	}
+
+	pll_7nm->bit_clk_hw = hw;
+
+	snprintf(clk_name, 32, "dsi%d_phy_pll_out_byteclk", pll_7nm->id);
+	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->id);
+
+	/* DSI Byte clock = VCO_CLK / OUT_DIV / BIT_DIV / 8 */
+	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,
+					  CLK_SET_RATE_PARENT, 1, 8);
+	if (IS_ERR(hw)) {
+		ret = PTR_ERR(hw);
+		goto err_bit_clk_hw;
+	}
+
+	pll_7nm->byte_clk_hw = hw;
+	hw_data->hws[DSI_BYTE_PLL_CLK] = hw;
+
+	snprintf(clk_name, 32, "dsi%d_pll_by_2_bit_clk", pll_7nm->id);
+	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->id);
+
+	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,
+					  0, 1, 2);
+	if (IS_ERR(hw)) {
+		ret = PTR_ERR(hw);
+		goto err_byte_clk_hw;
+	}
+
+	pll_7nm->by_2_bit_clk_hw = hw;
+
+	snprintf(clk_name, 32, "dsi%d_pll_post_out_div_clk", pll_7nm->id);
+	snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_7nm->id);
+
+	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,
+					  0, 1, 4);
+	if (IS_ERR(hw)) {
+		ret = PTR_ERR(hw);
+		goto err_by_2_bit_clk_hw;
+	}
+
+	pll_7nm->post_out_div_clk_hw = hw;
+
+	snprintf(clk_name, 32, "dsi%d_pclk_mux", pll_7nm->id);
+	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->id);
+	snprintf(parent2, 32, "dsi%d_pll_by_2_bit_clk", pll_7nm->id);
+	snprintf(parent3, 32, "dsi%d_pll_out_div_clk", pll_7nm->id);
+	snprintf(parent4, 32, "dsi%d_pll_post_out_div_clk", pll_7nm->id);
+
+	hw = clk_hw_register_mux(dev, clk_name,
+				 ((const char *[]){
+				 parent, parent2, parent3, parent4
+				 }), 4, 0, pll_7nm->phy_cmn_mmio +
+				 REG_DSI_7nm_PHY_CMN_CLK_CFG1,
+				 0, 2, 0, NULL);
+	if (IS_ERR(hw)) {
+		ret = PTR_ERR(hw);
+		goto err_post_out_div_clk_hw;
+	}
+
+	pll_7nm->pclk_mux_hw = hw;
+
+	snprintf(clk_name, 32, "dsi%d_phy_pll_out_dsiclk", pll_7nm->id);
+	snprintf(parent, 32, "dsi%d_pclk_mux", pll_7nm->id);
+
+	/* PIX CLK DIV : DIV_CTRL_7_4*/
+	hw = clk_hw_register_divider(dev, clk_name, parent,
+				     0, pll_7nm->phy_cmn_mmio +
+					REG_DSI_7nm_PHY_CMN_CLK_CFG0,
+				     4, 4, CLK_DIVIDER_ONE_BASED,
+				     &pll_7nm->postdiv_lock);
+	if (IS_ERR(hw)) {
+		ret = PTR_ERR(hw);
+		goto err_pclk_mux_hw;
+	}
+
+	pll_7nm->out_dsiclk_hw = hw;
+	hw_data->hws[DSI_PIXEL_PLL_CLK] = hw;
+
+	hw_data->num = NUM_PROVIDED_CLKS;
+	pll_7nm->hw_data = hw_data;
+
+	ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
+				     pll_7nm->hw_data);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret);
+		goto err_dsiclk_hw;
+	}
+
+	return 0;
+
+err_dsiclk_hw:
+	clk_hw_unregister_divider(pll_7nm->out_dsiclk_hw);
+err_pclk_mux_hw:
+	clk_hw_unregister_mux(pll_7nm->pclk_mux_hw);
+err_post_out_div_clk_hw:
+	clk_hw_unregister_fixed_factor(pll_7nm->post_out_div_clk_hw);
+err_by_2_bit_clk_hw:
+	clk_hw_unregister_fixed_factor(pll_7nm->by_2_bit_clk_hw);
+err_byte_clk_hw:
+	clk_hw_unregister_fixed_factor(pll_7nm->byte_clk_hw);
+err_bit_clk_hw:
+	clk_hw_unregister_divider(pll_7nm->bit_clk_hw);
+err_out_div_clk_hw:
+	clk_hw_unregister_divider(pll_7nm->out_div_clk_hw);
+err_base_clk_hw:
+	clk_hw_unregister(&pll_7nm->base.clk_hw);
+
+	return ret;
+}
+
+struct msm_dsi_pll *msm_dsi_pll_7nm_init(struct platform_device *pdev,
+					enum msm_dsi_phy_type type, int id)
+{
+	struct dsi_pll_7nm *pll_7nm;
+	struct msm_dsi_pll *pll;
+	int ret;
+
+	pll_7nm = devm_kzalloc(&pdev->dev, sizeof(*pll_7nm), GFP_KERNEL);
+	if (!pll_7nm)
+		return ERR_PTR(-ENOMEM);
+
+	DBG("DSI PLL%d", id);
+
+	pll_7nm->pdev = pdev;
+	pll_7nm->id = id;
+	pll_7nm_list[id] = pll_7nm;
+
+	pll_7nm->phy_cmn_mmio = msm_ioremap(pdev, "dsi_phy", "DSI_PHY");
+	if (IS_ERR_OR_NULL(pll_7nm->phy_cmn_mmio)) {
+		DRM_DEV_ERROR(&pdev->dev, "failed to map CMN PHY base\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	pll_7nm->mmio = msm_ioremap(pdev, "dsi_pll", "DSI_PLL");
+	if (IS_ERR_OR_NULL(pll_7nm->mmio)) {
+		DRM_DEV_ERROR(&pdev->dev, "failed to map PLL base\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	spin_lock_init(&pll_7nm->postdiv_lock);
+
+	pll = &pll_7nm->base;
+	pll->min_rate = 1000000000UL;
+	pll->max_rate = 3500000000UL;
+	if (type == MSM_DSI_PHY_7NM_V4_1) {
+		pll->min_rate = 600000000UL;
+		pll->max_rate = (unsigned long)5000000000ULL;
+		/* workaround for max rate overflowing on 32-bit builds: */
+		pll->max_rate = max(pll->max_rate, 0xffffffffUL);
+	}
+	pll->get_provider = dsi_pll_7nm_get_provider;
+	pll->destroy = dsi_pll_7nm_destroy;
+	pll->save_state = dsi_pll_7nm_save_state;
+	pll->restore_state = dsi_pll_7nm_restore_state;
+	pll->set_usecase = dsi_pll_7nm_set_usecase;
+
+	pll_7nm->vco_delay = 1;
+
+	ret = pll_7nm_register(pll_7nm);
+	if (ret) {
+		DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret);
+		return ERR_PTR(ret);
+	}
+
+	/* TODO: Remove this when we have proper display handover support */
+	msm_dsi_pll_save_state(pll);
+
+	return pll;
+}
+
 static int dsi_phy_hw_v4_0_is_pll_on(struct msm_dsi_phy *phy)
 {
 	void __iomem *base = phy->base;
diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c b/drivers/gpu/drm/msm/dsi/phy/dsi_pll.c
similarity index 100%
rename from drivers/gpu/drm/msm/dsi/pll/dsi_pll.c
rename to drivers/gpu/drm/msm/dsi/phy/dsi_pll.c
diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h b/drivers/gpu/drm/msm/dsi/phy/dsi_pll.h
similarity index 100%
rename from drivers/gpu/drm/msm/dsi/pll/dsi_pll.h
rename to drivers/gpu/drm/msm/dsi/phy/dsi_pll.h
diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c
deleted file mode 100644
index de3b802ccd3d..000000000000
--- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c
+++ /dev/null
@@ -1,881 +0,0 @@ 
-/*
- * SPDX-License-Identifier: GPL-2.0
- * Copyright (c) 2018, The Linux Foundation
- */
-
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/iopoll.h>
-
-#include "dsi_pll.h"
-#include "dsi.xml.h"
-
-/*
- * DSI PLL 10nm - clock diagram (eg: DSI0):
- *
- *           dsi0_pll_out_div_clk  dsi0_pll_bit_clk
- *                              |                |
- *                              |                |
- *                 +---------+  |  +----------+  |  +----+
- *  dsi0vco_clk ---| out_div |--o--| divl_3_0 |--o--| /8 |-- dsi0_phy_pll_out_byteclk
- *                 +---------+  |  +----------+  |  +----+
- *                              |                |
- *                              |                |         dsi0_pll_by_2_bit_clk
- *                              |                |          |
- *                              |                |  +----+  |  |\  dsi0_pclk_mux
- *                              |                |--| /2 |--o--| \   |
- *                              |                |  +----+     |  \  |  +---------+
- *                              |                --------------|  |--o--| div_7_4 |-- dsi0_phy_pll_out_dsiclk
- *                              |------------------------------|  /     +---------+
- *                              |          +-----+             | /
- *                              -----------| /4? |--o----------|/
- *                                         +-----+  |           |
- *                                                  |           |dsiclk_sel
- *                                                  |
- *                                                  dsi0_pll_post_out_div_clk
- */
-
-#define DSI_BYTE_PLL_CLK		0
-#define DSI_PIXEL_PLL_CLK		1
-#define NUM_PROVIDED_CLKS		2
-
-#define VCO_REF_CLK_RATE		19200000
-
-struct dsi_pll_regs {
-	u32 pll_prop_gain_rate;
-	u32 pll_lockdet_rate;
-	u32 decimal_div_start;
-	u32 frac_div_start_low;
-	u32 frac_div_start_mid;
-	u32 frac_div_start_high;
-	u32 pll_clock_inverters;
-	u32 ssc_stepsize_low;
-	u32 ssc_stepsize_high;
-	u32 ssc_div_per_low;
-	u32 ssc_div_per_high;
-	u32 ssc_adjper_low;
-	u32 ssc_adjper_high;
-	u32 ssc_control;
-};
-
-struct dsi_pll_config {
-	u32 ref_freq;
-	bool div_override;
-	u32 output_div;
-	bool ignore_frac;
-	bool disable_prescaler;
-	bool enable_ssc;
-	bool ssc_center;
-	u32 dec_bits;
-	u32 frac_bits;
-	u32 lock_timer;
-	u32 ssc_freq;
-	u32 ssc_offset;
-	u32 ssc_adj_per;
-	u32 thresh_cycles;
-	u32 refclk_cycles;
-};
-
-struct pll_10nm_cached_state {
-	unsigned long vco_rate;
-	u8 bit_clk_div;
-	u8 pix_clk_div;
-	u8 pll_out_div;
-	u8 pll_mux;
-};
-
-struct dsi_pll_10nm {
-	struct msm_dsi_pll base;
-
-	int id;
-	struct platform_device *pdev;
-
-	void __iomem *phy_cmn_mmio;
-	void __iomem *mmio;
-
-	u64 vco_ref_clk_rate;
-	u64 vco_current_rate;
-
-	/* protects REG_DSI_10nm_PHY_CMN_CLK_CFG0 register */
-	spinlock_t postdiv_lock;
-
-	int vco_delay;
-	struct dsi_pll_config pll_configuration;
-	struct dsi_pll_regs reg_setup;
-
-	/* private clocks: */
-	struct clk_hw *out_div_clk_hw;
-	struct clk_hw *bit_clk_hw;
-	struct clk_hw *byte_clk_hw;
-	struct clk_hw *by_2_bit_clk_hw;
-	struct clk_hw *post_out_div_clk_hw;
-	struct clk_hw *pclk_mux_hw;
-	struct clk_hw *out_dsiclk_hw;
-
-	/* clock-provider: */
-	struct clk_hw_onecell_data *hw_data;
-
-	struct pll_10nm_cached_state cached_state;
-
-	enum msm_dsi_phy_usecase uc;
-	struct dsi_pll_10nm *slave;
-};
-
-#define to_pll_10nm(x)	container_of(x, struct dsi_pll_10nm, base)
-
-/*
- * Global list of private DSI PLL struct pointers. We need this for Dual DSI
- * mode, where the master PLL's clk_ops needs access the slave's private data
- */
-static struct dsi_pll_10nm *pll_10nm_list[DSI_MAX];
-
-static void dsi_pll_setup_config(struct dsi_pll_10nm *pll)
-{
-	struct dsi_pll_config *config = &pll->pll_configuration;
-
-	config->ref_freq = pll->vco_ref_clk_rate;
-	config->output_div = 1;
-	config->dec_bits = 8;
-	config->frac_bits = 18;
-	config->lock_timer = 64;
-	config->ssc_freq = 31500;
-	config->ssc_offset = 5000;
-	config->ssc_adj_per = 2;
-	config->thresh_cycles = 32;
-	config->refclk_cycles = 256;
-
-	config->div_override = false;
-	config->ignore_frac = false;
-	config->disable_prescaler = false;
-
-	config->enable_ssc = false;
-	config->ssc_center = 0;
-}
-
-static void dsi_pll_calc_dec_frac(struct dsi_pll_10nm *pll)
-{
-	struct dsi_pll_config *config = &pll->pll_configuration;
-	struct dsi_pll_regs *regs = &pll->reg_setup;
-	u64 fref = pll->vco_ref_clk_rate;
-	u64 pll_freq;
-	u64 divider;
-	u64 dec, dec_multiple;
-	u32 frac;
-	u64 multiplier;
-
-	pll_freq = pll->vco_current_rate;
-
-	if (config->disable_prescaler)
-		divider = fref;
-	else
-		divider = fref * 2;
-
-	multiplier = 1 << config->frac_bits;
-	dec_multiple = div_u64(pll_freq * multiplier, divider);
-	dec = div_u64_rem(dec_multiple, multiplier, &frac);
-
-	if (pll_freq <= 1900000000UL)
-		regs->pll_prop_gain_rate = 8;
-	else if (pll_freq <= 3000000000UL)
-		regs->pll_prop_gain_rate = 10;
-	else
-		regs->pll_prop_gain_rate = 12;
-	if (pll_freq < 1100000000UL)
-		regs->pll_clock_inverters = 8;
-	else
-		regs->pll_clock_inverters = 0;
-
-	regs->pll_lockdet_rate = config->lock_timer;
-	regs->decimal_div_start = dec;
-	regs->frac_div_start_low = (frac & 0xff);
-	regs->frac_div_start_mid = (frac & 0xff00) >> 8;
-	regs->frac_div_start_high = (frac & 0x30000) >> 16;
-}
-
-#define SSC_CENTER		BIT(0)
-#define SSC_EN			BIT(1)
-
-static void dsi_pll_calc_ssc(struct dsi_pll_10nm *pll)
-{
-	struct dsi_pll_config *config = &pll->pll_configuration;
-	struct dsi_pll_regs *regs = &pll->reg_setup;
-	u32 ssc_per;
-	u32 ssc_mod;
-	u64 ssc_step_size;
-	u64 frac;
-
-	if (!config->enable_ssc) {
-		DBG("SSC not enabled\n");
-		return;
-	}
-
-	ssc_per = DIV_ROUND_CLOSEST(config->ref_freq, config->ssc_freq) / 2 - 1;
-	ssc_mod = (ssc_per + 1) % (config->ssc_adj_per + 1);
-	ssc_per -= ssc_mod;
-
-	frac = regs->frac_div_start_low |
-			(regs->frac_div_start_mid << 8) |
-			(regs->frac_div_start_high << 16);
-	ssc_step_size = regs->decimal_div_start;
-	ssc_step_size *= (1 << config->frac_bits);
-	ssc_step_size += frac;
-	ssc_step_size *= config->ssc_offset;
-	ssc_step_size *= (config->ssc_adj_per + 1);
-	ssc_step_size = div_u64(ssc_step_size, (ssc_per + 1));
-	ssc_step_size = DIV_ROUND_CLOSEST_ULL(ssc_step_size, 1000000);
-
-	regs->ssc_div_per_low = ssc_per & 0xFF;
-	regs->ssc_div_per_high = (ssc_per & 0xFF00) >> 8;
-	regs->ssc_stepsize_low = (u32)(ssc_step_size & 0xFF);
-	regs->ssc_stepsize_high = (u32)((ssc_step_size & 0xFF00) >> 8);
-	regs->ssc_adjper_low = config->ssc_adj_per & 0xFF;
-	regs->ssc_adjper_high = (config->ssc_adj_per & 0xFF00) >> 8;
-
-	regs->ssc_control = config->ssc_center ? SSC_CENTER : 0;
-
-	pr_debug("SCC: Dec:%d, frac:%llu, frac_bits:%d\n",
-		 regs->decimal_div_start, frac, config->frac_bits);
-	pr_debug("SSC: div_per:0x%X, stepsize:0x%X, adjper:0x%X\n",
-		 ssc_per, (u32)ssc_step_size, config->ssc_adj_per);
-}
-
-static void dsi_pll_ssc_commit(struct dsi_pll_10nm *pll)
-{
-	void __iomem *base = pll->mmio;
-	struct dsi_pll_regs *regs = &pll->reg_setup;
-
-	if (pll->pll_configuration.enable_ssc) {
-		pr_debug("SSC is enabled\n");
-
-		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_STEPSIZE_LOW_1,
-			  regs->ssc_stepsize_low);
-		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_STEPSIZE_HIGH_1,
-			  regs->ssc_stepsize_high);
-		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_DIV_PER_LOW_1,
-			  regs->ssc_div_per_low);
-		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_DIV_PER_HIGH_1,
-			  regs->ssc_div_per_high);
-		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_DIV_ADJPER_LOW_1,
-			  regs->ssc_adjper_low);
-		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_DIV_ADJPER_HIGH_1,
-			  regs->ssc_adjper_high);
-		pll_write(base + REG_DSI_10nm_PHY_PLL_SSC_CONTROL,
-			  SSC_EN | regs->ssc_control);
-	}
-}
-
-static void dsi_pll_config_hzindep_reg(struct dsi_pll_10nm *pll)
-{
-	void __iomem *base = pll->mmio;
-
-	pll_write(base + REG_DSI_10nm_PHY_PLL_ANALOG_CONTROLS_ONE, 0x80);
-	pll_write(base + REG_DSI_10nm_PHY_PLL_ANALOG_CONTROLS_TWO, 0x03);
-	pll_write(base + REG_DSI_10nm_PHY_PLL_ANALOG_CONTROLS_THREE, 0x00);
-	pll_write(base + REG_DSI_10nm_PHY_PLL_DSM_DIVIDER, 0x00);
-	pll_write(base + REG_DSI_10nm_PHY_PLL_FEEDBACK_DIVIDER, 0x4e);
-	pll_write(base + REG_DSI_10nm_PHY_PLL_CALIBRATION_SETTINGS, 0x40);
-	pll_write(base + REG_DSI_10nm_PHY_PLL_BAND_SEL_CAL_SETTINGS_THREE,
-		  0xba);
-	pll_write(base + REG_DSI_10nm_PHY_PLL_FREQ_DETECT_SETTINGS_ONE, 0x0c);
-	pll_write(base + REG_DSI_10nm_PHY_PLL_OUTDIV, 0x00);
-	pll_write(base + REG_DSI_10nm_PHY_PLL_CORE_OVERRIDE, 0x00);
-	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_DIGITAL_TIMERS_TWO, 0x08);
-	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_PROP_GAIN_RATE_1, 0x08);
-	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_BAND_SET_RATE_1, 0xc0);
-	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_1, 0xfa);
-	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_FL_INT_GAIN_PFILT_BAND_1,
-		  0x4c);
-	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_LOCK_OVERRIDE, 0x80);
-	pll_write(base + REG_DSI_10nm_PHY_PLL_PFILT, 0x29);
-	pll_write(base + REG_DSI_10nm_PHY_PLL_IFILT, 0x3f);
-}
-
-static void dsi_pll_commit(struct dsi_pll_10nm *pll)
-{
-	void __iomem *base = pll->mmio;
-	struct dsi_pll_regs *reg = &pll->reg_setup;
-
-	pll_write(base + REG_DSI_10nm_PHY_PLL_CORE_INPUT_OVERRIDE, 0x12);
-	pll_write(base + REG_DSI_10nm_PHY_PLL_DECIMAL_DIV_START_1,
-		  reg->decimal_div_start);
-	pll_write(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_LOW_1,
-		  reg->frac_div_start_low);
-	pll_write(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_MID_1,
-		  reg->frac_div_start_mid);
-	pll_write(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_HIGH_1,
-		  reg->frac_div_start_high);
-	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_LOCKDET_RATE_1,
-		  reg->pll_lockdet_rate);
-	pll_write(base + REG_DSI_10nm_PHY_PLL_PLL_LOCK_DELAY, 0x06);
-	pll_write(base + REG_DSI_10nm_PHY_PLL_CMODE, 0x10);
-	pll_write(base + REG_DSI_10nm_PHY_PLL_CLOCK_INVERTERS,
-		  reg->pll_clock_inverters);
-}
-
-static int dsi_pll_10nm_vco_set_rate(struct clk_hw *hw, unsigned long rate,
-				     unsigned long parent_rate)
-{
-	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
-	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);
-
-	DBG("DSI PLL%d rate=%lu, parent's=%lu", pll_10nm->id, rate,
-	    parent_rate);
-
-	pll_10nm->vco_current_rate = rate;
-	pll_10nm->vco_ref_clk_rate = VCO_REF_CLK_RATE;
-
-	dsi_pll_setup_config(pll_10nm);
-
-	dsi_pll_calc_dec_frac(pll_10nm);
-
-	dsi_pll_calc_ssc(pll_10nm);
-
-	dsi_pll_commit(pll_10nm);
-
-	dsi_pll_config_hzindep_reg(pll_10nm);
-
-	dsi_pll_ssc_commit(pll_10nm);
-
-	/* flush, ensure all register writes are done*/
-	wmb();
-
-	return 0;
-}
-
-static int dsi_pll_10nm_lock_status(struct dsi_pll_10nm *pll)
-{
-	struct device *dev = &pll->pdev->dev;
-	int rc;
-	u32 status = 0;
-	u32 const delay_us = 100;
-	u32 const timeout_us = 5000;
-
-	rc = readl_poll_timeout_atomic(pll->mmio +
-				       REG_DSI_10nm_PHY_PLL_COMMON_STATUS_ONE,
-				       status,
-				       ((status & BIT(0)) > 0),
-				       delay_us,
-				       timeout_us);
-	if (rc)
-		DRM_DEV_ERROR(dev, "DSI PLL(%d) lock failed, status=0x%08x\n",
-			      pll->id, status);
-
-	return rc;
-}
-
-static void dsi_pll_disable_pll_bias(struct dsi_pll_10nm *pll)
-{
-	u32 data = pll_read(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CTRL_0);
-
-	pll_write(pll->mmio + REG_DSI_10nm_PHY_PLL_SYSTEM_MUXES, 0);
-	pll_write(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CTRL_0,
-		  data & ~BIT(5));
-	ndelay(250);
-}
-
-static void dsi_pll_enable_pll_bias(struct dsi_pll_10nm *pll)
-{
-	u32 data = pll_read(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CTRL_0);
-
-	pll_write(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CTRL_0,
-		  data | BIT(5));
-	pll_write(pll->mmio + REG_DSI_10nm_PHY_PLL_SYSTEM_MUXES, 0xc0);
-	ndelay(250);
-}
-
-static void dsi_pll_disable_global_clk(struct dsi_pll_10nm *pll)
-{
-	u32 data;
-
-	data = pll_read(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CLK_CFG1);
-	pll_write(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CLK_CFG1,
-		  data & ~BIT(5));
-}
-
-static void dsi_pll_enable_global_clk(struct dsi_pll_10nm *pll)
-{
-	u32 data;
-
-	data = pll_read(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CLK_CFG1);
-	pll_write(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_CLK_CFG1,
-		  data | BIT(5));
-}
-
-static int dsi_pll_10nm_vco_prepare(struct clk_hw *hw)
-{
-	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
-	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);
-	struct device *dev = &pll_10nm->pdev->dev;
-	int rc;
-
-	dsi_pll_enable_pll_bias(pll_10nm);
-	if (pll_10nm->slave)
-		dsi_pll_enable_pll_bias(pll_10nm->slave);
-
-	rc = dsi_pll_10nm_vco_set_rate(hw,pll_10nm->vco_current_rate, 0);
-	if (rc) {
-		DRM_DEV_ERROR(dev, "vco_set_rate failed, rc=%d\n", rc);
-		return rc;
-	}
-
-	/* Start PLL */
-	pll_write(pll_10nm->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_PLL_CNTRL,
-		  0x01);
-
-	/*
-	 * ensure all PLL configurations are written prior to checking
-	 * for PLL lock.
-	 */
-	wmb();
-
-	/* Check for PLL lock */
-	rc = dsi_pll_10nm_lock_status(pll_10nm);
-	if (rc) {
-		DRM_DEV_ERROR(dev, "PLL(%d) lock failed\n", pll_10nm->id);
-		goto error;
-	}
-
-	pll->pll_on = true;
-
-	dsi_pll_enable_global_clk(pll_10nm);
-	if (pll_10nm->slave)
-		dsi_pll_enable_global_clk(pll_10nm->slave);
-
-	pll_write(pll_10nm->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_RBUF_CTRL,
-		  0x01);
-	if (pll_10nm->slave)
-		pll_write(pll_10nm->slave->phy_cmn_mmio +
-			  REG_DSI_10nm_PHY_CMN_RBUF_CTRL, 0x01);
-
-error:
-	return rc;
-}
-
-static void dsi_pll_disable_sub(struct dsi_pll_10nm *pll)
-{
-	pll_write(pll->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_RBUF_CTRL, 0);
-	dsi_pll_disable_pll_bias(pll);
-}
-
-static void dsi_pll_10nm_vco_unprepare(struct clk_hw *hw)
-{
-	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
-	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);
-
-	/*
-	 * To avoid any stray glitches while abruptly powering down the PLL
-	 * make sure to gate the clock using the clock enable bit before
-	 * powering down the PLL
-	 */
-	dsi_pll_disable_global_clk(pll_10nm);
-	pll_write(pll_10nm->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_PLL_CNTRL, 0);
-	dsi_pll_disable_sub(pll_10nm);
-	if (pll_10nm->slave) {
-		dsi_pll_disable_global_clk(pll_10nm->slave);
-		dsi_pll_disable_sub(pll_10nm->slave);
-	}
-	/* flush, ensure all register writes are done */
-	wmb();
-	pll->pll_on = false;
-}
-
-static unsigned long dsi_pll_10nm_vco_recalc_rate(struct clk_hw *hw,
-						  unsigned long parent_rate)
-{
-	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
-	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);
-	struct dsi_pll_config *config = &pll_10nm->pll_configuration;
-	void __iomem *base = pll_10nm->mmio;
-	u64 ref_clk = pll_10nm->vco_ref_clk_rate;
-	u64 vco_rate = 0x0;
-	u64 multiplier;
-	u32 frac;
-	u32 dec;
-	u64 pll_freq, tmp64;
-
-	dec = pll_read(base + REG_DSI_10nm_PHY_PLL_DECIMAL_DIV_START_1);
-	dec &= 0xff;
-
-	frac = pll_read(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_LOW_1);
-	frac |= ((pll_read(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_MID_1) &
-		  0xff) << 8);
-	frac |= ((pll_read(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_HIGH_1) &
-		  0x3) << 16);
-
-	/*
-	 * TODO:
-	 *	1. Assumes prescaler is disabled
-	 */
-	multiplier = 1 << config->frac_bits;
-	pll_freq = dec * (ref_clk * 2);
-	tmp64 = (ref_clk * 2 * frac);
-	pll_freq += div_u64(tmp64, multiplier);
-
-	vco_rate = pll_freq;
-
-	DBG("DSI PLL%d returning vco rate = %lu, dec = %x, frac = %x",
-	    pll_10nm->id, (unsigned long)vco_rate, dec, frac);
-
-	return (unsigned long)vco_rate;
-}
-
-static const struct clk_ops clk_ops_dsi_pll_10nm_vco = {
-	.round_rate = msm_dsi_pll_helper_clk_round_rate,
-	.set_rate = dsi_pll_10nm_vco_set_rate,
-	.recalc_rate = dsi_pll_10nm_vco_recalc_rate,
-	.prepare = dsi_pll_10nm_vco_prepare,
-	.unprepare = dsi_pll_10nm_vco_unprepare,
-};
-
-/*
- * PLL Callbacks
- */
-
-static void dsi_pll_10nm_save_state(struct msm_dsi_pll *pll)
-{
-	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);
-	struct pll_10nm_cached_state *cached = &pll_10nm->cached_state;
-	void __iomem *phy_base = pll_10nm->phy_cmn_mmio;
-	u32 cmn_clk_cfg0, cmn_clk_cfg1;
-
-	cached->pll_out_div = pll_read(pll_10nm->mmio +
-				       REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE);
-	cached->pll_out_div &= 0x3;
-
-	cmn_clk_cfg0 = pll_read(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG0);
-	cached->bit_clk_div = cmn_clk_cfg0 & 0xf;
-	cached->pix_clk_div = (cmn_clk_cfg0 & 0xf0) >> 4;
-
-	cmn_clk_cfg1 = pll_read(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG1);
-	cached->pll_mux = cmn_clk_cfg1 & 0x3;
-
-	DBG("DSI PLL%d outdiv %x bit_clk_div %x pix_clk_div %x pll_mux %x",
-	    pll_10nm->id, cached->pll_out_div, cached->bit_clk_div,
-	    cached->pix_clk_div, cached->pll_mux);
-}
-
-static int dsi_pll_10nm_restore_state(struct msm_dsi_pll *pll)
-{
-	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);
-	struct pll_10nm_cached_state *cached = &pll_10nm->cached_state;
-	void __iomem *phy_base = pll_10nm->phy_cmn_mmio;
-	u32 val;
-	int ret;
-
-	val = pll_read(pll_10nm->mmio + REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE);
-	val &= ~0x3;
-	val |= cached->pll_out_div;
-	pll_write(pll_10nm->mmio + REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE, val);
-
-	pll_write(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG0,
-		  cached->bit_clk_div | (cached->pix_clk_div << 4));
-
-	val = pll_read(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG1);
-	val &= ~0x3;
-	val |= cached->pll_mux;
-	pll_write(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG1, val);
-
-	ret = dsi_pll_10nm_vco_set_rate(&pll->clk_hw, pll_10nm->vco_current_rate, pll_10nm->vco_ref_clk_rate);
-	if (ret) {
-		DRM_DEV_ERROR(&pll_10nm->pdev->dev,
-			"restore vco rate failed. ret=%d\n", ret);
-		return ret;
-	}
-
-	DBG("DSI PLL%d", pll_10nm->id);
-
-	return 0;
-}
-
-static int dsi_pll_10nm_set_usecase(struct msm_dsi_pll *pll,
-				    enum msm_dsi_phy_usecase uc)
-{
-	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);
-	void __iomem *base = pll_10nm->phy_cmn_mmio;
-	u32 data = 0x0;	/* internal PLL */
-
-	DBG("DSI PLL%d", pll_10nm->id);
-
-	switch (uc) {
-	case MSM_DSI_PHY_STANDALONE:
-		break;
-	case MSM_DSI_PHY_MASTER:
-		pll_10nm->slave = pll_10nm_list[(pll_10nm->id + 1) % DSI_MAX];
-		break;
-	case MSM_DSI_PHY_SLAVE:
-		data = 0x1; /* external PLL */
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/* set PLL src */
-	pll_write(base + REG_DSI_10nm_PHY_CMN_CLK_CFG1, (data << 2));
-
-	pll_10nm->uc = uc;
-
-	return 0;
-}
-
-static int dsi_pll_10nm_get_provider(struct msm_dsi_pll *pll,
-				     struct clk **byte_clk_provider,
-				     struct clk **pixel_clk_provider)
-{
-	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);
-	struct clk_hw_onecell_data *hw_data = pll_10nm->hw_data;
-
-	DBG("DSI PLL%d", pll_10nm->id);
-
-	if (byte_clk_provider)
-		*byte_clk_provider = hw_data->hws[DSI_BYTE_PLL_CLK]->clk;
-	if (pixel_clk_provider)
-		*pixel_clk_provider = hw_data->hws[DSI_PIXEL_PLL_CLK]->clk;
-
-	return 0;
-}
-
-static void dsi_pll_10nm_destroy(struct msm_dsi_pll *pll)
-{
-	struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);
-	struct device *dev = &pll_10nm->pdev->dev;
-
-	DBG("DSI PLL%d", pll_10nm->id);
-	of_clk_del_provider(dev->of_node);
-
-	clk_hw_unregister_divider(pll_10nm->out_dsiclk_hw);
-	clk_hw_unregister_mux(pll_10nm->pclk_mux_hw);
-	clk_hw_unregister_fixed_factor(pll_10nm->post_out_div_clk_hw);
-	clk_hw_unregister_fixed_factor(pll_10nm->by_2_bit_clk_hw);
-	clk_hw_unregister_fixed_factor(pll_10nm->byte_clk_hw);
-	clk_hw_unregister_divider(pll_10nm->bit_clk_hw);
-	clk_hw_unregister_divider(pll_10nm->out_div_clk_hw);
-	clk_hw_unregister(&pll_10nm->base.clk_hw);
-}
-
-/*
- * The post dividers and mux clocks are created using the standard divider and
- * mux API. Unlike the 14nm PHY, the slave PLL doesn't need its dividers/mux
- * state to follow the master PLL's divider/mux state. Therefore, we don't
- * require special clock ops that also configure the slave PLL registers
- */
-static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm)
-{
-	char clk_name[32], parent[32], vco_name[32];
-	char parent2[32], parent3[32], parent4[32];
-	struct clk_init_data vco_init = {
-		.parent_names = (const char *[]){ "xo" },
-		.num_parents = 1,
-		.name = vco_name,
-		.flags = CLK_IGNORE_UNUSED,
-		.ops = &clk_ops_dsi_pll_10nm_vco,
-	};
-	struct device *dev = &pll_10nm->pdev->dev;
-	struct clk_hw_onecell_data *hw_data;
-	struct clk_hw *hw;
-	int ret;
-
-	DBG("DSI%d", pll_10nm->id);
-
-	hw_data = devm_kzalloc(dev, sizeof(*hw_data) +
-			       NUM_PROVIDED_CLKS * sizeof(struct clk_hw *),
-			       GFP_KERNEL);
-	if (!hw_data)
-		return -ENOMEM;
-
-	snprintf(vco_name, 32, "dsi%dvco_clk", pll_10nm->id);
-	pll_10nm->base.clk_hw.init = &vco_init;
-
-	ret = clk_hw_register(dev, &pll_10nm->base.clk_hw);
-	if (ret)
-		return ret;
-
-	snprintf(clk_name, 32, "dsi%d_pll_out_div_clk", pll_10nm->id);
-	snprintf(parent, 32, "dsi%dvco_clk", pll_10nm->id);
-
-	hw = clk_hw_register_divider(dev, clk_name,
-				     parent, CLK_SET_RATE_PARENT,
-				     pll_10nm->mmio +
-				     REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE,
-				     0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL);
-	if (IS_ERR(hw)) {
-		ret = PTR_ERR(hw);
-		goto err_base_clk_hw;
-	}
-
-	pll_10nm->out_div_clk_hw = hw;
-
-	snprintf(clk_name, 32, "dsi%d_pll_bit_clk", pll_10nm->id);
-	snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_10nm->id);
-
-	/* BIT CLK: DIV_CTRL_3_0 */
-	hw = clk_hw_register_divider(dev, clk_name, parent,
-				     CLK_SET_RATE_PARENT,
-				     pll_10nm->phy_cmn_mmio +
-				     REG_DSI_10nm_PHY_CMN_CLK_CFG0,
-				     0, 4, CLK_DIVIDER_ONE_BASED,
-				     &pll_10nm->postdiv_lock);
-	if (IS_ERR(hw)) {
-		ret = PTR_ERR(hw);
-		goto err_out_div_clk_hw;
-	}
-
-	pll_10nm->bit_clk_hw = hw;
-
-	snprintf(clk_name, 32, "dsi%d_phy_pll_out_byteclk", pll_10nm->id);
-	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_10nm->id);
-
-	/* DSI Byte clock = VCO_CLK / OUT_DIV / BIT_DIV / 8 */
-	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,
-					  CLK_SET_RATE_PARENT, 1, 8);
-	if (IS_ERR(hw)) {
-		ret = PTR_ERR(hw);
-		goto err_bit_clk_hw;
-	}
-
-	pll_10nm->byte_clk_hw = hw;
-	hw_data->hws[DSI_BYTE_PLL_CLK] = hw;
-
-	snprintf(clk_name, 32, "dsi%d_pll_by_2_bit_clk", pll_10nm->id);
-	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_10nm->id);
-
-	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,
-					  0, 1, 2);
-	if (IS_ERR(hw)) {
-		ret = PTR_ERR(hw);
-		goto err_byte_clk_hw;
-	}
-
-	pll_10nm->by_2_bit_clk_hw = hw;
-
-	snprintf(clk_name, 32, "dsi%d_pll_post_out_div_clk", pll_10nm->id);
-	snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_10nm->id);
-
-	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,
-					  0, 1, 4);
-	if (IS_ERR(hw)) {
-		ret = PTR_ERR(hw);
-		goto err_by_2_bit_clk_hw;
-	}
-
-	pll_10nm->post_out_div_clk_hw = hw;
-
-	snprintf(clk_name, 32, "dsi%d_pclk_mux", pll_10nm->id);
-	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_10nm->id);
-	snprintf(parent2, 32, "dsi%d_pll_by_2_bit_clk", pll_10nm->id);
-	snprintf(parent3, 32, "dsi%d_pll_out_div_clk", pll_10nm->id);
-	snprintf(parent4, 32, "dsi%d_pll_post_out_div_clk", pll_10nm->id);
-
-	hw = clk_hw_register_mux(dev, clk_name,
-				 ((const char *[]){
-				 parent, parent2, parent3, parent4
-				 }), 4, 0, pll_10nm->phy_cmn_mmio +
-				 REG_DSI_10nm_PHY_CMN_CLK_CFG1,
-				 0, 2, 0, NULL);
-	if (IS_ERR(hw)) {
-		ret = PTR_ERR(hw);
-		goto err_post_out_div_clk_hw;
-	}
-
-	pll_10nm->pclk_mux_hw = hw;
-
-	snprintf(clk_name, 32, "dsi%d_phy_pll_out_dsiclk", pll_10nm->id);
-	snprintf(parent, 32, "dsi%d_pclk_mux", pll_10nm->id);
-
-	/* PIX CLK DIV : DIV_CTRL_7_4*/
-	hw = clk_hw_register_divider(dev, clk_name, parent,
-				     0, pll_10nm->phy_cmn_mmio +
-					REG_DSI_10nm_PHY_CMN_CLK_CFG0,
-				     4, 4, CLK_DIVIDER_ONE_BASED,
-				     &pll_10nm->postdiv_lock);
-	if (IS_ERR(hw)) {
-		ret = PTR_ERR(hw);
-		goto err_pclk_mux_hw;
-	}
-
-	pll_10nm->out_dsiclk_hw = hw;
-	hw_data->hws[DSI_PIXEL_PLL_CLK] = hw;
-
-	hw_data->num = NUM_PROVIDED_CLKS;
-	pll_10nm->hw_data = hw_data;
-
-	ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
-				     pll_10nm->hw_data);
-	if (ret) {
-		DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret);
-		goto err_dsiclk_hw;
-	}
-
-	return 0;
-
-err_dsiclk_hw:
-	clk_hw_unregister_divider(pll_10nm->out_dsiclk_hw);
-err_pclk_mux_hw:
-	clk_hw_unregister_mux(pll_10nm->pclk_mux_hw);
-err_post_out_div_clk_hw:
-	clk_hw_unregister_fixed_factor(pll_10nm->post_out_div_clk_hw);
-err_by_2_bit_clk_hw:
-	clk_hw_unregister_fixed_factor(pll_10nm->by_2_bit_clk_hw);
-err_byte_clk_hw:
-	clk_hw_unregister_fixed_factor(pll_10nm->byte_clk_hw);
-err_bit_clk_hw:
-	clk_hw_unregister_divider(pll_10nm->bit_clk_hw);
-err_out_div_clk_hw:
-	clk_hw_unregister_divider(pll_10nm->out_div_clk_hw);
-err_base_clk_hw:
-	clk_hw_unregister(&pll_10nm->base.clk_hw);
-
-	return ret;
-}
-
-struct msm_dsi_pll *msm_dsi_pll_10nm_init(struct platform_device *pdev, int id)
-{
-	struct dsi_pll_10nm *pll_10nm;
-	struct msm_dsi_pll *pll;
-	int ret;
-
-	pll_10nm = devm_kzalloc(&pdev->dev, sizeof(*pll_10nm), GFP_KERNEL);
-	if (!pll_10nm)
-		return ERR_PTR(-ENOMEM);
-
-	DBG("DSI PLL%d", id);
-
-	pll_10nm->pdev = pdev;
-	pll_10nm->id = id;
-	pll_10nm_list[id] = pll_10nm;
-
-	pll_10nm->phy_cmn_mmio = msm_ioremap(pdev, "dsi_phy", "DSI_PHY");
-	if (IS_ERR_OR_NULL(pll_10nm->phy_cmn_mmio)) {
-		DRM_DEV_ERROR(&pdev->dev, "failed to map CMN PHY base\n");
-		return ERR_PTR(-ENOMEM);
-	}
-
-	pll_10nm->mmio = msm_ioremap(pdev, "dsi_pll", "DSI_PLL");
-	if (IS_ERR_OR_NULL(pll_10nm->mmio)) {
-		DRM_DEV_ERROR(&pdev->dev, "failed to map PLL base\n");
-		return ERR_PTR(-ENOMEM);
-	}
-
-	spin_lock_init(&pll_10nm->postdiv_lock);
-
-	pll = &pll_10nm->base;
-	pll->min_rate = 1000000000UL;
-	pll->max_rate = 3500000000UL;
-	pll->get_provider = dsi_pll_10nm_get_provider;
-	pll->destroy = dsi_pll_10nm_destroy;
-	pll->save_state = dsi_pll_10nm_save_state;
-	pll->restore_state = dsi_pll_10nm_restore_state;
-	pll->set_usecase = dsi_pll_10nm_set_usecase;
-
-	pll_10nm->vco_delay = 1;
-
-	ret = pll_10nm_register(pll_10nm);
-	if (ret) {
-		DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret);
-		return ERR_PTR(ret);
-	}
-
-	/* TODO: Remove this when we have proper display handover support */
-	msm_dsi_pll_save_state(pll);
-
-	return pll;
-}
diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c
deleted file mode 100644
index f847376d501e..000000000000
--- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c
+++ /dev/null
@@ -1,1096 +0,0 @@ 
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
- */
-
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-
-#include "dsi_pll.h"
-#include "dsi.xml.h"
-
-/*
- * DSI PLL 14nm - clock diagram (eg: DSI0):
- *
- *         dsi0n1_postdiv_clk
- *                         |
- *                         |
- *                 +----+  |  +----+
- *  dsi0vco_clk ---| n1 |--o--| /8 |-- dsi0pllbyte
- *                 +----+  |  +----+
- *                         |           dsi0n1_postdivby2_clk
- *                         |   +----+  |
- *                         o---| /2 |--o--|\
- *                         |   +----+     | \   +----+
- *                         |              |  |--| n2 |-- dsi0pll
- *                         o--------------| /   +----+
- *                                        |/
- */
-
-#define POLL_MAX_READS			15
-#define POLL_TIMEOUT_US			1000
-
-#define NUM_PROVIDED_CLKS		2
-
-#define VCO_REF_CLK_RATE		19200000
-#define VCO_MIN_RATE			1300000000UL
-#define VCO_MAX_RATE			2600000000UL
-
-#define DSI_BYTE_PLL_CLK		0
-#define DSI_PIXEL_PLL_CLK		1
-
-#define DSI_PLL_DEFAULT_VCO_POSTDIV	1
-
-struct dsi_pll_input {
-	u32 fref;	/* reference clk */
-	u32 fdata;	/* bit clock rate */
-	u32 dsiclk_sel; /* Mux configuration (see diagram) */
-	u32 ssc_en;	/* SSC enable/disable */
-	u32 ldo_en;
-
-	/* fixed params */
-	u32 refclk_dbler_en;
-	u32 vco_measure_time;
-	u32 kvco_measure_time;
-	u32 bandgap_timer;
-	u32 pll_wakeup_timer;
-	u32 plllock_cnt;
-	u32 plllock_rng;
-	u32 ssc_center;
-	u32 ssc_adj_period;
-	u32 ssc_spread;
-	u32 ssc_freq;
-	u32 pll_ie_trim;
-	u32 pll_ip_trim;
-	u32 pll_iptat_trim;
-	u32 pll_cpcset_cur;
-	u32 pll_cpmset_cur;
-
-	u32 pll_icpmset;
-	u32 pll_icpcset;
-
-	u32 pll_icpmset_p;
-	u32 pll_icpmset_m;
-
-	u32 pll_icpcset_p;
-	u32 pll_icpcset_m;
-
-	u32 pll_lpf_res1;
-	u32 pll_lpf_cap1;
-	u32 pll_lpf_cap2;
-	u32 pll_c3ctrl;
-	u32 pll_r3ctrl;
-};
-
-struct dsi_pll_output {
-	u32 pll_txclk_en;
-	u32 dec_start;
-	u32 div_frac_start;
-	u32 ssc_period;
-	u32 ssc_step_size;
-	u32 plllock_cmp;
-	u32 pll_vco_div_ref;
-	u32 pll_vco_count;
-	u32 pll_kvco_div_ref;
-	u32 pll_kvco_count;
-	u32 pll_misc1;
-	u32 pll_lpf2_postdiv;
-	u32 pll_resetsm_cntrl;
-	u32 pll_resetsm_cntrl2;
-	u32 pll_resetsm_cntrl5;
-	u32 pll_kvco_code;
-
-	u32 cmn_clk_cfg0;
-	u32 cmn_clk_cfg1;
-	u32 cmn_ldo_cntrl;
-
-	u32 pll_postdiv;
-	u32 fcvo;
-};
-
-struct pll_14nm_cached_state {
-	unsigned long vco_rate;
-	u8 n2postdiv;
-	u8 n1postdiv;
-};
-
-struct dsi_pll_14nm {
-	struct msm_dsi_pll base;
-
-	int id;
-	struct platform_device *pdev;
-
-	void __iomem *phy_cmn_mmio;
-	void __iomem *mmio;
-
-	int vco_delay;
-
-	struct dsi_pll_input in;
-	struct dsi_pll_output out;
-
-	/* protects REG_DSI_14nm_PHY_CMN_CLK_CFG0 register */
-	spinlock_t postdiv_lock;
-
-	u64 vco_current_rate;
-	u64 vco_ref_clk_rate;
-
-	/* private clocks: */
-	struct clk_hw *hws[NUM_DSI_CLOCKS_MAX];
-	u32 num_hws;
-
-	/* clock-provider: */
-	struct clk_hw_onecell_data *hw_data;
-
-	struct pll_14nm_cached_state cached_state;
-
-	enum msm_dsi_phy_usecase uc;
-	struct dsi_pll_14nm *slave;
-};
-
-#define to_pll_14nm(x)	container_of(x, struct dsi_pll_14nm, base)
-
-/*
- * Private struct for N1/N2 post-divider clocks. These clocks are similar to
- * the generic clk_divider class of clocks. The only difference is that it
- * also sets the slave DSI PLL's post-dividers if in Dual DSI mode
- */
-struct dsi_pll_14nm_postdiv {
-	struct clk_hw hw;
-
-	/* divider params */
-	u8 shift;
-	u8 width;
-	u8 flags; /* same flags as used by clk_divider struct */
-
-	struct dsi_pll_14nm *pll;
-};
-
-#define to_pll_14nm_postdiv(_hw) container_of(_hw, struct dsi_pll_14nm_postdiv, hw)
-
-/*
- * Global list of private DSI PLL struct pointers. We need this for Dual DSI
- * mode, where the master PLL's clk_ops needs access the slave's private data
- */
-static struct dsi_pll_14nm *pll_14nm_list[DSI_MAX];
-
-static bool pll_14nm_poll_for_ready(struct dsi_pll_14nm *pll_14nm,
-				    u32 nb_tries, u32 timeout_us)
-{
-	bool pll_locked = false;
-	void __iomem *base = pll_14nm->mmio;
-	u32 tries, val;
-
-	tries = nb_tries;
-	while (tries--) {
-		val = pll_read(base +
-			       REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS);
-		pll_locked = !!(val & BIT(5));
-
-		if (pll_locked)
-			break;
-
-		udelay(timeout_us);
-	}
-
-	if (!pll_locked) {
-		tries = nb_tries;
-		while (tries--) {
-			val = pll_read(base +
-				REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS);
-			pll_locked = !!(val & BIT(0));
-
-			if (pll_locked)
-				break;
-
-			udelay(timeout_us);
-		}
-	}
-
-	DBG("DSI PLL is %slocked", pll_locked ? "" : "*not* ");
-
-	return pll_locked;
-}
-
-static void dsi_pll_14nm_input_init(struct dsi_pll_14nm *pll)
-{
-	pll->in.fref = pll->vco_ref_clk_rate;
-	pll->in.fdata = 0;
-	pll->in.dsiclk_sel = 1;	/* Use the /2 path in Mux */
-	pll->in.ldo_en = 0;	/* disabled for now */
-
-	/* fixed input */
-	pll->in.refclk_dbler_en = 0;
-	pll->in.vco_measure_time = 5;
-	pll->in.kvco_measure_time = 5;
-	pll->in.bandgap_timer = 4;
-	pll->in.pll_wakeup_timer = 5;
-	pll->in.plllock_cnt = 1;
-	pll->in.plllock_rng = 0;
-
-	/*
-	 * SSC is enabled by default. We might need DT props for configuring
-	 * some SSC params like PPM and center/down spread etc.
-	 */
-	pll->in.ssc_en = 1;
-	pll->in.ssc_center = 0;		/* down spread by default */
-	pll->in.ssc_spread = 5;		/* PPM / 1000 */
-	pll->in.ssc_freq = 31500;	/* default recommended */
-	pll->in.ssc_adj_period = 37;
-
-	pll->in.pll_ie_trim = 4;
-	pll->in.pll_ip_trim = 4;
-	pll->in.pll_cpcset_cur = 1;
-	pll->in.pll_cpmset_cur = 1;
-	pll->in.pll_icpmset = 4;
-	pll->in.pll_icpcset = 4;
-	pll->in.pll_icpmset_p = 0;
-	pll->in.pll_icpmset_m = 0;
-	pll->in.pll_icpcset_p = 0;
-	pll->in.pll_icpcset_m = 0;
-	pll->in.pll_lpf_res1 = 3;
-	pll->in.pll_lpf_cap1 = 11;
-	pll->in.pll_lpf_cap2 = 1;
-	pll->in.pll_iptat_trim = 7;
-	pll->in.pll_c3ctrl = 2;
-	pll->in.pll_r3ctrl = 1;
-}
-
-#define CEIL(x, y)		(((x) + ((y) - 1)) / (y))
-
-static void pll_14nm_ssc_calc(struct dsi_pll_14nm *pll)
-{
-	u32 period, ssc_period;
-	u32 ref, rem;
-	u64 step_size;
-
-	DBG("vco=%lld ref=%lld", pll->vco_current_rate, pll->vco_ref_clk_rate);
-
-	ssc_period = pll->in.ssc_freq / 500;
-	period = (u32)pll->vco_ref_clk_rate / 1000;
-	ssc_period  = CEIL(period, ssc_period);
-	ssc_period -= 1;
-	pll->out.ssc_period = ssc_period;
-
-	DBG("ssc freq=%d spread=%d period=%d", pll->in.ssc_freq,
-	    pll->in.ssc_spread, pll->out.ssc_period);
-
-	step_size = (u32)pll->vco_current_rate;
-	ref = pll->vco_ref_clk_rate;
-	ref /= 1000;
-	step_size = div_u64(step_size, ref);
-	step_size <<= 20;
-	step_size = div_u64(step_size, 1000);
-	step_size *= pll->in.ssc_spread;
-	step_size = div_u64(step_size, 1000);
-	step_size *= (pll->in.ssc_adj_period + 1);
-
-	rem = 0;
-	step_size = div_u64_rem(step_size, ssc_period + 1, &rem);
-	if (rem)
-		step_size++;
-
-	DBG("step_size=%lld", step_size);
-
-	step_size &= 0x0ffff;	/* take lower 16 bits */
-
-	pll->out.ssc_step_size = step_size;
-}
-
-static void pll_14nm_dec_frac_calc(struct dsi_pll_14nm *pll)
-{
-	struct dsi_pll_input *pin = &pll->in;
-	struct dsi_pll_output *pout = &pll->out;
-	u64 multiplier = BIT(20);
-	u64 dec_start_multiple, dec_start, pll_comp_val;
-	u32 duration, div_frac_start;
-	u64 vco_clk_rate = pll->vco_current_rate;
-	u64 fref = pll->vco_ref_clk_rate;
-
-	DBG("vco_clk_rate=%lld ref_clk_rate=%lld", vco_clk_rate, fref);
-
-	dec_start_multiple = div_u64(vco_clk_rate * multiplier, fref);
-	div_u64_rem(dec_start_multiple, multiplier, &div_frac_start);
-
-	dec_start = div_u64(dec_start_multiple, multiplier);
-
-	pout->dec_start = (u32)dec_start;
-	pout->div_frac_start = div_frac_start;
-
-	if (pin->plllock_cnt == 0)
-		duration = 1024;
-	else if (pin->plllock_cnt == 1)
-		duration = 256;
-	else if (pin->plllock_cnt == 2)
-		duration = 128;
-	else
-		duration = 32;
-
-	pll_comp_val = duration * dec_start_multiple;
-	pll_comp_val = div_u64(pll_comp_val, multiplier);
-	do_div(pll_comp_val, 10);
-
-	pout->plllock_cmp = (u32)pll_comp_val;
-
-	pout->pll_txclk_en = 1;
-	pout->cmn_ldo_cntrl = 0x3c;
-}
-
-static u32 pll_14nm_kvco_slop(u32 vrate)
-{
-	u32 slop = 0;
-
-	if (vrate > VCO_MIN_RATE && vrate <= 1800000000UL)
-		slop =  600;
-	else if (vrate > 1800000000UL && vrate < 2300000000UL)
-		slop = 400;
-	else if (vrate > 2300000000UL && vrate < VCO_MAX_RATE)
-		slop = 280;
-
-	return slop;
-}
-
-static void pll_14nm_calc_vco_count(struct dsi_pll_14nm *pll)
-{
-	struct dsi_pll_input *pin = &pll->in;
-	struct dsi_pll_output *pout = &pll->out;
-	u64 vco_clk_rate = pll->vco_current_rate;
-	u64 fref = pll->vco_ref_clk_rate;
-	u64 data;
-	u32 cnt;
-
-	data = fref * pin->vco_measure_time;
-	do_div(data, 1000000);
-	data &= 0x03ff;	/* 10 bits */
-	data -= 2;
-	pout->pll_vco_div_ref = data;
-
-	data = div_u64(vco_clk_rate, 1000000);	/* unit is Mhz */
-	data *= pin->vco_measure_time;
-	do_div(data, 10);
-	pout->pll_vco_count = data;
-
-	data = fref * pin->kvco_measure_time;
-	do_div(data, 1000000);
-	data &= 0x03ff;	/* 10 bits */
-	data -= 1;
-	pout->pll_kvco_div_ref = data;
-
-	cnt = pll_14nm_kvco_slop(vco_clk_rate);
-	cnt *= 2;
-	cnt /= 100;
-	cnt *= pin->kvco_measure_time;
-	pout->pll_kvco_count = cnt;
-
-	pout->pll_misc1 = 16;
-	pout->pll_resetsm_cntrl = 48;
-	pout->pll_resetsm_cntrl2 = pin->bandgap_timer << 3;
-	pout->pll_resetsm_cntrl5 = pin->pll_wakeup_timer;
-	pout->pll_kvco_code = 0;
-}
-
-static void pll_db_commit_ssc(struct dsi_pll_14nm *pll)
-{
-	void __iomem *base = pll->mmio;
-	struct dsi_pll_input *pin = &pll->in;
-	struct dsi_pll_output *pout = &pll->out;
-	u8 data;
-
-	data = pin->ssc_adj_period;
-	data &= 0x0ff;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_ADJ_PER1, data);
-	data = (pin->ssc_adj_period >> 8);
-	data &= 0x03;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_ADJ_PER2, data);
-
-	data = pout->ssc_period;
-	data &= 0x0ff;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_PER1, data);
-	data = (pout->ssc_period >> 8);
-	data &= 0x0ff;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_PER2, data);
-
-	data = pout->ssc_step_size;
-	data &= 0x0ff;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_STEP_SIZE1, data);
-	data = (pout->ssc_step_size >> 8);
-	data &= 0x0ff;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_STEP_SIZE2, data);
-
-	data = (pin->ssc_center & 0x01);
-	data <<= 1;
-	data |= 0x01; /* enable */
-	pll_write(base + REG_DSI_14nm_PHY_PLL_SSC_EN_CENTER, data);
-
-	wmb();	/* make sure register committed */
-}
-
-static void pll_db_commit_common(struct dsi_pll_14nm *pll,
-				 struct dsi_pll_input *pin,
-				 struct dsi_pll_output *pout)
-{
-	void __iomem *base = pll->mmio;
-	u8 data;
-
-	/* confgiure the non frequency dependent pll registers */
-	data = 0;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_SYSCLK_EN_RESET, data);
-
-	data = pout->pll_txclk_en;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_TXCLK_EN, data);
-
-	data = pout->pll_resetsm_cntrl;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL, data);
-	data = pout->pll_resetsm_cntrl2;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL2, data);
-	data = pout->pll_resetsm_cntrl5;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL5, data);
-
-	data = pout->pll_vco_div_ref & 0xff;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_VCO_DIV_REF1, data);
-	data = (pout->pll_vco_div_ref >> 8) & 0x3;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_VCO_DIV_REF2, data);
-
-	data = pout->pll_kvco_div_ref & 0xff;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_KVCO_DIV_REF1, data);
-	data = (pout->pll_kvco_div_ref >> 8) & 0x3;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_KVCO_DIV_REF2, data);
-
-	data = pout->pll_misc1;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_MISC1, data);
-
-	data = pin->pll_ie_trim;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_IE_TRIM, data);
-
-	data = pin->pll_ip_trim;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_IP_TRIM, data);
-
-	data = pin->pll_cpmset_cur << 3 | pin->pll_cpcset_cur;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_CP_SET_CUR, data);
-
-	data = pin->pll_icpcset_p << 3 | pin->pll_icpcset_m;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_ICPCSET, data);
-
-	data = pin->pll_icpmset_p << 3 | pin->pll_icpcset_m;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_ICPMSET, data);
-
-	data = pin->pll_icpmset << 3 | pin->pll_icpcset;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_ICP_SET, data);
-
-	data = pin->pll_lpf_cap2 << 4 | pin->pll_lpf_cap1;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_LPF1, data);
-
-	data = pin->pll_iptat_trim;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_IPTAT_TRIM, data);
-
-	data = pin->pll_c3ctrl | pin->pll_r3ctrl << 4;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_CRCTRL, data);
-}
-
-static void pll_14nm_software_reset(struct dsi_pll_14nm *pll_14nm)
-{
-	void __iomem *cmn_base = pll_14nm->phy_cmn_mmio;
-
-	/* de assert pll start and apply pll sw reset */
-
-	/* stop pll */
-	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL, 0);
-
-	/* pll sw reset */
-	pll_write_udelay(cmn_base + REG_DSI_14nm_PHY_CMN_CTRL_1, 0x20, 10);
-	wmb();	/* make sure register committed */
-
-	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_CTRL_1, 0);
-	wmb();	/* make sure register committed */
-}
-
-static void pll_db_commit_14nm(struct dsi_pll_14nm *pll,
-			       struct dsi_pll_input *pin,
-			       struct dsi_pll_output *pout)
-{
-	void __iomem *base = pll->mmio;
-	void __iomem *cmn_base = pll->phy_cmn_mmio;
-	u8 data;
-
-	DBG("DSI%d PLL", pll->id);
-
-	data = pout->cmn_ldo_cntrl;
-	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_LDO_CNTRL, data);
-
-	pll_db_commit_common(pll, pin, pout);
-
-	pll_14nm_software_reset(pll);
-
-	data = pin->dsiclk_sel; /* set dsiclk_sel = 1  */
-	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_CLK_CFG1, data);
-
-	data = 0xff; /* data, clk, pll normal operation */
-	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_CTRL_0, data);
-
-	/* configure the frequency dependent pll registers */
-	data = pout->dec_start;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_DEC_START, data);
-
-	data = pout->div_frac_start & 0xff;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START1, data);
-	data = (pout->div_frac_start >> 8) & 0xff;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START2, data);
-	data = (pout->div_frac_start >> 16) & 0xf;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START3, data);
-
-	data = pout->plllock_cmp & 0xff;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP1, data);
-
-	data = (pout->plllock_cmp >> 8) & 0xff;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP2, data);
-
-	data = (pout->plllock_cmp >> 16) & 0x3;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP3, data);
-
-	data = pin->plllock_cnt << 1 | pin->plllock_rng << 3;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP_EN, data);
-
-	data = pout->pll_vco_count & 0xff;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_VCO_COUNT1, data);
-	data = (pout->pll_vco_count >> 8) & 0xff;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_VCO_COUNT2, data);
-
-	data = pout->pll_kvco_count & 0xff;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_KVCO_COUNT1, data);
-	data = (pout->pll_kvco_count >> 8) & 0x3;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_KVCO_COUNT2, data);
-
-	data = (pout->pll_postdiv - 1) << 4 | pin->pll_lpf_res1;
-	pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_LPF2_POSTDIV, data);
-
-	if (pin->ssc_en)
-		pll_db_commit_ssc(pll);
-
-	wmb();	/* make sure register committed */
-}
-
-/*
- * VCO clock Callbacks
- */
-static int dsi_pll_14nm_vco_set_rate(struct clk_hw *hw, unsigned long rate,
-				     unsigned long parent_rate)
-{
-	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
-	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);
-	struct dsi_pll_input *pin = &pll_14nm->in;
-	struct dsi_pll_output *pout = &pll_14nm->out;
-
-	DBG("DSI PLL%d rate=%lu, parent's=%lu", pll_14nm->id, rate,
-	    parent_rate);
-
-	pll_14nm->vco_current_rate = rate;
-	pll_14nm->vco_ref_clk_rate = VCO_REF_CLK_RATE;
-
-	dsi_pll_14nm_input_init(pll_14nm);
-
-	/*
-	 * This configures the post divider internal to the VCO. It's
-	 * fixed to divide by 1 for now.
-	 *
-	 * tx_band = pll_postdiv.
-	 * 0: divided by 1
-	 * 1: divided by 2
-	 * 2: divided by 4
-	 * 3: divided by 8
-	 */
-	pout->pll_postdiv = DSI_PLL_DEFAULT_VCO_POSTDIV;
-
-	pll_14nm_dec_frac_calc(pll_14nm);
-
-	if (pin->ssc_en)
-		pll_14nm_ssc_calc(pll_14nm);
-
-	pll_14nm_calc_vco_count(pll_14nm);
-
-	/* commit the slave DSI PLL registers if we're master. Note that we
-	 * don't lock the slave PLL. We just ensure that the PLL/PHY registers
-	 * of the master and slave are identical
-	 */
-	if (pll_14nm->uc == MSM_DSI_PHY_MASTER) {
-		struct dsi_pll_14nm *pll_14nm_slave = pll_14nm->slave;
-
-		pll_db_commit_14nm(pll_14nm_slave, pin, pout);
-	}
-
-	pll_db_commit_14nm(pll_14nm, pin, pout);
-
-	return 0;
-}
-
-static unsigned long dsi_pll_14nm_vco_recalc_rate(struct clk_hw *hw,
-						  unsigned long parent_rate)
-{
-	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
-	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);
-	void __iomem *base = pll_14nm->mmio;
-	u64 vco_rate, multiplier = BIT(20);
-	u32 div_frac_start;
-	u32 dec_start;
-	u64 ref_clk = parent_rate;
-
-	dec_start = pll_read(base + REG_DSI_14nm_PHY_PLL_DEC_START);
-	dec_start &= 0x0ff;
-
-	DBG("dec_start = %x", dec_start);
-
-	div_frac_start = (pll_read(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START3)
-				& 0xf) << 16;
-	div_frac_start |= (pll_read(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START2)
-				& 0xff) << 8;
-	div_frac_start |= pll_read(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START1)
-				& 0xff;
-
-	DBG("div_frac_start = %x", div_frac_start);
-
-	vco_rate = ref_clk * dec_start;
-
-	vco_rate += ((ref_clk * div_frac_start) / multiplier);
-
-	/*
-	 * Recalculating the rate from dec_start and frac_start doesn't end up
-	 * the rate we originally set. Convert the freq to KHz, round it up and
-	 * convert it back to MHz.
-	 */
-	vco_rate = DIV_ROUND_UP_ULL(vco_rate, 1000) * 1000;
-
-	DBG("returning vco rate = %lu", (unsigned long)vco_rate);
-
-	return (unsigned long)vco_rate;
-}
-
-static const struct clk_ops clk_ops_dsi_pll_14nm_vco = {
-	.round_rate = msm_dsi_pll_helper_clk_round_rate,
-	.set_rate = dsi_pll_14nm_vco_set_rate,
-	.recalc_rate = dsi_pll_14nm_vco_recalc_rate,
-	.prepare = msm_dsi_pll_helper_clk_prepare,
-	.unprepare = msm_dsi_pll_helper_clk_unprepare,
-};
-
-/*
- * N1 and N2 post-divider clock callbacks
- */
-#define div_mask(width)	((1 << (width)) - 1)
-static unsigned long dsi_pll_14nm_postdiv_recalc_rate(struct clk_hw *hw,
-						      unsigned long parent_rate)
-{
-	struct dsi_pll_14nm_postdiv *postdiv = to_pll_14nm_postdiv(hw);
-	struct dsi_pll_14nm *pll_14nm = postdiv->pll;
-	void __iomem *base = pll_14nm->phy_cmn_mmio;
-	u8 shift = postdiv->shift;
-	u8 width = postdiv->width;
-	u32 val;
-
-	DBG("DSI%d PLL parent rate=%lu", pll_14nm->id, parent_rate);
-
-	val = pll_read(base + REG_DSI_14nm_PHY_CMN_CLK_CFG0) >> shift;
-	val &= div_mask(width);
-
-	return divider_recalc_rate(hw, parent_rate, val, NULL,
-				   postdiv->flags, width);
-}
-
-static long dsi_pll_14nm_postdiv_round_rate(struct clk_hw *hw,
-					    unsigned long rate,
-					    unsigned long *prate)
-{
-	struct dsi_pll_14nm_postdiv *postdiv = to_pll_14nm_postdiv(hw);
-	struct dsi_pll_14nm *pll_14nm = postdiv->pll;
-
-	DBG("DSI%d PLL parent rate=%lu", pll_14nm->id, rate);
-
-	return divider_round_rate(hw, rate, prate, NULL,
-				  postdiv->width,
-				  postdiv->flags);
-}
-
-static int dsi_pll_14nm_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
-					 unsigned long parent_rate)
-{
-	struct dsi_pll_14nm_postdiv *postdiv = to_pll_14nm_postdiv(hw);
-	struct dsi_pll_14nm *pll_14nm = postdiv->pll;
-	void __iomem *base = pll_14nm->phy_cmn_mmio;
-	spinlock_t *lock = &pll_14nm->postdiv_lock;
-	u8 shift = postdiv->shift;
-	u8 width = postdiv->width;
-	unsigned int value;
-	unsigned long flags = 0;
-	u32 val;
-
-	DBG("DSI%d PLL parent rate=%lu parent rate %lu", pll_14nm->id, rate,
-	    parent_rate);
-
-	value = divider_get_val(rate, parent_rate, NULL, postdiv->width,
-				postdiv->flags);
-
-	spin_lock_irqsave(lock, flags);
-
-	val = pll_read(base + REG_DSI_14nm_PHY_CMN_CLK_CFG0);
-	val &= ~(div_mask(width) << shift);
-
-	val |= value << shift;
-	pll_write(base + REG_DSI_14nm_PHY_CMN_CLK_CFG0, val);
-
-	/* If we're master in dual DSI mode, then the slave PLL's post-dividers
-	 * follow the master's post dividers
-	 */
-	if (pll_14nm->uc == MSM_DSI_PHY_MASTER) {
-		struct dsi_pll_14nm *pll_14nm_slave = pll_14nm->slave;
-		void __iomem *slave_base = pll_14nm_slave->phy_cmn_mmio;
-
-		pll_write(slave_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0, val);
-	}
-
-	spin_unlock_irqrestore(lock, flags);
-
-	return 0;
-}
-
-static const struct clk_ops clk_ops_dsi_pll_14nm_postdiv = {
-	.recalc_rate = dsi_pll_14nm_postdiv_recalc_rate,
-	.round_rate = dsi_pll_14nm_postdiv_round_rate,
-	.set_rate = dsi_pll_14nm_postdiv_set_rate,
-};
-
-/*
- * PLL Callbacks
- */
-
-static int dsi_pll_14nm_enable_seq(struct msm_dsi_pll *pll)
-{
-	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);
-	void __iomem *base = pll_14nm->mmio;
-	void __iomem *cmn_base = pll_14nm->phy_cmn_mmio;
-	bool locked;
-
-	DBG("");
-
-	pll_write(base + REG_DSI_14nm_PHY_PLL_VREF_CFG1, 0x10);
-	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL, 1);
-
-	locked = pll_14nm_poll_for_ready(pll_14nm, POLL_MAX_READS,
-					 POLL_TIMEOUT_US);
-
-	if (unlikely(!locked))
-		DRM_DEV_ERROR(&pll_14nm->pdev->dev, "DSI PLL lock failed\n");
-	else
-		DBG("DSI PLL lock success");
-
-	return locked ? 0 : -EINVAL;
-}
-
-static void dsi_pll_14nm_disable_seq(struct msm_dsi_pll *pll)
-{
-	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);
-	void __iomem *cmn_base = pll_14nm->phy_cmn_mmio;
-
-	DBG("");
-
-	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL, 0);
-}
-
-static void dsi_pll_14nm_save_state(struct msm_dsi_pll *pll)
-{
-	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);
-	struct pll_14nm_cached_state *cached_state = &pll_14nm->cached_state;
-	void __iomem *cmn_base = pll_14nm->phy_cmn_mmio;
-	u32 data;
-
-	data = pll_read(cmn_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0);
-
-	cached_state->n1postdiv = data & 0xf;
-	cached_state->n2postdiv = (data >> 4) & 0xf;
-
-	DBG("DSI%d PLL save state %x %x", pll_14nm->id,
-	    cached_state->n1postdiv, cached_state->n2postdiv);
-
-	cached_state->vco_rate = clk_hw_get_rate(&pll->clk_hw);
-}
-
-static int dsi_pll_14nm_restore_state(struct msm_dsi_pll *pll)
-{
-	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);
-	struct pll_14nm_cached_state *cached_state = &pll_14nm->cached_state;
-	void __iomem *cmn_base = pll_14nm->phy_cmn_mmio;
-	u32 data;
-	int ret;
-
-	ret = dsi_pll_14nm_vco_set_rate(&pll->clk_hw,
-					cached_state->vco_rate, 0);
-	if (ret) {
-		DRM_DEV_ERROR(&pll_14nm->pdev->dev,
-			"restore vco rate failed. ret=%d\n", ret);
-		return ret;
-	}
-
-	data = cached_state->n1postdiv | (cached_state->n2postdiv << 4);
-
-	DBG("DSI%d PLL restore state %x %x", pll_14nm->id,
-	    cached_state->n1postdiv, cached_state->n2postdiv);
-
-	pll_write(cmn_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0, data);
-
-	/* also restore post-dividers for slave DSI PLL */
-	if (pll_14nm->uc == MSM_DSI_PHY_MASTER) {
-		struct dsi_pll_14nm *pll_14nm_slave = pll_14nm->slave;
-		void __iomem *slave_base = pll_14nm_slave->phy_cmn_mmio;
-
-		pll_write(slave_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0, data);
-	}
-
-	return 0;
-}
-
-static int dsi_pll_14nm_set_usecase(struct msm_dsi_pll *pll,
-				    enum msm_dsi_phy_usecase uc)
-{
-	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);
-	void __iomem *base = pll_14nm->mmio;
-	u32 clkbuflr_en, bandgap = 0;
-
-	switch (uc) {
-	case MSM_DSI_PHY_STANDALONE:
-		clkbuflr_en = 0x1;
-		break;
-	case MSM_DSI_PHY_MASTER:
-		clkbuflr_en = 0x3;
-		pll_14nm->slave = pll_14nm_list[(pll_14nm->id + 1) % DSI_MAX];
-		break;
-	case MSM_DSI_PHY_SLAVE:
-		clkbuflr_en = 0x0;
-		bandgap = 0x3;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	pll_write(base + REG_DSI_14nm_PHY_PLL_CLKBUFLR_EN, clkbuflr_en);
-	if (bandgap)
-		pll_write(base + REG_DSI_14nm_PHY_PLL_PLL_BANDGAP, bandgap);
-
-	pll_14nm->uc = uc;
-
-	return 0;
-}
-
-static int dsi_pll_14nm_get_provider(struct msm_dsi_pll *pll,
-				     struct clk **byte_clk_provider,
-				     struct clk **pixel_clk_provider)
-{
-	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);
-	struct clk_hw_onecell_data *hw_data = pll_14nm->hw_data;
-
-	if (byte_clk_provider)
-		*byte_clk_provider = hw_data->hws[DSI_BYTE_PLL_CLK]->clk;
-	if (pixel_clk_provider)
-		*pixel_clk_provider = hw_data->hws[DSI_PIXEL_PLL_CLK]->clk;
-
-	return 0;
-}
-
-static void dsi_pll_14nm_destroy(struct msm_dsi_pll *pll)
-{
-	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(pll);
-	struct platform_device *pdev = pll_14nm->pdev;
-	int num_hws = pll_14nm->num_hws;
-
-	of_clk_del_provider(pdev->dev.of_node);
-
-	while (num_hws--)
-		clk_hw_unregister(pll_14nm->hws[num_hws]);
-}
-
-static struct clk_hw *pll_14nm_postdiv_register(struct dsi_pll_14nm *pll_14nm,
-						const char *name,
-						const char *parent_name,
-						unsigned long flags,
-						u8 shift)
-{
-	struct dsi_pll_14nm_postdiv *pll_postdiv;
-	struct device *dev = &pll_14nm->pdev->dev;
-	struct clk_init_data postdiv_init = {
-		.parent_names = (const char *[]) { parent_name },
-		.num_parents = 1,
-		.name = name,
-		.flags = flags,
-		.ops = &clk_ops_dsi_pll_14nm_postdiv,
-	};
-	int ret;
-
-	pll_postdiv = devm_kzalloc(dev, sizeof(*pll_postdiv), GFP_KERNEL);
-	if (!pll_postdiv)
-		return ERR_PTR(-ENOMEM);
-
-	pll_postdiv->pll = pll_14nm;
-	pll_postdiv->shift = shift;
-	/* both N1 and N2 postdividers are 4 bits wide */
-	pll_postdiv->width = 4;
-	/* range of each divider is from 1 to 15 */
-	pll_postdiv->flags = CLK_DIVIDER_ONE_BASED;
-	pll_postdiv->hw.init = &postdiv_init;
-
-	ret = clk_hw_register(dev, &pll_postdiv->hw);
-	if (ret)
-		return ERR_PTR(ret);
-
-	return &pll_postdiv->hw;
-}
-
-static int pll_14nm_register(struct dsi_pll_14nm *pll_14nm)
-{
-	char clk_name[32], parent[32], vco_name[32];
-	struct clk_init_data vco_init = {
-		.parent_names = (const char *[]){ "xo" },
-		.num_parents = 1,
-		.name = vco_name,
-		.flags = CLK_IGNORE_UNUSED,
-		.ops = &clk_ops_dsi_pll_14nm_vco,
-	};
-	struct device *dev = &pll_14nm->pdev->dev;
-	struct clk_hw **hws = pll_14nm->hws;
-	struct clk_hw_onecell_data *hw_data;
-	struct clk_hw *hw;
-	int num = 0;
-	int ret;
-
-	DBG("DSI%d", pll_14nm->id);
-
-	hw_data = devm_kzalloc(dev, sizeof(*hw_data) +
-			       NUM_PROVIDED_CLKS * sizeof(struct clk_hw *),
-			       GFP_KERNEL);
-	if (!hw_data)
-		return -ENOMEM;
-
-	snprintf(vco_name, 32, "dsi%dvco_clk", pll_14nm->id);
-	pll_14nm->base.clk_hw.init = &vco_init;
-
-	ret = clk_hw_register(dev, &pll_14nm->base.clk_hw);
-	if (ret)
-		return ret;
-
-	hws[num++] = &pll_14nm->base.clk_hw;
-
-	snprintf(clk_name, 32, "dsi%dn1_postdiv_clk", pll_14nm->id);
-	snprintf(parent, 32, "dsi%dvco_clk", pll_14nm->id);
-
-	/* N1 postdiv, bits 0-3 in REG_DSI_14nm_PHY_CMN_CLK_CFG0 */
-	hw = pll_14nm_postdiv_register(pll_14nm, clk_name, parent,
-				       CLK_SET_RATE_PARENT, 0);
-	if (IS_ERR(hw))
-		return PTR_ERR(hw);
-
-	hws[num++] = hw;
-
-	snprintf(clk_name, 32, "dsi%dpllbyte", pll_14nm->id);
-	snprintf(parent, 32, "dsi%dn1_postdiv_clk", pll_14nm->id);
-
-	/* DSI Byte clock = VCO_CLK / N1 / 8 */
-	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,
-					  CLK_SET_RATE_PARENT, 1, 8);
-	if (IS_ERR(hw))
-		return PTR_ERR(hw);
-
-	hws[num++] = hw;
-	hw_data->hws[DSI_BYTE_PLL_CLK] = hw;
-
-	snprintf(clk_name, 32, "dsi%dn1_postdivby2_clk", pll_14nm->id);
-	snprintf(parent, 32, "dsi%dn1_postdiv_clk", pll_14nm->id);
-
-	/*
-	 * Skip the mux for now, force DSICLK_SEL to 1, Add a /2 divider
-	 * on the way. Don't let it set parent.
-	 */
-	hw = clk_hw_register_fixed_factor(dev, clk_name, parent, 0, 1, 2);
-	if (IS_ERR(hw))
-		return PTR_ERR(hw);
-
-	hws[num++] = hw;
-
-	snprintf(clk_name, 32, "dsi%dpll", pll_14nm->id);
-	snprintf(parent, 32, "dsi%dn1_postdivby2_clk", pll_14nm->id);
-
-	/* DSI pixel clock = VCO_CLK / N1 / 2 / N2
-	 * This is the output of N2 post-divider, bits 4-7 in
-	 * REG_DSI_14nm_PHY_CMN_CLK_CFG0. Don't let it set parent.
-	 */
-	hw = pll_14nm_postdiv_register(pll_14nm, clk_name, parent, 0, 4);
-	if (IS_ERR(hw))
-		return PTR_ERR(hw);
-
-	hws[num++] = hw;
-	hw_data->hws[DSI_PIXEL_PLL_CLK]	= hw;
-
-	pll_14nm->num_hws = num;
-
-	hw_data->num = NUM_PROVIDED_CLKS;
-	pll_14nm->hw_data = hw_data;
-
-	ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
-				     pll_14nm->hw_data);
-	if (ret) {
-		DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret);
-		return ret;
-	}
-
-	return 0;
-}
-
-struct msm_dsi_pll *msm_dsi_pll_14nm_init(struct platform_device *pdev, int id)
-{
-	struct dsi_pll_14nm *pll_14nm;
-	struct msm_dsi_pll *pll;
-	int ret;
-
-	if (!pdev)
-		return ERR_PTR(-ENODEV);
-
-	pll_14nm = devm_kzalloc(&pdev->dev, sizeof(*pll_14nm), GFP_KERNEL);
-	if (!pll_14nm)
-		return ERR_PTR(-ENOMEM);
-
-	DBG("PLL%d", id);
-
-	pll_14nm->pdev = pdev;
-	pll_14nm->id = id;
-	pll_14nm_list[id] = pll_14nm;
-
-	pll_14nm->phy_cmn_mmio = msm_ioremap(pdev, "dsi_phy", "DSI_PHY");
-	if (IS_ERR_OR_NULL(pll_14nm->phy_cmn_mmio)) {
-		DRM_DEV_ERROR(&pdev->dev, "failed to map CMN PHY base\n");
-		return ERR_PTR(-ENOMEM);
-	}
-
-	pll_14nm->mmio = msm_ioremap(pdev, "dsi_pll", "DSI_PLL");
-	if (IS_ERR_OR_NULL(pll_14nm->mmio)) {
-		DRM_DEV_ERROR(&pdev->dev, "failed to map PLL base\n");
-		return ERR_PTR(-ENOMEM);
-	}
-
-	spin_lock_init(&pll_14nm->postdiv_lock);
-
-	pll = &pll_14nm->base;
-	pll->min_rate = VCO_MIN_RATE;
-	pll->max_rate = VCO_MAX_RATE;
-	pll->get_provider = dsi_pll_14nm_get_provider;
-	pll->destroy = dsi_pll_14nm_destroy;
-	pll->disable_seq = dsi_pll_14nm_disable_seq;
-	pll->save_state = dsi_pll_14nm_save_state;
-	pll->restore_state = dsi_pll_14nm_restore_state;
-	pll->set_usecase = dsi_pll_14nm_set_usecase;
-
-	pll_14nm->vco_delay = 1;
-
-	pll->en_seq_cnt = 1;
-	pll->enable_seqs[0] = dsi_pll_14nm_enable_seq;
-
-	ret = pll_14nm_register(pll_14nm);
-	if (ret) {
-		DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret);
-		return ERR_PTR(ret);
-	}
-
-	return pll;
-}
diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c
deleted file mode 100644
index 37a1f996a588..000000000000
--- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c
+++ /dev/null
@@ -1,643 +0,0 @@ 
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
- */
-
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-
-#include "dsi_pll.h"
-#include "dsi.xml.h"
-
-/*
- * DSI PLL 28nm - clock diagram (eg: DSI0):
- *
- *         dsi0analog_postdiv_clk
- *                             |         dsi0indirect_path_div2_clk
- *                             |          |
- *                   +------+  |  +----+  |  |\   dsi0byte_mux
- *  dsi0vco_clk --o--| DIV1 |--o--| /2 |--o--| \   |
- *                |  +------+     +----+     | m|  |  +----+
- *                |                          | u|--o--| /4 |-- dsi0pllbyte
- *                |                          | x|     +----+
- *                o--------------------------| /
- *                |                          |/
- *                |          +------+
- *                o----------| DIV3 |------------------------- dsi0pll
- *                           +------+
- */
-
-#define POLL_MAX_READS			10
-#define POLL_TIMEOUT_US		50
-
-#define NUM_PROVIDED_CLKS		2
-
-#define VCO_REF_CLK_RATE		19200000
-#define VCO_MIN_RATE			350000000
-#define VCO_MAX_RATE			750000000
-
-#define DSI_BYTE_PLL_CLK		0
-#define DSI_PIXEL_PLL_CLK		1
-
-#define LPFR_LUT_SIZE			10
-struct lpfr_cfg {
-	unsigned long vco_rate;
-	u32 resistance;
-};
-
-/* Loop filter resistance: */
-static const struct lpfr_cfg lpfr_lut[LPFR_LUT_SIZE] = {
-	{ 479500000,  8 },
-	{ 480000000, 11 },
-	{ 575500000,  8 },
-	{ 576000000, 12 },
-	{ 610500000,  8 },
-	{ 659500000,  9 },
-	{ 671500000, 10 },
-	{ 672000000, 14 },
-	{ 708500000, 10 },
-	{ 750000000, 11 },
-};
-
-struct pll_28nm_cached_state {
-	unsigned long vco_rate;
-	u8 postdiv3;
-	u8 postdiv1;
-	u8 byte_mux;
-};
-
-struct dsi_pll_28nm {
-	struct msm_dsi_pll base;
-
-	int id;
-	struct platform_device *pdev;
-	void __iomem *mmio;
-
-	int vco_delay;
-
-	/* private clocks: */
-	struct clk *clks[NUM_DSI_CLOCKS_MAX];
-	u32 num_clks;
-
-	/* clock-provider: */
-	struct clk *provided_clks[NUM_PROVIDED_CLKS];
-	struct clk_onecell_data clk_data;
-
-	struct pll_28nm_cached_state cached_state;
-};
-
-#define to_pll_28nm(x)	container_of(x, struct dsi_pll_28nm, base)
-
-static bool pll_28nm_poll_for_ready(struct dsi_pll_28nm *pll_28nm,
-				u32 nb_tries, u32 timeout_us)
-{
-	bool pll_locked = false;
-	u32 val;
-
-	while (nb_tries--) {
-		val = pll_read(pll_28nm->mmio + REG_DSI_28nm_PHY_PLL_STATUS);
-		pll_locked = !!(val & DSI_28nm_PHY_PLL_STATUS_PLL_RDY);
-
-		if (pll_locked)
-			break;
-
-		udelay(timeout_us);
-	}
-	DBG("DSI PLL is %slocked", pll_locked ? "" : "*not* ");
-
-	return pll_locked;
-}
-
-static void pll_28nm_software_reset(struct dsi_pll_28nm *pll_28nm)
-{
-	void __iomem *base = pll_28nm->mmio;
-
-	/*
-	 * Add HW recommended delays after toggling the software
-	 * reset bit off and back on.
-	 */
-	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_TEST_CFG,
-			DSI_28nm_PHY_PLL_TEST_CFG_PLL_SW_RESET, 1);
-	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_TEST_CFG, 0x00, 1);
-}
-
-/*
- * Clock Callbacks
- */
-static int dsi_pll_28nm_clk_set_rate(struct clk_hw *hw, unsigned long rate,
-		unsigned long parent_rate)
-{
-	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
-	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
-	struct device *dev = &pll_28nm->pdev->dev;
-	void __iomem *base = pll_28nm->mmio;
-	unsigned long div_fbx1000, gen_vco_clk;
-	u32 refclk_cfg, frac_n_mode, frac_n_value;
-	u32 sdm_cfg0, sdm_cfg1, sdm_cfg2, sdm_cfg3;
-	u32 cal_cfg10, cal_cfg11;
-	u32 rem;
-	int i;
-
-	VERB("rate=%lu, parent's=%lu", rate, parent_rate);
-
-	/* Force postdiv2 to be div-4 */
-	pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV2_CFG, 3);
-
-	/* Configure the Loop filter resistance */
-	for (i = 0; i < LPFR_LUT_SIZE; i++)
-		if (rate <= lpfr_lut[i].vco_rate)
-			break;
-	if (i == LPFR_LUT_SIZE) {
-		DRM_DEV_ERROR(dev, "unable to get loop filter resistance. vco=%lu\n",
-				rate);
-		return -EINVAL;
-	}
-	pll_write(base + REG_DSI_28nm_PHY_PLL_LPFR_CFG, lpfr_lut[i].resistance);
-
-	/* Loop filter capacitance values : c1 and c2 */
-	pll_write(base + REG_DSI_28nm_PHY_PLL_LPFC1_CFG, 0x70);
-	pll_write(base + REG_DSI_28nm_PHY_PLL_LPFC2_CFG, 0x15);
-
-	rem = rate % VCO_REF_CLK_RATE;
-	if (rem) {
-		refclk_cfg = DSI_28nm_PHY_PLL_REFCLK_CFG_DBLR;
-		frac_n_mode = 1;
-		div_fbx1000 = rate / (VCO_REF_CLK_RATE / 500);
-		gen_vco_clk = div_fbx1000 * (VCO_REF_CLK_RATE / 500);
-	} else {
-		refclk_cfg = 0x0;
-		frac_n_mode = 0;
-		div_fbx1000 = rate / (VCO_REF_CLK_RATE / 1000);
-		gen_vco_clk = div_fbx1000 * (VCO_REF_CLK_RATE / 1000);
-	}
-
-	DBG("refclk_cfg = %d", refclk_cfg);
-
-	rem = div_fbx1000 % 1000;
-	frac_n_value = (rem << 16) / 1000;
-
-	DBG("div_fb = %lu", div_fbx1000);
-	DBG("frac_n_value = %d", frac_n_value);
-
-	DBG("Generated VCO Clock: %lu", gen_vco_clk);
-	rem = 0;
-	sdm_cfg1 = pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1);
-	sdm_cfg1 &= ~DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET__MASK;
-	if (frac_n_mode) {
-		sdm_cfg0 = 0x0;
-		sdm_cfg0 |= DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV(0);
-		sdm_cfg1 |= DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET(
-				(u32)(((div_fbx1000 / 1000) & 0x3f) - 1));
-		sdm_cfg3 = frac_n_value >> 8;
-		sdm_cfg2 = frac_n_value & 0xff;
-	} else {
-		sdm_cfg0 = DSI_28nm_PHY_PLL_SDM_CFG0_BYP;
-		sdm_cfg0 |= DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV(
-				(u32)(((div_fbx1000 / 1000) & 0x3f) - 1));
-		sdm_cfg1 |= DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET(0);
-		sdm_cfg2 = 0;
-		sdm_cfg3 = 0;
-	}
-
-	DBG("sdm_cfg0=%d", sdm_cfg0);
-	DBG("sdm_cfg1=%d", sdm_cfg1);
-	DBG("sdm_cfg2=%d", sdm_cfg2);
-	DBG("sdm_cfg3=%d", sdm_cfg3);
-
-	cal_cfg11 = (u32)(gen_vco_clk / (256 * 1000000));
-	cal_cfg10 = (u32)((gen_vco_clk % (256 * 1000000)) / 1000000);
-	DBG("cal_cfg10=%d, cal_cfg11=%d", cal_cfg10, cal_cfg11);
-
-	pll_write(base + REG_DSI_28nm_PHY_PLL_CHGPUMP_CFG, 0x02);
-	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG3,    0x2b);
-	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG4,    0x06);
-	pll_write(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2,  0x0d);
-
-	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1, sdm_cfg1);
-	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG2,
-		DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0(sdm_cfg2));
-	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG3,
-		DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8(sdm_cfg3));
-	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG4, 0x00);
-
-	/* Add hardware recommended delay for correct PLL configuration */
-	if (pll_28nm->vco_delay)
-		udelay(pll_28nm->vco_delay);
-
-	pll_write(base + REG_DSI_28nm_PHY_PLL_REFCLK_CFG, refclk_cfg);
-	pll_write(base + REG_DSI_28nm_PHY_PLL_PWRGEN_CFG, 0x00);
-	pll_write(base + REG_DSI_28nm_PHY_PLL_VCOLPF_CFG, 0x31);
-	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0,   sdm_cfg0);
-	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG0,   0x12);
-	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG6,   0x30);
-	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG7,   0x00);
-	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG8,   0x60);
-	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG9,   0x00);
-	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG10,  cal_cfg10 & 0xff);
-	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG11,  cal_cfg11 & 0xff);
-	pll_write(base + REG_DSI_28nm_PHY_PLL_EFUSE_CFG,  0x20);
-
-	return 0;
-}
-
-static int dsi_pll_28nm_clk_is_enabled(struct clk_hw *hw)
-{
-	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
-	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
-
-	return pll_28nm_poll_for_ready(pll_28nm, POLL_MAX_READS,
-					POLL_TIMEOUT_US);
-}
-
-static unsigned long dsi_pll_28nm_clk_recalc_rate(struct clk_hw *hw,
-		unsigned long parent_rate)
-{
-	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
-	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
-	void __iomem *base = pll_28nm->mmio;
-	u32 sdm0, doubler, sdm_byp_div;
-	u32 sdm_dc_off, sdm_freq_seed, sdm2, sdm3;
-	u32 ref_clk = VCO_REF_CLK_RATE;
-	unsigned long vco_rate;
-
-	VERB("parent_rate=%lu", parent_rate);
-
-	/* Check to see if the ref clk doubler is enabled */
-	doubler = pll_read(base + REG_DSI_28nm_PHY_PLL_REFCLK_CFG) &
-			DSI_28nm_PHY_PLL_REFCLK_CFG_DBLR;
-	ref_clk += (doubler * VCO_REF_CLK_RATE);
-
-	/* see if it is integer mode or sdm mode */
-	sdm0 = pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0);
-	if (sdm0 & DSI_28nm_PHY_PLL_SDM_CFG0_BYP) {
-		/* integer mode */
-		sdm_byp_div = FIELD(
-				pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0),
-				DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV) + 1;
-		vco_rate = ref_clk * sdm_byp_div;
-	} else {
-		/* sdm mode */
-		sdm_dc_off = FIELD(
-				pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1),
-				DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET);
-		DBG("sdm_dc_off = %d", sdm_dc_off);
-		sdm2 = FIELD(pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG2),
-				DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0);
-		sdm3 = FIELD(pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG3),
-				DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8);
-		sdm_freq_seed = (sdm3 << 8) | sdm2;
-		DBG("sdm_freq_seed = %d", sdm_freq_seed);
-
-		vco_rate = (ref_clk * (sdm_dc_off + 1)) +
-			mult_frac(ref_clk, sdm_freq_seed, BIT(16));
-		DBG("vco rate = %lu", vco_rate);
-	}
-
-	DBG("returning vco rate = %lu", vco_rate);
-
-	return vco_rate;
-}
-
-static const struct clk_ops clk_ops_dsi_pll_28nm_vco = {
-	.round_rate = msm_dsi_pll_helper_clk_round_rate,
-	.set_rate = dsi_pll_28nm_clk_set_rate,
-	.recalc_rate = dsi_pll_28nm_clk_recalc_rate,
-	.prepare = msm_dsi_pll_helper_clk_prepare,
-	.unprepare = msm_dsi_pll_helper_clk_unprepare,
-	.is_enabled = dsi_pll_28nm_clk_is_enabled,
-};
-
-/*
- * PLL Callbacks
- */
-static int dsi_pll_28nm_enable_seq_hpm(struct msm_dsi_pll *pll)
-{
-	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
-	struct device *dev = &pll_28nm->pdev->dev;
-	void __iomem *base = pll_28nm->mmio;
-	u32 max_reads = 5, timeout_us = 100;
-	bool locked;
-	u32 val;
-	int i;
-
-	DBG("id=%d", pll_28nm->id);
-
-	pll_28nm_software_reset(pll_28nm);
-
-	/*
-	 * PLL power up sequence.
-	 * Add necessary delays recommended by hardware.
-	 */
-	val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;
-	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 1);
-
-	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;
-	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);
-
-	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;
-	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);
-
-	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;
-	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 600);
-
-	for (i = 0; i < 2; i++) {
-		/* DSI Uniphy lock detect setting */
-		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2,
-				0x0c, 100);
-		pll_write(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x0d);
-
-		/* poll for PLL ready status */
-		locked = pll_28nm_poll_for_ready(pll_28nm,
-						max_reads, timeout_us);
-		if (locked)
-			break;
-
-		pll_28nm_software_reset(pll_28nm);
-
-		/*
-		 * PLL power up sequence.
-		 * Add necessary delays recommended by hardware.
-		 */
-		val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;
-		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 1);
-
-		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;
-		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);
-
-		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;
-		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 250);
-
-		val &= ~DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;
-		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);
-
-		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;
-		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);
-
-		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;
-		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 600);
-	}
-
-	if (unlikely(!locked))
-		DRM_DEV_ERROR(dev, "DSI PLL lock failed\n");
-	else
-		DBG("DSI PLL Lock success");
-
-	return locked ? 0 : -EINVAL;
-}
-
-static int dsi_pll_28nm_enable_seq_lp(struct msm_dsi_pll *pll)
-{
-	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
-	struct device *dev = &pll_28nm->pdev->dev;
-	void __iomem *base = pll_28nm->mmio;
-	bool locked;
-	u32 max_reads = 10, timeout_us = 50;
-	u32 val;
-
-	DBG("id=%d", pll_28nm->id);
-
-	pll_28nm_software_reset(pll_28nm);
-
-	/*
-	 * PLL power up sequence.
-	 * Add necessary delays recommended by hardware.
-	 */
-	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_CAL_CFG1, 0x34, 500);
-
-	val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;
-	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);
-
-	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;
-	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);
-
-	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B |
-		DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;
-	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);
-
-	/* DSI PLL toggle lock detect setting */
-	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x04, 500);
-	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x05, 512);
-
-	locked = pll_28nm_poll_for_ready(pll_28nm, max_reads, timeout_us);
-
-	if (unlikely(!locked))
-		DRM_DEV_ERROR(dev, "DSI PLL lock failed\n");
-	else
-		DBG("DSI PLL lock success");
-
-	return locked ? 0 : -EINVAL;
-}
-
-static void dsi_pll_28nm_disable_seq(struct msm_dsi_pll *pll)
-{
-	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
-
-	DBG("id=%d", pll_28nm->id);
-	pll_write(pll_28nm->mmio + REG_DSI_28nm_PHY_PLL_GLB_CFG, 0x00);
-}
-
-static void dsi_pll_28nm_save_state(struct msm_dsi_pll *pll)
-{
-	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
-	struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;
-	void __iomem *base = pll_28nm->mmio;
-
-	cached_state->postdiv3 =
-			pll_read(base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG);
-	cached_state->postdiv1 =
-			pll_read(base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG);
-	cached_state->byte_mux = pll_read(base + REG_DSI_28nm_PHY_PLL_VREG_CFG);
-	if (dsi_pll_28nm_clk_is_enabled(&pll->clk_hw))
-		cached_state->vco_rate = clk_hw_get_rate(&pll->clk_hw);
-	else
-		cached_state->vco_rate = 0;
-}
-
-static int dsi_pll_28nm_restore_state(struct msm_dsi_pll *pll)
-{
-	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
-	struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;
-	void __iomem *base = pll_28nm->mmio;
-	int ret;
-
-	ret = dsi_pll_28nm_clk_set_rate(&pll->clk_hw,
-					cached_state->vco_rate, 0);
-	if (ret) {
-		DRM_DEV_ERROR(&pll_28nm->pdev->dev,
-			"restore vco rate failed. ret=%d\n", ret);
-		return ret;
-	}
-
-	pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG,
-			cached_state->postdiv3);
-	pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG,
-			cached_state->postdiv1);
-	pll_write(base + REG_DSI_28nm_PHY_PLL_VREG_CFG,
-			cached_state->byte_mux);
-
-	return 0;
-}
-
-static int dsi_pll_28nm_get_provider(struct msm_dsi_pll *pll,
-				struct clk **byte_clk_provider,
-				struct clk **pixel_clk_provider)
-{
-	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
-
-	if (byte_clk_provider)
-		*byte_clk_provider = pll_28nm->provided_clks[DSI_BYTE_PLL_CLK];
-	if (pixel_clk_provider)
-		*pixel_clk_provider =
-				pll_28nm->provided_clks[DSI_PIXEL_PLL_CLK];
-
-	return 0;
-}
-
-static void dsi_pll_28nm_destroy(struct msm_dsi_pll *pll)
-{
-	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
-	int i;
-
-	msm_dsi_pll_helper_unregister_clks(pll_28nm->pdev,
-					pll_28nm->clks, pll_28nm->num_clks);
-
-	for (i = 0; i < NUM_PROVIDED_CLKS; i++)
-		pll_28nm->provided_clks[i] = NULL;
-
-	pll_28nm->num_clks = 0;
-	pll_28nm->clk_data.clks = NULL;
-	pll_28nm->clk_data.clk_num = 0;
-}
-
-static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm)
-{
-	char clk_name[32], parent1[32], parent2[32], vco_name[32];
-	struct clk_init_data vco_init = {
-		.parent_names = (const char *[]){ "xo" },
-		.num_parents = 1,
-		.name = vco_name,
-		.flags = CLK_IGNORE_UNUSED,
-		.ops = &clk_ops_dsi_pll_28nm_vco,
-	};
-	struct device *dev = &pll_28nm->pdev->dev;
-	struct clk **clks = pll_28nm->clks;
-	struct clk **provided_clks = pll_28nm->provided_clks;
-	int num = 0;
-	int ret;
-
-	DBG("%d", pll_28nm->id);
-
-	snprintf(vco_name, 32, "dsi%dvco_clk", pll_28nm->id);
-	pll_28nm->base.clk_hw.init = &vco_init;
-	clks[num++] = clk_register(dev, &pll_28nm->base.clk_hw);
-
-	snprintf(clk_name, 32, "dsi%danalog_postdiv_clk", pll_28nm->id);
-	snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->id);
-	clks[num++] = clk_register_divider(dev, clk_name,
-			parent1, CLK_SET_RATE_PARENT,
-			pll_28nm->mmio +
-			REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG,
-			0, 4, 0, NULL);
-
-	snprintf(clk_name, 32, "dsi%dindirect_path_div2_clk", pll_28nm->id);
-	snprintf(parent1, 32, "dsi%danalog_postdiv_clk", pll_28nm->id);
-	clks[num++] = clk_register_fixed_factor(dev, clk_name,
-			parent1, CLK_SET_RATE_PARENT,
-			1, 2);
-
-	snprintf(clk_name, 32, "dsi%dpll", pll_28nm->id);
-	snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->id);
-	clks[num++] = provided_clks[DSI_PIXEL_PLL_CLK] =
-			clk_register_divider(dev, clk_name,
-				parent1, 0, pll_28nm->mmio +
-				REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG,
-				0, 8, 0, NULL);
-
-	snprintf(clk_name, 32, "dsi%dbyte_mux", pll_28nm->id);
-	snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->id);
-	snprintf(parent2, 32, "dsi%dindirect_path_div2_clk", pll_28nm->id);
-	clks[num++] = clk_register_mux(dev, clk_name,
-			((const char *[]){
-				parent1, parent2
-			}), 2, CLK_SET_RATE_PARENT, pll_28nm->mmio +
-			REG_DSI_28nm_PHY_PLL_VREG_CFG, 1, 1, 0, NULL);
-
-	snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->id);
-	snprintf(parent1, 32, "dsi%dbyte_mux", pll_28nm->id);
-	clks[num++] = provided_clks[DSI_BYTE_PLL_CLK] =
-			clk_register_fixed_factor(dev, clk_name,
-				parent1, CLK_SET_RATE_PARENT, 1, 4);
-
-	pll_28nm->num_clks = num;
-
-	pll_28nm->clk_data.clk_num = NUM_PROVIDED_CLKS;
-	pll_28nm->clk_data.clks = provided_clks;
-
-	ret = of_clk_add_provider(dev->of_node,
-			of_clk_src_onecell_get, &pll_28nm->clk_data);
-	if (ret) {
-		DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret);
-		return ret;
-	}
-
-	return 0;
-}
-
-struct msm_dsi_pll *msm_dsi_pll_28nm_init(struct platform_device *pdev,
-					enum msm_dsi_phy_type type, int id)
-{
-	struct dsi_pll_28nm *pll_28nm;
-	struct msm_dsi_pll *pll;
-	int ret;
-
-	if (!pdev)
-		return ERR_PTR(-ENODEV);
-
-	pll_28nm = devm_kzalloc(&pdev->dev, sizeof(*pll_28nm), GFP_KERNEL);
-	if (!pll_28nm)
-		return ERR_PTR(-ENOMEM);
-
-	pll_28nm->pdev = pdev;
-	pll_28nm->id = id;
-
-	pll_28nm->mmio = msm_ioremap(pdev, "dsi_pll", "DSI_PLL");
-	if (IS_ERR_OR_NULL(pll_28nm->mmio)) {
-		DRM_DEV_ERROR(&pdev->dev, "%s: failed to map pll base\n", __func__);
-		return ERR_PTR(-ENOMEM);
-	}
-
-	pll = &pll_28nm->base;
-	pll->min_rate = VCO_MIN_RATE;
-	pll->max_rate = VCO_MAX_RATE;
-	pll->get_provider = dsi_pll_28nm_get_provider;
-	pll->destroy = dsi_pll_28nm_destroy;
-	pll->disable_seq = dsi_pll_28nm_disable_seq;
-	pll->save_state = dsi_pll_28nm_save_state;
-	pll->restore_state = dsi_pll_28nm_restore_state;
-
-	if (type == MSM_DSI_PHY_28NM_HPM) {
-		pll_28nm->vco_delay = 1;
-
-		pll->en_seq_cnt = 3;
-		pll->enable_seqs[0] = dsi_pll_28nm_enable_seq_hpm;
-		pll->enable_seqs[1] = dsi_pll_28nm_enable_seq_hpm;
-		pll->enable_seqs[2] = dsi_pll_28nm_enable_seq_hpm;
-	} else if (type == MSM_DSI_PHY_28NM_LP) {
-		pll_28nm->vco_delay = 1000;
-
-		pll->en_seq_cnt = 1;
-		pll->enable_seqs[0] = dsi_pll_28nm_enable_seq_lp;
-	} else {
-		DRM_DEV_ERROR(&pdev->dev, "phy type (%d) is not 28nm\n", type);
-		return ERR_PTR(-EINVAL);
-	}
-
-	ret = pll_28nm_register(pll_28nm);
-	if (ret) {
-		DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret);
-		return ERR_PTR(ret);
-	}
-
-	return pll;
-}
-
diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c
deleted file mode 100644
index a6e7a2525fe0..000000000000
--- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c
+++ /dev/null
@@ -1,526 +0,0 @@ 
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
- */
-
-#include <linux/clk-provider.h>
-
-#include "dsi_pll.h"
-#include "dsi.xml.h"
-
-/*
- * DSI PLL 28nm (8960/A family) - clock diagram (eg: DSI1):
- *
- *
- *                        +------+
- *  dsi1vco_clk ----o-----| DIV1 |---dsi1pllbit (not exposed as clock)
- *  F * byte_clk    |     +------+
- *                  | bit clock divider (F / 8)
- *                  |
- *                  |     +------+
- *                  o-----| DIV2 |---dsi0pllbyte---o---> To byte RCG
- *                  |     +------+                 | (sets parent rate)
- *                  | byte clock divider (F)       |
- *                  |                              |
- *                  |                              o---> To esc RCG
- *                  |                                (doesn't set parent rate)
- *                  |
- *                  |     +------+
- *                  o-----| DIV3 |----dsi0pll------o---> To dsi RCG
- *                        +------+                 | (sets parent rate)
- *                  dsi clock divider (F * magic)  |
- *                                                 |
- *                                                 o---> To pixel rcg
- *                                                  (doesn't set parent rate)
- */
-
-#define POLL_MAX_READS		8000
-#define POLL_TIMEOUT_US		1
-
-#define NUM_PROVIDED_CLKS	2
-
-#define VCO_REF_CLK_RATE	27000000
-#define VCO_MIN_RATE		600000000
-#define VCO_MAX_RATE		1200000000
-
-#define DSI_BYTE_PLL_CLK	0
-#define DSI_PIXEL_PLL_CLK	1
-
-#define VCO_PREF_DIV_RATIO	27
-
-struct pll_28nm_cached_state {
-	unsigned long vco_rate;
-	u8 postdiv3;
-	u8 postdiv2;
-	u8 postdiv1;
-};
-
-struct clk_bytediv {
-	struct clk_hw hw;
-	void __iomem *reg;
-};
-
-struct dsi_pll_28nm {
-	struct msm_dsi_pll base;
-
-	int id;
-	struct platform_device *pdev;
-	void __iomem *mmio;
-
-	/* custom byte clock divider */
-	struct clk_bytediv *bytediv;
-
-	/* private clocks: */
-	struct clk *clks[NUM_DSI_CLOCKS_MAX];
-	u32 num_clks;
-
-	/* clock-provider: */
-	struct clk *provided_clks[NUM_PROVIDED_CLKS];
-	struct clk_onecell_data clk_data;
-
-	struct pll_28nm_cached_state cached_state;
-};
-
-#define to_pll_28nm(x)	container_of(x, struct dsi_pll_28nm, base)
-
-static bool pll_28nm_poll_for_ready(struct dsi_pll_28nm *pll_28nm,
-				    int nb_tries, int timeout_us)
-{
-	bool pll_locked = false;
-	u32 val;
-
-	while (nb_tries--) {
-		val = pll_read(pll_28nm->mmio + REG_DSI_28nm_8960_PHY_PLL_RDY);
-		pll_locked = !!(val & DSI_28nm_8960_PHY_PLL_RDY_PLL_RDY);
-
-		if (pll_locked)
-			break;
-
-		udelay(timeout_us);
-	}
-	DBG("DSI PLL is %slocked", pll_locked ? "" : "*not* ");
-
-	return pll_locked;
-}
-
-/*
- * Clock Callbacks
- */
-static int dsi_pll_28nm_clk_set_rate(struct clk_hw *hw, unsigned long rate,
-				     unsigned long parent_rate)
-{
-	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
-	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
-	void __iomem *base = pll_28nm->mmio;
-	u32 val, temp, fb_divider;
-
-	DBG("rate=%lu, parent's=%lu", rate, parent_rate);
-
-	temp = rate / 10;
-	val = VCO_REF_CLK_RATE / 10;
-	fb_divider = (temp * VCO_PREF_DIV_RATIO) / val;
-	fb_divider = fb_divider / 2 - 1;
-	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_1,
-			fb_divider & 0xff);
-
-	val = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2);
-
-	val |= (fb_divider >> 8) & 0x07;
-
-	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2,
-			val);
-
-	val = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3);
-
-	val |= (VCO_PREF_DIV_RATIO - 1) & 0x3f;
-
-	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3,
-			val);
-
-	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_6,
-			0xf);
-
-	val = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
-	val |= 0x7 << 4;
-	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8,
-			val);
-
-	return 0;
-}
-
-static int dsi_pll_28nm_clk_is_enabled(struct clk_hw *hw)
-{
-	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
-	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
-
-	return pll_28nm_poll_for_ready(pll_28nm, POLL_MAX_READS,
-					POLL_TIMEOUT_US);
-}
-
-static unsigned long dsi_pll_28nm_clk_recalc_rate(struct clk_hw *hw,
-						  unsigned long parent_rate)
-{
-	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
-	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
-	void __iomem *base = pll_28nm->mmio;
-	unsigned long vco_rate;
-	u32 status, fb_divider, temp, ref_divider;
-
-	VERB("parent_rate=%lu", parent_rate);
-
-	status = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_0);
-
-	if (status & DSI_28nm_8960_PHY_PLL_CTRL_0_ENABLE) {
-		fb_divider = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_1);
-		fb_divider &= 0xff;
-		temp = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2) & 0x07;
-		fb_divider = (temp << 8) | fb_divider;
-		fb_divider += 1;
-
-		ref_divider = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3);
-		ref_divider &= 0x3f;
-		ref_divider += 1;
-
-		/* multiply by 2 */
-		vco_rate = (parent_rate / ref_divider) * fb_divider * 2;
-	} else {
-		vco_rate = 0;
-	}
-
-	DBG("returning vco rate = %lu", vco_rate);
-
-	return vco_rate;
-}
-
-static const struct clk_ops clk_ops_dsi_pll_28nm_vco = {
-	.round_rate = msm_dsi_pll_helper_clk_round_rate,
-	.set_rate = dsi_pll_28nm_clk_set_rate,
-	.recalc_rate = dsi_pll_28nm_clk_recalc_rate,
-	.prepare = msm_dsi_pll_helper_clk_prepare,
-	.unprepare = msm_dsi_pll_helper_clk_unprepare,
-	.is_enabled = dsi_pll_28nm_clk_is_enabled,
-};
-
-/*
- * Custom byte clock divier clk_ops
- *
- * This clock is the entry point to configuring the PLL. The user (dsi host)
- * will set this clock's rate to the desired byte clock rate. The VCO lock
- * frequency is a multiple of the byte clock rate. The multiplication factor
- * (shown as F in the diagram above) is a function of the byte clock rate.
- *
- * This custom divider clock ensures that its parent (VCO) is set to the
- * desired rate, and that the byte clock postdivider (POSTDIV2) is configured
- * accordingly
- */
-#define to_clk_bytediv(_hw) container_of(_hw, struct clk_bytediv, hw)
-
-static unsigned long clk_bytediv_recalc_rate(struct clk_hw *hw,
-		unsigned long parent_rate)
-{
-	struct clk_bytediv *bytediv = to_clk_bytediv(hw);
-	unsigned int div;
-
-	div = pll_read(bytediv->reg) & 0xff;
-
-	return parent_rate / (div + 1);
-}
-
-/* find multiplication factor(wrt byte clock) at which the VCO should be set */
-static unsigned int get_vco_mul_factor(unsigned long byte_clk_rate)
-{
-	unsigned long bit_mhz;
-
-	/* convert to bit clock in Mhz */
-	bit_mhz = (byte_clk_rate * 8) / 1000000;
-
-	if (bit_mhz < 125)
-		return 64;
-	else if (bit_mhz < 250)
-		return 32;
-	else if (bit_mhz < 600)
-		return 16;
-	else
-		return 8;
-}
-
-static long clk_bytediv_round_rate(struct clk_hw *hw, unsigned long rate,
-				   unsigned long *prate)
-{
-	unsigned long best_parent;
-	unsigned int factor;
-
-	factor = get_vco_mul_factor(rate);
-
-	best_parent = rate * factor;
-	*prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
-
-	return *prate / factor;
-}
-
-static int clk_bytediv_set_rate(struct clk_hw *hw, unsigned long rate,
-				unsigned long parent_rate)
-{
-	struct clk_bytediv *bytediv = to_clk_bytediv(hw);
-	u32 val;
-	unsigned int factor;
-
-	factor = get_vco_mul_factor(rate);
-
-	val = pll_read(bytediv->reg);
-	val |= (factor - 1) & 0xff;
-	pll_write(bytediv->reg, val);
-
-	return 0;
-}
-
-/* Our special byte clock divider ops */
-static const struct clk_ops clk_bytediv_ops = {
-	.round_rate = clk_bytediv_round_rate,
-	.set_rate = clk_bytediv_set_rate,
-	.recalc_rate = clk_bytediv_recalc_rate,
-};
-
-/*
- * PLL Callbacks
- */
-static int dsi_pll_28nm_enable_seq(struct msm_dsi_pll *pll)
-{
-	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
-	struct device *dev = &pll_28nm->pdev->dev;
-	void __iomem *base = pll_28nm->mmio;
-	bool locked;
-	unsigned int bit_div, byte_div;
-	int max_reads = 1000, timeout_us = 100;
-	u32 val;
-
-	DBG("id=%d", pll_28nm->id);
-
-	/*
-	 * before enabling the PLL, configure the bit clock divider since we
-	 * don't expose it as a clock to the outside world
-	 * 1: read back the byte clock divider that should already be set
-	 * 2: divide by 8 to get bit clock divider
-	 * 3: write it to POSTDIV1
-	 */
-	val = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9);
-	byte_div = val + 1;
-	bit_div = byte_div / 8;
-
-	val = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
-	val &= ~0xf;
-	val |= (bit_div - 1);
-	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8, val);
-
-	/* enable the PLL */
-	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_0,
-			DSI_28nm_8960_PHY_PLL_CTRL_0_ENABLE);
-
-	locked = pll_28nm_poll_for_ready(pll_28nm, max_reads, timeout_us);
-
-	if (unlikely(!locked))
-		DRM_DEV_ERROR(dev, "DSI PLL lock failed\n");
-	else
-		DBG("DSI PLL lock success");
-
-	return locked ? 0 : -EINVAL;
-}
-
-static void dsi_pll_28nm_disable_seq(struct msm_dsi_pll *pll)
-{
-	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
-
-	DBG("id=%d", pll_28nm->id);
-	pll_write(pll_28nm->mmio + REG_DSI_28nm_8960_PHY_PLL_CTRL_0, 0x00);
-}
-
-static void dsi_pll_28nm_save_state(struct msm_dsi_pll *pll)
-{
-	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
-	struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;
-	void __iomem *base = pll_28nm->mmio;
-
-	cached_state->postdiv3 =
-			pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_10);
-	cached_state->postdiv2 =
-			pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9);
-	cached_state->postdiv1 =
-			pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
-
-	cached_state->vco_rate = clk_hw_get_rate(&pll->clk_hw);
-}
-
-static int dsi_pll_28nm_restore_state(struct msm_dsi_pll *pll)
-{
-	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
-	struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;
-	void __iomem *base = pll_28nm->mmio;
-	int ret;
-
-	ret = dsi_pll_28nm_clk_set_rate(&pll->clk_hw,
-					cached_state->vco_rate, 0);
-	if (ret) {
-		DRM_DEV_ERROR(&pll_28nm->pdev->dev,
-			"restore vco rate failed. ret=%d\n", ret);
-		return ret;
-	}
-
-	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_10,
-			cached_state->postdiv3);
-	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9,
-			cached_state->postdiv2);
-	pll_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8,
-			cached_state->postdiv1);
-
-	return 0;
-}
-
-static int dsi_pll_28nm_get_provider(struct msm_dsi_pll *pll,
-				struct clk **byte_clk_provider,
-				struct clk **pixel_clk_provider)
-{
-	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
-
-	if (byte_clk_provider)
-		*byte_clk_provider = pll_28nm->provided_clks[DSI_BYTE_PLL_CLK];
-	if (pixel_clk_provider)
-		*pixel_clk_provider =
-				pll_28nm->provided_clks[DSI_PIXEL_PLL_CLK];
-
-	return 0;
-}
-
-static void dsi_pll_28nm_destroy(struct msm_dsi_pll *pll)
-{
-	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
-
-	msm_dsi_pll_helper_unregister_clks(pll_28nm->pdev,
-					pll_28nm->clks, pll_28nm->num_clks);
-}
-
-static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm)
-{
-	char *clk_name, *parent_name, *vco_name;
-	struct clk_init_data vco_init = {
-		.parent_names = (const char *[]){ "pxo" },
-		.num_parents = 1,
-		.flags = CLK_IGNORE_UNUSED,
-		.ops = &clk_ops_dsi_pll_28nm_vco,
-	};
-	struct device *dev = &pll_28nm->pdev->dev;
-	struct clk **clks = pll_28nm->clks;
-	struct clk **provided_clks = pll_28nm->provided_clks;
-	struct clk_bytediv *bytediv;
-	struct clk_init_data bytediv_init = { };
-	int ret, num = 0;
-
-	DBG("%d", pll_28nm->id);
-
-	bytediv = devm_kzalloc(dev, sizeof(*bytediv), GFP_KERNEL);
-	if (!bytediv)
-		return -ENOMEM;
-
-	vco_name = devm_kzalloc(dev, 32, GFP_KERNEL);
-	if (!vco_name)
-		return -ENOMEM;
-
-	parent_name = devm_kzalloc(dev, 32, GFP_KERNEL);
-	if (!parent_name)
-		return -ENOMEM;
-
-	clk_name = devm_kzalloc(dev, 32, GFP_KERNEL);
-	if (!clk_name)
-		return -ENOMEM;
-
-	pll_28nm->bytediv = bytediv;
-
-	snprintf(vco_name, 32, "dsi%dvco_clk", pll_28nm->id);
-	vco_init.name = vco_name;
-
-	pll_28nm->base.clk_hw.init = &vco_init;
-
-	clks[num++] = clk_register(dev, &pll_28nm->base.clk_hw);
-
-	/* prepare and register bytediv */
-	bytediv->hw.init = &bytediv_init;
-	bytediv->reg = pll_28nm->mmio + REG_DSI_28nm_8960_PHY_PLL_CTRL_9;
-
-	snprintf(parent_name, 32, "dsi%dvco_clk", pll_28nm->id);
-	snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->id);
-
-	bytediv_init.name = clk_name;
-	bytediv_init.ops = &clk_bytediv_ops;
-	bytediv_init.flags = CLK_SET_RATE_PARENT;
-	bytediv_init.parent_names = (const char * const *) &parent_name;
-	bytediv_init.num_parents = 1;
-
-	/* DIV2 */
-	clks[num++] = provided_clks[DSI_BYTE_PLL_CLK] =
-			clk_register(dev, &bytediv->hw);
-
-	snprintf(clk_name, 32, "dsi%dpll", pll_28nm->id);
-	/* DIV3 */
-	clks[num++] = provided_clks[DSI_PIXEL_PLL_CLK] =
-			clk_register_divider(dev, clk_name,
-				parent_name, 0, pll_28nm->mmio +
-				REG_DSI_28nm_8960_PHY_PLL_CTRL_10,
-				0, 8, 0, NULL);
-
-	pll_28nm->num_clks = num;
-
-	pll_28nm->clk_data.clk_num = NUM_PROVIDED_CLKS;
-	pll_28nm->clk_data.clks = provided_clks;
-
-	ret = of_clk_add_provider(dev->of_node,
-			of_clk_src_onecell_get, &pll_28nm->clk_data);
-	if (ret) {
-		DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret);
-		return ret;
-	}
-
-	return 0;
-}
-
-struct msm_dsi_pll *msm_dsi_pll_28nm_8960_init(struct platform_device *pdev,
-					       int id)
-{
-	struct dsi_pll_28nm *pll_28nm;
-	struct msm_dsi_pll *pll;
-	int ret;
-
-	if (!pdev)
-		return ERR_PTR(-ENODEV);
-
-	pll_28nm = devm_kzalloc(&pdev->dev, sizeof(*pll_28nm), GFP_KERNEL);
-	if (!pll_28nm)
-		return ERR_PTR(-ENOMEM);
-
-	pll_28nm->pdev = pdev;
-	pll_28nm->id = id + 1;
-
-	pll_28nm->mmio = msm_ioremap(pdev, "dsi_pll", "DSI_PLL");
-	if (IS_ERR_OR_NULL(pll_28nm->mmio)) {
-		DRM_DEV_ERROR(&pdev->dev, "%s: failed to map pll base\n", __func__);
-		return ERR_PTR(-ENOMEM);
-	}
-
-	pll = &pll_28nm->base;
-	pll->min_rate = VCO_MIN_RATE;
-	pll->max_rate = VCO_MAX_RATE;
-	pll->get_provider = dsi_pll_28nm_get_provider;
-	pll->destroy = dsi_pll_28nm_destroy;
-	pll->disable_seq = dsi_pll_28nm_disable_seq;
-	pll->save_state = dsi_pll_28nm_save_state;
-	pll->restore_state = dsi_pll_28nm_restore_state;
-
-	pll->en_seq_cnt = 1;
-	pll->enable_seqs[0] = dsi_pll_28nm_enable_seq;
-
-	ret = pll_28nm_register(pll_28nm);
-	if (ret) {
-		DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret);
-		return ERR_PTR(ret);
-	}
-
-	return pll;
-}
diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c
deleted file mode 100644
index e29b3bfd63d1..000000000000
--- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c
+++ /dev/null
@@ -1,913 +0,0 @@ 
-/*
- * SPDX-License-Identifier: GPL-2.0
- * Copyright (c) 2018, The Linux Foundation
- */
-
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/iopoll.h>
-
-#include "dsi_pll.h"
-#include "dsi.xml.h"
-
-/*
- * DSI PLL 7nm - clock diagram (eg: DSI0): TODO: updated CPHY diagram
- *
- *           dsi0_pll_out_div_clk  dsi0_pll_bit_clk
- *                              |                |
- *                              |                |
- *                 +---------+  |  +----------+  |  +----+
- *  dsi0vco_clk ---| out_div |--o--| divl_3_0 |--o--| /8 |-- dsi0_phy_pll_out_byteclk
- *                 +---------+  |  +----------+  |  +----+
- *                              |                |
- *                              |                |         dsi0_pll_by_2_bit_clk
- *                              |                |          |
- *                              |                |  +----+  |  |\  dsi0_pclk_mux
- *                              |                |--| /2 |--o--| \   |
- *                              |                |  +----+     |  \  |  +---------+
- *                              |                --------------|  |--o--| div_7_4 |-- dsi0_phy_pll_out_dsiclk
- *                              |------------------------------|  /     +---------+
- *                              |          +-----+             | /
- *                              -----------| /4? |--o----------|/
- *                                         +-----+  |           |
- *                                                  |           |dsiclk_sel
- *                                                  |
- *                                                  dsi0_pll_post_out_div_clk
- */
-
-#define DSI_BYTE_PLL_CLK		0
-#define DSI_PIXEL_PLL_CLK		1
-#define NUM_PROVIDED_CLKS		2
-
-#define VCO_REF_CLK_RATE		19200000
-
-struct dsi_pll_regs {
-	u32 pll_prop_gain_rate;
-	u32 pll_lockdet_rate;
-	u32 decimal_div_start;
-	u32 frac_div_start_low;
-	u32 frac_div_start_mid;
-	u32 frac_div_start_high;
-	u32 pll_clock_inverters;
-	u32 ssc_stepsize_low;
-	u32 ssc_stepsize_high;
-	u32 ssc_div_per_low;
-	u32 ssc_div_per_high;
-	u32 ssc_adjper_low;
-	u32 ssc_adjper_high;
-	u32 ssc_control;
-};
-
-struct dsi_pll_config {
-	u32 ref_freq;
-	bool div_override;
-	u32 output_div;
-	bool ignore_frac;
-	bool disable_prescaler;
-	bool enable_ssc;
-	bool ssc_center;
-	u32 dec_bits;
-	u32 frac_bits;
-	u32 lock_timer;
-	u32 ssc_freq;
-	u32 ssc_offset;
-	u32 ssc_adj_per;
-	u32 thresh_cycles;
-	u32 refclk_cycles;
-};
-
-struct pll_7nm_cached_state {
-	unsigned long vco_rate;
-	u8 bit_clk_div;
-	u8 pix_clk_div;
-	u8 pll_out_div;
-	u8 pll_mux;
-};
-
-struct dsi_pll_7nm {
-	struct msm_dsi_pll base;
-
-	int id;
-	struct platform_device *pdev;
-
-	void __iomem *phy_cmn_mmio;
-	void __iomem *mmio;
-
-	u64 vco_ref_clk_rate;
-	u64 vco_current_rate;
-
-	/* protects REG_DSI_7nm_PHY_CMN_CLK_CFG0 register */
-	spinlock_t postdiv_lock;
-
-	int vco_delay;
-	struct dsi_pll_config pll_configuration;
-	struct dsi_pll_regs reg_setup;
-
-	/* private clocks: */
-	struct clk_hw *out_div_clk_hw;
-	struct clk_hw *bit_clk_hw;
-	struct clk_hw *byte_clk_hw;
-	struct clk_hw *by_2_bit_clk_hw;
-	struct clk_hw *post_out_div_clk_hw;
-	struct clk_hw *pclk_mux_hw;
-	struct clk_hw *out_dsiclk_hw;
-
-	/* clock-provider: */
-	struct clk_hw_onecell_data *hw_data;
-
-	struct pll_7nm_cached_state cached_state;
-
-	enum msm_dsi_phy_usecase uc;
-	struct dsi_pll_7nm *slave;
-};
-
-#define to_pll_7nm(x)	container_of(x, struct dsi_pll_7nm, base)
-
-/*
- * Global list of private DSI PLL struct pointers. We need this for Dual DSI
- * mode, where the master PLL's clk_ops needs access the slave's private data
- */
-static struct dsi_pll_7nm *pll_7nm_list[DSI_MAX];
-
-static void dsi_pll_setup_config(struct dsi_pll_7nm *pll)
-{
-	struct dsi_pll_config *config = &pll->pll_configuration;
-
-	config->ref_freq = pll->vco_ref_clk_rate;
-	config->output_div = 1;
-	config->dec_bits = 8;
-	config->frac_bits = 18;
-	config->lock_timer = 64;
-	config->ssc_freq = 31500;
-	config->ssc_offset = 4800;
-	config->ssc_adj_per = 2;
-	config->thresh_cycles = 32;
-	config->refclk_cycles = 256;
-
-	config->div_override = false;
-	config->ignore_frac = false;
-	config->disable_prescaler = false;
-
-	/* TODO: ssc enable */
-	config->enable_ssc = false;
-	config->ssc_center = 0;
-}
-
-static void dsi_pll_calc_dec_frac(struct dsi_pll_7nm *pll)
-{
-	struct dsi_pll_config *config = &pll->pll_configuration;
-	struct dsi_pll_regs *regs = &pll->reg_setup;
-	u64 fref = pll->vco_ref_clk_rate;
-	u64 pll_freq;
-	u64 divider;
-	u64 dec, dec_multiple;
-	u32 frac;
-	u64 multiplier;
-
-	pll_freq = pll->vco_current_rate;
-
-	if (config->disable_prescaler)
-		divider = fref;
-	else
-		divider = fref * 2;
-
-	multiplier = 1 << config->frac_bits;
-	dec_multiple = div_u64(pll_freq * multiplier, divider);
-	div_u64_rem(dec_multiple, multiplier, &frac);
-
-	dec = div_u64(dec_multiple, multiplier);
-
-	if (pll->base.type != MSM_DSI_PHY_7NM_V4_1)
-		regs->pll_clock_inverters = 0x28;
-	else if (pll_freq <= 1000000000ULL)
-		regs->pll_clock_inverters = 0xa0;
-	else if (pll_freq <= 2500000000ULL)
-		regs->pll_clock_inverters = 0x20;
-	else if (pll_freq <= 3020000000ULL)
-		regs->pll_clock_inverters = 0x00;
-	else
-		regs->pll_clock_inverters = 0x40;
-
-	regs->pll_lockdet_rate = config->lock_timer;
-	regs->decimal_div_start = dec;
-	regs->frac_div_start_low = (frac & 0xff);
-	regs->frac_div_start_mid = (frac & 0xff00) >> 8;
-	regs->frac_div_start_high = (frac & 0x30000) >> 16;
-}
-
-#define SSC_CENTER		BIT(0)
-#define SSC_EN			BIT(1)
-
-static void dsi_pll_calc_ssc(struct dsi_pll_7nm *pll)
-{
-	struct dsi_pll_config *config = &pll->pll_configuration;
-	struct dsi_pll_regs *regs = &pll->reg_setup;
-	u32 ssc_per;
-	u32 ssc_mod;
-	u64 ssc_step_size;
-	u64 frac;
-
-	if (!config->enable_ssc) {
-		DBG("SSC not enabled\n");
-		return;
-	}
-
-	ssc_per = DIV_ROUND_CLOSEST(config->ref_freq, config->ssc_freq) / 2 - 1;
-	ssc_mod = (ssc_per + 1) % (config->ssc_adj_per + 1);
-	ssc_per -= ssc_mod;
-
-	frac = regs->frac_div_start_low |
-			(regs->frac_div_start_mid << 8) |
-			(regs->frac_div_start_high << 16);
-	ssc_step_size = regs->decimal_div_start;
-	ssc_step_size *= (1 << config->frac_bits);
-	ssc_step_size += frac;
-	ssc_step_size *= config->ssc_offset;
-	ssc_step_size *= (config->ssc_adj_per + 1);
-	ssc_step_size = div_u64(ssc_step_size, (ssc_per + 1));
-	ssc_step_size = DIV_ROUND_CLOSEST_ULL(ssc_step_size, 1000000);
-
-	regs->ssc_div_per_low = ssc_per & 0xFF;
-	regs->ssc_div_per_high = (ssc_per & 0xFF00) >> 8;
-	regs->ssc_stepsize_low = (u32)(ssc_step_size & 0xFF);
-	regs->ssc_stepsize_high = (u32)((ssc_step_size & 0xFF00) >> 8);
-	regs->ssc_adjper_low = config->ssc_adj_per & 0xFF;
-	regs->ssc_adjper_high = (config->ssc_adj_per & 0xFF00) >> 8;
-
-	regs->ssc_control = config->ssc_center ? SSC_CENTER : 0;
-
-	pr_debug("SCC: Dec:%d, frac:%llu, frac_bits:%d\n",
-		 regs->decimal_div_start, frac, config->frac_bits);
-	pr_debug("SSC: div_per:0x%X, stepsize:0x%X, adjper:0x%X\n",
-		 ssc_per, (u32)ssc_step_size, config->ssc_adj_per);
-}
-
-static void dsi_pll_ssc_commit(struct dsi_pll_7nm *pll)
-{
-	void __iomem *base = pll->mmio;
-	struct dsi_pll_regs *regs = &pll->reg_setup;
-
-	if (pll->pll_configuration.enable_ssc) {
-		pr_debug("SSC is enabled\n");
-
-		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_STEPSIZE_LOW_1,
-			  regs->ssc_stepsize_low);
-		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_STEPSIZE_HIGH_1,
-			  regs->ssc_stepsize_high);
-		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_DIV_PER_LOW_1,
-			  regs->ssc_div_per_low);
-		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_DIV_PER_HIGH_1,
-			  regs->ssc_div_per_high);
-		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_ADJPER_LOW_1,
-			  regs->ssc_adjper_low);
-		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_ADJPER_HIGH_1,
-			  regs->ssc_adjper_high);
-		pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_CONTROL,
-			  SSC_EN | regs->ssc_control);
-	}
-}
-
-static void dsi_pll_config_hzindep_reg(struct dsi_pll_7nm *pll)
-{
-	void __iomem *base = pll->mmio;
-	u8 analog_controls_five_1 = 0x01, vco_config_1 = 0x00;
-
-	if (pll->base.type == MSM_DSI_PHY_7NM_V4_1) {
-		if (pll->vco_current_rate >= 3100000000ULL)
-			analog_controls_five_1 = 0x03;
-
-		if (pll->vco_current_rate < 1520000000ULL)
-			vco_config_1 = 0x08;
-		else if (pll->vco_current_rate < 2990000000ULL)
-			vco_config_1 = 0x01;
-	}
-
-	pll_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_FIVE_1,
-		  analog_controls_five_1);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_VCO_CONFIG_1, vco_config_1);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_FIVE, 0x01);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_TWO, 0x03);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_THREE, 0x00);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_DSM_DIVIDER, 0x00);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_FEEDBACK_DIVIDER, 0x4e);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_CALIBRATION_SETTINGS, 0x40);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_BAND_SEL_CAL_SETTINGS_THREE, 0xba);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_FREQ_DETECT_SETTINGS_ONE, 0x0c);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_OUTDIV, 0x00);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_CORE_OVERRIDE, 0x00);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_DIGITAL_TIMERS_TWO, 0x08);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_PROP_GAIN_RATE_1, 0x0a);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_BAND_SEL_RATE_1, 0xc0);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_1, 0x84);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_1, 0x82);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_FL_INT_GAIN_PFILT_BAND_1, 0x4c);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCK_OVERRIDE, 0x80);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_PFILT, 0x29);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_PFILT, 0x2f);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_IFILT, 0x2a);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_IFILT,
-		  pll->base.type == MSM_DSI_PHY_7NM_V4_1 ? 0x3f : 0x22);
-
-	if (pll->base.type == MSM_DSI_PHY_7NM_V4_1) {
-		pll_write(base + REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE, 0x22);
-		if (pll->slave)
-			pll_write(pll->slave->mmio + REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE, 0x22);
-	}
-}
-
-static void dsi_pll_commit(struct dsi_pll_7nm *pll)
-{
-	void __iomem *base = pll->mmio;
-	struct dsi_pll_regs *reg = &pll->reg_setup;
-
-	pll_write(base + REG_DSI_7nm_PHY_PLL_CORE_INPUT_OVERRIDE, 0x12);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_DECIMAL_DIV_START_1, reg->decimal_div_start);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_LOW_1, reg->frac_div_start_low);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_MID_1, reg->frac_div_start_mid);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_HIGH_1, reg->frac_div_start_high);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCKDET_RATE_1, reg->pll_lockdet_rate);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCK_DELAY, 0x06);
-	pll_write(base + REG_DSI_7nm_PHY_PLL_CMODE_1, 0x10); /* TODO: 0x00 for CPHY */
-	pll_write(base + REG_DSI_7nm_PHY_PLL_CLOCK_INVERTERS, reg->pll_clock_inverters);
-}
-
-static int dsi_pll_7nm_vco_set_rate(struct clk_hw *hw, unsigned long rate,
-				     unsigned long parent_rate)
-{
-	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
-	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);
-
-	DBG("DSI PLL%d rate=%lu, parent's=%lu", pll_7nm->id, rate,
-	    parent_rate);
-
-	pll_7nm->vco_current_rate = rate;
-	pll_7nm->vco_ref_clk_rate = VCO_REF_CLK_RATE;
-
-	dsi_pll_setup_config(pll_7nm);
-
-	dsi_pll_calc_dec_frac(pll_7nm);
-
-	dsi_pll_calc_ssc(pll_7nm);
-
-	dsi_pll_commit(pll_7nm);
-
-	dsi_pll_config_hzindep_reg(pll_7nm);
-
-	dsi_pll_ssc_commit(pll_7nm);
-
-	/* flush, ensure all register writes are done*/
-	wmb();
-
-	return 0;
-}
-
-static int dsi_pll_7nm_lock_status(struct dsi_pll_7nm *pll)
-{
-	int rc;
-	u32 status = 0;
-	u32 const delay_us = 100;
-	u32 const timeout_us = 5000;
-
-	rc = readl_poll_timeout_atomic(pll->mmio +
-				       REG_DSI_7nm_PHY_PLL_COMMON_STATUS_ONE,
-				       status,
-				       ((status & BIT(0)) > 0),
-				       delay_us,
-				       timeout_us);
-	if (rc)
-		pr_err("DSI PLL(%d) lock failed, status=0x%08x\n",
-		       pll->id, status);
-
-	return rc;
-}
-
-static void dsi_pll_disable_pll_bias(struct dsi_pll_7nm *pll)
-{
-	u32 data = pll_read(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CTRL_0);
-
-	pll_write(pll->mmio + REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES, 0);
-	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CTRL_0, data & ~BIT(5));
-	ndelay(250);
-}
-
-static void dsi_pll_enable_pll_bias(struct dsi_pll_7nm *pll)
-{
-	u32 data = pll_read(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CTRL_0);
-
-	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CTRL_0, data | BIT(5));
-	pll_write(pll->mmio + REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES, 0xc0);
-	ndelay(250);
-}
-
-static void dsi_pll_disable_global_clk(struct dsi_pll_7nm *pll)
-{
-	u32 data;
-
-	data = pll_read(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
-	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CLK_CFG1, data & ~BIT(5));
-}
-
-static void dsi_pll_enable_global_clk(struct dsi_pll_7nm *pll)
-{
-	u32 data;
-
-	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CTRL_3, 0x04);
-
-	data = pll_read(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
-	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CLK_CFG1,
-		  data | BIT(5) | BIT(4));
-}
-
-static void dsi_pll_phy_dig_reset(struct dsi_pll_7nm *pll)
-{
-	/*
-	 * Reset the PHY digital domain. This would be needed when
-	 * coming out of a CX or analog rail power collapse while
-	 * ensuring that the pads maintain LP00 or LP11 state
-	 */
-	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE4, BIT(0));
-	wmb(); /* Ensure that the reset is deasserted */
-	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE4, 0x0);
-	wmb(); /* Ensure that the reset is deasserted */
-}
-
-static int dsi_pll_7nm_vco_prepare(struct clk_hw *hw)
-{
-	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
-	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);
-	int rc;
-
-	dsi_pll_enable_pll_bias(pll_7nm);
-	if (pll_7nm->slave)
-		dsi_pll_enable_pll_bias(pll_7nm->slave);
-
-	/* Start PLL */
-	pll_write(pll_7nm->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_PLL_CNTRL, 0x01);
-
-	/*
-	 * ensure all PLL configurations are written prior to checking
-	 * for PLL lock.
-	 */
-	wmb();
-
-	/* Check for PLL lock */
-	rc = dsi_pll_7nm_lock_status(pll_7nm);
-	if (rc) {
-		pr_err("PLL(%d) lock failed\n", pll_7nm->id);
-		goto error;
-	}
-
-	pll->pll_on = true;
-
-	/*
-	 * assert power on reset for PHY digital in case the PLL is
-	 * enabled after CX of analog domain power collapse. This needs
-	 * to be done before enabling the global clk.
-	 */
-	dsi_pll_phy_dig_reset(pll_7nm);
-	if (pll_7nm->slave)
-		dsi_pll_phy_dig_reset(pll_7nm->slave);
-
-	dsi_pll_enable_global_clk(pll_7nm);
-	if (pll_7nm->slave)
-		dsi_pll_enable_global_clk(pll_7nm->slave);
-
-error:
-	return rc;
-}
-
-static void dsi_pll_disable_sub(struct dsi_pll_7nm *pll)
-{
-	pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_RBUF_CTRL, 0);
-	dsi_pll_disable_pll_bias(pll);
-}
-
-static void dsi_pll_7nm_vco_unprepare(struct clk_hw *hw)
-{
-	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
-	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);
-
-	/*
-	 * To avoid any stray glitches while abruptly powering down the PLL
-	 * make sure to gate the clock using the clock enable bit before
-	 * powering down the PLL
-	 */
-	dsi_pll_disable_global_clk(pll_7nm);
-	pll_write(pll_7nm->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_PLL_CNTRL, 0);
-	dsi_pll_disable_sub(pll_7nm);
-	if (pll_7nm->slave) {
-		dsi_pll_disable_global_clk(pll_7nm->slave);
-		dsi_pll_disable_sub(pll_7nm->slave);
-	}
-	/* flush, ensure all register writes are done */
-	wmb();
-	pll->pll_on = false;
-}
-
-static unsigned long dsi_pll_7nm_vco_recalc_rate(struct clk_hw *hw,
-						  unsigned long parent_rate)
-{
-	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
-	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);
-	struct dsi_pll_config *config = &pll_7nm->pll_configuration;
-	void __iomem *base = pll_7nm->mmio;
-	u64 ref_clk = pll_7nm->vco_ref_clk_rate;
-	u64 vco_rate = 0x0;
-	u64 multiplier;
-	u32 frac;
-	u32 dec;
-	u64 pll_freq, tmp64;
-
-	dec = pll_read(base + REG_DSI_7nm_PHY_PLL_DECIMAL_DIV_START_1);
-	dec &= 0xff;
-
-	frac = pll_read(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_LOW_1);
-	frac |= ((pll_read(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_MID_1) &
-		  0xff) << 8);
-	frac |= ((pll_read(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_HIGH_1) &
-		  0x3) << 16);
-
-	/*
-	 * TODO:
-	 *	1. Assumes prescaler is disabled
-	 */
-	multiplier = 1 << config->frac_bits;
-	pll_freq = dec * (ref_clk * 2);
-	tmp64 = (ref_clk * 2 * frac);
-	pll_freq += div_u64(tmp64, multiplier);
-
-	vco_rate = pll_freq;
-
-	DBG("DSI PLL%d returning vco rate = %lu, dec = %x, frac = %x",
-	    pll_7nm->id, (unsigned long)vco_rate, dec, frac);
-
-	return (unsigned long)vco_rate;
-}
-
-static const struct clk_ops clk_ops_dsi_pll_7nm_vco = {
-	.round_rate = msm_dsi_pll_helper_clk_round_rate,
-	.set_rate = dsi_pll_7nm_vco_set_rate,
-	.recalc_rate = dsi_pll_7nm_vco_recalc_rate,
-	.prepare = dsi_pll_7nm_vco_prepare,
-	.unprepare = dsi_pll_7nm_vco_unprepare,
-};
-
-/*
- * PLL Callbacks
- */
-
-static void dsi_pll_7nm_save_state(struct msm_dsi_pll *pll)
-{
-	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);
-	struct pll_7nm_cached_state *cached = &pll_7nm->cached_state;
-	void __iomem *phy_base = pll_7nm->phy_cmn_mmio;
-	u32 cmn_clk_cfg0, cmn_clk_cfg1;
-
-	cached->pll_out_div = pll_read(pll_7nm->mmio +
-				       REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE);
-	cached->pll_out_div &= 0x3;
-
-	cmn_clk_cfg0 = pll_read(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0);
-	cached->bit_clk_div = cmn_clk_cfg0 & 0xf;
-	cached->pix_clk_div = (cmn_clk_cfg0 & 0xf0) >> 4;
-
-	cmn_clk_cfg1 = pll_read(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
-	cached->pll_mux = cmn_clk_cfg1 & 0x3;
-
-	DBG("DSI PLL%d outdiv %x bit_clk_div %x pix_clk_div %x pll_mux %x",
-	    pll_7nm->id, cached->pll_out_div, cached->bit_clk_div,
-	    cached->pix_clk_div, cached->pll_mux);
-}
-
-static int dsi_pll_7nm_restore_state(struct msm_dsi_pll *pll)
-{
-	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);
-	struct pll_7nm_cached_state *cached = &pll_7nm->cached_state;
-	void __iomem *phy_base = pll_7nm->phy_cmn_mmio;
-	u32 val;
-	int ret;
-
-	val = pll_read(pll_7nm->mmio + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE);
-	val &= ~0x3;
-	val |= cached->pll_out_div;
-	pll_write(pll_7nm->mmio + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE, val);
-
-	pll_write(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0,
-		  cached->bit_clk_div | (cached->pix_clk_div << 4));
-
-	val = pll_read(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
-	val &= ~0x3;
-	val |= cached->pll_mux;
-	pll_write(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, val);
-
-	ret = dsi_pll_7nm_vco_set_rate(&pll->clk_hw, pll_7nm->vco_current_rate, pll_7nm->vco_ref_clk_rate);
-	if (ret) {
-		DRM_DEV_ERROR(&pll_7nm->pdev->dev,
-			"restore vco rate failed. ret=%d\n", ret);
-		return ret;
-	}
-
-	DBG("DSI PLL%d", pll_7nm->id);
-
-	return 0;
-}
-
-static int dsi_pll_7nm_set_usecase(struct msm_dsi_pll *pll,
-				    enum msm_dsi_phy_usecase uc)
-{
-	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);
-	void __iomem *base = pll_7nm->phy_cmn_mmio;
-	u32 data = 0x0;	/* internal PLL */
-
-	DBG("DSI PLL%d", pll_7nm->id);
-
-	switch (uc) {
-	case MSM_DSI_PHY_STANDALONE:
-		break;
-	case MSM_DSI_PHY_MASTER:
-		pll_7nm->slave = pll_7nm_list[(pll_7nm->id + 1) % DSI_MAX];
-		break;
-	case MSM_DSI_PHY_SLAVE:
-		data = 0x1; /* external PLL */
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/* set PLL src */
-	pll_write(base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, (data << 2));
-
-	pll_7nm->uc = uc;
-
-	return 0;
-}
-
-static int dsi_pll_7nm_get_provider(struct msm_dsi_pll *pll,
-				     struct clk **byte_clk_provider,
-				     struct clk **pixel_clk_provider)
-{
-	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);
-	struct clk_hw_onecell_data *hw_data = pll_7nm->hw_data;
-
-	DBG("DSI PLL%d", pll_7nm->id);
-
-	if (byte_clk_provider)
-		*byte_clk_provider = hw_data->hws[DSI_BYTE_PLL_CLK]->clk;
-	if (pixel_clk_provider)
-		*pixel_clk_provider = hw_data->hws[DSI_PIXEL_PLL_CLK]->clk;
-
-	return 0;
-}
-
-static void dsi_pll_7nm_destroy(struct msm_dsi_pll *pll)
-{
-	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);
-	struct device *dev = &pll_7nm->pdev->dev;
-
-	DBG("DSI PLL%d", pll_7nm->id);
-	of_clk_del_provider(dev->of_node);
-
-	clk_hw_unregister_divider(pll_7nm->out_dsiclk_hw);
-	clk_hw_unregister_mux(pll_7nm->pclk_mux_hw);
-	clk_hw_unregister_fixed_factor(pll_7nm->post_out_div_clk_hw);
-	clk_hw_unregister_fixed_factor(pll_7nm->by_2_bit_clk_hw);
-	clk_hw_unregister_fixed_factor(pll_7nm->byte_clk_hw);
-	clk_hw_unregister_divider(pll_7nm->bit_clk_hw);
-	clk_hw_unregister_divider(pll_7nm->out_div_clk_hw);
-	clk_hw_unregister(&pll_7nm->base.clk_hw);
-}
-
-/*
- * The post dividers and mux clocks are created using the standard divider and
- * mux API. Unlike the 14nm PHY, the slave PLL doesn't need its dividers/mux
- * state to follow the master PLL's divider/mux state. Therefore, we don't
- * require special clock ops that also configure the slave PLL registers
- */
-static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm)
-{
-	char clk_name[32], parent[32], vco_name[32];
-	char parent2[32], parent3[32], parent4[32];
-	struct clk_init_data vco_init = {
-		.parent_names = (const char *[]){ "bi_tcxo" },
-		.num_parents = 1,
-		.name = vco_name,
-		.flags = CLK_IGNORE_UNUSED,
-		.ops = &clk_ops_dsi_pll_7nm_vco,
-	};
-	struct device *dev = &pll_7nm->pdev->dev;
-	struct clk_hw_onecell_data *hw_data;
-	struct clk_hw *hw;
-	int ret;
-
-	DBG("DSI%d", pll_7nm->id);
-
-	hw_data = devm_kzalloc(dev, sizeof(*hw_data) +
-			       NUM_PROVIDED_CLKS * sizeof(struct clk_hw *),
-			       GFP_KERNEL);
-	if (!hw_data)
-		return -ENOMEM;
-
-	snprintf(vco_name, 32, "dsi%dvco_clk", pll_7nm->id);
-	pll_7nm->base.clk_hw.init = &vco_init;
-
-	ret = clk_hw_register(dev, &pll_7nm->base.clk_hw);
-	if (ret)
-		return ret;
-
-	snprintf(clk_name, 32, "dsi%d_pll_out_div_clk", pll_7nm->id);
-	snprintf(parent, 32, "dsi%dvco_clk", pll_7nm->id);
-
-	hw = clk_hw_register_divider(dev, clk_name,
-				     parent, CLK_SET_RATE_PARENT,
-				     pll_7nm->mmio +
-				     REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE,
-				     0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL);
-	if (IS_ERR(hw)) {
-		ret = PTR_ERR(hw);
-		goto err_base_clk_hw;
-	}
-
-	pll_7nm->out_div_clk_hw = hw;
-
-	snprintf(clk_name, 32, "dsi%d_pll_bit_clk", pll_7nm->id);
-	snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_7nm->id);
-
-	/* BIT CLK: DIV_CTRL_3_0 */
-	hw = clk_hw_register_divider(dev, clk_name, parent,
-				     CLK_SET_RATE_PARENT,
-				     pll_7nm->phy_cmn_mmio +
-				     REG_DSI_7nm_PHY_CMN_CLK_CFG0,
-				     0, 4, CLK_DIVIDER_ONE_BASED,
-				     &pll_7nm->postdiv_lock);
-	if (IS_ERR(hw)) {
-		ret = PTR_ERR(hw);
-		goto err_out_div_clk_hw;
-	}
-
-	pll_7nm->bit_clk_hw = hw;
-
-	snprintf(clk_name, 32, "dsi%d_phy_pll_out_byteclk", pll_7nm->id);
-	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->id);
-
-	/* DSI Byte clock = VCO_CLK / OUT_DIV / BIT_DIV / 8 */
-	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,
-					  CLK_SET_RATE_PARENT, 1, 8);
-	if (IS_ERR(hw)) {
-		ret = PTR_ERR(hw);
-		goto err_bit_clk_hw;
-	}
-
-	pll_7nm->byte_clk_hw = hw;
-	hw_data->hws[DSI_BYTE_PLL_CLK] = hw;
-
-	snprintf(clk_name, 32, "dsi%d_pll_by_2_bit_clk", pll_7nm->id);
-	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->id);
-
-	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,
-					  0, 1, 2);
-	if (IS_ERR(hw)) {
-		ret = PTR_ERR(hw);
-		goto err_byte_clk_hw;
-	}
-
-	pll_7nm->by_2_bit_clk_hw = hw;
-
-	snprintf(clk_name, 32, "dsi%d_pll_post_out_div_clk", pll_7nm->id);
-	snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_7nm->id);
-
-	hw = clk_hw_register_fixed_factor(dev, clk_name, parent,
-					  0, 1, 4);
-	if (IS_ERR(hw)) {
-		ret = PTR_ERR(hw);
-		goto err_by_2_bit_clk_hw;
-	}
-
-	pll_7nm->post_out_div_clk_hw = hw;
-
-	snprintf(clk_name, 32, "dsi%d_pclk_mux", pll_7nm->id);
-	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->id);
-	snprintf(parent2, 32, "dsi%d_pll_by_2_bit_clk", pll_7nm->id);
-	snprintf(parent3, 32, "dsi%d_pll_out_div_clk", pll_7nm->id);
-	snprintf(parent4, 32, "dsi%d_pll_post_out_div_clk", pll_7nm->id);
-
-	hw = clk_hw_register_mux(dev, clk_name,
-				 ((const char *[]){
-				 parent, parent2, parent3, parent4
-				 }), 4, 0, pll_7nm->phy_cmn_mmio +
-				 REG_DSI_7nm_PHY_CMN_CLK_CFG1,
-				 0, 2, 0, NULL);
-	if (IS_ERR(hw)) {
-		ret = PTR_ERR(hw);
-		goto err_post_out_div_clk_hw;
-	}
-
-	pll_7nm->pclk_mux_hw = hw;
-
-	snprintf(clk_name, 32, "dsi%d_phy_pll_out_dsiclk", pll_7nm->id);
-	snprintf(parent, 32, "dsi%d_pclk_mux", pll_7nm->id);
-
-	/* PIX CLK DIV : DIV_CTRL_7_4*/
-	hw = clk_hw_register_divider(dev, clk_name, parent,
-				     0, pll_7nm->phy_cmn_mmio +
-					REG_DSI_7nm_PHY_CMN_CLK_CFG0,
-				     4, 4, CLK_DIVIDER_ONE_BASED,
-				     &pll_7nm->postdiv_lock);
-	if (IS_ERR(hw)) {
-		ret = PTR_ERR(hw);
-		goto err_pclk_mux_hw;
-	}
-
-	pll_7nm->out_dsiclk_hw = hw;
-	hw_data->hws[DSI_PIXEL_PLL_CLK] = hw;
-
-	hw_data->num = NUM_PROVIDED_CLKS;
-	pll_7nm->hw_data = hw_data;
-
-	ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
-				     pll_7nm->hw_data);
-	if (ret) {
-		DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret);
-		goto err_dsiclk_hw;
-	}
-
-	return 0;
-
-err_dsiclk_hw:
-	clk_hw_unregister_divider(pll_7nm->out_dsiclk_hw);
-err_pclk_mux_hw:
-	clk_hw_unregister_mux(pll_7nm->pclk_mux_hw);
-err_post_out_div_clk_hw:
-	clk_hw_unregister_fixed_factor(pll_7nm->post_out_div_clk_hw);
-err_by_2_bit_clk_hw:
-	clk_hw_unregister_fixed_factor(pll_7nm->by_2_bit_clk_hw);
-err_byte_clk_hw:
-	clk_hw_unregister_fixed_factor(pll_7nm->byte_clk_hw);
-err_bit_clk_hw:
-	clk_hw_unregister_divider(pll_7nm->bit_clk_hw);
-err_out_div_clk_hw:
-	clk_hw_unregister_divider(pll_7nm->out_div_clk_hw);
-err_base_clk_hw:
-	clk_hw_unregister(&pll_7nm->base.clk_hw);
-
-	return ret;
-}
-
-struct msm_dsi_pll *msm_dsi_pll_7nm_init(struct platform_device *pdev,
-					enum msm_dsi_phy_type type, int id)
-{
-	struct dsi_pll_7nm *pll_7nm;
-	struct msm_dsi_pll *pll;
-	int ret;
-
-	pll_7nm = devm_kzalloc(&pdev->dev, sizeof(*pll_7nm), GFP_KERNEL);
-	if (!pll_7nm)
-		return ERR_PTR(-ENOMEM);
-
-	DBG("DSI PLL%d", id);
-
-	pll_7nm->pdev = pdev;
-	pll_7nm->id = id;
-	pll_7nm_list[id] = pll_7nm;
-
-	pll_7nm->phy_cmn_mmio = msm_ioremap(pdev, "dsi_phy", "DSI_PHY");
-	if (IS_ERR_OR_NULL(pll_7nm->phy_cmn_mmio)) {
-		DRM_DEV_ERROR(&pdev->dev, "failed to map CMN PHY base\n");
-		return ERR_PTR(-ENOMEM);
-	}
-
-	pll_7nm->mmio = msm_ioremap(pdev, "dsi_pll", "DSI_PLL");
-	if (IS_ERR_OR_NULL(pll_7nm->mmio)) {
-		DRM_DEV_ERROR(&pdev->dev, "failed to map PLL base\n");
-		return ERR_PTR(-ENOMEM);
-	}
-
-	spin_lock_init(&pll_7nm->postdiv_lock);
-
-	pll = &pll_7nm->base;
-	pll->min_rate = 1000000000UL;
-	pll->max_rate = 3500000000UL;
-	if (type == MSM_DSI_PHY_7NM_V4_1) {
-		pll->min_rate = 600000000UL;
-		pll->max_rate = (unsigned long)5000000000ULL;
-		/* workaround for max rate overflowing on 32-bit builds: */
-		pll->max_rate = max(pll->max_rate, 0xffffffffUL);
-	}
-	pll->get_provider = dsi_pll_7nm_get_provider;
-	pll->destroy = dsi_pll_7nm_destroy;
-	pll->save_state = dsi_pll_7nm_save_state;
-	pll->restore_state = dsi_pll_7nm_restore_state;
-	pll->set_usecase = dsi_pll_7nm_set_usecase;
-
-	pll_7nm->vco_delay = 1;
-
-	ret = pll_7nm_register(pll_7nm);
-	if (ret) {
-		DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret);
-		return ERR_PTR(ret);
-	}
-
-	/* TODO: Remove this when we have proper display handover support */
-	msm_dsi_pll_save_state(pll);
-
-	return pll;
-}