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 void (*select_dr_mode)(struct udevice *dev, int index, 214 enum usb_dr_mode mode); 215 }; 216 217 void dwc3_ti_select_dr_mode(struct udevice *dev, int index, 218 enum usb_dr_mode mode) 219 { 220 #define USBOTGSS_UTMI_OTG_STATUS 0x0084 221 #define USBOTGSS_UTMI_OTG_OFFSET 0x0480 222 223 /* UTMI_OTG_STATUS REGISTER */ 224 #define USBOTGSS_UTMI_OTG_STATUS_SW_MODE BIT(31) 225 #define USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT BIT(9) 226 #define USBOTGSS_UTMI_OTG_STATUS_TXBITSTUFFENABLE BIT(8) 227 #define USBOTGSS_UTMI_OTG_STATUS_IDDIG BIT(4) 228 #define USBOTGSS_UTMI_OTG_STATUS_SESSEND BIT(3) 229 #define USBOTGSS_UTMI_OTG_STATUS_SESSVALID BIT(2) 230 #define USBOTGSS_UTMI_OTG_STATUS_VBUSVALID BIT(1) 231 enum dwc3_omap_utmi_mode { 232 DWC3_OMAP_UTMI_MODE_UNKNOWN = 0, 233 DWC3_OMAP_UTMI_MODE_HW, 234 DWC3_OMAP_UTMI_MODE_SW, 235 }; 236 237 u32 use_id_pin; 238 u32 host_mode; 239 u32 reg; 240 u32 utmi_mode; 241 u32 utmi_status_offset = USBOTGSS_UTMI_OTG_STATUS; 242 243 struct dwc3_glue_data *glue = dev_get_platdata(dev); 244 void *base = map_physmem(glue->regs, 0x10000, MAP_NOCACHE); 245 246 if (device_is_compatible(dev, "ti,am437x-dwc3")) 247 utmi_status_offset += USBOTGSS_UTMI_OTG_OFFSET; 248 249 utmi_mode = dev_read_u32_default(dev, "utmi-mode", 250 DWC3_OMAP_UTMI_MODE_UNKNOWN); 251 if (utmi_mode != DWC3_OMAP_UTMI_MODE_HW) { 252 debug("%s: OTG is not supported. defaulting to PERIPHERAL\n", 253 dev->name); 254 mode = USB_DR_MODE_PERIPHERAL; 255 } 256 257 switch (mode) { 258 case USB_DR_MODE_PERIPHERAL: 259 use_id_pin = 0; 260 host_mode = 0; 261 break; 262 case USB_DR_MODE_HOST: 263 use_id_pin = 0; 264 host_mode = 1; 265 break; 266 case USB_DR_MODE_OTG: 267 default: 268 use_id_pin = 1; 269 host_mode = 0; 270 break; 271 } 272 273 reg = readl(base + utmi_status_offset); 274 275 reg &= ~(USBOTGSS_UTMI_OTG_STATUS_SW_MODE); 276 if (!use_id_pin) 277 reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE; 278 279 writel(reg, base + utmi_status_offset); 280 281 reg &= ~(USBOTGSS_UTMI_OTG_STATUS_SESSEND | 282 USBOTGSS_UTMI_OTG_STATUS_VBUSVALID | 283 USBOTGSS_UTMI_OTG_STATUS_IDDIG); 284 285 reg |= USBOTGSS_UTMI_OTG_STATUS_SESSVALID | 286 USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT; 287 288 if (!host_mode) 289 reg |= USBOTGSS_UTMI_OTG_STATUS_IDDIG | 290 USBOTGSS_UTMI_OTG_STATUS_VBUSVALID; 291 292 writel(reg, base + utmi_status_offset); 293 294 unmap_physmem(base, MAP_NOCACHE); 295 } 296 297 struct dwc3_glue_ops ti_ops = { 298 .select_dr_mode = dwc3_ti_select_dr_mode, 299 }; 300 301 static int dwc3_glue_bind(struct udevice *parent) 302 { 303 ofnode node; 304 int ret; 305 306 ofnode_for_each_subnode(node, parent->node) { 307 const char *name = ofnode_get_name(node); 308 enum usb_dr_mode dr_mode; 309 struct udevice *dev; 310 const char *driver = NULL; 311 312 debug("%s: subnode name: %s\n", __func__, name); 313 314 dr_mode = usb_get_dr_mode(node); 315 316 switch (dr_mode) { 317 case USB_DR_MODE_OTG: 318 #if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_USB_XHCI_HCD) 319 debug("%s: dr_mode: force to HOST\n", __func__); 320 driver = "dwc3-generic-host"; 321 break; 322 #endif 323 case USB_DR_MODE_PERIPHERAL: 324 #if CONFIG_IS_ENABLED(DM_USB_GADGET) 325 debug("%s: dr_mode: OTG or Peripheral\n", __func__); 326 driver = "dwc3-generic-peripheral"; 327 #endif 328 break; 329 #if defined(CONFIG_SPL_USB_HOST_SUPPORT) || !defined(CONFIG_SPL_BUILD) 330 case USB_DR_MODE_HOST: 331 debug("%s: dr_mode: HOST\n", __func__); 332 driver = "dwc3-generic-host"; 333 break; 334 #endif 335 default: 336 debug("%s: unsupported dr_mode\n", __func__); 337 return -ENODEV; 338 }; 339 340 if (!driver) 341 continue; 342 343 ret = device_bind_driver_to_node(parent, driver, name, 344 node, &dev); 345 if (ret) { 346 debug("%s: not able to bind usb device mode\n", 347 __func__); 348 return ret; 349 } 350 } 351 352 return 0; 353 } 354 355 static int dwc3_glue_reset_init(struct udevice *dev, 356 struct dwc3_glue_data *glue) 357 { 358 int ret; 359 360 ret = reset_get_bulk(dev, &glue->resets); 361 if (ret == -ENOTSUPP || ret == -ENOENT) 362 return 0; 363 else if (ret) 364 return ret; 365 366 ret = reset_deassert_bulk(&glue->resets); 367 if (ret) { 368 reset_release_bulk(&glue->resets); 369 return ret; 370 } 371 372 return 0; 373 } 374 375 static int dwc3_glue_clk_init(struct udevice *dev, 376 struct dwc3_glue_data *glue) 377 { 378 int ret; 379 380 ret = clk_get_bulk(dev, &glue->clks); 381 if (ret == -ENOSYS || ret == -ENOENT) 382 return 0; 383 if (ret) 384 return ret; 385 386 #if CONFIG_IS_ENABLED(CLK) 387 ret = clk_enable_bulk(&glue->clks); 388 if (ret) { 389 clk_release_bulk(&glue->clks); 390 return ret; 391 } 392 #endif 393 394 return 0; 395 } 396 397 static int dwc3_glue_probe(struct udevice *dev) 398 { 399 struct dwc3_glue_ops *ops = (struct dwc3_glue_ops *)dev_get_driver_data(dev); 400 struct dwc3_glue_data *glue = dev_get_platdata(dev); 401 struct udevice *child = NULL; 402 int index = 0; 403 int ret; 404 405 glue->regs = dev_read_addr(dev); 406 407 ret = dwc3_glue_clk_init(dev, glue); 408 if (ret) 409 return ret; 410 411 ret = dwc3_glue_reset_init(dev, glue); 412 if (ret) 413 return ret; 414 415 ret = device_find_first_child(dev, &child); 416 if (ret) 417 return ret; 418 419 if (glue->resets.count < 1) { 420 ret = dwc3_glue_reset_init(child, glue); 421 if (ret) 422 return ret; 423 } 424 425 while (child) { 426 enum usb_dr_mode dr_mode; 427 428 dr_mode = usb_get_dr_mode(child->node); 429 device_find_next_child(&child); 430 if (ops && ops->select_dr_mode) 431 ops->select_dr_mode(dev, index, dr_mode); 432 index++; 433 } 434 435 return 0; 436 } 437 438 static int dwc3_glue_remove(struct udevice *dev) 439 { 440 struct dwc3_glue_data *glue = dev_get_platdata(dev); 441 442 reset_release_bulk(&glue->resets); 443 444 clk_release_bulk(&glue->clks); 445 446 return 0; 447 } 448 449 static const struct udevice_id dwc3_glue_ids[] = { 450 { .compatible = "xlnx,zynqmp-dwc3" }, 451 { .compatible = "ti,keystone-dwc3"}, 452 { .compatible = "ti,dwc3", .data = (ulong)&ti_ops }, 453 { .compatible = "ti,am437x-dwc3", .data = (ulong)&ti_ops }, 454 { .compatible = "rockchip,rk3328-dwc3" }, 455 { .compatible = "rockchip,rk3399-dwc3" }, 456 { } 457 }; 458 459 U_BOOT_DRIVER(dwc3_generic_wrapper) = { 460 .name = "dwc3-generic-wrapper", 461 .id = UCLASS_NOP, 462 .of_match = dwc3_glue_ids, 463 .bind = dwc3_glue_bind, 464 .probe = dwc3_glue_probe, 465 .remove = dwc3_glue_remove, 466 .platdata_auto_alloc_size = sizeof(struct dwc3_glue_data), 467 468 }; 469