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