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