1*ee5f1a3fSBiju Das // SPDX-License-Identifier: GPL-2.0
2*ee5f1a3fSBiju Das /*
3*ee5f1a3fSBiju Das * Renesas RZ/G3E USB3.0 PHY driver
4*ee5f1a3fSBiju Das *
5*ee5f1a3fSBiju Das * Copyright (C) 2025 Renesas Electronics Corporation
6*ee5f1a3fSBiju Das */
7*ee5f1a3fSBiju Das
8*ee5f1a3fSBiju Das #include <linux/bitfield.h>
9*ee5f1a3fSBiju Das #include <linux/delay.h>
10*ee5f1a3fSBiju Das #include <linux/io.h>
11*ee5f1a3fSBiju Das #include <linux/iopoll.h>
12*ee5f1a3fSBiju Das #include <linux/module.h>
13*ee5f1a3fSBiju Das #include <linux/of.h>
14*ee5f1a3fSBiju Das #include <linux/phy/phy.h>
15*ee5f1a3fSBiju Das #include <linux/platform_device.h>
16*ee5f1a3fSBiju Das #include <linux/pm_runtime.h>
17*ee5f1a3fSBiju Das #include <linux/reset.h>
18*ee5f1a3fSBiju Das
19*ee5f1a3fSBiju Das #define USB3_TEST_RESET 0x0000
20*ee5f1a3fSBiju Das #define USB3_TEST_UTMICTRL2 0x0b04
21*ee5f1a3fSBiju Das #define USB3_TEST_PRMCTRL5_R 0x0c10
22*ee5f1a3fSBiju Das #define USB3_TEST_PRMCTRL6_R 0x0c14
23*ee5f1a3fSBiju Das
24*ee5f1a3fSBiju Das #define USB3_TEST_RSTCTRL 0x1000
25*ee5f1a3fSBiju Das #define USB3_TEST_CLKCTRL 0x1004
26*ee5f1a3fSBiju Das #define USB3_TEST_RAMCTRL 0x100c
27*ee5f1a3fSBiju Das #define USB3_TEST_CREGCTRL 0x1010
28*ee5f1a3fSBiju Das #define USB3_TEST_LANECONFIG0 0x1030
29*ee5f1a3fSBiju Das
30*ee5f1a3fSBiju Das #define USB3_TEST_RESET_PORTRESET0_CTRL BIT(9)
31*ee5f1a3fSBiju Das #define USB3_TEST_RESET_SIDDQ BIT(3)
32*ee5f1a3fSBiju Das #define USB3_TEST_RESET_PHY_RESET BIT(2)
33*ee5f1a3fSBiju Das #define USB3_TEST_RESET_PORTRESET0 BIT(1)
34*ee5f1a3fSBiju Das #define USB3_TEST_RESET_RELEASE_OVERRIDE (0)
35*ee5f1a3fSBiju Das
36*ee5f1a3fSBiju Das #define USB3_TEST_UTMICTRL2_CTRL_MASK GENMASK(9, 8)
37*ee5f1a3fSBiju Das #define USB3_TEST_UTMICTRL2_MODE_MASK GENMASK(1, 0)
38*ee5f1a3fSBiju Das
39*ee5f1a3fSBiju Das #define USB3_TEST_PRMCTRL5_R_TXPREEMPAMPTUNE0_MASK GENMASK(2, 1)
40*ee5f1a3fSBiju Das
41*ee5f1a3fSBiju Das #define USB3_TEST_PRMCTRL6_R_OTGTUNE0_MASK GENMASK(2, 0)
42*ee5f1a3fSBiju Das
43*ee5f1a3fSBiju Das #define USB3_TEST_RSTCTRL_HARDRESET_ODEN BIT(9)
44*ee5f1a3fSBiju Das #define USB3_TEST_RSTCTRL_PIPERESET_ODEN BIT(8)
45*ee5f1a3fSBiju Das #define USB3_TEST_RSTCTRL_HARDRESET BIT(1)
46*ee5f1a3fSBiju Das #define USB3_TEST_RSTCTRL_PIPERESET BIT(0)
47*ee5f1a3fSBiju Das #define USB3_TEST_RSTCTRL_ASSERT \
48*ee5f1a3fSBiju Das (USB3_TEST_RSTCTRL_HARDRESET_ODEN | USB3_TEST_RSTCTRL_PIPERESET_ODEN | \
49*ee5f1a3fSBiju Das USB3_TEST_RSTCTRL_HARDRESET | USB3_TEST_RSTCTRL_PIPERESET)
50*ee5f1a3fSBiju Das #define USB3_TEST_RSTCTRL_RELEASE_HARDRESET \
51*ee5f1a3fSBiju Das (USB3_TEST_RSTCTRL_HARDRESET_ODEN | USB3_TEST_RSTCTRL_PIPERESET_ODEN | \
52*ee5f1a3fSBiju Das USB3_TEST_RSTCTRL_PIPERESET)
53*ee5f1a3fSBiju Das #define USB3_TEST_RSTCTRL_DEASSERT \
54*ee5f1a3fSBiju Das (USB3_TEST_RSTCTRL_HARDRESET_ODEN | USB3_TEST_RSTCTRL_PIPERESET_ODEN)
55*ee5f1a3fSBiju Das #define USB3_TEST_RSTCTRL_RELEASE_OVERRIDE (0)
56*ee5f1a3fSBiju Das
57*ee5f1a3fSBiju Das #define USB3_TEST_CLKCTRL_MPLLA_SSC_EN BIT(2)
58*ee5f1a3fSBiju Das
59*ee5f1a3fSBiju Das #define USB3_TEST_RAMCTRL_SRAM_INIT_DONE BIT(2)
60*ee5f1a3fSBiju Das #define USB3_TEST_RAMCTRL_SRAM_EXT_LD_DONE BIT(0)
61*ee5f1a3fSBiju Das
62*ee5f1a3fSBiju Das #define USB3_TEST_CREGCTRL_PARA_SEL BIT(8)
63*ee5f1a3fSBiju Das
64*ee5f1a3fSBiju Das #define USB3_TEST_LANECONFIG0_DEFAULT (0xd)
65*ee5f1a3fSBiju Das
66*ee5f1a3fSBiju Das struct rz_usb3 {
67*ee5f1a3fSBiju Das void __iomem *base;
68*ee5f1a3fSBiju Das struct reset_control *rstc;
69*ee5f1a3fSBiju Das bool skip_reinit;
70*ee5f1a3fSBiju Das };
71*ee5f1a3fSBiju Das
rzg3e_phy_usb2test_phy_init(void __iomem * base)72*ee5f1a3fSBiju Das static void rzg3e_phy_usb2test_phy_init(void __iomem *base)
73*ee5f1a3fSBiju Das {
74*ee5f1a3fSBiju Das u32 val;
75*ee5f1a3fSBiju Das
76*ee5f1a3fSBiju Das val = readl(base + USB3_TEST_UTMICTRL2);
77*ee5f1a3fSBiju Das val |= USB3_TEST_UTMICTRL2_CTRL_MASK | USB3_TEST_UTMICTRL2_MODE_MASK;
78*ee5f1a3fSBiju Das writel(val, base + USB3_TEST_UTMICTRL2);
79*ee5f1a3fSBiju Das
80*ee5f1a3fSBiju Das val = readl(base + USB3_TEST_PRMCTRL5_R);
81*ee5f1a3fSBiju Das val &= ~USB3_TEST_PRMCTRL5_R_TXPREEMPAMPTUNE0_MASK;
82*ee5f1a3fSBiju Das val |= FIELD_PREP(USB3_TEST_PRMCTRL5_R_TXPREEMPAMPTUNE0_MASK, 2);
83*ee5f1a3fSBiju Das writel(val, base + USB3_TEST_PRMCTRL5_R);
84*ee5f1a3fSBiju Das
85*ee5f1a3fSBiju Das val = readl(base + USB3_TEST_PRMCTRL6_R);
86*ee5f1a3fSBiju Das val &= ~USB3_TEST_PRMCTRL6_R_OTGTUNE0_MASK;
87*ee5f1a3fSBiju Das val |= FIELD_PREP(USB3_TEST_PRMCTRL6_R_OTGTUNE0_MASK, 7);
88*ee5f1a3fSBiju Das writel(val, base + USB3_TEST_PRMCTRL6_R);
89*ee5f1a3fSBiju Das
90*ee5f1a3fSBiju Das val = readl(base + USB3_TEST_RESET);
91*ee5f1a3fSBiju Das val &= ~USB3_TEST_RESET_SIDDQ;
92*ee5f1a3fSBiju Das val |= USB3_TEST_RESET_PORTRESET0_CTRL | USB3_TEST_RESET_PHY_RESET |
93*ee5f1a3fSBiju Das USB3_TEST_RESET_PORTRESET0;
94*ee5f1a3fSBiju Das writel(val, base + USB3_TEST_RESET);
95*ee5f1a3fSBiju Das fsleep(10);
96*ee5f1a3fSBiju Das
97*ee5f1a3fSBiju Das val &= ~(USB3_TEST_RESET_PHY_RESET | USB3_TEST_RESET_PORTRESET0);
98*ee5f1a3fSBiju Das writel(val, base + USB3_TEST_RESET);
99*ee5f1a3fSBiju Das fsleep(10);
100*ee5f1a3fSBiju Das
101*ee5f1a3fSBiju Das val = readl(base + USB3_TEST_UTMICTRL2);
102*ee5f1a3fSBiju Das val &= ~USB3_TEST_UTMICTRL2_CTRL_MASK;
103*ee5f1a3fSBiju Das writel(val, base + USB3_TEST_UTMICTRL2);
104*ee5f1a3fSBiju Das
105*ee5f1a3fSBiju Das writel(USB3_TEST_RESET_RELEASE_OVERRIDE, base + USB3_TEST_RESET);
106*ee5f1a3fSBiju Das }
107*ee5f1a3fSBiju Das
rzg3e_phy_usb3test_phy_init(void __iomem * base)108*ee5f1a3fSBiju Das static int rzg3e_phy_usb3test_phy_init(void __iomem *base)
109*ee5f1a3fSBiju Das {
110*ee5f1a3fSBiju Das int ret;
111*ee5f1a3fSBiju Das u32 val;
112*ee5f1a3fSBiju Das
113*ee5f1a3fSBiju Das writel(USB3_TEST_CREGCTRL_PARA_SEL, base + USB3_TEST_CREGCTRL);
114*ee5f1a3fSBiju Das writel(USB3_TEST_RSTCTRL_ASSERT, base + USB3_TEST_RSTCTRL);
115*ee5f1a3fSBiju Das fsleep(20);
116*ee5f1a3fSBiju Das
117*ee5f1a3fSBiju Das writel(USB3_TEST_CLKCTRL_MPLLA_SSC_EN, base + USB3_TEST_CLKCTRL);
118*ee5f1a3fSBiju Das writel(USB3_TEST_LANECONFIG0_DEFAULT, base + USB3_TEST_LANECONFIG0);
119*ee5f1a3fSBiju Das writel(USB3_TEST_RSTCTRL_RELEASE_HARDRESET, base + USB3_TEST_RSTCTRL);
120*ee5f1a3fSBiju Das
121*ee5f1a3fSBiju Das ret = readl_poll_timeout_atomic(base + USB3_TEST_RAMCTRL, val,
122*ee5f1a3fSBiju Das val & USB3_TEST_RAMCTRL_SRAM_INIT_DONE, 1, 10000);
123*ee5f1a3fSBiju Das if (ret)
124*ee5f1a3fSBiju Das return ret;
125*ee5f1a3fSBiju Das
126*ee5f1a3fSBiju Das writel(USB3_TEST_RSTCTRL_DEASSERT, base + USB3_TEST_RSTCTRL);
127*ee5f1a3fSBiju Das writel(USB3_TEST_RAMCTRL_SRAM_EXT_LD_DONE, base + USB3_TEST_RAMCTRL);
128*ee5f1a3fSBiju Das writel(USB3_TEST_RSTCTRL_RELEASE_OVERRIDE, base + USB3_TEST_RSTCTRL);
129*ee5f1a3fSBiju Das
130*ee5f1a3fSBiju Das return 0;
131*ee5f1a3fSBiju Das }
132*ee5f1a3fSBiju Das
rzg3e_phy_usb3_init_helper(void __iomem * base)133*ee5f1a3fSBiju Das static int rzg3e_phy_usb3_init_helper(void __iomem *base)
134*ee5f1a3fSBiju Das {
135*ee5f1a3fSBiju Das rzg3e_phy_usb2test_phy_init(base);
136*ee5f1a3fSBiju Das
137*ee5f1a3fSBiju Das return rzg3e_phy_usb3test_phy_init(base);
138*ee5f1a3fSBiju Das }
139*ee5f1a3fSBiju Das
rzg3e_phy_usb3_init(struct phy * p)140*ee5f1a3fSBiju Das static int rzg3e_phy_usb3_init(struct phy *p)
141*ee5f1a3fSBiju Das {
142*ee5f1a3fSBiju Das struct rz_usb3 *r = phy_get_drvdata(p);
143*ee5f1a3fSBiju Das int ret = 0;
144*ee5f1a3fSBiju Das
145*ee5f1a3fSBiju Das if (!r->skip_reinit)
146*ee5f1a3fSBiju Das ret = rzg3e_phy_usb3_init_helper(r->base);
147*ee5f1a3fSBiju Das
148*ee5f1a3fSBiju Das return ret;
149*ee5f1a3fSBiju Das }
150*ee5f1a3fSBiju Das
151*ee5f1a3fSBiju Das static const struct phy_ops rzg3e_phy_usb3_ops = {
152*ee5f1a3fSBiju Das .init = rzg3e_phy_usb3_init,
153*ee5f1a3fSBiju Das .owner = THIS_MODULE,
154*ee5f1a3fSBiju Das };
155*ee5f1a3fSBiju Das
rzg3e_phy_usb3_probe(struct platform_device * pdev)156*ee5f1a3fSBiju Das static int rzg3e_phy_usb3_probe(struct platform_device *pdev)
157*ee5f1a3fSBiju Das {
158*ee5f1a3fSBiju Das struct device *dev = &pdev->dev;
159*ee5f1a3fSBiju Das struct phy_provider *provider;
160*ee5f1a3fSBiju Das struct rz_usb3 *r;
161*ee5f1a3fSBiju Das struct phy *phy;
162*ee5f1a3fSBiju Das int ret;
163*ee5f1a3fSBiju Das
164*ee5f1a3fSBiju Das r = devm_kzalloc(dev, sizeof(*r), GFP_KERNEL);
165*ee5f1a3fSBiju Das if (!r)
166*ee5f1a3fSBiju Das return -ENOMEM;
167*ee5f1a3fSBiju Das
168*ee5f1a3fSBiju Das r->base = devm_platform_ioremap_resource(pdev, 0);
169*ee5f1a3fSBiju Das if (IS_ERR(r->base))
170*ee5f1a3fSBiju Das return PTR_ERR(r->base);
171*ee5f1a3fSBiju Das
172*ee5f1a3fSBiju Das r->rstc = devm_reset_control_get_shared_deasserted(dev, NULL);
173*ee5f1a3fSBiju Das if (IS_ERR(r->rstc))
174*ee5f1a3fSBiju Das return dev_err_probe(dev, PTR_ERR(r->rstc), "failed to get deasserted reset\n");
175*ee5f1a3fSBiju Das
176*ee5f1a3fSBiju Das /*
177*ee5f1a3fSBiju Das * devm_phy_create() will call pm_runtime_enable(&phy->dev);
178*ee5f1a3fSBiju Das * And then, phy-core will manage runtime pm for this device.
179*ee5f1a3fSBiju Das */
180*ee5f1a3fSBiju Das ret = devm_pm_runtime_enable(dev);
181*ee5f1a3fSBiju Das if (ret < 0)
182*ee5f1a3fSBiju Das return ret;
183*ee5f1a3fSBiju Das
184*ee5f1a3fSBiju Das phy = devm_phy_create(dev, NULL, &rzg3e_phy_usb3_ops);
185*ee5f1a3fSBiju Das if (IS_ERR(phy))
186*ee5f1a3fSBiju Das return dev_err_probe(dev, PTR_ERR(phy), "failed to create USB3 PHY\n");
187*ee5f1a3fSBiju Das
188*ee5f1a3fSBiju Das platform_set_drvdata(pdev, r);
189*ee5f1a3fSBiju Das phy_set_drvdata(phy, r);
190*ee5f1a3fSBiju Das
191*ee5f1a3fSBiju Das provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
192*ee5f1a3fSBiju Das if (IS_ERR(provider))
193*ee5f1a3fSBiju Das return dev_err_probe(dev, PTR_ERR(provider), "failed to register PHY provider\n");
194*ee5f1a3fSBiju Das
195*ee5f1a3fSBiju Das return 0;
196*ee5f1a3fSBiju Das }
197*ee5f1a3fSBiju Das
rzg3e_phy_usb3_suspend(struct device * dev)198*ee5f1a3fSBiju Das static int rzg3e_phy_usb3_suspend(struct device *dev)
199*ee5f1a3fSBiju Das {
200*ee5f1a3fSBiju Das struct rz_usb3 *r = dev_get_drvdata(dev);
201*ee5f1a3fSBiju Das
202*ee5f1a3fSBiju Das pm_runtime_put(dev);
203*ee5f1a3fSBiju Das reset_control_assert(r->rstc);
204*ee5f1a3fSBiju Das r->skip_reinit = false;
205*ee5f1a3fSBiju Das
206*ee5f1a3fSBiju Das return 0;
207*ee5f1a3fSBiju Das }
208*ee5f1a3fSBiju Das
rzg3e_phy_usb3_resume(struct device * dev)209*ee5f1a3fSBiju Das static int rzg3e_phy_usb3_resume(struct device *dev)
210*ee5f1a3fSBiju Das {
211*ee5f1a3fSBiju Das struct rz_usb3 *r = dev_get_drvdata(dev);
212*ee5f1a3fSBiju Das int ret;
213*ee5f1a3fSBiju Das
214*ee5f1a3fSBiju Das ret = reset_control_deassert(r->rstc);
215*ee5f1a3fSBiju Das if (ret)
216*ee5f1a3fSBiju Das return ret;
217*ee5f1a3fSBiju Das
218*ee5f1a3fSBiju Das ret = pm_runtime_resume_and_get(dev);
219*ee5f1a3fSBiju Das if (ret)
220*ee5f1a3fSBiju Das goto reset_assert;
221*ee5f1a3fSBiju Das
222*ee5f1a3fSBiju Das ret = rzg3e_phy_usb3_init_helper(r->base);
223*ee5f1a3fSBiju Das if (ret)
224*ee5f1a3fSBiju Das goto pm_put;
225*ee5f1a3fSBiju Das
226*ee5f1a3fSBiju Das r->skip_reinit = true;
227*ee5f1a3fSBiju Das
228*ee5f1a3fSBiju Das return 0;
229*ee5f1a3fSBiju Das
230*ee5f1a3fSBiju Das pm_put:
231*ee5f1a3fSBiju Das pm_runtime_put(dev);
232*ee5f1a3fSBiju Das reset_assert:
233*ee5f1a3fSBiju Das reset_control_assert(r->rstc);
234*ee5f1a3fSBiju Das return ret;
235*ee5f1a3fSBiju Das }
236*ee5f1a3fSBiju Das
237*ee5f1a3fSBiju Das static const struct dev_pm_ops rzg3e_phy_usb3_pm = {
238*ee5f1a3fSBiju Das NOIRQ_SYSTEM_SLEEP_PM_OPS(rzg3e_phy_usb3_suspend, rzg3e_phy_usb3_resume)
239*ee5f1a3fSBiju Das };
240*ee5f1a3fSBiju Das
241*ee5f1a3fSBiju Das static const struct of_device_id rzg3e_phy_usb3_match_table[] = {
242*ee5f1a3fSBiju Das { .compatible = "renesas,r9a09g047-usb3-phy" },
243*ee5f1a3fSBiju Das { /* Sentinel */ }
244*ee5f1a3fSBiju Das };
245*ee5f1a3fSBiju Das
246*ee5f1a3fSBiju Das MODULE_DEVICE_TABLE(of, rzg3e_phy_usb3_match_table);
247*ee5f1a3fSBiju Das static struct platform_driver rzg3e_phy_usb3_driver = {
248*ee5f1a3fSBiju Das .driver = {
249*ee5f1a3fSBiju Das .name = "phy_rzg3e_usb3",
250*ee5f1a3fSBiju Das .of_match_table = rzg3e_phy_usb3_match_table,
251*ee5f1a3fSBiju Das .pm = pm_sleep_ptr(&rzg3e_phy_usb3_pm),
252*ee5f1a3fSBiju Das },
253*ee5f1a3fSBiju Das .probe = rzg3e_phy_usb3_probe,
254*ee5f1a3fSBiju Das };
255*ee5f1a3fSBiju Das module_platform_driver(rzg3e_phy_usb3_driver);
256*ee5f1a3fSBiju Das
257*ee5f1a3fSBiju Das MODULE_LICENSE("GPL");
258*ee5f1a3fSBiju Das MODULE_DESCRIPTION("Renesas RZ/G3E USB3.0 PHY Driver");
259*ee5f1a3fSBiju Das MODULE_AUTHOR("biju.das.jz@bp.renesas.com>");
260