xref: /freebsd-14.2/sys/dev/usb/controller/dwc3.c (revision 22dca7ac)
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