blob: d5408ccac9768d1f5558dc0ce9c994f3f180f496 [file] [log] [blame]
Jagan Teki0d2d0bf2023-02-17 17:28:41 +05301// 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-rockchip/clock.h>
17#include <regmap.h>
18#include <reset-uclass.h>
19#include <dm/device_compat.h>
20
21#define BIT_WRITEABLE_SHIFT 16
22
23struct rockchip_combphy_priv;
24
25struct combphy_reg {
26 u16 offset;
27 u16 bitend;
28 u16 bitstart;
29 u16 disable;
30 u16 enable;
31};
32
33struct rockchip_combphy_grfcfg {
34 struct combphy_reg pcie_mode_set;
35 struct combphy_reg usb_mode_set;
36 struct combphy_reg sgmii_mode_set;
37 struct combphy_reg qsgmii_mode_set;
38 struct combphy_reg pipe_rxterm_set;
39 struct combphy_reg pipe_txelec_set;
40 struct combphy_reg pipe_txcomp_set;
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;
Jon Linbc980f62023-04-27 10:35:35 +030061 struct combphy_reg pipe_con1_for_sata;
Jagan Teki0d2d0bf2023-02-17 17:28:41 +053062 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
68struct rockchip_combphy_cfg {
69 const struct rockchip_combphy_grfcfg *grfcfg;
70 int (*combphy_cfg)(struct rockchip_combphy_priv *priv);
71};
72
73struct 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;
Eugen Hristev03a44832023-04-27 10:35:34 +030080 struct reset_ctl_bulk phy_rsts;
Jagan Teki0d2d0bf2023-02-17 17:28:41 +053081 struct clk ref_clk;
82 const struct rockchip_combphy_cfg *cfg;
83};
84
85static 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
97static 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
112static 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
127static 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
142static 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
157static 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
180static 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
Eugen Hristev03a44832023-04-27 10:35:34 +0300193 reset_deassert_bulk(&priv->phy_rsts);
Jagan Teki0d2d0bf2023-02-17 17:28:41 +0530194
195 return 0;
196
197err_clk:
198 clk_disable(&priv->ref_clk);
199
200 return ret;
201}
202
203static 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);
Eugen Hristev03a44832023-04-27 10:35:34 +0300208 reset_assert_bulk(&priv->phy_rsts);
Jagan Teki0d2d0bf2023-02-17 17:28:41 +0530209
210 return 0;
211}
212
213static 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
227static 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
233static int rockchip_combphy_parse_dt(struct udevice *dev,
234 struct rockchip_combphy_priv *priv)
235{
236 struct udevice *syscon;
237 int ret;
238
239 ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, "rockchip,pipe-grf", &syscon);
240 if (ret) {
241 dev_err(dev, "failed to find peri_ctrl pipe-grf regmap");
242 return ret;
243 }
244 priv->pipe_grf = syscon_get_regmap(syscon);
245
246 ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, "rockchip,pipe-phy-grf", &syscon);
247 if (ret) {
248 dev_err(dev, "failed to find peri_ctrl pipe-phy-grf regmap\n");
249 return ret;
250 }
251 priv->phy_grf = syscon_get_regmap(syscon);
252
253 ret = clk_get_by_index(dev, 0, &priv->ref_clk);
254 if (ret) {
255 dev_err(dev, "failed to find ref clock\n");
256 return PTR_ERR(&priv->ref_clk);
257 }
258
Eugen Hristev03a44832023-04-27 10:35:34 +0300259 ret = reset_get_bulk(dev, &priv->phy_rsts);
Jagan Teki0d2d0bf2023-02-17 17:28:41 +0530260 if (ret) {
261 dev_err(dev, "no phy reset control specified\n");
262 return ret;
263 }
264
265 return 0;
266}
267
268static int rockchip_combphy_probe(struct udevice *udev)
269{
270 struct rockchip_combphy_priv *priv = dev_get_priv(udev);
271 const struct rockchip_combphy_cfg *phy_cfg;
272
273 priv->mmio = (void __iomem *)dev_read_addr(udev);
274 if (IS_ERR(priv->mmio))
275 return PTR_ERR(priv->mmio);
276
277 phy_cfg = (const struct rockchip_combphy_cfg *)dev_get_driver_data(udev);
278 if (!phy_cfg) {
279 dev_err(udev, "No OF match data provided\n");
280 return -EINVAL;
281 }
282
283 priv->dev = udev;
284 priv->mode = PHY_TYPE_SATA;
285 priv->cfg = phy_cfg;
286
287 return rockchip_combphy_parse_dt(udev, priv);
288}
289
290static int rk3568_combphy_cfg(struct rockchip_combphy_priv *priv)
291{
292 const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
293 u32 val;
294
295 switch (priv->mode) {
296 case PHY_TYPE_PCIE:
297 /* Set SSC downward spread spectrum */
298 val = readl(priv->mmio + (0x1f << 2));
299 val &= ~GENMASK(5, 4);
300 val |= 0x01 << 4;
301 writel(val, priv->mmio + 0x7c);
302
303 param_write(priv->phy_grf, &cfg->con0_for_pcie, true);
304 param_write(priv->phy_grf, &cfg->con1_for_pcie, true);
305 param_write(priv->phy_grf, &cfg->con2_for_pcie, true);
306 param_write(priv->phy_grf, &cfg->con3_for_pcie, true);
307 break;
308 case PHY_TYPE_USB3:
309 /* Set SSC downward spread spectrum */
310 val = readl(priv->mmio + (0x1f << 2));
311 val &= ~GENMASK(5, 4);
312 val |= 0x01 << 4;
313 writel(val, priv->mmio + 0x7c);
314
315 /* Enable adaptive CTLE for USB3.0 Rx */
316 val = readl(priv->mmio + (0x0e << 2));
317 val &= ~GENMASK(0, 0);
318 val |= 0x01;
319 writel(val, priv->mmio + (0x0e << 2));
320
321 /* Set PLL KVCO fine tuning signals */
322 val = readl(priv->mmio + (0x20 << 2));
323 val &= ~(0x7 << 2);
324 val |= 0x2 << 2;
325 writel(val, priv->mmio + (0x20 << 2));
326
327 /* Set PLL LPF R1 to su_trim[10:7]=1001 */
328 writel(0x4, priv->mmio + (0xb << 2));
329
330 /* Set PLL input clock divider 1/2 */
331 val = readl(priv->mmio + (0x5 << 2));
332 val &= ~(0x3 << 6);
333 val |= 0x1 << 6;
334 writel(val, priv->mmio + (0x5 << 2));
335
336 /* Set PLL loop divider */
337 writel(0x32, priv->mmio + (0x11 << 2));
338
339 /* Set PLL KVCO to min and set PLL charge pump current to max */
340 writel(0xf0, priv->mmio + (0xa << 2));
341
342 param_write(priv->phy_grf, &cfg->pipe_sel_usb, true);
343 param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false);
344 param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false);
345 param_write(priv->phy_grf, &cfg->usb_mode_set, true);
346 break;
347 case PHY_TYPE_SATA:
348 writel(0x41, priv->mmio + 0x38);
349 writel(0x8F, priv->mmio + 0x18);
350 param_write(priv->phy_grf, &cfg->con0_for_sata, true);
351 param_write(priv->phy_grf, &cfg->con1_for_sata, true);
352 param_write(priv->phy_grf, &cfg->con2_for_sata, true);
353 param_write(priv->phy_grf, &cfg->con3_for_sata, true);
354 param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true);
355 break;
356 case PHY_TYPE_SGMII:
357 param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true);
358 param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true);
359 param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true);
360 param_write(priv->phy_grf, &cfg->sgmii_mode_set, true);
361 break;
362 case PHY_TYPE_QSGMII:
363 param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true);
364 param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true);
365 param_write(priv->phy_grf, &cfg->pipe_rate_sel, true);
366 param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true);
367 param_write(priv->phy_grf, &cfg->qsgmii_mode_set, true);
368 break;
369 default:
370 pr_err("%s, phy-type %d\n", __func__, priv->mode);
371 return -EINVAL;
372 }
373
374 /* The default ref clock is 25Mhz */
375 param_write(priv->phy_grf, &cfg->pipe_clk_25m, true);
376
377 if (dev_read_bool(priv->dev, "rockchip,enable-ssc")) {
378 val = readl(priv->mmio + (0x7 << 2));
379 val |= BIT(4);
380 writel(val, priv->mmio + (0x7 << 2));
381 }
382
383 return 0;
384}
385
386static const struct rockchip_combphy_grfcfg rk3568_combphy_grfcfgs = {
387 /* pipe-phy-grf */
388 .pcie_mode_set = { 0x0000, 5, 0, 0x00, 0x11 },
389 .usb_mode_set = { 0x0000, 5, 0, 0x00, 0x04 },
390 .sgmii_mode_set = { 0x0000, 5, 0, 0x00, 0x01 },
391 .qsgmii_mode_set = { 0x0000, 5, 0, 0x00, 0x21 },
392 .pipe_rxterm_set = { 0x0000, 12, 12, 0x00, 0x01 },
393 .pipe_txelec_set = { 0x0004, 1, 1, 0x00, 0x01 },
394 .pipe_txcomp_set = { 0x0004, 4, 4, 0x00, 0x01 },
395 .pipe_clk_25m = { 0x0004, 14, 13, 0x00, 0x01 },
396 .pipe_clk_100m = { 0x0004, 14, 13, 0x00, 0x02 },
397 .pipe_phymode_sel = { 0x0008, 1, 1, 0x00, 0x01 },
398 .pipe_rate_sel = { 0x0008, 2, 2, 0x00, 0x01 },
399 .pipe_rxterm_sel = { 0x0008, 8, 8, 0x00, 0x01 },
400 .pipe_txelec_sel = { 0x0008, 12, 12, 0x00, 0x01 },
401 .pipe_txcomp_sel = { 0x0008, 15, 15, 0x00, 0x01 },
402 .pipe_clk_ext = { 0x000c, 9, 8, 0x02, 0x01 },
403 .pipe_sel_usb = { 0x000c, 14, 13, 0x00, 0x01 },
404 .pipe_sel_qsgmii = { 0x000c, 15, 13, 0x00, 0x07 },
405 .pipe_phy_status = { 0x0034, 6, 6, 0x01, 0x00 },
406 .con0_for_pcie = { 0x0000, 15, 0, 0x00, 0x1000 },
407 .con1_for_pcie = { 0x0004, 15, 0, 0x00, 0x0000 },
408 .con2_for_pcie = { 0x0008, 15, 0, 0x00, 0x0101 },
409 .con3_for_pcie = { 0x000c, 15, 0, 0x00, 0x0200 },
410 .con0_for_sata = { 0x0000, 15, 0, 0x00, 0x0119 },
411 .con1_for_sata = { 0x0004, 15, 0, 0x00, 0x0040 },
412 .con2_for_sata = { 0x0008, 15, 0, 0x00, 0x80c3 },
413 .con3_for_sata = { 0x000c, 15, 0, 0x00, 0x4407 },
414 /* pipe-grf */
415 .pipe_con0_for_sata = { 0x0000, 15, 0, 0x00, 0x2220 },
416 .pipe_sgmii_mac_sel = { 0x0040, 1, 1, 0x00, 0x01 },
417 .pipe_xpcs_phy_ready = { 0x0040, 2, 2, 0x00, 0x01 },
418 .u3otg0_port_en = { 0x0104, 15, 0, 0x0181, 0x1100 },
419 .u3otg1_port_en = { 0x0144, 15, 0, 0x0181, 0x1100 },
420};
421
422static const struct rockchip_combphy_cfg rk3568_combphy_cfgs = {
423 .grfcfg = &rk3568_combphy_grfcfgs,
424 .combphy_cfg = rk3568_combphy_cfg,
425};
426
Jon Linbc980f62023-04-27 10:35:35 +0300427static int rk3588_combphy_cfg(struct rockchip_combphy_priv *priv)
428{
429 const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
430 u32 val;
431
432 switch (priv->mode) {
433 case PHY_TYPE_PCIE:
434 param_write(priv->phy_grf, &cfg->con0_for_pcie, true);
435 param_write(priv->phy_grf, &cfg->con1_for_pcie, true);
436 param_write(priv->phy_grf, &cfg->con2_for_pcie, true);
437 param_write(priv->phy_grf, &cfg->con3_for_pcie, true);
438 break;
439 case PHY_TYPE_USB3:
440 param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false);
441 param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false);
442 param_write(priv->phy_grf, &cfg->usb_mode_set, true);
443 break;
444 case PHY_TYPE_SATA:
445 param_write(priv->phy_grf, &cfg->con0_for_sata, true);
446 param_write(priv->phy_grf, &cfg->con1_for_sata, true);
447 param_write(priv->phy_grf, &cfg->con2_for_sata, true);
448 param_write(priv->phy_grf, &cfg->con3_for_sata, true);
449 param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true);
450 param_write(priv->pipe_grf, &cfg->pipe_con1_for_sata, true);
451 break;
452 case PHY_TYPE_SGMII:
453 case PHY_TYPE_QSGMII:
454 default:
455 dev_err(priv->dev, "incompatible PHY type\n");
456 return -EINVAL;
457 }
458
459 /* 100MHz refclock signal is good */
460 clk_set_rate(&priv->ref_clk, 100000000);
461 param_write(priv->phy_grf, &cfg->pipe_clk_100m, true);
462 if (priv->mode == PHY_TYPE_PCIE) {
463 /* PLL KVCO tuning fine */
464 val = readl(priv->mmio + (0x20 << 2));
465 val &= ~GENMASK(4, 2);
466 val |= 0x4 << 2;
467 writel(val, priv->mmio + (0x20 << 2));
468
469 /* Set up rx_trim: PLL LPF C1 85pf R1 1.25kohm */
470 val = 0x4c;
471 writel(val, priv->mmio + (0x1b << 2));
472
473 /* Set up su_trim: T3 */
474 val = 0xb0;
475 writel(val, priv->mmio + (0xa << 2));
476 val = 0x47;
477 writel(val, priv->mmio + (0xb << 2));
478 val = 0x57;
479 writel(val, priv->mmio + (0xd << 2));
480 }
481
482 return 0;
483}
484
485static const struct rockchip_combphy_grfcfg rk3588_combphy_grfcfgs = {
486 /* pipe-phy-grf */
487 .pcie_mode_set = { 0x0000, 5, 0, 0x00, 0x11 },
488 .usb_mode_set = { 0x0000, 5, 0, 0x00, 0x04 },
489 .pipe_rxterm_set = { 0x0000, 12, 12, 0x00, 0x01 },
490 .pipe_txelec_set = { 0x0004, 1, 1, 0x00, 0x01 },
491 .pipe_txcomp_set = { 0x0004, 4, 4, 0x00, 0x01 },
492 .pipe_clk_25m = { 0x0004, 14, 13, 0x00, 0x01 },
493 .pipe_clk_100m = { 0x0004, 14, 13, 0x00, 0x02 },
494 .pipe_rxterm_sel = { 0x0008, 8, 8, 0x00, 0x01 },
495 .pipe_txelec_sel = { 0x0008, 12, 12, 0x00, 0x01 },
496 .pipe_txcomp_sel = { 0x0008, 15, 15, 0x00, 0x01 },
497 .pipe_clk_ext = { 0x000c, 9, 8, 0x02, 0x01 },
498 .pipe_phy_status = { 0x0034, 6, 6, 0x01, 0x00 },
499 .con0_for_pcie = { 0x0000, 15, 0, 0x00, 0x1000 },
500 .con1_for_pcie = { 0x0004, 15, 0, 0x00, 0x0000 },
501 .con2_for_pcie = { 0x0008, 15, 0, 0x00, 0x0101 },
502 .con3_for_pcie = { 0x000c, 15, 0, 0x00, 0x0200 },
503 .con0_for_sata = { 0x0000, 15, 0, 0x00, 0x0129 },
504 .con1_for_sata = { 0x0004, 15, 0, 0x00, 0x0040 },
505 .con2_for_sata = { 0x0008, 15, 0, 0x00, 0x80c1 },
506 .con3_for_sata = { 0x000c, 15, 0, 0x00, 0x0407 },
507 /* pipe-grf */
508 .pipe_con0_for_sata = { 0x0000, 11, 5, 0x00, 0x22 },
509 .pipe_con1_for_sata = { 0x0000, 2, 0, 0x00, 0x2 },
510};
511
512static const struct rockchip_combphy_cfg rk3588_combphy_cfgs = {
513 .grfcfg = &rk3588_combphy_grfcfgs,
514 .combphy_cfg = rk3588_combphy_cfg,
515};
516
Jagan Teki0d2d0bf2023-02-17 17:28:41 +0530517static const struct udevice_id rockchip_combphy_ids[] = {
518 {
519 .compatible = "rockchip,rk3568-naneng-combphy",
520 .data = (ulong)&rk3568_combphy_cfgs
521 },
Jon Linbc980f62023-04-27 10:35:35 +0300522 {
523 .compatible = "rockchip,rk3588-naneng-combphy",
524 .data = (ulong)&rk3588_combphy_cfgs
525 },
Jagan Teki0d2d0bf2023-02-17 17:28:41 +0530526 { }
527};
528
529U_BOOT_DRIVER(rockchip_naneng_combphy) = {
530 .name = "naneng-combphy",
531 .id = UCLASS_PHY,
532 .of_match = rockchip_combphy_ids,
533 .ops = &rochchip_combphy_ops,
534 .probe = rockchip_combphy_probe,
535 .priv_auto = sizeof(struct rockchip_combphy_priv),
536};