1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Generic DWC3 Glue layer 4 * 5 * Copyright (C) 2016 - 2018 Xilinx, Inc. 6 * 7 * Based on dwc3-omap.c. 8 */ 9 10 #include <common.h> 11 #include <asm-generic/io.h> 12 #include <dm.h> 13 #include <dm/device-internal.h> 14 #include <dm/lists.h> 15 #include <dwc3-uboot.h> 16 #include <linux/usb/ch9.h> 17 #include <linux/usb/gadget.h> 18 #include <malloc.h> 19 #include <usb.h> 20 #include "core.h" 21 #include "gadget.h" 22 #include <reset.h> 23 #include <clk.h> 24 #include <usb/xhci.h> 25 26 #include "dwc3-generic.h" 27 28 struct dwc3_generic_plat { 29 fdt_addr_t base; 30 u32 maximum_speed; 31 enum usb_dr_mode dr_mode; 32 }; 33 34 struct dwc3_generic_priv { 35 void *base; 36 struct dwc3 dwc3; 37 struct phy *phys; 38 int num_phys; 39 }; 40 41 struct dwc3_generic_host_priv { 42 struct xhci_ctrl xhci_ctrl; 43 struct dwc3_generic_priv gen_priv; 44 }; 45 46 static int dwc3_generic_probe(struct udevice *dev, 47 struct dwc3_generic_priv *priv) 48 { 49 int rc; 50 struct dwc3_generic_plat *plat = dev_get_platdata(dev); 51 struct dwc3 *dwc3 = &priv->dwc3; 52 struct dwc3_glue_data *glue = dev_get_platdata(dev->parent); 53 54 dwc3->dev = dev; 55 dwc3->maximum_speed = plat->maximum_speed; 56 dwc3->dr_mode = plat->dr_mode; 57 #if CONFIG_IS_ENABLED(OF_CONTROL) 58 dwc3_of_parse(dwc3); 59 #endif 60 61 /* 62 * It must hold whole USB3.0 OTG controller in resetting to hold pipe 63 * power state in P2 before initializing TypeC PHY on RK3399 platform. 64 */ 65 if (device_is_compatible(dev->parent, "rockchip,rk3399-dwc3")) { 66 reset_assert_bulk(&glue->resets); 67 udelay(1); 68 } 69 70 rc = dwc3_setup_phy(dev, &priv->phys, &priv->num_phys); 71 if (rc) 72 return rc; 73 74 if (device_is_compatible(dev->parent, "rockchip,rk3399-dwc3")) 75 reset_deassert_bulk(&glue->resets); 76 77 priv->base = map_physmem(plat->base, DWC3_OTG_REGS_END, MAP_NOCACHE); 78 dwc3->regs = priv->base + DWC3_GLOBALS_REGS_START; 79 80 81 rc = dwc3_init(dwc3); 82 if (rc) { 83 unmap_physmem(priv->base, MAP_NOCACHE); 84 return rc; 85 } 86 87 return 0; 88 } 89 90 static int dwc3_generic_remove(struct udevice *dev, 91 struct dwc3_generic_priv *priv) 92 { 93 struct dwc3 *dwc3 = &priv->dwc3; 94 95 dwc3_remove(dwc3); 96 dwc3_shutdown_phy(dev, priv->phys, priv->num_phys); 97 unmap_physmem(dwc3->regs, MAP_NOCACHE); 98 99 return 0; 100 } 101 102 static int dwc3_generic_ofdata_to_platdata(struct udevice *dev) 103 { 104 struct dwc3_generic_plat *plat = dev_get_platdata(dev); 105 ofnode node = dev->node; 106 107 plat->base = dev_read_addr(dev); 108 109 plat->maximum_speed = usb_get_maximum_speed(node); 110 if (plat->maximum_speed == USB_SPEED_UNKNOWN) { 111 pr_info("No USB maximum speed specified. Using super speed\n"); 112 plat->maximum_speed = USB_SPEED_SUPER; 113 } 114 115 plat->dr_mode = usb_get_dr_mode(node); 116 if (plat->dr_mode == USB_DR_MODE_UNKNOWN) { 117 pr_err("Invalid usb mode setup\n"); 118 return -ENODEV; 119 } else if (plat->dr_mode != USB_DR_MODE_HOST && 120 !strcmp(dev->driver->name, "dwc3-generic-host")) { 121 pr_info("Set dr_mode to HOST\n"); 122 plat->dr_mode = USB_DR_MODE_HOST; 123 } 124 125 return 0; 126 } 127 128 #if CONFIG_IS_ENABLED(DM_USB_GADGET) 129 int dm_usb_gadget_handle_interrupts(struct udevice *dev) 130 { 131 struct dwc3_generic_priv *priv = dev_get_priv(dev); 132 struct dwc3 *dwc3 = &priv->dwc3; 133 134 dwc3_gadget_uboot_handle_interrupt(dwc3); 135 136 return 0; 137 } 138 139 static int dwc3_generic_peripheral_probe(struct udevice *dev) 140 { 141 struct dwc3_generic_priv *priv = dev_get_priv(dev); 142 143 return dwc3_generic_probe(dev, priv); 144 } 145 146 static int dwc3_generic_peripheral_remove(struct udevice *dev) 147 { 148 struct dwc3_generic_priv *priv = dev_get_priv(dev); 149 150 return dwc3_generic_remove(dev, priv); 151 } 152 153 U_BOOT_DRIVER(dwc3_generic_peripheral) = { 154 .name = "dwc3-generic-peripheral", 155 .id = UCLASS_USB_GADGET_GENERIC, 156 .ofdata_to_platdata = dwc3_generic_ofdata_to_platdata, 157 .probe = dwc3_generic_peripheral_probe, 158 .remove = dwc3_generic_peripheral_remove, 159 .priv_auto_alloc_size = sizeof(struct dwc3_generic_priv), 160 .platdata_auto_alloc_size = sizeof(struct dwc3_generic_plat), 161 }; 162 #endif 163 164 #if defined(CONFIG_SPL_USB_HOST_SUPPORT) || !defined(CONFIG_SPL_BUILD) 165 static int dwc3_generic_host_probe(struct udevice *dev) 166 { 167 struct xhci_hcor *hcor; 168 struct xhci_hccr *hccr; 169 struct dwc3_generic_host_priv *priv = dev_get_priv(dev); 170 int rc; 171 172 rc = dwc3_generic_probe(dev, &priv->gen_priv); 173 if (rc) 174 return rc; 175 176 hccr = (struct xhci_hccr *)priv->gen_priv.base; 177 hcor = (struct xhci_hcor *)(priv->gen_priv.base + 178 HC_LENGTH(xhci_readl(&(hccr)->cr_capbase))); 179 180 return xhci_register(dev, hccr, hcor); 181 } 182 183 static int dwc3_generic_host_remove(struct udevice *dev) 184 { 185 struct dwc3_generic_host_priv *priv = dev_get_priv(dev); 186 int rc; 187 188 rc = xhci_deregister(dev); 189 if (rc) 190 return rc; 191 192 return dwc3_generic_remove(dev, &priv->gen_priv); 193 } 194 195 U_BOOT_DRIVER(dwc3_generic_host) = { 196 .name = "dwc3-generic-host", 197 .id = UCLASS_USB, 198 .ofdata_to_platdata = dwc3_generic_ofdata_to_platdata, 199 .probe = dwc3_generic_host_probe, 200 .remove = dwc3_generic_host_remove, 201 .priv_auto_alloc_size = sizeof(struct dwc3_generic_host_priv), 202 .platdata_auto_alloc_size = sizeof(struct dwc3_generic_plat), 203 .ops = &xhci_usb_ops, 204 .flags = DM_FLAG_ALLOC_PRIV_DMA, 205 }; 206 #endif 207 208 void dwc3_ti_glue_configure(struct udevice *dev, int index, 209 enum usb_dr_mode mode) 210 { 211 #define USBOTGSS_UTMI_OTG_STATUS 0x0084 212 #define USBOTGSS_UTMI_OTG_OFFSET 0x0480 213 214 /* UTMI_OTG_STATUS REGISTER */ 215 #define USBOTGSS_UTMI_OTG_STATUS_SW_MODE BIT(31) 216 #define USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT BIT(9) 217 #define USBOTGSS_UTMI_OTG_STATUS_TXBITSTUFFENABLE BIT(8) 218 #define USBOTGSS_UTMI_OTG_STATUS_IDDIG BIT(4) 219 #define USBOTGSS_UTMI_OTG_STATUS_SESSEND BIT(3) 220 #define USBOTGSS_UTMI_OTG_STATUS_SESSVALID BIT(2) 221 #define USBOTGSS_UTMI_OTG_STATUS_VBUSVALID BIT(1) 222 enum dwc3_omap_utmi_mode { 223 DWC3_OMAP_UTMI_MODE_UNKNOWN = 0, 224 DWC3_OMAP_UTMI_MODE_HW, 225 DWC3_OMAP_UTMI_MODE_SW, 226 }; 227 228 u32 use_id_pin; 229 u32 host_mode; 230 u32 reg; 231 u32 utmi_mode; 232 u32 utmi_status_offset = USBOTGSS_UTMI_OTG_STATUS; 233 234 struct dwc3_glue_data *glue = dev_get_platdata(dev); 235 void *base = map_physmem(glue->regs, 0x10000, MAP_NOCACHE); 236 237 if (device_is_compatible(dev, "ti,am437x-dwc3")) 238 utmi_status_offset += USBOTGSS_UTMI_OTG_OFFSET; 239 240 utmi_mode = dev_read_u32_default(dev, "utmi-mode", 241 DWC3_OMAP_UTMI_MODE_UNKNOWN); 242 if (utmi_mode != DWC3_OMAP_UTMI_MODE_HW) { 243 debug("%s: OTG is not supported. defaulting to PERIPHERAL\n", 244 dev->name); 245 mode = USB_DR_MODE_PERIPHERAL; 246 } 247 248 switch (mode) { 249 case USB_DR_MODE_PERIPHERAL: 250 use_id_pin = 0; 251 host_mode = 0; 252 break; 253 case USB_DR_MODE_HOST: 254 use_id_pin = 0; 255 host_mode = 1; 256 break; 257 case USB_DR_MODE_OTG: 258 default: 259 use_id_pin = 1; 260 host_mode = 0; 261 break; 262 } 263 264 reg = readl(base + utmi_status_offset); 265 266 reg &= ~(USBOTGSS_UTMI_OTG_STATUS_SW_MODE); 267 if (!use_id_pin) 268 reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE; 269 270 writel(reg, base + utmi_status_offset); 271 272 reg &= ~(USBOTGSS_UTMI_OTG_STATUS_SESSEND | 273 USBOTGSS_UTMI_OTG_STATUS_VBUSVALID | 274 USBOTGSS_UTMI_OTG_STATUS_IDDIG); 275 276 reg |= USBOTGSS_UTMI_OTG_STATUS_SESSVALID | 277 USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT; 278 279 if (!host_mode) 280 reg |= USBOTGSS_UTMI_OTG_STATUS_IDDIG | 281 USBOTGSS_UTMI_OTG_STATUS_VBUSVALID; 282 283 writel(reg, base + utmi_status_offset); 284 285 unmap_physmem(base, MAP_NOCACHE); 286 } 287 288 struct dwc3_glue_ops ti_ops = { 289 .glue_configure = dwc3_ti_glue_configure, 290 }; 291 292 static int dwc3_rk_glue_get_ctrl_dev(struct udevice *dev, ofnode *node) 293 { 294 *node = dev_ofnode(dev); 295 if (!ofnode_valid(*node)) 296 return -EINVAL; 297 298 return 0; 299 } 300 301 struct dwc3_glue_ops rk_ops = { 302 .glue_get_ctrl_dev = dwc3_rk_glue_get_ctrl_dev, 303 }; 304 305 static int dwc3_glue_bind_common(struct udevice *parent, ofnode node) 306 { 307 const char *name = ofnode_get_name(node); 308 const char *driver = NULL; 309 enum usb_dr_mode dr_mode; 310 struct udevice *dev; 311 int ret; 312 313 debug("%s: subnode name: %s\n", __func__, name); 314 315 /* if the parent node doesn't have a mode check the leaf */ 316 dr_mode = usb_get_dr_mode(dev_ofnode(parent)); 317 if (!dr_mode) 318 dr_mode = usb_get_dr_mode(node); 319 320 switch (dr_mode) { 321 case USB_DR_MODE_OTG: 322 #if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_USB_XHCI_HCD) 323 debug("%s: dr_mode: force to HOST\n", __func__); 324 driver = "dwc3-generic-host"; 325 break; 326 #endif 327 case USB_DR_MODE_PERIPHERAL: 328 #if CONFIG_IS_ENABLED(DM_USB_GADGET) 329 debug("%s: dr_mode: OTG or Peripheral\n", __func__); 330 driver = "dwc3-generic-peripheral"; 331 #endif 332 break; 333 #if defined(CONFIG_SPL_USB_HOST) || !defined(CONFIG_SPL_BUILD) 334 case USB_DR_MODE_HOST: 335 debug("%s: dr_mode: HOST\n", __func__); 336 driver = "dwc3-generic-host"; 337 break; 338 #endif 339 default: 340 debug("%s: unsupported dr_mode\n", __func__); 341 return -ENODEV; 342 }; 343 344 if (!driver) 345 return -ENXIO; 346 347 ret = device_bind_driver_to_node(parent, driver, name, 348 node, &dev); 349 if (ret) { 350 debug("%s: not able to bind usb device mode\n", 351 __func__); 352 return ret; 353 } 354 355 return 0; 356 } 357 358 int dwc3_glue_bind(struct udevice *parent) 359 { 360 struct dwc3_glue_ops *ops = (struct dwc3_glue_ops *)dev_get_driver_data(parent); 361 ofnode node; 362 int ret; 363 364 if (ops && ops->glue_get_ctrl_dev) { 365 ret = ops->glue_get_ctrl_dev(parent, &node); 366 if (ret) 367 return ret; 368 369 return dwc3_glue_bind_common(parent, node); 370 } 371 372 ofnode_for_each_subnode(node, dev_ofnode(parent)) { 373 ret = dwc3_glue_bind_common(parent, node); 374 if (ret == -ENXIO) 375 continue; 376 if (ret) 377 return ret; 378 } 379 380 return 0; 381 } 382 383 static int dwc3_glue_reset_init(struct udevice *dev, 384 struct dwc3_glue_data *glue) 385 { 386 int ret; 387 388 ret = reset_get_bulk(dev, &glue->resets); 389 if (ret == -ENOTSUPP || ret == -ENOENT) 390 return 0; 391 else if (ret) 392 return ret; 393 394 ret = reset_deassert_bulk(&glue->resets); 395 if (ret) { 396 reset_release_bulk(&glue->resets); 397 return ret; 398 } 399 400 return 0; 401 } 402 403 static int dwc3_glue_clk_init(struct udevice *dev, 404 struct dwc3_glue_data *glue) 405 { 406 int ret; 407 408 ret = clk_get_bulk(dev, &glue->clks); 409 if (ret == -ENOSYS || ret == -ENOENT) 410 return 0; 411 if (ret) 412 return ret; 413 414 #if CONFIG_IS_ENABLED(CLK) 415 ret = clk_enable_bulk(&glue->clks); 416 if (ret) { 417 clk_release_bulk(&glue->clks); 418 return ret; 419 } 420 #endif 421 422 return 0; 423 } 424 425 int dwc3_glue_probe(struct udevice *dev) 426 { 427 struct dwc3_glue_ops *ops = (struct dwc3_glue_ops *)dev_get_driver_data(dev); 428 struct dwc3_glue_data *glue = dev_get_platdata(dev); 429 struct udevice *child = NULL; 430 int index = 0; 431 int ret; 432 433 glue->regs = dev_read_addr(dev); 434 435 ret = dwc3_glue_clk_init(dev, glue); 436 if (ret) 437 return ret; 438 439 ret = dwc3_glue_reset_init(dev, glue); 440 if (ret) 441 return ret; 442 443 ret = device_find_first_child(dev, &child); 444 if (ret) 445 return ret; 446 447 if (glue->clks.count == 0) { 448 ret = dwc3_glue_clk_init(child, glue); 449 if (ret) 450 return ret; 451 } 452 453 if (glue->resets.count == 0) { 454 ret = dwc3_glue_reset_init(child, glue); 455 if (ret) 456 return ret; 457 } 458 459 while (child) { 460 enum usb_dr_mode dr_mode; 461 462 dr_mode = usb_get_dr_mode(child->node); 463 device_find_next_child(&child); 464 if (ops && ops->glue_configure) 465 ops->glue_configure(dev, index, dr_mode); 466 index++; 467 } 468 469 return 0; 470 } 471 472 int dwc3_glue_remove(struct udevice *dev) 473 { 474 struct dwc3_glue_data *glue = dev_get_platdata(dev); 475 476 reset_release_bulk(&glue->resets); 477 478 clk_release_bulk(&glue->clks); 479 480 return 0; 481 } 482 483 static const struct udevice_id dwc3_glue_ids[] = { 484 { .compatible = "xlnx,zynqmp-dwc3" }, 485 { .compatible = "ti,keystone-dwc3"}, 486 { .compatible = "ti,dwc3", .data = (ulong)&ti_ops }, 487 { .compatible = "ti,am437x-dwc3", .data = (ulong)&ti_ops }, 488 { .compatible = "rockchip,rk3328-dwc3" }, 489 { .compatible = "rockchip,rk3399-dwc3" }, 490 { .compatible = "rockchip,rk3576-dwc3", .data = (ulong)&rk_ops }, 491 { } 492 }; 493 494 U_BOOT_DRIVER(dwc3_generic_wrapper) = { 495 .name = "dwc3-generic-wrapper", 496 .id = UCLASS_NOP, 497 .of_match = dwc3_glue_ids, 498 .bind = dwc3_glue_bind, 499 .probe = dwc3_glue_probe, 500 .remove = dwc3_glue_remove, 501 .platdata_auto_alloc_size = sizeof(struct dwc3_glue_data), 502 503 }; 504