xref: /linux/drivers/phy/qualcomm/phy-qcom-edp.c (revision 7d55b44e2be1069504e22253d26d08982884f930)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2017, 2020, The Linux Foundation. All rights reserved.
4  * Copyright (c) 2021, Linaro Ltd.
5  */
6 
7 #include <linux/clk.h>
8 #include <linux/clk-provider.h>
9 #include <linux/delay.h>
10 #include <linux/err.h>
11 #include <linux/io.h>
12 #include <linux/iopoll.h>
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/of.h>
16 #include <linux/phy/phy.h>
17 #include <linux/phy/phy-dp.h>
18 #include <linux/platform_device.h>
19 #include <linux/regulator/consumer.h>
20 #include <linux/reset.h>
21 #include <linux/slab.h>
22 
23 #include <dt-bindings/phy/phy.h>
24 
25 #include "phy-qcom-qmp-dp-phy.h"
26 #include "phy-qcom-qmp-qserdes-com-v4.h"
27 #include "phy-qcom-qmp-qserdes-com-v6.h"
28 
29 #include "phy-qcom-qmp-qserdes-dp-com-v8.h"
30 
31 /* EDP_PHY registers */
32 #define DP_PHY_CFG                              0x0010
33 #define DP_PHY_CFG_1                            0x0014
34 #define DP_PHY_PD_CTL                           0x001c
35 #define DP_PHY_MODE                             0x0020
36 
37 #define DP_AUX_CFG_SIZE                         13
38 #define DP_PHY_AUX_CFG(n)                       (0x24 + (0x04 * (n)))
39 
40 #define DP_PHY_AUX_INTERRUPT_MASK		0x0058
41 
42 #define DP_PHY_VCO_DIV                          0x0074
43 #define DP_PHY_TX0_TX1_LANE_CTL                 0x007c
44 #define DP_PHY_TX2_TX3_LANE_CTL                 0x00a0
45 
46 #define DP_PHY_STATUS                           0x00e0
47 
48 /* LANE_TXn registers */
49 #define TXn_CLKBUF_ENABLE                       0x0000
50 #define TXn_TX_EMP_POST1_LVL                    0x0004
51 
52 #define TXn_TX_DRV_LVL                          0x0014
53 #define TXn_TX_DRV_LVL_OFFSET                   0x0018
54 #define TXn_RESET_TSYNC_EN                      0x001c
55 #define TXn_LDO_CONFIG                          0x0084
56 #define TXn_TX_BAND                             0x0028
57 
58 #define TXn_RES_CODE_LANE_OFFSET_TX0            0x0044
59 #define TXn_RES_CODE_LANE_OFFSET_TX1            0x0048
60 
61 #define TXn_TRANSCEIVER_BIAS_EN                 0x0054
62 #define TXn_HIGHZ_DRVR_EN                       0x0058
63 #define TXn_TX_POL_INV                          0x005c
64 #define TXn_LANE_MODE_1                         0x0064
65 
66 #define TXn_TRAN_DRVR_EMP_EN                    0x0078
67 
68 struct qcom_edp_swing_pre_emph_cfg {
69 	const u8 (*swing_hbr_rbr)[4][4];
70 	const u8 (*swing_hbr3_hbr2)[4][4];
71 	const u8 (*pre_emphasis_hbr_rbr)[4][4];
72 	const u8 (*pre_emphasis_hbr3_hbr2)[4][4];
73 };
74 
75 struct qcom_edp;
76 
77 struct phy_ver_ops {
78 	int (*com_power_on)(const struct qcom_edp *edp);
79 	int (*com_resetsm_cntrl)(const struct qcom_edp *edp);
80 	int (*com_bias_en_clkbuflr)(const struct qcom_edp *edp);
81 	int (*com_clk_fwd_cfg)(const struct qcom_edp *edp);
82 	int (*com_configure_pll)(const struct qcom_edp *edp);
83 	int (*com_configure_ssc)(const struct qcom_edp *edp);
84 };
85 
86 struct qcom_edp_phy_cfg {
87 	bool is_edp;
88 	const u8 *aux_cfg;
89 	const u8 *vco_div_cfg;
90 	const struct qcom_edp_swing_pre_emph_cfg *swing_pre_emph_cfg;
91 	const struct phy_ver_ops *ver_ops;
92 };
93 
94 struct qcom_edp {
95 	struct device *dev;
96 	const struct qcom_edp_phy_cfg *cfg;
97 
98 	struct phy *phy;
99 
100 	void __iomem *edp;
101 	void __iomem *tx0;
102 	void __iomem *tx1;
103 	void __iomem *pll;
104 
105 	struct clk_hw dp_link_hw;
106 	struct clk_hw dp_pixel_hw;
107 
108 	struct phy_configure_opts_dp dp_opts;
109 
110 	struct clk_bulk_data *clks;
111 	int num_clks;
112 
113 	struct regulator_bulk_data supplies[2];
114 
115 	bool is_edp;
116 };
117 
118 static const u8 dp_swing_hbr_rbr[4][4] = {
119 	{ 0x08, 0x0f, 0x16, 0x1f },
120 	{ 0x11, 0x1e, 0x1f, 0xff },
121 	{ 0x16, 0x1f, 0xff, 0xff },
122 	{ 0x1f, 0xff, 0xff, 0xff }
123 };
124 
125 static const u8 dp_pre_emp_hbr_rbr[4][4] = {
126 	{ 0x00, 0x0d, 0x14, 0x1a },
127 	{ 0x00, 0x0e, 0x15, 0xff },
128 	{ 0x00, 0x0e, 0xff, 0xff },
129 	{ 0x03, 0xff, 0xff, 0xff }
130 };
131 
132 static const u8 dp_swing_hbr2_hbr3[4][4] = {
133 	{ 0x02, 0x12, 0x16, 0x1a },
134 	{ 0x09, 0x19, 0x1f, 0xff },
135 	{ 0x10, 0x1f, 0xff, 0xff },
136 	{ 0x1f, 0xff, 0xff, 0xff }
137 };
138 
139 static const u8 dp_pre_emp_hbr2_hbr3[4][4] = {
140 	{ 0x00, 0x0c, 0x15, 0x1b },
141 	{ 0x02, 0x0e, 0x16, 0xff },
142 	{ 0x02, 0x11, 0xff, 0xff },
143 	{ 0x04, 0xff, 0xff, 0xff }
144 };
145 
146 static const struct qcom_edp_swing_pre_emph_cfg dp_phy_swing_pre_emph_cfg = {
147 	.swing_hbr_rbr = &dp_swing_hbr_rbr,
148 	.swing_hbr3_hbr2 = &dp_swing_hbr2_hbr3,
149 	.pre_emphasis_hbr_rbr = &dp_pre_emp_hbr_rbr,
150 	.pre_emphasis_hbr3_hbr2 = &dp_pre_emp_hbr2_hbr3,
151 };
152 
153 static const u8 edp_swing_hbr_rbr[4][4] = {
154 	{ 0x07, 0x0f, 0x16, 0x1f },
155 	{ 0x0d, 0x16, 0x1e, 0xff },
156 	{ 0x11, 0x1b, 0xff, 0xff },
157 	{ 0x16, 0xff, 0xff, 0xff }
158 };
159 
160 static const u8 edp_pre_emp_hbr_rbr[4][4] = {
161 	{ 0x05, 0x12, 0x17, 0x1d },
162 	{ 0x05, 0x11, 0x18, 0xff },
163 	{ 0x06, 0x11, 0xff, 0xff },
164 	{ 0x00, 0xff, 0xff, 0xff }
165 };
166 
167 static const u8 edp_swing_hbr2_hbr3[4][4] = {
168 	{ 0x0b, 0x11, 0x17, 0x1c },
169 	{ 0x10, 0x19, 0x1f, 0xff },
170 	{ 0x19, 0x1f, 0xff, 0xff },
171 	{ 0x1f, 0xff, 0xff, 0xff }
172 };
173 
174 static const u8 edp_pre_emp_hbr2_hbr3[4][4] = {
175 	{ 0x08, 0x11, 0x17, 0x1b },
176 	{ 0x00, 0x0c, 0x13, 0xff },
177 	{ 0x05, 0x10, 0xff, 0xff },
178 	{ 0x00, 0xff, 0xff, 0xff }
179 };
180 
181 static const struct qcom_edp_swing_pre_emph_cfg edp_phy_swing_pre_emph_cfg = {
182 	.swing_hbr_rbr = &edp_swing_hbr_rbr,
183 	.swing_hbr3_hbr2 = &edp_swing_hbr2_hbr3,
184 	.pre_emphasis_hbr_rbr = &edp_pre_emp_hbr_rbr,
185 	.pre_emphasis_hbr3_hbr2 = &edp_pre_emp_hbr2_hbr3,
186 };
187 
188 static const u8 edp_phy_aux_cfg_v4[DP_AUX_CFG_SIZE] = {
189 	0x00, 0x13, 0x24, 0x00, 0x0a, 0x26, 0x0a, 0x03, 0x37, 0x03, 0x02, 0x02, 0x00,
190 };
191 
192 static const u8 edp_phy_vco_div_cfg_v4[4] = {
193 	0x01, 0x01, 0x02, 0x00,
194 };
195 
196 static const u8 edp_pre_emp_hbr_rbr_v5[4][4] = {
197 	{ 0x05, 0x11, 0x17, 0x1d },
198 	{ 0x05, 0x11, 0x18, 0xff },
199 	{ 0x06, 0x11, 0xff, 0xff },
200 	{ 0x00, 0xff, 0xff, 0xff }
201 };
202 
203 static const u8 edp_pre_emp_hbr2_hbr3_v5[4][4] = {
204 	{ 0x0c, 0x15, 0x19, 0x1e },
205 	{ 0x0b, 0x15, 0x19, 0xff },
206 	{ 0x0e, 0x14, 0xff, 0xff },
207 	{ 0x0d, 0xff, 0xff, 0xff }
208 };
209 
210 static const struct qcom_edp_swing_pre_emph_cfg edp_phy_swing_pre_emph_cfg_v5 = {
211 	.swing_hbr_rbr = &edp_swing_hbr_rbr,
212 	.swing_hbr3_hbr2 = &edp_swing_hbr2_hbr3,
213 	.pre_emphasis_hbr_rbr = &edp_pre_emp_hbr_rbr_v5,
214 	.pre_emphasis_hbr3_hbr2 = &edp_pre_emp_hbr2_hbr3_v5,
215 };
216 
217 static const u8 edp_phy_aux_cfg_v5[DP_AUX_CFG_SIZE] = {
218 	0x00, 0x13, 0xa4, 0x00, 0x0a, 0x26, 0x0a, 0x03, 0x37, 0x03, 0x02, 0x02, 0x00,
219 };
220 
221 static const u8 edp_phy_aux_cfg_v8[DP_AUX_CFG_SIZE] = {
222 	0x00, 0x00, 0xa0, 0x00, 0x0a, 0x26, 0x0a, 0x03, 0x37, 0x03, 0x02, 0x02, 0x04,
223 };
224 
225 static const u8 edp_phy_vco_div_cfg_v8[4] = {
226 	0x00, 0x00, 0x02, 0x01,
227 };
228 
229 static int qcom_edp_phy_init(struct phy *phy)
230 {
231 	struct qcom_edp *edp = phy_get_drvdata(phy);
232 	u8 aux_cfg[DP_AUX_CFG_SIZE];
233 	int ret;
234 
235 	ret = regulator_bulk_enable(ARRAY_SIZE(edp->supplies), edp->supplies);
236 	if (ret)
237 		return ret;
238 
239 	ret = clk_bulk_prepare_enable(edp->num_clks, edp->clks);
240 	if (ret)
241 		goto out_disable_supplies;
242 
243 	memcpy(aux_cfg, edp->cfg->aux_cfg, sizeof(aux_cfg));
244 
245 	ret = edp->cfg->ver_ops->com_clk_fwd_cfg(edp);
246 	if (ret)
247 		return ret;
248 
249 	writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
250 	       DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
251 	       edp->edp + DP_PHY_PD_CTL);
252 
253 	ret = edp->cfg->ver_ops->com_bias_en_clkbuflr(edp);
254 	if (ret)
255 		return ret;
256 
257 	writel(DP_PHY_PD_CTL_PSR_PWRDN, edp->edp + DP_PHY_PD_CTL);
258 	msleep(20);
259 
260 	writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
261 	       DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN |
262 	       DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
263 	       edp->edp + DP_PHY_PD_CTL);
264 
265 	/*
266 	 * TODO: Re-work the conditions around setting the cfg8 value
267 	 * when more information becomes available about why this is
268 	 * even needed.
269 	 */
270 	if (edp->cfg->swing_pre_emph_cfg && !edp->is_edp)
271 		aux_cfg[8] = 0xb7;
272 
273 	writel(0xfc, edp->edp + DP_PHY_MODE);
274 
275 	for (int i = 0; i < DP_AUX_CFG_SIZE; i++)
276 		writel(aux_cfg[i], edp->edp + DP_PHY_AUX_CFG(i));
277 
278 	writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK |
279 	       PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK |
280 	       PHY_AUX_REQ_ERR_MASK, edp->edp + DP_PHY_AUX_INTERRUPT_MASK);
281 
282 	msleep(20);
283 
284 	return 0;
285 
286 out_disable_supplies:
287 	regulator_bulk_disable(ARRAY_SIZE(edp->supplies), edp->supplies);
288 
289 	return ret;
290 }
291 
292 static int qcom_edp_set_voltages(struct qcom_edp *edp, const struct phy_configure_opts_dp *dp_opts)
293 {
294 	const struct qcom_edp_swing_pre_emph_cfg *cfg = edp->cfg->swing_pre_emph_cfg;
295 	unsigned int v_level = 0;
296 	unsigned int p_level = 0;
297 	u8 ldo_config;
298 	u8 swing;
299 	u8 emph;
300 	int i;
301 
302 	if (!cfg)
303 		return 0;
304 
305 	if (edp->is_edp)
306 		cfg = &edp_phy_swing_pre_emph_cfg;
307 
308 	for (i = 0; i < dp_opts->lanes; i++) {
309 		v_level = max(v_level, dp_opts->voltage[i]);
310 		p_level = max(p_level, dp_opts->pre[i]);
311 	}
312 
313 	if (dp_opts->link_rate <= 2700) {
314 		swing = (*cfg->swing_hbr_rbr)[v_level][p_level];
315 		emph = (*cfg->pre_emphasis_hbr_rbr)[v_level][p_level];
316 	} else {
317 		swing = (*cfg->swing_hbr3_hbr2)[v_level][p_level];
318 		emph = (*cfg->pre_emphasis_hbr3_hbr2)[v_level][p_level];
319 	}
320 
321 	if (swing == 0xff || emph == 0xff)
322 		return -EINVAL;
323 
324 	ldo_config = edp->is_edp ? 0x0 : 0x1;
325 
326 	writel(ldo_config, edp->tx0 + TXn_LDO_CONFIG);
327 	writel(swing, edp->tx0 + TXn_TX_DRV_LVL);
328 	writel(emph, edp->tx0 + TXn_TX_EMP_POST1_LVL);
329 
330 	writel(ldo_config, edp->tx1 + TXn_LDO_CONFIG);
331 	writel(swing, edp->tx1 + TXn_TX_DRV_LVL);
332 	writel(emph, edp->tx1 + TXn_TX_EMP_POST1_LVL);
333 
334 	return 0;
335 }
336 
337 static int qcom_edp_phy_configure(struct phy *phy, union phy_configure_opts *opts)
338 {
339 	const struct phy_configure_opts_dp *dp_opts = &opts->dp;
340 	struct qcom_edp *edp = phy_get_drvdata(phy);
341 	int ret = 0;
342 
343 	memcpy(&edp->dp_opts, dp_opts, sizeof(*dp_opts));
344 
345 	if (dp_opts->set_voltages)
346 		ret = qcom_edp_set_voltages(edp, dp_opts);
347 
348 	return ret;
349 }
350 
351 static int qcom_edp_configure_ssc(const struct qcom_edp *edp)
352 {
353 	return edp->cfg->ver_ops->com_configure_ssc(edp);
354 }
355 
356 static int qcom_edp_configure_pll(const struct qcom_edp *edp)
357 {
358 	return edp->cfg->ver_ops->com_configure_pll(edp);
359 }
360 
361 static int qcom_edp_set_vco_div(const struct qcom_edp *edp, unsigned long *pixel_freq)
362 {
363 	const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
364 	u32 vco_div;
365 
366 	switch (dp_opts->link_rate) {
367 	case 1620:
368 		vco_div = edp->cfg->vco_div_cfg[0];
369 		*pixel_freq = 1620000000UL / 2;
370 		break;
371 
372 	case 2700:
373 		vco_div = edp->cfg->vco_div_cfg[1];
374 		*pixel_freq = 2700000000UL / 2;
375 		break;
376 
377 	case 5400:
378 		vco_div = edp->cfg->vco_div_cfg[2];
379 		*pixel_freq = 5400000000UL / 4;
380 		break;
381 
382 	case 8100:
383 		vco_div = edp->cfg->vco_div_cfg[3];
384 		*pixel_freq = 8100000000UL / 6;
385 		break;
386 
387 	default:
388 		/* Other link rates aren't supported */
389 		return -EINVAL;
390 	}
391 
392 	writel(vco_div, edp->edp + DP_PHY_VCO_DIV);
393 
394 	return 0;
395 }
396 
397 static int qcom_edp_phy_power_on_v4(const struct qcom_edp *edp)
398 {
399 	u32 val;
400 
401 	writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
402 	       DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN |
403 	       DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
404 	       edp->edp + DP_PHY_PD_CTL);
405 	writel(0xfc, edp->edp + DP_PHY_MODE);
406 
407 	return readl_poll_timeout(edp->pll + QSERDES_V4_COM_CMN_STATUS,
408 				     val, val & BIT(7), 5, 200);
409 }
410 
411 static int qcom_edp_phy_com_resetsm_cntrl_v4(const struct qcom_edp *edp)
412 {
413 	u32 val;
414 
415 	writel(0x20, edp->pll + QSERDES_V4_COM_RESETSM_CNTRL);
416 
417 	return readl_poll_timeout(edp->pll + QSERDES_V4_COM_C_READY_STATUS,
418 				     val, val & BIT(0), 500, 10000);
419 }
420 
421 static int qcom_edp_com_clk_fwd_cfg_v4(const struct qcom_edp *edp)
422 {
423 	return 0;
424 }
425 
426 static int qcom_edp_com_bias_en_clkbuflr_v4(const struct qcom_edp *edp)
427 {
428 	/* Turn on BIAS current for PHY/PLL */
429 	writel(0x17, edp->pll + QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN);
430 
431 	return 0;
432 }
433 
434 static int qcom_edp_com_configure_ssc_v4(const struct qcom_edp *edp)
435 {
436 	const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
437 	u32 step1;
438 	u32 step2;
439 
440 	switch (dp_opts->link_rate) {
441 	case 1620:
442 	case 2700:
443 	case 8100:
444 		step1 = 0x45;
445 		step2 = 0x06;
446 		break;
447 
448 	case 5400:
449 		step1 = 0x5c;
450 		step2 = 0x08;
451 		break;
452 
453 	default:
454 		/* Other link rates aren't supported */
455 		return -EINVAL;
456 	}
457 
458 	writel(0x01, edp->pll + QSERDES_V4_COM_SSC_EN_CENTER);
459 	writel(0x00, edp->pll + QSERDES_V4_COM_SSC_ADJ_PER1);
460 	writel(0x36, edp->pll + QSERDES_V4_COM_SSC_PER1);
461 	writel(0x01, edp->pll + QSERDES_V4_COM_SSC_PER2);
462 	writel(step1, edp->pll + QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0);
463 	writel(step2, edp->pll + QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0);
464 
465 	return 0;
466 }
467 
468 static int qcom_edp_com_configure_pll_v4(const struct qcom_edp *edp)
469 {
470 	const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
471 	u32 div_frac_start2_mode0;
472 	u32 div_frac_start3_mode0;
473 	u32 dec_start_mode0;
474 	u32 lock_cmp1_mode0;
475 	u32 lock_cmp2_mode0;
476 	u32 hsclk_sel;
477 
478 	switch (dp_opts->link_rate) {
479 	case 1620:
480 		hsclk_sel = 0x5;
481 		dec_start_mode0 = 0x69;
482 		div_frac_start2_mode0 = 0x80;
483 		div_frac_start3_mode0 = 0x07;
484 		lock_cmp1_mode0 = 0x6f;
485 		lock_cmp2_mode0 = 0x08;
486 		break;
487 
488 	case 2700:
489 		hsclk_sel = 0x3;
490 		dec_start_mode0 = 0x69;
491 		div_frac_start2_mode0 = 0x80;
492 		div_frac_start3_mode0 = 0x07;
493 		lock_cmp1_mode0 = 0x0f;
494 		lock_cmp2_mode0 = 0x0e;
495 		break;
496 
497 	case 5400:
498 		hsclk_sel = 0x1;
499 		dec_start_mode0 = 0x8c;
500 		div_frac_start2_mode0 = 0x00;
501 		div_frac_start3_mode0 = 0x0a;
502 		lock_cmp1_mode0 = 0x1f;
503 		lock_cmp2_mode0 = 0x1c;
504 		break;
505 
506 	case 8100:
507 		hsclk_sel = 0x0;
508 		dec_start_mode0 = 0x69;
509 		div_frac_start2_mode0 = 0x80;
510 		div_frac_start3_mode0 = 0x07;
511 		lock_cmp1_mode0 = 0x2f;
512 		lock_cmp2_mode0 = 0x2a;
513 		break;
514 
515 	default:
516 		/* Other link rates aren't supported */
517 		return -EINVAL;
518 	}
519 
520 	writel(0x01, edp->pll + QSERDES_V4_COM_SVS_MODE_CLK_SEL);
521 	writel(0x0b, edp->pll + QSERDES_V4_COM_SYSCLK_EN_SEL);
522 	writel(0x02, edp->pll + QSERDES_V4_COM_SYS_CLK_CTRL);
523 	writel(0x0c, edp->pll + QSERDES_V4_COM_CLK_ENABLE1);
524 	writel(0x06, edp->pll + QSERDES_V4_COM_SYSCLK_BUF_ENABLE);
525 	writel(0x30, edp->pll + QSERDES_V4_COM_CLK_SELECT);
526 	writel(hsclk_sel, edp->pll + QSERDES_V4_COM_HSCLK_SEL);
527 	writel(0x0f, edp->pll + QSERDES_V4_COM_PLL_IVCO);
528 	writel(0x08, edp->pll + QSERDES_V4_COM_LOCK_CMP_EN);
529 	writel(0x36, edp->pll + QSERDES_V4_COM_PLL_CCTRL_MODE0);
530 	writel(0x16, edp->pll + QSERDES_V4_COM_PLL_RCTRL_MODE0);
531 	writel(0x06, edp->pll + QSERDES_V4_COM_CP_CTRL_MODE0);
532 	writel(dec_start_mode0, edp->pll + QSERDES_V4_COM_DEC_START_MODE0);
533 	writel(0x00, edp->pll + QSERDES_V4_COM_DIV_FRAC_START1_MODE0);
534 	writel(div_frac_start2_mode0, edp->pll + QSERDES_V4_COM_DIV_FRAC_START2_MODE0);
535 	writel(div_frac_start3_mode0, edp->pll + QSERDES_V4_COM_DIV_FRAC_START3_MODE0);
536 	writel(0x02, edp->pll + QSERDES_V4_COM_CMN_CONFIG);
537 	writel(0x3f, edp->pll + QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0);
538 	writel(0x00, edp->pll + QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0);
539 	writel(0x00, edp->pll + QSERDES_V4_COM_VCO_TUNE_MAP);
540 	writel(lock_cmp1_mode0, edp->pll + QSERDES_V4_COM_LOCK_CMP1_MODE0);
541 	writel(lock_cmp2_mode0, edp->pll + QSERDES_V4_COM_LOCK_CMP2_MODE0);
542 
543 	writel(0x0a, edp->pll + QSERDES_V4_COM_BG_TIMER);
544 	writel(0x14, edp->pll + QSERDES_V4_COM_CORECLK_DIV_MODE0);
545 	writel(0x00, edp->pll + QSERDES_V4_COM_VCO_TUNE_CTRL);
546 	writel(0x17, edp->pll + QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN);
547 	writel(0x0f, edp->pll + QSERDES_V4_COM_CORE_CLK_EN);
548 	writel(0xa0, edp->pll + QSERDES_V4_COM_VCO_TUNE1_MODE0);
549 	writel(0x03, edp->pll + QSERDES_V4_COM_VCO_TUNE2_MODE0);
550 
551 	return 0;
552 }
553 
554 static const struct phy_ver_ops qcom_edp_phy_ops_v4 = {
555 	.com_power_on		= qcom_edp_phy_power_on_v4,
556 	.com_resetsm_cntrl	= qcom_edp_phy_com_resetsm_cntrl_v4,
557 	.com_bias_en_clkbuflr	= qcom_edp_com_bias_en_clkbuflr_v4,
558 	.com_clk_fwd_cfg	= qcom_edp_com_clk_fwd_cfg_v4,
559 	.com_configure_pll	= qcom_edp_com_configure_pll_v4,
560 	.com_configure_ssc	= qcom_edp_com_configure_ssc_v4,
561 };
562 
563 static const struct qcom_edp_phy_cfg sa8775p_dp_phy_cfg = {
564 	.is_edp = false,
565 	.aux_cfg = edp_phy_aux_cfg_v5,
566 	.vco_div_cfg = edp_phy_vco_div_cfg_v4,
567 	.swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg_v5,
568 	.ver_ops = &qcom_edp_phy_ops_v4,
569 };
570 
571 static const struct qcom_edp_phy_cfg sc7280_dp_phy_cfg = {
572 	.aux_cfg = edp_phy_aux_cfg_v4,
573 	.vco_div_cfg = edp_phy_vco_div_cfg_v4,
574 	.ver_ops = &qcom_edp_phy_ops_v4,
575 };
576 
577 static const struct qcom_edp_phy_cfg sc8280xp_dp_phy_cfg = {
578 	.aux_cfg = edp_phy_aux_cfg_v4,
579 	.vco_div_cfg = edp_phy_vco_div_cfg_v4,
580 	.swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
581 	.ver_ops = &qcom_edp_phy_ops_v4,
582 };
583 
584 static const struct qcom_edp_phy_cfg sc8280xp_edp_phy_cfg = {
585 	.is_edp = true,
586 	.aux_cfg = edp_phy_aux_cfg_v4,
587 	.vco_div_cfg = edp_phy_vco_div_cfg_v4,
588 	.swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg,
589 	.ver_ops = &qcom_edp_phy_ops_v4,
590 };
591 
592 static int qcom_edp_phy_power_on_v6(const struct qcom_edp *edp)
593 {
594 	u32 val;
595 
596 	writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
597 	       DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN |
598 	       DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
599 	       edp->edp + DP_PHY_PD_CTL);
600 	writel(0xfc, edp->edp + DP_PHY_MODE);
601 
602 	return readl_poll_timeout(edp->pll + QSERDES_V6_COM_CMN_STATUS,
603 				     val, val & BIT(7), 5, 200);
604 }
605 
606 static int qcom_edp_phy_com_resetsm_cntrl_v6(const struct qcom_edp *edp)
607 {
608 	u32 val;
609 
610 	writel(0x20, edp->pll + QSERDES_V6_COM_RESETSM_CNTRL);
611 
612 	return readl_poll_timeout(edp->pll + QSERDES_V6_COM_C_READY_STATUS,
613 				     val, val & BIT(0), 500, 10000);
614 }
615 
616 static int qcom_edp_com_bias_en_clkbuflr_v6(const struct qcom_edp *edp)
617 {
618 	/* Turn on BIAS current for PHY/PLL */
619 	writel(0x1f, edp->pll + QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN);
620 
621 	return 0;
622 }
623 
624 static int qcom_edp_com_configure_ssc_v6(const struct qcom_edp *edp)
625 {
626 	const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
627 	u32 step1;
628 	u32 step2;
629 
630 	switch (dp_opts->link_rate) {
631 	case 1620:
632 	case 2700:
633 	case 8100:
634 		step1 = 0x92;
635 		step2 = 0x01;
636 		break;
637 
638 	case 5400:
639 		step1 = 0x18;
640 		step2 = 0x02;
641 		break;
642 
643 	default:
644 		/* Other link rates aren't supported */
645 		return -EINVAL;
646 	}
647 
648 	writel(0x01, edp->pll + QSERDES_V6_COM_SSC_EN_CENTER);
649 	writel(0x00, edp->pll + QSERDES_V6_COM_SSC_ADJ_PER1);
650 	writel(0x36, edp->pll + QSERDES_V6_COM_SSC_PER1);
651 	writel(0x01, edp->pll + QSERDES_V6_COM_SSC_PER2);
652 	writel(step1, edp->pll + QSERDES_V6_COM_SSC_STEP_SIZE1_MODE0);
653 	writel(step2, edp->pll + QSERDES_V6_COM_SSC_STEP_SIZE2_MODE0);
654 
655 	return 0;
656 }
657 
658 static int qcom_edp_com_configure_pll_v6(const struct qcom_edp *edp)
659 {
660 	const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
661 	u32 div_frac_start2_mode0;
662 	u32 div_frac_start3_mode0;
663 	u32 dec_start_mode0;
664 	u32 lock_cmp1_mode0;
665 	u32 lock_cmp2_mode0;
666 	u32 code1_mode0;
667 	u32 code2_mode0;
668 	u32 hsclk_sel;
669 
670 	switch (dp_opts->link_rate) {
671 	case 1620:
672 		hsclk_sel = 0x5;
673 		dec_start_mode0 = 0x34;
674 		div_frac_start2_mode0 = 0xc0;
675 		div_frac_start3_mode0 = 0x0b;
676 		lock_cmp1_mode0 = 0x37;
677 		lock_cmp2_mode0 = 0x04;
678 		code1_mode0 = 0x71;
679 		code2_mode0 = 0x0c;
680 		break;
681 
682 	case 2700:
683 		hsclk_sel = 0x3;
684 		dec_start_mode0 = 0x34;
685 		div_frac_start2_mode0 = 0xc0;
686 		div_frac_start3_mode0 = 0x0b;
687 		lock_cmp1_mode0 = 0x07;
688 		lock_cmp2_mode0 = 0x07;
689 		code1_mode0 = 0x71;
690 		code2_mode0 = 0x0c;
691 		break;
692 
693 	case 5400:
694 		hsclk_sel = 0x1;
695 		dec_start_mode0 = 0x46;
696 		div_frac_start2_mode0 = 0x00;
697 		div_frac_start3_mode0 = 0x05;
698 		lock_cmp1_mode0 = 0x0f;
699 		lock_cmp2_mode0 = 0x0e;
700 		code1_mode0 = 0x97;
701 		code2_mode0 = 0x10;
702 		break;
703 
704 	case 8100:
705 		hsclk_sel = 0x0;
706 		dec_start_mode0 = 0x34;
707 		div_frac_start2_mode0 = 0xc0;
708 		div_frac_start3_mode0 = 0x0b;
709 		lock_cmp1_mode0 = 0x17;
710 		lock_cmp2_mode0 = 0x15;
711 		code1_mode0 = 0x71;
712 		code2_mode0 = 0x0c;
713 		break;
714 
715 	default:
716 		/* Other link rates aren't supported */
717 		return -EINVAL;
718 	}
719 
720 	writel(0x01, edp->pll + QSERDES_V6_COM_SVS_MODE_CLK_SEL);
721 	writel(0x0b, edp->pll + QSERDES_V6_COM_SYSCLK_EN_SEL);
722 	writel(0x02, edp->pll + QSERDES_V6_COM_SYS_CLK_CTRL);
723 	writel(0x0c, edp->pll + QSERDES_V6_COM_CLK_ENABLE1);
724 	writel(0x06, edp->pll + QSERDES_V6_COM_SYSCLK_BUF_ENABLE);
725 	writel(0x30, edp->pll + QSERDES_V6_COM_CLK_SELECT);
726 	writel(hsclk_sel, edp->pll + QSERDES_V6_COM_HSCLK_SEL_1);
727 	writel(0x07, edp->pll + QSERDES_V6_COM_PLL_IVCO);
728 	writel(0x08, edp->pll + QSERDES_V6_COM_LOCK_CMP_EN);
729 	writel(0x36, edp->pll + QSERDES_V6_COM_PLL_CCTRL_MODE0);
730 	writel(0x16, edp->pll + QSERDES_V6_COM_PLL_RCTRL_MODE0);
731 	writel(0x06, edp->pll + QSERDES_V6_COM_CP_CTRL_MODE0);
732 	writel(dec_start_mode0, edp->pll + QSERDES_V6_COM_DEC_START_MODE0);
733 	writel(0x00, edp->pll + QSERDES_V6_COM_DIV_FRAC_START1_MODE0);
734 	writel(div_frac_start2_mode0, edp->pll + QSERDES_V6_COM_DIV_FRAC_START2_MODE0);
735 	writel(div_frac_start3_mode0, edp->pll + QSERDES_V6_COM_DIV_FRAC_START3_MODE0);
736 	writel(0x12, edp->pll + QSERDES_V6_COM_CMN_CONFIG_1);
737 	writel(0x3f, edp->pll + QSERDES_V6_COM_INTEGLOOP_GAIN0_MODE0);
738 	writel(0x00, edp->pll + QSERDES_V6_COM_INTEGLOOP_GAIN1_MODE0);
739 	writel(0x00, edp->pll + QSERDES_V6_COM_VCO_TUNE_MAP);
740 	writel(lock_cmp1_mode0, edp->pll + QSERDES_V6_COM_LOCK_CMP1_MODE0);
741 	writel(lock_cmp2_mode0, edp->pll + QSERDES_V6_COM_LOCK_CMP2_MODE0);
742 
743 	writel(0x0a, edp->pll + QSERDES_V6_COM_BG_TIMER);
744 	writel(0x14, edp->pll + QSERDES_V6_COM_PLL_CORE_CLK_DIV_MODE0);
745 	writel(0x00, edp->pll + QSERDES_V6_COM_VCO_TUNE_CTRL);
746 	writel(0x1f, edp->pll + QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN);
747 	writel(0x0f, edp->pll + QSERDES_V6_COM_CORE_CLK_EN);
748 	writel(0xa0, edp->pll + QSERDES_V6_COM_VCO_TUNE1_MODE0);
749 	writel(0x03, edp->pll + QSERDES_V6_COM_VCO_TUNE2_MODE0);
750 
751 	writel(code1_mode0, edp->pll + QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE1_MODE0);
752 	writel(code2_mode0, edp->pll + QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE2_MODE0);
753 
754 	return 0;
755 }
756 
757 static const struct phy_ver_ops qcom_edp_phy_ops_v6 = {
758 	.com_power_on		= qcom_edp_phy_power_on_v6,
759 	.com_resetsm_cntrl	= qcom_edp_phy_com_resetsm_cntrl_v6,
760 	.com_bias_en_clkbuflr	= qcom_edp_com_bias_en_clkbuflr_v6,
761 	.com_clk_fwd_cfg	= qcom_edp_com_clk_fwd_cfg_v4,
762 	.com_configure_pll	= qcom_edp_com_configure_pll_v6,
763 	.com_configure_ssc	= qcom_edp_com_configure_ssc_v6,
764 };
765 
766 static struct qcom_edp_phy_cfg x1e80100_phy_cfg = {
767 	.aux_cfg = edp_phy_aux_cfg_v4,
768 	.vco_div_cfg = edp_phy_vco_div_cfg_v4,
769 	.swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
770 	.ver_ops = &qcom_edp_phy_ops_v6,
771 };
772 
773 static int qcom_edp_com_configure_ssc_v8(const struct qcom_edp *edp)
774 {
775 	const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
776 	u32 step1;
777 	u32 step2;
778 
779 	switch (dp_opts->link_rate) {
780 	case 1620:
781 	case 2700:
782 	case 8100:
783 		step1 = 0x5b;
784 		step2 = 0x02;
785 		break;
786 
787 	case 5400:
788 		step1 = 0x5b;
789 		step2 = 0x02;
790 		break;
791 
792 	default:
793 		/* Other link rates aren't supported */
794 		return -EINVAL;
795 	}
796 
797 	writel(0x01, edp->pll + DP_QSERDES_V8_COM_SSC_EN_CENTER);
798 	writel(0x00, edp->pll + DP_QSERDES_V8_COM_SSC_ADJ_PER1);
799 	writel(0x6b, edp->pll + DP_QSERDES_V8_COM_SSC_PER1);
800 	writel(0x02, edp->pll + DP_QSERDES_V8_COM_SSC_PER2);
801 	writel(step1, edp->pll + DP_QSERDES_V8_COM_SSC_STEP_SIZE1_MODE0);
802 	writel(step2, edp->pll + DP_QSERDES_V8_COM_SSC_STEP_SIZE2_MODE0);
803 
804 	return 0;
805 }
806 
807 static int qcom_edp_com_configure_pll_v8(const struct qcom_edp *edp)
808 {
809 	const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
810 	u32 div_frac_start2_mode0;
811 	u32 div_frac_start3_mode0;
812 	u32 dec_start_mode0;
813 	u32 lock_cmp1_mode0;
814 	u32 lock_cmp2_mode0;
815 	u32 code1_mode0;
816 	u32 code2_mode0;
817 	u32 hsclk_sel;
818 
819 	switch (dp_opts->link_rate) {
820 	case 1620:
821 		hsclk_sel = 0x5;
822 		dec_start_mode0 = 0x34;
823 		div_frac_start2_mode0 = 0xc0;
824 		div_frac_start3_mode0 = 0x0b;
825 		lock_cmp1_mode0 = 0x37;
826 		lock_cmp2_mode0 = 0x04;
827 		code1_mode0 = 0x71;
828 		code2_mode0 = 0x0c;
829 		break;
830 
831 	case 2700:
832 		hsclk_sel = 0x3;
833 		dec_start_mode0 = 0x34;
834 		div_frac_start2_mode0 = 0xc0;
835 		div_frac_start3_mode0 = 0x0b;
836 		lock_cmp1_mode0 = 0x07;
837 		lock_cmp2_mode0 = 0x07;
838 		code1_mode0 = 0x71;
839 		code2_mode0 = 0x0c;
840 		break;
841 
842 	case 5400:
843 	case 8100:
844 		hsclk_sel = 0x2;
845 		dec_start_mode0 = 0x4f;
846 		div_frac_start2_mode0 = 0xa0;
847 		div_frac_start3_mode0 = 0x01;
848 		lock_cmp1_mode0 = 0x18;
849 		lock_cmp2_mode0 = 0x15;
850 		code1_mode0 = 0x14;
851 		code2_mode0 = 0x25;
852 		break;
853 
854 	default:
855 		/* Other link rates aren't supported */
856 		return -EINVAL;
857 	}
858 
859 	writel(0x01, edp->pll + DP_QSERDES_V8_COM_SVS_MODE_CLK_SEL);
860 	writel(0x3b, edp->pll + DP_QSERDES_V8_COM_SYSCLK_EN_SEL);
861 	writel(0x02, edp->pll + DP_QSERDES_V8_COM_SYS_CLK_CTRL);
862 	writel(0x0c, edp->pll + DP_QSERDES_V8_COM_CLK_ENABLE1);
863 	writel(0x06, edp->pll + DP_QSERDES_V8_COM_SYSCLK_BUF_ENABLE);
864 	writel(0x30, edp->pll + DP_QSERDES_V8_COM_CLK_SELECT);
865 	writel(hsclk_sel, edp->pll + DP_QSERDES_V8_COM_HSCLK_SEL_1);
866 	writel(0x07, edp->pll + DP_QSERDES_V8_COM_PLL_IVCO);
867 	writel(0x00, edp->pll + DP_QSERDES_V8_COM_LOCK_CMP_EN);
868 	writel(0x36, edp->pll + DP_QSERDES_V8_COM_PLL_CCTRL_MODE0);
869 	writel(0x16, edp->pll + DP_QSERDES_V8_COM_PLL_RCTRL_MODE0);
870 	writel(0x06, edp->pll + DP_QSERDES_V8_COM_CP_CTRL_MODE0);
871 	writel(dec_start_mode0, edp->pll + DP_QSERDES_V8_COM_DEC_START_MODE0);
872 	writel(0x00, edp->pll + DP_QSERDES_V8_COM_DIV_FRAC_START1_MODE0);
873 	writel(div_frac_start2_mode0, edp->pll + DP_QSERDES_V8_COM_DIV_FRAC_START2_MODE0);
874 	writel(div_frac_start3_mode0, edp->pll + DP_QSERDES_V8_COM_DIV_FRAC_START3_MODE0);
875 	writel(0x96, edp->pll + DP_QSERDES_V8_COM_CMN_CONFIG_1);
876 	writel(0x3f, edp->pll + DP_QSERDES_V8_COM_INTEGLOOP_GAIN0_MODE0);
877 	writel(0x00, edp->pll + DP_QSERDES_V8_COM_INTEGLOOP_GAIN1_MODE0);
878 	writel(0x00, edp->pll + DP_QSERDES_V8_COM_VCO_TUNE_MAP);
879 	writel(lock_cmp1_mode0, edp->pll + DP_QSERDES_V8_COM_LOCK_CMP1_MODE0);
880 	writel(lock_cmp2_mode0, edp->pll + DP_QSERDES_V8_COM_LOCK_CMP2_MODE0);
881 
882 	writel(0x0a, edp->pll + DP_QSERDES_V8_COM_BG_TIMER);
883 	writel(0x0a, edp->pll + DP_QSERDES_V8_COM_CORECLK_DIV_MODE0);
884 	writel(0x00, edp->pll + DP_QSERDES_V8_COM_VCO_TUNE_CTRL);
885 	writel(0x1f, edp->pll + DP_QSERDES_V8_COM_BIAS_EN_CLKBUFLR_EN);
886 	writel(0x00, edp->pll + DP_QSERDES_V8_COM_CORE_CLK_EN);
887 	writel(0xa0, edp->pll + DP_QSERDES_V8_COM_VCO_TUNE1_MODE0);
888 	writel(0x01, edp->pll + DP_QSERDES_V8_COM_VCO_TUNE2_MODE0);
889 
890 	writel(code1_mode0, edp->pll + DP_QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE1_MODE0);
891 	writel(code2_mode0, edp->pll + DP_QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE2_MODE0);
892 
893 	return 0;
894 }
895 
896 
897 static int qcom_edp_phy_com_resetsm_cntrl_v8(const struct qcom_edp *edp)
898 {
899 	u32 val;
900 
901 	writel(0x20, edp->pll + DP_QSERDES_V8_COM_RESETSM_CNTRL);
902 
903 	return readl_poll_timeout(edp->pll + DP_QSERDES_V8_COM_C_READY_STATUS,
904 				     val, val & BIT(0), 500, 10000);
905 }
906 
907 static int qcom_edp_com_clk_fwd_cfg_v8(const struct qcom_edp *edp)
908 {
909 	writel(0x3f, edp->pll + DP_QSERDES_V8_COM_CLK_FWD_CONFIG_1);
910 
911 	return 0;
912 }
913 
914 static int qcom_edp_com_bias_en_clkbuflr_v8(const struct qcom_edp *edp)
915 {
916 	/* Turn on BIAS current for PHY/PLL */
917 	writel(0x1f, edp->pll + DP_QSERDES_V8_COM_BIAS_EN_CLKBUFLR_EN);
918 
919 	return 0;
920 }
921 
922 static int qcom_edp_phy_power_on_v8(const struct qcom_edp *edp)
923 {
924 	u32 val;
925 
926 	writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
927 	       DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN |
928 	       DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
929 	       edp->edp + DP_PHY_PD_CTL);
930 	writel(0xfc, edp->edp + DP_PHY_MODE);
931 
932 	return readl_poll_timeout(edp->pll + DP_QSERDES_V8_COM_CMN_STATUS,
933 				     val, val & BIT(7), 5, 200);
934 }
935 
936 static const struct phy_ver_ops qcom_edp_phy_ops_v8 = {
937 	.com_power_on		= qcom_edp_phy_power_on_v8,
938 	.com_resetsm_cntrl	= qcom_edp_phy_com_resetsm_cntrl_v8,
939 	.com_bias_en_clkbuflr	= qcom_edp_com_bias_en_clkbuflr_v8,
940 	.com_clk_fwd_cfg	= qcom_edp_com_clk_fwd_cfg_v8,
941 	.com_configure_pll	= qcom_edp_com_configure_pll_v8,
942 	.com_configure_ssc	= qcom_edp_com_configure_ssc_v8,
943 };
944 
945 static struct qcom_edp_phy_cfg glymur_phy_cfg = {
946 	.aux_cfg = edp_phy_aux_cfg_v8,
947 	.vco_div_cfg = edp_phy_vco_div_cfg_v8,
948 	.swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg_v5,
949 	.ver_ops = &qcom_edp_phy_ops_v8,
950 };
951 
952 static int qcom_edp_phy_power_on(struct phy *phy)
953 {
954 	const struct qcom_edp *edp = phy_get_drvdata(phy);
955 	u32 bias0_en, drvr0_en, bias1_en, drvr1_en;
956 	unsigned long pixel_freq;
957 	u8 ldo_config = 0x0;
958 	int ret;
959 	u32 val;
960 	u8 cfg1;
961 
962 	ret = edp->cfg->ver_ops->com_power_on(edp);
963 	if (ret)
964 		return ret;
965 
966 	if (edp->cfg->swing_pre_emph_cfg && !edp->is_edp)
967 		ldo_config = 0x1;
968 
969 	writel(ldo_config, edp->tx0 + TXn_LDO_CONFIG);
970 	writel(ldo_config, edp->tx1 + TXn_LDO_CONFIG);
971 	writel(0x00, edp->tx0 + TXn_LANE_MODE_1);
972 	writel(0x00, edp->tx1 + TXn_LANE_MODE_1);
973 
974 	if (edp->dp_opts.ssc) {
975 		ret = qcom_edp_configure_ssc(edp);
976 		if (ret)
977 			return ret;
978 	}
979 
980 	ret = qcom_edp_configure_pll(edp);
981 	if (ret)
982 		return ret;
983 
984 	/* TX Lane configuration */
985 	writel(0x05, edp->edp + DP_PHY_TX0_TX1_LANE_CTL);
986 	writel(0x05, edp->edp + DP_PHY_TX2_TX3_LANE_CTL);
987 
988 	/* TX-0 register configuration */
989 	writel(0x03, edp->tx0 + TXn_TRANSCEIVER_BIAS_EN);
990 	writel(0x0f, edp->tx0 + TXn_CLKBUF_ENABLE);
991 	writel(0x03, edp->tx0 + TXn_RESET_TSYNC_EN);
992 	writel(0x01, edp->tx0 + TXn_TRAN_DRVR_EMP_EN);
993 	writel(0x04, edp->tx0 + TXn_TX_BAND);
994 
995 	/* TX-1 register configuration */
996 	writel(0x03, edp->tx1 + TXn_TRANSCEIVER_BIAS_EN);
997 	writel(0x0f, edp->tx1 + TXn_CLKBUF_ENABLE);
998 	writel(0x03, edp->tx1 + TXn_RESET_TSYNC_EN);
999 	writel(0x01, edp->tx1 + TXn_TRAN_DRVR_EMP_EN);
1000 	writel(0x04, edp->tx1 + TXn_TX_BAND);
1001 
1002 	ret = qcom_edp_set_vco_div(edp, &pixel_freq);
1003 	if (ret)
1004 		return ret;
1005 
1006 	writel(0x01, edp->edp + DP_PHY_CFG);
1007 	writel(0x05, edp->edp + DP_PHY_CFG);
1008 	writel(0x01, edp->edp + DP_PHY_CFG);
1009 	writel(0x09, edp->edp + DP_PHY_CFG);
1010 
1011 	ret = edp->cfg->ver_ops->com_resetsm_cntrl(edp);
1012 	if (ret)
1013 		return ret;
1014 
1015 	writel(0x19, edp->edp + DP_PHY_CFG);
1016 	writel(0x1f, edp->tx0 + TXn_HIGHZ_DRVR_EN);
1017 	writel(0x04, edp->tx0 + TXn_HIGHZ_DRVR_EN);
1018 	writel(0x00, edp->tx0 + TXn_TX_POL_INV);
1019 	writel(0x1f, edp->tx1 + TXn_HIGHZ_DRVR_EN);
1020 	writel(0x04, edp->tx1 + TXn_HIGHZ_DRVR_EN);
1021 	writel(0x00, edp->tx1 + TXn_TX_POL_INV);
1022 	writel(0x10, edp->tx0 + TXn_TX_DRV_LVL_OFFSET);
1023 	writel(0x10, edp->tx1 + TXn_TX_DRV_LVL_OFFSET);
1024 	writel(0x11, edp->tx0 + TXn_RES_CODE_LANE_OFFSET_TX0);
1025 	writel(0x11, edp->tx0 + TXn_RES_CODE_LANE_OFFSET_TX1);
1026 	writel(0x11, edp->tx1 + TXn_RES_CODE_LANE_OFFSET_TX0);
1027 	writel(0x11, edp->tx1 + TXn_RES_CODE_LANE_OFFSET_TX1);
1028 
1029 	writel(0x10, edp->tx0 + TXn_TX_EMP_POST1_LVL);
1030 	writel(0x10, edp->tx1 + TXn_TX_EMP_POST1_LVL);
1031 	writel(0x1f, edp->tx0 + TXn_TX_DRV_LVL);
1032 	writel(0x1f, edp->tx1 + TXn_TX_DRV_LVL);
1033 
1034 	if (edp->dp_opts.lanes == 1) {
1035 		bias0_en = 0x01;
1036 		bias1_en = 0x00;
1037 		drvr0_en = 0x06;
1038 		drvr1_en = 0x07;
1039 		cfg1 = 0x1;
1040 	} else if (edp->dp_opts.lanes == 2) {
1041 		bias0_en = 0x03;
1042 		bias1_en = 0x00;
1043 		drvr0_en = 0x04;
1044 		drvr1_en = 0x07;
1045 		cfg1 = 0x3;
1046 	} else {
1047 		bias0_en = 0x03;
1048 		bias1_en = 0x03;
1049 		drvr0_en = 0x04;
1050 		drvr1_en = 0x04;
1051 		cfg1 = 0xf;
1052 	}
1053 
1054 	writel(drvr0_en, edp->tx0 + TXn_HIGHZ_DRVR_EN);
1055 	writel(bias0_en, edp->tx0 + TXn_TRANSCEIVER_BIAS_EN);
1056 	writel(drvr1_en, edp->tx1 + TXn_HIGHZ_DRVR_EN);
1057 	writel(bias1_en, edp->tx1 + TXn_TRANSCEIVER_BIAS_EN);
1058 	writel(cfg1, edp->edp + DP_PHY_CFG_1);
1059 
1060 	writel(0x18, edp->edp + DP_PHY_CFG);
1061 	usleep_range(100, 1000);
1062 
1063 	writel(0x19, edp->edp + DP_PHY_CFG);
1064 
1065 	ret = readl_poll_timeout(edp->edp + DP_PHY_STATUS,
1066 				 val, val & BIT(1), 500, 10000);
1067 	if (ret)
1068 		return ret;
1069 
1070 	clk_set_rate(edp->dp_link_hw.clk, edp->dp_opts.link_rate * 100000);
1071 	clk_set_rate(edp->dp_pixel_hw.clk, pixel_freq);
1072 
1073 	return 0;
1074 }
1075 
1076 static int qcom_edp_phy_power_off(struct phy *phy)
1077 {
1078 	const struct qcom_edp *edp = phy_get_drvdata(phy);
1079 
1080 	writel(DP_PHY_PD_CTL_PSR_PWRDN, edp->edp + DP_PHY_PD_CTL);
1081 
1082 	return 0;
1083 }
1084 
1085 static int qcom_edp_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
1086 {
1087 	struct qcom_edp *edp = phy_get_drvdata(phy);
1088 
1089 	if (mode != PHY_MODE_DP)
1090 		return -EINVAL;
1091 
1092 	edp->is_edp = submode == PHY_SUBMODE_EDP;
1093 
1094 	return 0;
1095 }
1096 
1097 static int qcom_edp_phy_exit(struct phy *phy)
1098 {
1099 	struct qcom_edp *edp = phy_get_drvdata(phy);
1100 
1101 	clk_bulk_disable_unprepare(edp->num_clks, edp->clks);
1102 	regulator_bulk_disable(ARRAY_SIZE(edp->supplies), edp->supplies);
1103 
1104 	return 0;
1105 }
1106 
1107 static const struct phy_ops qcom_edp_ops = {
1108 	.init		= qcom_edp_phy_init,
1109 	.configure	= qcom_edp_phy_configure,
1110 	.power_on	= qcom_edp_phy_power_on,
1111 	.power_off	= qcom_edp_phy_power_off,
1112 	.set_mode	= qcom_edp_phy_set_mode,
1113 	.exit		= qcom_edp_phy_exit,
1114 	.owner		= THIS_MODULE,
1115 };
1116 
1117 /*
1118  * Embedded Display Port PLL driver block diagram for branch clocks
1119  *
1120  *              +------------------------------+
1121  *              |        EDP_VCO_CLK           |
1122  *              |                              |
1123  *              |    +-------------------+     |
1124  *              |    |  (EDP PLL/VCO)    |     |
1125  *              |    +---------+---------+     |
1126  *              |              v               |
1127  *              |   +----------+-----------+   |
1128  *              |   | hsclk_divsel_clk_src |   |
1129  *              |   +----------+-----------+   |
1130  *              +------------------------------+
1131  *                              |
1132  *          +---------<---------v------------>----------+
1133  *          |                                           |
1134  * +--------v----------------+                          |
1135  * |   edp_phy_pll_link_clk  |                          |
1136  * |     link_clk            |                          |
1137  * +--------+----------------+                          |
1138  *          |                                           |
1139  *          |                                           |
1140  *          v                                           v
1141  * Input to DISPCC block                                |
1142  * for link clk, crypto clk                             |
1143  * and interface clock                                  |
1144  *                                                      |
1145  *                                                      |
1146  *      +--------<------------+-----------------+---<---+
1147  *      |                     |                 |
1148  * +----v---------+  +--------v-----+  +--------v------+
1149  * | vco_divided  |  | vco_divided  |  | vco_divided   |
1150  * |    _clk_src  |  |    _clk_src  |  |    _clk_src   |
1151  * |              |  |              |  |               |
1152  * |divsel_six    |  |  divsel_two  |  |  divsel_four  |
1153  * +-------+------+  +-----+--------+  +--------+------+
1154  *         |                 |                  |
1155  *         v---->----------v-------------<------v
1156  *                         |
1157  *              +----------+-----------------+
1158  *              |   edp_phy_pll_vco_div_clk  |
1159  *              +---------+------------------+
1160  *                        |
1161  *                        v
1162  *              Input to DISPCC block
1163  *              for EDP pixel clock
1164  *
1165  */
1166 static int qcom_edp_dp_pixel_clk_determine_rate(struct clk_hw *hw,
1167 						struct clk_rate_request *req)
1168 {
1169 	switch (req->rate) {
1170 	case 1620000000UL / 2:
1171 	case 2700000000UL / 2:
1172 	/* 5.4 and 8.1 GHz are same link rate as 2.7GHz, i.e. div 4 and div 6 */
1173 		return 0;
1174 
1175 	default:
1176 		return -EINVAL;
1177 	}
1178 }
1179 
1180 static unsigned long
1181 qcom_edp_dp_pixel_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
1182 {
1183 	const struct qcom_edp *edp = container_of(hw, struct qcom_edp, dp_pixel_hw);
1184 	const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
1185 
1186 	switch (dp_opts->link_rate) {
1187 	case 1620:
1188 		return 1620000000UL / 2;
1189 	case 2700:
1190 		return 2700000000UL / 2;
1191 	case 5400:
1192 		return 5400000000UL / 4;
1193 	case 8100:
1194 		return 8100000000UL / 6;
1195 	default:
1196 		return 0;
1197 	}
1198 }
1199 
1200 static const struct clk_ops qcom_edp_dp_pixel_clk_ops = {
1201 	.determine_rate = qcom_edp_dp_pixel_clk_determine_rate,
1202 	.recalc_rate = qcom_edp_dp_pixel_clk_recalc_rate,
1203 };
1204 
1205 static int qcom_edp_dp_link_clk_determine_rate(struct clk_hw *hw,
1206 					       struct clk_rate_request *req)
1207 {
1208 	switch (req->rate) {
1209 	case 162000000:
1210 	case 270000000:
1211 	case 540000000:
1212 	case 810000000:
1213 		return 0;
1214 
1215 	default:
1216 		return -EINVAL;
1217 	}
1218 }
1219 
1220 static unsigned long
1221 qcom_edp_dp_link_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
1222 {
1223 	const struct qcom_edp *edp = container_of(hw, struct qcom_edp, dp_link_hw);
1224 	const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
1225 
1226 	switch (dp_opts->link_rate) {
1227 	case 1620:
1228 	case 2700:
1229 	case 5400:
1230 	case 8100:
1231 		return dp_opts->link_rate * 100000;
1232 
1233 	default:
1234 		return 0;
1235 	}
1236 }
1237 
1238 static const struct clk_ops qcom_edp_dp_link_clk_ops = {
1239 	.determine_rate = qcom_edp_dp_link_clk_determine_rate,
1240 	.recalc_rate = qcom_edp_dp_link_clk_recalc_rate,
1241 };
1242 
1243 static int qcom_edp_clks_register(struct qcom_edp *edp, struct device_node *np)
1244 {
1245 	struct clk_hw_onecell_data *data;
1246 	struct clk_init_data init = { };
1247 	char name[64];
1248 	int ret;
1249 
1250 	data = devm_kzalloc(edp->dev, struct_size(data, hws, 2), GFP_KERNEL);
1251 	if (!data)
1252 		return -ENOMEM;
1253 	data->num = 2;
1254 
1255 	snprintf(name, sizeof(name), "%s::link_clk", dev_name(edp->dev));
1256 	init.ops = &qcom_edp_dp_link_clk_ops;
1257 	init.name = name;
1258 	edp->dp_link_hw.init = &init;
1259 	ret = devm_clk_hw_register(edp->dev, &edp->dp_link_hw);
1260 	if (ret)
1261 		return ret;
1262 
1263 	snprintf(name, sizeof(name), "%s::vco_div_clk", dev_name(edp->dev));
1264 	init.ops = &qcom_edp_dp_pixel_clk_ops;
1265 	init.name = name;
1266 	edp->dp_pixel_hw.init = &init;
1267 	ret = devm_clk_hw_register(edp->dev, &edp->dp_pixel_hw);
1268 	if (ret)
1269 		return ret;
1270 
1271 	data->hws[0] = &edp->dp_link_hw;
1272 	data->hws[1] = &edp->dp_pixel_hw;
1273 
1274 	return devm_of_clk_add_hw_provider(edp->dev, of_clk_hw_onecell_get, data);
1275 }
1276 
1277 static int qcom_edp_phy_probe(struct platform_device *pdev)
1278 {
1279 	struct phy_provider *phy_provider;
1280 	struct device *dev = &pdev->dev;
1281 	struct qcom_edp *edp;
1282 	int ret;
1283 
1284 	edp = devm_kzalloc(dev, sizeof(*edp), GFP_KERNEL);
1285 	if (!edp)
1286 		return -ENOMEM;
1287 
1288 	edp->dev = dev;
1289 	edp->cfg = of_device_get_match_data(&pdev->dev);
1290 	edp->is_edp = edp->cfg->is_edp;
1291 
1292 	edp->edp = devm_platform_ioremap_resource(pdev, 0);
1293 	if (IS_ERR(edp->edp))
1294 		return PTR_ERR(edp->edp);
1295 
1296 	edp->tx0 = devm_platform_ioremap_resource(pdev, 1);
1297 	if (IS_ERR(edp->tx0))
1298 		return PTR_ERR(edp->tx0);
1299 
1300 	edp->tx1 = devm_platform_ioremap_resource(pdev, 2);
1301 	if (IS_ERR(edp->tx1))
1302 		return PTR_ERR(edp->tx1);
1303 
1304 	edp->pll = devm_platform_ioremap_resource(pdev, 3);
1305 	if (IS_ERR(edp->pll))
1306 		return PTR_ERR(edp->pll);
1307 
1308 	edp->num_clks = devm_clk_bulk_get_all(dev, &edp->clks);
1309 	if (edp->num_clks < 0)
1310 		return dev_err_probe(dev, edp->num_clks, "failed to get clocks\n");
1311 
1312 	edp->supplies[0].supply = "vdda-phy";
1313 	edp->supplies[1].supply = "vdda-pll";
1314 	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(edp->supplies), edp->supplies);
1315 	if (ret)
1316 		return ret;
1317 
1318 	ret = regulator_set_load(edp->supplies[0].consumer, 21800); /* 1.2 V vdda-phy */
1319 	if (ret) {
1320 		dev_err(dev, "failed to set load at %s\n", edp->supplies[0].supply);
1321 		return ret;
1322 	}
1323 
1324 	ret = regulator_set_load(edp->supplies[1].consumer, 36000); /* 0.9 V vdda-pll */
1325 	if (ret) {
1326 		dev_err(dev, "failed to set load at %s\n", edp->supplies[1].supply);
1327 		return ret;
1328 	}
1329 
1330 	ret = qcom_edp_clks_register(edp, pdev->dev.of_node);
1331 	if (ret)
1332 		return ret;
1333 
1334 	edp->phy = devm_phy_create(dev, pdev->dev.of_node, &qcom_edp_ops);
1335 	if (IS_ERR(edp->phy)) {
1336 		dev_err(dev, "failed to register phy\n");
1337 		return PTR_ERR(edp->phy);
1338 	}
1339 
1340 	phy_set_drvdata(edp->phy, edp);
1341 
1342 	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
1343 	return PTR_ERR_OR_ZERO(phy_provider);
1344 }
1345 
1346 static const struct of_device_id qcom_edp_phy_match_table[] = {
1347 	{ .compatible = "qcom,glymur-dp-phy", .data = &glymur_phy_cfg, },
1348 	{ .compatible = "qcom,sa8775p-edp-phy", .data = &sa8775p_dp_phy_cfg, },
1349 	{ .compatible = "qcom,sc7280-edp-phy", .data = &sc7280_dp_phy_cfg, },
1350 	{ .compatible = "qcom,sc8180x-edp-phy", .data = &sc7280_dp_phy_cfg, },
1351 	{ .compatible = "qcom,sc8280xp-dp-phy", .data = &sc8280xp_dp_phy_cfg, },
1352 	{ .compatible = "qcom,sc8280xp-edp-phy", .data = &sc8280xp_edp_phy_cfg, },
1353 	{ .compatible = "qcom,x1e80100-dp-phy", .data = &x1e80100_phy_cfg, },
1354 	{ }
1355 };
1356 MODULE_DEVICE_TABLE(of, qcom_edp_phy_match_table);
1357 
1358 static struct platform_driver qcom_edp_phy_driver = {
1359 	.probe		= qcom_edp_phy_probe,
1360 	.driver = {
1361 		.name	= "qcom-edp-phy",
1362 		.of_match_table = qcom_edp_phy_match_table,
1363 	},
1364 };
1365 
1366 module_platform_driver(qcom_edp_phy_driver);
1367 
1368 MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@linaro.org>");
1369 MODULE_DESCRIPTION("Qualcomm eDP QMP PHY driver");
1370 MODULE_LICENSE("GPL v2");
1371