xref: /rk3399_rockchip-uboot/drivers/phy/phy-rockchip-naneng-combphy.c (revision 5eec6d12ddd5a699d108fb21ee56db5a435bc659)
1925c5749SYifeng Zhao // SPDX-License-Identifier: GPL-2.0
2925c5749SYifeng Zhao /*
3925c5749SYifeng Zhao  * Rockchip USB3.0/PCIe Gen2/SATA/SGMII combphy driver
4925c5749SYifeng Zhao  *
5925c5749SYifeng Zhao  * Copyright (C) 2021 Rockchip Electronics Co., Ltd.
6925c5749SYifeng Zhao  */
7925c5749SYifeng Zhao 
8925c5749SYifeng Zhao #include <common.h>
9925c5749SYifeng Zhao #include <clk.h>
10925c5749SYifeng Zhao #include <dm.h>
11925c5749SYifeng Zhao #include <dm/lists.h>
12925c5749SYifeng Zhao #include <dt-bindings/phy/phy.h>
13925c5749SYifeng Zhao #include <generic-phy.h>
14925c5749SYifeng Zhao #include <syscon.h>
15925c5749SYifeng Zhao #include <asm/io.h>
16925c5749SYifeng Zhao #include <asm/arch/clock.h>
17925c5749SYifeng Zhao #include <regmap.h>
18925c5749SYifeng Zhao #include <reset-uclass.h>
19925c5749SYifeng Zhao 
20925c5749SYifeng Zhao #define BIT_WRITEABLE_SHIFT		16
21925c5749SYifeng Zhao 
22925c5749SYifeng Zhao struct rockchip_combphy_priv;
23925c5749SYifeng Zhao 
24925c5749SYifeng Zhao struct combphy_reg {
25925c5749SYifeng Zhao 	u16 offset;
26925c5749SYifeng Zhao 	u16 bitend;
27925c5749SYifeng Zhao 	u16 bitstart;
28925c5749SYifeng Zhao 	u16 disable;
29925c5749SYifeng Zhao 	u16 enable;
30925c5749SYifeng Zhao };
31925c5749SYifeng Zhao 
32925c5749SYifeng Zhao struct rockchip_combphy_grfcfg {
33925c5749SYifeng Zhao 	struct combphy_reg pcie_mode_set;
34925c5749SYifeng Zhao 	struct combphy_reg usb_mode_set;
35925c5749SYifeng Zhao 	struct combphy_reg sgmii_mode_set;
36925c5749SYifeng Zhao 	struct combphy_reg qsgmii_mode_set;
37925c5749SYifeng Zhao 	struct combphy_reg pipe_rxterm_set;
38925c5749SYifeng Zhao 	struct combphy_reg pipe_txelec_set;
39925c5749SYifeng Zhao 	struct combphy_reg pipe_txcomp_set;
40925c5749SYifeng Zhao 	struct combphy_reg pipe_clk_25m;
41925c5749SYifeng Zhao 	struct combphy_reg pipe_clk_100m;
42925c5749SYifeng Zhao 	struct combphy_reg pipe_phymode_sel;
43925c5749SYifeng Zhao 	struct combphy_reg pipe_rate_sel;
44925c5749SYifeng Zhao 	struct combphy_reg pipe_rxterm_sel;
45925c5749SYifeng Zhao 	struct combphy_reg pipe_txelec_sel;
46925c5749SYifeng Zhao 	struct combphy_reg pipe_txcomp_sel;
47925c5749SYifeng Zhao 	struct combphy_reg pipe_clk_ext;
48925c5749SYifeng Zhao 	struct combphy_reg pipe_sel_usb;
49925c5749SYifeng Zhao 	struct combphy_reg pipe_sel_qsgmii;
50925c5749SYifeng Zhao 	struct combphy_reg pipe_phy_status;
51925c5749SYifeng Zhao 	struct combphy_reg con0_for_pcie;
52925c5749SYifeng Zhao 	struct combphy_reg con1_for_pcie;
53925c5749SYifeng Zhao 	struct combphy_reg con2_for_pcie;
54925c5749SYifeng Zhao 	struct combphy_reg con3_for_pcie;
55925c5749SYifeng Zhao 	struct combphy_reg con0_for_sata;
56925c5749SYifeng Zhao 	struct combphy_reg con1_for_sata;
57925c5749SYifeng Zhao 	struct combphy_reg con2_for_sata;
58925c5749SYifeng Zhao 	struct combphy_reg con3_for_sata;
59925c5749SYifeng Zhao 	struct combphy_reg pipe_con0_for_sata;
60cf3c44cbSJon Lin 	struct combphy_reg pipe_con1_for_sata;
61925c5749SYifeng Zhao 	struct combphy_reg pipe_sgmii_mac_sel;
62925c5749SYifeng Zhao 	struct combphy_reg pipe_xpcs_phy_ready;
63925c5749SYifeng Zhao 	struct combphy_reg u3otg0_port_en;
64925c5749SYifeng Zhao 	struct combphy_reg u3otg1_port_en;
65925c5749SYifeng Zhao };
66925c5749SYifeng Zhao 
67925c5749SYifeng Zhao struct rockchip_combphy_cfg {
68925c5749SYifeng Zhao 	const struct rockchip_combphy_grfcfg *grfcfg;
69925c5749SYifeng Zhao 	int (*combphy_cfg)(struct rockchip_combphy_priv *priv);
70925c5749SYifeng Zhao };
71925c5749SYifeng Zhao 
72925c5749SYifeng Zhao struct rockchip_combphy_priv {
73925c5749SYifeng Zhao 	u32 mode;
74925c5749SYifeng Zhao 	void __iomem *mmio;
75925c5749SYifeng Zhao 	struct udevice *dev;
76925c5749SYifeng Zhao 	struct regmap *pipe_grf;
77925c5749SYifeng Zhao 	struct regmap *phy_grf;
78925c5749SYifeng Zhao 	struct phy *phy;
79925c5749SYifeng Zhao 	struct reset_ctl phy_rst;
80925c5749SYifeng Zhao 	struct clk ref_clk;
81925c5749SYifeng Zhao 	const struct rockchip_combphy_cfg *cfg;
82925c5749SYifeng Zhao };
83925c5749SYifeng Zhao 
84925c5749SYifeng Zhao static int param_write(struct regmap *base,
85925c5749SYifeng Zhao 		       const struct combphy_reg *reg, bool en)
86925c5749SYifeng Zhao {
87925c5749SYifeng Zhao 	u32 val, mask, tmp;
88925c5749SYifeng Zhao 
89925c5749SYifeng Zhao 	tmp = en ? reg->enable : reg->disable;
90925c5749SYifeng Zhao 	mask = GENMASK(reg->bitend, reg->bitstart);
91925c5749SYifeng Zhao 	val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT);
92925c5749SYifeng Zhao 
93925c5749SYifeng Zhao 	return regmap_write(base, reg->offset, val);
94925c5749SYifeng Zhao }
95925c5749SYifeng Zhao 
96925c5749SYifeng Zhao static int rockchip_combphy_pcie_init(struct rockchip_combphy_priv *priv)
97925c5749SYifeng Zhao {
98925c5749SYifeng Zhao 	int ret = 0;
99925c5749SYifeng Zhao 
100925c5749SYifeng Zhao 	if (priv->cfg->combphy_cfg) {
101925c5749SYifeng Zhao 		ret = priv->cfg->combphy_cfg(priv);
102925c5749SYifeng Zhao 		if (ret) {
103925c5749SYifeng Zhao 			dev_err(priv->dev, "failed to init phy for pcie\n");
104925c5749SYifeng Zhao 			return ret;
105925c5749SYifeng Zhao 		}
106925c5749SYifeng Zhao 	}
107925c5749SYifeng Zhao 
108925c5749SYifeng Zhao 	return ret;
109925c5749SYifeng Zhao }
110925c5749SYifeng Zhao 
111925c5749SYifeng Zhao static int rockchip_combphy_usb3_init(struct rockchip_combphy_priv *priv)
112925c5749SYifeng Zhao {
113925c5749SYifeng Zhao 	int ret = 0;
114925c5749SYifeng Zhao 
115925c5749SYifeng Zhao 	if (priv->cfg->combphy_cfg) {
116925c5749SYifeng Zhao 		ret = priv->cfg->combphy_cfg(priv);
117925c5749SYifeng Zhao 		if (ret) {
118925c5749SYifeng Zhao 			dev_err(priv->dev, "failed to init phy for usb3\n");
119925c5749SYifeng Zhao 			return ret;
120925c5749SYifeng Zhao 		}
121925c5749SYifeng Zhao 	}
122925c5749SYifeng Zhao 
123925c5749SYifeng Zhao 	return ret;
124925c5749SYifeng Zhao }
125925c5749SYifeng Zhao 
126925c5749SYifeng Zhao static int rockchip_combphy_sata_init(struct rockchip_combphy_priv *priv)
127925c5749SYifeng Zhao {
128925c5749SYifeng Zhao 	int ret = 0;
129925c5749SYifeng Zhao 
130925c5749SYifeng Zhao 	if (priv->cfg->combphy_cfg) {
131925c5749SYifeng Zhao 		ret = priv->cfg->combphy_cfg(priv);
132925c5749SYifeng Zhao 		if (ret) {
133925c5749SYifeng Zhao 			dev_err(priv->dev, "failed to init phy for sata\n");
134925c5749SYifeng Zhao 			return ret;
135925c5749SYifeng Zhao 		}
136925c5749SYifeng Zhao 	}
137925c5749SYifeng Zhao 
138925c5749SYifeng Zhao 	return ret;
139925c5749SYifeng Zhao }
140925c5749SYifeng Zhao 
141925c5749SYifeng Zhao static int rockchip_combphy_sgmii_init(struct rockchip_combphy_priv *priv)
142925c5749SYifeng Zhao {
143925c5749SYifeng Zhao 	int ret = 0;
144925c5749SYifeng Zhao 
145925c5749SYifeng Zhao 	if (priv->cfg->combphy_cfg) {
146925c5749SYifeng Zhao 		ret = priv->cfg->combphy_cfg(priv);
147925c5749SYifeng Zhao 		if (ret) {
148925c5749SYifeng Zhao 			dev_err(priv->dev, "failed to init phy for sgmii\n");
149925c5749SYifeng Zhao 			return ret;
150925c5749SYifeng Zhao 		}
151925c5749SYifeng Zhao 	}
152925c5749SYifeng Zhao 
153925c5749SYifeng Zhao 	return ret;
154925c5749SYifeng Zhao }
155925c5749SYifeng Zhao 
156925c5749SYifeng Zhao static int rockchip_combphy_set_mode(struct rockchip_combphy_priv *priv)
157925c5749SYifeng Zhao {
158925c5749SYifeng Zhao 	switch (priv->mode) {
159925c5749SYifeng Zhao 	case PHY_TYPE_PCIE:
160925c5749SYifeng Zhao 		rockchip_combphy_pcie_init(priv);
161925c5749SYifeng Zhao 		break;
162925c5749SYifeng Zhao 	case PHY_TYPE_USB3:
163925c5749SYifeng Zhao 		rockchip_combphy_usb3_init(priv);
164925c5749SYifeng Zhao 		break;
165925c5749SYifeng Zhao 	case PHY_TYPE_SATA:
166925c5749SYifeng Zhao 		rockchip_combphy_sata_init(priv);
167925c5749SYifeng Zhao 		break;
168925c5749SYifeng Zhao 	case PHY_TYPE_SGMII:
169925c5749SYifeng Zhao 	case PHY_TYPE_QSGMII:
170925c5749SYifeng Zhao 		return rockchip_combphy_sgmii_init(priv);
171925c5749SYifeng Zhao 	default:
172925c5749SYifeng Zhao 		dev_err(priv->dev, "incompatible PHY type\n");
173925c5749SYifeng Zhao 		return -EINVAL;
174925c5749SYifeng Zhao 	}
175925c5749SYifeng Zhao 
176925c5749SYifeng Zhao 	return 0;
177925c5749SYifeng Zhao }
178925c5749SYifeng Zhao 
179925c5749SYifeng Zhao static int rockchip_combphy_init(struct phy *phy)
180925c5749SYifeng Zhao {
181925c5749SYifeng Zhao 	struct rockchip_combphy_priv *priv = dev_get_priv(phy->dev);
182925c5749SYifeng Zhao 	int ret;
183925c5749SYifeng Zhao 
184925c5749SYifeng Zhao 	ret = clk_enable(&priv->ref_clk);
185925c5749SYifeng Zhao 	if (ret < 0 && ret != -ENOSYS)
186925c5749SYifeng Zhao 		return ret;
187925c5749SYifeng Zhao 
188925c5749SYifeng Zhao 	ret = rockchip_combphy_set_mode(priv);
189925c5749SYifeng Zhao 	if (ret)
190925c5749SYifeng Zhao 		goto err_clk;
191925c5749SYifeng Zhao 
192925c5749SYifeng Zhao 	reset_deassert(&priv->phy_rst);
193925c5749SYifeng Zhao 
194925c5749SYifeng Zhao 	return 0;
195925c5749SYifeng Zhao 
196925c5749SYifeng Zhao err_clk:
197925c5749SYifeng Zhao 	clk_disable(&priv->ref_clk);
198925c5749SYifeng Zhao 
199925c5749SYifeng Zhao 	return ret;
200925c5749SYifeng Zhao }
201925c5749SYifeng Zhao 
202925c5749SYifeng Zhao static int rockchip_combphy_exit(struct phy *phy)
203925c5749SYifeng Zhao {
204925c5749SYifeng Zhao 	struct rockchip_combphy_priv *priv = dev_get_priv(phy->dev);
205925c5749SYifeng Zhao 
206925c5749SYifeng Zhao 	clk_disable(&priv->ref_clk);
207925c5749SYifeng Zhao 	reset_assert(&priv->phy_rst);
208925c5749SYifeng Zhao 
209925c5749SYifeng Zhao 	return 0;
210925c5749SYifeng Zhao }
211925c5749SYifeng Zhao 
212925c5749SYifeng Zhao static int rockchip_combphy_xlate(struct phy *phy, struct ofnode_phandle_args *args)
213925c5749SYifeng Zhao {
214925c5749SYifeng Zhao 	struct rockchip_combphy_priv *priv = dev_get_priv(phy->dev);
215925c5749SYifeng Zhao 
216925c5749SYifeng Zhao 	if (args->args_count != 1) {
217925c5749SYifeng Zhao 		pr_err("invalid number of arguments\n");
218925c5749SYifeng Zhao 		return -EINVAL;
219925c5749SYifeng Zhao 	}
220925c5749SYifeng Zhao 
221925c5749SYifeng Zhao 	priv->mode = args->args[0];
222925c5749SYifeng Zhao 
223925c5749SYifeng Zhao 	return 0;
224925c5749SYifeng Zhao }
225925c5749SYifeng Zhao 
226925c5749SYifeng Zhao static const struct phy_ops rochchip_combphy_ops = {
227925c5749SYifeng Zhao 	.init = rockchip_combphy_init,
228925c5749SYifeng Zhao 	.exit = rockchip_combphy_exit,
229925c5749SYifeng Zhao 	.of_xlate = rockchip_combphy_xlate,
230925c5749SYifeng Zhao };
231925c5749SYifeng Zhao 
232925c5749SYifeng Zhao static int rockchip_combphy_parse_dt(struct udevice *dev,
233925c5749SYifeng Zhao 				     struct rockchip_combphy_priv *priv)
234925c5749SYifeng Zhao {
235925c5749SYifeng Zhao 	struct udevice *syscon;
236925c5749SYifeng Zhao 	int ret;
2377cc44222SJon Lin 	u32 vals[4];
238925c5749SYifeng Zhao 
239925c5749SYifeng Zhao 	ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, "rockchip,pipe-grf", &syscon);
240925c5749SYifeng Zhao 	if (ret) {
241cf3c44cbSJon Lin 		dev_err(dev, "failed to find peri_ctrl pipe-grf regmap ret= %d\n", ret);
242925c5749SYifeng Zhao 		return ret;
243925c5749SYifeng Zhao 	}
244925c5749SYifeng Zhao 	priv->pipe_grf = syscon_get_regmap(syscon);
245925c5749SYifeng Zhao 
246925c5749SYifeng Zhao 	ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, "rockchip,pipe-phy-grf", &syscon);
247925c5749SYifeng Zhao 	if (ret) {
248925c5749SYifeng Zhao 		dev_err(dev, "failed to find peri_ctrl pipe-phy-grf regmap\n");
249925c5749SYifeng Zhao 		return ret;
250925c5749SYifeng Zhao 	}
251925c5749SYifeng Zhao 	priv->phy_grf = syscon_get_regmap(syscon);
252925c5749SYifeng Zhao 
253925c5749SYifeng Zhao 	ret = clk_get_by_index(dev, 0, &priv->ref_clk);
254925c5749SYifeng Zhao 	if (ret) {
255925c5749SYifeng Zhao 		dev_err(dev, "failed to find ref clock\n");
256925c5749SYifeng Zhao 		return PTR_ERR(&priv->ref_clk);
257925c5749SYifeng Zhao 	}
258925c5749SYifeng Zhao 
259dbf89912SRen Jianing 	ret = reset_get_by_name(dev, "combphy", &priv->phy_rst);
260925c5749SYifeng Zhao 	if (ret) {
261925c5749SYifeng Zhao 		dev_err(dev, "no phy reset control specified\n");
262925c5749SYifeng Zhao 		return ret;
263925c5749SYifeng Zhao 	}
264925c5749SYifeng Zhao 
2657cc44222SJon Lin 	if (!dev_read_u32_array(dev, "rockchip,pcie1ln-sel-bits",
2667cc44222SJon Lin 				vals, ARRAY_SIZE(vals)))
2677cc44222SJon Lin 		regmap_write(priv->pipe_grf, vals[0],
2687cc44222SJon Lin 			     (GENMASK(vals[2], vals[1]) << 16) | vals[3]);
2697cc44222SJon Lin 
270925c5749SYifeng Zhao 	return 0;
271925c5749SYifeng Zhao }
272925c5749SYifeng Zhao 
273925c5749SYifeng Zhao static int rockchip_combphy_probe(struct udevice *udev)
274925c5749SYifeng Zhao {
275925c5749SYifeng Zhao 	struct rockchip_combphy_priv *priv = dev_get_priv(udev);
276925c5749SYifeng Zhao 	const struct rockchip_combphy_cfg *phy_cfg;
277925c5749SYifeng Zhao 
278925c5749SYifeng Zhao 	priv->mmio = (void __iomem *)dev_read_addr(udev);
279925c5749SYifeng Zhao 	if (IS_ERR(priv->mmio))
280925c5749SYifeng Zhao 		return PTR_ERR(priv->mmio);
281925c5749SYifeng Zhao 
282925c5749SYifeng Zhao 	phy_cfg = (const struct rockchip_combphy_cfg *)dev_get_driver_data(udev);
283925c5749SYifeng Zhao 	if (!phy_cfg) {
284925c5749SYifeng Zhao 		dev_err(udev, "No OF match data provided\n");
285925c5749SYifeng Zhao 		return -EINVAL;
286925c5749SYifeng Zhao 	}
287925c5749SYifeng Zhao 
288925c5749SYifeng Zhao 	priv->dev = udev;
289925c5749SYifeng Zhao 	priv->mode = PHY_TYPE_SATA;
290925c5749SYifeng Zhao 	priv->cfg = phy_cfg;
291925c5749SYifeng Zhao 
292*5eec6d12SJon Lin 	return rockchip_combphy_parse_dt(udev, priv);
293925c5749SYifeng Zhao }
294925c5749SYifeng Zhao 
295925c5749SYifeng Zhao static int rk3568_combphy_cfg(struct rockchip_combphy_priv *priv)
296925c5749SYifeng Zhao {
297925c5749SYifeng Zhao 	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
298925c5749SYifeng Zhao 	u32 val;
299925c5749SYifeng Zhao 
300925c5749SYifeng Zhao 	switch (priv->mode) {
301925c5749SYifeng Zhao 	case PHY_TYPE_PCIE:
302925c5749SYifeng Zhao 		/* Set SSC downward spread spectrum */
303925c5749SYifeng Zhao 		val = readl(priv->mmio + (0x1f << 2));
304925c5749SYifeng Zhao 		val &= ~GENMASK(5, 4);
305925c5749SYifeng Zhao 		val |= 0x01 << 4;
306925c5749SYifeng Zhao 		writel(val, priv->mmio + 0x7c);
307925c5749SYifeng Zhao 
308925c5749SYifeng Zhao 		param_write(priv->phy_grf, &cfg->con0_for_pcie, true);
309925c5749SYifeng Zhao 		param_write(priv->phy_grf, &cfg->con1_for_pcie, true);
310925c5749SYifeng Zhao 		param_write(priv->phy_grf, &cfg->con2_for_pcie, true);
311925c5749SYifeng Zhao 		param_write(priv->phy_grf, &cfg->con3_for_pcie, true);
312925c5749SYifeng Zhao 		break;
313925c5749SYifeng Zhao 	case PHY_TYPE_USB3:
314925c5749SYifeng Zhao 		/* Set SSC downward spread spectrum */
315925c5749SYifeng Zhao 		val = readl(priv->mmio + (0x1f << 2));
316925c5749SYifeng Zhao 		val &= ~GENMASK(5, 4);
317925c5749SYifeng Zhao 		val |= 0x01 << 4;
318925c5749SYifeng Zhao 		writel(val, priv->mmio + 0x7c);
319925c5749SYifeng Zhao 
320925c5749SYifeng Zhao 		/* Enable adaptive CTLE for USB3.0 Rx */
321925c5749SYifeng Zhao 		val = readl(priv->mmio + (0x0e << 2));
322925c5749SYifeng Zhao 		val &= ~GENMASK(0, 0);
323925c5749SYifeng Zhao 		val |= 0x01;
324925c5749SYifeng Zhao 		writel(val, priv->mmio + (0x0e << 2));
325925c5749SYifeng Zhao 
326a0d03578SWilliam Wu 		/* Set PLL KVCO fine tuning signals */
327a0d03578SWilliam Wu 		val = readl(priv->mmio + (0x20 << 2));
328a0d03578SWilliam Wu 		val &= ~(0x7 << 2);
329a0d03578SWilliam Wu 		val |= 0x2 << 2;
330a0d03578SWilliam Wu 		writel(val, priv->mmio + (0x20 << 2));
331a0d03578SWilliam Wu 
332a0d03578SWilliam Wu 		/* Set PLL LPF R1 to su_trim[10:7]=1001 */
333a0d03578SWilliam Wu 		writel(0x4, priv->mmio + (0xb << 2));
334a0d03578SWilliam Wu 
335a0d03578SWilliam Wu 		/* Set PLL input clock divider 1/2 */
336a0d03578SWilliam Wu 		val = readl(priv->mmio + (0x5 << 2));
337a0d03578SWilliam Wu 		val &= ~(0x3 << 6);
338a0d03578SWilliam Wu 		val |= 0x1 << 6;
339a0d03578SWilliam Wu 		writel(val, priv->mmio + (0x5 << 2));
340a0d03578SWilliam Wu 
341a0d03578SWilliam Wu 		/* Set PLL loop divider */
342a0d03578SWilliam Wu 		writel(0x32, priv->mmio + (0x11 << 2));
343a0d03578SWilliam Wu 
344a0d03578SWilliam Wu 		/* Set PLL KVCO to min and set PLL charge pump current to max */
345a0d03578SWilliam Wu 		writel(0xf0, priv->mmio + (0xa << 2));
346a0d03578SWilliam Wu 
347925c5749SYifeng Zhao 		param_write(priv->phy_grf, &cfg->pipe_sel_usb, true);
348925c5749SYifeng Zhao 		param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false);
349925c5749SYifeng Zhao 		param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false);
350925c5749SYifeng Zhao 		param_write(priv->phy_grf, &cfg->usb_mode_set, true);
351925c5749SYifeng Zhao 		break;
352925c5749SYifeng Zhao 	case PHY_TYPE_SATA:
353925c5749SYifeng Zhao 		writel(0x41, priv->mmio + 0x38);
354925c5749SYifeng Zhao 		writel(0x8F, priv->mmio + 0x18);
355925c5749SYifeng Zhao 		param_write(priv->phy_grf, &cfg->con0_for_sata, true);
356925c5749SYifeng Zhao 		param_write(priv->phy_grf, &cfg->con1_for_sata, true);
357925c5749SYifeng Zhao 		param_write(priv->phy_grf, &cfg->con2_for_sata, true);
358925c5749SYifeng Zhao 		param_write(priv->phy_grf, &cfg->con3_for_sata, true);
359925c5749SYifeng Zhao 		param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true);
360925c5749SYifeng Zhao 		break;
361925c5749SYifeng Zhao 	case PHY_TYPE_SGMII:
362925c5749SYifeng Zhao 		param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true);
363925c5749SYifeng Zhao 		param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true);
364925c5749SYifeng Zhao 		param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true);
365925c5749SYifeng Zhao 		param_write(priv->phy_grf, &cfg->sgmii_mode_set, true);
366925c5749SYifeng Zhao 		break;
367925c5749SYifeng Zhao 	case PHY_TYPE_QSGMII:
368925c5749SYifeng Zhao 		param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true);
369925c5749SYifeng Zhao 		param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true);
370925c5749SYifeng Zhao 		param_write(priv->phy_grf, &cfg->pipe_rate_sel, true);
371925c5749SYifeng Zhao 		param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true);
372925c5749SYifeng Zhao 		param_write(priv->phy_grf, &cfg->qsgmii_mode_set, true);
373925c5749SYifeng Zhao 		break;
374925c5749SYifeng Zhao 	default:
375925c5749SYifeng Zhao 		pr_err("%s, phy-type %d\n", __func__, priv->mode);
376925c5749SYifeng Zhao 		return -EINVAL;
377925c5749SYifeng Zhao 	}
378925c5749SYifeng Zhao 
379dbf89912SRen Jianing 	/* The default ref clock is 25Mhz */
380dbf89912SRen Jianing 	param_write(priv->phy_grf, &cfg->pipe_clk_25m, true);
381925c5749SYifeng Zhao 
382925c5749SYifeng Zhao 	if (dev_read_bool(priv->dev, "rockchip,enable-ssc")) {
383925c5749SYifeng Zhao 		val = readl(priv->mmio + (0x7 << 2));
384925c5749SYifeng Zhao 		val |= BIT(4);
385925c5749SYifeng Zhao 		writel(val, priv->mmio + (0x7 << 2));
386925c5749SYifeng Zhao 	}
387925c5749SYifeng Zhao 
388925c5749SYifeng Zhao 	return 0;
389925c5749SYifeng Zhao }
390925c5749SYifeng Zhao 
391925c5749SYifeng Zhao static const struct rockchip_combphy_grfcfg rk3568_combphy_grfcfgs = {
392925c5749SYifeng Zhao 	/* pipe-phy-grf */
393925c5749SYifeng Zhao 	.pcie_mode_set		= { 0x0000, 5, 0, 0x00, 0x11 },
394925c5749SYifeng Zhao 	.usb_mode_set		= { 0x0000, 5, 0, 0x00, 0x04 },
395925c5749SYifeng Zhao 	.sgmii_mode_set		= { 0x0000, 5, 0, 0x00, 0x01 },
396925c5749SYifeng Zhao 	.qsgmii_mode_set	= { 0x0000, 5, 0, 0x00, 0x21 },
397925c5749SYifeng Zhao 	.pipe_rxterm_set	= { 0x0000, 12, 12, 0x00, 0x01 },
398925c5749SYifeng Zhao 	.pipe_txelec_set	= { 0x0004, 1, 1, 0x00, 0x01 },
399925c5749SYifeng Zhao 	.pipe_txcomp_set	= { 0x0004, 4, 4, 0x00, 0x01 },
400925c5749SYifeng Zhao 	.pipe_clk_25m		= { 0x0004, 14, 13, 0x00, 0x01 },
401925c5749SYifeng Zhao 	.pipe_clk_100m		= { 0x0004, 14, 13, 0x00, 0x02 },
402925c5749SYifeng Zhao 	.pipe_phymode_sel	= { 0x0008, 1, 1, 0x00, 0x01 },
403925c5749SYifeng Zhao 	.pipe_rate_sel		= { 0x0008, 2, 2, 0x00, 0x01 },
404925c5749SYifeng Zhao 	.pipe_rxterm_sel	= { 0x0008, 8, 8, 0x00, 0x01 },
405925c5749SYifeng Zhao 	.pipe_txelec_sel	= { 0x0008, 12, 12, 0x00, 0x01 },
406925c5749SYifeng Zhao 	.pipe_txcomp_sel	= { 0x0008, 15, 15, 0x00, 0x01 },
407925c5749SYifeng Zhao 	.pipe_clk_ext		= { 0x000c, 9, 8, 0x02, 0x01 },
408925c5749SYifeng Zhao 	.pipe_sel_usb		= { 0x000c, 14, 13, 0x00, 0x01 },
409925c5749SYifeng Zhao 	.pipe_sel_qsgmii	= { 0x000c, 15, 13, 0x00, 0x07 },
410925c5749SYifeng Zhao 	.pipe_phy_status	= { 0x0034, 6, 6, 0x01, 0x00 },
411925c5749SYifeng Zhao 	.con0_for_pcie		= { 0x0000, 15, 0, 0x00, 0x1000 },
412925c5749SYifeng Zhao 	.con1_for_pcie		= { 0x0004, 15, 0, 0x00, 0x0000 },
413925c5749SYifeng Zhao 	.con2_for_pcie		= { 0x0008, 15, 0, 0x00, 0x0101 },
414925c5749SYifeng Zhao 	.con3_for_pcie		= { 0x000c, 15, 0, 0x00, 0x0200 },
415925c5749SYifeng Zhao 	.con0_for_sata		= { 0x0000, 15, 0, 0x00, 0x0119 },
416925c5749SYifeng Zhao 	.con1_for_sata		= { 0x0004, 15, 0, 0x00, 0x0040 },
417925c5749SYifeng Zhao 	.con2_for_sata		= { 0x0008, 15, 0, 0x00, 0x80c3 },
418925c5749SYifeng Zhao 	.con3_for_sata		= { 0x000c, 15, 0, 0x00, 0x4407 },
419925c5749SYifeng Zhao 	/* pipe-grf */
420925c5749SYifeng Zhao 	.pipe_con0_for_sata	= { 0x0000, 15, 0, 0x00, 0x2220 },
421925c5749SYifeng Zhao 	.pipe_sgmii_mac_sel	= { 0x0040, 1, 1, 0x00, 0x01 },
422925c5749SYifeng Zhao 	.pipe_xpcs_phy_ready	= { 0x0040, 2, 2, 0x00, 0x01 },
423925c5749SYifeng Zhao 	.u3otg0_port_en		= { 0x0104, 15, 0, 0x0181, 0x1100 },
424925c5749SYifeng Zhao 	.u3otg1_port_en		= { 0x0144, 15, 0, 0x0181, 0x1100 },
425925c5749SYifeng Zhao };
426925c5749SYifeng Zhao 
427925c5749SYifeng Zhao static const struct rockchip_combphy_cfg rk3568_combphy_cfgs = {
428925c5749SYifeng Zhao 	.grfcfg		= &rk3568_combphy_grfcfgs,
429925c5749SYifeng Zhao 	.combphy_cfg	= rk3568_combphy_cfg,
430925c5749SYifeng Zhao };
431925c5749SYifeng Zhao 
432cf3c44cbSJon Lin static int rk3588_combphy_cfg(struct rockchip_combphy_priv *priv)
433cf3c44cbSJon Lin {
434cf3c44cbSJon Lin 	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
435d8968f57SWilliam Wu 	u32 val;
436cf3c44cbSJon Lin 
437cf3c44cbSJon Lin 	switch (priv->mode) {
438cf3c44cbSJon Lin 	case PHY_TYPE_PCIE:
439cf3c44cbSJon Lin 		param_write(priv->phy_grf, &cfg->con0_for_pcie, true);
440cf3c44cbSJon Lin 		param_write(priv->phy_grf, &cfg->con1_for_pcie, true);
441cf3c44cbSJon Lin 		param_write(priv->phy_grf, &cfg->con2_for_pcie, true);
442cf3c44cbSJon Lin 		param_write(priv->phy_grf, &cfg->con3_for_pcie, true);
443cf3c44cbSJon Lin 		break;
444cf3c44cbSJon Lin 	case PHY_TYPE_USB3:
445d8968f57SWilliam Wu 		/* Set SSC downward spread spectrum */
446d8968f57SWilliam Wu 		val = readl(priv->mmio + (0x1f << 2));
447d8968f57SWilliam Wu 		val &= ~GENMASK(5, 4);
448d8968f57SWilliam Wu 		val |= 0x01 << 4;
449d8968f57SWilliam Wu 		writel(val, priv->mmio + 0x7c);
450d8968f57SWilliam Wu 
451d8968f57SWilliam Wu 		/* Enable adaptive CTLE for USB3.0 Rx */
452d8968f57SWilliam Wu 		val = readl(priv->mmio + (0x0e << 2));
453d8968f57SWilliam Wu 		val &= ~GENMASK(0, 0);
454d8968f57SWilliam Wu 		val |= 0x01;
455d8968f57SWilliam Wu 		writel(val, priv->mmio + (0x0e << 2));
456d8968f57SWilliam Wu 
457d8968f57SWilliam Wu 		/* Set PLL KVCO fine tuning signals */
458d8968f57SWilliam Wu 		val = readl(priv->mmio + (0x20 << 2));
459d8968f57SWilliam Wu 		val &= ~(0x7 << 2);
460d8968f57SWilliam Wu 		val |= 0x2 << 2;
461d8968f57SWilliam Wu 		writel(val, priv->mmio + (0x20 << 2));
462d8968f57SWilliam Wu 
463d8968f57SWilliam Wu 		/* Set PLL LPF R1 to su_trim[10:7]=1001 */
464d8968f57SWilliam Wu 		writel(0x4, priv->mmio + (0xb << 2));
465d8968f57SWilliam Wu 
466d8968f57SWilliam Wu 		/* Set PLL input clock divider 1/2 */
467d8968f57SWilliam Wu 		val = readl(priv->mmio + (0x5 << 2));
468d8968f57SWilliam Wu 		val &= ~(0x3 << 6);
469d8968f57SWilliam Wu 		val |= 0x1 << 6;
470d8968f57SWilliam Wu 		writel(val, priv->mmio + (0x5 << 2));
471d8968f57SWilliam Wu 
472d8968f57SWilliam Wu 		/* Set PLL loop divider */
473d8968f57SWilliam Wu 		writel(0x32, priv->mmio + (0x11 << 2));
474d8968f57SWilliam Wu 
475d8968f57SWilliam Wu 		/* Set PLL KVCO to min and set PLL charge pump current to max */
476d8968f57SWilliam Wu 		writel(0xf0, priv->mmio + (0xa << 2));
477d8968f57SWilliam Wu 
478cf3c44cbSJon Lin 		param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false);
479cf3c44cbSJon Lin 		param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false);
480cf3c44cbSJon Lin 		param_write(priv->phy_grf, &cfg->usb_mode_set, true);
481cf3c44cbSJon Lin 		break;
482cf3c44cbSJon Lin 	case PHY_TYPE_SATA:
483cf3c44cbSJon Lin 		param_write(priv->phy_grf, &cfg->con0_for_sata, true);
484cf3c44cbSJon Lin 		param_write(priv->phy_grf, &cfg->con1_for_sata, true);
485cf3c44cbSJon Lin 		param_write(priv->phy_grf, &cfg->con2_for_sata, true);
486cf3c44cbSJon Lin 		param_write(priv->phy_grf, &cfg->con3_for_sata, true);
487cf3c44cbSJon Lin 		param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true);
488cf3c44cbSJon Lin 		param_write(priv->pipe_grf, &cfg->pipe_con1_for_sata, true);
489cf3c44cbSJon Lin 		break;
490cf3c44cbSJon Lin 	case PHY_TYPE_SGMII:
491cf3c44cbSJon Lin 	case PHY_TYPE_QSGMII:
492cf3c44cbSJon Lin 	default:
493cf3c44cbSJon Lin 		dev_err(priv->dev, "incompatible PHY type\n");
494cf3c44cbSJon Lin 		return -EINVAL;
495cf3c44cbSJon Lin 	}
496cf3c44cbSJon Lin 
497c72d402cSJon Lin 	/* 100MHz refclock signal is good */
498c72d402cSJon Lin 	clk_set_rate(&priv->ref_clk, 100000000);
499cf3c44cbSJon Lin 	param_write(priv->phy_grf, &cfg->pipe_clk_100m, true);
500e278c201SKever Yang 	if (priv->mode == PHY_TYPE_PCIE) {
501e278c201SKever Yang 		/* PLL KVCO tuning fine */
502e278c201SKever Yang 		val = readl(priv->mmio + (0x20 << 2));
503e278c201SKever Yang 		val &= ~GENMASK(4, 2);
504e278c201SKever Yang 		val |= 0x4 << 2;
505e278c201SKever Yang 		writel(val, priv->mmio + (0x20 << 2));
506e278c201SKever Yang 
507e278c201SKever Yang 		/* Set up rx_trim: PLL LPF C1 85pf R1 1.25kohm */
508e278c201SKever Yang 		val = 0x4c;
509e278c201SKever Yang 		writel(val, priv->mmio + (0x1b << 2));
510e278c201SKever Yang 
511e278c201SKever Yang 		/* Set up su_trim: T3 */
512e278c201SKever Yang 		val = 0xb0;
513e278c201SKever Yang 		writel(val, priv->mmio + (0xa << 2));
514e278c201SKever Yang 		val = 0x47;
515e278c201SKever Yang 		writel(val, priv->mmio + (0xb << 2));
516e278c201SKever Yang 		val = 0x57;
517e278c201SKever Yang 		writel(val, priv->mmio + (0xd << 2));
518e278c201SKever Yang 	}
519cf3c44cbSJon Lin 
520cf3c44cbSJon Lin 	return 0;
521cf3c44cbSJon Lin }
522cf3c44cbSJon Lin 
523cf3c44cbSJon Lin static const struct rockchip_combphy_grfcfg rk3588_combphy_grfcfgs = {
524cf3c44cbSJon Lin 	/* pipe-phy-grf */
525cf3c44cbSJon Lin 	.pcie_mode_set		= { 0x0000, 5, 0, 0x00, 0x11 },
526cf3c44cbSJon Lin 	.usb_mode_set		= { 0x0000, 5, 0, 0x00, 0x04 },
527cf3c44cbSJon Lin 	.pipe_rxterm_set	= { 0x0000, 12, 12, 0x00, 0x01 },
528cf3c44cbSJon Lin 	.pipe_txelec_set	= { 0x0004, 1, 1, 0x00, 0x01 },
529cf3c44cbSJon Lin 	.pipe_txcomp_set	= { 0x0004, 4, 4, 0x00, 0x01 },
530cf3c44cbSJon Lin 	.pipe_clk_25m		= { 0x0004, 14, 13, 0x00, 0x01 },
531cf3c44cbSJon Lin 	.pipe_clk_100m		= { 0x0004, 14, 13, 0x00, 0x02 },
532cf3c44cbSJon Lin 	.pipe_rxterm_sel	= { 0x0008, 8, 8, 0x00, 0x01 },
533cf3c44cbSJon Lin 	.pipe_txelec_sel	= { 0x0008, 12, 12, 0x00, 0x01 },
534cf3c44cbSJon Lin 	.pipe_txcomp_sel	= { 0x0008, 15, 15, 0x00, 0x01 },
535cf3c44cbSJon Lin 	.pipe_clk_ext		= { 0x000c, 9, 8, 0x02, 0x01 },
536cf3c44cbSJon Lin 	.pipe_phy_status	= { 0x0034, 6, 6, 0x01, 0x00 },
537cf3c44cbSJon Lin 	.con0_for_pcie		= { 0x0000, 15, 0, 0x00, 0x1000 },
538cf3c44cbSJon Lin 	.con1_for_pcie		= { 0x0004, 15, 0, 0x00, 0x0000 },
539cf3c44cbSJon Lin 	.con2_for_pcie		= { 0x0008, 15, 0, 0x00, 0x0101 },
540cf3c44cbSJon Lin 	.con3_for_pcie		= { 0x000c, 15, 0, 0x00, 0x0200 },
541cf3c44cbSJon Lin 	.con0_for_sata		= { 0x0000, 15, 0, 0x00, 0x0129 },
542cf3c44cbSJon Lin 	.con1_for_sata		= { 0x0004, 15, 0, 0x00, 0x0040 },
543cf3c44cbSJon Lin 	.con2_for_sata		= { 0x0008, 15, 0, 0x00, 0x80c1 },
544cf3c44cbSJon Lin 	.con3_for_sata		= { 0x000c, 15, 0, 0x00, 0x0407 },
545cf3c44cbSJon Lin 	/* pipe-grf */
546cf3c44cbSJon Lin 	.pipe_con0_for_sata	= { 0x0000, 11, 5, 0x00, 0x22 },
547cf3c44cbSJon Lin 	.pipe_con1_for_sata	= { 0x0000, 2, 0, 0x00, 0x2 },
548cf3c44cbSJon Lin };
549cf3c44cbSJon Lin 
550cf3c44cbSJon Lin static const struct rockchip_combphy_cfg rk3588_combphy_cfgs = {
551cf3c44cbSJon Lin 	.grfcfg		= &rk3588_combphy_grfcfgs,
552cf3c44cbSJon Lin 	.combphy_cfg	= rk3588_combphy_cfg,
553cf3c44cbSJon Lin };
554cf3c44cbSJon Lin 
555925c5749SYifeng Zhao static const struct udevice_id rockchip_combphy_ids[] = {
556925c5749SYifeng Zhao 	{
557925c5749SYifeng Zhao 		.compatible = "rockchip,rk3568-naneng-combphy",
558925c5749SYifeng Zhao 		.data = (ulong)&rk3568_combphy_cfgs
559925c5749SYifeng Zhao 	},
560cf3c44cbSJon Lin 	{
561cf3c44cbSJon Lin 		.compatible = "rockchip,rk3588-naneng-combphy",
562cf3c44cbSJon Lin 		.data = (ulong)&rk3588_combphy_cfgs
563cf3c44cbSJon Lin 	},
564925c5749SYifeng Zhao 	{ }
565925c5749SYifeng Zhao };
566925c5749SYifeng Zhao 
567925c5749SYifeng Zhao U_BOOT_DRIVER(rockchip_naneng_combphy) = {
568925c5749SYifeng Zhao 	.name		= "naneng-combphy",
569925c5749SYifeng Zhao 	.id		= UCLASS_PHY,
570925c5749SYifeng Zhao 	.of_match	= rockchip_combphy_ids,
571925c5749SYifeng Zhao 	.ops		= &rochchip_combphy_ops,
572925c5749SYifeng Zhao 	.probe		= rockchip_combphy_probe,
573925c5749SYifeng Zhao 	.priv_auto_alloc_size = sizeof(struct rockchip_combphy_priv),
574925c5749SYifeng Zhao };
575