Linux Audio

Check our new training course

Linux kernel drivers training

Mar 31-Apr 9, 2025, special US time zones
Register
Loading...
Note: File does not exist in v4.6.
   1/*
   2 * SPDX-License-Identifier: GPL-2.0
   3 * Copyright (c) 2018, The Linux Foundation
   4 */
   5
   6#include <linux/clk.h>
   7#include <linux/clk-provider.h>
   8#include <linux/iopoll.h>
   9
  10#include "dsi_phy.h"
  11#include "dsi.xml.h"
  12#include "dsi_phy_7nm.xml.h"
  13
  14/*
  15 * DSI PLL 7nm - clock diagram (eg: DSI0): TODO: updated CPHY diagram
  16 *
  17 *           dsi0_pll_out_div_clk  dsi0_pll_bit_clk
  18 *                              |                |
  19 *                              |                |
  20 *                 +---------+  |  +----------+  |  +----+
  21 *  dsi0vco_clk ---| out_div |--o--| divl_3_0 |--o--| /8 |-- dsi0_phy_pll_out_byteclk
  22 *                 +---------+  |  +----------+  |  +----+
  23 *                              |                |
  24 *                              |                |         dsi0_pll_by_2_bit_clk
  25 *                              |                |          |
  26 *                              |                |  +----+  |  |\  dsi0_pclk_mux
  27 *                              |                |--| /2 |--o--| \   |
  28 *                              |                |  +----+     |  \  |  +---------+
  29 *                              |                --------------|  |--o--| div_7_4 |-- dsi0_phy_pll_out_dsiclk
  30 *                              |------------------------------|  /     +---------+
  31 *                              |          +-----+             | /
  32 *                              -----------| /4? |--o----------|/
  33 *                                         +-----+  |           |
  34 *                                                  |           |dsiclk_sel
  35 *                                                  |
  36 *                                                  dsi0_pll_post_out_div_clk
  37 */
  38
  39#define VCO_REF_CLK_RATE		19200000
  40#define FRAC_BITS 18
  41
  42/* Hardware is V4.1 */
  43#define DSI_PHY_7NM_QUIRK_V4_1		BIT(0)
  44
  45struct dsi_pll_config {
  46	bool enable_ssc;
  47	bool ssc_center;
  48	u32 ssc_freq;
  49	u32 ssc_offset;
  50	u32 ssc_adj_per;
  51
  52	/* out */
  53	u32 decimal_div_start;
  54	u32 frac_div_start;
  55	u32 pll_clock_inverters;
  56	u32 ssc_stepsize;
  57	u32 ssc_div_per;
  58};
  59
  60struct pll_7nm_cached_state {
  61	unsigned long vco_rate;
  62	u8 bit_clk_div;
  63	u8 pix_clk_div;
  64	u8 pll_out_div;
  65	u8 pll_mux;
  66};
  67
  68struct dsi_pll_7nm {
  69	struct clk_hw clk_hw;
  70
  71	struct msm_dsi_phy *phy;
  72
  73	u64 vco_current_rate;
  74
  75	/* protects REG_DSI_7nm_PHY_CMN_CLK_CFG0 register */
  76	spinlock_t postdiv_lock;
  77
  78	struct pll_7nm_cached_state cached_state;
  79
  80	struct dsi_pll_7nm *slave;
  81};
  82
  83#define to_pll_7nm(x)	container_of(x, struct dsi_pll_7nm, clk_hw)
  84
  85/*
  86 * Global list of private DSI PLL struct pointers. We need this for Dual DSI
  87 * mode, where the master PLL's clk_ops needs access the slave's private data
  88 */
  89static struct dsi_pll_7nm *pll_7nm_list[DSI_MAX];
  90
  91static void dsi_pll_setup_config(struct dsi_pll_config *config)
  92{
  93	config->ssc_freq = 31500;
  94	config->ssc_offset = 4800;
  95	config->ssc_adj_per = 2;
  96
  97	/* TODO: ssc enable */
  98	config->enable_ssc = false;
  99	config->ssc_center = 0;
 100}
 101
 102static void dsi_pll_calc_dec_frac(struct dsi_pll_7nm *pll, struct dsi_pll_config *config)
 103{
 104	u64 fref = VCO_REF_CLK_RATE;
 105	u64 pll_freq;
 106	u64 divider;
 107	u64 dec, dec_multiple;
 108	u32 frac;
 109	u64 multiplier;
 110
 111	pll_freq = pll->vco_current_rate;
 112
 113	divider = fref * 2;
 114
 115	multiplier = 1 << FRAC_BITS;
 116	dec_multiple = div_u64(pll_freq * multiplier, divider);
 117	div_u64_rem(dec_multiple, multiplier, &frac);
 118
 119	dec = div_u64(dec_multiple, multiplier);
 120
 121	if (!(pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1))
 122		config->pll_clock_inverters = 0x28;
 123	else if (pll_freq <= 1000000000ULL)
 124		config->pll_clock_inverters = 0xa0;
 125	else if (pll_freq <= 2500000000ULL)
 126		config->pll_clock_inverters = 0x20;
 127	else if (pll_freq <= 3020000000ULL)
 128		config->pll_clock_inverters = 0x00;
 129	else
 130		config->pll_clock_inverters = 0x40;
 131
 132	config->decimal_div_start = dec;
 133	config->frac_div_start = frac;
 134}
 135
 136#define SSC_CENTER		BIT(0)
 137#define SSC_EN			BIT(1)
 138
 139static void dsi_pll_calc_ssc(struct dsi_pll_7nm *pll, struct dsi_pll_config *config)
 140{
 141	u32 ssc_per;
 142	u32 ssc_mod;
 143	u64 ssc_step_size;
 144	u64 frac;
 145
 146	if (!config->enable_ssc) {
 147		DBG("SSC not enabled\n");
 148		return;
 149	}
 150
 151	ssc_per = DIV_ROUND_CLOSEST(VCO_REF_CLK_RATE, config->ssc_freq) / 2 - 1;
 152	ssc_mod = (ssc_per + 1) % (config->ssc_adj_per + 1);
 153	ssc_per -= ssc_mod;
 154
 155	frac = config->frac_div_start;
 156	ssc_step_size = config->decimal_div_start;
 157	ssc_step_size *= (1 << FRAC_BITS);
 158	ssc_step_size += frac;
 159	ssc_step_size *= config->ssc_offset;
 160	ssc_step_size *= (config->ssc_adj_per + 1);
 161	ssc_step_size = div_u64(ssc_step_size, (ssc_per + 1));
 162	ssc_step_size = DIV_ROUND_CLOSEST_ULL(ssc_step_size, 1000000);
 163
 164	config->ssc_div_per = ssc_per;
 165	config->ssc_stepsize = ssc_step_size;
 166
 167	pr_debug("SCC: Dec:%d, frac:%llu, frac_bits:%d\n",
 168		 config->decimal_div_start, frac, FRAC_BITS);
 169	pr_debug("SSC: div_per:0x%X, stepsize:0x%X, adjper:0x%X\n",
 170		 ssc_per, (u32)ssc_step_size, config->ssc_adj_per);
 171}
 172
 173static void dsi_pll_ssc_commit(struct dsi_pll_7nm *pll, struct dsi_pll_config *config)
 174{
 175	void __iomem *base = pll->phy->pll_base;
 176
 177	if (config->enable_ssc) {
 178		pr_debug("SSC is enabled\n");
 179
 180		dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_SSC_STEPSIZE_LOW_1,
 181			  config->ssc_stepsize & 0xff);
 182		dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_SSC_STEPSIZE_HIGH_1,
 183			  config->ssc_stepsize >> 8);
 184		dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_SSC_DIV_PER_LOW_1,
 185			  config->ssc_div_per & 0xff);
 186		dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_SSC_DIV_PER_HIGH_1,
 187			  config->ssc_div_per >> 8);
 188		dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_SSC_ADJPER_LOW_1,
 189			  config->ssc_adj_per & 0xff);
 190		dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_SSC_ADJPER_HIGH_1,
 191			  config->ssc_adj_per >> 8);
 192		dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_SSC_CONTROL,
 193			  SSC_EN | (config->ssc_center ? SSC_CENTER : 0));
 194	}
 195}
 196
 197static void dsi_pll_config_hzindep_reg(struct dsi_pll_7nm *pll)
 198{
 199	void __iomem *base = pll->phy->pll_base;
 200	u8 analog_controls_five_1 = 0x01, vco_config_1 = 0x00;
 201
 202	if (pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1) {
 203		if (pll->vco_current_rate >= 3100000000ULL)
 204			analog_controls_five_1 = 0x03;
 205
 206		if (pll->vco_current_rate < 1520000000ULL)
 207			vco_config_1 = 0x08;
 208		else if (pll->vco_current_rate < 2990000000ULL)
 209			vco_config_1 = 0x01;
 210	}
 211
 212	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_FIVE_1,
 213		  analog_controls_five_1);
 214	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_VCO_CONFIG_1, vco_config_1);
 215	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_FIVE, 0x01);
 216	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_TWO, 0x03);
 217	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_THREE, 0x00);
 218	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_DSM_DIVIDER, 0x00);
 219	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_FEEDBACK_DIVIDER, 0x4e);
 220	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_CALIBRATION_SETTINGS, 0x40);
 221	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_BAND_SEL_CAL_SETTINGS_THREE, 0xba);
 222	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_FREQ_DETECT_SETTINGS_ONE, 0x0c);
 223	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_OUTDIV, 0x00);
 224	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_CORE_OVERRIDE, 0x00);
 225	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PLL_DIGITAL_TIMERS_TWO, 0x08);
 226	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PLL_PROP_GAIN_RATE_1, 0x0a);
 227	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PLL_BAND_SEL_RATE_1, 0xc0);
 228	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_1, 0x84);
 229	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_1, 0x82);
 230	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PLL_FL_INT_GAIN_PFILT_BAND_1, 0x4c);
 231	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCK_OVERRIDE, 0x80);
 232	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PFILT, 0x29);
 233	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PFILT, 0x2f);
 234	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_IFILT, 0x2a);
 235	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_IFILT,
 236		  pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1 ? 0x3f : 0x22);
 237
 238	if (pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1) {
 239		dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE, 0x22);
 240		if (pll->slave)
 241			dsi_phy_write(pll->slave->phy->pll_base + REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE, 0x22);
 242	}
 243}
 244
 245static void dsi_pll_commit(struct dsi_pll_7nm *pll, struct dsi_pll_config *config)
 246{
 247	void __iomem *base = pll->phy->pll_base;
 248
 249	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_CORE_INPUT_OVERRIDE, 0x12);
 250	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_DECIMAL_DIV_START_1, config->decimal_div_start);
 251	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_LOW_1,
 252		  config->frac_div_start & 0xff);
 253	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_MID_1,
 254		  (config->frac_div_start & 0xff00) >> 8);
 255	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_HIGH_1,
 256		  (config->frac_div_start & 0x30000) >> 16);
 257	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCKDET_RATE_1, 0x40);
 258	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCK_DELAY, 0x06);
 259	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_CMODE_1, 0x10); /* TODO: 0x00 for CPHY */
 260	dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_CLOCK_INVERTERS, config->pll_clock_inverters);
 261}
 262
 263static int dsi_pll_7nm_vco_set_rate(struct clk_hw *hw, unsigned long rate,
 264				     unsigned long parent_rate)
 265{
 266	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(hw);
 267	struct dsi_pll_config config;
 268
 269	DBG("DSI PLL%d rate=%lu, parent's=%lu", pll_7nm->phy->id, rate,
 270	    parent_rate);
 271
 272	pll_7nm->vco_current_rate = rate;
 273
 274	dsi_pll_setup_config(&config);
 275
 276	dsi_pll_calc_dec_frac(pll_7nm, &config);
 277
 278	dsi_pll_calc_ssc(pll_7nm, &config);
 279
 280	dsi_pll_commit(pll_7nm, &config);
 281
 282	dsi_pll_config_hzindep_reg(pll_7nm);
 283
 284	dsi_pll_ssc_commit(pll_7nm, &config);
 285
 286	/* flush, ensure all register writes are done*/
 287	wmb();
 288
 289	return 0;
 290}
 291
 292static int dsi_pll_7nm_lock_status(struct dsi_pll_7nm *pll)
 293{
 294	int rc;
 295	u32 status = 0;
 296	u32 const delay_us = 100;
 297	u32 const timeout_us = 5000;
 298
 299	rc = readl_poll_timeout_atomic(pll->phy->pll_base +
 300				       REG_DSI_7nm_PHY_PLL_COMMON_STATUS_ONE,
 301				       status,
 302				       ((status & BIT(0)) > 0),
 303				       delay_us,
 304				       timeout_us);
 305	if (rc)
 306		pr_err("DSI PLL(%d) lock failed, status=0x%08x\n",
 307		       pll->phy->id, status);
 308
 309	return rc;
 310}
 311
 312static void dsi_pll_disable_pll_bias(struct dsi_pll_7nm *pll)
 313{
 314	u32 data = dsi_phy_read(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0);
 315
 316	dsi_phy_write(pll->phy->pll_base + REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES, 0);
 317	dsi_phy_write(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0, data & ~BIT(5));
 318	ndelay(250);
 319}
 320
 321static void dsi_pll_enable_pll_bias(struct dsi_pll_7nm *pll)
 322{
 323	u32 data = dsi_phy_read(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0);
 324
 325	dsi_phy_write(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0, data | BIT(5));
 326	dsi_phy_write(pll->phy->pll_base + REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES, 0xc0);
 327	ndelay(250);
 328}
 329
 330static void dsi_pll_disable_global_clk(struct dsi_pll_7nm *pll)
 331{
 332	u32 data;
 333
 334	data = dsi_phy_read(pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
 335	dsi_phy_write(pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, data & ~BIT(5));
 336}
 337
 338static void dsi_pll_enable_global_clk(struct dsi_pll_7nm *pll)
 339{
 340	u32 data;
 341
 342	dsi_phy_write(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_3, 0x04);
 343
 344	data = dsi_phy_read(pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
 345	dsi_phy_write(pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1,
 346		  data | BIT(5) | BIT(4));
 347}
 348
 349static void dsi_pll_phy_dig_reset(struct dsi_pll_7nm *pll)
 350{
 351	/*
 352	 * Reset the PHY digital domain. This would be needed when
 353	 * coming out of a CX or analog rail power collapse while
 354	 * ensuring that the pads maintain LP00 or LP11 state
 355	 */
 356	dsi_phy_write(pll->phy->base + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE4, BIT(0));
 357	wmb(); /* Ensure that the reset is deasserted */
 358	dsi_phy_write(pll->phy->base + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE4, 0x0);
 359	wmb(); /* Ensure that the reset is deasserted */
 360}
 361
 362static int dsi_pll_7nm_vco_prepare(struct clk_hw *hw)
 363{
 364	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(hw);
 365	int rc;
 366
 367	dsi_pll_enable_pll_bias(pll_7nm);
 368	if (pll_7nm->slave)
 369		dsi_pll_enable_pll_bias(pll_7nm->slave);
 370
 371	/* Start PLL */
 372	dsi_phy_write(pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_PLL_CNTRL, 0x01);
 373
 374	/*
 375	 * ensure all PLL configurations are written prior to checking
 376	 * for PLL lock.
 377	 */
 378	wmb();
 379
 380	/* Check for PLL lock */
 381	rc = dsi_pll_7nm_lock_status(pll_7nm);
 382	if (rc) {
 383		pr_err("PLL(%d) lock failed\n", pll_7nm->phy->id);
 384		goto error;
 385	}
 386
 387	pll_7nm->phy->pll_on = true;
 388
 389	/*
 390	 * assert power on reset for PHY digital in case the PLL is
 391	 * enabled after CX of analog domain power collapse. This needs
 392	 * to be done before enabling the global clk.
 393	 */
 394	dsi_pll_phy_dig_reset(pll_7nm);
 395	if (pll_7nm->slave)
 396		dsi_pll_phy_dig_reset(pll_7nm->slave);
 397
 398	dsi_pll_enable_global_clk(pll_7nm);
 399	if (pll_7nm->slave)
 400		dsi_pll_enable_global_clk(pll_7nm->slave);
 401
 402error:
 403	return rc;
 404}
 405
 406static void dsi_pll_disable_sub(struct dsi_pll_7nm *pll)
 407{
 408	dsi_phy_write(pll->phy->base + REG_DSI_7nm_PHY_CMN_RBUF_CTRL, 0);
 409	dsi_pll_disable_pll_bias(pll);
 410}
 411
 412static void dsi_pll_7nm_vco_unprepare(struct clk_hw *hw)
 413{
 414	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(hw);
 415
 416	/*
 417	 * To avoid any stray glitches while abruptly powering down the PLL
 418	 * make sure to gate the clock using the clock enable bit before
 419	 * powering down the PLL
 420	 */
 421	dsi_pll_disable_global_clk(pll_7nm);
 422	dsi_phy_write(pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_PLL_CNTRL, 0);
 423	dsi_pll_disable_sub(pll_7nm);
 424	if (pll_7nm->slave) {
 425		dsi_pll_disable_global_clk(pll_7nm->slave);
 426		dsi_pll_disable_sub(pll_7nm->slave);
 427	}
 428	/* flush, ensure all register writes are done */
 429	wmb();
 430	pll_7nm->phy->pll_on = false;
 431}
 432
 433static unsigned long dsi_pll_7nm_vco_recalc_rate(struct clk_hw *hw,
 434						  unsigned long parent_rate)
 435{
 436	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(hw);
 437	void __iomem *base = pll_7nm->phy->pll_base;
 438	u64 ref_clk = VCO_REF_CLK_RATE;
 439	u64 vco_rate = 0x0;
 440	u64 multiplier;
 441	u32 frac;
 442	u32 dec;
 443	u64 pll_freq, tmp64;
 444
 445	dec = dsi_phy_read(base + REG_DSI_7nm_PHY_PLL_DECIMAL_DIV_START_1);
 446	dec &= 0xff;
 447
 448	frac = dsi_phy_read(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_LOW_1);
 449	frac |= ((dsi_phy_read(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_MID_1) &
 450		  0xff) << 8);
 451	frac |= ((dsi_phy_read(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_HIGH_1) &
 452		  0x3) << 16);
 453
 454	/*
 455	 * TODO:
 456	 *	1. Assumes prescaler is disabled
 457	 */
 458	multiplier = 1 << FRAC_BITS;
 459	pll_freq = dec * (ref_clk * 2);
 460	tmp64 = (ref_clk * 2 * frac);
 461	pll_freq += div_u64(tmp64, multiplier);
 462
 463	vco_rate = pll_freq;
 464	pll_7nm->vco_current_rate = vco_rate;
 465
 466	DBG("DSI PLL%d returning vco rate = %lu, dec = %x, frac = %x",
 467	    pll_7nm->phy->id, (unsigned long)vco_rate, dec, frac);
 468
 469	return (unsigned long)vco_rate;
 470}
 471
 472static long dsi_pll_7nm_clk_round_rate(struct clk_hw *hw,
 473		unsigned long rate, unsigned long *parent_rate)
 474{
 475	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(hw);
 476
 477	if      (rate < pll_7nm->phy->cfg->min_pll_rate)
 478		return  pll_7nm->phy->cfg->min_pll_rate;
 479	else if (rate > pll_7nm->phy->cfg->max_pll_rate)
 480		return  pll_7nm->phy->cfg->max_pll_rate;
 481	else
 482		return rate;
 483}
 484
 485static const struct clk_ops clk_ops_dsi_pll_7nm_vco = {
 486	.round_rate = dsi_pll_7nm_clk_round_rate,
 487	.set_rate = dsi_pll_7nm_vco_set_rate,
 488	.recalc_rate = dsi_pll_7nm_vco_recalc_rate,
 489	.prepare = dsi_pll_7nm_vco_prepare,
 490	.unprepare = dsi_pll_7nm_vco_unprepare,
 491};
 492
 493/*
 494 * PLL Callbacks
 495 */
 496
 497static void dsi_7nm_pll_save_state(struct msm_dsi_phy *phy)
 498{
 499	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(phy->vco_hw);
 500	struct pll_7nm_cached_state *cached = &pll_7nm->cached_state;
 501	void __iomem *phy_base = pll_7nm->phy->base;
 502	u32 cmn_clk_cfg0, cmn_clk_cfg1;
 503
 504	cached->pll_out_div = dsi_phy_read(pll_7nm->phy->pll_base +
 505				       REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE);
 506	cached->pll_out_div &= 0x3;
 507
 508	cmn_clk_cfg0 = dsi_phy_read(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0);
 509	cached->bit_clk_div = cmn_clk_cfg0 & 0xf;
 510	cached->pix_clk_div = (cmn_clk_cfg0 & 0xf0) >> 4;
 511
 512	cmn_clk_cfg1 = dsi_phy_read(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
 513	cached->pll_mux = cmn_clk_cfg1 & 0x3;
 514
 515	DBG("DSI PLL%d outdiv %x bit_clk_div %x pix_clk_div %x pll_mux %x",
 516	    pll_7nm->phy->id, cached->pll_out_div, cached->bit_clk_div,
 517	    cached->pix_clk_div, cached->pll_mux);
 518}
 519
 520static int dsi_7nm_pll_restore_state(struct msm_dsi_phy *phy)
 521{
 522	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(phy->vco_hw);
 523	struct pll_7nm_cached_state *cached = &pll_7nm->cached_state;
 524	void __iomem *phy_base = pll_7nm->phy->base;
 525	u32 val;
 526	int ret;
 527
 528	val = dsi_phy_read(pll_7nm->phy->pll_base + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE);
 529	val &= ~0x3;
 530	val |= cached->pll_out_div;
 531	dsi_phy_write(pll_7nm->phy->pll_base + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE, val);
 532
 533	dsi_phy_write(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0,
 534		  cached->bit_clk_div | (cached->pix_clk_div << 4));
 535
 536	val = dsi_phy_read(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
 537	val &= ~0x3;
 538	val |= cached->pll_mux;
 539	dsi_phy_write(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, val);
 540
 541	ret = dsi_pll_7nm_vco_set_rate(phy->vco_hw,
 542			pll_7nm->vco_current_rate,
 543			VCO_REF_CLK_RATE);
 544	if (ret) {
 545		DRM_DEV_ERROR(&pll_7nm->phy->pdev->dev,
 546			"restore vco rate failed. ret=%d\n", ret);
 547		return ret;
 548	}
 549
 550	DBG("DSI PLL%d", pll_7nm->phy->id);
 551
 552	return 0;
 553}
 554
 555static int dsi_7nm_set_usecase(struct msm_dsi_phy *phy)
 556{
 557	struct dsi_pll_7nm *pll_7nm = to_pll_7nm(phy->vco_hw);
 558	void __iomem *base = phy->base;
 559	u32 data = 0x0;	/* internal PLL */
 560
 561	DBG("DSI PLL%d", pll_7nm->phy->id);
 562
 563	switch (phy->usecase) {
 564	case MSM_DSI_PHY_STANDALONE:
 565		break;
 566	case MSM_DSI_PHY_MASTER:
 567		pll_7nm->slave = pll_7nm_list[(pll_7nm->phy->id + 1) % DSI_MAX];
 568		break;
 569	case MSM_DSI_PHY_SLAVE:
 570		data = 0x1; /* external PLL */
 571		break;
 572	default:
 573		return -EINVAL;
 574	}
 575
 576	/* set PLL src */
 577	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, (data << 2));
 578
 579	return 0;
 580}
 581
 582/*
 583 * The post dividers and mux clocks are created using the standard divider and
 584 * mux API. Unlike the 14nm PHY, the slave PLL doesn't need its dividers/mux
 585 * state to follow the master PLL's divider/mux state. Therefore, we don't
 586 * require special clock ops that also configure the slave PLL registers
 587 */
 588static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provided_clocks)
 589{
 590	char clk_name[32], parent[32], vco_name[32];
 591	char parent2[32], parent3[32], parent4[32];
 592	struct clk_init_data vco_init = {
 593		.parent_names = (const char *[]){ "bi_tcxo" },
 594		.num_parents = 1,
 595		.name = vco_name,
 596		.flags = CLK_IGNORE_UNUSED,
 597		.ops = &clk_ops_dsi_pll_7nm_vco,
 598	};
 599	struct device *dev = &pll_7nm->phy->pdev->dev;
 600	struct clk_hw *hw;
 601	int ret;
 602
 603	DBG("DSI%d", pll_7nm->phy->id);
 604
 605	snprintf(vco_name, 32, "dsi%dvco_clk", pll_7nm->phy->id);
 606	pll_7nm->clk_hw.init = &vco_init;
 607
 608	ret = devm_clk_hw_register(dev, &pll_7nm->clk_hw);
 609	if (ret)
 610		return ret;
 611
 612	snprintf(clk_name, 32, "dsi%d_pll_out_div_clk", pll_7nm->phy->id);
 613	snprintf(parent, 32, "dsi%dvco_clk", pll_7nm->phy->id);
 614
 615	hw = devm_clk_hw_register_divider(dev, clk_name,
 616				     parent, CLK_SET_RATE_PARENT,
 617				     pll_7nm->phy->pll_base +
 618				     REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE,
 619				     0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL);
 620	if (IS_ERR(hw)) {
 621		ret = PTR_ERR(hw);
 622		goto fail;
 623	}
 624
 625	snprintf(clk_name, 32, "dsi%d_pll_bit_clk", pll_7nm->phy->id);
 626	snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_7nm->phy->id);
 627
 628	/* BIT CLK: DIV_CTRL_3_0 */
 629	hw = devm_clk_hw_register_divider(dev, clk_name, parent,
 630				     CLK_SET_RATE_PARENT,
 631				     pll_7nm->phy->base +
 632				     REG_DSI_7nm_PHY_CMN_CLK_CFG0,
 633				     0, 4, CLK_DIVIDER_ONE_BASED,
 634				     &pll_7nm->postdiv_lock);
 635	if (IS_ERR(hw)) {
 636		ret = PTR_ERR(hw);
 637		goto fail;
 638	}
 639
 640	snprintf(clk_name, 32, "dsi%d_phy_pll_out_byteclk", pll_7nm->phy->id);
 641	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->phy->id);
 642
 643	/* DSI Byte clock = VCO_CLK / OUT_DIV / BIT_DIV / 8 */
 644	hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent,
 645					  CLK_SET_RATE_PARENT, 1, 8);
 646	if (IS_ERR(hw)) {
 647		ret = PTR_ERR(hw);
 648		goto fail;
 649	}
 650
 651	provided_clocks[DSI_BYTE_PLL_CLK] = hw;
 652
 653	snprintf(clk_name, 32, "dsi%d_pll_by_2_bit_clk", pll_7nm->phy->id);
 654	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->phy->id);
 655
 656	hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent,
 657					  0, 1, 2);
 658	if (IS_ERR(hw)) {
 659		ret = PTR_ERR(hw);
 660		goto fail;
 661	}
 662
 663	snprintf(clk_name, 32, "dsi%d_pll_post_out_div_clk", pll_7nm->phy->id);
 664	snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_7nm->phy->id);
 665
 666	hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent,
 667					  0, 1, 4);
 668	if (IS_ERR(hw)) {
 669		ret = PTR_ERR(hw);
 670		goto fail;
 671	}
 672
 673	snprintf(clk_name, 32, "dsi%d_pclk_mux", pll_7nm->phy->id);
 674	snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->phy->id);
 675	snprintf(parent2, 32, "dsi%d_pll_by_2_bit_clk", pll_7nm->phy->id);
 676	snprintf(parent3, 32, "dsi%d_pll_out_div_clk", pll_7nm->phy->id);
 677	snprintf(parent4, 32, "dsi%d_pll_post_out_div_clk", pll_7nm->phy->id);
 678
 679	hw = devm_clk_hw_register_mux(dev, clk_name,
 680				 ((const char *[]){
 681				 parent, parent2, parent3, parent4
 682				 }), 4, 0, pll_7nm->phy->base +
 683				 REG_DSI_7nm_PHY_CMN_CLK_CFG1,
 684				 0, 2, 0, NULL);
 685	if (IS_ERR(hw)) {
 686		ret = PTR_ERR(hw);
 687		goto fail;
 688	}
 689
 690	snprintf(clk_name, 32, "dsi%d_phy_pll_out_dsiclk", pll_7nm->phy->id);
 691	snprintf(parent, 32, "dsi%d_pclk_mux", pll_7nm->phy->id);
 692
 693	/* PIX CLK DIV : DIV_CTRL_7_4*/
 694	hw = devm_clk_hw_register_divider(dev, clk_name, parent,
 695				     0, pll_7nm->phy->base +
 696					REG_DSI_7nm_PHY_CMN_CLK_CFG0,
 697				     4, 4, CLK_DIVIDER_ONE_BASED,
 698				     &pll_7nm->postdiv_lock);
 699	if (IS_ERR(hw)) {
 700		ret = PTR_ERR(hw);
 701		goto fail;
 702	}
 703
 704	provided_clocks[DSI_PIXEL_PLL_CLK] = hw;
 705
 706	return 0;
 707
 708fail:
 709
 710	return ret;
 711}
 712
 713static int dsi_pll_7nm_init(struct msm_dsi_phy *phy)
 714{
 715	struct platform_device *pdev = phy->pdev;
 716	struct dsi_pll_7nm *pll_7nm;
 717	int ret;
 718
 719	pll_7nm = devm_kzalloc(&pdev->dev, sizeof(*pll_7nm), GFP_KERNEL);
 720	if (!pll_7nm)
 721		return -ENOMEM;
 722
 723	DBG("DSI PLL%d", phy->id);
 724
 725	pll_7nm_list[phy->id] = pll_7nm;
 726
 727	spin_lock_init(&pll_7nm->postdiv_lock);
 728
 729	pll_7nm->phy = phy;
 730
 731	ret = pll_7nm_register(pll_7nm, phy->provided_clocks->hws);
 732	if (ret) {
 733		DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret);
 734		return ret;
 735	}
 736
 737	phy->vco_hw = &pll_7nm->clk_hw;
 738
 739	/* TODO: Remove this when we have proper display handover support */
 740	msm_dsi_phy_pll_save_state(phy);
 741
 742	return 0;
 743}
 744
 745static int dsi_phy_hw_v4_0_is_pll_on(struct msm_dsi_phy *phy)
 746{
 747	void __iomem *base = phy->base;
 748	u32 data = 0;
 749
 750	data = dsi_phy_read(base + REG_DSI_7nm_PHY_CMN_PLL_CNTRL);
 751	mb(); /* make sure read happened */
 752
 753	return (data & BIT(0));
 754}
 755
 756static void dsi_phy_hw_v4_0_config_lpcdrx(struct msm_dsi_phy *phy, bool enable)
 757{
 758	void __iomem *lane_base = phy->lane_base;
 759	int phy_lane_0 = 0;	/* TODO: Support all lane swap configs */
 760
 761	/*
 762	 * LPRX and CDRX need to enabled only for physical data lane
 763	 * corresponding to the logical data lane 0
 764	 */
 765	if (enable)
 766		dsi_phy_write(lane_base +
 767			      REG_DSI_7nm_PHY_LN_LPRX_CTRL(phy_lane_0), 0x3);
 768	else
 769		dsi_phy_write(lane_base +
 770			      REG_DSI_7nm_PHY_LN_LPRX_CTRL(phy_lane_0), 0);
 771}
 772
 773static void dsi_phy_hw_v4_0_lane_settings(struct msm_dsi_phy *phy)
 774{
 775	int i;
 776	const u8 tx_dctrl_0[] = { 0x00, 0x00, 0x00, 0x04, 0x01 };
 777	const u8 tx_dctrl_1[] = { 0x40, 0x40, 0x40, 0x46, 0x41 };
 778	const u8 *tx_dctrl = tx_dctrl_0;
 779	void __iomem *lane_base = phy->lane_base;
 780
 781	if (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1)
 782		tx_dctrl = tx_dctrl_1;
 783
 784	/* Strength ctrl settings */
 785	for (i = 0; i < 5; i++) {
 786		/*
 787		 * Disable LPRX and CDRX for all lanes. And later on, it will
 788		 * be only enabled for the physical data lane corresponding
 789		 * to the logical data lane 0
 790		 */
 791		dsi_phy_write(lane_base + REG_DSI_7nm_PHY_LN_LPRX_CTRL(i), 0);
 792		dsi_phy_write(lane_base + REG_DSI_7nm_PHY_LN_PIN_SWAP(i), 0x0);
 793	}
 794
 795	dsi_phy_hw_v4_0_config_lpcdrx(phy, true);
 796
 797	/* other settings */
 798	for (i = 0; i < 5; i++) {
 799		dsi_phy_write(lane_base + REG_DSI_7nm_PHY_LN_CFG0(i), 0x0);
 800		dsi_phy_write(lane_base + REG_DSI_7nm_PHY_LN_CFG1(i), 0x0);
 801		dsi_phy_write(lane_base + REG_DSI_7nm_PHY_LN_CFG2(i), i == 4 ? 0x8a : 0xa);
 802		dsi_phy_write(lane_base + REG_DSI_7nm_PHY_LN_TX_DCTRL(i), tx_dctrl[i]);
 803	}
 804}
 805
 806static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
 807			      struct msm_dsi_phy_clk_request *clk_req)
 808{
 809	int ret;
 810	u32 status;
 811	u32 const delay_us = 5;
 812	u32 const timeout_us = 1000;
 813	struct msm_dsi_dphy_timing *timing = &phy->timing;
 814	void __iomem *base = phy->base;
 815	bool less_than_1500_mhz;
 816	u32 vreg_ctrl_0, glbl_str_swi_cal_sel_ctrl, glbl_hstx_str_ctrl_0;
 817	u32 glbl_rescode_top_ctrl, glbl_rescode_bot_ctrl;
 818	u32 data;
 819
 820	DBG("");
 821
 822	if (msm_dsi_dphy_timing_calc_v4(timing, clk_req)) {
 823		DRM_DEV_ERROR(&phy->pdev->dev,
 824			"%s: D-PHY timing calculation failed\n", __func__);
 825		return -EINVAL;
 826	}
 827
 828	if (dsi_phy_hw_v4_0_is_pll_on(phy))
 829		pr_warn("PLL turned on before configuring PHY\n");
 830
 831	/* wait for REFGEN READY */
 832	ret = readl_poll_timeout_atomic(base + REG_DSI_7nm_PHY_CMN_PHY_STATUS,
 833					status, (status & BIT(0)),
 834					delay_us, timeout_us);
 835	if (ret) {
 836		pr_err("Ref gen not ready. Aborting\n");
 837		return -EINVAL;
 838	}
 839
 840	/* TODO: CPHY enable path (this is for DPHY only) */
 841
 842	/* Alter PHY configurations if data rate less than 1.5GHZ*/
 843	less_than_1500_mhz = (clk_req->bitclk_rate <= 1500000000);
 844
 845	if (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1) {
 846		vreg_ctrl_0 = less_than_1500_mhz ? 0x53 : 0x52;
 847		glbl_rescode_top_ctrl = less_than_1500_mhz ? 0x3d :  0x00;
 848		glbl_rescode_bot_ctrl = less_than_1500_mhz ? 0x39 :  0x3c;
 849		glbl_str_swi_cal_sel_ctrl = 0x00;
 850		glbl_hstx_str_ctrl_0 = 0x88;
 851	} else {
 852		vreg_ctrl_0 = less_than_1500_mhz ? 0x5B : 0x59;
 853		glbl_str_swi_cal_sel_ctrl = less_than_1500_mhz ? 0x03 : 0x00;
 854		glbl_hstx_str_ctrl_0 = less_than_1500_mhz ? 0x66 : 0x88;
 855		glbl_rescode_top_ctrl = 0x03;
 856		glbl_rescode_bot_ctrl = 0x3c;
 857	}
 858
 859	/* de-assert digital and pll power down */
 860	data = BIT(6) | BIT(5);
 861	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_0, data);
 862
 863	/* Assert PLL core reset */
 864	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_PLL_CNTRL, 0x00);
 865
 866	/* turn off resync FIFO */
 867	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_RBUF_CTRL, 0x00);
 868
 869	/* program CMN_CTRL_4 for minor_ver 2 chipsets*/
 870	data = dsi_phy_read(base + REG_DSI_7nm_PHY_CMN_REVISION_ID0);
 871	data = data & (0xf0);
 872	if (data == 0x20)
 873		dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_4, 0x04);
 874
 875	/* Configure PHY lane swap (TODO: we need to calculate this) */
 876	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_LANE_CFG0, 0x21);
 877	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_LANE_CFG1, 0x84);
 878
 879	/* Enable LDO */
 880	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_VREG_CTRL_0, vreg_ctrl_0);
 881	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_VREG_CTRL_1, 0x5c);
 882	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_3, 0x00);
 883	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_STR_SWI_CAL_SEL_CTRL,
 884		      glbl_str_swi_cal_sel_ctrl);
 885	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_HSTX_STR_CTRL_0,
 886		      glbl_hstx_str_ctrl_0);
 887	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_PEMPH_CTRL_0, 0x00);
 888	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_RESCODE_OFFSET_TOP_CTRL,
 889		      glbl_rescode_top_ctrl);
 890	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_RESCODE_OFFSET_BOT_CTRL,
 891		      glbl_rescode_bot_ctrl);
 892	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_LPTX_STR_CTRL, 0x55);
 893
 894	/* Remove power down from all blocks */
 895	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_0, 0x7f);
 896
 897	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_LANE_CTRL0, 0x1f);
 898
 899	/* Select full-rate mode */
 900	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_2, 0x40);
 901
 902	ret = dsi_7nm_set_usecase(phy);
 903	if (ret) {
 904		DRM_DEV_ERROR(&phy->pdev->dev, "%s: set pll usecase failed, %d\n",
 905			__func__, ret);
 906		return ret;
 907	}
 908
 909	/* DSI PHY timings */
 910	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_0, 0x00);
 911	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_1, timing->clk_zero);
 912	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_2, timing->clk_prepare);
 913	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_3, timing->clk_trail);
 914	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_4, timing->hs_exit);
 915	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_5, timing->hs_zero);
 916	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_6, timing->hs_prepare);
 917	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_7, timing->hs_trail);
 918	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_8, timing->hs_rqst);
 919	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_9, 0x02);
 920	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_10, 0x04);
 921	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_11, 0x00);
 922	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_12,
 923		      timing->shared_timings.clk_pre);
 924	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_13,
 925		      timing->shared_timings.clk_post);
 926
 927	/* DSI lane settings */
 928	dsi_phy_hw_v4_0_lane_settings(phy);
 929
 930	DBG("DSI%d PHY enabled", phy->id);
 931
 932	return 0;
 933}
 934
 935static void dsi_7nm_phy_disable(struct msm_dsi_phy *phy)
 936{
 937	void __iomem *base = phy->base;
 938	u32 data;
 939
 940	DBG("");
 941
 942	if (dsi_phy_hw_v4_0_is_pll_on(phy))
 943		pr_warn("Turning OFF PHY while PLL is on\n");
 944
 945	dsi_phy_hw_v4_0_config_lpcdrx(phy, false);
 946	data = dsi_phy_read(base + REG_DSI_7nm_PHY_CMN_CTRL_0);
 947
 948	/* disable all lanes */
 949	data &= ~0x1F;
 950	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_0, data);
 951	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_LANE_CTRL0, 0);
 952
 953	/* Turn off all PHY blocks */
 954	dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_0, 0x00);
 955	/* make sure phy is turned off */
 956	wmb();
 957
 958	DBG("DSI%d PHY disabled", phy->id);
 959}
 960
 961const struct msm_dsi_phy_cfg dsi_phy_7nm_cfgs = {
 962	.has_phy_lane = true,
 963	.reg_cfg = {
 964		.num = 1,
 965		.regs = {
 966			{"vdds", 36000, 32},
 967		},
 968	},
 969	.ops = {
 970		.enable = dsi_7nm_phy_enable,
 971		.disable = dsi_7nm_phy_disable,
 972		.pll_init = dsi_pll_7nm_init,
 973		.save_pll_state = dsi_7nm_pll_save_state,
 974		.restore_pll_state = dsi_7nm_pll_restore_state,
 975	},
 976	.min_pll_rate = 600000000UL,
 977#ifdef CONFIG_64BIT
 978	.max_pll_rate = 5000000000UL,
 979#else
 980	.max_pll_rate = ULONG_MAX,
 981#endif
 982	.io_start = { 0xae94400, 0xae96400 },
 983	.num_dsi_phy = 2,
 984	.quirks = DSI_PHY_7NM_QUIRK_V4_1,
 985};
 986
 987const struct msm_dsi_phy_cfg dsi_phy_7nm_8150_cfgs = {
 988	.has_phy_lane = true,
 989	.reg_cfg = {
 990		.num = 1,
 991		.regs = {
 992			{"vdds", 36000, 32},
 993		},
 994	},
 995	.ops = {
 996		.enable = dsi_7nm_phy_enable,
 997		.disable = dsi_7nm_phy_disable,
 998		.pll_init = dsi_pll_7nm_init,
 999		.save_pll_state = dsi_7nm_pll_save_state,
1000		.restore_pll_state = dsi_7nm_pll_restore_state,
1001	},
1002	.min_pll_rate = 1000000000UL,
1003	.max_pll_rate = 3500000000UL,
1004	.io_start = { 0xae94400, 0xae96400 },
1005	.num_dsi_phy = 2,
1006};