Linux Audio

Check our new training course

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