xref: /rk3399_rockchip-uboot/drivers/phy/phy-rockchip-naneng-combphy.c (revision cc9876f42ce8a1db06e33086fdb242c362c3b43d)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Rockchip USB3.0/PCIe Gen2/SATA/SGMII combphy driver
4  *
5  * Copyright (C) 2021 Rockchip Electronics Co., Ltd.
6  */
7 
8 #include <common.h>
9 #include <clk.h>
10 #include <dm.h>
11 #include <dm/lists.h>
12 #include <dt-bindings/phy/phy.h>
13 #include <generic-phy.h>
14 #include <syscon.h>
15 #include <asm/io.h>
16 #include <asm/arch/clock.h>
17 #include <regmap.h>
18 #include <reset-uclass.h>
19 
20 #define BIT_WRITEABLE_SHIFT		16
21 
22 struct rockchip_combphy_priv;
23 
24 struct combphy_reg {
25 	u32 offset;
26 	u16 bitend;
27 	u16 bitstart;
28 	u16 disable;
29 	u16 enable;
30 };
31 
32 struct rockchip_combphy_grfcfg {
33 	struct combphy_reg pcie_mode_set;
34 	struct combphy_reg usb_mode_set;
35 	struct combphy_reg sgmii_mode_set;
36 	struct combphy_reg qsgmii_mode_set;
37 	struct combphy_reg pipe_rxterm_set;
38 	struct combphy_reg pipe_txelec_set;
39 	struct combphy_reg pipe_txcomp_set;
40 	struct combphy_reg pipe_clk_24m;
41 	struct combphy_reg pipe_clk_25m;
42 	struct combphy_reg pipe_clk_100m;
43 	struct combphy_reg pipe_phymode_sel;
44 	struct combphy_reg pipe_rate_sel;
45 	struct combphy_reg pipe_rxterm_sel;
46 	struct combphy_reg pipe_txelec_sel;
47 	struct combphy_reg pipe_txcomp_sel;
48 	struct combphy_reg pipe_clk_ext;
49 	struct combphy_reg pipe_sel_usb;
50 	struct combphy_reg pipe_sel_qsgmii;
51 	struct combphy_reg pipe_phy_status;
52 	struct combphy_reg con0_for_pcie;
53 	struct combphy_reg con1_for_pcie;
54 	struct combphy_reg con2_for_pcie;
55 	struct combphy_reg con3_for_pcie;
56 	struct combphy_reg con0_for_sata;
57 	struct combphy_reg con1_for_sata;
58 	struct combphy_reg con2_for_sata;
59 	struct combphy_reg con3_for_sata;
60 	struct combphy_reg pipe_con0_for_sata;
61 	struct combphy_reg pipe_con1_for_sata;
62 	struct combphy_reg pipe_sgmii_mac_sel;
63 	struct combphy_reg pipe_xpcs_phy_ready;
64 	struct combphy_reg u3otg0_port_en;
65 	struct combphy_reg u3otg1_port_en;
66 };
67 
68 struct rockchip_combphy_cfg {
69 	const struct rockchip_combphy_grfcfg *grfcfg;
70 	int (*combphy_cfg)(struct rockchip_combphy_priv *priv);
71 };
72 
73 struct rockchip_combphy_priv {
74 	u32 mode;
75 	void __iomem *mmio;
76 	struct udevice *dev;
77 	struct regmap *pipe_grf;
78 	struct regmap *phy_grf;
79 	struct phy *phy;
80 	struct reset_ctl phy_rst;
81 	struct clk ref_clk;
82 	const struct rockchip_combphy_cfg *cfg;
83 };
84 
85 static int param_write(struct regmap *base,
86 		       const struct combphy_reg *reg, bool en)
87 {
88 	u32 val, mask, tmp;
89 
90 	tmp = en ? reg->enable : reg->disable;
91 	mask = GENMASK(reg->bitend, reg->bitstart);
92 	val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT);
93 
94 	return regmap_write(base, reg->offset, val);
95 }
96 
97 static int rockchip_combphy_pcie_init(struct rockchip_combphy_priv *priv)
98 {
99 	int ret = 0;
100 
101 	if (priv->cfg->combphy_cfg) {
102 		ret = priv->cfg->combphy_cfg(priv);
103 		if (ret) {
104 			dev_err(priv->dev, "failed to init phy for pcie\n");
105 			return ret;
106 		}
107 	}
108 
109 	return ret;
110 }
111 
112 static int rockchip_combphy_usb3_init(struct rockchip_combphy_priv *priv)
113 {
114 	int ret = 0;
115 
116 	if (priv->cfg->combphy_cfg) {
117 		ret = priv->cfg->combphy_cfg(priv);
118 		if (ret) {
119 			dev_err(priv->dev, "failed to init phy for usb3\n");
120 			return ret;
121 		}
122 	}
123 
124 	return ret;
125 }
126 
127 static int rockchip_combphy_sata_init(struct rockchip_combphy_priv *priv)
128 {
129 	int ret = 0;
130 
131 	if (priv->cfg->combphy_cfg) {
132 		ret = priv->cfg->combphy_cfg(priv);
133 		if (ret) {
134 			dev_err(priv->dev, "failed to init phy for sata\n");
135 			return ret;
136 		}
137 	}
138 
139 	return ret;
140 }
141 
142 static int rockchip_combphy_sgmii_init(struct rockchip_combphy_priv *priv)
143 {
144 	int ret = 0;
145 
146 	if (priv->cfg->combphy_cfg) {
147 		ret = priv->cfg->combphy_cfg(priv);
148 		if (ret) {
149 			dev_err(priv->dev, "failed to init phy for sgmii\n");
150 			return ret;
151 		}
152 	}
153 
154 	return ret;
155 }
156 
157 static int rockchip_combphy_set_mode(struct rockchip_combphy_priv *priv)
158 {
159 	switch (priv->mode) {
160 	case PHY_TYPE_PCIE:
161 		rockchip_combphy_pcie_init(priv);
162 		break;
163 	case PHY_TYPE_USB3:
164 		rockchip_combphy_usb3_init(priv);
165 		break;
166 	case PHY_TYPE_SATA:
167 		rockchip_combphy_sata_init(priv);
168 		break;
169 	case PHY_TYPE_SGMII:
170 	case PHY_TYPE_QSGMII:
171 		return rockchip_combphy_sgmii_init(priv);
172 	default:
173 		dev_err(priv->dev, "incompatible PHY type\n");
174 		return -EINVAL;
175 	}
176 
177 	return 0;
178 }
179 
180 static int rockchip_combphy_init(struct phy *phy)
181 {
182 	struct rockchip_combphy_priv *priv = dev_get_priv(phy->dev);
183 	int ret;
184 
185 	ret = clk_enable(&priv->ref_clk);
186 	if (ret < 0 && ret != -ENOSYS)
187 		return ret;
188 
189 	ret = rockchip_combphy_set_mode(priv);
190 	if (ret)
191 		goto err_clk;
192 
193 	reset_deassert(&priv->phy_rst);
194 
195 	return 0;
196 
197 err_clk:
198 	clk_disable(&priv->ref_clk);
199 
200 	return ret;
201 }
202 
203 static int rockchip_combphy_exit(struct phy *phy)
204 {
205 	struct rockchip_combphy_priv *priv = dev_get_priv(phy->dev);
206 
207 	clk_disable(&priv->ref_clk);
208 	reset_assert(&priv->phy_rst);
209 
210 	return 0;
211 }
212 
213 static int rockchip_combphy_xlate(struct phy *phy, struct ofnode_phandle_args *args)
214 {
215 	struct rockchip_combphy_priv *priv = dev_get_priv(phy->dev);
216 
217 	if (args->args_count != 1) {
218 		pr_err("invalid number of arguments\n");
219 		return -EINVAL;
220 	}
221 
222 	priv->mode = args->args[0];
223 
224 	return 0;
225 }
226 
227 static const struct phy_ops rochchip_combphy_ops = {
228 	.init = rockchip_combphy_init,
229 	.exit = rockchip_combphy_exit,
230 	.of_xlate = rockchip_combphy_xlate,
231 };
232 
233 static int rockchip_combphy_parse_dt(struct udevice *dev,
234 				     struct rockchip_combphy_priv *priv)
235 {
236 	struct udevice *syscon;
237 	int ret;
238 	u32 vals[4];
239 
240 	ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, "rockchip,pipe-grf", &syscon);
241 	if (ret) {
242 		dev_err(dev, "failed to find peri_ctrl pipe-grf regmap ret= %d\n", ret);
243 		return ret;
244 	}
245 	priv->pipe_grf = syscon_get_regmap(syscon);
246 
247 	ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, "rockchip,pipe-phy-grf", &syscon);
248 	if (ret) {
249 		dev_err(dev, "failed to find peri_ctrl pipe-phy-grf regmap\n");
250 		return ret;
251 	}
252 	priv->phy_grf = syscon_get_regmap(syscon);
253 
254 	ret = clk_get_by_index(dev, 0, &priv->ref_clk);
255 	if (ret) {
256 		dev_err(dev, "failed to find ref clock\n");
257 		return PTR_ERR(&priv->ref_clk);
258 	}
259 
260 	ret = reset_get_by_name(dev, "combphy", &priv->phy_rst);
261 	if (ret) {
262 		dev_err(dev, "no phy reset control specified\n");
263 		return ret;
264 	}
265 
266 	if (!dev_read_u32_array(dev, "rockchip,pcie1ln-sel-bits",
267 				vals, ARRAY_SIZE(vals)))
268 		regmap_write(priv->pipe_grf, vals[0],
269 			     (GENMASK(vals[2], vals[1]) << 16) | vals[3]);
270 
271 	return 0;
272 }
273 
274 static int rockchip_combphy_probe(struct udevice *udev)
275 {
276 	struct rockchip_combphy_priv *priv = dev_get_priv(udev);
277 	const struct rockchip_combphy_cfg *phy_cfg;
278 
279 	priv->mmio = (void __iomem *)dev_read_addr(udev);
280 	if (IS_ERR(priv->mmio))
281 		return PTR_ERR(priv->mmio);
282 
283 	phy_cfg = (const struct rockchip_combphy_cfg *)dev_get_driver_data(udev);
284 	if (!phy_cfg) {
285 		dev_err(udev, "No OF match data provided\n");
286 		return -EINVAL;
287 	}
288 
289 	priv->dev = udev;
290 	priv->mode = PHY_TYPE_SATA;
291 	priv->cfg = phy_cfg;
292 
293 	return rockchip_combphy_parse_dt(udev, priv);
294 }
295 
296 static int rk3528_combphy_cfg(struct rockchip_combphy_priv *priv)
297 {
298 	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
299 	u32 val;
300 
301 	switch (priv->mode) {
302 	case PHY_TYPE_PCIE:
303 		/* Set SSC downward spread spectrum */
304 		val = readl(priv->mmio + 0x18);
305 		val &= ~GENMASK(5, 4);
306 		val |= 0x01 << 4;
307 		writel(val, priv->mmio + 0x18);
308 
309 		param_write(priv->phy_grf, &cfg->con0_for_pcie, true);
310 		param_write(priv->phy_grf, &cfg->con1_for_pcie, true);
311 		param_write(priv->phy_grf, &cfg->con2_for_pcie, true);
312 		param_write(priv->phy_grf, &cfg->con3_for_pcie, true);
313 		break;
314 	case PHY_TYPE_USB3:
315 		/* Set SSC downward spread spectrum */
316 		val = readl(priv->mmio + 0x18);
317 		val &= ~GENMASK(5, 4);
318 		val |= 0x01 << 4;
319 		writel(val, priv->mmio + 0x18);
320 
321 		/* Enable adaptive CTLE for USB3.0 Rx */
322 		val = readl(priv->mmio + 0x200);
323 		val &= ~GENMASK(17, 17);
324 		val |= 0x01;
325 		writel(val, priv->mmio + 0x200);
326 
327 		param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false);
328 		param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false);
329 		param_write(priv->phy_grf, &cfg->usb_mode_set, true);
330 		break;
331 	default:
332 		dev_err(priv->dev, "incompatible PHY type\n");
333 		return -EINVAL;
334 	}
335 
336 	param_write(priv->phy_grf, &cfg->pipe_clk_100m, true);
337 	if (priv->mode == PHY_TYPE_PCIE) {
338 		/* PLL KVCO tuning fine */
339 		val = readl(priv->mmio + 0x18);
340 		val &= ~(0x7 << 10);
341 		val |= 0x2 << 10;
342 		writel(val, priv->mmio + 0x18);
343 
344 		/* su_trim[6:4]=111, [10:7]=1001, [2:0]=000 */
345 		val = readl(priv->mmio + 0x108);
346 		val &= ~(0x7f7);
347 		val |= 0x4f0;
348 		writel(val, priv->mmio + 0x108);
349 	}
350 
351 	return 0;
352 }
353 
354 static const struct rockchip_combphy_grfcfg rk3528_combphy_grfcfgs = {
355 	/* pipe-phy-grf */
356 	.pcie_mode_set		= { 0x48000, 5, 0, 0x00, 0x11 },
357 	.usb_mode_set		= { 0x48000, 5, 0, 0x00, 0x04 },
358 	.pipe_rxterm_set	= { 0x48000, 12, 12, 0x00, 0x01 },
359 	.pipe_txelec_set	= { 0x48004, 1, 1, 0x00, 0x01 },
360 	.pipe_txcomp_set	= { 0x48004, 4, 4, 0x00, 0x01 },
361 	.pipe_clk_24m		= { 0x48004, 14, 13, 0x00, 0x00 },
362 	.pipe_clk_100m		= { 0x48004, 14, 13, 0x00, 0x02 },
363 	.pipe_rxterm_sel	= { 0x48008, 8, 8, 0x00, 0x01 },
364 	.pipe_txelec_sel	= { 0x48008, 12, 12, 0x00, 0x01 },
365 	.pipe_txcomp_sel	= { 0x48008, 15, 15, 0x00, 0x01 },
366 	.pipe_clk_ext		= { 0x4800c, 9, 8, 0x02, 0x01 },
367 	.pipe_phy_status	= { 0x48034, 6, 6, 0x01, 0x00 },
368 	.con0_for_pcie		= { 0x48000, 15, 0, 0x00, 0x110 },
369 	.con1_for_pcie		= { 0x48004, 15, 0, 0x00, 0x00 },
370 	.con2_for_pcie		= { 0x48008, 15, 0, 0x00, 0x101 },
371 	.con3_for_pcie		= { 0x4800c, 15, 0, 0x00, 0x0200 },
372 	/* pipe-grf */
373 	.u3otg0_port_en		= { 0x40044, 15, 0, 0x0181, 0x1100 },
374 };
375 
376 static const struct rockchip_combphy_cfg rk3528_combphy_cfgs = {
377 	.grfcfg		= &rk3528_combphy_grfcfgs,
378 	.combphy_cfg	= rk3528_combphy_cfg,
379 };
380 
381 static int rk3562_combphy_cfg(struct rockchip_combphy_priv *priv)
382 {
383 	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
384 	u32 val;
385 
386 	switch (priv->mode) {
387 	case PHY_TYPE_PCIE:
388 		/* Set SSC downward spread spectrum */
389 		val = readl(priv->mmio + (0x1f << 2));
390 		val &= ~GENMASK(5, 4);
391 		val |= 0x01 << 4;
392 		writel(val, priv->mmio + 0x7c);
393 
394 		param_write(priv->phy_grf, &cfg->con0_for_pcie, true);
395 		param_write(priv->phy_grf, &cfg->con1_for_pcie, true);
396 		param_write(priv->phy_grf, &cfg->con2_for_pcie, true);
397 		param_write(priv->phy_grf, &cfg->con3_for_pcie, true);
398 		break;
399 	case PHY_TYPE_USB3:
400 		/* Set SSC downward spread spectrum */
401 		val = readl(priv->mmio + (0x1f << 2));
402 		val &= ~GENMASK(5, 4);
403 		val |= 0x01 << 4;
404 		writel(val, priv->mmio + 0x7c);
405 
406 		/* Enable adaptive CTLE for USB3.0 Rx */
407 		val = readl(priv->mmio + (0x0e << 2));
408 		val &= ~GENMASK(0, 0);
409 		val |= 0x01;
410 		writel(val, priv->mmio + (0x0e << 2));
411 
412 		/* Set PLL KVCO fine tuning signals */
413 		val = readl(priv->mmio + (0x20 << 2));
414 		val &= ~(0x7 << 2);
415 		val |= 0x2 << 2;
416 		writel(val, priv->mmio + (0x20 << 2));
417 
418 		/* Set PLL LPF R1 to su_trim[10:7]=1001 */
419 		writel(0x4, priv->mmio + (0xb << 2));
420 
421 		/* Set PLL input clock divider 1/2 */
422 		val = readl(priv->mmio + (0x5 << 2));
423 		val &= ~(0x3 << 6);
424 		val |= 0x1 << 6;
425 		writel(val, priv->mmio + (0x5 << 2));
426 
427 		/* Set PLL loop divider */
428 		writel(0x32, priv->mmio + (0x11 << 2));
429 
430 		/* Set PLL KVCO to min and set PLL charge pump current to max */
431 		writel(0xf0, priv->mmio + (0xa << 2));
432 
433 		param_write(priv->phy_grf, &cfg->pipe_sel_usb, true);
434 		param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false);
435 		param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false);
436 		param_write(priv->phy_grf, &cfg->usb_mode_set, true);
437 		break;
438 	default:
439 		pr_err("%s, phy-type %d\n", __func__, priv->mode);
440 		return -EINVAL;
441 	}
442 
443 	clk_set_rate(&priv->ref_clk, 100000000);
444 	param_write(priv->phy_grf, &cfg->pipe_clk_100m, true);
445 
446 	if (priv->mode == PHY_TYPE_PCIE) {
447 		/* PLL KVCO tuning fine */
448 		val = readl(priv->mmio + (0x20 << 2));
449 		val &= ~(0x7 << 2);
450 		val |= 0x2 << 2;
451 		writel(val, priv->mmio + (0x20 << 2));
452 
453 		/* Enable controlling random jitter, aka RMJ */
454 		writel(0x4, priv->mmio + (0xb << 2));
455 
456 		val = readl(priv->mmio + (0x5 << 2));
457 		val &= ~(0x3 << 6);
458 		val |= 0x1 << 6;
459 		writel(val, priv->mmio + (0x5 << 2));
460 
461 		writel(0x32, priv->mmio + (0x11 << 2));
462 		writel(0xf0, priv->mmio + (0xa << 2));
463 	}
464 
465 	if (dev_read_bool(priv->dev, "rockchip,enable-ssc")) {
466 		val = readl(priv->mmio + (0x7 << 2));
467 		val |= BIT(4);
468 		writel(val, priv->mmio + (0x7 << 2));
469 	}
470 
471 	return 0;
472 }
473 
474 static const struct rockchip_combphy_grfcfg rk3562_combphy_grfcfgs = {
475 	/* pipe-phy-grf */
476 	.pcie_mode_set		= { 0x0000, 5, 0, 0x00, 0x11 },
477 	.usb_mode_set		= { 0x0000, 5, 0, 0x00, 0x04 },
478 	.pipe_rxterm_set	= { 0x0000, 12, 12, 0x00, 0x01 },
479 	.pipe_txelec_set	= { 0x0004, 1, 1, 0x00, 0x01 },
480 	.pipe_txcomp_set	= { 0x0004, 4, 4, 0x00, 0x01 },
481 	.pipe_clk_25m		= { 0x0004, 14, 13, 0x00, 0x01 },
482 	.pipe_clk_100m		= { 0x0004, 14, 13, 0x00, 0x02 },
483 	.pipe_phymode_sel	= { 0x0008, 1, 1, 0x00, 0x01 },
484 	.pipe_rate_sel		= { 0x0008, 2, 2, 0x00, 0x01 },
485 	.pipe_rxterm_sel	= { 0x0008, 8, 8, 0x00, 0x01 },
486 	.pipe_txelec_sel	= { 0x0008, 12, 12, 0x00, 0x01 },
487 	.pipe_txcomp_sel	= { 0x0008, 15, 15, 0x00, 0x01 },
488 	.pipe_clk_ext		= { 0x000c, 9, 8, 0x02, 0x01 },
489 	.pipe_sel_usb		= { 0x000c, 14, 13, 0x00, 0x01 },
490 	.pipe_phy_status	= { 0x0034, 6, 6, 0x01, 0x00 },
491 	.con0_for_pcie		= { 0x0000, 15, 0, 0x00, 0x1000 },
492 	.con1_for_pcie		= { 0x0004, 15, 0, 0x00, 0x0000 },
493 	.con2_for_pcie		= { 0x0008, 15, 0, 0x00, 0x0101 },
494 	.con3_for_pcie		= { 0x000c, 15, 0, 0x00, 0x0200 },
495 	/* pipe-grf */
496 	.u3otg0_port_en		= { 0x0094, 15, 0, 0x0181, 0x1100 },
497 };
498 
499 static const struct rockchip_combphy_cfg rk3562_combphy_cfgs = {
500 	.grfcfg		= &rk3562_combphy_grfcfgs,
501 	.combphy_cfg	= rk3562_combphy_cfg,
502 };
503 
504 static int rk3568_combphy_cfg(struct rockchip_combphy_priv *priv)
505 {
506 	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
507 	u32 val;
508 
509 	switch (priv->mode) {
510 	case PHY_TYPE_PCIE:
511 		/* Set SSC downward spread spectrum */
512 		val = readl(priv->mmio + (0x1f << 2));
513 		val &= ~GENMASK(5, 4);
514 		val |= 0x01 << 4;
515 		writel(val, priv->mmio + 0x7c);
516 
517 		param_write(priv->phy_grf, &cfg->con0_for_pcie, true);
518 		param_write(priv->phy_grf, &cfg->con1_for_pcie, true);
519 		param_write(priv->phy_grf, &cfg->con2_for_pcie, true);
520 		param_write(priv->phy_grf, &cfg->con3_for_pcie, true);
521 		break;
522 	case PHY_TYPE_USB3:
523 		/* Set SSC downward spread spectrum */
524 		val = readl(priv->mmio + (0x1f << 2));
525 		val &= ~GENMASK(5, 4);
526 		val |= 0x01 << 4;
527 		writel(val, priv->mmio + 0x7c);
528 
529 		/* Enable adaptive CTLE for USB3.0 Rx */
530 		val = readl(priv->mmio + (0x0e << 2));
531 		val &= ~GENMASK(0, 0);
532 		val |= 0x01;
533 		writel(val, priv->mmio + (0x0e << 2));
534 
535 		/* Set PLL KVCO fine tuning signals */
536 		val = readl(priv->mmio + (0x20 << 2));
537 		val &= ~(0x7 << 2);
538 		val |= 0x2 << 2;
539 		writel(val, priv->mmio + (0x20 << 2));
540 
541 		/* Set PLL LPF R1 to su_trim[10:7]=1001 */
542 		writel(0x4, priv->mmio + (0xb << 2));
543 
544 		/* Set PLL input clock divider 1/2 */
545 		val = readl(priv->mmio + (0x5 << 2));
546 		val &= ~(0x3 << 6);
547 		val |= 0x1 << 6;
548 		writel(val, priv->mmio + (0x5 << 2));
549 
550 		/* Set PLL loop divider */
551 		writel(0x32, priv->mmio + (0x11 << 2));
552 
553 		/* Set PLL KVCO to min and set PLL charge pump current to max */
554 		writel(0xf0, priv->mmio + (0xa << 2));
555 
556 		param_write(priv->phy_grf, &cfg->pipe_sel_usb, true);
557 		param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false);
558 		param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false);
559 		param_write(priv->phy_grf, &cfg->usb_mode_set, true);
560 		break;
561 	case PHY_TYPE_SATA:
562 		writel(0x41, priv->mmio + 0x38);
563 		writel(0x8F, priv->mmio + 0x18);
564 		param_write(priv->phy_grf, &cfg->con0_for_sata, true);
565 		param_write(priv->phy_grf, &cfg->con1_for_sata, true);
566 		param_write(priv->phy_grf, &cfg->con2_for_sata, true);
567 		param_write(priv->phy_grf, &cfg->con3_for_sata, true);
568 		param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true);
569 		break;
570 	case PHY_TYPE_SGMII:
571 		param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true);
572 		param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true);
573 		param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true);
574 		param_write(priv->phy_grf, &cfg->sgmii_mode_set, true);
575 		break;
576 	case PHY_TYPE_QSGMII:
577 		param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true);
578 		param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true);
579 		param_write(priv->phy_grf, &cfg->pipe_rate_sel, true);
580 		param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true);
581 		param_write(priv->phy_grf, &cfg->qsgmii_mode_set, true);
582 		break;
583 	default:
584 		pr_err("%s, phy-type %d\n", __func__, priv->mode);
585 		return -EINVAL;
586 	}
587 
588 	/* The default ref clock is 25Mhz */
589 	param_write(priv->phy_grf, &cfg->pipe_clk_25m, true);
590 
591 	if (dev_read_bool(priv->dev, "rockchip,enable-ssc")) {
592 		val = readl(priv->mmio + (0x7 << 2));
593 		val |= BIT(4);
594 		writel(val, priv->mmio + (0x7 << 2));
595 	}
596 
597 	return 0;
598 }
599 
600 static const struct rockchip_combphy_grfcfg rk3568_combphy_grfcfgs = {
601 	/* pipe-phy-grf */
602 	.pcie_mode_set		= { 0x0000, 5, 0, 0x00, 0x11 },
603 	.usb_mode_set		= { 0x0000, 5, 0, 0x00, 0x04 },
604 	.sgmii_mode_set		= { 0x0000, 5, 0, 0x00, 0x01 },
605 	.qsgmii_mode_set	= { 0x0000, 5, 0, 0x00, 0x21 },
606 	.pipe_rxterm_set	= { 0x0000, 12, 12, 0x00, 0x01 },
607 	.pipe_txelec_set	= { 0x0004, 1, 1, 0x00, 0x01 },
608 	.pipe_txcomp_set	= { 0x0004, 4, 4, 0x00, 0x01 },
609 	.pipe_clk_25m		= { 0x0004, 14, 13, 0x00, 0x01 },
610 	.pipe_clk_100m		= { 0x0004, 14, 13, 0x00, 0x02 },
611 	.pipe_phymode_sel	= { 0x0008, 1, 1, 0x00, 0x01 },
612 	.pipe_rate_sel		= { 0x0008, 2, 2, 0x00, 0x01 },
613 	.pipe_rxterm_sel	= { 0x0008, 8, 8, 0x00, 0x01 },
614 	.pipe_txelec_sel	= { 0x0008, 12, 12, 0x00, 0x01 },
615 	.pipe_txcomp_sel	= { 0x0008, 15, 15, 0x00, 0x01 },
616 	.pipe_clk_ext		= { 0x000c, 9, 8, 0x02, 0x01 },
617 	.pipe_sel_usb		= { 0x000c, 14, 13, 0x00, 0x01 },
618 	.pipe_sel_qsgmii	= { 0x000c, 15, 13, 0x00, 0x07 },
619 	.pipe_phy_status	= { 0x0034, 6, 6, 0x01, 0x00 },
620 	.con0_for_pcie		= { 0x0000, 15, 0, 0x00, 0x1000 },
621 	.con1_for_pcie		= { 0x0004, 15, 0, 0x00, 0x0000 },
622 	.con2_for_pcie		= { 0x0008, 15, 0, 0x00, 0x0101 },
623 	.con3_for_pcie		= { 0x000c, 15, 0, 0x00, 0x0200 },
624 	.con0_for_sata		= { 0x0000, 15, 0, 0x00, 0x0119 },
625 	.con1_for_sata		= { 0x0004, 15, 0, 0x00, 0x0040 },
626 	.con2_for_sata		= { 0x0008, 15, 0, 0x00, 0x80c3 },
627 	.con3_for_sata		= { 0x000c, 15, 0, 0x00, 0x4407 },
628 	/* pipe-grf */
629 	.pipe_con0_for_sata	= { 0x0000, 15, 0, 0x00, 0x2220 },
630 	.pipe_sgmii_mac_sel	= { 0x0040, 1, 1, 0x00, 0x01 },
631 	.pipe_xpcs_phy_ready	= { 0x0040, 2, 2, 0x00, 0x01 },
632 	.u3otg0_port_en		= { 0x0104, 15, 0, 0x0181, 0x1100 },
633 	.u3otg1_port_en		= { 0x0144, 15, 0, 0x0181, 0x1100 },
634 };
635 
636 static const struct rockchip_combphy_cfg rk3568_combphy_cfgs = {
637 	.grfcfg		= &rk3568_combphy_grfcfgs,
638 	.combphy_cfg	= rk3568_combphy_cfg,
639 };
640 
641 static int rk3588_combphy_cfg(struct rockchip_combphy_priv *priv)
642 {
643 	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
644 	u32 val;
645 
646 	switch (priv->mode) {
647 	case PHY_TYPE_PCIE:
648 		param_write(priv->phy_grf, &cfg->con0_for_pcie, true);
649 		param_write(priv->phy_grf, &cfg->con1_for_pcie, true);
650 		param_write(priv->phy_grf, &cfg->con2_for_pcie, true);
651 		param_write(priv->phy_grf, &cfg->con3_for_pcie, true);
652 		break;
653 	case PHY_TYPE_USB3:
654 		/* Set SSC downward spread spectrum */
655 		val = readl(priv->mmio + (0x1f << 2));
656 		val &= ~GENMASK(5, 4);
657 		val |= 0x01 << 4;
658 		writel(val, priv->mmio + 0x7c);
659 
660 		/* Enable adaptive CTLE for USB3.0 Rx */
661 		val = readl(priv->mmio + (0x0e << 2));
662 		val &= ~GENMASK(0, 0);
663 		val |= 0x01;
664 		writel(val, priv->mmio + (0x0e << 2));
665 
666 		/* Set PLL KVCO fine tuning signals */
667 		val = readl(priv->mmio + (0x20 << 2));
668 		val &= ~(0x7 << 2);
669 		val |= 0x2 << 2;
670 		writel(val, priv->mmio + (0x20 << 2));
671 
672 		/* Set PLL LPF R1 to su_trim[10:7]=1001 */
673 		writel(0x4, priv->mmio + (0xb << 2));
674 
675 		/* Set PLL input clock divider 1/2 */
676 		val = readl(priv->mmio + (0x5 << 2));
677 		val &= ~(0x3 << 6);
678 		val |= 0x1 << 6;
679 		writel(val, priv->mmio + (0x5 << 2));
680 
681 		/* Set PLL loop divider */
682 		writel(0x32, priv->mmio + (0x11 << 2));
683 
684 		/* Set PLL KVCO to min and set PLL charge pump current to max */
685 		writel(0xf0, priv->mmio + (0xa << 2));
686 
687 		/* Set Rx squelch input filler bandwidth */
688 		writel(0x0d, priv->mmio + (0x14 << 2));
689 
690 		param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false);
691 		param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false);
692 		param_write(priv->phy_grf, &cfg->usb_mode_set, true);
693 		break;
694 	case PHY_TYPE_SATA:
695 		/* Enable adaptive CTLE for SATA Rx */
696 		val = readl(priv->mmio + (0x0e << 2));
697 		val &= ~GENMASK(0, 0);
698 		val |= 0x01;
699 		writel(val, priv->mmio + (0x0e << 2));
700 		/* Set tx_rterm = 50 ohm and rx_rterm = 43.5 ohm */
701 		writel(0x8F, priv->mmio + (0x06 << 2));
702 
703 		param_write(priv->phy_grf, &cfg->con0_for_sata, true);
704 		param_write(priv->phy_grf, &cfg->con1_for_sata, true);
705 		param_write(priv->phy_grf, &cfg->con2_for_sata, true);
706 		param_write(priv->phy_grf, &cfg->con3_for_sata, true);
707 		param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true);
708 		param_write(priv->pipe_grf, &cfg->pipe_con1_for_sata, true);
709 		break;
710 	case PHY_TYPE_SGMII:
711 	case PHY_TYPE_QSGMII:
712 	default:
713 		dev_err(priv->dev, "incompatible PHY type\n");
714 		return -EINVAL;
715 	}
716 
717 	/* 100MHz refclock signal is good */
718 	clk_set_rate(&priv->ref_clk, 100000000);
719 	param_write(priv->phy_grf, &cfg->pipe_clk_100m, true);
720 	if (priv->mode == PHY_TYPE_PCIE) {
721 		/* PLL KVCO tuning fine */
722 		val = readl(priv->mmio + (0x20 << 2));
723 		val &= ~GENMASK(4, 2);
724 		val |= 0x4 << 2;
725 		writel(val, priv->mmio + (0x20 << 2));
726 
727 		/* Set up rx_trim: PLL LPF C1 85pf R1 1.25kohm */
728 		val = 0x4c;
729 		writel(val, priv->mmio + (0x1b << 2));
730 
731 		/* Set up su_trim: T3 */
732 		val = 0xb0;
733 		writel(val, priv->mmio + (0xa << 2));
734 		val = 0x47;
735 		writel(val, priv->mmio + (0xb << 2));
736 		val = 0x57;
737 		writel(val, priv->mmio + (0xd << 2));
738 	}
739 
740 	return 0;
741 }
742 
743 static const struct rockchip_combphy_grfcfg rk3588_combphy_grfcfgs = {
744 	/* pipe-phy-grf */
745 	.pcie_mode_set		= { 0x0000, 5, 0, 0x00, 0x11 },
746 	.usb_mode_set		= { 0x0000, 5, 0, 0x00, 0x04 },
747 	.pipe_rxterm_set	= { 0x0000, 12, 12, 0x00, 0x01 },
748 	.pipe_txelec_set	= { 0x0004, 1, 1, 0x00, 0x01 },
749 	.pipe_txcomp_set	= { 0x0004, 4, 4, 0x00, 0x01 },
750 	.pipe_clk_25m		= { 0x0004, 14, 13, 0x00, 0x01 },
751 	.pipe_clk_100m		= { 0x0004, 14, 13, 0x00, 0x02 },
752 	.pipe_rxterm_sel	= { 0x0008, 8, 8, 0x00, 0x01 },
753 	.pipe_txelec_sel	= { 0x0008, 12, 12, 0x00, 0x01 },
754 	.pipe_txcomp_sel	= { 0x0008, 15, 15, 0x00, 0x01 },
755 	.pipe_clk_ext		= { 0x000c, 9, 8, 0x02, 0x01 },
756 	.pipe_phy_status	= { 0x0034, 6, 6, 0x01, 0x00 },
757 	.con0_for_pcie		= { 0x0000, 15, 0, 0x00, 0x1000 },
758 	.con1_for_pcie		= { 0x0004, 15, 0, 0x00, 0x0000 },
759 	.con2_for_pcie		= { 0x0008, 15, 0, 0x00, 0x0101 },
760 	.con3_for_pcie		= { 0x000c, 15, 0, 0x00, 0x0200 },
761 	.con0_for_sata		= { 0x0000, 15, 0, 0x00, 0x0129 },
762 	.con1_for_sata		= { 0x0004, 15, 0, 0x00, 0x0000 },
763 	.con2_for_sata		= { 0x0008, 15, 0, 0x00, 0x80c1 },
764 	.con3_for_sata		= { 0x000c, 15, 0, 0x00, 0x0407 },
765 	/* pipe-grf */
766 	.pipe_con0_for_sata	= { 0x0000, 11, 5, 0x00, 0x22 },
767 	.pipe_con1_for_sata	= { 0x0000, 2, 0, 0x00, 0x2 },
768 };
769 
770 static const struct rockchip_combphy_cfg rk3588_combphy_cfgs = {
771 	.grfcfg		= &rk3588_combphy_grfcfgs,
772 	.combphy_cfg	= rk3588_combphy_cfg,
773 };
774 
775 static const struct udevice_id rockchip_combphy_ids[] = {
776 	{
777 		.compatible = "rockchip,rk3528-naneng-combphy",
778 		.data = (ulong)&rk3528_combphy_cfgs
779 	},
780 	{
781 		.compatible = "rockchip,rk3562-naneng-combphy",
782 		.data = (ulong)&rk3562_combphy_cfgs
783 	},
784 	{
785 		.compatible = "rockchip,rk3568-naneng-combphy",
786 		.data = (ulong)&rk3568_combphy_cfgs
787 	},
788 	{
789 		.compatible = "rockchip,rk3588-naneng-combphy",
790 		.data = (ulong)&rk3588_combphy_cfgs
791 	},
792 	{ }
793 };
794 
795 U_BOOT_DRIVER(rockchip_naneng_combphy) = {
796 	.name		= "naneng-combphy",
797 	.id		= UCLASS_PHY,
798 	.of_match	= rockchip_combphy_ids,
799 	.ops		= &rochchip_combphy_ops,
800 	.probe		= rockchip_combphy_probe,
801 	.priv_auto_alloc_size = sizeof(struct rockchip_combphy_priv),
802 };
803