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