1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Cadence USBSS DRD Driver. 4 * 5 * Copyright (C) 2018-2019 Cadence. 6 * Copyright (C) 2017-2018 NXP 7 * Copyright (C) 2019 Texas Instruments 8 * 9 * Author: Peter Chen <peter.chen@nxp.com> 10 * Pawel Laszczak <pawell@cadence.com> 11 * Roger Quadros <rogerq@ti.com> 12 */ 13 14 #include <common.h> 15 #include <dm.h> 16 #include <dm/device-internal.h> 17 #include <dm/lists.h> 18 #include <linux/kernel.h> 19 #include <linux/io.h> 20 #include <usb.h> 21 #include <usb/xhci.h> 22 23 #include "core.h" 24 #include "host-export.h" 25 #include "gadget-export.h" 26 #include "drd.h" 27 28 static int cdns3_idle_init(struct cdns3 *cdns); 29 30 struct cdns3_host_priv { 31 struct xhci_ctrl xhci_ctrl; 32 struct cdns3 cdns; 33 }; 34 35 struct cdns3_gadget_priv { 36 struct cdns3 cdns; 37 }; 38 39 static inline 40 struct cdns3_role_driver *cdns3_get_current_role_driver(struct cdns3 *cdns) 41 { 42 WARN_ON(!cdns->roles[cdns->role]); 43 return cdns->roles[cdns->role]; 44 } 45 46 static int cdns3_role_start(struct cdns3 *cdns, enum usb_role role) 47 { 48 int ret; 49 50 if (WARN_ON(role > USB_ROLE_DEVICE)) 51 return 0; 52 53 mutex_lock(&cdns->mutex); 54 cdns->role = role; 55 mutex_unlock(&cdns->mutex); 56 57 if (!cdns->roles[role]) 58 return -ENXIO; 59 60 if (cdns->roles[role]->state == CDNS3_ROLE_STATE_ACTIVE) 61 return 0; 62 63 mutex_lock(&cdns->mutex); 64 ret = cdns->roles[role]->start(cdns); 65 if (!ret) 66 cdns->roles[role]->state = CDNS3_ROLE_STATE_ACTIVE; 67 mutex_unlock(&cdns->mutex); 68 69 return ret; 70 } 71 72 static void cdns3_role_stop(struct cdns3 *cdns) 73 { 74 enum usb_role role = cdns->role; 75 76 if (WARN_ON(role > USB_ROLE_DEVICE)) 77 return; 78 79 if (cdns->roles[role]->state == CDNS3_ROLE_STATE_INACTIVE) 80 return; 81 82 mutex_lock(&cdns->mutex); 83 cdns->roles[role]->stop(cdns); 84 cdns->roles[role]->state = CDNS3_ROLE_STATE_INACTIVE; 85 mutex_unlock(&cdns->mutex); 86 } 87 88 static void cdns3_exit_roles(struct cdns3 *cdns) 89 { 90 cdns3_role_stop(cdns); 91 cdns3_drd_exit(cdns); 92 } 93 94 static enum usb_role cdsn3_hw_role_state_machine(struct cdns3 *cdns); 95 96 /** 97 * cdns3_core_init_role - initialize role of operation 98 * @cdns: Pointer to cdns3 structure 99 * 100 * Returns 0 on success otherwise negative errno 101 */ 102 static int cdns3_core_init_role(struct cdns3 *cdns) 103 { 104 struct udevice *dev = cdns->dev; 105 enum usb_dr_mode best_dr_mode; 106 enum usb_dr_mode dr_mode; 107 int ret = 0; 108 109 dr_mode = usb_get_dr_mode(dev_of_offset(dev)); 110 cdns->role = USB_ROLE_NONE; 111 112 /* 113 * If driver can't read mode by means of usb_get_dr_mode function then 114 * chooses mode according with Kernel configuration. This setting 115 * can be restricted later depending on strap pin configuration. 116 */ 117 if (dr_mode == USB_DR_MODE_UNKNOWN) { 118 if (IS_ENABLED(CONFIG_USB_CDNS3_HOST) && 119 IS_ENABLED(CONFIG_USB_CDNS3_GADGET)) 120 dr_mode = USB_DR_MODE_OTG; 121 else if (IS_ENABLED(CONFIG_USB_CDNS3_HOST)) 122 dr_mode = USB_DR_MODE_HOST; 123 else if (IS_ENABLED(CONFIG_USB_CDNS3_GADGET)) 124 dr_mode = USB_DR_MODE_PERIPHERAL; 125 } 126 127 /* 128 * At this point cdns->dr_mode contains strap configuration. 129 * Driver try update this setting considering kernel configuration 130 */ 131 best_dr_mode = cdns->dr_mode; 132 133 ret = cdns3_idle_init(cdns); 134 if (ret) 135 return ret; 136 137 if (dr_mode == USB_DR_MODE_OTG) { 138 best_dr_mode = cdns->dr_mode; 139 } else if (cdns->dr_mode == USB_DR_MODE_OTG) { 140 best_dr_mode = dr_mode; 141 } else if (cdns->dr_mode != dr_mode) { 142 dev_err(dev, "Incorrect DRD configuration\n"); 143 return -EINVAL; 144 } 145 146 dr_mode = best_dr_mode; 147 148 #if defined(CONFIG_SPL_USB_HOST_SUPPORT) || !defined(CONFIG_SPL_BUILD) 149 if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_HOST) { 150 ret = cdns3_host_init(cdns); 151 if (ret) { 152 dev_err(dev, "Host initialization failed with %d\n", 153 ret); 154 goto err; 155 } 156 } 157 #endif 158 159 #if CONFIG_IS_ENABLED(DM_USB_GADGET) 160 if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_PERIPHERAL) { 161 ret = cdns3_gadget_init(cdns); 162 if (ret) { 163 dev_err(dev, "Device initialization failed with %d\n", 164 ret); 165 goto err; 166 } 167 } 168 #endif 169 170 cdns->dr_mode = dr_mode; 171 172 ret = cdns3_drd_update_mode(cdns); 173 if (ret) 174 goto err; 175 176 if (cdns->dr_mode != USB_DR_MODE_OTG) { 177 ret = cdns3_hw_role_switch(cdns); 178 if (ret) 179 goto err; 180 } 181 182 return ret; 183 err: 184 cdns3_exit_roles(cdns); 185 return ret; 186 } 187 188 /** 189 * cdsn3_hw_role_state_machine - role switch state machine based on hw events 190 * @cdns: Pointer to controller structure. 191 * 192 * Returns next role to be entered based on hw events. 193 */ 194 static enum usb_role cdsn3_hw_role_state_machine(struct cdns3 *cdns) 195 { 196 enum usb_role role; 197 int id, vbus; 198 199 if (cdns->dr_mode != USB_DR_MODE_OTG) 200 goto not_otg; 201 202 id = cdns3_get_id(cdns); 203 vbus = cdns3_get_vbus(cdns); 204 205 /* 206 * Role change state machine 207 * Inputs: ID, VBUS 208 * Previous state: cdns->role 209 * Next state: role 210 */ 211 role = cdns->role; 212 213 switch (role) { 214 case USB_ROLE_NONE: 215 /* 216 * Driver treats USB_ROLE_NONE synonymous to IDLE state from 217 * controller specification. 218 */ 219 if (!id) 220 role = USB_ROLE_HOST; 221 else if (vbus) 222 role = USB_ROLE_DEVICE; 223 break; 224 case USB_ROLE_HOST: /* from HOST, we can only change to NONE */ 225 if (id) 226 role = USB_ROLE_NONE; 227 break; 228 case USB_ROLE_DEVICE: /* from GADGET, we can only change to NONE*/ 229 if (!vbus) 230 role = USB_ROLE_NONE; 231 break; 232 } 233 234 dev_dbg(cdns->dev, "role %d -> %d\n", cdns->role, role); 235 236 return role; 237 238 not_otg: 239 if (cdns3_is_host(cdns)) 240 role = USB_ROLE_HOST; 241 if (cdns3_is_device(cdns)) 242 role = USB_ROLE_DEVICE; 243 244 return role; 245 } 246 247 static int cdns3_idle_role_start(struct cdns3 *cdns) 248 { 249 return 0; 250 } 251 252 static void cdns3_idle_role_stop(struct cdns3 *cdns) 253 { 254 /* Program Lane swap and bring PHY out of RESET */ 255 generic_phy_reset(&cdns->usb3_phy); 256 } 257 258 static int cdns3_idle_init(struct cdns3 *cdns) 259 { 260 struct cdns3_role_driver *rdrv; 261 262 rdrv = devm_kzalloc(cdns->dev, sizeof(*rdrv), GFP_KERNEL); 263 if (!rdrv) 264 return -ENOMEM; 265 266 rdrv->start = cdns3_idle_role_start; 267 rdrv->stop = cdns3_idle_role_stop; 268 rdrv->state = CDNS3_ROLE_STATE_INACTIVE; 269 rdrv->suspend = NULL; 270 rdrv->resume = NULL; 271 rdrv->name = "idle"; 272 273 cdns->roles[USB_ROLE_NONE] = rdrv; 274 275 return 0; 276 } 277 278 /** 279 * cdns3_hw_role_switch - switch roles based on HW state 280 * @cdns3: controller 281 */ 282 int cdns3_hw_role_switch(struct cdns3 *cdns) 283 { 284 enum usb_role real_role, current_role; 285 int ret = 0; 286 287 /* Do nothing if role based on syfs. */ 288 if (cdns->role_override) 289 return 0; 290 291 current_role = cdns->role; 292 real_role = cdsn3_hw_role_state_machine(cdns); 293 294 /* Do nothing if nothing changed */ 295 if (current_role == real_role) 296 goto exit; 297 298 cdns3_role_stop(cdns); 299 300 dev_dbg(cdns->dev, "Switching role %d -> %d", current_role, real_role); 301 302 ret = cdns3_role_start(cdns, real_role); 303 if (ret) { 304 /* Back to current role */ 305 dev_err(cdns->dev, "set %d has failed, back to %d\n", 306 real_role, current_role); 307 ret = cdns3_role_start(cdns, current_role); 308 if (ret) 309 dev_err(cdns->dev, "back to %d failed too\n", 310 current_role); 311 } 312 exit: 313 return ret; 314 } 315 316 static int cdns3_probe(struct cdns3 *cdns) 317 { 318 struct udevice *dev = cdns->dev; 319 int ret; 320 321 cdns->xhci_regs = dev_remap_addr_name(dev, "xhci"); 322 if (!cdns->xhci_regs) 323 return -EINVAL; 324 325 cdns->dev_regs = dev_remap_addr_name(dev, "dev"); 326 if (!cdns->dev_regs) 327 return -EINVAL; 328 329 mutex_init(&cdns->mutex); 330 331 ret = generic_phy_get_by_name(dev, "cdns3,usb2-phy", &cdns->usb2_phy); 332 if (ret) 333 dev_warn(dev, "Unable to get USB2 phy (ret %d)\n", ret); 334 335 ret = generic_phy_init(&cdns->usb2_phy); 336 if (ret) 337 return ret; 338 339 ret = generic_phy_get_by_name(dev, "cdns3,usb3-phy", &cdns->usb3_phy); 340 if (ret) 341 dev_warn(dev, "Unable to get USB3 phy (ret %d)\n", ret); 342 343 ret = generic_phy_init(&cdns->usb3_phy); 344 if (ret) 345 return ret; 346 347 ret = generic_phy_power_on(&cdns->usb2_phy); 348 if (ret) 349 return ret; 350 351 ret = generic_phy_power_on(&cdns->usb3_phy); 352 if (ret) 353 return ret; 354 355 ret = cdns3_drd_init(cdns); 356 if (ret) 357 return ret; 358 359 ret = cdns3_core_init_role(cdns); 360 if (ret) 361 return ret; 362 363 dev_dbg(dev, "Cadence USB3 core: probe succeed\n"); 364 365 return 0; 366 } 367 368 static int cdns3_remove(struct cdns3 *cdns) 369 { 370 cdns3_exit_roles(cdns); 371 generic_phy_power_off(&cdns->usb2_phy); 372 generic_phy_power_off(&cdns->usb3_phy); 373 generic_phy_exit(&cdns->usb2_phy); 374 generic_phy_exit(&cdns->usb3_phy); 375 return 0; 376 } 377 378 static const struct udevice_id cdns3_ids[] = { 379 { .compatible = "cdns,usb3" }, 380 { }, 381 }; 382 383 int cdns3_bind(struct udevice *parent) 384 { 385 int from = dev_of_offset(parent); 386 const void *fdt = gd->fdt_blob; 387 enum usb_dr_mode dr_mode; 388 struct udevice *dev; 389 const char *driver; 390 const char *name; 391 int node; 392 int ret; 393 394 node = fdt_node_offset_by_compatible(fdt, from, "cdns,usb3"); 395 if (node < 0) { 396 ret = -ENODEV; 397 goto fail; 398 } 399 400 name = fdt_get_name(fdt, node, NULL); 401 dr_mode = usb_get_dr_mode(node); 402 403 switch (dr_mode) { 404 #if defined(CONFIG_SPL_USB_HOST_SUPPORT) || \ 405 (!defined(CONFIG_SPL_BUILD) && defined(CONFIG_USB_HOST)) 406 case USB_DR_MODE_HOST: 407 debug("%s: dr_mode: HOST\n", __func__); 408 driver = "cdns-usb3-host"; 409 break; 410 #endif 411 #if CONFIG_IS_ENABLED(DM_USB_GADGET) 412 case USB_DR_MODE_PERIPHERAL: 413 debug("%s: dr_mode: PERIPHERAL\n", __func__); 414 driver = "cdns-usb3-peripheral"; 415 break; 416 #endif 417 default: 418 printf("%s: unsupported dr_mode\n", __func__); 419 ret = -ENODEV; 420 goto fail; 421 }; 422 423 ret = device_bind_driver_to_node(parent, driver, name, 424 offset_to_ofnode(node), &dev); 425 if (ret) { 426 printf("%s: not able to bind usb device mode\n", 427 __func__); 428 goto fail; 429 } 430 431 return 0; 432 433 fail: 434 /* do not return an error: failing to bind would hang the board */ 435 return 0; 436 } 437 438 #if CONFIG_IS_ENABLED(DM_USB_GADGET) 439 static int cdns3_gadget_probe(struct udevice *dev) 440 { 441 struct cdns3_gadget_priv *priv = dev_get_priv(dev); 442 struct cdns3 *cdns = &priv->cdns; 443 444 cdns->dev = dev; 445 446 return cdns3_probe(cdns); 447 } 448 449 static int cdns3_gadget_remove(struct udevice *dev) 450 { 451 struct cdns3_gadget_priv *priv = dev_get_priv(dev); 452 struct cdns3 *cdns = &priv->cdns; 453 454 return cdns3_remove(cdns); 455 } 456 457 U_BOOT_DRIVER(cdns_usb3_peripheral) = { 458 .name = "cdns-usb3-peripheral", 459 .id = UCLASS_USB_GADGET_GENERIC, 460 .of_match = cdns3_ids, 461 .probe = cdns3_gadget_probe, 462 .remove = cdns3_gadget_remove, 463 .priv_auto_alloc_size = sizeof(struct cdns3_gadget_priv), 464 .flags = DM_FLAG_ALLOC_PRIV_DMA, 465 }; 466 #endif 467 468 #if defined(CONFIG_SPL_USB_HOST_SUPPORT) || \ 469 (!defined(CONFIG_SPL_BUILD) && defined(CONFIG_USB_HOST)) 470 static int cdns3_host_probe(struct udevice *dev) 471 { 472 struct cdns3_host_priv *priv = dev_get_priv(dev); 473 struct cdns3 *cdns = &priv->cdns; 474 475 cdns->dev = dev; 476 477 return cdns3_probe(cdns); 478 } 479 480 static int cdns3_host_remove(struct udevice *dev) 481 { 482 struct cdns3_host_priv *priv = dev_get_priv(dev); 483 struct cdns3 *cdns = &priv->cdns; 484 485 return cdns3_remove(cdns); 486 } 487 488 U_BOOT_DRIVER(cdns_usb3_host) = { 489 .name = "cdns-usb3-host", 490 .id = UCLASS_USB, 491 .of_match = cdns3_ids, 492 .probe = cdns3_host_probe, 493 .remove = cdns3_host_remove, 494 .priv_auto_alloc_size = sizeof(struct cdns3_host_priv), 495 .ops = &xhci_usb_ops, 496 .flags = DM_FLAG_ALLOC_PRIV_DMA, 497 }; 498 #endif 499