1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
4 */
5
6 #include <linux/clk.h>
7 #include <linux/clk-provider.h>
8 #include <linux/delay.h>
9 #include <linux/err.h>
10 #include <linux/io.h>
11 #include <linux/iopoll.h>
12 #include <linux/mfd/syscon.h>
13 #include <linux/module.h>
14 #include <linux/of.h>
15 #include <linux/phy/phy.h>
16 #include <linux/platform_device.h>
17 #include <linux/pm_domain.h>
18 #include <linux/pm_runtime.h>
19 #include <linux/regmap.h>
20 #include <linux/regulator/consumer.h>
21 #include <linux/reset.h>
22 #include <linux/slab.h>
23
24 #include "phy-qcom-qmp.h"
25
26 #define PHY_INIT_COMPLETE_TIMEOUT_US 10000
27
28 enum qmp_pcie_glymur_link_mode {
29 QMP_PCIE_GLYMUR_MODE_X8,
30 QMP_PCIE_GLYMUR_MODE_X4X4,
31 };
32
33 enum qphy_reg_layout {
34 QPHY_PCS_STATUS,
35 QPHY_LAYOUT_SIZE
36 };
37
38 static const unsigned int pciephy_v8_50_regs_layout[QPHY_LAYOUT_SIZE] = {
39 [QPHY_PCS_STATUS] = QPHY_V8_50_PCS_STATUS1,
40 };
41
42 struct qmp_pcie_offsets {
43 u16 pcs;
44 };
45
46 struct qmp_phy_cfg {
47 const struct qmp_pcie_offsets *offsets;
48 const char * const *reg_names;
49 int num_regs;
50 const char * const *pd_names;
51 int num_pds;
52 const char * const *nocsr_reset_list;
53 int num_nocsr_resets;
54 const char * const *vreg_list;
55 int num_vregs;
56 const unsigned int *regs;
57 unsigned int phy_status;
58 const char * const *clk_list;
59 int num_clks;
60 const char * const *pipe_clk_list;
61 int num_pipe_clks;
62 };
63
64 struct qmp_pcie {
65 struct device *dev;
66 const struct qmp_phy_cfg *cfg;
67 void __iomem **base;
68 struct clk_bulk_data *clks;
69 struct clk_bulk_data *pipe_clks;
70 struct reset_control_bulk_data *nocsr_resets;
71 struct regulator_bulk_data *vregs;
72 struct device **pd_devs;
73 };
74
75 struct qmp_pcie_multiphy {
76 struct phy **phys;
77 const struct qmp_pcie_link_mode_cfg *mode_cfg;
78 int num_pipe_outputs;
79 struct clk_fixed_rate *pipe_out_clks;
80 };
81
82 struct qmp_pcie_link_mode_cfg {
83 const struct qmp_phy_cfg * const *cfgs;
84 u32 num_phys;
85 };
86
87 struct qmp_pcie_match_data {
88 const struct qmp_pcie_link_mode_cfg *mode_cfgs;
89 u32 num_modes;
90 };
91
92 static const char * const glymur_pciephy_clk_l[] = {
93 "aux", "cfg_ahb", "ref", "rchng", "phy_b_aux",
94 };
95
96 static const char * const glymur_pciephy_a_clk_l[] = {
97 "aux", "cfg_ahb", "ref", "rchng",
98 };
99
100 static const char * const glymur_pciephy_b_clk_l[] = {
101 "phy_b_aux", "cfg_ahb_b", "ref", "rchng_b",
102 };
103
104 static const char * const glymur_pciephy_pipeclk_l[] = {
105 "pipe",
106 };
107
108 static const char * const glymur_pipephy_b_pipeclk_l[] = {
109 "pipe_b", "pipediv2_b",
110 };
111
112 static const char * const glymur_vreg_l[] = {
113 "vdda-phy", "vdda-pll", "vdda-refgen0p9", "vdda-refgen1p2",
114 };
115
116 static const char * const glymur_pciephy_a_reg_l[] = {
117 "port_a",
118 };
119
120 static const char * const glymur_pciephy_b_reg_l[] = {
121 "port_b",
122 };
123
124 static const char * const glymur_pciephy_reg_l[] = {
125 "port_a", "port_b",
126 };
127
128 static const char * const glymur_pciephy_a_pd_l[] = {
129 "port_a",
130 };
131
132 static const char * const glymur_pciephy_b_pd_l[] = {
133 "port_b",
134 };
135
136 static const char * const glymur_pciephy_pd_l[] = {
137 "port_a", "port_b",
138 };
139
140 static const char * const glymur_pciephy_a_nocsr_reset_l[] = {
141 "port_a_nocsr",
142 };
143
144 static const char * const glymur_pciephy_nocsr_reset_l[] = {
145 "port_a_nocsr", "port_b_nocsr",
146 };
147
148 static const char * const glymur_pciephy_b_nocsr_reset_l[] = {
149 "port_b_nocsr",
150 };
151
152 static const struct qmp_pcie_offsets glymur_pcie_offsets_v8_50 = {
153 .pcs = 0x9000,
154 };
155
156 static const struct qmp_phy_cfg glymur_qmp_gen5x4_pciephy_a_cfg = {
157 .offsets = &glymur_pcie_offsets_v8_50,
158 .reg_names = glymur_pciephy_a_reg_l,
159 .num_regs = ARRAY_SIZE(glymur_pciephy_a_reg_l),
160 .pd_names = glymur_pciephy_a_pd_l,
161 .num_pds = ARRAY_SIZE(glymur_pciephy_a_pd_l),
162 .nocsr_reset_list = glymur_pciephy_a_nocsr_reset_l,
163 .num_nocsr_resets = ARRAY_SIZE(glymur_pciephy_a_nocsr_reset_l),
164 .vreg_list = glymur_vreg_l,
165 .num_vregs = ARRAY_SIZE(glymur_vreg_l),
166 .regs = pciephy_v8_50_regs_layout,
167 .phy_status = PHYSTATUS_4_20,
168 .pipe_clk_list = glymur_pciephy_pipeclk_l,
169 .num_pipe_clks = ARRAY_SIZE(glymur_pciephy_pipeclk_l),
170 .clk_list = glymur_pciephy_a_clk_l,
171 .num_clks = ARRAY_SIZE(glymur_pciephy_a_clk_l),
172 };
173
174 static const struct qmp_phy_cfg glymur_qmp_gen5x4_pciephy_b_cfg = {
175 .offsets = &glymur_pcie_offsets_v8_50,
176 .reg_names = glymur_pciephy_b_reg_l,
177 .num_regs = ARRAY_SIZE(glymur_pciephy_b_reg_l),
178 .pd_names = glymur_pciephy_b_pd_l,
179 .num_pds = ARRAY_SIZE(glymur_pciephy_b_pd_l),
180 .nocsr_reset_list = glymur_pciephy_b_nocsr_reset_l,
181 .num_nocsr_resets = ARRAY_SIZE(glymur_pciephy_b_nocsr_reset_l),
182 .vreg_list = glymur_vreg_l,
183 .num_vregs = ARRAY_SIZE(glymur_vreg_l),
184 .regs = pciephy_v8_50_regs_layout,
185 .phy_status = PHYSTATUS_4_20,
186 .pipe_clk_list = glymur_pipephy_b_pipeclk_l,
187 .num_pipe_clks = ARRAY_SIZE(glymur_pipephy_b_pipeclk_l),
188 .clk_list = glymur_pciephy_b_clk_l,
189 .num_clks = ARRAY_SIZE(glymur_pciephy_b_clk_l),
190 };
191
192 static const struct qmp_phy_cfg glymur_qmp_gen5x8_pciephy_cfg = {
193 .offsets = &glymur_pcie_offsets_v8_50,
194 .reg_names = glymur_pciephy_reg_l,
195 .num_regs = ARRAY_SIZE(glymur_pciephy_reg_l),
196 .pd_names = glymur_pciephy_pd_l,
197 .num_pds = ARRAY_SIZE(glymur_pciephy_pd_l),
198 .nocsr_reset_list = glymur_pciephy_nocsr_reset_l,
199 .num_nocsr_resets = ARRAY_SIZE(glymur_pciephy_nocsr_reset_l),
200 .vreg_list = glymur_vreg_l,
201 .num_vregs = ARRAY_SIZE(glymur_vreg_l),
202 .regs = pciephy_v8_50_regs_layout,
203 .phy_status = PHYSTATUS_4_20,
204 .pipe_clk_list = glymur_pciephy_pipeclk_l,
205 .num_pipe_clks = ARRAY_SIZE(glymur_pciephy_pipeclk_l),
206 .clk_list = glymur_pciephy_clk_l,
207 .num_clks = ARRAY_SIZE(glymur_pciephy_clk_l),
208 };
209
210 static const struct qmp_phy_cfg * const glymur_qmp_gen5x8_mode_x8_cfgs[] = {
211 &glymur_qmp_gen5x8_pciephy_cfg,
212 };
213
214 static const struct qmp_phy_cfg * const glymur_qmp_gen5x8_mode_x4x4_cfgs[] = {
215 &glymur_qmp_gen5x4_pciephy_a_cfg,
216 &glymur_qmp_gen5x4_pciephy_b_cfg,
217 };
218
219 static const struct qmp_pcie_link_mode_cfg glymur_qmp_gen5x8_mode_cfgs[] = {
220 [QMP_PCIE_GLYMUR_MODE_X8] = {
221 .cfgs = glymur_qmp_gen5x8_mode_x8_cfgs,
222 .num_phys = ARRAY_SIZE(glymur_qmp_gen5x8_mode_x8_cfgs),
223 },
224 [QMP_PCIE_GLYMUR_MODE_X4X4] = {
225 .cfgs = glymur_qmp_gen5x8_mode_x4x4_cfgs,
226 .num_phys = ARRAY_SIZE(glymur_qmp_gen5x8_mode_x4x4_cfgs),
227 },
228 };
229
230 static const struct qmp_pcie_match_data glymur_qmp_gen5x8_match_data = {
231 .mode_cfgs = glymur_qmp_gen5x8_mode_cfgs,
232 .num_modes = ARRAY_SIZE(glymur_qmp_gen5x8_mode_cfgs),
233 };
234
qmp_pcie_pd_power_on(struct qmp_pcie * qmp)235 static int qmp_pcie_pd_power_on(struct qmp_pcie *qmp)
236 {
237 const struct qmp_phy_cfg *cfg = qmp->cfg;
238 int i, ret;
239
240 for (i = 0; i < cfg->num_pds; i++) {
241 ret = pm_runtime_resume_and_get(qmp->pd_devs[i]);
242 if (ret < 0) {
243 dev_err(qmp->dev, "failed to power on %s domain: %d\n",
244 cfg->pd_names[i], ret);
245 goto err_power_off;
246 }
247 }
248
249 return 0;
250
251 err_power_off:
252 while (--i >= 0)
253 pm_runtime_put(qmp->pd_devs[i]);
254
255 return ret;
256 }
257
qmp_pcie_pd_power_off(struct qmp_pcie * qmp)258 static void qmp_pcie_pd_power_off(struct qmp_pcie *qmp)
259 {
260 const struct qmp_phy_cfg *cfg = qmp->cfg;
261 int i;
262
263 for (i = cfg->num_pds - 1; i >= 0; i--)
264 pm_runtime_put(qmp->pd_devs[i]);
265 }
266
qmp_pcie_init(struct phy * phy)267 static int qmp_pcie_init(struct phy *phy)
268 {
269 struct qmp_pcie *qmp = phy_get_drvdata(phy);
270 const struct qmp_phy_cfg *cfg = qmp->cfg;
271 int ret;
272
273 ret = qmp_pcie_pd_power_on(qmp);
274 if (ret)
275 return ret;
276
277 ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
278 if (ret) {
279 dev_err(qmp->dev, "failed to enable regulators: %d\n", ret);
280 goto err_pd_power_off;
281 }
282
283 ret = reset_control_bulk_assert(qmp->cfg->num_nocsr_resets, qmp->nocsr_resets);
284 if (ret) {
285 dev_err(qmp->dev, "no-csr reset assert failed: %d\n", ret);
286 goto err_disable_regulators;
287 }
288
289 usleep_range(200, 300);
290
291 ret = clk_bulk_prepare_enable(qmp->cfg->num_clks, qmp->clks);
292 if (ret)
293 goto err_disable_regulators;
294
295 return 0;
296
297 err_disable_regulators:
298 regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
299 err_pd_power_off:
300 qmp_pcie_pd_power_off(qmp);
301
302 return ret;
303 }
304
qmp_pcie_exit(struct phy * phy)305 static int qmp_pcie_exit(struct phy *phy)
306 {
307 struct qmp_pcie *qmp = phy_get_drvdata(phy);
308 const struct qmp_phy_cfg *cfg = qmp->cfg;
309
310 reset_control_bulk_assert(qmp->cfg->num_nocsr_resets, qmp->nocsr_resets);
311
312 clk_bulk_disable_unprepare(qmp->cfg->num_clks, qmp->clks);
313 regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
314 qmp_pcie_pd_power_off(qmp);
315
316 return 0;
317 }
318
qmp_pcie_power_on(struct phy * phy)319 static int qmp_pcie_power_on(struct phy *phy)
320 {
321 struct qmp_pcie *qmp = phy_get_drvdata(phy);
322 const struct qmp_phy_cfg *cfg = qmp->cfg;
323 const struct qmp_pcie_offsets *offs = cfg->offsets;
324 void __iomem *status;
325 unsigned int val;
326 int i, ret;
327
328 ret = clk_bulk_prepare_enable(qmp->cfg->num_pipe_clks, qmp->pipe_clks);
329 if (ret)
330 return ret;
331
332 ret = reset_control_bulk_deassert(qmp->cfg->num_nocsr_resets, qmp->nocsr_resets);
333 if (ret) {
334 dev_err(qmp->dev, "no-csr reset deassert failed: %d\n", ret);
335 goto err_disable_pipe_clk;
336 }
337
338 for (i = 0; i < cfg->num_regs; i++) {
339 status = qmp->base[i] + offs->pcs + cfg->regs[QPHY_PCS_STATUS];
340 ret = readl_poll_timeout(status, val, !(val & cfg->phy_status), 200,
341 PHY_INIT_COMPLETE_TIMEOUT_US);
342 if (ret) {
343 dev_err(qmp->dev, "PHY power on timed-out (%s): %d\n",
344 cfg->reg_names[i], ret);
345 goto err_disable_pipe_clk;
346 }
347 }
348
349 return 0;
350
351 err_disable_pipe_clk:
352 clk_bulk_disable_unprepare(qmp->cfg->num_pipe_clks, qmp->pipe_clks);
353
354 return ret;
355 }
356
qmp_pcie_power_off(struct phy * phy)357 static int qmp_pcie_power_off(struct phy *phy)
358 {
359 struct qmp_pcie *qmp = phy_get_drvdata(phy);
360
361 clk_bulk_disable_unprepare(qmp->cfg->num_pipe_clks, qmp->pipe_clks);
362
363 return 0;
364 }
365
qmp_pcie_enable(struct phy * phy)366 static int qmp_pcie_enable(struct phy *phy)
367 {
368 int ret;
369
370 ret = qmp_pcie_init(phy);
371 if (ret)
372 return ret;
373
374 ret = qmp_pcie_power_on(phy);
375 if (ret)
376 qmp_pcie_exit(phy);
377
378 return ret;
379 }
380
qmp_pcie_disable(struct phy * phy)381 static int qmp_pcie_disable(struct phy *phy)
382 {
383 int ret;
384
385 ret = qmp_pcie_power_off(phy);
386 if (ret)
387 return ret;
388
389 return qmp_pcie_exit(phy);
390 }
391
392 static const struct phy_ops qmp_pcie_phy_ops = {
393 .power_on = qmp_pcie_enable,
394 .power_off = qmp_pcie_disable,
395 .owner = THIS_MODULE,
396 };
397
qmp_pcie_pd_detach(void * data)398 static void qmp_pcie_pd_detach(void *data)
399 {
400 struct qmp_pcie *qmp = data;
401 const struct qmp_phy_cfg *cfg = qmp->cfg;
402 int i;
403
404 for (i = 0; i < cfg->num_pds; i++) {
405 if (!IS_ERR_OR_NULL(qmp->pd_devs[i]))
406 dev_pm_domain_detach(qmp->pd_devs[i], true);
407 }
408 }
409
qmp_pcie_pd_init(struct qmp_pcie * qmp)410 static int qmp_pcie_pd_init(struct qmp_pcie *qmp)
411 {
412 const struct qmp_phy_cfg *cfg = qmp->cfg;
413 struct device *dev = qmp->dev;
414 int i, ret;
415
416 if (!cfg->num_pds)
417 return 0;
418
419 qmp->pd_devs = devm_kcalloc(dev, cfg->num_pds, sizeof(*qmp->pd_devs),
420 GFP_KERNEL);
421 if (!qmp->pd_devs)
422 return -ENOMEM;
423
424 for (i = 0; i < cfg->num_pds; i++) {
425 qmp->pd_devs[i] = dev_pm_domain_attach_by_name(dev,
426 cfg->pd_names[i]);
427 if (IS_ERR_OR_NULL(qmp->pd_devs[i])) {
428 ret = PTR_ERR(qmp->pd_devs[i]) ? : -ENODATA;
429 goto err_detach;
430 }
431 }
432
433 return devm_add_action_or_reset(dev, qmp_pcie_pd_detach, qmp);
434
435 err_detach:
436 while (--i >= 0)
437 dev_pm_domain_detach(qmp->pd_devs[i], false);
438
439 return ret;
440 }
441
qmp_pcie_vreg_init(struct qmp_pcie * qmp)442 static int qmp_pcie_vreg_init(struct qmp_pcie *qmp)
443 {
444 const struct qmp_phy_cfg *cfg = qmp->cfg;
445 struct device *dev = qmp->dev;
446 int i;
447
448 qmp->vregs = devm_kcalloc(dev, cfg->num_vregs, sizeof(*qmp->vregs),
449 GFP_KERNEL);
450 if (!qmp->vregs)
451 return -ENOMEM;
452
453 for (i = 0; i < cfg->num_vregs; i++)
454 qmp->vregs[i].supply = cfg->vreg_list[i];
455
456 return devm_regulator_bulk_get(dev, cfg->num_vregs, qmp->vregs);
457 }
458
qmp_pcie_reset_init(struct qmp_pcie * qmp)459 static int qmp_pcie_reset_init(struct qmp_pcie *qmp)
460 {
461 const struct qmp_phy_cfg *cfg = qmp->cfg;
462 struct device *dev = qmp->dev;
463 int i, ret;
464
465 qmp->nocsr_resets = devm_kcalloc(dev, cfg->num_nocsr_resets,
466 sizeof(*qmp->nocsr_resets),
467 GFP_KERNEL);
468 if (!qmp->nocsr_resets)
469 return -ENOMEM;
470
471 for (i = 0; i < cfg->num_nocsr_resets; i++)
472 qmp->nocsr_resets[i].id = cfg->nocsr_reset_list[i];
473
474 ret = devm_reset_control_bulk_get_exclusive(dev,
475 cfg->num_nocsr_resets,
476 qmp->nocsr_resets);
477 if (ret)
478 return dev_err_probe(dev, ret, "failed to get no-csr resets\n");
479
480 return 0;
481 }
482
qmp_pcie_clk_init(struct qmp_pcie * qmp)483 static int qmp_pcie_clk_init(struct qmp_pcie *qmp)
484 {
485 const struct qmp_phy_cfg *cfg = qmp->cfg;
486 struct device *dev = qmp->dev;
487 int i, ret;
488
489 qmp->clks = devm_kcalloc(dev, cfg->num_clks, sizeof(*qmp->clks),
490 GFP_KERNEL);
491 if (!qmp->clks)
492 return -ENOMEM;
493
494 for (i = 0; i < cfg->num_clks; i++)
495 qmp->clks[i].id = cfg->clk_list[i];
496
497 ret = devm_clk_bulk_get_optional(dev, cfg->num_clks, qmp->clks);
498 if (ret)
499 return ret;
500
501 qmp->pipe_clks = devm_kcalloc(dev, cfg->num_pipe_clks,
502 sizeof(*qmp->pipe_clks), GFP_KERNEL);
503 if (!qmp->pipe_clks)
504 return -ENOMEM;
505
506 for (i = 0; i < cfg->num_pipe_clks; i++)
507 qmp->pipe_clks[i].id = cfg->pipe_clk_list[i];
508
509 return devm_clk_bulk_get_optional(dev, cfg->num_pipe_clks,
510 qmp->pipe_clks);
511 }
512
__phy_pipe_clk_register(struct device * dev,struct device_node * np,int idx,struct clk_fixed_rate * fixed)513 static int __phy_pipe_clk_register(struct device *dev, struct device_node *np,
514 int idx, struct clk_fixed_rate *fixed)
515 {
516 struct clk_init_data init = { };
517 int ret;
518
519 ret = of_property_read_string_index(np, "clock-output-names", idx,
520 &init.name);
521 if (ret) {
522 dev_err(dev, "%pOFn: No clock-output-names\n", np);
523 return ret;
524 }
525
526 init.ops = &clk_fixed_rate_ops;
527
528 fixed->fixed_rate = 125000000;
529
530 fixed->hw.init = &init;
531
532 return devm_clk_hw_register(dev, &fixed->hw);
533 }
534
535 static struct clk_hw *
qmp_pcie_multiphy_clk_hw_get(struct of_phandle_args * clkspec,void * data)536 qmp_pcie_multiphy_clk_hw_get(struct of_phandle_args *clkspec, void *data)
537 {
538 struct qmp_pcie_multiphy *qmp_data = data;
539 unsigned int idx = 0;
540
541 if (clkspec->args_count)
542 idx = clkspec->args[0];
543
544 if (idx < (unsigned int)qmp_data->num_pipe_outputs)
545 return &qmp_data->pipe_out_clks[idx].hw;
546
547 return ERR_PTR(-EINVAL);
548 }
549
qmp_pcie_multiphy_register_clocks(struct device * dev,struct device_node * np,struct qmp_pcie_multiphy * qmp_data)550 static int qmp_pcie_multiphy_register_clocks(struct device *dev,
551 struct device_node *np,
552 struct qmp_pcie_multiphy *qmp_data)
553 {
554 int num_pipe_outputs;
555 int i, ret;
556
557 num_pipe_outputs = of_property_count_strings(np, "clock-output-names");
558
559 qmp_data->num_pipe_outputs = num_pipe_outputs;
560 qmp_data->pipe_out_clks = devm_kcalloc(dev, num_pipe_outputs,
561 sizeof(*qmp_data->pipe_out_clks),
562 GFP_KERNEL);
563 if (!qmp_data->pipe_out_clks)
564 return -ENOMEM;
565
566 for (i = 0; i < num_pipe_outputs; i++) {
567 ret = __phy_pipe_clk_register(dev, np, i,
568 &qmp_data->pipe_out_clks[i]);
569 if (ret)
570 return ret;
571 }
572
573 return devm_of_clk_add_hw_provider(dev, qmp_pcie_multiphy_clk_hw_get, qmp_data);
574 }
575
qmp_pcie_get_mmio(struct qmp_pcie * qmp)576 static int qmp_pcie_get_mmio(struct qmp_pcie *qmp)
577 {
578 struct platform_device *pdev = to_platform_device(qmp->dev);
579 const struct qmp_phy_cfg *cfg = qmp->cfg;
580 struct device *dev = qmp->dev;
581 void __iomem *base;
582 int i;
583
584 qmp->base = devm_kcalloc(dev, cfg->num_regs, sizeof(*qmp->base),
585 GFP_KERNEL);
586 if (!qmp->base)
587 return -ENOMEM;
588
589 for (i = 0; i < cfg->num_regs; i++) {
590 base = devm_platform_ioremap_resource_byname(pdev, cfg->reg_names[i]);
591 if (IS_ERR(base))
592 return PTR_ERR(base);
593
594 qmp->base[i] = base;
595 }
596
597 return 0;
598 }
599
qmp_pcie_read_link_mode(struct device * dev,unsigned int * link_mode)600 static int qmp_pcie_read_link_mode(struct device *dev, unsigned int *link_mode)
601 {
602 struct regmap *map;
603 unsigned int args[1];
604
605 map = syscon_regmap_lookup_by_phandle_args(dev->of_node, "qcom,link-mode",
606 ARRAY_SIZE(args), args);
607 if (IS_ERR(map))
608 return PTR_ERR(map);
609
610 return regmap_read(map, args[0], link_mode);
611 }
612
qmp_pcie_multiphy_xlate(struct device * dev,const struct of_phandle_args * args)613 static struct phy *qmp_pcie_multiphy_xlate(struct device *dev,
614 const struct of_phandle_args *args)
615 {
616 struct qmp_pcie_multiphy *qmp_data = dev_get_drvdata(dev);
617 unsigned int idx;
618
619 if (!qmp_data || args->args_count < 1)
620 return ERR_PTR(-EINVAL);
621
622 idx = args->args[0];
623
624 if (idx < (unsigned int)qmp_data->mode_cfg->num_phys)
625 return qmp_data->phys[idx] ?: ERR_PTR(-EINVAL);
626
627 return ERR_PTR(-EINVAL);
628 }
629
qmp_pcie_probe_phy(struct qmp_pcie * qmp,struct device_node * np,struct phy ** out_phy)630 static int qmp_pcie_probe_phy(struct qmp_pcie *qmp, struct device_node *np,
631 struct phy **out_phy)
632 {
633 int ret;
634
635 ret = qmp_pcie_get_mmio(qmp);
636 if (ret)
637 return ret;
638
639 ret = qmp_pcie_clk_init(qmp);
640 if (ret)
641 return ret;
642
643 ret = qmp_pcie_reset_init(qmp);
644 if (ret)
645 return ret;
646
647 ret = qmp_pcie_vreg_init(qmp);
648 if (ret)
649 return ret;
650
651 ret = qmp_pcie_pd_init(qmp);
652 if (ret)
653 return ret;
654
655 *out_phy = devm_phy_create(qmp->dev, np, &qmp_pcie_phy_ops);
656 if (IS_ERR(*out_phy))
657 return PTR_ERR(*out_phy);
658
659 phy_set_drvdata(*out_phy, qmp);
660
661 return 0;
662 }
663
qmp_pcie_multiphy_probe(struct platform_device * pdev)664 static int qmp_pcie_multiphy_probe(struct platform_device *pdev)
665 {
666 const struct qmp_pcie_match_data *match_data;
667 struct qmp_pcie_multiphy *qmp_data;
668 struct phy_provider *phy_provider;
669 struct device *dev = &pdev->dev;
670 unsigned int link_mode;
671 struct qmp_pcie *qmp;
672 struct phy **phys;
673 int phy_index;
674 int ret;
675
676 qmp_data = devm_kzalloc(dev, sizeof(*qmp_data), GFP_KERNEL);
677
678 match_data = of_device_get_match_data(dev);
679 if (!match_data)
680 return -EINVAL;
681
682 if (!qmp_data)
683 return -ENOMEM;
684
685 ret = qmp_pcie_read_link_mode(dev, &link_mode);
686 if (ret)
687 return dev_err_probe(dev, ret, "failed to read qcom,link-mode\n");
688
689 if (link_mode >= match_data->num_modes)
690 return dev_err_probe(dev, -EINVAL, "invalid qcom,link-mode: %u\n",
691 link_mode);
692
693 qmp_data->mode_cfg = &match_data->mode_cfgs[link_mode];
694
695 qmp = devm_kcalloc(dev, qmp_data->mode_cfg->num_phys, sizeof(*qmp), GFP_KERNEL);
696 if (!qmp)
697 return -ENOMEM;
698
699 phys = devm_kcalloc(dev, qmp_data->mode_cfg->num_phys, sizeof(*phys), GFP_KERNEL);
700 if (!phys)
701 return -ENOMEM;
702
703 qmp_data->phys = phys;
704 dev_set_drvdata(dev, qmp_data);
705
706 for (phy_index = 0; phy_index < qmp_data->mode_cfg->num_phys; phy_index++) {
707 qmp[phy_index].dev = dev;
708 qmp[phy_index].cfg = qmp_data->mode_cfg->cfgs[phy_index];
709 ret = qmp_pcie_probe_phy(&qmp[phy_index], dev->of_node, &phys[phy_index]);
710 if (ret)
711 return ret;
712 }
713
714 ret = qmp_pcie_multiphy_register_clocks(dev, dev->of_node, qmp_data);
715 if (ret)
716 return ret;
717
718 phy_provider = devm_of_phy_provider_register(dev, qmp_pcie_multiphy_xlate);
719
720 return PTR_ERR_OR_ZERO(phy_provider);
721 }
722
723 static const struct of_device_id qmp_pcie_multiphy_of_match_table[] = {
724 {
725 .compatible = "qcom,glymur-qmp-gen5x8-pcie-phy",
726 .data = &glymur_qmp_gen5x8_match_data,
727 },
728 { }
729 };
730 MODULE_DEVICE_TABLE(of, qmp_pcie_multiphy_of_match_table);
731
732 static struct platform_driver qmp_pcie_multiphy_driver = {
733 .probe = qmp_pcie_multiphy_probe,
734 .driver = {
735 .name = "qcom-qmp-pcie-multiphy",
736 .of_match_table = qmp_pcie_multiphy_of_match_table,
737 },
738 };
739 module_platform_driver(qmp_pcie_multiphy_driver);
740
741 MODULE_AUTHOR("Qiang Yu <qiang.yu@oss.qualcomm.com>");
742 MODULE_DESCRIPTION("Qualcomm QMP PCIe Multi-PHY driver for Glymur");
743 MODULE_LICENSE("GPL");
744