1184610Salfred/*- 2184610Salfred * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. 3184610Salfred * 4184610Salfred * Redistribution and use in source and binary forms, with or without 5184610Salfred * modification, are permitted provided that the following conditions 6184610Salfred * are met: 7184610Salfred * 1. Redistributions of source code must retain the above copyright 8184610Salfred * notice, this list of conditions and the following disclaimer. 9184610Salfred * 2. Redistributions in binary form must reproduce the above copyright 10184610Salfred * notice, this list of conditions and the following disclaimer in the 11184610Salfred * documentation and/or other materials provided with the distribution. 12184610Salfred * 13184610Salfred * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14184610Salfred * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15184610Salfred * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16184610Salfred * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17184610Salfred * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18184610Salfred * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19184610Salfred * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20184610Salfred * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21184610Salfred * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22184610Salfred * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23184610Salfred * SUCH DAMAGE. 24184610Salfred */ 25184610Salfred 26227843Smarius#include <sys/cdefs.h> 27227843Smarius__FBSDID("$FreeBSD: releng/10.3/sys/dev/usb/controller/musb_otg_atmelarm.c 278278 2015-02-05 20:03:02Z hselasky $"); 28227843Smarius 29194677Sthompsa#include <sys/stdint.h> 30194677Sthompsa#include <sys/stddef.h> 31194677Sthompsa#include <sys/param.h> 32194677Sthompsa#include <sys/queue.h> 33194677Sthompsa#include <sys/types.h> 34194677Sthompsa#include <sys/systm.h> 35194677Sthompsa#include <sys/kernel.h> 36194677Sthompsa#include <sys/bus.h> 37194677Sthompsa#include <sys/module.h> 38194677Sthompsa#include <sys/lock.h> 39194677Sthompsa#include <sys/mutex.h> 40194677Sthompsa#include <sys/condvar.h> 41194677Sthompsa#include <sys/sysctl.h> 42194677Sthompsa#include <sys/sx.h> 43194677Sthompsa#include <sys/unistd.h> 44194677Sthompsa#include <sys/callout.h> 45194677Sthompsa#include <sys/malloc.h> 46194677Sthompsa#include <sys/priv.h> 47194677Sthompsa 48188942Sthompsa#include <dev/usb/usb.h> 49194677Sthompsa#include <dev/usb/usbdi.h> 50184610Salfred 51188942Sthompsa#include <dev/usb/usb_core.h> 52188942Sthompsa#include <dev/usb/usb_busdma.h> 53188942Sthompsa#include <dev/usb/usb_process.h> 54188942Sthompsa#include <dev/usb/usb_util.h> 55184610Salfred 56188942Sthompsa#include <dev/usb/usb_controller.h> 57188942Sthompsa#include <dev/usb/usb_bus.h> 58189598Sthompsa#include <dev/usb/controller/musb_otg.h> 59184610Salfred 60184610Salfred#include <sys/rman.h> 61184610Salfred 62184610Salfredstatic device_probe_t musbotg_probe; 63184610Salfredstatic device_attach_t musbotg_attach; 64184610Salfredstatic device_detach_t musbotg_detach; 65184610Salfred 66184610Salfredstruct musbotg_super_softc { 67184610Salfred struct musbotg_softc sc_otg; /* must be first */ 68184610Salfred}; 69184610Salfred 70184610Salfredstatic void 71187175Sthompsamusbotg_vbus_poll(struct musbotg_super_softc *sc) 72184610Salfred{ 73184610Salfred uint8_t vbus_val = 1; /* fake VBUS on - TODO */ 74184610Salfred 75184610Salfred /* just forward it */ 76187175Sthompsa musbotg_vbus_interrupt(&sc->sc_otg, vbus_val); 77184610Salfred} 78184610Salfred 79184610Salfredstatic void 80184610Salfredmusbotg_clocks_on(void *arg) 81184610Salfred{ 82184610Salfred#if 0 83184610Salfred struct musbotg_super_softc *sc = arg; 84184610Salfred 85184610Salfred#endif 86184610Salfred} 87184610Salfred 88184610Salfredstatic void 89184610Salfredmusbotg_clocks_off(void *arg) 90184610Salfred{ 91184610Salfred#if 0 92184610Salfred struct musbotg_super_softc *sc = arg; 93184610Salfred 94184610Salfred#endif 95184610Salfred} 96184610Salfred 97252912Sgonzostatic void 98252912Sgonzomusbotg_wrapper_interrupt(void *arg) 99252912Sgonzo{ 100252912Sgonzo 101252912Sgonzo /* 102252912Sgonzo * Nothing to do. 103252912Sgonzo * Main driver takes care about everything 104252912Sgonzo */ 105252912Sgonzo musbotg_interrupt(arg, 0, 0, 0); 106252912Sgonzo} 107252912Sgonzo 108252912Sgonzostatic void 109252912Sgonzomusbotg_ep_int_set(struct musbotg_softc *sc, int ep, int on) 110252912Sgonzo{ 111252912Sgonzo /* 112252912Sgonzo * Nothing to do. 113252912Sgonzo * Main driver takes care about everything 114252912Sgonzo */ 115252912Sgonzo} 116252912Sgonzo 117184610Salfredstatic int 118184610Salfredmusbotg_probe(device_t dev) 119184610Salfred{ 120184610Salfred device_set_desc(dev, "MUSB OTG integrated USB controller"); 121184610Salfred return (0); 122184610Salfred} 123184610Salfred 124184610Salfredstatic int 125184610Salfredmusbotg_attach(device_t dev) 126184610Salfred{ 127184610Salfred struct musbotg_super_softc *sc = device_get_softc(dev); 128184610Salfred int err; 129184610Salfred int rid; 130184610Salfred 131184610Salfred /* setup MUSB OTG USB controller interface softc */ 132184610Salfred sc->sc_otg.sc_clocks_on = &musbotg_clocks_on; 133184610Salfred sc->sc_otg.sc_clocks_off = &musbotg_clocks_off; 134184610Salfred sc->sc_otg.sc_clocks_arg = sc; 135184610Salfred 136187170Sthompsa /* initialise some bus fields */ 137187170Sthompsa sc->sc_otg.sc_bus.parent = dev; 138187170Sthompsa sc->sc_otg.sc_bus.devices = sc->sc_otg.sc_devices; 139187170Sthompsa sc->sc_otg.sc_bus.devices_max = MUSB2_MAX_DEVICES; 140278278Shselasky sc->sc_otg.sc_bus.dma_bits = 32; 141187170Sthompsa 142184610Salfred /* get all DMA memory */ 143194228Sthompsa if (usb_bus_mem_alloc_all(&sc->sc_otg.sc_bus, 144184610Salfred USB_GET_DMA_TAG(dev), NULL)) { 145184610Salfred return (ENOMEM); 146184610Salfred } 147184610Salfred rid = 0; 148184610Salfred sc->sc_otg.sc_io_res = 149184610Salfred bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 150184610Salfred 151184610Salfred if (!(sc->sc_otg.sc_io_res)) { 152184610Salfred err = ENOMEM; 153184610Salfred goto error; 154184610Salfred } 155184610Salfred sc->sc_otg.sc_io_tag = rman_get_bustag(sc->sc_otg.sc_io_res); 156184610Salfred sc->sc_otg.sc_io_hdl = rman_get_bushandle(sc->sc_otg.sc_io_res); 157184610Salfred sc->sc_otg.sc_io_size = rman_get_size(sc->sc_otg.sc_io_res); 158184610Salfred 159184610Salfred rid = 0; 160184610Salfred sc->sc_otg.sc_irq_res = 161184610Salfred bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); 162184610Salfred if (!(sc->sc_otg.sc_irq_res)) { 163184610Salfred goto error; 164184610Salfred } 165184610Salfred sc->sc_otg.sc_bus.bdev = device_add_child(dev, "usbus", -1); 166184610Salfred if (!(sc->sc_otg.sc_bus.bdev)) { 167184610Salfred goto error; 168184610Salfred } 169184610Salfred device_set_ivars(sc->sc_otg.sc_bus.bdev, &sc->sc_otg.sc_bus); 170184610Salfred 171252912Sgonzo sc->sc_otg.sc_id = 0; 172252912Sgonzo sc->sc_otg.sc_platform_data = sc; 173252912Sgonzo sc->sc_otg.sc_mode = MUSB2_DEVICE_MODE; 174252912Sgonzo 175184610Salfred#if (__FreeBSD_version >= 700031) 176184610Salfred err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 177252912Sgonzo NULL, (driver_intr_t *)musbotg_wrapper_interrupt, sc, &sc->sc_otg.sc_intr_hdl); 178184610Salfred#else 179184610Salfred err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 180252912Sgonzo (driver_intr_t *)musbotg_wrapper_interrupt, sc, &sc->sc_otg.sc_intr_hdl); 181184610Salfred#endif 182184610Salfred if (err) { 183184610Salfred sc->sc_otg.sc_intr_hdl = NULL; 184184610Salfred goto error; 185184610Salfred } 186184610Salfred err = musbotg_init(&sc->sc_otg); 187184610Salfred if (!err) { 188184610Salfred err = device_probe_and_attach(sc->sc_otg.sc_bus.bdev); 189184610Salfred } 190184610Salfred if (err) { 191184610Salfred goto error; 192184610Salfred } else { 193184610Salfred /* poll VBUS one time */ 194187175Sthompsa musbotg_vbus_poll(sc); 195184610Salfred } 196184610Salfred return (0); 197184610Salfred 198184610Salfrederror: 199184610Salfred musbotg_detach(dev); 200184610Salfred return (ENXIO); 201184610Salfred} 202184610Salfred 203184610Salfredstatic int 204184610Salfredmusbotg_detach(device_t dev) 205184610Salfred{ 206184610Salfred struct musbotg_super_softc *sc = device_get_softc(dev); 207184610Salfred device_t bdev; 208184610Salfred int err; 209184610Salfred 210184610Salfred if (sc->sc_otg.sc_bus.bdev) { 211184610Salfred bdev = sc->sc_otg.sc_bus.bdev; 212184610Salfred device_detach(bdev); 213184610Salfred device_delete_child(dev, bdev); 214184610Salfred } 215184610Salfred /* during module unload there are lots of children leftover */ 216227849Shselasky device_delete_children(dev); 217184610Salfred 218184610Salfred if (sc->sc_otg.sc_irq_res && sc->sc_otg.sc_intr_hdl) { 219184610Salfred /* 220184610Salfred * only call musbotg_uninit() after musbotg_init() 221184610Salfred */ 222184610Salfred musbotg_uninit(&sc->sc_otg); 223184610Salfred 224184610Salfred err = bus_teardown_intr(dev, sc->sc_otg.sc_irq_res, 225184610Salfred sc->sc_otg.sc_intr_hdl); 226184610Salfred sc->sc_otg.sc_intr_hdl = NULL; 227184610Salfred } 228184610Salfred /* free IRQ channel, if any */ 229184610Salfred if (sc->sc_otg.sc_irq_res) { 230184610Salfred bus_release_resource(dev, SYS_RES_IRQ, 0, 231184610Salfred sc->sc_otg.sc_irq_res); 232184610Salfred sc->sc_otg.sc_irq_res = NULL; 233184610Salfred } 234184610Salfred /* free memory resource, if any */ 235184610Salfred if (sc->sc_otg.sc_io_res) { 236184610Salfred bus_release_resource(dev, SYS_RES_MEMORY, 0, 237184610Salfred sc->sc_otg.sc_io_res); 238184610Salfred sc->sc_otg.sc_io_res = NULL; 239184610Salfred } 240194228Sthompsa usb_bus_mem_free_all(&sc->sc_otg.sc_bus, NULL); 241184610Salfred 242184610Salfred return (0); 243184610Salfred} 244184610Salfred 245184610Salfredstatic device_method_t musbotg_methods[] = { 246184610Salfred /* Device interface */ 247184610Salfred DEVMETHOD(device_probe, musbotg_probe), 248184610Salfred DEVMETHOD(device_attach, musbotg_attach), 249184610Salfred DEVMETHOD(device_detach, musbotg_detach), 250228483Shselasky DEVMETHOD(device_suspend, bus_generic_suspend), 251228483Shselasky DEVMETHOD(device_resume, bus_generic_resume), 252228483Shselasky DEVMETHOD(device_shutdown, bus_generic_shutdown), 253184610Salfred 254227843Smarius DEVMETHOD_END 255184610Salfred}; 256184610Salfred 257184610Salfredstatic driver_t musbotg_driver = { 258228483Shselasky .name = "musbotg", 259228483Shselasky .methods = musbotg_methods, 260228483Shselasky .size = sizeof(struct musbotg_super_softc), 261184610Salfred}; 262184610Salfred 263184610Salfredstatic devclass_t musbotg_devclass; 264184610Salfred 265184610SalfredDRIVER_MODULE(musbotg, atmelarm, musbotg_driver, musbotg_devclass, 0, 0); 266188942SthompsaMODULE_DEPEND(musbotg, usb, 1, 1, 1); 267