musb_otg_atmelarm.c revision 190633
1210284Sjmallett/* $FreeBSD: head/sys/dev/usb/controller/musb_otg_atmelarm.c 190633 2009-04-01 20:23:47Z piso $ */ 2232812Sjmallett/*- 3215990Sjmallett * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. 4210284Sjmallett * 5210284Sjmallett * Redistribution and use in source and binary forms, with or without 6215990Sjmallett * modification, are permitted provided that the following conditions 7215990Sjmallett * are met: 8215990Sjmallett * 1. Redistributions of source code must retain the above copyright 9210284Sjmallett * notice, this list of conditions and the following disclaimer. 10215990Sjmallett * 2. Redistributions in binary form must reproduce the above copyright 11215990Sjmallett * notice, this list of conditions and the following disclaimer in the 12210284Sjmallett * documentation and/or other materials provided with the distribution. 13215990Sjmallett * 14215990Sjmallett * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15215990Sjmallett * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16215990Sjmallett * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17215990Sjmallett * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18232812Sjmallett * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19215990Sjmallett * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20215990Sjmallett * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21215990Sjmallett * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22215990Sjmallett * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23215990Sjmallett * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24215990Sjmallett * SUCH DAMAGE. 25215990Sjmallett */ 26215990Sjmallett 27215990Sjmallett#include <dev/usb/usb_mfunc.h> 28215990Sjmallett#include <dev/usb/usb.h> 29232812Sjmallett 30215990Sjmallett#include <dev/usb/usb_core.h> 31215990Sjmallett#include <dev/usb/usb_busdma.h> 32215990Sjmallett#include <dev/usb/usb_process.h> 33215990Sjmallett#include <dev/usb/usb_sw_transfer.h> 34215990Sjmallett#include <dev/usb/usb_util.h> 35215990Sjmallett 36215990Sjmallett#include <dev/usb/usb_controller.h> 37215990Sjmallett#include <dev/usb/usb_bus.h> 38210284Sjmallett#include <dev/usb/controller/musb_otg.h> 39210284Sjmallett 40215990Sjmallett#include <sys/rman.h> 41210284Sjmallett 42210284Sjmallettstatic device_probe_t musbotg_probe; 43210284Sjmallettstatic device_attach_t musbotg_attach; 44210284Sjmallettstatic device_detach_t musbotg_detach; 45210284Sjmallettstatic device_shutdown_t musbotg_shutdown; 46210284Sjmallett 47210284Sjmallettstruct musbotg_super_softc { 48210284Sjmallett struct musbotg_softc sc_otg; /* must be first */ 49210284Sjmallett}; 50210284Sjmallett 51210284Sjmallettstatic void 52210284Sjmallettmusbotg_vbus_poll(struct musbotg_super_softc *sc) 53210284Sjmallett{ 54210284Sjmallett uint8_t vbus_val = 1; /* fake VBUS on - TODO */ 55210284Sjmallett 56210284Sjmallett /* just forward it */ 57210284Sjmallett musbotg_vbus_interrupt(&sc->sc_otg, vbus_val); 58210284Sjmallett} 59210284Sjmallett 60210284Sjmallettstatic void 61210284Sjmallettmusbotg_clocks_on(void *arg) 62210284Sjmallett{ 63210284Sjmallett#if 0 64210284Sjmallett struct musbotg_super_softc *sc = arg; 65210284Sjmallett 66210284Sjmallett#endif 67210284Sjmallett} 68210284Sjmallett 69210284Sjmallettstatic void 70210284Sjmallettmusbotg_clocks_off(void *arg) 71210284Sjmallett{ 72210284Sjmallett#if 0 73210284Sjmallett struct musbotg_super_softc *sc = arg; 74210284Sjmallett 75210284Sjmallett#endif 76210284Sjmallett} 77210284Sjmallett 78210284Sjmallettstatic int 79210284Sjmallettmusbotg_probe(device_t dev) 80210284Sjmallett{ 81210284Sjmallett device_set_desc(dev, "MUSB OTG integrated USB controller"); 82210284Sjmallett return (0); 83210284Sjmallett} 84210284Sjmallett 85210284Sjmallettstatic int 86215990Sjmallettmusbotg_attach(device_t dev) 87215990Sjmallett{ 88215990Sjmallett struct musbotg_super_softc *sc = device_get_softc(dev); 89215990Sjmallett int err; 90215990Sjmallett int rid; 91215990Sjmallett 92215990Sjmallett /* setup MUSB OTG USB controller interface softc */ 93215990Sjmallett sc->sc_otg.sc_clocks_on = &musbotg_clocks_on; 94215990Sjmallett sc->sc_otg.sc_clocks_off = &musbotg_clocks_off; 95215990Sjmallett sc->sc_otg.sc_clocks_arg = sc; 96215990Sjmallett 97215990Sjmallett /* initialise some bus fields */ 98215990Sjmallett sc->sc_otg.sc_bus.parent = dev; 99215990Sjmallett sc->sc_otg.sc_bus.devices = sc->sc_otg.sc_devices; 100215990Sjmallett sc->sc_otg.sc_bus.devices_max = MUSB2_MAX_DEVICES; 101215990Sjmallett 102215990Sjmallett /* get all DMA memory */ 103215990Sjmallett if (usb2_bus_mem_alloc_all(&sc->sc_otg.sc_bus, 104210284Sjmallett USB_GET_DMA_TAG(dev), NULL)) { 105210284Sjmallett return (ENOMEM); 106210284Sjmallett } 107210284Sjmallett rid = 0; 108210284Sjmallett sc->sc_otg.sc_io_res = 109210284Sjmallett bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 110210284Sjmallett 111210284Sjmallett if (!(sc->sc_otg.sc_io_res)) { 112210284Sjmallett err = ENOMEM; 113210284Sjmallett goto error; 114210284Sjmallett } 115210284Sjmallett sc->sc_otg.sc_io_tag = rman_get_bustag(sc->sc_otg.sc_io_res); 116210284Sjmallett sc->sc_otg.sc_io_hdl = rman_get_bushandle(sc->sc_otg.sc_io_res); 117210284Sjmallett sc->sc_otg.sc_io_size = rman_get_size(sc->sc_otg.sc_io_res); 118210284Sjmallett 119210284Sjmallett rid = 0; 120210284Sjmallett sc->sc_otg.sc_irq_res = 121210284Sjmallett bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); 122210284Sjmallett if (!(sc->sc_otg.sc_irq_res)) { 123210284Sjmallett goto error; 124210284Sjmallett } 125210284Sjmallett sc->sc_otg.sc_bus.bdev = device_add_child(dev, "usbus", -1); 126210284Sjmallett if (!(sc->sc_otg.sc_bus.bdev)) { 127210284Sjmallett goto error; 128210284Sjmallett } 129210284Sjmallett device_set_ivars(sc->sc_otg.sc_bus.bdev, &sc->sc_otg.sc_bus); 130210284Sjmallett 131210284Sjmallett#if (__FreeBSD_version >= 700031) 132210284Sjmallett err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 133210284Sjmallett NULL, (driver_intr_t *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl); 134210284Sjmallett#else 135210284Sjmallett err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 136210284Sjmallett (driver_intr_t *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl); 137210284Sjmallett#endif 138210284Sjmallett if (err) { 139210284Sjmallett sc->sc_otg.sc_intr_hdl = NULL; 140210284Sjmallett goto error; 141210284Sjmallett } 142210311Sjmallett err = musbotg_init(&sc->sc_otg); 143210311Sjmallett if (!err) { 144210284Sjmallett err = device_probe_and_attach(sc->sc_otg.sc_bus.bdev); 145210284Sjmallett } 146210284Sjmallett if (err) { 147210284Sjmallett goto error; 148210284Sjmallett } else { 149210284Sjmallett /* poll VBUS one time */ 150210284Sjmallett musbotg_vbus_poll(sc); 151210284Sjmallett } 152210284Sjmallett return (0); 153210284Sjmallett 154210284Sjmalletterror: 155210284Sjmallett musbotg_detach(dev); 156210284Sjmallett return (ENXIO); 157210284Sjmallett} 158210284Sjmallett 159210284Sjmallettstatic int 160210284Sjmallettmusbotg_detach(device_t dev) 161210284Sjmallett{ 162210284Sjmallett struct musbotg_super_softc *sc = device_get_softc(dev); 163210284Sjmallett device_t bdev; 164210284Sjmallett int err; 165210284Sjmallett 166210284Sjmallett if (sc->sc_otg.sc_bus.bdev) { 167210284Sjmallett bdev = sc->sc_otg.sc_bus.bdev; 168210284Sjmallett device_detach(bdev); 169210284Sjmallett device_delete_child(dev, bdev); 170210284Sjmallett } 171210284Sjmallett /* during module unload there are lots of children leftover */ 172210284Sjmallett device_delete_all_children(dev); 173210284Sjmallett 174210284Sjmallett if (sc->sc_otg.sc_irq_res && sc->sc_otg.sc_intr_hdl) { 175210284Sjmallett /* 176210284Sjmallett * only call musbotg_uninit() after musbotg_init() 177210284Sjmallett */ 178210284Sjmallett musbotg_uninit(&sc->sc_otg); 179210284Sjmallett 180210284Sjmallett err = bus_teardown_intr(dev, sc->sc_otg.sc_irq_res, 181210284Sjmallett sc->sc_otg.sc_intr_hdl); 182210284Sjmallett sc->sc_otg.sc_intr_hdl = NULL; 183210284Sjmallett } 184210284Sjmallett /* free IRQ channel, if any */ 185210284Sjmallett if (sc->sc_otg.sc_irq_res) { 186210284Sjmallett bus_release_resource(dev, SYS_RES_IRQ, 0, 187215990Sjmallett sc->sc_otg.sc_irq_res); 188215990Sjmallett sc->sc_otg.sc_irq_res = NULL; 189215990Sjmallett } 190215990Sjmallett /* free memory resource, if any */ 191215990Sjmallett if (sc->sc_otg.sc_io_res) { 192215990Sjmallett bus_release_resource(dev, SYS_RES_MEMORY, 0, 193215990Sjmallett sc->sc_otg.sc_io_res); 194215990Sjmallett sc->sc_otg.sc_io_res = NULL; 195215990Sjmallett } 196215990Sjmallett usb2_bus_mem_free_all(&sc->sc_otg.sc_bus, NULL); 197215990Sjmallett 198215990Sjmallett return (0); 199215990Sjmallett} 200215990Sjmallett 201215990Sjmallettstatic int 202215990Sjmallettmusbotg_shutdown(device_t dev) 203215990Sjmallett{ 204215990Sjmallett struct musbotg_super_softc *sc = device_get_softc(dev); 205215990Sjmallett int err; 206215990Sjmallett 207215990Sjmallett err = bus_generic_shutdown(dev); 208215990Sjmallett if (err) 209215990Sjmallett return (err); 210215990Sjmallett 211215990Sjmallett musbotg_uninit(&sc->sc_otg); 212215990Sjmallett 213215990Sjmallett return (0); 214215990Sjmallett} 215215990Sjmallett 216215990Sjmallettstatic device_method_t musbotg_methods[] = { 217215990Sjmallett /* Device interface */ 218215990Sjmallett DEVMETHOD(device_probe, musbotg_probe), 219215990Sjmallett DEVMETHOD(device_attach, musbotg_attach), 220215990Sjmallett DEVMETHOD(device_detach, musbotg_detach), 221215990Sjmallett DEVMETHOD(device_shutdown, musbotg_shutdown), 222215990Sjmallett 223210284Sjmallett /* Bus interface */ 224210284Sjmallett DEVMETHOD(bus_print_child, bus_generic_print_child), 225210284Sjmallett 226210284Sjmallett {0, 0} 227210284Sjmallett}; 228210284Sjmallett 229210284Sjmallettstatic driver_t musbotg_driver = { 230210284Sjmallett "musbotg", 231210284Sjmallett musbotg_methods, 232210284Sjmallett sizeof(struct musbotg_super_softc), 233210284Sjmallett}; 234210284Sjmallett 235210284Sjmallettstatic devclass_t musbotg_devclass; 236210284Sjmallett 237210284SjmallettDRIVER_MODULE(musbotg, atmelarm, musbotg_driver, musbotg_devclass, 0, 0); 238210284SjmallettMODULE_DEPEND(musbotg, usb, 1, 1, 1); 239210284Sjmallett