[Freedreno] [PATCH v2 05/28] drm/msm/dsi: fuse dsi_pll_* code into dsi_phy_* code
abhinavk at codeaurora.org
abhinavk at codeaurora.org
Fri Mar 26 17:48:16 UTC 2021
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 at linaro.org>
Reviewed-by: Abhinav Kumar <abhinavk at 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;
> -}
More information about the Freedreno
mailing list