1d71896a7SEmmanuel Vadot /*- 2d3f13132SWarner Losh * Copyright (c) 2016 Emmanuel Vadot <manu@freebsd.org> All rights reserved. 3f86e6000SWarner Losh * Copyright (c) 2006 M. Warner Losh <imp@FreeBSD.org> 4d71896a7SEmmanuel Vadot * 5d71896a7SEmmanuel Vadot * Redistribution and use in source and binary forms, with or without 6d71896a7SEmmanuel Vadot * modification, are permitted provided that the following conditions 7d71896a7SEmmanuel Vadot * are met: 8d71896a7SEmmanuel Vadot * 1. Redistributions of source code must retain the above copyright 9d71896a7SEmmanuel Vadot * notice, this list of conditions and the following disclaimer. 10d71896a7SEmmanuel Vadot * 2. Redistributions in binary form must reproduce the above copyright 11d71896a7SEmmanuel Vadot * notice, this list of conditions and the following disclaimer in the 12d71896a7SEmmanuel Vadot * documentation and/or other materials provided with the distribution. 13d71896a7SEmmanuel Vadot * 14d71896a7SEmmanuel Vadot * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15d71896a7SEmmanuel Vadot * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16d71896a7SEmmanuel Vadot * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17d71896a7SEmmanuel Vadot * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18d71896a7SEmmanuel Vadot * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19d71896a7SEmmanuel Vadot * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20d71896a7SEmmanuel Vadot * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21d71896a7SEmmanuel Vadot * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22d71896a7SEmmanuel Vadot * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23d71896a7SEmmanuel Vadot * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24d71896a7SEmmanuel Vadot * SUCH DAMAGE. 25d71896a7SEmmanuel Vadot */ 26d71896a7SEmmanuel Vadot 27d71896a7SEmmanuel Vadot /* 28d71896a7SEmmanuel Vadot * Generic OHCI driver based on AT91 OHCI 29d71896a7SEmmanuel Vadot */ 30d71896a7SEmmanuel Vadot 31d71896a7SEmmanuel Vadot #include <sys/param.h> 32d71896a7SEmmanuel Vadot #include <sys/systm.h> 33d71896a7SEmmanuel Vadot #include <sys/bus.h> 34d71896a7SEmmanuel Vadot #include <sys/rman.h> 35d71896a7SEmmanuel Vadot #include <sys/condvar.h> 36d71896a7SEmmanuel Vadot #include <sys/kernel.h> 37d71896a7SEmmanuel Vadot #include <sys/module.h> 38d71896a7SEmmanuel Vadot 39d71896a7SEmmanuel Vadot #include <machine/bus.h> 40d71896a7SEmmanuel Vadot #include <dev/ofw/ofw_bus.h> 41d71896a7SEmmanuel Vadot #include <dev/ofw/ofw_bus_subr.h> 42d71896a7SEmmanuel Vadot 43d71896a7SEmmanuel Vadot #include <dev/usb/usb.h> 44d71896a7SEmmanuel Vadot #include <dev/usb/usbdi.h> 45d71896a7SEmmanuel Vadot 46d71896a7SEmmanuel Vadot #include <dev/usb/usb_core.h> 47d71896a7SEmmanuel Vadot #include <dev/usb/usb_busdma.h> 48d71896a7SEmmanuel Vadot #include <dev/usb/usb_process.h> 49d71896a7SEmmanuel Vadot #include <dev/usb/usb_util.h> 50d71896a7SEmmanuel Vadot 51d71896a7SEmmanuel Vadot #include <dev/usb/usb_controller.h> 52d71896a7SEmmanuel Vadot #include <dev/usb/usb_bus.h> 53d71896a7SEmmanuel Vadot #include <dev/usb/controller/ohci.h> 54d71896a7SEmmanuel Vadot #include <dev/usb/controller/ohcireg.h> 55d71896a7SEmmanuel Vadot 56be82b3a0SEmmanuel Vadot #include <dev/clk/clk.h> 571f469a9fSEmmanuel Vadot #include <dev/hwreset/hwreset.h> 58950a6087SEmmanuel Vadot #include <dev/phy/phy.h> 59950a6087SEmmanuel Vadot #include <dev/phy/phy_usb.h> 60d71896a7SEmmanuel Vadot 61d71896a7SEmmanuel Vadot #include "generic_usb_if.h" 62d71896a7SEmmanuel Vadot 63d71896a7SEmmanuel Vadot struct clk_list { 64d71896a7SEmmanuel Vadot TAILQ_ENTRY(clk_list) next; 65d71896a7SEmmanuel Vadot clk_t clk; 66d71896a7SEmmanuel Vadot }; 67150c95edSEmmanuel Vadot struct phy_list { 68150c95edSEmmanuel Vadot TAILQ_ENTRY(phy_list) next; 69150c95edSEmmanuel Vadot phy_t phy; 70150c95edSEmmanuel Vadot }; 71150c95edSEmmanuel Vadot struct hwrst_list { 72150c95edSEmmanuel Vadot TAILQ_ENTRY(hwrst_list) next; 73150c95edSEmmanuel Vadot hwreset_t rst; 74150c95edSEmmanuel Vadot }; 75d71896a7SEmmanuel Vadot 76d71896a7SEmmanuel Vadot struct generic_ohci_softc { 77d71896a7SEmmanuel Vadot ohci_softc_t ohci_sc; 78d71896a7SEmmanuel Vadot 79d71896a7SEmmanuel Vadot TAILQ_HEAD(, clk_list) clk_list; 80150c95edSEmmanuel Vadot TAILQ_HEAD(, phy_list) phy_list; 81150c95edSEmmanuel Vadot TAILQ_HEAD(, hwrst_list) rst_list; 82d71896a7SEmmanuel Vadot }; 83d71896a7SEmmanuel Vadot 84d71896a7SEmmanuel Vadot static int generic_ohci_detach(device_t); 85d71896a7SEmmanuel Vadot 86d71896a7SEmmanuel Vadot static int 87d71896a7SEmmanuel Vadot generic_ohci_probe(device_t dev) 88d71896a7SEmmanuel Vadot { 89d71896a7SEmmanuel Vadot 90d71896a7SEmmanuel Vadot if (!ofw_bus_status_okay(dev)) 91d71896a7SEmmanuel Vadot return (ENXIO); 92d71896a7SEmmanuel Vadot 93d71896a7SEmmanuel Vadot if (!ofw_bus_is_compatible(dev, "generic-ohci")) 94d71896a7SEmmanuel Vadot return (ENXIO); 95d71896a7SEmmanuel Vadot 96d71896a7SEmmanuel Vadot device_set_desc(dev, "Generic OHCI Controller"); 97d71896a7SEmmanuel Vadot 98d71896a7SEmmanuel Vadot return (BUS_PROBE_DEFAULT); 99d71896a7SEmmanuel Vadot } 100d71896a7SEmmanuel Vadot 101d71896a7SEmmanuel Vadot static int 102d71896a7SEmmanuel Vadot generic_ohci_attach(device_t dev) 103d71896a7SEmmanuel Vadot { 104d71896a7SEmmanuel Vadot struct generic_ohci_softc *sc = device_get_softc(dev); 105d71896a7SEmmanuel Vadot int err, rid; 106d71896a7SEmmanuel Vadot int off; 107d71896a7SEmmanuel Vadot struct clk_list *clkp; 108150c95edSEmmanuel Vadot struct phy_list *phyp; 109150c95edSEmmanuel Vadot struct hwrst_list *rstp; 110d71896a7SEmmanuel Vadot clk_t clk; 111150c95edSEmmanuel Vadot phy_t phy; 112150c95edSEmmanuel Vadot hwreset_t rst; 113d71896a7SEmmanuel Vadot 114d71896a7SEmmanuel Vadot sc->ohci_sc.sc_bus.parent = dev; 115d71896a7SEmmanuel Vadot sc->ohci_sc.sc_bus.devices = sc->ohci_sc.sc_devices; 116d71896a7SEmmanuel Vadot sc->ohci_sc.sc_bus.devices_max = OHCI_MAX_DEVICES; 117d71896a7SEmmanuel Vadot sc->ohci_sc.sc_bus.dma_bits = 32; 118d71896a7SEmmanuel Vadot 119d71896a7SEmmanuel Vadot /* get all DMA memory */ 120d71896a7SEmmanuel Vadot if (usb_bus_mem_alloc_all(&sc->ohci_sc.sc_bus, 121d71896a7SEmmanuel Vadot USB_GET_DMA_TAG(dev), &ohci_iterate_hw_softc)) { 122d71896a7SEmmanuel Vadot return (ENOMEM); 123d71896a7SEmmanuel Vadot } 124d71896a7SEmmanuel Vadot 125d71896a7SEmmanuel Vadot rid = 0; 126d71896a7SEmmanuel Vadot sc->ohci_sc.sc_io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 127d71896a7SEmmanuel Vadot &rid, RF_ACTIVE); 128d71896a7SEmmanuel Vadot if (sc->ohci_sc.sc_io_res == 0) { 129d71896a7SEmmanuel Vadot err = ENOMEM; 130d71896a7SEmmanuel Vadot goto error; 131d71896a7SEmmanuel Vadot } 132d71896a7SEmmanuel Vadot 133d71896a7SEmmanuel Vadot sc->ohci_sc.sc_io_tag = rman_get_bustag(sc->ohci_sc.sc_io_res); 134d71896a7SEmmanuel Vadot sc->ohci_sc.sc_io_hdl = rman_get_bushandle(sc->ohci_sc.sc_io_res); 135d71896a7SEmmanuel Vadot sc->ohci_sc.sc_io_size = rman_get_size(sc->ohci_sc.sc_io_res); 136d71896a7SEmmanuel Vadot 137d71896a7SEmmanuel Vadot rid = 0; 138d71896a7SEmmanuel Vadot sc->ohci_sc.sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 139d71896a7SEmmanuel Vadot RF_ACTIVE); 140d71896a7SEmmanuel Vadot if (sc->ohci_sc.sc_irq_res == 0) { 141d71896a7SEmmanuel Vadot err = ENXIO; 142d71896a7SEmmanuel Vadot goto error; 143d71896a7SEmmanuel Vadot } 1445b56413dSWarner Losh sc->ohci_sc.sc_bus.bdev = device_add_child(dev, "usbus", DEVICE_UNIT_ANY); 145d71896a7SEmmanuel Vadot if (sc->ohci_sc.sc_bus.bdev == 0) { 146d71896a7SEmmanuel Vadot err = ENXIO; 147d71896a7SEmmanuel Vadot goto error; 148d71896a7SEmmanuel Vadot } 149d71896a7SEmmanuel Vadot device_set_ivars(sc->ohci_sc.sc_bus.bdev, &sc->ohci_sc.sc_bus); 150d71896a7SEmmanuel Vadot 151d71896a7SEmmanuel Vadot strlcpy(sc->ohci_sc.sc_vendor, "Generic", 152d71896a7SEmmanuel Vadot sizeof(sc->ohci_sc.sc_vendor)); 153d71896a7SEmmanuel Vadot 154d71896a7SEmmanuel Vadot err = bus_setup_intr(dev, sc->ohci_sc.sc_irq_res, 155d71896a7SEmmanuel Vadot INTR_TYPE_BIO | INTR_MPSAFE, NULL, 156d71896a7SEmmanuel Vadot (driver_intr_t *)ohci_interrupt, sc, &sc->ohci_sc.sc_intr_hdl); 157d71896a7SEmmanuel Vadot if (err) { 158d71896a7SEmmanuel Vadot sc->ohci_sc.sc_intr_hdl = NULL; 159d71896a7SEmmanuel Vadot goto error; 160d71896a7SEmmanuel Vadot } 161d71896a7SEmmanuel Vadot 162d71896a7SEmmanuel Vadot TAILQ_INIT(&sc->clk_list); 163d71896a7SEmmanuel Vadot /* Enable clock */ 164dac93553SMichal Meloun for (off = 0; clk_get_by_ofw_index(dev, 0, off, &clk) == 0; off++) { 165d71896a7SEmmanuel Vadot err = clk_enable(clk); 166d71896a7SEmmanuel Vadot if (err != 0) { 167d71896a7SEmmanuel Vadot device_printf(dev, "Could not enable clock %s\n", 168d71896a7SEmmanuel Vadot clk_get_name(clk)); 169d71896a7SEmmanuel Vadot goto error; 170d71896a7SEmmanuel Vadot } 1716e2392aeSHans Petter Selasky clkp = malloc(sizeof(*clkp), M_DEVBUF, M_WAITOK | M_ZERO); 172d71896a7SEmmanuel Vadot clkp->clk = clk; 173d71896a7SEmmanuel Vadot TAILQ_INSERT_TAIL(&sc->clk_list, clkp, next); 174d71896a7SEmmanuel Vadot } 175d71896a7SEmmanuel Vadot 176d71896a7SEmmanuel Vadot /* De-assert reset */ 177150c95edSEmmanuel Vadot TAILQ_INIT(&sc->rst_list); 178150c95edSEmmanuel Vadot for (off = 0; hwreset_get_by_ofw_idx(dev, 0, off, &rst) == 0; off++) { 179150c95edSEmmanuel Vadot err = hwreset_deassert(rst); 180d71896a7SEmmanuel Vadot if (err != 0) { 181150c95edSEmmanuel Vadot device_printf(dev, "Could not de-assert reset\n"); 182d71896a7SEmmanuel Vadot goto error; 183d71896a7SEmmanuel Vadot } 184150c95edSEmmanuel Vadot rstp = malloc(sizeof(*rstp), M_DEVBUF, M_WAITOK | M_ZERO); 185150c95edSEmmanuel Vadot rstp->rst = rst; 186150c95edSEmmanuel Vadot TAILQ_INSERT_TAIL(&sc->rst_list, rstp, next); 187d71896a7SEmmanuel Vadot } 188627c360fSJared McNeill 189627c360fSJared McNeill /* Enable phy */ 190150c95edSEmmanuel Vadot TAILQ_INIT(&sc->phy_list); 191150c95edSEmmanuel Vadot for (off = 0; phy_get_by_ofw_idx(dev, 0, off, &phy) == 0; off++) { 192150c95edSEmmanuel Vadot err = phy_usb_set_mode(phy, PHY_USB_MODE_HOST); 193150c95edSEmmanuel Vadot if (err != 0) { 194150c95edSEmmanuel Vadot device_printf(dev, "Could not set phy to host mode\n"); 195150c95edSEmmanuel Vadot goto error; 196150c95edSEmmanuel Vadot } 197150c95edSEmmanuel Vadot err = phy_enable(phy); 198627c360fSJared McNeill if (err != 0) { 199627c360fSJared McNeill device_printf(dev, "Could not enable phy\n"); 200627c360fSJared McNeill goto error; 201627c360fSJared McNeill } 202150c95edSEmmanuel Vadot phyp = malloc(sizeof(*phyp), M_DEVBUF, M_WAITOK | M_ZERO); 203150c95edSEmmanuel Vadot phyp->phy = phy; 204150c95edSEmmanuel Vadot TAILQ_INSERT_TAIL(&sc->phy_list, phyp, next); 205627c360fSJared McNeill } 206d71896a7SEmmanuel Vadot 207d71896a7SEmmanuel Vadot if (GENERIC_USB_INIT(dev) != 0) { 208d71896a7SEmmanuel Vadot err = ENXIO; 209d71896a7SEmmanuel Vadot goto error; 210d71896a7SEmmanuel Vadot } 211d71896a7SEmmanuel Vadot 212d71896a7SEmmanuel Vadot err = ohci_init(&sc->ohci_sc); 213d71896a7SEmmanuel Vadot if (err == 0) 214d71896a7SEmmanuel Vadot err = device_probe_and_attach(sc->ohci_sc.sc_bus.bdev); 215d71896a7SEmmanuel Vadot if (err) 216d71896a7SEmmanuel Vadot goto error; 217d71896a7SEmmanuel Vadot 218d71896a7SEmmanuel Vadot return (0); 219d71896a7SEmmanuel Vadot error: 220d71896a7SEmmanuel Vadot generic_ohci_detach(dev); 221d71896a7SEmmanuel Vadot return (err); 222d71896a7SEmmanuel Vadot } 223d71896a7SEmmanuel Vadot 224d71896a7SEmmanuel Vadot static int 225d71896a7SEmmanuel Vadot generic_ohci_detach(device_t dev) 226d71896a7SEmmanuel Vadot { 227d71896a7SEmmanuel Vadot struct generic_ohci_softc *sc = device_get_softc(dev); 228d71896a7SEmmanuel Vadot int err; 229d71896a7SEmmanuel Vadot struct clk_list *clk, *clk_tmp; 230150c95edSEmmanuel Vadot struct phy_list *phy, *phy_tmp; 231150c95edSEmmanuel Vadot struct hwrst_list *rst, *rst_tmp; 232d71896a7SEmmanuel Vadot 233d71896a7SEmmanuel Vadot /* during module unload there are lots of children leftover */ 234*3ddaf820SJohn Baldwin err = bus_generic_detach(dev); 235*3ddaf820SJohn Baldwin if (err != 0) 236*3ddaf820SJohn Baldwin return (err); 237d71896a7SEmmanuel Vadot 238d71896a7SEmmanuel Vadot /* 239d71896a7SEmmanuel Vadot * Put the controller into reset, then disable clocks and do 240d71896a7SEmmanuel Vadot * the MI tear down. We have to disable the clocks/hardware 241d71896a7SEmmanuel Vadot * after we do the rest of the teardown. We also disable the 242d71896a7SEmmanuel Vadot * clocks in the opposite order we acquire them, but that 243d71896a7SEmmanuel Vadot * doesn't seem to be absolutely necessary. We free up the 244d71896a7SEmmanuel Vadot * clocks after we disable them, so the system could, in 245d71896a7SEmmanuel Vadot * theory, reuse them. 246d71896a7SEmmanuel Vadot */ 247d71896a7SEmmanuel Vadot bus_space_write_4(sc->ohci_sc.sc_io_tag, sc->ohci_sc.sc_io_hdl, 248d71896a7SEmmanuel Vadot OHCI_CONTROL, 0); 249d71896a7SEmmanuel Vadot 250d71896a7SEmmanuel Vadot if (sc->ohci_sc.sc_irq_res && sc->ohci_sc.sc_intr_hdl) { 251d71896a7SEmmanuel Vadot /* 252d71896a7SEmmanuel Vadot * only call ohci_detach() after ohci_init() 253d71896a7SEmmanuel Vadot */ 254d71896a7SEmmanuel Vadot ohci_detach(&sc->ohci_sc); 255d71896a7SEmmanuel Vadot 256d71896a7SEmmanuel Vadot err = bus_teardown_intr(dev, sc->ohci_sc.sc_irq_res, 257d71896a7SEmmanuel Vadot sc->ohci_sc.sc_intr_hdl); 258d71896a7SEmmanuel Vadot sc->ohci_sc.sc_intr_hdl = NULL; 259d71896a7SEmmanuel Vadot } 260d71896a7SEmmanuel Vadot if (sc->ohci_sc.sc_irq_res) { 261d71896a7SEmmanuel Vadot bus_release_resource(dev, SYS_RES_IRQ, 0, 262d71896a7SEmmanuel Vadot sc->ohci_sc.sc_irq_res); 263d71896a7SEmmanuel Vadot sc->ohci_sc.sc_irq_res = NULL; 264d71896a7SEmmanuel Vadot } 265d71896a7SEmmanuel Vadot if (sc->ohci_sc.sc_io_res) { 266d71896a7SEmmanuel Vadot bus_release_resource(dev, SYS_RES_MEMORY, 0, 267d71896a7SEmmanuel Vadot sc->ohci_sc.sc_io_res); 268d71896a7SEmmanuel Vadot sc->ohci_sc.sc_io_res = NULL; 269d71896a7SEmmanuel Vadot } 270d71896a7SEmmanuel Vadot usb_bus_mem_free_all(&sc->ohci_sc.sc_bus, &ohci_iterate_hw_softc); 271d71896a7SEmmanuel Vadot 272627c360fSJared McNeill /* Disable phy */ 273150c95edSEmmanuel Vadot TAILQ_FOREACH_SAFE(phy, &sc->phy_list, next, phy_tmp) { 274150c95edSEmmanuel Vadot err = phy_disable(phy->phy); 275627c360fSJared McNeill if (err != 0) 276627c360fSJared McNeill device_printf(dev, "Could not disable phy\n"); 277150c95edSEmmanuel Vadot phy_release(phy->phy); 278150c95edSEmmanuel Vadot TAILQ_REMOVE(&sc->phy_list, phy, next); 279150c95edSEmmanuel Vadot free(phy, M_DEVBUF); 280150c95edSEmmanuel Vadot } 281150c95edSEmmanuel Vadot 282150c95edSEmmanuel Vadot /* Assert reset */ 283150c95edSEmmanuel Vadot TAILQ_FOREACH_SAFE(rst, &sc->rst_list, next, rst_tmp) { 284150c95edSEmmanuel Vadot hwreset_assert(rst->rst); 285150c95edSEmmanuel Vadot hwreset_release(rst->rst); 286150c95edSEmmanuel Vadot TAILQ_REMOVE(&sc->rst_list, rst, next); 287150c95edSEmmanuel Vadot free(rst, M_DEVBUF); 288627c360fSJared McNeill } 289627c360fSJared McNeill 290d71896a7SEmmanuel Vadot /* Disable clock */ 291d71896a7SEmmanuel Vadot TAILQ_FOREACH_SAFE(clk, &sc->clk_list, next, clk_tmp) { 292d71896a7SEmmanuel Vadot err = clk_disable(clk->clk); 293d71896a7SEmmanuel Vadot if (err != 0) 294d71896a7SEmmanuel Vadot device_printf(dev, "Could not disable clock %s\n", 295d71896a7SEmmanuel Vadot clk_get_name(clk->clk)); 296d71896a7SEmmanuel Vadot err = clk_release(clk->clk); 297d71896a7SEmmanuel Vadot if (err != 0) 298d71896a7SEmmanuel Vadot device_printf(dev, "Could not release clock %s\n", 299d71896a7SEmmanuel Vadot clk_get_name(clk->clk)); 300d71896a7SEmmanuel Vadot TAILQ_REMOVE(&sc->clk_list, clk, next); 301d71896a7SEmmanuel Vadot free(clk, M_DEVBUF); 302d71896a7SEmmanuel Vadot } 303d71896a7SEmmanuel Vadot 304d71896a7SEmmanuel Vadot if (GENERIC_USB_DEINIT(dev) != 0) 305d71896a7SEmmanuel Vadot return (ENXIO); 306d71896a7SEmmanuel Vadot 307d71896a7SEmmanuel Vadot return (0); 308d71896a7SEmmanuel Vadot } 309d71896a7SEmmanuel Vadot 310d71896a7SEmmanuel Vadot static device_method_t generic_ohci_methods[] = { 311d71896a7SEmmanuel Vadot /* Device interface */ 312d71896a7SEmmanuel Vadot DEVMETHOD(device_probe, generic_ohci_probe), 313d71896a7SEmmanuel Vadot DEVMETHOD(device_attach, generic_ohci_attach), 314d71896a7SEmmanuel Vadot DEVMETHOD(device_detach, generic_ohci_detach), 315d71896a7SEmmanuel Vadot 316d71896a7SEmmanuel Vadot DEVMETHOD(device_suspend, bus_generic_suspend), 317d71896a7SEmmanuel Vadot DEVMETHOD(device_resume, bus_generic_resume), 318d71896a7SEmmanuel Vadot DEVMETHOD(device_shutdown, bus_generic_shutdown), 319d71896a7SEmmanuel Vadot 320d71896a7SEmmanuel Vadot DEVMETHOD_END 321d71896a7SEmmanuel Vadot }; 322d71896a7SEmmanuel Vadot 323d71896a7SEmmanuel Vadot driver_t generic_ohci_driver = { 324d71896a7SEmmanuel Vadot .name = "ohci", 325d71896a7SEmmanuel Vadot .methods = generic_ohci_methods, 326d71896a7SEmmanuel Vadot .size = sizeof(struct generic_ohci_softc), 327d71896a7SEmmanuel Vadot }; 328d71896a7SEmmanuel Vadot 329bc9372d7SJohn Baldwin DRIVER_MODULE(ohci, simplebus, generic_ohci_driver, 0, 0); 330d71896a7SEmmanuel Vadot MODULE_DEPEND(ohci, usb, 1, 1, 1); 331