1052073c3SEmmanuel Vadot /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3052073c3SEmmanuel Vadot *
4052073c3SEmmanuel Vadot * Copyright (c) 2015 Semihalf.
5052073c3SEmmanuel Vadot * Copyright (c) 2015 Stormshield.
6052073c3SEmmanuel Vadot * All rights reserved.
7052073c3SEmmanuel Vadot *
8052073c3SEmmanuel Vadot * Redistribution and use in source and binary forms, with or without
9052073c3SEmmanuel Vadot * modification, are permitted provided that the following conditions
10052073c3SEmmanuel Vadot * are met:
11052073c3SEmmanuel Vadot * 1. Redistributions of source code must retain the above copyright
12052073c3SEmmanuel Vadot * notice, this list of conditions and the following disclaimer.
13052073c3SEmmanuel Vadot * 2. Redistributions in binary form must reproduce the above copyright
14052073c3SEmmanuel Vadot * notice, this list of conditions and the following disclaimer in the
15052073c3SEmmanuel Vadot * documentation and/or other materials provided with the distribution.
16052073c3SEmmanuel Vadot *
17052073c3SEmmanuel Vadot * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18052073c3SEmmanuel Vadot * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19052073c3SEmmanuel Vadot * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20052073c3SEmmanuel Vadot * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21052073c3SEmmanuel Vadot * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22052073c3SEmmanuel Vadot * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23052073c3SEmmanuel Vadot * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24052073c3SEmmanuel Vadot * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25052073c3SEmmanuel Vadot * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26052073c3SEmmanuel Vadot * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27052073c3SEmmanuel Vadot * SUCH DAMAGE.
28052073c3SEmmanuel Vadot */
29052073c3SEmmanuel Vadot
30052073c3SEmmanuel Vadot #include <sys/cdefs.h>
31052073c3SEmmanuel Vadot #include "opt_bus.h"
32052073c3SEmmanuel Vadot
33052073c3SEmmanuel Vadot #include <sys/param.h>
34052073c3SEmmanuel Vadot #include <sys/systm.h>
35052073c3SEmmanuel Vadot #include <sys/bus.h>
36052073c3SEmmanuel Vadot #include <sys/condvar.h>
37052073c3SEmmanuel Vadot #include <sys/kernel.h>
38052073c3SEmmanuel Vadot #include <sys/module.h>
39052073c3SEmmanuel Vadot
40052073c3SEmmanuel Vadot #include <dev/usb/usb.h>
41052073c3SEmmanuel Vadot #include <dev/usb/usbdi.h>
42052073c3SEmmanuel Vadot
43052073c3SEmmanuel Vadot #include <dev/usb/usb_core.h>
44052073c3SEmmanuel Vadot #include <dev/usb/usb_busdma.h>
45052073c3SEmmanuel Vadot #include <dev/usb/usb_process.h>
46052073c3SEmmanuel Vadot
47052073c3SEmmanuel Vadot #include <dev/usb/usb_controller.h>
48052073c3SEmmanuel Vadot #include <dev/usb/usb_bus.h>
49052073c3SEmmanuel Vadot #include <dev/usb/controller/xhci.h>
50052073c3SEmmanuel Vadot
51052073c3SEmmanuel Vadot #include <dev/ofw/ofw_bus.h>
52052073c3SEmmanuel Vadot #include <dev/ofw/ofw_bus_subr.h>
53052073c3SEmmanuel Vadot
54*950a6087SEmmanuel Vadot #include <dev/phy/phy.h>
55052073c3SEmmanuel Vadot
56052073c3SEmmanuel Vadot #include "generic_xhci.h"
57052073c3SEmmanuel Vadot
58332af8c2SStephen J. Kiernan /* Flags for the OFW compat data table */
59332af8c2SStephen J. Kiernan #define XHCI_FDT_MATCH 0x01
60332af8c2SStephen J. Kiernan #define XHCI_FDT_32BIT_DMA 0x02 /* Controller needs 32-bit DMA */
61332af8c2SStephen J. Kiernan
62052073c3SEmmanuel Vadot static struct ofw_compat_data compat_data[] = {
63332af8c2SStephen J. Kiernan {"marvell,armada-380-xhci", XHCI_FDT_MATCH},
64332af8c2SStephen J. Kiernan {"marvell,armada3700-xhci", XHCI_FDT_MATCH},
65332af8c2SStephen J. Kiernan {"marvell,armada-8k-xhci", XHCI_FDT_MATCH},
66332af8c2SStephen J. Kiernan {"generic-xhci", XHCI_FDT_MATCH},
67332af8c2SStephen J. Kiernan {NULL, 0}
68052073c3SEmmanuel Vadot };
69052073c3SEmmanuel Vadot
70052073c3SEmmanuel Vadot static int
generic_xhci_fdt_probe(device_t dev)71052073c3SEmmanuel Vadot generic_xhci_fdt_probe(device_t dev)
72052073c3SEmmanuel Vadot {
73052073c3SEmmanuel Vadot
74052073c3SEmmanuel Vadot if (!ofw_bus_status_okay(dev))
75052073c3SEmmanuel Vadot return (ENXIO);
76052073c3SEmmanuel Vadot
77052073c3SEmmanuel Vadot if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
78052073c3SEmmanuel Vadot return (ENXIO);
79052073c3SEmmanuel Vadot
80052073c3SEmmanuel Vadot device_set_desc(dev, XHCI_HC_DEVSTR);
81052073c3SEmmanuel Vadot
82052073c3SEmmanuel Vadot return (BUS_PROBE_DEFAULT);
83052073c3SEmmanuel Vadot }
84052073c3SEmmanuel Vadot
85052073c3SEmmanuel Vadot static int
generic_xhci_fdt_attach(device_t dev)86052073c3SEmmanuel Vadot generic_xhci_fdt_attach(device_t dev)
87052073c3SEmmanuel Vadot {
88332af8c2SStephen J. Kiernan struct xhci_softc *sc = device_get_softc(dev);
89052073c3SEmmanuel Vadot phandle_t node;
90052073c3SEmmanuel Vadot phy_t phy;
91332af8c2SStephen J. Kiernan int flags;
92052073c3SEmmanuel Vadot
93052073c3SEmmanuel Vadot node = ofw_bus_get_node(dev);
94052073c3SEmmanuel Vadot if (phy_get_by_ofw_property(dev, node, "usb-phy", &phy) == 0)
95052073c3SEmmanuel Vadot if (phy_enable(phy) != 0)
96052073c3SEmmanuel Vadot device_printf(dev, "Cannot enable phy\n");
97052073c3SEmmanuel Vadot
98332af8c2SStephen J. Kiernan flags = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
99332af8c2SStephen J. Kiernan if ((flags & XHCI_FDT_32BIT_DMA) != 0)
100332af8c2SStephen J. Kiernan sc->sc_quirks |= XHCI_QUIRK_DMA_32B;
101332af8c2SStephen J. Kiernan
102052073c3SEmmanuel Vadot return (generic_xhci_attach(dev));
103052073c3SEmmanuel Vadot }
104052073c3SEmmanuel Vadot
105052073c3SEmmanuel Vadot static int
generic_xhci_fdt_detach(device_t dev)106052073c3SEmmanuel Vadot generic_xhci_fdt_detach(device_t dev)
107052073c3SEmmanuel Vadot {
108052073c3SEmmanuel Vadot phandle_t node;
109052073c3SEmmanuel Vadot phy_t phy;
110052073c3SEmmanuel Vadot int err;
111052073c3SEmmanuel Vadot
112052073c3SEmmanuel Vadot err = generic_xhci_detach(dev);
113052073c3SEmmanuel Vadot if (err != 0)
114052073c3SEmmanuel Vadot return (err);
115052073c3SEmmanuel Vadot
116052073c3SEmmanuel Vadot node = ofw_bus_get_node(dev);
117052073c3SEmmanuel Vadot if (phy_get_by_ofw_property(dev, node, "usb-phy", &phy) == 0)
118052073c3SEmmanuel Vadot phy_release(phy);
119052073c3SEmmanuel Vadot
120052073c3SEmmanuel Vadot return (0);
121052073c3SEmmanuel Vadot }
122052073c3SEmmanuel Vadot
123052073c3SEmmanuel Vadot static device_method_t xhci_fdt_methods[] = {
124052073c3SEmmanuel Vadot /* Device interface */
125052073c3SEmmanuel Vadot DEVMETHOD(device_probe, generic_xhci_fdt_probe),
126052073c3SEmmanuel Vadot DEVMETHOD(device_attach, generic_xhci_fdt_attach),
127052073c3SEmmanuel Vadot DEVMETHOD(device_detach, generic_xhci_fdt_detach),
128052073c3SEmmanuel Vadot
129052073c3SEmmanuel Vadot DEVMETHOD_END
130052073c3SEmmanuel Vadot };
131052073c3SEmmanuel Vadot
132052073c3SEmmanuel Vadot DEFINE_CLASS_1(xhci, xhci_fdt_driver, xhci_fdt_methods,
133052073c3SEmmanuel Vadot sizeof(struct xhci_softc), generic_xhci_driver);
134052073c3SEmmanuel Vadot
135bc9372d7SJohn Baldwin DRIVER_MODULE(xhci, simplebus, xhci_fdt_driver, 0, 0);
136052073c3SEmmanuel Vadot MODULE_DEPEND(xhci, usb, 1, 1, 1);
137