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