musb_otg_atmelarm.c revision 190749
1210284Sjmallett/* $FreeBSD: head/sys/dev/usb/controller/musb_otg_atmelarm.c 190749 2009-04-05 21:24:15Z 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 40210284Sjmallett#include <sys/rman.h> 41210284Sjmallett 42210284Sjmallettstatic device_probe_t musbotg_probe; 43210284Sjmallettstatic device_attach_t musbotg_attach; 44215990Sjmallettstatic 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 */ 49232812Sjmallett}; 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; 65232812Sjmallett 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 78215990Sjmallettstatic int 79232812Sjmallettmusbotg_probe(device_t dev) 80210284Sjmallett{ 81210284Sjmallett device_set_desc(dev, "MUSB OTG integrated USB controller"); 82210284Sjmallett return (0); 83210284Sjmallett} 84210284Sjmallett 85210284Sjmallettstatic int 86210284Sjmallettmusbotg_attach(device_t dev) 87210284Sjmallett{ 88210284Sjmallett struct musbotg_super_softc *sc = device_get_softc(dev); 89210284Sjmallett int err; 90210284Sjmallett int rid; 91210284Sjmallett 92210284Sjmallett /* setup MUSB OTG USB controller interface softc */ 93210284Sjmallett sc->sc_otg.sc_clocks_on = &musbotg_clocks_on; 94210284Sjmallett sc->sc_otg.sc_clocks_off = &musbotg_clocks_off; 95210284Sjmallett sc->sc_otg.sc_clocks_arg = sc; 96210284Sjmallett 97210284Sjmallett /* initialise some bus fields */ 98210284Sjmallett sc->sc_otg.sc_bus.parent = dev; 99210284Sjmallett sc->sc_otg.sc_bus.devices = sc->sc_otg.sc_devices; 100210284Sjmallett sc->sc_otg.sc_bus.devices_max = MUSB2_MAX_DEVICES; 101210284Sjmallett 102210284Sjmallett /* get all DMA memory */ 103210284Sjmallett 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; 124232812Sjmallett } 125232812Sjmallett sc->sc_otg.sc_bus.bdev = device_add_child(dev, "usbus", -1); 126232812Sjmallett if (!(sc->sc_otg.sc_bus.bdev)) { 127232812Sjmallett goto error; 128232812Sjmallett } 129232812Sjmallett device_set_ivars(sc->sc_otg.sc_bus.bdev, &sc->sc_otg.sc_bus); 130232812Sjmallett 131232812Sjmallett#if (__FreeBSD_version >= 700031) 132232812Sjmallett err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 133232812Sjmallett NULL, (driver_intr_t *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl); 134232812Sjmallett#else 135210284Sjmallett err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 136232812Sjmallett (driver_intr_t *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl); 137232812Sjmallett#endif 138232812Sjmallett if (err) { 139232812Sjmallett sc->sc_otg.sc_intr_hdl = NULL; 140210284Sjmallett goto error; 141232812Sjmallett } 142232812Sjmallett err = musbotg_init(&sc->sc_otg); 143232812Sjmallett if (!err) { 144232812Sjmallett err = device_probe_and_attach(sc->sc_otg.sc_bus.bdev); 145232812Sjmallett } 146232812Sjmallett if (err) { 147232812Sjmallett goto error; 148232812Sjmallett } else { 149232812Sjmallett /* poll VBUS one time */ 150232812Sjmallett musbotg_vbus_poll(sc); 151232812Sjmallett } 152232812Sjmallett return (0); 153232812Sjmallett 154232812Sjmalletterror: 155232812Sjmallett musbotg_detach(dev); 156232812Sjmallett return (ENXIO); 157232812Sjmallett} 158232812Sjmallett 159232812Sjmallettstatic int 160232812Sjmallettmusbotg_detach(device_t dev) 161232812Sjmallett{ 162232812Sjmallett struct musbotg_super_softc *sc = device_get_softc(dev); 163232812Sjmallett device_t bdev; 164232812Sjmallett int err; 165232812Sjmallett 166232812Sjmallett if (sc->sc_otg.sc_bus.bdev) { 167232812Sjmallett bdev = sc->sc_otg.sc_bus.bdev; 168232812Sjmallett device_detach(bdev); 169232812Sjmallett device_delete_child(dev, bdev); 170232812Sjmallett } 171232812Sjmallett /* during module unload there are lots of children leftover */ 172232812Sjmallett device_delete_all_children(dev); 173232812Sjmallett 174232812Sjmallett if (sc->sc_otg.sc_irq_res && sc->sc_otg.sc_intr_hdl) { 175232812Sjmallett /* 176232812Sjmallett * only call musbotg_uninit() after musbotg_init() 177232812Sjmallett */ 178232812Sjmallett musbotg_uninit(&sc->sc_otg); 179232812Sjmallett 180232812Sjmallett err = bus_teardown_intr(dev, sc->sc_otg.sc_irq_res, 181232812Sjmallett sc->sc_otg.sc_intr_hdl); 182232812Sjmallett sc->sc_otg.sc_intr_hdl = NULL; 183232812Sjmallett } 184232812Sjmallett /* free IRQ channel, if any */ 185232812Sjmallett if (sc->sc_otg.sc_irq_res) { 186232812Sjmallett bus_release_resource(dev, SYS_RES_IRQ, 0, 187232812Sjmallett sc->sc_otg.sc_irq_res); 188215990Sjmallett sc->sc_otg.sc_irq_res = NULL; 189210284Sjmallett } 190215990Sjmallett /* free memory resource, if any */ 191215990Sjmallett if (sc->sc_otg.sc_io_res) { 192210284Sjmallett bus_release_resource(dev, SYS_RES_MEMORY, 0, 193210284Sjmallett sc->sc_otg.sc_io_res); 194210284Sjmallett sc->sc_otg.sc_io_res = NULL; 195210284Sjmallett } 196210284Sjmallett usb2_bus_mem_free_all(&sc->sc_otg.sc_bus, NULL); 197210284Sjmallett 198210284Sjmallett return (0); 199210284Sjmallett} 200210284Sjmallett 201210284Sjmallettstatic int 202210284Sjmallettmusbotg_shutdown(device_t dev) 203210284Sjmallett{ 204210284Sjmallett struct musbotg_super_softc *sc = device_get_softc(dev); 205210284Sjmallett int err; 206210284Sjmallett 207210284Sjmallett err = bus_generic_shutdown(dev); 208210284Sjmallett if (err) 209210284Sjmallett return (err); 210210284Sjmallett 211232812Sjmallett musbotg_uninit(&sc->sc_otg); 212210284Sjmallett 213210284Sjmallett return (0); 214210284Sjmallett} 215210284Sjmallett 216210284Sjmallettstatic device_method_t musbotg_methods[] = { 217210284Sjmallett /* Device interface */ 218210284Sjmallett DEVMETHOD(device_probe, musbotg_probe), 219210284Sjmallett DEVMETHOD(device_attach, musbotg_attach), 220210284Sjmallett DEVMETHOD(device_detach, musbotg_detach), 221210284Sjmallett DEVMETHOD(device_shutdown, musbotg_shutdown), 222210284Sjmallett 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 235215990Sjmallettstatic devclass_t musbotg_devclass; 236215990Sjmallett 237215990SjmallettDRIVER_MODULE(musbotg, atmelarm, musbotg_driver, musbotg_devclass, 0, 0); 238215990SjmallettMODULE_DEPEND(musbotg, usb, 1, 1, 1); 239215990Sjmallett