xref: /linux/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c (revision 7255fcc80d4b525cc10cfaaf7f485830d4ed2000)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Rockchip PIPE USB3.0 PCIE SATA Combo Phy driver
4  *
5  * Copyright (C) 2021 Rockchip Electronics Co., Ltd.
6  */
7 
8 #include <dt-bindings/phy/phy.h>
9 #include <linux/clk.h>
10 #include <linux/mfd/syscon.h>
11 #include <linux/of.h>
12 #include <linux/phy/phy.h>
13 #include <linux/platform_device.h>
14 #include <linux/regmap.h>
15 #include <linux/reset.h>
16 #include <linux/units.h>
17 
18 #define BIT_WRITEABLE_SHIFT		16
19 #define REF_CLOCK_24MHz			(24 * HZ_PER_MHZ)
20 #define REF_CLOCK_25MHz			(25 * HZ_PER_MHZ)
21 #define REF_CLOCK_100MHz		(100 * HZ_PER_MHZ)
22 
23 /* COMBO PHY REG */
24 #define PHYREG6				0x14
25 #define PHYREG6_PLL_DIV_MASK		GENMASK(7, 6)
26 #define PHYREG6_PLL_DIV_SHIFT		6
27 #define PHYREG6_PLL_DIV_2		1
28 
29 #define PHYREG7				0x18
30 #define PHYREG7_TX_RTERM_MASK		GENMASK(7, 4)
31 #define PHYREG7_TX_RTERM_SHIFT		4
32 #define PHYREG7_TX_RTERM_50OHM		8
33 #define PHYREG7_RX_RTERM_MASK		GENMASK(3, 0)
34 #define PHYREG7_RX_RTERM_SHIFT		0
35 #define PHYREG7_RX_RTERM_44OHM		15
36 
37 #define PHYREG8				0x1C
38 #define PHYREG8_SSC_EN			BIT(4)
39 
40 #define PHYREG11			0x28
41 #define PHYREG11_SU_TRIM_0_7		0xF0
42 
43 #define PHYREG12			0x2C
44 #define PHYREG12_PLL_LPF_ADJ_VALUE	4
45 
46 #define PHYREG13			0x30
47 #define PHYREG13_RESISTER_MASK		GENMASK(5, 4)
48 #define PHYREG13_RESISTER_SHIFT		0x4
49 #define PHYREG13_RESISTER_HIGH_Z	3
50 #define PHYREG13_CKRCV_AMP0		BIT(7)
51 
52 #define PHYREG14			0x34
53 #define PHYREG14_CKRCV_AMP1		BIT(0)
54 
55 #define PHYREG15			0x38
56 #define PHYREG15_CTLE_EN		BIT(0)
57 #define PHYREG15_SSC_CNT_MASK		GENMASK(7, 6)
58 #define PHYREG15_SSC_CNT_SHIFT		6
59 #define PHYREG15_SSC_CNT_VALUE		1
60 
61 #define PHYREG16			0x3C
62 #define PHYREG16_SSC_CNT_VALUE		0x5f
63 
64 #define PHYREG18			0x44
65 #define PHYREG18_PLL_LOOP		0x32
66 
67 #define PHYREG27			0x6C
68 #define PHYREG27_RX_TRIM_RK3588		0x4C
69 
70 #define PHYREG32			0x7C
71 #define PHYREG32_SSC_MASK		GENMASK(7, 4)
72 #define PHYREG32_SSC_DIR_SHIFT		4
73 #define PHYREG32_SSC_UPWARD		0
74 #define PHYREG32_SSC_DOWNWARD		1
75 #define PHYREG32_SSC_OFFSET_SHIFT	6
76 #define PHYREG32_SSC_OFFSET_500PPM	1
77 
78 #define PHYREG33			0x80
79 #define PHYREG33_PLL_KVCO_MASK		GENMASK(4, 2)
80 #define PHYREG33_PLL_KVCO_SHIFT		2
81 #define PHYREG33_PLL_KVCO_VALUE		2
82 
83 struct rockchip_combphy_priv;
84 
85 struct combphy_reg {
86 	u16 offset;
87 	u16 bitend;
88 	u16 bitstart;
89 	u16 disable;
90 	u16 enable;
91 };
92 
93 struct rockchip_combphy_grfcfg {
94 	struct combphy_reg pcie_mode_set;
95 	struct combphy_reg usb_mode_set;
96 	struct combphy_reg sgmii_mode_set;
97 	struct combphy_reg qsgmii_mode_set;
98 	struct combphy_reg pipe_rxterm_set;
99 	struct combphy_reg pipe_txelec_set;
100 	struct combphy_reg pipe_txcomp_set;
101 	struct combphy_reg pipe_clk_25m;
102 	struct combphy_reg pipe_clk_100m;
103 	struct combphy_reg pipe_phymode_sel;
104 	struct combphy_reg pipe_rate_sel;
105 	struct combphy_reg pipe_rxterm_sel;
106 	struct combphy_reg pipe_txelec_sel;
107 	struct combphy_reg pipe_txcomp_sel;
108 	struct combphy_reg pipe_clk_ext;
109 	struct combphy_reg pipe_sel_usb;
110 	struct combphy_reg pipe_sel_qsgmii;
111 	struct combphy_reg pipe_phy_status;
112 	struct combphy_reg con0_for_pcie;
113 	struct combphy_reg con1_for_pcie;
114 	struct combphy_reg con2_for_pcie;
115 	struct combphy_reg con3_for_pcie;
116 	struct combphy_reg con0_for_sata;
117 	struct combphy_reg con1_for_sata;
118 	struct combphy_reg con2_for_sata;
119 	struct combphy_reg con3_for_sata;
120 	struct combphy_reg pipe_con0_for_sata;
121 	struct combphy_reg pipe_con1_for_sata;
122 	struct combphy_reg pipe_xpcs_phy_ready;
123 	struct combphy_reg pipe_pcie1l0_sel;
124 	struct combphy_reg pipe_pcie1l1_sel;
125 };
126 
127 struct rockchip_combphy_cfg {
128 	const struct rockchip_combphy_grfcfg *grfcfg;
129 	int (*combphy_cfg)(struct rockchip_combphy_priv *priv);
130 };
131 
132 struct rockchip_combphy_priv {
133 	u8 type;
134 	void __iomem *mmio;
135 	int num_clks;
136 	struct clk_bulk_data *clks;
137 	struct device *dev;
138 	struct regmap *pipe_grf;
139 	struct regmap *phy_grf;
140 	struct phy *phy;
141 	struct reset_control *phy_rst;
142 	const struct rockchip_combphy_cfg *cfg;
143 	bool enable_ssc;
144 	bool ext_refclk;
145 	struct clk *refclk;
146 };
147 
148 static void rockchip_combphy_updatel(struct rockchip_combphy_priv *priv,
149 				     int mask, int val, int reg)
150 {
151 	unsigned int temp;
152 
153 	temp = readl(priv->mmio + reg);
154 	temp = (temp & ~(mask)) | val;
155 	writel(temp, priv->mmio + reg);
156 }
157 
158 static int rockchip_combphy_param_write(struct regmap *base,
159 					const struct combphy_reg *reg, bool en)
160 {
161 	u32 val, mask, tmp;
162 
163 	tmp = en ? reg->enable : reg->disable;
164 	mask = GENMASK(reg->bitend, reg->bitstart);
165 	val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT);
166 
167 	return regmap_write(base, reg->offset, val);
168 }
169 
170 static u32 rockchip_combphy_is_ready(struct rockchip_combphy_priv *priv)
171 {
172 	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
173 	u32 mask, val;
174 
175 	mask = GENMASK(cfg->pipe_phy_status.bitend,
176 		       cfg->pipe_phy_status.bitstart);
177 
178 	regmap_read(priv->phy_grf, cfg->pipe_phy_status.offset, &val);
179 	val = (val & mask) >> cfg->pipe_phy_status.bitstart;
180 
181 	return val;
182 }
183 
184 static int rockchip_combphy_init(struct phy *phy)
185 {
186 	struct rockchip_combphy_priv *priv = phy_get_drvdata(phy);
187 	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
188 	u32 val;
189 	int ret;
190 
191 	ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks);
192 	if (ret) {
193 		dev_err(priv->dev, "failed to enable clks\n");
194 		return ret;
195 	}
196 
197 	switch (priv->type) {
198 	case PHY_TYPE_PCIE:
199 	case PHY_TYPE_USB3:
200 	case PHY_TYPE_SATA:
201 	case PHY_TYPE_SGMII:
202 	case PHY_TYPE_QSGMII:
203 		if (priv->cfg->combphy_cfg)
204 			ret = priv->cfg->combphy_cfg(priv);
205 		break;
206 	default:
207 		dev_err(priv->dev, "incompatible PHY type\n");
208 		ret = -EINVAL;
209 		break;
210 	}
211 
212 	if (ret) {
213 		dev_err(priv->dev, "failed to init phy for phy type %x\n", priv->type);
214 		goto err_clk;
215 	}
216 
217 	ret = reset_control_deassert(priv->phy_rst);
218 	if (ret)
219 		goto err_clk;
220 
221 	if (priv->type == PHY_TYPE_USB3) {
222 		ret = readx_poll_timeout_atomic(rockchip_combphy_is_ready,
223 						priv, val,
224 						val == cfg->pipe_phy_status.enable,
225 						10, 1000);
226 		if (ret)
227 			dev_warn(priv->dev, "wait phy status ready timeout\n");
228 	}
229 
230 	return 0;
231 
232 err_clk:
233 	clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
234 
235 	return ret;
236 }
237 
238 static int rockchip_combphy_exit(struct phy *phy)
239 {
240 	struct rockchip_combphy_priv *priv = phy_get_drvdata(phy);
241 
242 	clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
243 	reset_control_assert(priv->phy_rst);
244 
245 	return 0;
246 }
247 
248 static const struct phy_ops rochchip_combphy_ops = {
249 	.init = rockchip_combphy_init,
250 	.exit = rockchip_combphy_exit,
251 	.owner = THIS_MODULE,
252 };
253 
254 static struct phy *rockchip_combphy_xlate(struct device *dev, const struct of_phandle_args *args)
255 {
256 	struct rockchip_combphy_priv *priv = dev_get_drvdata(dev);
257 
258 	if (args->args_count != 1) {
259 		dev_err(dev, "invalid number of arguments\n");
260 		return ERR_PTR(-EINVAL);
261 	}
262 
263 	if (priv->type != PHY_NONE && priv->type != args->args[0])
264 		dev_warn(dev, "phy type select %d overwriting type %d\n",
265 			 args->args[0], priv->type);
266 
267 	priv->type = args->args[0];
268 
269 	return priv->phy;
270 }
271 
272 static int rockchip_combphy_parse_dt(struct device *dev, struct rockchip_combphy_priv *priv)
273 {
274 	int i;
275 
276 	priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks);
277 	if (priv->num_clks < 1)
278 		return -EINVAL;
279 
280 	priv->refclk = NULL;
281 	for (i = 0; i < priv->num_clks; i++) {
282 		if (!strncmp(priv->clks[i].id, "ref", 3)) {
283 			priv->refclk = priv->clks[i].clk;
284 			break;
285 		}
286 	}
287 
288 	if (!priv->refclk) {
289 		dev_err(dev, "no refclk found\n");
290 		return -EINVAL;
291 	}
292 
293 	priv->pipe_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pipe-grf");
294 	if (IS_ERR(priv->pipe_grf)) {
295 		dev_err(dev, "failed to find peri_ctrl pipe-grf regmap\n");
296 		return PTR_ERR(priv->pipe_grf);
297 	}
298 
299 	priv->phy_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pipe-phy-grf");
300 	if (IS_ERR(priv->phy_grf)) {
301 		dev_err(dev, "failed to find peri_ctrl pipe-phy-grf regmap\n");
302 		return PTR_ERR(priv->phy_grf);
303 	}
304 
305 	priv->enable_ssc = device_property_present(dev, "rockchip,enable-ssc");
306 
307 	priv->ext_refclk = device_property_present(dev, "rockchip,ext-refclk");
308 
309 	priv->phy_rst = devm_reset_control_array_get_exclusive(dev);
310 	if (IS_ERR(priv->phy_rst))
311 		return dev_err_probe(dev, PTR_ERR(priv->phy_rst), "failed to get phy reset\n");
312 
313 	return 0;
314 }
315 
316 static int rockchip_combphy_probe(struct platform_device *pdev)
317 {
318 	struct phy_provider *phy_provider;
319 	struct device *dev = &pdev->dev;
320 	struct rockchip_combphy_priv *priv;
321 	const struct rockchip_combphy_cfg *phy_cfg;
322 	struct resource *res;
323 	int ret;
324 
325 	phy_cfg = of_device_get_match_data(dev);
326 	if (!phy_cfg) {
327 		dev_err(dev, "no OF match data provided\n");
328 		return -EINVAL;
329 	}
330 
331 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
332 	if (!priv)
333 		return -ENOMEM;
334 
335 	priv->mmio = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
336 	if (IS_ERR(priv->mmio)) {
337 		ret = PTR_ERR(priv->mmio);
338 		return ret;
339 	}
340 
341 	priv->dev = dev;
342 	priv->type = PHY_NONE;
343 	priv->cfg = phy_cfg;
344 
345 	ret = rockchip_combphy_parse_dt(dev, priv);
346 	if (ret)
347 		return ret;
348 
349 	ret = reset_control_assert(priv->phy_rst);
350 	if (ret) {
351 		dev_err(dev, "failed to reset phy\n");
352 		return ret;
353 	}
354 
355 	priv->phy = devm_phy_create(dev, NULL, &rochchip_combphy_ops);
356 	if (IS_ERR(priv->phy)) {
357 		dev_err(dev, "failed to create combphy\n");
358 		return PTR_ERR(priv->phy);
359 	}
360 
361 	dev_set_drvdata(dev, priv);
362 	phy_set_drvdata(priv->phy, priv);
363 
364 	phy_provider = devm_of_phy_provider_register(dev, rockchip_combphy_xlate);
365 
366 	return PTR_ERR_OR_ZERO(phy_provider);
367 }
368 
369 static int rk3568_combphy_cfg(struct rockchip_combphy_priv *priv)
370 {
371 	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
372 	unsigned long rate;
373 	u32 val;
374 
375 	switch (priv->type) {
376 	case PHY_TYPE_PCIE:
377 		/* Set SSC downward spread spectrum. */
378 		rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK,
379 					 PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT,
380 					 PHYREG32);
381 
382 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_pcie, true);
383 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_pcie, true);
384 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_pcie, true);
385 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_pcie, true);
386 		break;
387 
388 	case PHY_TYPE_USB3:
389 		/* Set SSC downward spread spectrum. */
390 		rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK,
391 					 PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT,
392 					 PHYREG32);
393 
394 		/* Enable adaptive CTLE for USB3.0 Rx. */
395 		val = readl(priv->mmio + PHYREG15);
396 		val |= PHYREG15_CTLE_EN;
397 		writel(val, priv->mmio + PHYREG15);
398 
399 		/* Set PLL KVCO fine tuning signals. */
400 		rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK,
401 					 PHYREG33_PLL_KVCO_VALUE << PHYREG33_PLL_KVCO_SHIFT,
402 					 PHYREG33);
403 
404 		/* Enable controlling random jitter. */
405 		writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12);
406 
407 		/* Set PLL input clock divider 1/2. */
408 		rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK,
409 					 PHYREG6_PLL_DIV_2 << PHYREG6_PLL_DIV_SHIFT,
410 					 PHYREG6);
411 
412 		writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18);
413 		writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11);
414 
415 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_usb, true);
416 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false);
417 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false);
418 		rockchip_combphy_param_write(priv->phy_grf, &cfg->usb_mode_set, true);
419 		break;
420 
421 	case PHY_TYPE_SATA:
422 		/* Enable adaptive CTLE for SATA Rx. */
423 		val = readl(priv->mmio + PHYREG15);
424 		val |= PHYREG15_CTLE_EN;
425 		writel(val, priv->mmio + PHYREG15);
426 		/*
427 		 * Set tx_rterm=50ohm and rx_rterm=44ohm for SATA.
428 		 * 0: 60ohm, 8: 50ohm 15: 44ohm (by step abort 1ohm)
429 		 */
430 		val = PHYREG7_TX_RTERM_50OHM << PHYREG7_TX_RTERM_SHIFT;
431 		val |= PHYREG7_RX_RTERM_44OHM << PHYREG7_RX_RTERM_SHIFT;
432 		writel(val, priv->mmio + PHYREG7);
433 
434 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_sata, true);
435 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_sata, true);
436 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_sata, true);
437 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_sata, true);
438 		rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true);
439 		break;
440 
441 	case PHY_TYPE_SGMII:
442 		rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true);
443 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true);
444 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true);
445 		rockchip_combphy_param_write(priv->phy_grf, &cfg->sgmii_mode_set, true);
446 		break;
447 
448 	case PHY_TYPE_QSGMII:
449 		rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true);
450 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true);
451 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_rate_sel, true);
452 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true);
453 		rockchip_combphy_param_write(priv->phy_grf, &cfg->qsgmii_mode_set, true);
454 		break;
455 
456 	default:
457 		dev_err(priv->dev, "incompatible PHY type\n");
458 		return -EINVAL;
459 	}
460 
461 	rate = clk_get_rate(priv->refclk);
462 
463 	switch (rate) {
464 	case REF_CLOCK_24MHz:
465 		if (priv->type == PHY_TYPE_USB3 || priv->type == PHY_TYPE_SATA) {
466 			/* Set ssc_cnt[9:0]=0101111101 & 31.5KHz. */
467 			val = PHYREG15_SSC_CNT_VALUE << PHYREG15_SSC_CNT_SHIFT;
468 			rockchip_combphy_updatel(priv, PHYREG15_SSC_CNT_MASK,
469 						 val, PHYREG15);
470 
471 			writel(PHYREG16_SSC_CNT_VALUE, priv->mmio + PHYREG16);
472 		}
473 		break;
474 
475 	case REF_CLOCK_25MHz:
476 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_25m, true);
477 		break;
478 
479 	case REF_CLOCK_100MHz:
480 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_100m, true);
481 		if (priv->type == PHY_TYPE_PCIE) {
482 			/* PLL KVCO  fine tuning. */
483 			val = PHYREG33_PLL_KVCO_VALUE << PHYREG33_PLL_KVCO_SHIFT;
484 			rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK,
485 						 val, PHYREG33);
486 
487 			/* Enable controlling random jitter. */
488 			writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12);
489 
490 			val = PHYREG6_PLL_DIV_2 << PHYREG6_PLL_DIV_SHIFT;
491 			rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK,
492 						 val, PHYREG6);
493 
494 			writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18);
495 			writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11);
496 		} else if (priv->type == PHY_TYPE_SATA) {
497 			/* downward spread spectrum +500ppm */
498 			val = PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT;
499 			val |= PHYREG32_SSC_OFFSET_500PPM << PHYREG32_SSC_OFFSET_SHIFT;
500 			rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, val, PHYREG32);
501 		}
502 		break;
503 
504 	default:
505 		dev_err(priv->dev, "unsupported rate: %lu\n", rate);
506 		return -EINVAL;
507 	}
508 
509 	if (priv->ext_refclk) {
510 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_ext, true);
511 		if (priv->type == PHY_TYPE_PCIE && rate == REF_CLOCK_100MHz) {
512 			val = PHYREG13_RESISTER_HIGH_Z << PHYREG13_RESISTER_SHIFT;
513 			val |= PHYREG13_CKRCV_AMP0;
514 			rockchip_combphy_updatel(priv, PHYREG13_RESISTER_MASK, val, PHYREG13);
515 
516 			val = readl(priv->mmio + PHYREG14);
517 			val |= PHYREG14_CKRCV_AMP1;
518 			writel(val, priv->mmio + PHYREG14);
519 		}
520 	}
521 
522 	if (priv->enable_ssc) {
523 		val = readl(priv->mmio + PHYREG8);
524 		val |= PHYREG8_SSC_EN;
525 		writel(val, priv->mmio + PHYREG8);
526 	}
527 
528 	return 0;
529 }
530 
531 static const struct rockchip_combphy_grfcfg rk3568_combphy_grfcfgs = {
532 	/* pipe-phy-grf */
533 	.pcie_mode_set		= { 0x0000, 5, 0, 0x00, 0x11 },
534 	.usb_mode_set		= { 0x0000, 5, 0, 0x00, 0x04 },
535 	.sgmii_mode_set		= { 0x0000, 5, 0, 0x00, 0x01 },
536 	.qsgmii_mode_set	= { 0x0000, 5, 0, 0x00, 0x21 },
537 	.pipe_rxterm_set	= { 0x0000, 12, 12, 0x00, 0x01 },
538 	.pipe_txelec_set	= { 0x0004, 1, 1, 0x00, 0x01 },
539 	.pipe_txcomp_set	= { 0x0004, 4, 4, 0x00, 0x01 },
540 	.pipe_clk_25m		= { 0x0004, 14, 13, 0x00, 0x01 },
541 	.pipe_clk_100m		= { 0x0004, 14, 13, 0x00, 0x02 },
542 	.pipe_phymode_sel	= { 0x0008, 1, 1, 0x00, 0x01 },
543 	.pipe_rate_sel		= { 0x0008, 2, 2, 0x00, 0x01 },
544 	.pipe_rxterm_sel	= { 0x0008, 8, 8, 0x00, 0x01 },
545 	.pipe_txelec_sel	= { 0x0008, 12, 12, 0x00, 0x01 },
546 	.pipe_txcomp_sel	= { 0x0008, 15, 15, 0x00, 0x01 },
547 	.pipe_clk_ext		= { 0x000c, 9, 8, 0x02, 0x01 },
548 	.pipe_sel_usb		= { 0x000c, 14, 13, 0x00, 0x01 },
549 	.pipe_sel_qsgmii	= { 0x000c, 15, 13, 0x00, 0x07 },
550 	.pipe_phy_status	= { 0x0034, 6, 6, 0x01, 0x00 },
551 	.con0_for_pcie		= { 0x0000, 15, 0, 0x00, 0x1000 },
552 	.con1_for_pcie		= { 0x0004, 15, 0, 0x00, 0x0000 },
553 	.con2_for_pcie		= { 0x0008, 15, 0, 0x00, 0x0101 },
554 	.con3_for_pcie		= { 0x000c, 15, 0, 0x00, 0x0200 },
555 	.con0_for_sata		= { 0x0000, 15, 0, 0x00, 0x0119 },
556 	.con1_for_sata		= { 0x0004, 15, 0, 0x00, 0x0040 },
557 	.con2_for_sata		= { 0x0008, 15, 0, 0x00, 0x80c3 },
558 	.con3_for_sata		= { 0x000c, 15, 0, 0x00, 0x4407 },
559 	/* pipe-grf */
560 	.pipe_con0_for_sata	= { 0x0000, 15, 0, 0x00, 0x2220 },
561 	.pipe_xpcs_phy_ready	= { 0x0040, 2, 2, 0x00, 0x01 },
562 };
563 
564 static const struct rockchip_combphy_cfg rk3568_combphy_cfgs = {
565 	.grfcfg		= &rk3568_combphy_grfcfgs,
566 	.combphy_cfg	= rk3568_combphy_cfg,
567 };
568 
569 static int rk3588_combphy_cfg(struct rockchip_combphy_priv *priv)
570 {
571 	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
572 	unsigned long rate;
573 	u32 val;
574 
575 	switch (priv->type) {
576 	case PHY_TYPE_PCIE:
577 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_pcie, true);
578 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_pcie, true);
579 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_pcie, true);
580 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_pcie, true);
581 		rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_pcie1l0_sel, true);
582 		rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_pcie1l1_sel, true);
583 		break;
584 	case PHY_TYPE_USB3:
585 		/* Set SSC downward spread spectrum */
586 		rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK,
587 					 PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT,
588 					 PHYREG32);
589 
590 		/* Enable adaptive CTLE for USB3.0 Rx. */
591 		val = readl(priv->mmio + PHYREG15);
592 		val |= PHYREG15_CTLE_EN;
593 		writel(val, priv->mmio + PHYREG15);
594 
595 		/* Set PLL KVCO fine tuning signals. */
596 		rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK,
597 					 PHYREG33_PLL_KVCO_VALUE << PHYREG33_PLL_KVCO_SHIFT,
598 					 PHYREG33);
599 
600 		/* Enable controlling random jitter. */
601 		writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12);
602 
603 		/* Set PLL input clock divider 1/2. */
604 		rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK,
605 					 PHYREG6_PLL_DIV_2 << PHYREG6_PLL_DIV_SHIFT,
606 					 PHYREG6);
607 
608 		writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18);
609 		writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11);
610 
611 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false);
612 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false);
613 		rockchip_combphy_param_write(priv->phy_grf, &cfg->usb_mode_set, true);
614 		break;
615 	case PHY_TYPE_SATA:
616 		/* Enable adaptive CTLE for SATA Rx. */
617 		val = readl(priv->mmio + PHYREG15);
618 		val |= PHYREG15_CTLE_EN;
619 		writel(val, priv->mmio + PHYREG15);
620 		/*
621 		 * Set tx_rterm=50ohm and rx_rterm=44ohm for SATA.
622 		 * 0: 60ohm, 8: 50ohm 15: 44ohm (by step abort 1ohm)
623 		 */
624 		val = PHYREG7_TX_RTERM_50OHM << PHYREG7_TX_RTERM_SHIFT;
625 		val |= PHYREG7_RX_RTERM_44OHM << PHYREG7_RX_RTERM_SHIFT;
626 		writel(val, priv->mmio + PHYREG7);
627 
628 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_sata, true);
629 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_sata, true);
630 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_sata, true);
631 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_sata, true);
632 		rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true);
633 		rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_con1_for_sata, true);
634 		break;
635 	case PHY_TYPE_SGMII:
636 	case PHY_TYPE_QSGMII:
637 	default:
638 		dev_err(priv->dev, "incompatible PHY type\n");
639 		return -EINVAL;
640 	}
641 
642 	rate = clk_get_rate(priv->refclk);
643 
644 	switch (rate) {
645 	case REF_CLOCK_24MHz:
646 		if (priv->type == PHY_TYPE_USB3 || priv->type == PHY_TYPE_SATA) {
647 			/* Set ssc_cnt[9:0]=0101111101 & 31.5KHz. */
648 			val = PHYREG15_SSC_CNT_VALUE << PHYREG15_SSC_CNT_SHIFT;
649 			rockchip_combphy_updatel(priv, PHYREG15_SSC_CNT_MASK,
650 						 val, PHYREG15);
651 
652 			writel(PHYREG16_SSC_CNT_VALUE, priv->mmio + PHYREG16);
653 		}
654 		break;
655 
656 	case REF_CLOCK_25MHz:
657 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_25m, true);
658 		break;
659 	case REF_CLOCK_100MHz:
660 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_100m, true);
661 		if (priv->type == PHY_TYPE_PCIE) {
662 			/* PLL KVCO fine tuning. */
663 			val = 4 << PHYREG33_PLL_KVCO_SHIFT;
664 			rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK,
665 						 val, PHYREG33);
666 
667 			/* Enable controlling random jitter. */
668 			writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12);
669 
670 			/* Set up rx_trim: PLL LPF C1 85pf R1 1.25kohm */
671 			writel(PHYREG27_RX_TRIM_RK3588, priv->mmio + PHYREG27);
672 
673 			/* Set up su_trim:  */
674 			writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11);
675 		} else if (priv->type == PHY_TYPE_SATA) {
676 			/* downward spread spectrum +500ppm */
677 			val = PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT;
678 			val |= PHYREG32_SSC_OFFSET_500PPM << PHYREG32_SSC_OFFSET_SHIFT;
679 			rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, val, PHYREG32);
680 		}
681 		break;
682 	default:
683 		dev_err(priv->dev, "Unsupported rate: %lu\n", rate);
684 		return -EINVAL;
685 	}
686 
687 	if (priv->ext_refclk) {
688 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_ext, true);
689 		if (priv->type == PHY_TYPE_PCIE && rate == REF_CLOCK_100MHz) {
690 			val = PHYREG13_RESISTER_HIGH_Z << PHYREG13_RESISTER_SHIFT;
691 			val |= PHYREG13_CKRCV_AMP0;
692 			rockchip_combphy_updatel(priv, PHYREG13_RESISTER_MASK, val, PHYREG13);
693 
694 			val = readl(priv->mmio + PHYREG14);
695 			val |= PHYREG14_CKRCV_AMP1;
696 			writel(val, priv->mmio + PHYREG14);
697 		}
698 	}
699 
700 	if (priv->enable_ssc) {
701 		val = readl(priv->mmio + PHYREG8);
702 		val |= PHYREG8_SSC_EN;
703 		writel(val, priv->mmio + PHYREG8);
704 	}
705 
706 	return 0;
707 }
708 
709 static const struct rockchip_combphy_grfcfg rk3588_combphy_grfcfgs = {
710 	/* pipe-phy-grf */
711 	.pcie_mode_set		= { 0x0000, 5, 0, 0x00, 0x11 },
712 	.usb_mode_set		= { 0x0000, 5, 0, 0x00, 0x04 },
713 	.pipe_rxterm_set	= { 0x0000, 12, 12, 0x00, 0x01 },
714 	.pipe_txelec_set	= { 0x0004, 1, 1, 0x00, 0x01 },
715 	.pipe_txcomp_set	= { 0x0004, 4, 4, 0x00, 0x01 },
716 	.pipe_clk_25m		= { 0x0004, 14, 13, 0x00, 0x01 },
717 	.pipe_clk_100m		= { 0x0004, 14, 13, 0x00, 0x02 },
718 	.pipe_rxterm_sel	= { 0x0008, 8, 8, 0x00, 0x01 },
719 	.pipe_txelec_sel	= { 0x0008, 12, 12, 0x00, 0x01 },
720 	.pipe_txcomp_sel	= { 0x0008, 15, 15, 0x00, 0x01 },
721 	.pipe_clk_ext		= { 0x000c, 9, 8, 0x02, 0x01 },
722 	.pipe_phy_status	= { 0x0034, 6, 6, 0x01, 0x00 },
723 	.con0_for_pcie		= { 0x0000, 15, 0, 0x00, 0x1000 },
724 	.con1_for_pcie		= { 0x0004, 15, 0, 0x00, 0x0000 },
725 	.con2_for_pcie		= { 0x0008, 15, 0, 0x00, 0x0101 },
726 	.con3_for_pcie		= { 0x000c, 15, 0, 0x00, 0x0200 },
727 	.con0_for_sata		= { 0x0000, 15, 0, 0x00, 0x0129 },
728 	.con1_for_sata		= { 0x0004, 15, 0, 0x00, 0x0000 },
729 	.con2_for_sata		= { 0x0008, 15, 0, 0x00, 0x80c1 },
730 	.con3_for_sata		= { 0x000c, 15, 0, 0x00, 0x0407 },
731 	/* pipe-grf */
732 	.pipe_con0_for_sata	= { 0x0000, 11, 5, 0x00, 0x22 },
733 	.pipe_con1_for_sata	= { 0x0000, 2, 0, 0x00, 0x2 },
734 	.pipe_pcie1l0_sel	= { 0x0100, 0, 0, 0x01, 0x0 },
735 	.pipe_pcie1l1_sel	= { 0x0100, 1, 1, 0x01, 0x0 },
736 };
737 
738 static const struct rockchip_combphy_cfg rk3588_combphy_cfgs = {
739 	.grfcfg		= &rk3588_combphy_grfcfgs,
740 	.combphy_cfg	= rk3588_combphy_cfg,
741 };
742 
743 static const struct of_device_id rockchip_combphy_of_match[] = {
744 	{
745 		.compatible = "rockchip,rk3568-naneng-combphy",
746 		.data = &rk3568_combphy_cfgs,
747 	},
748 	{
749 		.compatible = "rockchip,rk3588-naneng-combphy",
750 		.data = &rk3588_combphy_cfgs,
751 	},
752 	{ },
753 };
754 MODULE_DEVICE_TABLE(of, rockchip_combphy_of_match);
755 
756 static struct platform_driver rockchip_combphy_driver = {
757 	.probe	= rockchip_combphy_probe,
758 	.driver = {
759 		.name = "rockchip-naneng-combphy",
760 		.of_match_table = rockchip_combphy_of_match,
761 	},
762 };
763 module_platform_driver(rockchip_combphy_driver);
764 
765 MODULE_DESCRIPTION("Rockchip NANENG COMBPHY driver");
766 MODULE_LICENSE("GPL v2");
767