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