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