xref: /linux/drivers/phy/qualcomm/phy-qcom-qmp-pcie-multiphy.c (revision 16e6a1a3cb3fa5fa11cd76a9d71235d927923329)
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