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