musb_otg_atmelarm.c revision 187172
1/* $FreeBSD: head/sys/dev/usb2/controller/musb2_otg_atmelarm.c 187172 2009-01-13 19:03:01Z thompsa $ */ 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_sw_transfer.h> 35#include <dev/usb2/core/usb2_util.h> 36 37#include <dev/usb2/controller/usb2_controller.h> 38#include <dev/usb2/controller/usb2_bus.h> 39#include <dev/usb2/controller/musb2_otg.h> 40 41#include <sys/rman.h> 42 43static device_probe_t musbotg_probe; 44static device_attach_t musbotg_attach; 45static device_detach_t musbotg_detach; 46static device_shutdown_t musbotg_shutdown; 47 48struct musbotg_super_softc { 49 struct musbotg_softc sc_otg; /* must be first */ 50}; 51 52static void 53musbotg_vbus_interrupt(struct musbotg_super_softc *sc) 54{ 55 uint8_t vbus_val = 1; /* fake VBUS on - TODO */ 56 57 /* just forward it */ 58 59 (sc->sc_otg.sc_bus.methods->vbus_interrupt) 60 (&sc->sc_otg.sc_bus, vbus_val); 61} 62 63static void 64musbotg_clocks_on(void *arg) 65{ 66#if 0 67 struct musbotg_super_softc *sc = arg; 68 69#endif 70} 71 72static void 73musbotg_clocks_off(void *arg) 74{ 75#if 0 76 struct musbotg_super_softc *sc = arg; 77 78#endif 79} 80 81static int 82musbotg_probe(device_t dev) 83{ 84 device_set_desc(dev, "MUSB OTG integrated USB controller"); 85 return (0); 86} 87 88static int 89musbotg_attach(device_t dev) 90{ 91 struct musbotg_super_softc *sc = device_get_softc(dev); 92 int err; 93 int rid; 94 95 if (sc == NULL) { 96 return (ENXIO); 97 } 98 /* setup MUSB OTG USB controller interface softc */ 99 100 sc->sc_otg.sc_clocks_on = &musbotg_clocks_on; 101 sc->sc_otg.sc_clocks_off = &musbotg_clocks_off; 102 sc->sc_otg.sc_clocks_arg = sc; 103 104 /* initialise some bus fields */ 105 sc->sc_otg.sc_bus.parent = dev; 106 sc->sc_otg.sc_bus.devices = sc->sc_otg.sc_devices; 107 sc->sc_otg.sc_bus.devices_max = MUSB2_MAX_DEVICES; 108 109 /* get all DMA memory */ 110 if (usb2_bus_mem_alloc_all(&sc->sc_otg.sc_bus, 111 USB_GET_DMA_TAG(dev), NULL)) { 112 return (ENOMEM); 113 } 114 rid = 0; 115 sc->sc_otg.sc_io_res = 116 bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 117 118 if (!(sc->sc_otg.sc_io_res)) { 119 err = ENOMEM; 120 goto error; 121 } 122 sc->sc_otg.sc_io_tag = rman_get_bustag(sc->sc_otg.sc_io_res); 123 sc->sc_otg.sc_io_hdl = rman_get_bushandle(sc->sc_otg.sc_io_res); 124 sc->sc_otg.sc_io_size = rman_get_size(sc->sc_otg.sc_io_res); 125 126 rid = 0; 127 sc->sc_otg.sc_irq_res = 128 bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); 129 if (!(sc->sc_otg.sc_irq_res)) { 130 goto error; 131 } 132 sc->sc_otg.sc_bus.bdev = device_add_child(dev, "usbus", -1); 133 if (!(sc->sc_otg.sc_bus.bdev)) { 134 goto error; 135 } 136 device_set_ivars(sc->sc_otg.sc_bus.bdev, &sc->sc_otg.sc_bus); 137 138#if (__FreeBSD_version >= 700031) 139 err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 140 NULL, (void *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl); 141#else 142 err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 143 (void *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl); 144#endif 145 if (err) { 146 sc->sc_otg.sc_intr_hdl = NULL; 147 goto error; 148 } 149 err = musbotg_init(&sc->sc_otg); 150 if (!err) { 151 err = device_probe_and_attach(sc->sc_otg.sc_bus.bdev); 152 } 153 if (err) { 154 goto error; 155 } else { 156 /* poll VBUS one time */ 157 musbotg_vbus_interrupt(sc); 158 } 159 return (0); 160 161error: 162 musbotg_detach(dev); 163 return (ENXIO); 164} 165 166static int 167musbotg_detach(device_t dev) 168{ 169 struct musbotg_super_softc *sc = device_get_softc(dev); 170 device_t bdev; 171 int err; 172 173 if (sc->sc_otg.sc_bus.bdev) { 174 bdev = sc->sc_otg.sc_bus.bdev; 175 device_detach(bdev); 176 device_delete_child(dev, bdev); 177 } 178 /* during module unload there are lots of children leftover */ 179 device_delete_all_children(dev); 180 181 if (sc->sc_otg.sc_irq_res && sc->sc_otg.sc_intr_hdl) { 182 /* 183 * only call musbotg_uninit() after musbotg_init() 184 */ 185 musbotg_uninit(&sc->sc_otg); 186 187 err = bus_teardown_intr(dev, sc->sc_otg.sc_irq_res, 188 sc->sc_otg.sc_intr_hdl); 189 sc->sc_otg.sc_intr_hdl = NULL; 190 } 191 /* free IRQ channel, if any */ 192 if (sc->sc_otg.sc_irq_res) { 193 bus_release_resource(dev, SYS_RES_IRQ, 0, 194 sc->sc_otg.sc_irq_res); 195 sc->sc_otg.sc_irq_res = NULL; 196 } 197 /* free memory resource, if any */ 198 if (sc->sc_otg.sc_io_res) { 199 bus_release_resource(dev, SYS_RES_MEMORY, 0, 200 sc->sc_otg.sc_io_res); 201 sc->sc_otg.sc_io_res = NULL; 202 } 203 usb2_bus_mem_free_all(&sc->sc_otg.sc_bus, NULL); 204 205 return (0); 206} 207 208static int 209musbotg_shutdown(device_t dev) 210{ 211 struct musbotg_super_softc *sc = device_get_softc(dev); 212 int err; 213 214 err = bus_generic_shutdown(dev); 215 if (err) 216 return (err); 217 218 musbotg_uninit(&sc->sc_otg); 219 220 return (0); 221} 222 223static device_method_t musbotg_methods[] = { 224 /* Device interface */ 225 DEVMETHOD(device_probe, musbotg_probe), 226 DEVMETHOD(device_attach, musbotg_attach), 227 DEVMETHOD(device_detach, musbotg_detach), 228 DEVMETHOD(device_shutdown, musbotg_shutdown), 229 230 /* Bus interface */ 231 DEVMETHOD(bus_print_child, bus_generic_print_child), 232 233 {0, 0} 234}; 235 236static driver_t musbotg_driver = { 237 "musbotg", 238 musbotg_methods, 239 sizeof(struct musbotg_super_softc), 240}; 241 242static devclass_t musbotg_devclass; 243 244DRIVER_MODULE(musbotg, atmelarm, musbotg_driver, musbotg_devclass, 0, 0); 245MODULE_DEPEND(musbotg, usb2_controller, 1, 1, 1); 246MODULE_DEPEND(musbotg, usb2_core, 1, 1, 1); 247