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