]> Git Repo - J-linux.git/blob - drivers/usb/dwc3/dwc3-rtk.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / usb / dwc3 / dwc3-rtk.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * dwc3-rtk.c - Realtek DWC3 Specific Glue layer
4  *
5  * Copyright (C) 2023 Realtek Semiconductor Corporation
6  *
7  */
8
9 #include <linux/cleanup.h>
10 #include <linux/module.h>
11 #include <linux/kernel.h>
12 #include <linux/platform_device.h>
13 #include <linux/of.h>
14 #include <linux/of_platform.h>
15 #include <linux/suspend.h>
16 #include <linux/sys_soc.h>
17 #include <linux/usb/otg.h>
18 #include <linux/usb/of.h>
19 #include <linux/usb/role.h>
20
21 #include "core.h"
22
23 #define WRAP_CTR_REG  0x0
24 #define DISABLE_MULTI_REQ BIT(1)
25 #define DESC_R2W_MULTI_DISABLE BIT(9)
26 #define FORCE_PIPE3_PHY_STATUS_TO_0 BIT(13)
27
28 #define WRAP_USB2_PHY_UTMI_REG 0x8
29 #define TXHSVM_EN BIT(3)
30
31 #define WRAP_PHY_PIPE_REG 0xC
32 #define RESET_DISABLE_PIPE3_P0 BIT(0)
33 #define CLOCK_ENABLE_FOR_PIPE3_PCLK BIT(1)
34
35 #define WRAP_USB_HMAC_CTR0_REG 0x60
36 #define U3PORT_DIS BIT(8)
37
38 #define WRAP_USB2_PHY_REG  0x70
39 #define USB2_PHY_EN_PHY_PLL_PORT0 BIT(12)
40 #define USB2_PHY_EN_PHY_PLL_PORT1 BIT(13)
41 #define USB2_PHY_SWITCH_MASK 0x707
42 #define USB2_PHY_SWITCH_DEVICE 0x0
43 #define USB2_PHY_SWITCH_HOST 0x606
44
45 #define WRAP_APHY_REG 0x128
46 #define USB3_MBIAS_ENABLE BIT(1)
47
48 /* pm control */
49 #define WRAP_USB_DBUS_PWR_CTRL_REG 0x160
50 #define USB_DBUS_PWR_CTRL_REG 0x0
51 #define DBUS_PWR_CTRL_EN BIT(0)
52
53 struct dwc3_rtk {
54         struct device *dev;
55         void __iomem *regs;
56         size_t regs_size;
57         void __iomem *pm_base;
58
59         struct dwc3 *dwc;
60
61         enum usb_role cur_role;
62         struct usb_role_switch *role_switch;
63 };
64
65 static void switch_usb2_role(struct dwc3_rtk *rtk, enum usb_role role)
66 {
67         void __iomem *reg;
68         int val;
69
70         reg = rtk->regs + WRAP_USB2_PHY_REG;
71         val = ~USB2_PHY_SWITCH_MASK & readl(reg);
72
73         switch (role) {
74         case USB_ROLE_DEVICE:
75                 writel(USB2_PHY_SWITCH_DEVICE | val, reg);
76                 break;
77         case USB_ROLE_HOST:
78                 writel(USB2_PHY_SWITCH_HOST | val, reg);
79                 break;
80         default:
81                 dev_dbg(rtk->dev, "%s: role=%d\n", __func__, role);
82                 break;
83         }
84 }
85
86 static void switch_dwc3_role(struct dwc3_rtk *rtk, enum usb_role role)
87 {
88         if (!rtk->dwc->role_sw)
89                 return;
90
91         usb_role_switch_set_role(rtk->dwc->role_sw, role);
92 }
93
94 static enum usb_role dwc3_rtk_get_role(struct dwc3_rtk *rtk)
95 {
96         enum usb_role role;
97
98         role = rtk->cur_role;
99
100         if (rtk->dwc && rtk->dwc->role_sw)
101                 role = usb_role_switch_get_role(rtk->dwc->role_sw);
102         else
103                 dev_dbg(rtk->dev, "%s not usb_role_switch role=%d\n", __func__, role);
104
105         return role;
106 }
107
108 static void dwc3_rtk_set_role(struct dwc3_rtk *rtk, enum usb_role role)
109 {
110         rtk->cur_role = role;
111
112         switch_dwc3_role(rtk, role);
113         mdelay(10);
114         switch_usb2_role(rtk, role);
115 }
116
117 #if IS_ENABLED(CONFIG_USB_ROLE_SWITCH)
118 static int dwc3_usb_role_switch_set(struct usb_role_switch *sw, enum usb_role role)
119 {
120         struct dwc3_rtk *rtk = usb_role_switch_get_drvdata(sw);
121
122         dwc3_rtk_set_role(rtk, role);
123
124         return 0;
125 }
126
127 static enum usb_role dwc3_usb_role_switch_get(struct usb_role_switch *sw)
128 {
129         struct dwc3_rtk *rtk = usb_role_switch_get_drvdata(sw);
130
131         return dwc3_rtk_get_role(rtk);
132 }
133
134 static int dwc3_rtk_setup_role_switch(struct dwc3_rtk *rtk)
135 {
136         struct usb_role_switch_desc dwc3_role_switch = {NULL};
137
138         dwc3_role_switch.name = dev_name(rtk->dev);
139         dwc3_role_switch.driver_data = rtk;
140         dwc3_role_switch.allow_userspace_control = true;
141         dwc3_role_switch.fwnode = dev_fwnode(rtk->dev);
142         dwc3_role_switch.set = dwc3_usb_role_switch_set;
143         dwc3_role_switch.get = dwc3_usb_role_switch_get;
144         rtk->role_switch = usb_role_switch_register(rtk->dev, &dwc3_role_switch);
145         if (IS_ERR(rtk->role_switch))
146                 return PTR_ERR(rtk->role_switch);
147
148         return 0;
149 }
150
151 static int dwc3_rtk_remove_role_switch(struct dwc3_rtk *rtk)
152 {
153         if (rtk->role_switch)
154                 usb_role_switch_unregister(rtk->role_switch);
155
156         rtk->role_switch = NULL;
157
158         return 0;
159 }
160 #else
161 #define dwc3_rtk_setup_role_switch(x) 0
162 #define dwc3_rtk_remove_role_switch(x) 0
163 #endif
164
165 static const char *const speed_names[] = {
166         [USB_SPEED_UNKNOWN] = "UNKNOWN",
167         [USB_SPEED_LOW] = "low-speed",
168         [USB_SPEED_FULL] = "full-speed",
169         [USB_SPEED_HIGH] = "high-speed",
170         [USB_SPEED_WIRELESS] = "wireless",
171         [USB_SPEED_SUPER] = "super-speed",
172         [USB_SPEED_SUPER_PLUS] = "super-speed-plus",
173 };
174
175 static enum usb_device_speed __get_dwc3_maximum_speed(struct device_node *np)
176 {
177         const char *maximum_speed;
178         int ret;
179
180         struct device_node *dwc3_np __free(device_node) = of_get_compatible_child(np,
181                                                                                   "snps,dwc3");
182         if (!dwc3_np)
183                 return USB_SPEED_UNKNOWN;
184
185         ret = of_property_read_string(dwc3_np, "maximum-speed", &maximum_speed);
186         if (ret < 0)
187                 return USB_SPEED_UNKNOWN;
188
189         ret = match_string(speed_names, ARRAY_SIZE(speed_names), maximum_speed);
190
191         return (ret < 0) ? USB_SPEED_UNKNOWN : ret;
192 }
193
194 static int dwc3_rtk_init(struct dwc3_rtk *rtk)
195 {
196         struct device *dev = rtk->dev;
197         void __iomem *reg;
198         int val;
199         enum usb_device_speed maximum_speed;
200         const struct soc_device_attribute rtk_soc_kylin_a00[] = {
201                 { .family = "Realtek Kylin", .revision = "A00", },
202                 { /* empty */ } };
203         const struct soc_device_attribute rtk_soc_hercules[] = {
204                 { .family = "Realtek Hercules", }, { /* empty */ } };
205         const struct soc_device_attribute rtk_soc_thor[] = {
206                 { .family = "Realtek Thor", }, { /* empty */ } };
207
208         if (soc_device_match(rtk_soc_kylin_a00)) {
209                 reg = rtk->regs + WRAP_CTR_REG;
210                 val = readl(reg);
211                 writel(DISABLE_MULTI_REQ | val, reg);
212                 dev_info(dev, "[bug fixed] 1295/1296 A00: add workaround to disable multiple request for D-Bus");
213         }
214
215         if (soc_device_match(rtk_soc_hercules)) {
216                 reg = rtk->regs + WRAP_USB2_PHY_REG;
217                 val = readl(reg);
218                 writel(USB2_PHY_EN_PHY_PLL_PORT1 | val, reg);
219                 dev_info(dev, "[bug fixed] 1395 add workaround to disable usb2 port 2 suspend!");
220         }
221
222         reg = rtk->regs + WRAP_USB2_PHY_UTMI_REG;
223         val = readl(reg);
224         writel(TXHSVM_EN | val, reg);
225
226         maximum_speed = __get_dwc3_maximum_speed(dev->of_node);
227         if (maximum_speed != USB_SPEED_UNKNOWN && maximum_speed <= USB_SPEED_HIGH) {
228                 if (soc_device_match(rtk_soc_thor)) {
229                         reg = rtk->regs + WRAP_USB_HMAC_CTR0_REG;
230                         val = readl(reg);
231                         writel(U3PORT_DIS | val, reg);
232                 } else {
233                         reg = rtk->regs + WRAP_CTR_REG;
234                         val = readl(reg);
235                         writel(FORCE_PIPE3_PHY_STATUS_TO_0 | val, reg);
236
237                         reg = rtk->regs + WRAP_PHY_PIPE_REG;
238                         val = ~CLOCK_ENABLE_FOR_PIPE3_PCLK & readl(reg);
239                         writel(RESET_DISABLE_PIPE3_P0 | val, reg);
240
241                         reg =  rtk->regs + WRAP_USB_HMAC_CTR0_REG;
242                         val = readl(reg);
243                         writel(U3PORT_DIS | val, reg);
244
245                         reg = rtk->regs + WRAP_APHY_REG;
246                         val = readl(reg);
247                         writel(~USB3_MBIAS_ENABLE & val, reg);
248
249                         dev_dbg(rtk->dev, "%s: disable usb 3.0 phy\n", __func__);
250                 }
251         }
252
253         reg = rtk->regs + WRAP_CTR_REG;
254         val = readl(reg);
255         writel(DESC_R2W_MULTI_DISABLE | val, reg);
256
257         /* Set phy Dp/Dm initial state to host mode to avoid the Dp glitch */
258         reg = rtk->regs + WRAP_USB2_PHY_REG;
259         val = ~USB2_PHY_SWITCH_MASK & readl(reg);
260         writel(USB2_PHY_SWITCH_HOST | val, reg);
261
262         if (rtk->pm_base) {
263                 reg = rtk->pm_base + USB_DBUS_PWR_CTRL_REG;
264                 val = DBUS_PWR_CTRL_EN | readl(reg);
265                 writel(val, reg);
266         }
267
268         return 0;
269 }
270
271 static int dwc3_rtk_probe_dwc3_core(struct dwc3_rtk *rtk)
272 {
273         struct device *dev = rtk->dev;
274         struct device_node *node = dev->of_node;
275         struct platform_device *dwc3_pdev;
276         struct device *dwc3_dev;
277         enum usb_dr_mode dr_mode;
278         int ret = 0;
279
280         ret = dwc3_rtk_init(rtk);
281         if (ret)
282                 return -EINVAL;
283
284         ret = of_platform_populate(node, NULL, NULL, dev);
285         if (ret) {
286                 dev_err(dev, "failed to add dwc3 core\n");
287                 return ret;
288         }
289
290         struct device_node *dwc3_node __free(device_node) = of_get_compatible_child(node,
291                                                                                     "snps,dwc3");
292         if (!dwc3_node) {
293                 dev_err(dev, "failed to find dwc3 core node\n");
294                 ret = -ENODEV;
295                 goto depopulate;
296         }
297
298         dwc3_pdev = of_find_device_by_node(dwc3_node);
299         if (!dwc3_pdev) {
300                 dev_err(dev, "failed to find dwc3 core platform_device\n");
301                 ret = -ENODEV;
302                 goto depopulate;
303         }
304
305         dwc3_dev = &dwc3_pdev->dev;
306         rtk->dwc = platform_get_drvdata(dwc3_pdev);
307         if (!rtk->dwc) {
308                 dev_err(dev, "failed to find dwc3 core\n");
309                 ret = -ENODEV;
310                 goto err_pdev_put;
311         }
312
313         dr_mode = usb_get_dr_mode(dwc3_dev);
314         if (dr_mode != rtk->dwc->dr_mode) {
315                 dev_info(dev, "dts set dr_mode=%d, but dwc3 set dr_mode=%d\n",
316                          dr_mode, rtk->dwc->dr_mode);
317                 dr_mode = rtk->dwc->dr_mode;
318         }
319
320         switch (dr_mode) {
321         case USB_DR_MODE_PERIPHERAL:
322                 rtk->cur_role = USB_ROLE_DEVICE;
323                 break;
324         case USB_DR_MODE_HOST:
325                 rtk->cur_role = USB_ROLE_HOST;
326                 break;
327         default:
328                 dev_dbg(rtk->dev, "%s: dr_mode=%d\n", __func__, dr_mode);
329                 break;
330         }
331
332         if (device_property_read_bool(dwc3_dev, "usb-role-switch")) {
333                 ret = dwc3_rtk_setup_role_switch(rtk);
334                 if (ret) {
335                         dev_err(dev, "dwc3_rtk_setup_role_switch fail=%d\n", ret);
336                         goto err_pdev_put;
337                 }
338                 rtk->cur_role = dwc3_rtk_get_role(rtk);
339         }
340
341         switch_usb2_role(rtk, rtk->cur_role);
342
343         platform_device_put(dwc3_pdev);
344
345         return 0;
346
347 err_pdev_put:
348         platform_device_put(dwc3_pdev);
349 depopulate:
350         of_platform_depopulate(dev);
351
352         return ret;
353 }
354
355 static int dwc3_rtk_probe(struct platform_device *pdev)
356 {
357         struct dwc3_rtk *rtk;
358         struct device *dev = &pdev->dev;
359         struct resource *res;
360         void __iomem *regs;
361
362         rtk = devm_kzalloc(dev, sizeof(*rtk), GFP_KERNEL);
363         if (!rtk)
364                 return -ENOMEM;
365
366         platform_set_drvdata(pdev, rtk);
367
368         rtk->dev = dev;
369
370         regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
371         if (IS_ERR(regs))
372                 return PTR_ERR(regs);
373
374         rtk->regs = regs;
375         rtk->regs_size = resource_size(res);
376
377         res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
378         if (res) {
379                 rtk->pm_base = devm_ioremap_resource(dev, res);
380                 if (IS_ERR(rtk->pm_base))
381                         return PTR_ERR(rtk->pm_base);
382         }
383
384         return dwc3_rtk_probe_dwc3_core(rtk);
385 }
386
387 static void dwc3_rtk_remove(struct platform_device *pdev)
388 {
389         struct dwc3_rtk *rtk = platform_get_drvdata(pdev);
390
391         rtk->dwc = NULL;
392
393         dwc3_rtk_remove_role_switch(rtk);
394
395         of_platform_depopulate(rtk->dev);
396 }
397
398 static void dwc3_rtk_shutdown(struct platform_device *pdev)
399 {
400         struct dwc3_rtk *rtk = platform_get_drvdata(pdev);
401
402         of_platform_depopulate(rtk->dev);
403 }
404
405 static const struct of_device_id rtk_dwc3_match[] = {
406         { .compatible = "realtek,rtd-dwc3" },
407         {},
408 };
409 MODULE_DEVICE_TABLE(of, rtk_dwc3_match);
410
411 #ifdef CONFIG_PM_SLEEP
412 static int dwc3_rtk_suspend(struct device *dev)
413 {
414         return 0;
415 }
416
417 static int dwc3_rtk_resume(struct device *dev)
418 {
419         struct dwc3_rtk *rtk = dev_get_drvdata(dev);
420
421         dwc3_rtk_init(rtk);
422
423         switch_usb2_role(rtk, rtk->cur_role);
424
425         /* runtime set active to reflect active state. */
426         pm_runtime_disable(dev);
427         pm_runtime_set_active(dev);
428         pm_runtime_enable(dev);
429
430         return 0;
431 }
432
433 static const struct dev_pm_ops dwc3_rtk_dev_pm_ops = {
434         SET_SYSTEM_SLEEP_PM_OPS(dwc3_rtk_suspend, dwc3_rtk_resume)
435 };
436
437 #define DEV_PM_OPS      (&dwc3_rtk_dev_pm_ops)
438 #else
439 #define DEV_PM_OPS      NULL
440 #endif /* CONFIG_PM_SLEEP */
441
442 static struct platform_driver dwc3_rtk_driver = {
443         .probe          = dwc3_rtk_probe,
444         .remove         = dwc3_rtk_remove,
445         .driver         = {
446                 .name   = "rtk-dwc3",
447                 .of_match_table = rtk_dwc3_match,
448                 .pm     = DEV_PM_OPS,
449         },
450         .shutdown       = dwc3_rtk_shutdown,
451 };
452
453 module_platform_driver(dwc3_rtk_driver);
454
455 MODULE_AUTHOR("Stanley Chang <[email protected]>");
456 MODULE_DESCRIPTION("DesignWare USB3 Realtek Glue Layer");
457 MODULE_ALIAS("platform:rtk-dwc3");
458 MODULE_LICENSE("GPL");
459 MODULE_SOFTDEP("pre: phy_rtk_usb2 phy_rtk_usb3");
This page took 0.050936 seconds and 4 git commands to generate.