1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2019 Emmanuel Vadot <manu@FreeBSD.Org> 5 * Copyright (c) 2021-2022 Bjoern A. Zeeb <bz@FreeBSD.ORG> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include "opt_platform.h" 30 #include "opt_acpi.h" 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/bus.h> 35 #include <sys/rman.h> 36 #include <sys/condvar.h> 37 #include <sys/kernel.h> 38 #include <sys/module.h> 39 #include <sys/mutex.h> 40 #ifdef FDT 41 #include <sys/gpio.h> 42 #endif 43 44 #include <machine/bus.h> 45 46 #include <dev/usb/usb.h> 47 #include <dev/usb/usbdi.h> 48 49 #include <dev/usb/usb_core.h> 50 #include <dev/usb/usb_busdma.h> 51 #include <dev/usb/usb_process.h> 52 53 #include <dev/usb/usb_controller.h> 54 #include <dev/usb/usb_bus.h> 55 #include <dev/usb/controller/generic_xhci.h> 56 #include <dev/usb/controller/xhci.h> 57 #include <dev/usb/controller/dwc3/dwc3.h> 58 59 #ifdef FDT 60 #include <dev/fdt/simplebus.h> 61 62 #include <dev/fdt/fdt_common.h> 63 #include <dev/ofw/ofw_bus.h> 64 #include <dev/ofw/ofw_bus_subr.h> 65 #include <dev/ofw/ofw_subr.h> 66 67 #include <dev/clk/clk.h> 68 #include <dev/phy/phy_usb.h> 69 #endif 70 71 #ifdef DEV_ACPI 72 #include <contrib/dev/acpica/include/acpi.h> 73 #include <contrib/dev/acpica/include/accommon.h> 74 #include <dev/acpica/acpivar.h> 75 #endif 76 77 struct snps_dwc3_softc { 78 struct xhci_softc sc; 79 device_t dev; 80 struct resource * mem_res; 81 bus_space_tag_t bst; 82 bus_space_handle_t bsh; 83 uint32_t snpsid; 84 uint32_t snpsversion; 85 uint32_t snpsrevision; 86 uint32_t snpsversion_type; 87 #ifdef FDT 88 clk_t clk_ref; 89 clk_t clk_suspend; 90 clk_t clk_bus; 91 #endif 92 }; 93 94 #define DWC3_WRITE(_sc, _off, _val) \ 95 bus_space_write_4(_sc->bst, _sc->bsh, _off, _val) 96 #define DWC3_READ(_sc, _off) \ 97 bus_space_read_4(_sc->bst, _sc->bsh, _off) 98 99 #define IS_DMA_32B 1 100 101 static void 102 xhci_interrupt_poll(void *_sc) 103 { 104 struct xhci_softc *sc = _sc; 105 106 USB_BUS_UNLOCK(&sc->sc_bus); 107 xhci_interrupt(sc); 108 USB_BUS_LOCK(&sc->sc_bus); 109 usb_callout_reset(&sc->sc_callout, 1, (void *)&xhci_interrupt_poll, sc); 110 } 111 112 static int 113 snps_dwc3_attach_xhci(device_t dev) 114 { 115 struct snps_dwc3_softc *snps_sc = device_get_softc(dev); 116 struct xhci_softc *sc = &snps_sc->sc; 117 int err = 0, rid = 0; 118 119 sc->sc_io_res = snps_sc->mem_res; 120 sc->sc_io_tag = snps_sc->bst; 121 sc->sc_io_hdl = snps_sc->bsh; 122 sc->sc_io_size = rman_get_size(snps_sc->mem_res); 123 124 sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 125 RF_SHAREABLE | RF_ACTIVE); 126 if (sc->sc_irq_res == NULL) { 127 device_printf(dev, "Failed to allocate IRQ\n"); 128 return (ENXIO); 129 } 130 131 sc->sc_bus.bdev = device_add_child(dev, "usbus", DEVICE_UNIT_ANY); 132 if (sc->sc_bus.bdev == NULL) { 133 device_printf(dev, "Failed to add USB device\n"); 134 return (ENXIO); 135 } 136 137 device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); 138 139 sprintf(sc->sc_vendor, "Synopsys"); 140 device_set_desc(sc->sc_bus.bdev, "Synopsys"); 141 142 if (xhci_use_polling() == 0) { 143 err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 144 NULL, (driver_intr_t *)xhci_interrupt, sc, &sc->sc_intr_hdl); 145 if (err != 0) { 146 device_printf(dev, "Failed to setup IRQ, %d\n", err); 147 sc->sc_intr_hdl = NULL; 148 return (err); 149 } 150 } 151 152 err = xhci_init(sc, dev, IS_DMA_32B); 153 if (err != 0) { 154 device_printf(dev, "Failed to init XHCI, with error %d\n", err); 155 return (ENXIO); 156 } 157 158 usb_callout_init_mtx(&sc->sc_callout, &sc->sc_bus.bus_mtx, 0); 159 160 if (xhci_use_polling() != 0) { 161 device_printf(dev, "Interrupt polling at %dHz\n", hz); 162 USB_BUS_LOCK(&sc->sc_bus); 163 xhci_interrupt_poll(sc); 164 USB_BUS_UNLOCK(&sc->sc_bus); 165 } 166 167 err = xhci_start_controller(sc); 168 if (err != 0) { 169 device_printf(dev, "Failed to start XHCI controller, with error %d\n", err); 170 return (ENXIO); 171 } 172 173 device_printf(sc->sc_bus.bdev, "trying to attach\n"); 174 err = device_probe_and_attach(sc->sc_bus.bdev); 175 if (err != 0) { 176 device_printf(dev, "Failed to initialize USB, with error %d\n", err); 177 return (ENXIO); 178 } 179 180 return (0); 181 } 182 183 #ifdef DWC3_DEBUG 184 static void 185 snsp_dwc3_dump_regs(struct snps_dwc3_softc *sc, const char *msg) 186 { 187 struct xhci_softc *xsc; 188 uint32_t reg; 189 190 if (!bootverbose) 191 return; 192 193 device_printf(sc->dev, "%s: %s:\n", __func__, msg ? msg : ""); 194 195 reg = DWC3_READ(sc, DWC3_GCTL); 196 device_printf(sc->dev, "GCTL: %#012x\n", reg); 197 reg = DWC3_READ(sc, DWC3_GUCTL); 198 device_printf(sc->dev, "GUCTL: %#012x\n", reg); 199 reg = DWC3_READ(sc, DWC3_GUCTL1); 200 device_printf(sc->dev, "GUCTL1: %#012x\n", reg); 201 reg = DWC3_READ(sc, DWC3_GUSB2PHYCFG0); 202 device_printf(sc->dev, "GUSB2PHYCFG0: %#012x\n", reg); 203 reg = DWC3_READ(sc, DWC3_GUSB3PIPECTL0); 204 device_printf(sc->dev, "GUSB3PIPECTL0: %#012x\n", reg); 205 reg = DWC3_READ(sc, DWC3_DCFG); 206 device_printf(sc->dev, "DCFG: %#012x\n", reg); 207 208 xsc = &sc->sc; 209 device_printf(sc->dev, "xhci quirks: %#012x\n", xsc->sc_quirks); 210 } 211 212 static void 213 snps_dwc3_dump_ctrlparams(struct snps_dwc3_softc *sc) 214 { 215 const bus_size_t offs[] = { 216 DWC3_GHWPARAMS0, DWC3_GHWPARAMS1, DWC3_GHWPARAMS2, DWC3_GHWPARAMS3, 217 DWC3_GHWPARAMS4, DWC3_GHWPARAMS5, DWC3_GHWPARAMS6, DWC3_GHWPARAMS7, 218 DWC3_GHWPARAMS8, 219 }; 220 uint32_t reg; 221 int i; 222 223 for (i = 0; i < nitems(offs); i++) { 224 reg = DWC3_READ(sc, offs[i]); 225 if (bootverbose) 226 device_printf(sc->dev, "hwparams[%d]: %#012x\n", i, reg); 227 } 228 } 229 #endif 230 231 static void 232 snps_dwc3_reset(struct snps_dwc3_softc *sc) 233 { 234 uint32_t gctl, ghwp0, phy2, phy3; 235 236 ghwp0 = DWC3_READ(sc, DWC3_GHWPARAMS0); 237 238 gctl = DWC3_READ(sc, DWC3_GCTL); 239 gctl |= DWC3_GCTL_CORESOFTRESET; 240 DWC3_WRITE(sc, DWC3_GCTL, gctl); 241 242 phy2 = DWC3_READ(sc, DWC3_GUSB2PHYCFG0); 243 phy2 |= DWC3_GUSB2PHYCFG0_PHYSOFTRST; 244 if ((ghwp0 & DWC3_GHWPARAMS0_MODE_MASK) == 245 DWC3_GHWPARAMS0_MODE_DUALROLEDEVICE) 246 phy2 &= ~DWC3_GUSB2PHYCFG0_SUSPENDUSB20; 247 DWC3_WRITE(sc, DWC3_GUSB2PHYCFG0, phy2); 248 249 phy3 = DWC3_READ(sc, DWC3_GUSB3PIPECTL0); 250 phy3 |= DWC3_GUSB3PIPECTL0_PHYSOFTRST; 251 if ((ghwp0 & DWC3_GHWPARAMS0_MODE_MASK) == 252 DWC3_GHWPARAMS0_MODE_DUALROLEDEVICE) 253 phy3 &= ~DWC3_GUSB3PIPECTL0_SUSPENDUSB3; 254 DWC3_WRITE(sc, DWC3_GUSB3PIPECTL0, phy3); 255 256 DELAY(1000); 257 258 phy2 &= ~DWC3_GUSB2PHYCFG0_PHYSOFTRST; 259 DWC3_WRITE(sc, DWC3_GUSB2PHYCFG0, phy2); 260 261 phy3 &= ~DWC3_GUSB3PIPECTL0_PHYSOFTRST; 262 DWC3_WRITE(sc, DWC3_GUSB3PIPECTL0, phy3); 263 264 gctl &= ~DWC3_GCTL_CORESOFTRESET; 265 DWC3_WRITE(sc, DWC3_GCTL, gctl); 266 267 } 268 269 static void 270 snps_dwc3_configure_host(struct snps_dwc3_softc *sc) 271 { 272 uint32_t reg; 273 274 reg = DWC3_READ(sc, DWC3_GCTL); 275 reg &= ~DWC3_GCTL_PRTCAPDIR_MASK; 276 reg |= DWC3_GCTL_PRTCAPDIR_HOST; 277 DWC3_WRITE(sc, DWC3_GCTL, reg); 278 279 /* 280 * Enable the Host IN Auto Retry feature, making the 281 * host respond with a non-terminating retry ACK. 282 * XXX If we ever support more than host mode this needs a dr_mode check. 283 */ 284 reg = DWC3_READ(sc, DWC3_GUCTL); 285 reg |= DWC3_GUCTL_HOST_AUTO_RETRY; 286 DWC3_WRITE(sc, DWC3_GUCTL, reg); 287 } 288 289 #ifdef FDT 290 static void 291 snps_dwc3_configure_phy(struct snps_dwc3_softc *sc, phandle_t node) 292 { 293 char *phy_type; 294 uint32_t reg; 295 int nphy_types; 296 297 phy_type = NULL; 298 nphy_types = OF_getprop_alloc(node, "phy_type", (void **)&phy_type); 299 if (nphy_types <= 0) 300 return; 301 302 reg = DWC3_READ(sc, DWC3_GUSB2PHYCFG0); 303 if (strncmp(phy_type, "utmi_wide", 9) == 0) { 304 reg &= ~(DWC3_GUSB2PHYCFG0_PHYIF | DWC3_GUSB2PHYCFG0_USBTRDTIM(0xf)); 305 reg |= DWC3_GUSB2PHYCFG0_PHYIF | 306 DWC3_GUSB2PHYCFG0_USBTRDTIM(DWC3_GUSB2PHYCFG0_USBTRDTIM_16BITS); 307 } else { 308 reg &= ~(DWC3_GUSB2PHYCFG0_PHYIF | DWC3_GUSB2PHYCFG0_USBTRDTIM(0xf)); 309 reg |= DWC3_GUSB2PHYCFG0_PHYIF | 310 DWC3_GUSB2PHYCFG0_USBTRDTIM(DWC3_GUSB2PHYCFG0_USBTRDTIM_8BITS); 311 } 312 DWC3_WRITE(sc, DWC3_GUSB2PHYCFG0, reg); 313 OF_prop_free(phy_type); 314 } 315 #endif 316 317 static void 318 snps_dwc3_do_quirks(struct snps_dwc3_softc *sc) 319 { 320 struct xhci_softc *xsc; 321 uint32_t ghwp0, reg; 322 323 ghwp0 = DWC3_READ(sc, DWC3_GHWPARAMS0); 324 reg = DWC3_READ(sc, DWC3_GUSB2PHYCFG0); 325 if (device_has_property(sc->dev, "snps,dis-u2-freeclk-exists-quirk")) 326 reg &= ~DWC3_GUSB2PHYCFG0_U2_FREECLK_EXISTS; 327 else 328 reg |= DWC3_GUSB2PHYCFG0_U2_FREECLK_EXISTS; 329 if (device_has_property(sc->dev, "snps,dis_u2_susphy_quirk")) 330 reg &= ~DWC3_GUSB2PHYCFG0_SUSPENDUSB20; 331 else if ((ghwp0 & DWC3_GHWPARAMS0_MODE_MASK) == 332 DWC3_GHWPARAMS0_MODE_DUALROLEDEVICE) 333 reg |= DWC3_GUSB2PHYCFG0_SUSPENDUSB20; 334 if (device_has_property(sc->dev, "snps,dis_enblslpm_quirk")) 335 reg &= ~DWC3_GUSB2PHYCFG0_ENBLSLPM; 336 else 337 reg |= DWC3_GUSB2PHYCFG0_ENBLSLPM; 338 DWC3_WRITE(sc, DWC3_GUSB2PHYCFG0, reg); 339 340 reg = DWC3_READ(sc, DWC3_GUCTL1); 341 if (device_has_property(sc->dev, "snps,dis-tx-ipgap-linecheck-quirk")) 342 reg |= DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS; 343 DWC3_WRITE(sc, DWC3_GUCTL1, reg); 344 345 reg = DWC3_READ(sc, DWC3_GUSB3PIPECTL0); 346 if (device_has_property(sc->dev, "snps,dis-del-phy-power-chg-quirk")) 347 reg &= ~DWC3_GUSB3PIPECTL0_DELAYP1TRANS; 348 if (device_has_property(sc->dev, "snps,dis_rxdet_inp3_quirk")) 349 reg |= DWC3_GUSB3PIPECTL0_DISRXDETINP3; 350 if (device_has_property(sc->dev, "snps,dis_u3_susphy_quirk")) 351 reg &= ~DWC3_GUSB3PIPECTL0_SUSPENDUSB3; 352 else if ((ghwp0 & DWC3_GHWPARAMS0_MODE_MASK) == 353 DWC3_GHWPARAMS0_MODE_DUALROLEDEVICE) 354 reg |= DWC3_GUSB3PIPECTL0_SUSPENDUSB3; 355 DWC3_WRITE(sc, DWC3_GUSB3PIPECTL0, reg); 356 357 /* Port Disable does not work on <= 3.00a. Disable PORT_PED. */ 358 if ((sc->snpsid & 0xffff) <= 0x300a) { 359 xsc = &sc->sc; 360 xsc->sc_quirks |= XHCI_QUIRK_DISABLE_PORT_PED; 361 } 362 } 363 364 static int 365 snps_dwc3_probe_common(device_t dev) 366 { 367 char dr_mode[16] = { 0 }; 368 ssize_t s; 369 370 s = device_get_property(dev, "dr_mode", dr_mode, sizeof(dr_mode), 371 DEVICE_PROP_BUFFER); 372 if (s == -1) { 373 device_printf(dev, "Cannot determine dr_mode\n"); 374 return (ENXIO); 375 } 376 if (strcmp(dr_mode, "host") != 0) { 377 device_printf(dev, 378 "Found dr_mode '%s' but only 'host' supported. s=%zd\n", 379 dr_mode, s); 380 return (ENXIO); 381 } 382 383 device_set_desc(dev, "Synopsys Designware DWC3"); 384 return (BUS_PROBE_DEFAULT); 385 } 386 387 static int 388 snps_dwc3_common_attach(device_t dev, bool is_fdt) 389 { 390 struct snps_dwc3_softc *sc; 391 #ifdef FDT 392 phandle_t node; 393 phy_t usb2_phy, usb3_phy; 394 uint32_t reg; 395 #endif 396 int error, rid; 397 398 sc = device_get_softc(dev); 399 sc->dev = dev; 400 401 rid = 0; 402 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 403 RF_ACTIVE); 404 if (sc->mem_res == NULL) { 405 device_printf(dev, "Failed to map memory\n"); 406 return (ENXIO); 407 } 408 sc->bst = rman_get_bustag(sc->mem_res); 409 sc->bsh = rman_get_bushandle(sc->mem_res); 410 411 sc->snpsid = DWC3_READ(sc, DWC3_GSNPSID); 412 sc->snpsversion = DWC3_VERSION(sc->snpsid); 413 sc->snpsrevision = DWC3_REVISION(sc->snpsid); 414 if (sc->snpsversion == DWC3_1_IP_ID || 415 sc->snpsversion == DWC3_2_IP_ID) { 416 sc->snpsrevision = DWC3_READ(sc, DWC3_1_VER_NUMBER); 417 sc->snpsversion_type = DWC3_READ(sc, DWC3_1_VER_TYPE); 418 } 419 if (bootverbose) { 420 switch (sc->snpsversion) { 421 case DWC3_IP_ID: 422 device_printf(sc->dev, "SNPS Version: DWC3 (%x %x)\n", 423 sc->snpsversion, sc->snpsrevision); 424 break; 425 case DWC3_1_IP_ID: 426 device_printf(sc->dev, "SNPS Version: DWC3.1 (%x %x %x)\n", 427 sc->snpsversion, sc->snpsrevision, 428 sc->snpsversion_type); 429 break; 430 case DWC3_2_IP_ID: 431 device_printf(sc->dev, "SNPS Version: DWC3.2 (%x %x %x)\n", 432 sc->snpsversion, sc->snpsrevision, 433 sc->snpsversion_type); 434 break; 435 } 436 } 437 #ifdef DWC3_DEBUG 438 snps_dwc3_dump_ctrlparams(sc); 439 #endif 440 441 #ifdef FDT 442 if (!is_fdt) 443 goto skip_phys; 444 445 node = ofw_bus_get_node(dev); 446 447 /* Get the clocks if any */ 448 if (ofw_bus_is_compatible(dev, "rockchip,rk3328-dwc3") == 1 || 449 ofw_bus_is_compatible(dev, "rockchip,rk3568-dwc3") == 1) { 450 if (clk_get_by_ofw_name(dev, node, "ref_clk", &sc->clk_ref) != 0) 451 device_printf(dev, "Cannot get ref_clk\n"); 452 if (clk_get_by_ofw_name(dev, node, "suspend_clk", &sc->clk_suspend) != 0) 453 device_printf(dev, "Cannot get suspend_clk\n"); 454 if (clk_get_by_ofw_name(dev, node, "bus_clk", &sc->clk_bus) != 0) 455 device_printf(dev, "Cannot get bus_clk\n"); 456 } 457 458 if (sc->clk_ref != NULL) { 459 if (clk_enable(sc->clk_ref) != 0) 460 device_printf(dev, "Cannot enable ref_clk\n"); 461 } 462 if (sc->clk_suspend != NULL) { 463 if (clk_enable(sc->clk_suspend) != 0) 464 device_printf(dev, "Cannot enable suspend_clk\n"); 465 } 466 if (sc->clk_bus != NULL) { 467 if (clk_enable(sc->clk_bus) != 0) 468 device_printf(dev, "Cannot enable bus_clk\n"); 469 } 470 471 /* Get the phys */ 472 usb2_phy = usb3_phy = NULL; 473 error = phy_get_by_ofw_name(dev, node, "usb2-phy", &usb2_phy); 474 if (error == 0 && usb2_phy != NULL) 475 phy_enable(usb2_phy); 476 error = phy_get_by_ofw_name(dev, node, "usb3-phy", &usb3_phy); 477 if (error == 0 && usb3_phy != NULL) 478 phy_enable(usb3_phy); 479 if (sc->snpsversion == DWC3_IP_ID) { 480 if (sc->snpsrevision >= 0x290A) { 481 uint32_t hwparams3; 482 483 hwparams3 = DWC3_READ(sc, DWC3_GHWPARAMS3); 484 if (DWC3_HWPARAMS3_SSPHY(hwparams3) == DWC3_HWPARAMS3_SSPHY_DISABLE) { 485 reg = DWC3_READ(sc, DWC3_GUCTL1); 486 if (bootverbose) 487 device_printf(dev, "Forcing USB2 clock only\n"); 488 reg |= DWC3_GUCTL1_DEV_FORCE_20_CLK_FOR_30_CLK; 489 DWC3_WRITE(sc, DWC3_GUCTL1, reg); 490 } 491 } 492 } 493 snps_dwc3_configure_phy(sc, node); 494 skip_phys: 495 #endif 496 497 snps_dwc3_reset(sc); 498 snps_dwc3_configure_host(sc); 499 snps_dwc3_do_quirks(sc); 500 501 #ifdef DWC3_DEBUG 502 snsp_dwc3_dump_regs(sc, "Pre XHCI init"); 503 #endif 504 error = snps_dwc3_attach_xhci(dev); 505 #ifdef DWC3_DEBUG 506 snsp_dwc3_dump_regs(sc, "Post XHCI init"); 507 #endif 508 509 #ifdef FDT 510 if (error) { 511 if (sc->clk_ref != NULL) 512 clk_disable(sc->clk_ref); 513 if (sc->clk_suspend != NULL) 514 clk_disable(sc->clk_suspend); 515 if (sc->clk_bus != NULL) 516 clk_disable(sc->clk_bus); 517 } 518 #endif 519 return (error); 520 } 521 522 #ifdef FDT 523 static struct ofw_compat_data compat_data[] = { 524 { "snps,dwc3", 1 }, 525 { NULL, 0 } 526 }; 527 528 static int 529 snps_dwc3_fdt_probe(device_t dev) 530 { 531 532 if (!ofw_bus_status_okay(dev)) 533 return (ENXIO); 534 535 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) 536 return (ENXIO); 537 538 return (snps_dwc3_probe_common(dev)); 539 } 540 541 static int 542 snps_dwc3_fdt_attach(device_t dev) 543 { 544 545 return (snps_dwc3_common_attach(dev, true)); 546 } 547 548 static device_method_t snps_dwc3_fdt_methods[] = { 549 /* Device interface */ 550 DEVMETHOD(device_probe, snps_dwc3_fdt_probe), 551 DEVMETHOD(device_attach, snps_dwc3_fdt_attach), 552 553 DEVMETHOD_END 554 }; 555 556 DEFINE_CLASS_1(snps_dwc3_fdt, snps_dwc3_fdt_driver, snps_dwc3_fdt_methods, 557 sizeof(struct snps_dwc3_softc), generic_xhci_driver); 558 559 DRIVER_MODULE(snps_dwc3_fdt, simplebus, snps_dwc3_fdt_driver, 0, 0); 560 MODULE_DEPEND(snps_dwc3_fdt, xhci, 1, 1, 1); 561 #endif 562 563 #ifdef DEV_ACPI 564 static char *dwc3_acpi_ids[] = { 565 "808622B7", /* This was an Intel PCI Vendor/Device ID used. */ 566 "PNP0D10", /* The generic XHCI PNP ID needing extra probe checks. */ 567 NULL 568 }; 569 570 static int 571 snps_dwc3_acpi_probe(device_t dev) 572 { 573 char *match; 574 int error; 575 576 if (acpi_disabled("snps_dwc3")) 577 return (ENXIO); 578 579 error = ACPI_ID_PROBE(device_get_parent(dev), dev, dwc3_acpi_ids, &match); 580 if (error > 0) 581 return (ENXIO); 582 583 /* 584 * If we found the Generic XHCI PNP ID we can only attach if we have 585 * some other means to identify the device as dwc3. 586 */ 587 if (strcmp(match, "PNP0D10") == 0) { 588 /* This is needed in SolidRun's HoneyComb. */ 589 if (device_has_property(dev, "snps,dis_rxdet_inp3_quirk")) 590 goto is_dwc3; 591 592 return (ENXIO); 593 } 594 595 is_dwc3: 596 return (snps_dwc3_probe_common(dev)); 597 } 598 599 static int 600 snps_dwc3_acpi_attach(device_t dev) 601 { 602 603 return (snps_dwc3_common_attach(dev, false)); 604 } 605 606 static device_method_t snps_dwc3_acpi_methods[] = { 607 /* Device interface */ 608 DEVMETHOD(device_probe, snps_dwc3_acpi_probe), 609 DEVMETHOD(device_attach, snps_dwc3_acpi_attach), 610 611 DEVMETHOD_END 612 }; 613 614 DEFINE_CLASS_1(snps_dwc3_acpi, snps_dwc3_acpi_driver, snps_dwc3_acpi_methods, 615 sizeof(struct snps_dwc3_softc), generic_xhci_driver); 616 617 DRIVER_MODULE(snps_dwc3_acpi, acpi, snps_dwc3_acpi_driver, 0, 0); 618 MODULE_DEPEND(snps_dwc3_acpi, usb, 1, 1, 1); 619 #endif 620