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