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