musb_otg_atmelarm.c revision 190174
1133SN/A/* $FreeBSD: head/sys/dev/usb/controller/musb_otg_atmelarm.c 190174 2009-03-20 19:04:31Z thompsa $ */ 213147SN/A/*- 3133SN/A * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. 4133SN/A * 5133SN/A * Redistribution and use in source and binary forms, with or without 6133SN/A * modification, are permitted provided that the following conditions 7133SN/A * are met: 8133SN/A * 1. Redistributions of source code must retain the above copyright 9133SN/A * notice, this list of conditions and the following disclaimer. 10133SN/A * 2. Redistributions in binary form must reproduce the above copyright 11133SN/A * notice, this list of conditions and the following disclaimer in the 12133SN/A * documentation and/or other materials provided with the distribution. 13133SN/A * 14133SN/A * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15133SN/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16133SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17133SN/A * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18133SN/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 191472SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 201472SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 211472SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22133SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23133SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24133SN/A * SUCH DAMAGE. 251879SN/A */ 261879SN/A 271879SN/A#include <dev/usb/usb_mfunc.h> 28133SN/A#include <dev/usb/usb.h> 29133SN/A 30133SN/A#include <dev/usb/usb_core.h> 31133SN/A#include <dev/usb/usb_busdma.h> 32133SN/A#include <dev/usb/usb_process.h> 33133SN/A#include <dev/usb/usb_sw_transfer.h> 34133SN/A#include <dev/usb/usb_util.h> 35133SN/A 36133SN/A#include <dev/usb/usb_controller.h> 37133SN/A#include <dev/usb/usb_bus.h> 38133SN/A#include <dev/usb/controller/musb_otg.h> 39133SN/A 40133SN/A#include <sys/rman.h> 41133SN/A 42133SN/Astatic device_probe_t musbotg_probe; 43133SN/Astatic device_attach_t musbotg_attach; 44133SN/Astatic device_detach_t musbotg_detach; 45133SN/Astatic device_shutdown_t musbotg_shutdown; 46133SN/A 47133SN/Astruct musbotg_super_softc { 48133SN/A struct musbotg_softc sc_otg; /* must be first */ 49133SN/A}; 50133SN/A 51133SN/Astatic void 5213147SN/Amusbotg_vbus_poll(struct musbotg_super_softc *sc) 531999SN/A{ 5413512Seosterlund uint8_t vbus_val = 1; /* fake VBUS on - TODO */ 5513512Seosterlund 5613512Seosterlund /* just forward it */ 5713512Seosterlund musbotg_vbus_interrupt(&sc->sc_otg, vbus_val); 5813512Seosterlund} 5913512Seosterlund 6013512Seosterlundstatic void 6113512Seosterlundmusbotg_clocks_on(void *arg) 6213512Seosterlund{ 6313512Seosterlund#if 0 6413512Seosterlund struct musbotg_super_softc *sc = arg; 6513529Sglaubitz 6613529Sglaubitz#endif 6713512Seosterlund} 6813512Seosterlund 69133SN/Astatic void 70133SN/Amusbotg_clocks_off(void *arg) 71133SN/A{ 72133SN/A#if 0 73133SN/A struct musbotg_super_softc *sc = arg; 74133SN/A 75133SN/A#endif 76133SN/A} 77133SN/A 78133SN/Astatic int 79133SN/Amusbotg_probe(device_t dev) 80133SN/A{ 81133SN/A device_set_desc(dev, "MUSB OTG integrated USB controller"); 82133SN/A return (0); 83133SN/A} 8413529Sglaubitz 8513512Seosterlundstatic int 8613512Seosterlundmusbotg_attach(device_t dev) 8713529Sglaubitz{ 8813529Sglaubitz struct musbotg_super_softc *sc = device_get_softc(dev); 8913512Seosterlund int err; 9013512Seosterlund int rid; 91133SN/A 92133SN/A /* setup MUSB OTG USB controller interface softc */ 93133SN/A sc->sc_otg.sc_clocks_on = &musbotg_clocks_on; 946378SN/A sc->sc_otg.sc_clocks_off = &musbotg_clocks_off; 95133SN/A sc->sc_otg.sc_clocks_arg = sc; 96133SN/A 97133SN/A /* initialise some bus fields */ 98133SN/A sc->sc_otg.sc_bus.parent = dev; 996378SN/A sc->sc_otg.sc_bus.devices = sc->sc_otg.sc_devices; 100133SN/A sc->sc_otg.sc_bus.devices_max = MUSB2_MAX_DEVICES; 101133SN/A 102133SN/A /* get all DMA memory */ 103133SN/A if (usb2_bus_mem_alloc_all(&sc->sc_otg.sc_bus, 104133SN/A USB_GET_DMA_TAG(dev), NULL)) { 105133SN/A return (ENOMEM); 106133SN/A } 107133SN/A rid = 0; 108133SN/A sc->sc_otg.sc_io_res = 109133SN/A bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 110133SN/A 111133SN/A if (!(sc->sc_otg.sc_io_res)) { 112133SN/A err = ENOMEM; 113133SN/A goto error; 114133SN/A } 115133SN/A sc->sc_otg.sc_io_tag = rman_get_bustag(sc->sc_otg.sc_io_res); 116133SN/A sc->sc_otg.sc_io_hdl = rman_get_bushandle(sc->sc_otg.sc_io_res); 117133SN/A sc->sc_otg.sc_io_size = rman_get_size(sc->sc_otg.sc_io_res); 118133SN/A 119133SN/A rid = 0; 120133SN/A sc->sc_otg.sc_irq_res = 121133SN/A bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); 122133SN/A if (!(sc->sc_otg.sc_irq_res)) { 123133SN/A goto error; 124133SN/A } 125133SN/A sc->sc_otg.sc_bus.bdev = device_add_child(dev, "usbus", -1); 126133SN/A if (!(sc->sc_otg.sc_bus.bdev)) { 127133SN/A goto error; 128133SN/A } 129133SN/A device_set_ivars(sc->sc_otg.sc_bus.bdev, &sc->sc_otg.sc_bus); 130133SN/A 131133SN/A#if (__FreeBSD_version >= 700031) 132133SN/A err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 133133SN/A NULL, (void *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl); 134133SN/A#else 135133SN/A err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 136133SN/A (void *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl); 137133SN/A#endif 13813477Seosterlund if (err) { 13913477Seosterlund sc->sc_otg.sc_intr_hdl = NULL; 14013477Seosterlund goto error; 141133SN/A } 14213477Seosterlund err = musbotg_init(&sc->sc_otg); 14313477Seosterlund if (!err) { 14413477Seosterlund err = device_probe_and_attach(sc->sc_otg.sc_bus.bdev); 14513477Seosterlund } 14613477Seosterlund if (err) { 14713477Seosterlund goto error; 14813477Seosterlund } else { 14913477Seosterlund /* poll VBUS one time */ 150133SN/A musbotg_vbus_poll(sc); 151133SN/A } 152133SN/A return (0); 153133SN/A 154133SN/Aerror: 155133SN/A musbotg_detach(dev); 156133SN/A return (ENXIO); 157133SN/A} 15813477Seosterlund 15913477Seosterlundstatic int 16013477Seosterlundmusbotg_detach(device_t dev) 16113477Seosterlund{ 16213477Seosterlund struct musbotg_super_softc *sc = device_get_softc(dev); 16313477Seosterlund device_t bdev; 16413477Seosterlund int err; 16513477Seosterlund 166133SN/A if (sc->sc_otg.sc_bus.bdev) { 167133SN/A bdev = sc->sc_otg.sc_bus.bdev; 168133SN/A device_detach(bdev); 169133SN/A device_delete_child(dev, bdev); 170133SN/A } 171133SN/A /* during module unload there are lots of children leftover */ 172133SN/A device_delete_all_children(dev); 173133SN/A 1741879SN/A if (sc->sc_otg.sc_irq_res && sc->sc_otg.sc_intr_hdl) { 175 /* 176 * only call musbotg_uninit() after musbotg_init() 177 */ 178 musbotg_uninit(&sc->sc_otg); 179 180 err = bus_teardown_intr(dev, sc->sc_otg.sc_irq_res, 181 sc->sc_otg.sc_intr_hdl); 182 sc->sc_otg.sc_intr_hdl = NULL; 183 } 184 /* free IRQ channel, if any */ 185 if (sc->sc_otg.sc_irq_res) { 186 bus_release_resource(dev, SYS_RES_IRQ, 0, 187 sc->sc_otg.sc_irq_res); 188 sc->sc_otg.sc_irq_res = NULL; 189 } 190 /* free memory resource, if any */ 191 if (sc->sc_otg.sc_io_res) { 192 bus_release_resource(dev, SYS_RES_MEMORY, 0, 193 sc->sc_otg.sc_io_res); 194 sc->sc_otg.sc_io_res = NULL; 195 } 196 usb2_bus_mem_free_all(&sc->sc_otg.sc_bus, NULL); 197 198 return (0); 199} 200 201static int 202musbotg_shutdown(device_t dev) 203{ 204 struct musbotg_super_softc *sc = device_get_softc(dev); 205 int err; 206 207 err = bus_generic_shutdown(dev); 208 if (err) 209 return (err); 210 211 musbotg_uninit(&sc->sc_otg); 212 213 return (0); 214} 215 216static device_method_t musbotg_methods[] = { 217 /* Device interface */ 218 DEVMETHOD(device_probe, musbotg_probe), 219 DEVMETHOD(device_attach, musbotg_attach), 220 DEVMETHOD(device_detach, musbotg_detach), 221 DEVMETHOD(device_shutdown, musbotg_shutdown), 222 223 /* Bus interface */ 224 DEVMETHOD(bus_print_child, bus_generic_print_child), 225 226 {0, 0} 227}; 228 229static driver_t musbotg_driver = { 230 "musbotg", 231 musbotg_methods, 232 sizeof(struct musbotg_super_softc), 233}; 234 235static devclass_t musbotg_devclass; 236 237DRIVER_MODULE(musbotg, atmelarm, musbotg_driver, musbotg_devclass, 0, 0); 238MODULE_DEPEND(musbotg, usb, 1, 1, 1); 239