1a2c472e7SAleksandr Rybalko /*- 2a2c472e7SAleksandr Rybalko * Copyright (c) 2010-2012 Semihalf 3a2c472e7SAleksandr Rybalko * Copyright (c) 2012 The FreeBSD Foundation 4f26c8105SIan Lepore * Copyright (c) 2013 Ian Lepore <ian@freebsd.org> 5a2c472e7SAleksandr Rybalko * All rights reserved. 6a2c472e7SAleksandr Rybalko * 7a2c472e7SAleksandr Rybalko * Portions of this software were developed by Oleksandr Rybalko 8a2c472e7SAleksandr Rybalko * under sponsorship from the FreeBSD Foundation. 9a2c472e7SAleksandr Rybalko * 10a2c472e7SAleksandr Rybalko * Redistribution and use in source and binary forms, with or without 11a2c472e7SAleksandr Rybalko * modification, are permitted provided that the following conditions 12a2c472e7SAleksandr Rybalko * are met: 13a2c472e7SAleksandr Rybalko * 1. Redistributions of source code must retain the above copyright 14a2c472e7SAleksandr Rybalko * notice, this list of conditions and the following disclaimer. 15a2c472e7SAleksandr Rybalko * 2. Redistributions in binary form must reproduce the above copyright 16a2c472e7SAleksandr Rybalko * notice, this list of conditions and the following disclaimer in the 17a2c472e7SAleksandr Rybalko * documentation and/or other materials provided with the distribution. 18a2c472e7SAleksandr Rybalko * 19a2c472e7SAleksandr Rybalko * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20a2c472e7SAleksandr Rybalko * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21a2c472e7SAleksandr Rybalko * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22a2c472e7SAleksandr Rybalko * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23a2c472e7SAleksandr Rybalko * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24a2c472e7SAleksandr Rybalko * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25a2c472e7SAleksandr Rybalko * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26a2c472e7SAleksandr Rybalko * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27a2c472e7SAleksandr Rybalko * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28a2c472e7SAleksandr Rybalko * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29a2c472e7SAleksandr Rybalko * SUCH DAMAGE. 30a2c472e7SAleksandr Rybalko */ 31a2c472e7SAleksandr Rybalko 32a2c472e7SAleksandr Rybalko #include <sys/cdefs.h> 33a2c472e7SAleksandr Rybalko __FBSDID("$FreeBSD$"); 34a2c472e7SAleksandr Rybalko 35f26c8105SIan Lepore /* 36f26c8105SIan Lepore * EHCI driver for Freescale i.MX SoCs which incorporate the USBOH3 controller. 37f26c8105SIan Lepore */ 38a2c472e7SAleksandr Rybalko 39a2c472e7SAleksandr Rybalko #include <sys/param.h> 40a2c472e7SAleksandr Rybalko #include <sys/systm.h> 41a2c472e7SAleksandr Rybalko #include <sys/kernel.h> 42a2c472e7SAleksandr Rybalko #include <sys/module.h> 43a2c472e7SAleksandr Rybalko #include <sys/bus.h> 44a2c472e7SAleksandr Rybalko #include <sys/condvar.h> 45a2c472e7SAleksandr Rybalko #include <sys/rman.h> 46a2c472e7SAleksandr Rybalko 47a2c472e7SAleksandr Rybalko #include <dev/ofw/ofw_bus.h> 48a2c472e7SAleksandr Rybalko #include <dev/ofw/ofw_bus_subr.h> 49a2c472e7SAleksandr Rybalko 50a2c472e7SAleksandr Rybalko #include <dev/usb/usb.h> 51a2c472e7SAleksandr Rybalko #include <dev/usb/usbdi.h> 52a2c472e7SAleksandr Rybalko #include <dev/usb/usb_busdma.h> 53a2c472e7SAleksandr Rybalko #include <dev/usb/usb_process.h> 54a2c472e7SAleksandr Rybalko #include <dev/usb/usb_controller.h> 55a2c472e7SAleksandr Rybalko #include <dev/usb/usb_bus.h> 56a2c472e7SAleksandr Rybalko #include <dev/usb/controller/ehci.h> 57a2c472e7SAleksandr Rybalko #include <dev/usb/controller/ehcireg.h> 58f26c8105SIan Lepore #include "usbdevs.h" 59a2c472e7SAleksandr Rybalko 60a2c472e7SAleksandr Rybalko #include <machine/bus.h> 61a2c472e7SAleksandr Rybalko #include <machine/resource.h> 62a2c472e7SAleksandr Rybalko 63a7fa939bSIan Lepore #include <arm/freescale/imx/imx_ccmvar.h> 64f26c8105SIan Lepore 65a2c472e7SAleksandr Rybalko #include "opt_platform.h" 66a2c472e7SAleksandr Rybalko 67f26c8105SIan Lepore /* 68f26c8105SIan Lepore * Notes on the hardware and related FDT data seen in the wild. 69f26c8105SIan Lepore * 70f26c8105SIan Lepore * There are two sets of registers in the USBOH3 implementation; documentation 71f26c8105SIan Lepore * refers to them as "core" and "non-core" registers. A set of core register 72f26c8105SIan Lepore * exists for each OTG or EHCI device. There is a single set of non-core 73f26c8105SIan Lepore * registers per USBOH3, and they control aspects of operation not directly 74f26c8105SIan Lepore * related to the USB specs, such as whether interrupts from each of the core 75f26c8105SIan Lepore * devices are able to generate a SoC wakeup event. 76f26c8105SIan Lepore * 77f26c8105SIan Lepore * In the FreeBSD universe we might be inclined to describe the core and 78f26c8105SIan Lepore * non-core registers by using a pair of resource address/size values (two 79f26c8105SIan Lepore * entries in the reg property for each core). However, we have to work with 80f26c8105SIan Lepore * existing FDT data (which mostly comes from the linux universe), and the way 81f26c8105SIan Lepore * they've chosen to represent this is with an entry for a "usbmisc" device 82f26c8105SIan Lepore * whose reg property describes the non-core registers. The way we handle FDT 83f26c8105SIan Lepore * data, this means that the resources (memory-mapped register range) for the 84f26c8105SIan Lepore * non-core registers belongs to a device other than the echi devices. 85f26c8105SIan Lepore * 86f26c8105SIan Lepore * At the moment we have no need to access the non-core registers, so all of 87f26c8105SIan Lepore * this amounts to documenting what's known. The following compat strings have 88f26c8105SIan Lepore * been seen in existing FDT data: 89f26c8105SIan Lepore * - "fsl,imx25-usbmisc" 90f26c8105SIan Lepore * - "fsl,imx51-usbmisc"; 91f26c8105SIan Lepore * - "fsl,imx6q-usbmisc"; 92f26c8105SIan Lepore * 93f26c8105SIan Lepore * In addition to the single usbmisc device, the existing FDT data defines a 94f26c8105SIan Lepore * separate device for each of the OTG or EHCI cores within the USBOH3. Each of 95f26c8105SIan Lepore * those devices has a set of core registers described by the reg property. 96f26c8105SIan Lepore * 97f26c8105SIan Lepore * The core registers for each of the four cores in the USBOH3 are divided into 98f26c8105SIan Lepore * two parts: a set of imx-specific registers at an offset of 0 from the 99f26c8105SIan Lepore * beginning of the register range, and the standard USB (EHCI or OTG) registers 100f26c8105SIan Lepore * at an offset of 0x100 from the beginning of the register range. The FreeBSD 101f26c8105SIan Lepore * way of dealing with this might be to map out two ranges in the reg property, 102f26c8105SIan Lepore * but that's not what the alternate universe has done. To work with existing 103f26c8105SIan Lepore * FDT data, we acquire the resource that maps all the core registers, then use 104f26c8105SIan Lepore * bus_space_subregion() to create another resource that maps just the standard 105f26c8105SIan Lepore * USB registers, which we provide to the standard USB code in the ehci_softc. 106f26c8105SIan Lepore * 107f26c8105SIan Lepore * The following compat strings have been seen for the OTG and EHCI cores. The 108f26c8105SIan Lepore * FDT compat table in this driver contains all these strings, but as of this 109f26c8105SIan Lepore * writing, not all of these SoCs have been tested with the driver. The fact 110f26c8105SIan Lepore * that imx27 is common to all of them gives some hope that the driver will work 111f26c8105SIan Lepore * on all these SoCs. 112f26c8105SIan Lepore * - "fsl,imx23-usb", "fsl,imx27-usb"; 113f26c8105SIan Lepore * - "fsl,imx25-usb", "fsl,imx27-usb"; 114f26c8105SIan Lepore * - "fsl,imx28-usb", "fsl,imx27-usb"; 115f26c8105SIan Lepore * - "fsl,imx51-usb", "fsl,imx27-usb"; 116f26c8105SIan Lepore * - "fsl,imx53-usb", "fsl,imx27-usb"; 117f26c8105SIan Lepore * - "fsl,imx6q-usb", "fsl,imx27-usb"; 118f26c8105SIan Lepore * 119f26c8105SIan Lepore * The FDT data for some SoCs contains the following properties, which we don't 120f26c8105SIan Lepore * currently do anything with: 121f26c8105SIan Lepore * - fsl,usbmisc = <&usbmisc 0>; 122f26c8105SIan Lepore * - fsl,usbphy = <&usbphy0>; 123f26c8105SIan Lepore * 124f26c8105SIan Lepore * Some imx SoCs have FDT data related to USB PHY, some don't. We have separate 125f26c8105SIan Lepore * usbphy drivers where needed; this data is mentioned here just to keep all the 126f26c8105SIan Lepore * imx-FDT-usb-related info in one place. Here are the usbphy compat strings 127f26c8105SIan Lepore * known to exist: 128f26c8105SIan Lepore * - "nop-usbphy" 129f26c8105SIan Lepore * - "usb-nop-xceiv"; 130f26c8105SIan Lepore * - "fsl,imx23-usbphy" 131f26c8105SIan Lepore * - "fsl,imx28-usbphy", "fsl,imx23-usbphy"; 132f26c8105SIan Lepore * - "fsl,imx6q-usbphy", "fsl,imx23-usbphy"; 133f26c8105SIan Lepore * 134f26c8105SIan Lepore */ 135f26c8105SIan Lepore 136f26c8105SIan Lepore static struct ofw_compat_data compat_data[] = { 137f26c8105SIan Lepore {"fsl,imx6q-usb", 1}, 138f26c8105SIan Lepore {"fsl,imx53-usb", 1}, 139f26c8105SIan Lepore {"fsl,imx51-usb", 1}, 140f26c8105SIan Lepore {"fsl,imx28-usb", 1}, 141f26c8105SIan Lepore {"fsl,imx27-usb", 1}, 142f26c8105SIan Lepore {"fsl,imx25-usb", 1}, 143f26c8105SIan Lepore {"fsl,imx23-usb", 1}, 144f26c8105SIan Lepore {NULL, 0}, 145f26c8105SIan Lepore }; 146f26c8105SIan Lepore 147f26c8105SIan Lepore /* 148f26c8105SIan Lepore * Each EHCI device in the SoC has some SoC-specific per-device registers at an 149f26c8105SIan Lepore * offset of 0, then the standard EHCI registers begin at an offset of 0x100. 150f26c8105SIan Lepore */ 151f26c8105SIan Lepore #define IMX_EHCI_REG_OFF 0x100 152f26c8105SIan Lepore #define IMX_EHCI_REG_SIZE 0x100 153a2c472e7SAleksandr Rybalko 154a2c472e7SAleksandr Rybalko struct imx_ehci_softc { 155f26c8105SIan Lepore ehci_softc_t ehci_softc; 156f26c8105SIan Lepore struct resource *ehci_mem_res; /* EHCI core regs. */ 157f26c8105SIan Lepore struct resource *ehci_irq_res; /* EHCI core IRQ. */ 158a2c472e7SAleksandr Rybalko }; 159a2c472e7SAleksandr Rybalko 160cfed2e63SIan Lepore static void 161cfed2e63SIan Lepore imx_ehci_post_reset(struct ehci_softc *ehci_softc) 162cfed2e63SIan Lepore { 163cfed2e63SIan Lepore uint32_t usbmode; 164cfed2e63SIan Lepore 165cfed2e63SIan Lepore /* Force HOST mode */ 166cfed2e63SIan Lepore usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM); 167cfed2e63SIan Lepore usbmode &= ~EHCI_UM_CM; 168cfed2e63SIan Lepore usbmode |= EHCI_UM_CM_HOST; 169cfed2e63SIan Lepore EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode); 170cfed2e63SIan Lepore } 171cfed2e63SIan Lepore 172f26c8105SIan Lepore static int 173f26c8105SIan Lepore imx_ehci_probe(device_t dev) 174f26c8105SIan Lepore { 175a2c472e7SAleksandr Rybalko 176add35ed5SIan Lepore if (!ofw_bus_status_okay(dev)) 177add35ed5SIan Lepore return (ENXIO); 178add35ed5SIan Lepore 179f26c8105SIan Lepore if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) { 180f26c8105SIan Lepore device_set_desc(dev, "Freescale i.MX integrated USB controller"); 181f26c8105SIan Lepore return (BUS_PROBE_DEFAULT); 182f26c8105SIan Lepore } 183f26c8105SIan Lepore return (ENXIO); 184f26c8105SIan Lepore } 185f26c8105SIan Lepore 186f26c8105SIan Lepore static int 187f26c8105SIan Lepore imx_ehci_detach(device_t dev) 188f26c8105SIan Lepore { 189f26c8105SIan Lepore struct imx_ehci_softc *sc; 190f26c8105SIan Lepore ehci_softc_t *esc; 191f26c8105SIan Lepore 192f26c8105SIan Lepore sc = device_get_softc(dev); 193f26c8105SIan Lepore 194f26c8105SIan Lepore esc = &sc->ehci_softc; 195f26c8105SIan Lepore 196f26c8105SIan Lepore if (esc->sc_bus.bdev != NULL) 197f26c8105SIan Lepore device_delete_child(dev, esc->sc_bus.bdev); 198f26c8105SIan Lepore if (esc->sc_flags & EHCI_SCFLG_DONEINIT) 199f26c8105SIan Lepore ehci_detach(esc); 200f26c8105SIan Lepore if (esc->sc_intr_hdl != NULL) 201f26c8105SIan Lepore bus_teardown_intr(dev, esc->sc_irq_res, 202f26c8105SIan Lepore esc->sc_intr_hdl); 203f26c8105SIan Lepore if (sc->ehci_irq_res != NULL) 204f26c8105SIan Lepore bus_release_resource(dev, SYS_RES_IRQ, 0, 205f26c8105SIan Lepore sc->ehci_irq_res); 206f26c8105SIan Lepore if (sc->ehci_mem_res != NULL) 207f26c8105SIan Lepore bus_release_resource(dev, SYS_RES_MEMORY, 0, 208f26c8105SIan Lepore sc->ehci_mem_res); 209f26c8105SIan Lepore 210f26c8105SIan Lepore usb_bus_mem_free_all(&esc->sc_bus, &ehci_iterate_hw_softc); 211f26c8105SIan Lepore 212f26c8105SIan Lepore /* During module unload there are lots of children leftover */ 213f26c8105SIan Lepore device_delete_children(dev); 214f26c8105SIan Lepore 215f26c8105SIan Lepore return (0); 216f26c8105SIan Lepore } 217f26c8105SIan Lepore 218f26c8105SIan Lepore static int 219f26c8105SIan Lepore imx_ehci_attach(device_t dev) 220f26c8105SIan Lepore { 221f26c8105SIan Lepore struct imx_ehci_softc *sc; 222f26c8105SIan Lepore ehci_softc_t *esc; 223f26c8105SIan Lepore int err, rid; 224f26c8105SIan Lepore 225f26c8105SIan Lepore sc = device_get_softc(dev); 226f26c8105SIan Lepore esc = &sc->ehci_softc; 227f26c8105SIan Lepore err = 0; 228f26c8105SIan Lepore 229f26c8105SIan Lepore /* Allocate bus_space resources. */ 230f26c8105SIan Lepore rid = 0; 231f26c8105SIan Lepore sc->ehci_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 232f26c8105SIan Lepore RF_ACTIVE); 233f26c8105SIan Lepore if (sc->ehci_mem_res == NULL) { 234f26c8105SIan Lepore device_printf(dev, "Cannot allocate memory resources\n"); 235f26c8105SIan Lepore err = ENXIO; 236f26c8105SIan Lepore goto out; 237f26c8105SIan Lepore } 238f26c8105SIan Lepore 239f26c8105SIan Lepore rid = 0; 240f26c8105SIan Lepore sc->ehci_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 241f26c8105SIan Lepore RF_ACTIVE); 242f26c8105SIan Lepore if (sc->ehci_irq_res == NULL) { 243f26c8105SIan Lepore device_printf(dev, "Cannot allocate IRQ resources\n"); 244f26c8105SIan Lepore err = ENXIO; 245f26c8105SIan Lepore goto out; 246f26c8105SIan Lepore } 247f26c8105SIan Lepore 248f26c8105SIan Lepore esc->sc_io_tag = rman_get_bustag(sc->ehci_mem_res); 249f26c8105SIan Lepore esc->sc_bus.parent = dev; 250f26c8105SIan Lepore esc->sc_bus.devices = esc->sc_devices; 251f26c8105SIan Lepore esc->sc_bus.devices_max = EHCI_MAX_DEVICES; 252b217d184SHans Petter Selasky esc->sc_bus.dma_bits = 32; 253f26c8105SIan Lepore 254b217d184SHans Petter Selasky /* allocate all DMA memory */ 255f26c8105SIan Lepore if (usb_bus_mem_alloc_all(&esc->sc_bus, USB_GET_DMA_TAG(dev), 256f26c8105SIan Lepore &ehci_iterate_hw_softc) != 0) { 257f26c8105SIan Lepore device_printf(dev, "usb_bus_mem_alloc_all() failed\n"); 258f26c8105SIan Lepore err = ENOMEM; 259f26c8105SIan Lepore goto out; 260f26c8105SIan Lepore } 261f26c8105SIan Lepore 262f26c8105SIan Lepore /* 263f26c8105SIan Lepore * Set handle to USB related registers subregion used by 264f26c8105SIan Lepore * generic EHCI driver. 265f26c8105SIan Lepore */ 266f26c8105SIan Lepore err = bus_space_subregion(esc->sc_io_tag, 267f26c8105SIan Lepore rman_get_bushandle(sc->ehci_mem_res), 268f26c8105SIan Lepore IMX_EHCI_REG_OFF, IMX_EHCI_REG_SIZE, &esc->sc_io_hdl); 269f26c8105SIan Lepore if (err != 0) { 270f26c8105SIan Lepore device_printf(dev, "bus_space_subregion() failed\n"); 271f26c8105SIan Lepore err = ENXIO; 272f26c8105SIan Lepore goto out; 273f26c8105SIan Lepore } 274f26c8105SIan Lepore 275f26c8105SIan Lepore /* Setup interrupt handler. */ 276c520cb4fSMichal Meloun err = bus_setup_intr(dev, sc->ehci_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 277c520cb4fSMichal Meloun NULL, (driver_intr_t *)ehci_interrupt, esc, &esc->sc_intr_hdl); 278f26c8105SIan Lepore if (err != 0) { 279f26c8105SIan Lepore device_printf(dev, "Could not setup IRQ\n"); 280f26c8105SIan Lepore goto out; 281f26c8105SIan Lepore } 282f26c8105SIan Lepore 283f26c8105SIan Lepore /* Turn on clocks. */ 284f26c8105SIan Lepore imx_ccm_usb_enable(dev); 285f26c8105SIan Lepore 286f26c8105SIan Lepore /* Add USB bus device. */ 287f26c8105SIan Lepore esc->sc_bus.bdev = device_add_child(dev, "usbus", -1); 288f26c8105SIan Lepore if (esc->sc_bus.bdev == NULL) { 289f26c8105SIan Lepore device_printf(dev, "Could not add USB device\n"); 290f26c8105SIan Lepore goto out; 291f26c8105SIan Lepore } 292f26c8105SIan Lepore device_set_ivars(esc->sc_bus.bdev, &esc->sc_bus); 293f26c8105SIan Lepore 294f26c8105SIan Lepore esc->sc_id_vendor = USB_VENDOR_FREESCALE; 295f26c8105SIan Lepore strlcpy(esc->sc_vendor, "Freescale", sizeof(esc->sc_vendor)); 296f26c8105SIan Lepore 297cfed2e63SIan Lepore /* 298cfed2e63SIan Lepore * Set flags that affect ehci_init() behavior, and hook our post-reset 299cfed2e63SIan Lepore * code into the standard controller code. 300cfed2e63SIan Lepore */ 3018148f4f3SIan Lepore esc->sc_flags |= EHCI_SCFLG_NORESTERM | EHCI_SCFLG_TT; 302cfed2e63SIan Lepore esc->sc_vendor_post_reset = imx_ehci_post_reset; 3038148f4f3SIan Lepore esc->sc_vendor_get_port_speed = ehci_get_port_speed_portsc; 304cfed2e63SIan Lepore 305f26c8105SIan Lepore err = ehci_init(esc); 306f26c8105SIan Lepore if (err != 0) { 307f26c8105SIan Lepore device_printf(dev, "USB init failed, usb_err_t=%d\n", 308f26c8105SIan Lepore err); 309f26c8105SIan Lepore goto out; 310f26c8105SIan Lepore } 311f26c8105SIan Lepore esc->sc_flags |= EHCI_SCFLG_DONEINIT; 312f26c8105SIan Lepore 313f26c8105SIan Lepore /* Probe the bus. */ 314f26c8105SIan Lepore err = device_probe_and_attach(esc->sc_bus.bdev); 315f26c8105SIan Lepore if (err != 0) { 316f26c8105SIan Lepore device_printf(dev, 317f26c8105SIan Lepore "device_probe_and_attach() failed\n"); 318f26c8105SIan Lepore goto out; 319f26c8105SIan Lepore } 320f26c8105SIan Lepore 321f26c8105SIan Lepore err = 0; 322f26c8105SIan Lepore 323f26c8105SIan Lepore out: 324f26c8105SIan Lepore 325f26c8105SIan Lepore if (err != 0) 326f26c8105SIan Lepore imx_ehci_detach(dev); 327f26c8105SIan Lepore 328f26c8105SIan Lepore return (err); 329f26c8105SIan Lepore } 330a2c472e7SAleksandr Rybalko 331a2c472e7SAleksandr Rybalko static device_method_t ehci_methods[] = { 332a2c472e7SAleksandr Rybalko /* Device interface */ 333f26c8105SIan Lepore DEVMETHOD(device_probe, imx_ehci_probe), 334f26c8105SIan Lepore DEVMETHOD(device_attach, imx_ehci_attach), 335f26c8105SIan Lepore DEVMETHOD(device_detach, imx_ehci_detach), 336a2c472e7SAleksandr Rybalko DEVMETHOD(device_suspend, bus_generic_suspend), 337a2c472e7SAleksandr Rybalko DEVMETHOD(device_resume, bus_generic_resume), 338a2c472e7SAleksandr Rybalko DEVMETHOD(device_shutdown, bus_generic_shutdown), 339a2c472e7SAleksandr Rybalko 340a2c472e7SAleksandr Rybalko /* Bus interface */ 341a2c472e7SAleksandr Rybalko DEVMETHOD(bus_print_child, bus_generic_print_child), 342a2c472e7SAleksandr Rybalko 343f26c8105SIan Lepore DEVMETHOD_END 344a2c472e7SAleksandr Rybalko }; 345a2c472e7SAleksandr Rybalko 346a2c472e7SAleksandr Rybalko static driver_t ehci_driver = { 347a2c472e7SAleksandr Rybalko "ehci", 348a2c472e7SAleksandr Rybalko ehci_methods, 349a2c472e7SAleksandr Rybalko sizeof(struct imx_ehci_softc) 350a2c472e7SAleksandr Rybalko }; 351a2c472e7SAleksandr Rybalko 352a2c472e7SAleksandr Rybalko static devclass_t ehci_devclass; 353a2c472e7SAleksandr Rybalko 354a2c472e7SAleksandr Rybalko DRIVER_MODULE(ehci, simplebus, ehci_driver, ehci_devclass, 0, 0); 355a2c472e7SAleksandr Rybalko MODULE_DEPEND(ehci, usb, 1, 1, 1); 356