musb_otg_atmelarm.c revision 184610
1/* $FreeBSD: head/sys/dev/usb2/controller/musb2_otg_atmelarm.c 184610 2008-11-04 02:31:03Z alfred $ */ 2/*- 3 * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <dev/usb2/include/usb2_mfunc.h> 28#include <dev/usb2/include/usb2_defs.h> 29#include <dev/usb2/include/usb2_standard.h> 30 31#include <dev/usb2/core/usb2_core.h> 32#include <dev/usb2/core/usb2_busdma.h> 33#include <dev/usb2/core/usb2_process.h> 34#include <dev/usb2/core/usb2_config_td.h> 35#include <dev/usb2/core/usb2_sw_transfer.h> 36#include <dev/usb2/core/usb2_util.h> 37 38#include <dev/usb2/controller/usb2_controller.h> 39#include <dev/usb2/controller/usb2_bus.h> 40#include <dev/usb2/controller/musb2_otg.h> 41 42#include <sys/rman.h> 43 44static device_probe_t musbotg_probe; 45static device_attach_t musbotg_attach; 46static device_detach_t musbotg_detach; 47static device_shutdown_t musbotg_shutdown; 48 49struct musbotg_super_softc { 50 struct musbotg_softc sc_otg; /* must be first */ 51}; 52 53static void 54musbotg_vbus_interrupt(struct musbotg_super_softc *sc) 55{ 56 uint8_t vbus_val = 1; /* fake VBUS on - TODO */ 57 58 /* just forward it */ 59 60 (sc->sc_otg.sc_bus.methods->vbus_interrupt) 61 (&sc->sc_otg.sc_bus, vbus_val); 62 return; 63} 64 65static void 66musbotg_clocks_on(void *arg) 67{ 68#if 0 69 struct musbotg_super_softc *sc = arg; 70 71#endif 72 73 return; 74} 75 76static void 77musbotg_clocks_off(void *arg) 78{ 79#if 0 80 struct musbotg_super_softc *sc = arg; 81 82#endif 83 84 return; 85} 86 87static int 88musbotg_probe(device_t dev) 89{ 90 device_set_desc(dev, "MUSB OTG integrated USB controller"); 91 return (0); 92} 93 94static int 95musbotg_attach(device_t dev) 96{ 97 struct musbotg_super_softc *sc = device_get_softc(dev); 98 int err; 99 int rid; 100 101 if (sc == NULL) { 102 return (ENXIO); 103 } 104 /* setup MUSB OTG USB controller interface softc */ 105 106 sc->sc_otg.sc_clocks_on = &musbotg_clocks_on; 107 sc->sc_otg.sc_clocks_off = &musbotg_clocks_off; 108 sc->sc_otg.sc_clocks_arg = sc; 109 110 /* get all DMA memory */ 111 112 if (usb2_bus_mem_alloc_all(&sc->sc_otg.sc_bus, 113 USB_GET_DMA_TAG(dev), NULL)) { 114 return (ENOMEM); 115 } 116 rid = 0; 117 sc->sc_otg.sc_io_res = 118 bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 119 120 if (!(sc->sc_otg.sc_io_res)) { 121 err = ENOMEM; 122 goto error; 123 } 124 sc->sc_otg.sc_io_tag = rman_get_bustag(sc->sc_otg.sc_io_res); 125 sc->sc_otg.sc_io_hdl = rman_get_bushandle(sc->sc_otg.sc_io_res); 126 sc->sc_otg.sc_io_size = rman_get_size(sc->sc_otg.sc_io_res); 127 128 rid = 0; 129 sc->sc_otg.sc_irq_res = 130 bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); 131 if (!(sc->sc_otg.sc_irq_res)) { 132 goto error; 133 } 134 sc->sc_otg.sc_bus.bdev = device_add_child(dev, "usbus", -1); 135 if (!(sc->sc_otg.sc_bus.bdev)) { 136 goto error; 137 } 138 device_set_ivars(sc->sc_otg.sc_bus.bdev, &sc->sc_otg.sc_bus); 139 140 err = usb2_config_td_setup(&sc->sc_otg.sc_config_td, sc, 141 &sc->sc_otg.sc_bus.mtx, NULL, 0, 4); 142 if (err) { 143 device_printf(dev, "could not setup config thread!\n"); 144 goto error; 145 } 146#if (__FreeBSD_version >= 700031) 147 err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 148 NULL, (void *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl); 149#else 150 err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 151 (void *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl); 152#endif 153 if (err) { 154 sc->sc_otg.sc_intr_hdl = NULL; 155 goto error; 156 } 157 err = musbotg_init(&sc->sc_otg); 158 if (!err) { 159 err = device_probe_and_attach(sc->sc_otg.sc_bus.bdev); 160 } 161 if (err) { 162 goto error; 163 } else { 164 /* poll VBUS one time */ 165 musbotg_vbus_interrupt(sc); 166 } 167 return (0); 168 169error: 170 musbotg_detach(dev); 171 return (ENXIO); 172} 173 174static int 175musbotg_detach(device_t dev) 176{ 177 struct musbotg_super_softc *sc = device_get_softc(dev); 178 device_t bdev; 179 int err; 180 181 if (sc->sc_otg.sc_bus.bdev) { 182 bdev = sc->sc_otg.sc_bus.bdev; 183 device_detach(bdev); 184 device_delete_child(dev, bdev); 185 } 186 /* during module unload there are lots of children leftover */ 187 device_delete_all_children(dev); 188 189 if (sc->sc_otg.sc_irq_res && sc->sc_otg.sc_intr_hdl) { 190 /* 191 * only call musbotg_uninit() after musbotg_init() 192 */ 193 musbotg_uninit(&sc->sc_otg); 194 195 err = bus_teardown_intr(dev, sc->sc_otg.sc_irq_res, 196 sc->sc_otg.sc_intr_hdl); 197 sc->sc_otg.sc_intr_hdl = NULL; 198 } 199 /* free IRQ channel, if any */ 200 if (sc->sc_otg.sc_irq_res) { 201 bus_release_resource(dev, SYS_RES_IRQ, 0, 202 sc->sc_otg.sc_irq_res); 203 sc->sc_otg.sc_irq_res = NULL; 204 } 205 /* free memory resource, if any */ 206 if (sc->sc_otg.sc_io_res) { 207 bus_release_resource(dev, SYS_RES_MEMORY, 0, 208 sc->sc_otg.sc_io_res); 209 sc->sc_otg.sc_io_res = NULL; 210 } 211 usb2_config_td_unsetup(&sc->sc_otg.sc_config_td); 212 213 usb2_bus_mem_free_all(&sc->sc_otg.sc_bus, NULL); 214 215 return (0); 216} 217 218static int 219musbotg_shutdown(device_t dev) 220{ 221 struct musbotg_super_softc *sc = device_get_softc(dev); 222 int err; 223 224 err = bus_generic_shutdown(dev); 225 if (err) 226 return (err); 227 228 musbotg_uninit(&sc->sc_otg); 229 230 return (0); 231} 232 233static device_method_t musbotg_methods[] = { 234 /* Device interface */ 235 DEVMETHOD(device_probe, musbotg_probe), 236 DEVMETHOD(device_attach, musbotg_attach), 237 DEVMETHOD(device_detach, musbotg_detach), 238 DEVMETHOD(device_shutdown, musbotg_shutdown), 239 240 /* Bus interface */ 241 DEVMETHOD(bus_print_child, bus_generic_print_child), 242 243 {0, 0} 244}; 245 246static driver_t musbotg_driver = { 247 "musbotg", 248 musbotg_methods, 249 sizeof(struct musbotg_super_softc), 250}; 251 252static devclass_t musbotg_devclass; 253 254DRIVER_MODULE(musbotg, atmelarm, musbotg_driver, musbotg_devclass, 0, 0); 255MODULE_DEPEND(musbotg, usb2_controller, 1, 1, 1); 256MODULE_DEPEND(musbotg, usb2_core, 1, 1, 1); 257