1
2
3
4
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
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
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 {
74 struct device *dev;
75
76 struct phy *phy;
77
78 void __iomem *edp;
79 void __iomem *tx0;
80 void __iomem *tx1;
81 void __iomem *pll;
82
83 struct clk_hw dp_link_hw;
84 struct clk_hw dp_pixel_hw;
85
86 struct phy_configure_opts_dp dp_opts;
87
88 struct clk_bulk_data clks[2];
89 struct regulator_bulk_data supplies[2];
90};
91
92static int qcom_edp_phy_init(struct phy *phy)
93{
94 struct qcom_edp *edp = phy_get_drvdata(phy);
95 int ret;
96
97 ret = regulator_bulk_enable(ARRAY_SIZE(edp->supplies), edp->supplies);
98 if (ret)
99 return ret;
100
101 ret = clk_bulk_prepare_enable(ARRAY_SIZE(edp->clks), edp->clks);
102 if (ret)
103 goto out_disable_supplies;
104
105 writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
106 DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
107 edp->edp + DP_PHY_PD_CTL);
108
109
110 writel(0x17, edp->pll + QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN);
111
112 writel(DP_PHY_PD_CTL_PSR_PWRDN, edp->edp + DP_PHY_PD_CTL);
113 msleep(20);
114
115 writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
116 DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN |
117 DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
118 edp->edp + DP_PHY_PD_CTL);
119
120 writel(0x00, edp->edp + DP_PHY_AUX_CFG0);
121 writel(0x13, edp->edp + DP_PHY_AUX_CFG1);
122 writel(0x24, edp->edp + DP_PHY_AUX_CFG2);
123 writel(0x00, edp->edp + DP_PHY_AUX_CFG3);
124 writel(0x0a, edp->edp + DP_PHY_AUX_CFG4);
125 writel(0x26, edp->edp + DP_PHY_AUX_CFG5);
126 writel(0x0a, edp->edp + DP_PHY_AUX_CFG6);
127 writel(0x03, edp->edp + DP_PHY_AUX_CFG7);
128 writel(0x37, edp->edp + DP_PHY_AUX_CFG8);
129 writel(0x03, edp->edp + DP_PHY_AUX_CFG9);
130
131 writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK |
132 PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK |
133 PHY_AUX_REQ_ERR_MASK, edp->edp + DP_PHY_AUX_INTERRUPT_MASK);
134
135 msleep(20);
136
137 return 0;
138
139out_disable_supplies:
140 regulator_bulk_disable(ARRAY_SIZE(edp->supplies), edp->supplies);
141
142 return ret;
143}
144
145static int qcom_edp_phy_configure(struct phy *phy, union phy_configure_opts *opts)
146{
147 const struct phy_configure_opts_dp *dp_opts = &opts->dp;
148 struct qcom_edp *edp = phy_get_drvdata(phy);
149
150 memcpy(&edp->dp_opts, dp_opts, sizeof(*dp_opts));
151
152 return 0;
153}
154
155static int qcom_edp_configure_ssc(const struct qcom_edp *edp)
156{
157 const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
158 u32 step1;
159 u32 step2;
160
161 switch (dp_opts->link_rate) {
162 case 1620:
163 case 2700:
164 case 8100:
165 step1 = 0x45;
166 step2 = 0x06;
167 break;
168
169 case 5400:
170 step1 = 0x5c;
171 step2 = 0x08;
172 break;
173
174 default:
175
176 return -EINVAL;
177 }
178
179 writel(0x01, edp->pll + QSERDES_V4_COM_SSC_EN_CENTER);
180 writel(0x00, edp->pll + QSERDES_V4_COM_SSC_ADJ_PER1);
181 writel(0x36, edp->pll + QSERDES_V4_COM_SSC_PER1);
182 writel(0x01, edp->pll + QSERDES_V4_COM_SSC_PER2);
183 writel(step1, edp->pll + QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0);
184 writel(step2, edp->pll + QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0);
185
186 return 0;
187}
188
189static int qcom_edp_configure_pll(const struct qcom_edp *edp)
190{
191 const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
192 u32 div_frac_start2_mode0;
193 u32 div_frac_start3_mode0;
194 u32 dec_start_mode0;
195 u32 lock_cmp1_mode0;
196 u32 lock_cmp2_mode0;
197 u32 hsclk_sel;
198
199 switch (dp_opts->link_rate) {
200 case 1620:
201 hsclk_sel = 0x5;
202 dec_start_mode0 = 0x69;
203 div_frac_start2_mode0 = 0x80;
204 div_frac_start3_mode0 = 0x07;
205 lock_cmp1_mode0 = 0x6f;
206 lock_cmp2_mode0 = 0x08;
207 break;
208
209 case 2700:
210 hsclk_sel = 0x3;
211 dec_start_mode0 = 0x69;
212 div_frac_start2_mode0 = 0x80;
213 div_frac_start3_mode0 = 0x07;
214 lock_cmp1_mode0 = 0x0f;
215 lock_cmp2_mode0 = 0x0e;
216 break;
217
218 case 5400:
219 hsclk_sel = 0x1;
220 dec_start_mode0 = 0x8c;
221 div_frac_start2_mode0 = 0x00;
222 div_frac_start3_mode0 = 0x0a;
223 lock_cmp1_mode0 = 0x1f;
224 lock_cmp2_mode0 = 0x1c;
225 break;
226
227 case 8100:
228 hsclk_sel = 0x0;
229 dec_start_mode0 = 0x69;
230 div_frac_start2_mode0 = 0x80;
231 div_frac_start3_mode0 = 0x07;
232 lock_cmp1_mode0 = 0x2f;
233 lock_cmp2_mode0 = 0x2a;
234 break;
235
236 default:
237
238 return -EINVAL;
239 }
240
241 writel(0x01, edp->pll + QSERDES_V4_COM_SVS_MODE_CLK_SEL);
242 writel(0x0b, edp->pll + QSERDES_V4_COM_SYSCLK_EN_SEL);
243 writel(0x02, edp->pll + QSERDES_V4_COM_SYS_CLK_CTRL);
244 writel(0x0c, edp->pll + QSERDES_V4_COM_CLK_ENABLE1);
245 writel(0x06, edp->pll + QSERDES_V4_COM_SYSCLK_BUF_ENABLE);
246 writel(0x30, edp->pll + QSERDES_V4_COM_CLK_SELECT);
247 writel(hsclk_sel, edp->pll + QSERDES_V4_COM_HSCLK_SEL);
248 writel(0x0f, edp->pll + QSERDES_V4_COM_PLL_IVCO);
249 writel(0x08, edp->pll + QSERDES_V4_COM_LOCK_CMP_EN);
250 writel(0x36, edp->pll + QSERDES_V4_COM_PLL_CCTRL_MODE0);
251 writel(0x16, edp->pll + QSERDES_V4_COM_PLL_RCTRL_MODE0);
252 writel(0x06, edp->pll + QSERDES_V4_COM_CP_CTRL_MODE0);
253 writel(dec_start_mode0, edp->pll + QSERDES_V4_COM_DEC_START_MODE0);
254 writel(0x00, edp->pll + QSERDES_V4_COM_DIV_FRAC_START1_MODE0);
255 writel(div_frac_start2_mode0, edp->pll + QSERDES_V4_COM_DIV_FRAC_START2_MODE0);
256 writel(div_frac_start3_mode0, edp->pll + QSERDES_V4_COM_DIV_FRAC_START3_MODE0);
257 writel(0x02, edp->pll + QSERDES_V4_COM_CMN_CONFIG);
258 writel(0x3f, edp->pll + QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0);
259 writel(0x00, edp->pll + QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0);
260 writel(0x00, edp->pll + QSERDES_V4_COM_VCO_TUNE_MAP);
261 writel(lock_cmp1_mode0, edp->pll + QSERDES_V4_COM_LOCK_CMP1_MODE0);
262 writel(lock_cmp2_mode0, edp->pll + QSERDES_V4_COM_LOCK_CMP2_MODE0);
263
264 writel(0x0a, edp->pll + QSERDES_V4_COM_BG_TIMER);
265 writel(0x14, edp->pll + QSERDES_V4_COM_CORECLK_DIV_MODE0);
266 writel(0x00, edp->pll + QSERDES_V4_COM_VCO_TUNE_CTRL);
267 writel(0x17, edp->pll + QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN);
268 writel(0x0f, edp->pll + QSERDES_V4_COM_CORE_CLK_EN);
269 writel(0xa0, edp->pll + QSERDES_V4_COM_VCO_TUNE1_MODE0);
270 writel(0x03, edp->pll + QSERDES_V4_COM_VCO_TUNE2_MODE0);
271
272 return 0;
273}
274
275static int qcom_edp_set_vco_div(const struct qcom_edp *edp)
276{
277 const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
278 unsigned long pixel_freq;
279 u32 vco_div;
280
281 switch (dp_opts->link_rate) {
282 case 1620:
283 vco_div = 0x1;
284 pixel_freq = 1620000000UL / 2;
285 break;
286
287 case 2700:
288 vco_div = 0x1;
289 pixel_freq = 2700000000UL / 2;
290 break;
291
292 case 5400:
293 vco_div = 0x2;
294 pixel_freq = 5400000000UL / 4;
295 break;
296
297 case 8100:
298 vco_div = 0x0;
299 pixel_freq = 8100000000UL / 6;
300 break;
301
302 default:
303
304 return -EINVAL;
305 }
306
307 writel(vco_div, edp->edp + DP_PHY_VCO_DIV);
308
309 clk_set_rate(edp->dp_link_hw.clk, dp_opts->link_rate * 100000);
310 clk_set_rate(edp->dp_pixel_hw.clk, pixel_freq);
311
312 return 0;
313}
314
315static int qcom_edp_phy_power_on(struct phy *phy)
316{
317 const struct qcom_edp *edp = phy_get_drvdata(phy);
318 int timeout;
319 int ret;
320 u32 val;
321
322 writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
323 DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN |
324 DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
325 edp->edp + DP_PHY_PD_CTL);
326 writel(0xfc, edp->edp + DP_PHY_MODE);
327
328 timeout = readl_poll_timeout(edp->pll + QSERDES_V4_COM_CMN_STATUS,
329 val, val & BIT(7), 5, 200);
330 if (timeout)
331 return timeout;
332
333 writel(0x01, edp->tx0 + TXn_LDO_CONFIG);
334 writel(0x01, edp->tx1 + TXn_LDO_CONFIG);
335 writel(0x00, edp->tx0 + TXn_LANE_MODE_1);
336 writel(0x00, edp->tx1 + TXn_LANE_MODE_1);
337
338 ret = qcom_edp_configure_ssc(edp);
339 if (ret)
340 return ret;
341
342 ret = qcom_edp_configure_pll(edp);
343 if (ret)
344 return ret;
345
346
347 writel(0x05, edp->edp + DP_PHY_TX0_TX1_LANE_CTL);
348 writel(0x05, edp->edp + DP_PHY_TX2_TX3_LANE_CTL);
349
350
351 writel(0x03, edp->tx0 + TXn_TRANSCEIVER_BIAS_EN);
352 writel(0x0f, edp->tx0 + TXn_CLKBUF_ENABLE);
353 writel(0x03, edp->tx0 + TXn_RESET_TSYNC_EN);
354 writel(0x01, edp->tx0 + TXn_TRAN_DRVR_EMP_EN);
355 writel(0x04, edp->tx0 + TXn_TX_BAND);
356
357
358 writel(0x03, edp->tx1 + TXn_TRANSCEIVER_BIAS_EN);
359 writel(0x0f, edp->tx1 + TXn_CLKBUF_ENABLE);
360 writel(0x03, edp->tx1 + TXn_RESET_TSYNC_EN);
361 writel(0x01, edp->tx1 + TXn_TRAN_DRVR_EMP_EN);
362 writel(0x04, edp->tx1 + TXn_TX_BAND);
363
364 ret = qcom_edp_set_vco_div(edp);
365 if (ret)
366 return ret;
367
368 writel(0x01, edp->edp + DP_PHY_CFG);
369 writel(0x05, edp->edp + DP_PHY_CFG);
370 writel(0x01, edp->edp + DP_PHY_CFG);
371 writel(0x09, edp->edp + DP_PHY_CFG);
372
373 writel(0x20, edp->pll + QSERDES_V4_COM_RESETSM_CNTRL);
374
375 timeout = readl_poll_timeout(edp->pll + QSERDES_V4_COM_C_READY_STATUS,
376 val, val & BIT(0), 500, 10000);
377 if (timeout)
378 return timeout;
379
380 writel(0x19, edp->edp + DP_PHY_CFG);
381 writel(0x1f, edp->tx0 + TXn_HIGHZ_DRVR_EN);
382 writel(0x04, edp->tx0 + TXn_HIGHZ_DRVR_EN);
383 writel(0x00, edp->tx0 + TXn_TX_POL_INV);
384 writel(0x1f, edp->tx1 + TXn_HIGHZ_DRVR_EN);
385 writel(0x04, edp->tx1 + TXn_HIGHZ_DRVR_EN);
386 writel(0x00, edp->tx1 + TXn_TX_POL_INV);
387 writel(0x10, edp->tx0 + TXn_TX_DRV_LVL_OFFSET);
388 writel(0x10, edp->tx1 + TXn_TX_DRV_LVL_OFFSET);
389 writel(0x11, edp->tx0 + TXn_RES_CODE_LANE_OFFSET_TX0);
390 writel(0x11, edp->tx0 + TXn_RES_CODE_LANE_OFFSET_TX1);
391 writel(0x11, edp->tx1 + TXn_RES_CODE_LANE_OFFSET_TX0);
392 writel(0x11, edp->tx1 + TXn_RES_CODE_LANE_OFFSET_TX1);
393
394 writel(0x10, edp->tx0 + TXn_TX_EMP_POST1_LVL);
395 writel(0x10, edp->tx1 + TXn_TX_EMP_POST1_LVL);
396 writel(0x1f, edp->tx0 + TXn_TX_DRV_LVL);
397 writel(0x1f, edp->tx1 + TXn_TX_DRV_LVL);
398
399 writel(0x4, edp->tx0 + TXn_HIGHZ_DRVR_EN);
400 writel(0x3, edp->tx0 + TXn_TRANSCEIVER_BIAS_EN);
401 writel(0x4, edp->tx1 + TXn_HIGHZ_DRVR_EN);
402 writel(0x0, edp->tx1 + TXn_TRANSCEIVER_BIAS_EN);
403 writel(0x3, edp->edp + DP_PHY_CFG_1);
404
405 writel(0x18, edp->edp + DP_PHY_CFG);
406 usleep_range(100, 1000);
407
408 writel(0x19, edp->edp + DP_PHY_CFG);
409
410 return readl_poll_timeout(edp->edp + DP_PHY_STATUS,
411 val, val & BIT(1), 500, 10000);
412}
413
414static int qcom_edp_phy_power_off(struct phy *phy)
415{
416 const struct qcom_edp *edp = phy_get_drvdata(phy);
417
418 writel(DP_PHY_PD_CTL_PSR_PWRDN, edp->edp + DP_PHY_PD_CTL);
419
420 return 0;
421}
422
423static int qcom_edp_phy_exit(struct phy *phy)
424{
425 struct qcom_edp *edp = phy_get_drvdata(phy);
426
427 clk_bulk_disable_unprepare(ARRAY_SIZE(edp->clks), edp->clks);
428 regulator_bulk_disable(ARRAY_SIZE(edp->supplies), edp->supplies);
429
430 return 0;
431}
432
433static const struct phy_ops qcom_edp_ops = {
434 .init = qcom_edp_phy_init,
435 .configure = qcom_edp_phy_configure,
436 .power_on = qcom_edp_phy_power_on,
437 .power_off = qcom_edp_phy_power_off,
438 .exit = qcom_edp_phy_exit,
439 .owner = THIS_MODULE,
440};
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491static int qcom_edp_dp_pixel_clk_determine_rate(struct clk_hw *hw,
492 struct clk_rate_request *req)
493{
494 switch (req->rate) {
495 case 1620000000UL / 2:
496 case 2700000000UL / 2:
497
498 return 0;
499
500 default:
501 return -EINVAL;
502 }
503}
504
505static unsigned long
506qcom_edp_dp_pixel_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
507{
508 const struct qcom_edp *edp = container_of(hw, struct qcom_edp, dp_pixel_hw);
509 const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
510
511 switch (dp_opts->link_rate) {
512 case 1620:
513 return 1620000000UL / 2;
514 case 2700:
515 return 2700000000UL / 2;
516 case 5400:
517 return 5400000000UL / 4;
518 case 8100:
519 return 8100000000UL / 6;
520 default:
521 return 0;
522 }
523}
524
525static const struct clk_ops qcom_edp_dp_pixel_clk_ops = {
526 .determine_rate = qcom_edp_dp_pixel_clk_determine_rate,
527 .recalc_rate = qcom_edp_dp_pixel_clk_recalc_rate,
528};
529
530static int qcom_edp_dp_link_clk_determine_rate(struct clk_hw *hw,
531 struct clk_rate_request *req)
532{
533 switch (req->rate) {
534 case 162000000:
535 case 270000000:
536 case 540000000:
537 case 810000000:
538 return 0;
539
540 default:
541 return -EINVAL;
542 }
543}
544
545static unsigned long
546qcom_edp_dp_link_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
547{
548 const struct qcom_edp *edp = container_of(hw, struct qcom_edp, dp_link_hw);
549 const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
550
551 switch (dp_opts->link_rate) {
552 case 1620:
553 case 2700:
554 case 5400:
555 case 8100:
556 return dp_opts->link_rate * 100000;
557
558 default:
559 return 0;
560 }
561}
562
563static const struct clk_ops qcom_edp_dp_link_clk_ops = {
564 .determine_rate = qcom_edp_dp_link_clk_determine_rate,
565 .recalc_rate = qcom_edp_dp_link_clk_recalc_rate,
566};
567
568static int qcom_edp_clks_register(struct qcom_edp *edp, struct device_node *np)
569{
570 struct clk_hw_onecell_data *data;
571 struct clk_init_data init = { };
572 int ret;
573
574 data = devm_kzalloc(edp->dev, struct_size(data, hws, 2), GFP_KERNEL);
575 if (!data)
576 return -ENOMEM;
577
578 init.ops = &qcom_edp_dp_link_clk_ops;
579 init.name = "edp_phy_pll_link_clk";
580 edp->dp_link_hw.init = &init;
581 ret = devm_clk_hw_register(edp->dev, &edp->dp_link_hw);
582 if (ret)
583 return ret;
584
585 init.ops = &qcom_edp_dp_pixel_clk_ops;
586 init.name = "edp_phy_pll_vco_div_clk";
587 edp->dp_pixel_hw.init = &init;
588 ret = devm_clk_hw_register(edp->dev, &edp->dp_pixel_hw);
589 if (ret)
590 return ret;
591
592 data->hws[0] = &edp->dp_link_hw;
593 data->hws[1] = &edp->dp_pixel_hw;
594 data->num = 2;
595
596 return devm_of_clk_add_hw_provider(edp->dev, of_clk_hw_onecell_get, data);
597}
598
599static int qcom_edp_phy_probe(struct platform_device *pdev)
600{
601 struct phy_provider *phy_provider;
602 struct device *dev = &pdev->dev;
603 struct qcom_edp *edp;
604 int ret;
605
606 edp = devm_kzalloc(dev, sizeof(*edp), GFP_KERNEL);
607 if (!edp)
608 return -ENOMEM;
609
610 edp->dev = dev;
611
612 edp->edp = devm_platform_ioremap_resource(pdev, 0);
613 if (IS_ERR(edp->edp))
614 return PTR_ERR(edp->edp);
615
616 edp->tx0 = devm_platform_ioremap_resource(pdev, 1);
617 if (IS_ERR(edp->tx0))
618 return PTR_ERR(edp->tx0);
619
620 edp->tx1 = devm_platform_ioremap_resource(pdev, 2);
621 if (IS_ERR(edp->tx1))
622 return PTR_ERR(edp->tx1);
623
624 edp->pll = devm_platform_ioremap_resource(pdev, 3);
625 if (IS_ERR(edp->pll))
626 return PTR_ERR(edp->pll);
627
628 edp->clks[0].id = "aux";
629 edp->clks[1].id = "cfg_ahb";
630 ret = devm_clk_bulk_get(dev, ARRAY_SIZE(edp->clks), edp->clks);
631 if (ret)
632 return ret;
633
634 edp->supplies[0].supply = "vdda-phy";
635 edp->supplies[1].supply = "vdda-pll";
636 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(edp->supplies), edp->supplies);
637 if (ret)
638 return ret;
639
640 ret = qcom_edp_clks_register(edp, pdev->dev.of_node);
641 if (ret)
642 return ret;
643
644 edp->phy = devm_phy_create(dev, pdev->dev.of_node, &qcom_edp_ops);
645 if (IS_ERR(edp->phy)) {
646 dev_err(dev, "failed to register phy\n");
647 return PTR_ERR(edp->phy);
648 }
649
650 phy_set_drvdata(edp->phy, edp);
651
652 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
653 return PTR_ERR_OR_ZERO(phy_provider);
654}
655
656static const struct of_device_id qcom_edp_phy_match_table[] = {
657 { .compatible = "qcom,sc8180x-edp-phy" },
658 { }
659};
660MODULE_DEVICE_TABLE(of, qcom_edp_phy_match_table);
661
662static struct platform_driver qcom_edp_phy_driver = {
663 .probe = qcom_edp_phy_probe,
664 .driver = {
665 .name = "qcom-edp-phy",
666 .of_match_table = qcom_edp_phy_match_table,
667 },
668};
669
670module_platform_driver(qcom_edp_phy_driver);
671
672MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@linaro.org>");
673MODULE_DESCRIPTION("Qualcomm eDP QMP PHY driver");
674MODULE_LICENSE("GPL v2");
675