xref: /linux/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c (revision a760b10147d96c642ff152eef85db0c3799c9f74)
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 PHYREG10			0x24
41 #define PHYREG10_SSC_PCM_MASK		GENMASK(3, 0)
42 #define PHYREG10_SSC_PCM_3500PPM	7
43 
44 #define PHYREG11			0x28
45 #define PHYREG11_SU_TRIM_0_7		0xF0
46 
47 #define PHYREG12			0x2C
48 #define PHYREG12_PLL_LPF_ADJ_VALUE	4
49 
50 #define PHYREG13			0x30
51 #define PHYREG13_RESISTER_MASK		GENMASK(5, 4)
52 #define PHYREG13_RESISTER_SHIFT		0x4
53 #define PHYREG13_RESISTER_HIGH_Z	3
54 #define PHYREG13_CKRCV_AMP0		BIT(7)
55 
56 #define PHYREG14			0x34
57 #define PHYREG14_CKRCV_AMP1		BIT(0)
58 
59 #define PHYREG15			0x38
60 #define PHYREG15_CTLE_EN		BIT(0)
61 #define PHYREG15_SSC_CNT_MASK		GENMASK(7, 6)
62 #define PHYREG15_SSC_CNT_SHIFT		6
63 #define PHYREG15_SSC_CNT_VALUE		1
64 
65 #define PHYREG16			0x3C
66 #define PHYREG16_SSC_CNT_VALUE		0x5f
67 
68 #define PHYREG17			0x40
69 
70 #define PHYREG18			0x44
71 #define PHYREG18_PLL_LOOP		0x32
72 
73 #define PHYREG21			0x50
74 #define PHYREG21_RX_SQUELCH_VAL		0x0D
75 
76 #define PHYREG27			0x6C
77 #define PHYREG27_RX_TRIM_RK3588		0x4C
78 
79 #define PHYREG30			0x74
80 
81 #define PHYREG32			0x7C
82 #define PHYREG32_SSC_MASK		GENMASK(7, 4)
83 #define PHYREG32_SSC_DIR_MASK		GENMASK(5, 4)
84 #define PHYREG32_SSC_DIR_SHIFT		4
85 #define PHYREG32_SSC_UPWARD		0
86 #define PHYREG32_SSC_DOWNWARD		1
87 #define PHYREG32_SSC_OFFSET_MASK	GENMASK(7, 6)
88 #define PHYREG32_SSC_OFFSET_SHIFT	6
89 #define PHYREG32_SSC_OFFSET_500PPM	1
90 
91 #define PHYREG33			0x80
92 #define PHYREG33_PLL_KVCO_MASK		GENMASK(4, 2)
93 #define PHYREG33_PLL_KVCO_SHIFT		2
94 #define PHYREG33_PLL_KVCO_VALUE		2
95 #define PHYREG33_PLL_KVCO_VALUE_RK3576	4
96 
97 struct rockchip_combphy_priv;
98 
99 struct combphy_reg {
100 	u16 offset;
101 	u16 bitend;
102 	u16 bitstart;
103 	u16 disable;
104 	u16 enable;
105 };
106 
107 struct rockchip_combphy_grfcfg {
108 	struct combphy_reg pcie_mode_set;
109 	struct combphy_reg usb_mode_set;
110 	struct combphy_reg sgmii_mode_set;
111 	struct combphy_reg qsgmii_mode_set;
112 	struct combphy_reg pipe_rxterm_set;
113 	struct combphy_reg pipe_txelec_set;
114 	struct combphy_reg pipe_txcomp_set;
115 	struct combphy_reg pipe_clk_24m;
116 	struct combphy_reg pipe_clk_25m;
117 	struct combphy_reg pipe_clk_100m;
118 	struct combphy_reg pipe_phymode_sel;
119 	struct combphy_reg pipe_rate_sel;
120 	struct combphy_reg pipe_rxterm_sel;
121 	struct combphy_reg pipe_txelec_sel;
122 	struct combphy_reg pipe_txcomp_sel;
123 	struct combphy_reg pipe_clk_ext;
124 	struct combphy_reg pipe_sel_usb;
125 	struct combphy_reg pipe_sel_qsgmii;
126 	struct combphy_reg pipe_phy_status;
127 	struct combphy_reg con0_for_pcie;
128 	struct combphy_reg con1_for_pcie;
129 	struct combphy_reg con2_for_pcie;
130 	struct combphy_reg con3_for_pcie;
131 	struct combphy_reg con0_for_sata;
132 	struct combphy_reg con1_for_sata;
133 	struct combphy_reg con2_for_sata;
134 	struct combphy_reg con3_for_sata;
135 	struct combphy_reg pipe_con0_for_sata;
136 	struct combphy_reg pipe_con1_for_sata;
137 	struct combphy_reg pipe_xpcs_phy_ready;
138 	struct combphy_reg pipe_pcie1l0_sel;
139 	struct combphy_reg pipe_pcie1l1_sel;
140 };
141 
142 struct rockchip_combphy_cfg {
143 	unsigned int num_phys;
144 	unsigned int phy_ids[3];
145 	const struct rockchip_combphy_grfcfg *grfcfg;
146 	int (*combphy_cfg)(struct rockchip_combphy_priv *priv);
147 };
148 
149 struct rockchip_combphy_priv {
150 	u8 type;
151 	int id;
152 	void __iomem *mmio;
153 	int num_clks;
154 	struct clk_bulk_data *clks;
155 	struct device *dev;
156 	struct regmap *pipe_grf;
157 	struct regmap *phy_grf;
158 	struct phy *phy;
159 	struct reset_control *phy_rst;
160 	const struct rockchip_combphy_cfg *cfg;
161 	bool enable_ssc;
162 	bool ext_refclk;
163 	struct clk *refclk;
164 };
165 
rockchip_combphy_updatel(struct rockchip_combphy_priv * priv,int mask,int val,int reg)166 static void rockchip_combphy_updatel(struct rockchip_combphy_priv *priv,
167 				     int mask, int val, int reg)
168 {
169 	unsigned int temp;
170 
171 	temp = readl(priv->mmio + reg);
172 	temp = (temp & ~(mask)) | val;
173 	writel(temp, priv->mmio + reg);
174 }
175 
rockchip_combphy_param_write(struct regmap * base,const struct combphy_reg * reg,bool en)176 static int rockchip_combphy_param_write(struct regmap *base,
177 					const struct combphy_reg *reg, bool en)
178 {
179 	u32 val, mask, tmp;
180 
181 	tmp = en ? reg->enable : reg->disable;
182 	mask = GENMASK(reg->bitend, reg->bitstart);
183 	val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT);
184 
185 	return regmap_write(base, reg->offset, val);
186 }
187 
rockchip_combphy_is_ready(struct rockchip_combphy_priv * priv)188 static u32 rockchip_combphy_is_ready(struct rockchip_combphy_priv *priv)
189 {
190 	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
191 	u32 mask, val;
192 
193 	mask = GENMASK(cfg->pipe_phy_status.bitend,
194 		       cfg->pipe_phy_status.bitstart);
195 
196 	regmap_read(priv->phy_grf, cfg->pipe_phy_status.offset, &val);
197 	val = (val & mask) >> cfg->pipe_phy_status.bitstart;
198 
199 	return val;
200 }
201 
rockchip_combphy_init(struct phy * phy)202 static int rockchip_combphy_init(struct phy *phy)
203 {
204 	struct rockchip_combphy_priv *priv = phy_get_drvdata(phy);
205 	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
206 	u32 val;
207 	int ret;
208 
209 	ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks);
210 	if (ret) {
211 		dev_err(priv->dev, "failed to enable clks\n");
212 		return ret;
213 	}
214 
215 	switch (priv->type) {
216 	case PHY_TYPE_PCIE:
217 	case PHY_TYPE_USB3:
218 	case PHY_TYPE_SATA:
219 	case PHY_TYPE_SGMII:
220 	case PHY_TYPE_QSGMII:
221 		if (priv->cfg->combphy_cfg)
222 			ret = priv->cfg->combphy_cfg(priv);
223 		break;
224 	default:
225 		dev_err(priv->dev, "incompatible PHY type\n");
226 		ret = -EINVAL;
227 		break;
228 	}
229 
230 	if (ret) {
231 		dev_err(priv->dev, "failed to init phy for phy type %x\n", priv->type);
232 		goto err_clk;
233 	}
234 
235 	ret = reset_control_deassert(priv->phy_rst);
236 	if (ret)
237 		goto err_clk;
238 
239 	if (priv->type == PHY_TYPE_USB3) {
240 		ret = readx_poll_timeout_atomic(rockchip_combphy_is_ready,
241 						priv, val,
242 						val == cfg->pipe_phy_status.enable,
243 						10, 1000);
244 		if (ret)
245 			dev_warn(priv->dev, "wait phy status ready timeout\n");
246 	}
247 
248 	return 0;
249 
250 err_clk:
251 	clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
252 
253 	return ret;
254 }
255 
rockchip_combphy_exit(struct phy * phy)256 static int rockchip_combphy_exit(struct phy *phy)
257 {
258 	struct rockchip_combphy_priv *priv = phy_get_drvdata(phy);
259 
260 	clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
261 	reset_control_assert(priv->phy_rst);
262 
263 	return 0;
264 }
265 
266 static const struct phy_ops rockchip_combphy_ops = {
267 	.init = rockchip_combphy_init,
268 	.exit = rockchip_combphy_exit,
269 	.owner = THIS_MODULE,
270 };
271 
rockchip_combphy_xlate(struct device * dev,const struct of_phandle_args * args)272 static struct phy *rockchip_combphy_xlate(struct device *dev, const struct of_phandle_args *args)
273 {
274 	struct rockchip_combphy_priv *priv = dev_get_drvdata(dev);
275 
276 	if (args->args_count != 1) {
277 		dev_err(dev, "invalid number of arguments\n");
278 		return ERR_PTR(-EINVAL);
279 	}
280 
281 	if (priv->type != PHY_NONE && priv->type != args->args[0])
282 		dev_warn(dev, "phy type select %d overwriting type %d\n",
283 			 args->args[0], priv->type);
284 
285 	priv->type = args->args[0];
286 
287 	return priv->phy;
288 }
289 
rockchip_combphy_parse_dt(struct device * dev,struct rockchip_combphy_priv * priv)290 static int rockchip_combphy_parse_dt(struct device *dev, struct rockchip_combphy_priv *priv)
291 {
292 	int i;
293 
294 	priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks);
295 	if (priv->num_clks < 1)
296 		return -EINVAL;
297 
298 	priv->refclk = NULL;
299 	for (i = 0; i < priv->num_clks; i++) {
300 		if (!strncmp(priv->clks[i].id, "ref", 3)) {
301 			priv->refclk = priv->clks[i].clk;
302 			break;
303 		}
304 	}
305 
306 	if (!priv->refclk) {
307 		dev_err(dev, "no refclk found\n");
308 		return -EINVAL;
309 	}
310 
311 	priv->pipe_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pipe-grf");
312 	if (IS_ERR(priv->pipe_grf)) {
313 		dev_err(dev, "failed to find peri_ctrl pipe-grf regmap\n");
314 		return PTR_ERR(priv->pipe_grf);
315 	}
316 
317 	priv->phy_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pipe-phy-grf");
318 	if (IS_ERR(priv->phy_grf)) {
319 		dev_err(dev, "failed to find peri_ctrl pipe-phy-grf regmap\n");
320 		return PTR_ERR(priv->phy_grf);
321 	}
322 
323 	priv->enable_ssc = device_property_present(dev, "rockchip,enable-ssc");
324 
325 	priv->ext_refclk = device_property_present(dev, "rockchip,ext-refclk");
326 
327 	priv->phy_rst = devm_reset_control_get_exclusive(dev, "phy");
328 	/* fallback to old behaviour */
329 	if (PTR_ERR(priv->phy_rst) == -ENOENT)
330 		priv->phy_rst = devm_reset_control_array_get_exclusive(dev);
331 	if (IS_ERR(priv->phy_rst))
332 		return dev_err_probe(dev, PTR_ERR(priv->phy_rst), "failed to get phy reset\n");
333 
334 	return 0;
335 }
336 
rockchip_combphy_probe(struct platform_device * pdev)337 static int rockchip_combphy_probe(struct platform_device *pdev)
338 {
339 	struct phy_provider *phy_provider;
340 	struct device *dev = &pdev->dev;
341 	struct rockchip_combphy_priv *priv;
342 	const struct rockchip_combphy_cfg *phy_cfg;
343 	struct resource *res;
344 	int ret, id;
345 
346 	phy_cfg = of_device_get_match_data(dev);
347 	if (!phy_cfg) {
348 		dev_err(dev, "no OF match data provided\n");
349 		return -EINVAL;
350 	}
351 
352 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
353 	if (!priv)
354 		return -ENOMEM;
355 
356 	priv->mmio = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
357 	if (IS_ERR(priv->mmio)) {
358 		ret = PTR_ERR(priv->mmio);
359 		return ret;
360 	}
361 
362 	/* find the phy-id from the io address */
363 	priv->id = -ENODEV;
364 	for (id = 0; id < phy_cfg->num_phys; id++) {
365 		if (res->start == phy_cfg->phy_ids[id]) {
366 			priv->id = id;
367 			break;
368 		}
369 	}
370 
371 	priv->dev = dev;
372 	priv->type = PHY_NONE;
373 	priv->cfg = phy_cfg;
374 
375 	ret = rockchip_combphy_parse_dt(dev, priv);
376 	if (ret)
377 		return ret;
378 
379 	ret = reset_control_assert(priv->phy_rst);
380 	if (ret) {
381 		dev_err(dev, "failed to reset phy\n");
382 		return ret;
383 	}
384 
385 	priv->phy = devm_phy_create(dev, NULL, &rockchip_combphy_ops);
386 	if (IS_ERR(priv->phy)) {
387 		dev_err(dev, "failed to create combphy\n");
388 		return PTR_ERR(priv->phy);
389 	}
390 
391 	dev_set_drvdata(dev, priv);
392 	phy_set_drvdata(priv->phy, priv);
393 
394 	phy_provider = devm_of_phy_provider_register(dev, rockchip_combphy_xlate);
395 
396 	return PTR_ERR_OR_ZERO(phy_provider);
397 }
398 
rk3568_combphy_cfg(struct rockchip_combphy_priv * priv)399 static int rk3568_combphy_cfg(struct rockchip_combphy_priv *priv)
400 {
401 	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
402 	unsigned long rate;
403 	u32 val;
404 
405 	switch (priv->type) {
406 	case PHY_TYPE_PCIE:
407 		/* Set SSC downward spread spectrum. */
408 		rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK,
409 					 PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT,
410 					 PHYREG32);
411 
412 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_pcie, true);
413 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_pcie, true);
414 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_pcie, true);
415 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_pcie, true);
416 		break;
417 
418 	case PHY_TYPE_USB3:
419 		/* Set SSC downward spread spectrum. */
420 		rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK,
421 					 PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT,
422 					 PHYREG32);
423 
424 		/* Enable adaptive CTLE for USB3.0 Rx. */
425 		val = readl(priv->mmio + PHYREG15);
426 		val |= PHYREG15_CTLE_EN;
427 		writel(val, priv->mmio + PHYREG15);
428 
429 		/* Set PLL KVCO fine tuning signals. */
430 		rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK,
431 					 PHYREG33_PLL_KVCO_VALUE << PHYREG33_PLL_KVCO_SHIFT,
432 					 PHYREG33);
433 
434 		/* Enable controlling random jitter. */
435 		writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12);
436 
437 		/* Set PLL input clock divider 1/2. */
438 		rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK,
439 					 PHYREG6_PLL_DIV_2 << PHYREG6_PLL_DIV_SHIFT,
440 					 PHYREG6);
441 
442 		writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18);
443 		writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11);
444 
445 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_usb, true);
446 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false);
447 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false);
448 		rockchip_combphy_param_write(priv->phy_grf, &cfg->usb_mode_set, true);
449 		break;
450 
451 	case PHY_TYPE_SATA:
452 		/* Enable adaptive CTLE for SATA Rx. */
453 		val = readl(priv->mmio + PHYREG15);
454 		val |= PHYREG15_CTLE_EN;
455 		writel(val, priv->mmio + PHYREG15);
456 		/*
457 		 * Set tx_rterm=50ohm and rx_rterm=44ohm for SATA.
458 		 * 0: 60ohm, 8: 50ohm 15: 44ohm (by step abort 1ohm)
459 		 */
460 		val = PHYREG7_TX_RTERM_50OHM << PHYREG7_TX_RTERM_SHIFT;
461 		val |= PHYREG7_RX_RTERM_44OHM << PHYREG7_RX_RTERM_SHIFT;
462 		writel(val, priv->mmio + PHYREG7);
463 
464 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_sata, true);
465 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_sata, true);
466 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_sata, true);
467 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_sata, true);
468 		rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true);
469 		break;
470 
471 	case PHY_TYPE_SGMII:
472 		rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true);
473 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true);
474 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true);
475 		rockchip_combphy_param_write(priv->phy_grf, &cfg->sgmii_mode_set, true);
476 		break;
477 
478 	case PHY_TYPE_QSGMII:
479 		rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true);
480 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true);
481 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_rate_sel, true);
482 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true);
483 		rockchip_combphy_param_write(priv->phy_grf, &cfg->qsgmii_mode_set, true);
484 		break;
485 
486 	default:
487 		dev_err(priv->dev, "incompatible PHY type\n");
488 		return -EINVAL;
489 	}
490 
491 	rate = clk_get_rate(priv->refclk);
492 
493 	switch (rate) {
494 	case REF_CLOCK_24MHz:
495 		if (priv->type == PHY_TYPE_USB3 || priv->type == PHY_TYPE_SATA) {
496 			/* Set ssc_cnt[9:0]=0101111101 & 31.5KHz. */
497 			val = PHYREG15_SSC_CNT_VALUE << PHYREG15_SSC_CNT_SHIFT;
498 			rockchip_combphy_updatel(priv, PHYREG15_SSC_CNT_MASK,
499 						 val, PHYREG15);
500 
501 			writel(PHYREG16_SSC_CNT_VALUE, priv->mmio + PHYREG16);
502 		}
503 		break;
504 
505 	case REF_CLOCK_25MHz:
506 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_25m, true);
507 		break;
508 
509 	case REF_CLOCK_100MHz:
510 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_100m, true);
511 		if (priv->type == PHY_TYPE_PCIE) {
512 			/* PLL KVCO  fine tuning. */
513 			val = PHYREG33_PLL_KVCO_VALUE << PHYREG33_PLL_KVCO_SHIFT;
514 			rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK,
515 						 val, PHYREG33);
516 
517 			/* Enable controlling random jitter. */
518 			writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12);
519 
520 			val = PHYREG6_PLL_DIV_2 << PHYREG6_PLL_DIV_SHIFT;
521 			rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK,
522 						 val, PHYREG6);
523 
524 			writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18);
525 			writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11);
526 		} else if (priv->type == PHY_TYPE_SATA) {
527 			/* downward spread spectrum +500ppm */
528 			val = PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT;
529 			val |= PHYREG32_SSC_OFFSET_500PPM << PHYREG32_SSC_OFFSET_SHIFT;
530 			rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, val, PHYREG32);
531 		}
532 		break;
533 
534 	default:
535 		dev_err(priv->dev, "unsupported rate: %lu\n", rate);
536 		return -EINVAL;
537 	}
538 
539 	if (priv->ext_refclk) {
540 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_ext, true);
541 		if (priv->type == PHY_TYPE_PCIE && rate == REF_CLOCK_100MHz) {
542 			val = PHYREG13_RESISTER_HIGH_Z << PHYREG13_RESISTER_SHIFT;
543 			val |= PHYREG13_CKRCV_AMP0;
544 			rockchip_combphy_updatel(priv, PHYREG13_RESISTER_MASK, val, PHYREG13);
545 
546 			val = readl(priv->mmio + PHYREG14);
547 			val |= PHYREG14_CKRCV_AMP1;
548 			writel(val, priv->mmio + PHYREG14);
549 		}
550 	}
551 
552 	if (priv->enable_ssc) {
553 		val = readl(priv->mmio + PHYREG8);
554 		val |= PHYREG8_SSC_EN;
555 		writel(val, priv->mmio + PHYREG8);
556 	}
557 
558 	return 0;
559 }
560 
561 static const struct rockchip_combphy_grfcfg rk3568_combphy_grfcfgs = {
562 	/* pipe-phy-grf */
563 	.pcie_mode_set		= { 0x0000, 5, 0, 0x00, 0x11 },
564 	.usb_mode_set		= { 0x0000, 5, 0, 0x00, 0x04 },
565 	.sgmii_mode_set		= { 0x0000, 5, 0, 0x00, 0x01 },
566 	.qsgmii_mode_set	= { 0x0000, 5, 0, 0x00, 0x21 },
567 	.pipe_rxterm_set	= { 0x0000, 12, 12, 0x00, 0x01 },
568 	.pipe_txelec_set	= { 0x0004, 1, 1, 0x00, 0x01 },
569 	.pipe_txcomp_set	= { 0x0004, 4, 4, 0x00, 0x01 },
570 	.pipe_clk_25m		= { 0x0004, 14, 13, 0x00, 0x01 },
571 	.pipe_clk_100m		= { 0x0004, 14, 13, 0x00, 0x02 },
572 	.pipe_phymode_sel	= { 0x0008, 1, 1, 0x00, 0x01 },
573 	.pipe_rate_sel		= { 0x0008, 2, 2, 0x00, 0x01 },
574 	.pipe_rxterm_sel	= { 0x0008, 8, 8, 0x00, 0x01 },
575 	.pipe_txelec_sel	= { 0x0008, 12, 12, 0x00, 0x01 },
576 	.pipe_txcomp_sel	= { 0x0008, 15, 15, 0x00, 0x01 },
577 	.pipe_clk_ext		= { 0x000c, 9, 8, 0x02, 0x01 },
578 	.pipe_sel_usb		= { 0x000c, 14, 13, 0x00, 0x01 },
579 	.pipe_sel_qsgmii	= { 0x000c, 15, 13, 0x00, 0x07 },
580 	.pipe_phy_status	= { 0x0034, 6, 6, 0x01, 0x00 },
581 	.con0_for_pcie		= { 0x0000, 15, 0, 0x00, 0x1000 },
582 	.con1_for_pcie		= { 0x0004, 15, 0, 0x00, 0x0000 },
583 	.con2_for_pcie		= { 0x0008, 15, 0, 0x00, 0x0101 },
584 	.con3_for_pcie		= { 0x000c, 15, 0, 0x00, 0x0200 },
585 	.con0_for_sata		= { 0x0000, 15, 0, 0x00, 0x0119 },
586 	.con1_for_sata		= { 0x0004, 15, 0, 0x00, 0x0040 },
587 	.con2_for_sata		= { 0x0008, 15, 0, 0x00, 0x80c3 },
588 	.con3_for_sata		= { 0x000c, 15, 0, 0x00, 0x4407 },
589 	/* pipe-grf */
590 	.pipe_con0_for_sata	= { 0x0000, 15, 0, 0x00, 0x2220 },
591 	.pipe_xpcs_phy_ready	= { 0x0040, 2, 2, 0x00, 0x01 },
592 };
593 
594 static const struct rockchip_combphy_cfg rk3568_combphy_cfgs = {
595 	.num_phys = 3,
596 	.phy_ids = {
597 		0xfe820000,
598 		0xfe830000,
599 		0xfe840000,
600 	},
601 	.grfcfg		= &rk3568_combphy_grfcfgs,
602 	.combphy_cfg	= rk3568_combphy_cfg,
603 };
604 
rk3576_combphy_cfg(struct rockchip_combphy_priv * priv)605 static int rk3576_combphy_cfg(struct rockchip_combphy_priv *priv)
606 {
607 	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
608 	unsigned long rate;
609 	u32 val;
610 
611 	switch (priv->type) {
612 	case PHY_TYPE_PCIE:
613 		/* Set SSC downward spread spectrum */
614 		val = FIELD_PREP(PHYREG32_SSC_MASK, PHYREG32_SSC_DOWNWARD);
615 		rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, val, PHYREG32);
616 
617 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_pcie, true);
618 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_pcie, true);
619 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_pcie, true);
620 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_pcie, true);
621 		break;
622 
623 	case PHY_TYPE_USB3:
624 		/* Set SSC downward spread spectrum */
625 		val = FIELD_PREP(PHYREG32_SSC_MASK, PHYREG32_SSC_DOWNWARD);
626 		rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, val, PHYREG32);
627 
628 		/* Enable adaptive CTLE for USB3.0 Rx */
629 		val = readl(priv->mmio + PHYREG15);
630 		val |= PHYREG15_CTLE_EN;
631 		writel(val, priv->mmio + PHYREG15);
632 
633 		/* Set PLL KVCO fine tuning signals */
634 		rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK, BIT(3), PHYREG33);
635 
636 		/* Set PLL LPF R1 to su_trim[10:7]=1001 */
637 		writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12);
638 
639 		/* Set PLL input clock divider 1/2 */
640 		val = FIELD_PREP(PHYREG6_PLL_DIV_MASK, PHYREG6_PLL_DIV_2);
641 		rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK, val, PHYREG6);
642 
643 		/* Set PLL loop divider */
644 		writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18);
645 
646 		/* Set PLL KVCO to min and set PLL charge pump current to max */
647 		writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11);
648 
649 		/* Set Rx squelch input filler bandwidth */
650 		writel(PHYREG21_RX_SQUELCH_VAL, priv->mmio + PHYREG21);
651 
652 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false);
653 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false);
654 		rockchip_combphy_param_write(priv->phy_grf, &cfg->usb_mode_set, true);
655 		break;
656 
657 	case PHY_TYPE_SATA:
658 		/* Enable adaptive CTLE for SATA Rx */
659 		val = readl(priv->mmio + PHYREG15);
660 		val |= PHYREG15_CTLE_EN;
661 		writel(val, priv->mmio + PHYREG15);
662 
663 		/* Set tx_rterm = 50 ohm and rx_rterm = 43.5 ohm */
664 		val = PHYREG7_TX_RTERM_50OHM << PHYREG7_TX_RTERM_SHIFT;
665 		val |= PHYREG7_RX_RTERM_44OHM << PHYREG7_RX_RTERM_SHIFT;
666 		writel(val, priv->mmio + PHYREG7);
667 
668 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_sata, true);
669 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_sata, true);
670 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_sata, true);
671 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_sata, true);
672 		rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true);
673 		rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_con1_for_sata, true);
674 		break;
675 
676 	default:
677 		dev_err(priv->dev, "incompatible PHY type\n");
678 		return -EINVAL;
679 	}
680 
681 	rate = clk_get_rate(priv->refclk);
682 
683 	switch (rate) {
684 	case REF_CLOCK_24MHz:
685 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_24m, true);
686 		if (priv->type == PHY_TYPE_USB3 || priv->type == PHY_TYPE_SATA) {
687 			/* Set ssc_cnt[9:0]=0101111101 & 31.5KHz */
688 			val = FIELD_PREP(PHYREG15_SSC_CNT_MASK, PHYREG15_SSC_CNT_VALUE);
689 			rockchip_combphy_updatel(priv, PHYREG15_SSC_CNT_MASK,
690 						 val, PHYREG15);
691 
692 			writel(PHYREG16_SSC_CNT_VALUE, priv->mmio + PHYREG16);
693 		} else if (priv->type == PHY_TYPE_PCIE) {
694 			/* PLL KVCO tuning fine */
695 			val = FIELD_PREP(PHYREG33_PLL_KVCO_MASK, PHYREG33_PLL_KVCO_VALUE_RK3576);
696 			rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK,
697 						 val, PHYREG33);
698 
699 			/* Set up rx_pck invert and rx msb to disable */
700 			writel(0x00, priv->mmio + PHYREG27);
701 
702 			/*
703 			 * Set up SU adjust signal:
704 			 * su_trim[7:0],   PLL KVCO adjust bits[2:0] to min
705 			 * su_trim[15:8],  PLL LPF R1 adujst bits[9:7]=3'b011
706 			 * su_trim[31:24], CKDRV adjust
707 			 */
708 			writel(0x90, priv->mmio + PHYREG11);
709 			writel(0x02, priv->mmio + PHYREG12);
710 			writel(0x57, priv->mmio + PHYREG14);
711 
712 			writel(PHYREG16_SSC_CNT_VALUE, priv->mmio + PHYREG16);
713 		}
714 		break;
715 
716 	case REF_CLOCK_25MHz:
717 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_25m, true);
718 		break;
719 
720 	case REF_CLOCK_100MHz:
721 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_100m, true);
722 		if (priv->type == PHY_TYPE_PCIE) {
723 			/* gate_tx_pck_sel length select work for L1SS */
724 			writel(0xc0, priv->mmio + PHYREG30);
725 
726 			/* PLL KVCO tuning fine */
727 			val = FIELD_PREP(PHYREG33_PLL_KVCO_MASK, PHYREG33_PLL_KVCO_VALUE_RK3576);
728 			rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK,
729 						 val, PHYREG33);
730 
731 			/* Set up rx_trim: PLL LPF C1 85pf R1 1.25kohm */
732 			writel(0x4c, priv->mmio + PHYREG27);
733 
734 			/*
735 			 * Set up SU adjust signal:
736 			 * su_trim[7:0],   PLL KVCO adjust bits[2:0] to min
737 			 * su_trim[15:8],  bypass PLL loop divider code, and
738 			 *                 PLL LPF R1 adujst bits[9:7]=3'b101
739 			 * su_trim[23:16], CKRCV adjust
740 			 * su_trim[31:24], CKDRV adjust
741 			 */
742 			writel(0x90, priv->mmio + PHYREG11);
743 			writel(0x43, priv->mmio + PHYREG12);
744 			writel(0x88, priv->mmio + PHYREG13);
745 			writel(0x56, priv->mmio + PHYREG14);
746 		} else if (priv->type == PHY_TYPE_SATA) {
747 			/* downward spread spectrum +500ppm */
748 			val = FIELD_PREP(PHYREG32_SSC_DIR_MASK, PHYREG32_SSC_DOWNWARD);
749 			val |= FIELD_PREP(PHYREG32_SSC_OFFSET_MASK, PHYREG32_SSC_OFFSET_500PPM);
750 			rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, val, PHYREG32);
751 
752 			/* ssc ppm adjust to 3500ppm */
753 			rockchip_combphy_updatel(priv, PHYREG10_SSC_PCM_MASK,
754 						 PHYREG10_SSC_PCM_3500PPM,
755 						 PHYREG10);
756 		}
757 		break;
758 
759 	default:
760 		dev_err(priv->dev, "Unsupported rate: %lu\n", rate);
761 		return -EINVAL;
762 	}
763 
764 	if (priv->ext_refclk) {
765 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_ext, true);
766 		if (priv->type == PHY_TYPE_PCIE && rate == REF_CLOCK_100MHz) {
767 			val = FIELD_PREP(PHYREG33_PLL_KVCO_MASK, PHYREG33_PLL_KVCO_VALUE_RK3576);
768 			rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK,
769 						 val, PHYREG33);
770 
771 			/* Set up rx_trim: PLL LPF C1 85pf R1 2.5kohm */
772 			writel(0x0c, priv->mmio + PHYREG27);
773 
774 			/*
775 			 * Set up SU adjust signal:
776 			 * su_trim[7:0],   PLL KVCO adjust bits[2:0] to min
777 			 * su_trim[15:8],  bypass PLL loop divider code, and
778 			 *                 PLL LPF R1 adujst bits[9:7]=3'b101.
779 			 * su_trim[23:16], CKRCV adjust
780 			 * su_trim[31:24], CKDRV adjust
781 			 */
782 			writel(0x90, priv->mmio + PHYREG11);
783 			writel(0x43, priv->mmio + PHYREG12);
784 			writel(0x88, priv->mmio + PHYREG13);
785 			writel(0x56, priv->mmio + PHYREG14);
786 		}
787 	}
788 
789 	if (priv->enable_ssc) {
790 		val = readl(priv->mmio + PHYREG8);
791 		val |= PHYREG8_SSC_EN;
792 		writel(val, priv->mmio + PHYREG8);
793 
794 		if (priv->type == PHY_TYPE_PCIE && rate == REF_CLOCK_24MHz) {
795 			/* Set PLL loop divider */
796 			writel(0x00, priv->mmio + PHYREG17);
797 			writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18);
798 
799 			/* Set up rx_pck invert and rx msb to disable */
800 			writel(0x00, priv->mmio + PHYREG27);
801 
802 			/*
803 			 * Set up SU adjust signal:
804 			 * su_trim[7:0],   PLL KVCO adjust bits[2:0] to min
805 			 * su_trim[15:8],  PLL LPF R1 adujst bits[9:7]=3'b101
806 			 * su_trim[23:16], CKRCV adjust
807 			 * su_trim[31:24], CKDRV adjust
808 			 */
809 			writel(0x90, priv->mmio + PHYREG11);
810 			writel(0x02, priv->mmio + PHYREG12);
811 			writel(0x08, priv->mmio + PHYREG13);
812 			writel(0x57, priv->mmio + PHYREG14);
813 			writel(0x40, priv->mmio + PHYREG15);
814 
815 			writel(PHYREG16_SSC_CNT_VALUE, priv->mmio + PHYREG16);
816 
817 			val = FIELD_PREP(PHYREG33_PLL_KVCO_MASK, PHYREG33_PLL_KVCO_VALUE_RK3576);
818 			writel(val, priv->mmio + PHYREG33);
819 		}
820 	}
821 
822 	return 0;
823 }
824 
825 static const struct rockchip_combphy_grfcfg rk3576_combphy_grfcfgs = {
826 	/* pipe-phy-grf */
827 	.pcie_mode_set		= { 0x0000, 5, 0, 0x00, 0x11 },
828 	.usb_mode_set		= { 0x0000, 5, 0, 0x00, 0x04 },
829 	.pipe_rxterm_set	= { 0x0000, 12, 12, 0x00, 0x01 },
830 	.pipe_txelec_set	= { 0x0004, 1, 1, 0x00, 0x01 },
831 	.pipe_txcomp_set	= { 0x0004, 4, 4, 0x00, 0x01 },
832 	.pipe_clk_24m		= { 0x0004, 14, 13, 0x00, 0x00 },
833 	.pipe_clk_25m		= { 0x0004, 14, 13, 0x00, 0x01 },
834 	.pipe_clk_100m		= { 0x0004, 14, 13, 0x00, 0x02 },
835 	.pipe_phymode_sel	= { 0x0008, 1, 1, 0x00, 0x01 },
836 	.pipe_rate_sel		= { 0x0008, 2, 2, 0x00, 0x01 },
837 	.pipe_rxterm_sel	= { 0x0008, 8, 8, 0x00, 0x01 },
838 	.pipe_txelec_sel	= { 0x0008, 12, 12, 0x00, 0x01 },
839 	.pipe_txcomp_sel	= { 0x0008, 15, 15, 0x00, 0x01 },
840 	.pipe_clk_ext		= { 0x000c, 9, 8, 0x02, 0x01 },
841 	.pipe_phy_status	= { 0x0034, 6, 6, 0x01, 0x00 },
842 	.con0_for_pcie		= { 0x0000, 15, 0, 0x00, 0x1000 },
843 	.con1_for_pcie		= { 0x0004, 15, 0, 0x00, 0x0000 },
844 	.con2_for_pcie		= { 0x0008, 15, 0, 0x00, 0x0101 },
845 	.con3_for_pcie		= { 0x000c, 15, 0, 0x00, 0x0200 },
846 	.con0_for_sata		= { 0x0000, 15, 0, 0x00, 0x0129 },
847 	.con1_for_sata		= { 0x0004, 15, 0, 0x00, 0x0000 },
848 	.con2_for_sata		= { 0x0008, 15, 0, 0x00, 0x80c1 },
849 	.con3_for_sata		= { 0x000c, 15, 0, 0x00, 0x0407 },
850 	/* php-grf */
851 	.pipe_con0_for_sata	= { 0x001C, 2, 0, 0x00, 0x2 },
852 	.pipe_con1_for_sata	= { 0x0020, 2, 0, 0x00, 0x2 },
853 };
854 
855 static const struct rockchip_combphy_cfg rk3576_combphy_cfgs = {
856 	.num_phys = 2,
857 	.phy_ids = {
858 		0x2b050000,
859 		0x2b060000
860 	},
861 	.grfcfg		= &rk3576_combphy_grfcfgs,
862 	.combphy_cfg	= rk3576_combphy_cfg,
863 };
864 
rk3588_combphy_cfg(struct rockchip_combphy_priv * priv)865 static int rk3588_combphy_cfg(struct rockchip_combphy_priv *priv)
866 {
867 	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
868 	unsigned long rate;
869 	u32 val;
870 
871 	switch (priv->type) {
872 	case PHY_TYPE_PCIE:
873 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_pcie, true);
874 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_pcie, true);
875 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_pcie, true);
876 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_pcie, true);
877 		switch (priv->id) {
878 		case 1:
879 			rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_pcie1l0_sel, true);
880 			break;
881 		case 2:
882 			rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_pcie1l1_sel, true);
883 			break;
884 		}
885 		break;
886 	case PHY_TYPE_USB3:
887 		/* Set SSC downward spread spectrum */
888 		rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK,
889 					 PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT,
890 					 PHYREG32);
891 
892 		/* Enable adaptive CTLE for USB3.0 Rx. */
893 		val = readl(priv->mmio + PHYREG15);
894 		val |= PHYREG15_CTLE_EN;
895 		writel(val, priv->mmio + PHYREG15);
896 
897 		/* Set PLL KVCO fine tuning signals. */
898 		rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK,
899 					 PHYREG33_PLL_KVCO_VALUE << PHYREG33_PLL_KVCO_SHIFT,
900 					 PHYREG33);
901 
902 		/* Enable controlling random jitter. */
903 		writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12);
904 
905 		/* Set PLL input clock divider 1/2. */
906 		rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK,
907 					 PHYREG6_PLL_DIV_2 << PHYREG6_PLL_DIV_SHIFT,
908 					 PHYREG6);
909 
910 		writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18);
911 		writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11);
912 
913 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false);
914 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false);
915 		rockchip_combphy_param_write(priv->phy_grf, &cfg->usb_mode_set, true);
916 		break;
917 	case PHY_TYPE_SATA:
918 		/* Enable adaptive CTLE for SATA Rx. */
919 		val = readl(priv->mmio + PHYREG15);
920 		val |= PHYREG15_CTLE_EN;
921 		writel(val, priv->mmio + PHYREG15);
922 		/*
923 		 * Set tx_rterm=50ohm and rx_rterm=44ohm for SATA.
924 		 * 0: 60ohm, 8: 50ohm 15: 44ohm (by step abort 1ohm)
925 		 */
926 		val = PHYREG7_TX_RTERM_50OHM << PHYREG7_TX_RTERM_SHIFT;
927 		val |= PHYREG7_RX_RTERM_44OHM << PHYREG7_RX_RTERM_SHIFT;
928 		writel(val, priv->mmio + PHYREG7);
929 
930 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_sata, true);
931 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_sata, true);
932 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_sata, true);
933 		rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_sata, true);
934 		rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true);
935 		rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_con1_for_sata, true);
936 		break;
937 	case PHY_TYPE_SGMII:
938 	case PHY_TYPE_QSGMII:
939 	default:
940 		dev_err(priv->dev, "incompatible PHY type\n");
941 		return -EINVAL;
942 	}
943 
944 	rate = clk_get_rate(priv->refclk);
945 
946 	switch (rate) {
947 	case REF_CLOCK_24MHz:
948 		if (priv->type == PHY_TYPE_USB3 || priv->type == PHY_TYPE_SATA) {
949 			/* Set ssc_cnt[9:0]=0101111101 & 31.5KHz. */
950 			val = PHYREG15_SSC_CNT_VALUE << PHYREG15_SSC_CNT_SHIFT;
951 			rockchip_combphy_updatel(priv, PHYREG15_SSC_CNT_MASK,
952 						 val, PHYREG15);
953 
954 			writel(PHYREG16_SSC_CNT_VALUE, priv->mmio + PHYREG16);
955 		}
956 		break;
957 
958 	case REF_CLOCK_25MHz:
959 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_25m, true);
960 		break;
961 	case REF_CLOCK_100MHz:
962 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_100m, true);
963 		if (priv->type == PHY_TYPE_PCIE) {
964 			/* PLL KVCO fine tuning. */
965 			val = 4 << PHYREG33_PLL_KVCO_SHIFT;
966 			rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK,
967 						 val, PHYREG33);
968 
969 			/* Enable controlling random jitter. */
970 			writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12);
971 
972 			/* Set up rx_trim: PLL LPF C1 85pf R1 1.25kohm */
973 			writel(PHYREG27_RX_TRIM_RK3588, priv->mmio + PHYREG27);
974 
975 			/* Set up su_trim:  */
976 			writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11);
977 		} else if (priv->type == PHY_TYPE_SATA) {
978 			/* downward spread spectrum +500ppm */
979 			val = PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT;
980 			val |= PHYREG32_SSC_OFFSET_500PPM << PHYREG32_SSC_OFFSET_SHIFT;
981 			rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, val, PHYREG32);
982 		}
983 		break;
984 	default:
985 		dev_err(priv->dev, "Unsupported rate: %lu\n", rate);
986 		return -EINVAL;
987 	}
988 
989 	if (priv->ext_refclk) {
990 		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_ext, true);
991 		if (priv->type == PHY_TYPE_PCIE && rate == REF_CLOCK_100MHz) {
992 			val = PHYREG13_RESISTER_HIGH_Z << PHYREG13_RESISTER_SHIFT;
993 			val |= PHYREG13_CKRCV_AMP0;
994 			rockchip_combphy_updatel(priv, PHYREG13_RESISTER_MASK, val, PHYREG13);
995 
996 			val = readl(priv->mmio + PHYREG14);
997 			val |= PHYREG14_CKRCV_AMP1;
998 			writel(val, priv->mmio + PHYREG14);
999 		}
1000 	}
1001 
1002 	if (priv->enable_ssc) {
1003 		val = readl(priv->mmio + PHYREG8);
1004 		val |= PHYREG8_SSC_EN;
1005 		writel(val, priv->mmio + PHYREG8);
1006 	}
1007 
1008 	return 0;
1009 }
1010 
1011 static const struct rockchip_combphy_grfcfg rk3588_combphy_grfcfgs = {
1012 	/* pipe-phy-grf */
1013 	.pcie_mode_set		= { 0x0000, 5, 0, 0x00, 0x11 },
1014 	.usb_mode_set		= { 0x0000, 5, 0, 0x00, 0x04 },
1015 	.pipe_rxterm_set	= { 0x0000, 12, 12, 0x00, 0x01 },
1016 	.pipe_txelec_set	= { 0x0004, 1, 1, 0x00, 0x01 },
1017 	.pipe_txcomp_set	= { 0x0004, 4, 4, 0x00, 0x01 },
1018 	.pipe_clk_25m		= { 0x0004, 14, 13, 0x00, 0x01 },
1019 	.pipe_clk_100m		= { 0x0004, 14, 13, 0x00, 0x02 },
1020 	.pipe_rxterm_sel	= { 0x0008, 8, 8, 0x00, 0x01 },
1021 	.pipe_txelec_sel	= { 0x0008, 12, 12, 0x00, 0x01 },
1022 	.pipe_txcomp_sel	= { 0x0008, 15, 15, 0x00, 0x01 },
1023 	.pipe_clk_ext		= { 0x000c, 9, 8, 0x02, 0x01 },
1024 	.pipe_phy_status	= { 0x0034, 6, 6, 0x01, 0x00 },
1025 	.con0_for_pcie		= { 0x0000, 15, 0, 0x00, 0x1000 },
1026 	.con1_for_pcie		= { 0x0004, 15, 0, 0x00, 0x0000 },
1027 	.con2_for_pcie		= { 0x0008, 15, 0, 0x00, 0x0101 },
1028 	.con3_for_pcie		= { 0x000c, 15, 0, 0x00, 0x0200 },
1029 	.con0_for_sata		= { 0x0000, 15, 0, 0x00, 0x0129 },
1030 	.con1_for_sata		= { 0x0004, 15, 0, 0x00, 0x0000 },
1031 	.con2_for_sata		= { 0x0008, 15, 0, 0x00, 0x80c1 },
1032 	.con3_for_sata		= { 0x000c, 15, 0, 0x00, 0x0407 },
1033 	/* pipe-grf */
1034 	.pipe_con0_for_sata	= { 0x0000, 11, 5, 0x00, 0x22 },
1035 	.pipe_con1_for_sata	= { 0x0000, 2, 0, 0x00, 0x2 },
1036 	.pipe_pcie1l0_sel	= { 0x0100, 0, 0, 0x01, 0x0 },
1037 	.pipe_pcie1l1_sel	= { 0x0100, 1, 1, 0x01, 0x0 },
1038 };
1039 
1040 static const struct rockchip_combphy_cfg rk3588_combphy_cfgs = {
1041 	.num_phys = 3,
1042 	.phy_ids = {
1043 		0xfee00000,
1044 		0xfee10000,
1045 		0xfee20000,
1046 	},
1047 	.grfcfg		= &rk3588_combphy_grfcfgs,
1048 	.combphy_cfg	= rk3588_combphy_cfg,
1049 };
1050 
1051 static const struct of_device_id rockchip_combphy_of_match[] = {
1052 	{
1053 		.compatible = "rockchip,rk3568-naneng-combphy",
1054 		.data = &rk3568_combphy_cfgs,
1055 	},
1056 	{
1057 		.compatible = "rockchip,rk3576-naneng-combphy",
1058 		.data = &rk3576_combphy_cfgs,
1059 	},
1060 	{
1061 		.compatible = "rockchip,rk3588-naneng-combphy",
1062 		.data = &rk3588_combphy_cfgs,
1063 	},
1064 	{ },
1065 };
1066 MODULE_DEVICE_TABLE(of, rockchip_combphy_of_match);
1067 
1068 static struct platform_driver rockchip_combphy_driver = {
1069 	.probe	= rockchip_combphy_probe,
1070 	.driver = {
1071 		.name = "rockchip-naneng-combphy",
1072 		.of_match_table = rockchip_combphy_of_match,
1073 	},
1074 };
1075 module_platform_driver(rockchip_combphy_driver);
1076 
1077 MODULE_DESCRIPTION("Rockchip NANENG COMBPHY driver");
1078 MODULE_LICENSE("GPL v2");
1079