1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2017, 2020, The Linux Foundation. All rights reserved.
4 * Copyright (c) 2021, Linaro Ltd.
8 #include <linux/clk-provider.h>
9 #include <linux/delay.h>
10 #include <linux/err.h>
12 #include <linux/iopoll.h>
13 #include <linux/kernel.h>
14 #include <linux/module.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>
23 #include <dt-bindings/phy/phy.h>
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"
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
35 #define DP_AUX_CFG_SIZE 10
36 #define DP_PHY_AUX_CFG(n) (0x24 + (0x04 * (n)))
38 #define DP_PHY_AUX_INTERRUPT_MASK 0x0058
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
44 #define DP_PHY_STATUS 0x00e0
46 /* LANE_TXn registers */
47 #define TXn_CLKBUF_ENABLE 0x0000
48 #define TXn_TX_EMP_POST1_LVL 0x0004
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
56 #define TXn_RES_CODE_LANE_OFFSET_TX0 0x0044
57 #define TXn_RES_CODE_LANE_OFFSET_TX1 0x0048
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
64 #define TXn_TRAN_DRVR_EMP_EN 0x0078
66 struct 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];
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
);
83 struct qcom_edp_phy_cfg
{
86 const struct qcom_edp_swing_pre_emph_cfg
*swing_pre_emph_cfg
;
87 const struct phy_ver_ops
*ver_ops
;
92 const struct qcom_edp_phy_cfg
*cfg
;
101 struct clk_hw dp_link_hw
;
102 struct clk_hw dp_pixel_hw
;
104 struct phy_configure_opts_dp dp_opts
;
106 struct clk_bulk_data clks
[2];
107 struct regulator_bulk_data supplies
[2];
112 static 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 }
119 static 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 }
126 static 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 }
133 static 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 }
140 static 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
,
147 static 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 }
154 static 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 }
161 static 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 }
168 static 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 }
175 static 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
,
182 static const u8 edp_phy_aux_cfg_v4
[10] = {
183 0x00, 0x13, 0x24, 0x00, 0x0a, 0x26, 0x0a, 0x03, 0x37, 0x03
186 static 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 }
193 static 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 }
200 static 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
,
207 static const u8 edp_phy_aux_cfg_v5
[10] = {
208 0x00, 0x13, 0xa4, 0x00, 0x0a, 0x26, 0x0a, 0x03, 0x37, 0x03
211 static int qcom_edp_phy_init(struct phy
*phy
)
213 struct qcom_edp
*edp
= phy_get_drvdata(phy
);
214 u8 aux_cfg
[DP_AUX_CFG_SIZE
];
217 ret
= regulator_bulk_enable(ARRAY_SIZE(edp
->supplies
), edp
->supplies
);
221 ret
= clk_bulk_prepare_enable(ARRAY_SIZE(edp
->clks
), edp
->clks
);
223 goto out_disable_supplies
;
225 memcpy(aux_cfg
, edp
->cfg
->aux_cfg
, sizeof(aux_cfg
));
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
);
231 ret
= edp
->cfg
->ver_ops
->com_bias_en_clkbuflr(edp
);
235 writel(DP_PHY_PD_CTL_PSR_PWRDN
, edp
->edp
+ DP_PHY_PD_CTL
);
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
);
244 * TODO: Re-work the conditions around setting the cfg8 value
245 * when more information becomes available about why this is
248 if (edp
->cfg
->swing_pre_emph_cfg
&& !edp
->is_edp
)
251 writel(0xfc, edp
->edp
+ DP_PHY_MODE
);
253 for (int i
= 0; i
< DP_AUX_CFG_SIZE
; i
++)
254 writel(aux_cfg
[i
], edp
->edp
+ DP_PHY_AUX_CFG(i
));
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
);
264 out_disable_supplies
:
265 regulator_bulk_disable(ARRAY_SIZE(edp
->supplies
), edp
->supplies
);
270 static int qcom_edp_set_voltages(struct qcom_edp
*edp
, const struct phy_configure_opts_dp
*dp_opts
)
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;
284 cfg
= &edp_phy_swing_pre_emph_cfg
;
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
]);
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
];
295 swing
= (*cfg
->swing_hbr3_hbr2
)[v_level
][p_level
];
296 emph
= (*cfg
->pre_emphasis_hbr3_hbr2
)[v_level
][p_level
];
299 if (swing
== 0xff || emph
== 0xff)
302 ldo_config
= edp
->is_edp
? 0x0 : 0x1;
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
);
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
);
315 static int qcom_edp_phy_configure(struct phy
*phy
, union phy_configure_opts
*opts
)
317 const struct phy_configure_opts_dp
*dp_opts
= &opts
->dp
;
318 struct qcom_edp
*edp
= phy_get_drvdata(phy
);
321 memcpy(&edp
->dp_opts
, dp_opts
, sizeof(*dp_opts
));
323 if (dp_opts
->set_voltages
)
324 ret
= qcom_edp_set_voltages(edp
, dp_opts
);
329 static int qcom_edp_configure_ssc(const struct qcom_edp
*edp
)
331 return edp
->cfg
->ver_ops
->com_configure_ssc(edp
);
334 static int qcom_edp_configure_pll(const struct qcom_edp
*edp
)
336 return edp
->cfg
->ver_ops
->com_configure_pll(edp
);
339 static int qcom_edp_set_vco_div(const struct qcom_edp
*edp
, unsigned long *pixel_freq
)
341 const struct phy_configure_opts_dp
*dp_opts
= &edp
->dp_opts
;
344 switch (dp_opts
->link_rate
) {
347 *pixel_freq
= 1620000000UL / 2;
352 *pixel_freq
= 2700000000UL / 2;
357 *pixel_freq
= 5400000000UL / 4;
362 *pixel_freq
= 8100000000UL / 6;
366 /* Other link rates aren't supported */
370 writel(vco_div
, edp
->edp
+ DP_PHY_VCO_DIV
);
375 static int qcom_edp_phy_power_on_v4(const struct qcom_edp
*edp
)
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
);
385 return readl_poll_timeout(edp
->pll
+ QSERDES_V4_COM_CMN_STATUS
,
386 val
, val
& BIT(7), 5, 200);
389 static int qcom_edp_phy_com_resetsm_cntrl_v4(const struct qcom_edp
*edp
)
393 writel(0x20, edp
->pll
+ QSERDES_V4_COM_RESETSM_CNTRL
);
395 return readl_poll_timeout(edp
->pll
+ QSERDES_V4_COM_C_READY_STATUS
,
396 val
, val
& BIT(0), 500, 10000);
399 static int qcom_edp_com_bias_en_clkbuflr_v4(const struct qcom_edp
*edp
)
401 /* Turn on BIAS current for PHY/PLL */
402 writel(0x17, edp
->pll
+ QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN
);
407 static int qcom_edp_com_configure_ssc_v4(const struct qcom_edp
*edp
)
409 const struct phy_configure_opts_dp
*dp_opts
= &edp
->dp_opts
;
413 switch (dp_opts
->link_rate
) {
427 /* Other link rates aren't supported */
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
);
441 static int qcom_edp_com_configure_pll_v4(const struct qcom_edp
*edp
)
443 const struct phy_configure_opts_dp
*dp_opts
= &edp
->dp_opts
;
444 u32 div_frac_start2_mode0
;
445 u32 div_frac_start3_mode0
;
451 switch (dp_opts
->link_rate
) {
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;
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;
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;
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;
489 /* Other link rates aren't supported */
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
);
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
);
527 static 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
,
535 static const struct qcom_edp_phy_cfg sa8775p_dp_phy_cfg
= {
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
,
542 static 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
,
547 static 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
,
553 static const struct qcom_edp_phy_cfg sc8280xp_edp_phy_cfg
= {
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
,
560 static int qcom_edp_phy_power_on_v6(const struct qcom_edp
*edp
)
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
);
570 return readl_poll_timeout(edp
->pll
+ QSERDES_V6_COM_CMN_STATUS
,
571 val
, val
& BIT(7), 5, 200);
574 static int qcom_edp_phy_com_resetsm_cntrl_v6(const struct qcom_edp
*edp
)
578 writel(0x20, edp
->pll
+ QSERDES_V6_COM_RESETSM_CNTRL
);
580 return readl_poll_timeout(edp
->pll
+ QSERDES_V6_COM_C_READY_STATUS
,
581 val
, val
& BIT(0), 500, 10000);
584 static int qcom_edp_com_bias_en_clkbuflr_v6(const struct qcom_edp
*edp
)
586 /* Turn on BIAS current for PHY/PLL */
587 writel(0x1f, edp
->pll
+ QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN
);
592 static int qcom_edp_com_configure_ssc_v6(const struct qcom_edp
*edp
)
594 const struct phy_configure_opts_dp
*dp_opts
= &edp
->dp_opts
;
598 switch (dp_opts
->link_rate
) {
612 /* Other link rates aren't supported */
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
);
626 static int qcom_edp_com_configure_pll_v6(const struct qcom_edp
*edp
)
628 const struct phy_configure_opts_dp
*dp_opts
= &edp
->dp_opts
;
629 u32 div_frac_start2_mode0
;
630 u32 div_frac_start3_mode0
;
638 switch (dp_opts
->link_rate
) {
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;
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;
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;
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;
684 /* Other link rates aren't supported */
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
);
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
);
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
);
725 static 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
,
733 static 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
,
739 static int qcom_edp_phy_power_on(struct phy
*phy
)
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
;
749 ret
= edp
->cfg
->ver_ops
->com_power_on(edp
);
753 if (edp
->cfg
->swing_pre_emph_cfg
&& !edp
->is_edp
)
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
);
761 if (edp
->dp_opts
.ssc
) {
762 ret
= qcom_edp_configure_ssc(edp
);
767 ret
= qcom_edp_configure_pll(edp
);
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
);
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
);
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
);
789 ret
= qcom_edp_set_vco_div(edp
, &pixel_freq
);
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
);
798 ret
= edp
->cfg
->ver_ops
->com_resetsm_cntrl(edp
);
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
);
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
);
821 if (edp
->dp_opts
.lanes
== 1) {
827 } else if (edp
->dp_opts
.lanes
== 2) {
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
);
847 writel(0x18, edp
->edp
+ DP_PHY_CFG
);
848 usleep_range(100, 1000);
850 writel(0x19, edp
->edp
+ DP_PHY_CFG
);
852 ret
= readl_poll_timeout(edp
->edp
+ DP_PHY_STATUS
,
853 val
, val
& BIT(1), 500, 10000);
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
);
863 static int qcom_edp_phy_power_off(struct phy
*phy
)
865 const struct qcom_edp
*edp
= phy_get_drvdata(phy
);
867 writel(DP_PHY_PD_CTL_PSR_PWRDN
, edp
->edp
+ DP_PHY_PD_CTL
);
872 static int qcom_edp_phy_set_mode(struct phy
*phy
, enum phy_mode mode
, int submode
)
874 struct qcom_edp
*edp
= phy_get_drvdata(phy
);
876 if (mode
!= PHY_MODE_DP
)
879 edp
->is_edp
= submode
== PHY_SUBMODE_EDP
;
884 static int qcom_edp_phy_exit(struct phy
*phy
)
886 struct qcom_edp
*edp
= phy_get_drvdata(phy
);
888 clk_bulk_disable_unprepare(ARRAY_SIZE(edp
->clks
), edp
->clks
);
889 regulator_bulk_disable(ARRAY_SIZE(edp
->supplies
), edp
->supplies
);
894 static 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
,
905 * Embedded Display Port PLL driver block diagram for branch clocks
907 * +------------------------------+
910 * | +-------------------+ |
911 * | | (EDP PLL/VCO) | |
912 * | +---------+---------+ |
914 * | +----------+-----------+ |
915 * | | hsclk_divsel_clk_src | |
916 * | +----------+-----------+ |
917 * +------------------------------+
919 * +---------<---------v------------>----------+
921 * +--------v----------------+ |
922 * | edp_phy_pll_link_clk | |
924 * +--------+----------------+ |
928 * Input to DISPCC block |
929 * for link clk, crypto clk |
930 * and interface clock |
933 * +--------<------------+-----------------+---<---+
935 * +----v---------+ +--------v-----+ +--------v------+
936 * | vco_divided | | vco_divided | | vco_divided |
937 * | _clk_src | | _clk_src | | _clk_src |
939 * |divsel_six | | divsel_two | | divsel_four |
940 * +-------+------+ +-----+--------+ +--------+------+
942 * v---->----------v-------------<------v
944 * +----------+-----------------+
945 * | edp_phy_pll_vco_div_clk |
946 * +---------+------------------+
949 * Input to DISPCC block
950 * for EDP pixel clock
953 static int qcom_edp_dp_pixel_clk_determine_rate(struct clk_hw
*hw
,
954 struct clk_rate_request
*req
)
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 */
968 qcom_edp_dp_pixel_clk_recalc_rate(struct clk_hw
*hw
, unsigned long parent_rate
)
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
;
973 switch (dp_opts
->link_rate
) {
975 return 1620000000UL / 2;
977 return 2700000000UL / 2;
979 return 5400000000UL / 4;
981 return 8100000000UL / 6;
987 static 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
,
992 static int qcom_edp_dp_link_clk_determine_rate(struct clk_hw
*hw
,
993 struct clk_rate_request
*req
)
1007 static unsigned long
1008 qcom_edp_dp_link_clk_recalc_rate(struct clk_hw
*hw
, unsigned long parent_rate
)
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
;
1013 switch (dp_opts
->link_rate
) {
1018 return dp_opts
->link_rate
* 100000;
1025 static 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
,
1030 static int qcom_edp_clks_register(struct qcom_edp
*edp
, struct device_node
*np
)
1032 struct clk_hw_onecell_data
*data
;
1033 struct clk_init_data init
= { };
1037 data
= devm_kzalloc(edp
->dev
, struct_size(data
, hws
, 2), GFP_KERNEL
);
1042 snprintf(name
, sizeof(name
), "%s::link_clk", dev_name(edp
->dev
));
1043 init
.ops
= &qcom_edp_dp_link_clk_ops
;
1045 edp
->dp_link_hw
.init
= &init
;
1046 ret
= devm_clk_hw_register(edp
->dev
, &edp
->dp_link_hw
);
1050 snprintf(name
, sizeof(name
), "%s::vco_div_clk", dev_name(edp
->dev
));
1051 init
.ops
= &qcom_edp_dp_pixel_clk_ops
;
1053 edp
->dp_pixel_hw
.init
= &init
;
1054 ret
= devm_clk_hw_register(edp
->dev
, &edp
->dp_pixel_hw
);
1058 data
->hws
[0] = &edp
->dp_link_hw
;
1059 data
->hws
[1] = &edp
->dp_pixel_hw
;
1061 return devm_of_clk_add_hw_provider(edp
->dev
, of_clk_hw_onecell_get
, data
);
1064 static int qcom_edp_phy_probe(struct platform_device
*pdev
)
1066 struct phy_provider
*phy_provider
;
1067 struct device
*dev
= &pdev
->dev
;
1068 struct qcom_edp
*edp
;
1071 edp
= devm_kzalloc(dev
, sizeof(*edp
), GFP_KERNEL
);
1076 edp
->cfg
= of_device_get_match_data(&pdev
->dev
);
1077 edp
->is_edp
= edp
->cfg
->is_edp
;
1079 edp
->edp
= devm_platform_ioremap_resource(pdev
, 0);
1080 if (IS_ERR(edp
->edp
))
1081 return PTR_ERR(edp
->edp
);
1083 edp
->tx0
= devm_platform_ioremap_resource(pdev
, 1);
1084 if (IS_ERR(edp
->tx0
))
1085 return PTR_ERR(edp
->tx0
);
1087 edp
->tx1
= devm_platform_ioremap_resource(pdev
, 2);
1088 if (IS_ERR(edp
->tx1
))
1089 return PTR_ERR(edp
->tx1
);
1091 edp
->pll
= devm_platform_ioremap_resource(pdev
, 3);
1092 if (IS_ERR(edp
->pll
))
1093 return PTR_ERR(edp
->pll
);
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
);
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
);
1107 ret
= regulator_set_load(edp
->supplies
[0].consumer
, 21800); /* 1.2 V vdda-phy */
1109 dev_err(dev
, "failed to set load at %s\n", edp
->supplies
[0].supply
);
1113 ret
= regulator_set_load(edp
->supplies
[1].consumer
, 36000); /* 0.9 V vdda-pll */
1115 dev_err(dev
, "failed to set load at %s\n", edp
->supplies
[1].supply
);
1119 ret
= qcom_edp_clks_register(edp
, pdev
->dev
.of_node
);
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
);
1129 phy_set_drvdata(edp
->phy
, edp
);
1131 phy_provider
= devm_of_phy_provider_register(dev
, of_phy_simple_xlate
);
1132 return PTR_ERR_OR_ZERO(phy_provider
);
1135 static 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
, },
1144 MODULE_DEVICE_TABLE(of
, qcom_edp_phy_match_table
);
1146 static struct platform_driver qcom_edp_phy_driver
= {
1147 .probe
= qcom_edp_phy_probe
,
1149 .name
= "qcom-edp-phy",
1150 .of_match_table
= qcom_edp_phy_match_table
,
1154 module_platform_driver(qcom_edp_phy_driver
);
1156 MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@linaro.org>");
1157 MODULE_DESCRIPTION("Qualcomm eDP QMP PHY driver");
1158 MODULE_LICENSE("GPL v2");