The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/controller/dwc3.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: cf61adac8ecd69f6a937c7d54d68c68f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.