xref: /linux/drivers/usb/dwc3/dwc3-rtk.c (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
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 
switch_usb2_role(struct dwc3_rtk * rtk,enum usb_role role)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 
switch_dwc3_role(struct dwc3_rtk * rtk,enum usb_role role)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 
dwc3_rtk_get_role(struct dwc3_rtk * rtk)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 
dwc3_rtk_set_role(struct dwc3_rtk * rtk,enum usb_role role)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)
dwc3_usb_role_switch_set(struct usb_role_switch * sw,enum usb_role role)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 
dwc3_usb_role_switch_get(struct usb_role_switch * sw)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 
dwc3_rtk_setup_role_switch(struct dwc3_rtk * rtk)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 
dwc3_rtk_remove_role_switch(struct dwc3_rtk * rtk)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 
__get_dwc3_maximum_speed(struct device_node * np)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 
dwc3_rtk_init(struct dwc3_rtk * rtk)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 
dwc3_rtk_probe_dwc3_core(struct dwc3_rtk * rtk)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 
dwc3_rtk_probe(struct platform_device * pdev)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 
dwc3_rtk_remove(struct platform_device * pdev)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 
dwc3_rtk_shutdown(struct platform_device * pdev)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
dwc3_rtk_suspend(struct device * dev)412 static int dwc3_rtk_suspend(struct device *dev)
413 {
414 	return 0;
415 }
416 
dwc3_rtk_resume(struct device * dev)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_new	= 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 <stanley_chang@realtek.com>");
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");
460