1220297Sadrian#include <sys/cdefs.h> 2220297Sadrian__FBSDID("$FreeBSD$"); 3220297Sadrian 4220297Sadrian/*- 5220297Sadrian * Copyright (c) 2010,2011 Aleksandr Rybalko. All rights reserved. 6220297Sadrian * Copyright (c) 2007-2008 Hans Petter Selasky. All rights reserved. 7220297Sadrian * 8220297Sadrian * Redistribution and use in source and binary forms, with or without 9220297Sadrian * modification, are permitted provided that the following conditions 10220297Sadrian * are met: 11220297Sadrian * 1. Redistributions of source code must retain the above copyright 12220297Sadrian * notice, this list of conditions and the following disclaimer. 13220297Sadrian * 2. Redistributions in binary form must reproduce the above copyright 14220297Sadrian * notice, this list of conditions and the following disclaimer in the 15220297Sadrian * documentation and/or other materials provided with the distribution. 16220297Sadrian * 17220297Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18220297Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19220297Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20220297Sadrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21220297Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22220297Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23220297Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24220297Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25220297Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26220297Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27220297Sadrian * SUCH DAMAGE. 28220297Sadrian */ 29220297Sadrian 30220297Sadrian#include <sys/stdint.h> 31220297Sadrian#include <sys/stddef.h> 32220297Sadrian#include <sys/param.h> 33220297Sadrian#include <sys/queue.h> 34220297Sadrian#include <sys/types.h> 35220297Sadrian#include <sys/systm.h> 36220297Sadrian#include <sys/kernel.h> 37220297Sadrian#include <sys/bus.h> 38220297Sadrian#include <sys/module.h> 39220297Sadrian#include <sys/lock.h> 40220297Sadrian#include <sys/mutex.h> 41220297Sadrian#include <sys/condvar.h> 42220297Sadrian#include <sys/sysctl.h> 43220297Sadrian#include <sys/sx.h> 44220297Sadrian#include <sys/unistd.h> 45220297Sadrian#include <sys/callout.h> 46220297Sadrian#include <sys/malloc.h> 47220297Sadrian#include <sys/priv.h> 48220297Sadrian#include <sys/rman.h> 49220297Sadrian 50220297Sadrian#include <dev/usb/usb.h> 51220297Sadrian#include <dev/usb/usbdi.h> 52220297Sadrian 53220297Sadrian#include <dev/usb/usb_core.h> 54220297Sadrian#include <dev/usb/usb_busdma.h> 55220297Sadrian#include <dev/usb/usb_process.h> 56220297Sadrian#include <dev/usb/usb_util.h> 57220297Sadrian 58220297Sadrian#include <dev/usb/usb_controller.h> 59220297Sadrian#include <dev/usb/usb_bus.h> 60220297Sadrian 61220297Sadrian#include <dev/usb/controller/dotg.h> 62220297Sadrian#include <mips/rt305x/rt305xreg.h> 63220297Sadrian#include <mips/rt305x/rt305x_sysctlvar.h> 64220297Sadrian 65220297Sadrian#define MEM_RID 0 66220297Sadrian 67220297Sadrianstatic device_probe_t dotg_obio_probe; 68220297Sadrianstatic device_attach_t dotg_obio_attach; 69220297Sadrianstatic device_detach_t dotg_obio_detach; 70220297Sadrian 71220297Sadrianstruct dotg_obio_softc { 72220297Sadrian struct dotg_softc sc_dci; /* must be first */ 73220297Sadrian}; 74220297Sadrian 75220297Sadrianstatic int 76220297Sadriandotg_obio_probe(device_t dev) 77220297Sadrian{ 78220297Sadrian device_set_desc(dev, "DWC like USB OTG controller"); 79220297Sadrian return (0); 80220297Sadrian} 81220297Sadrian 82220297Sadrianstatic int 83220297Sadriandotg_obio_attach(device_t dev) 84220297Sadrian{ 85220297Sadrian struct dotg_obio_softc *sc = device_get_softc(dev); 86220297Sadrian int err; 87220297Sadrian 88220297Sadrian /* setup controller interface softc */ 89220297Sadrian 90220297Sadrian /* initialise some bus fields */ 91220297Sadrian sc->sc_dci.sc_dev = dev; 92220297Sadrian sc->sc_dci.sc_bus.parent = dev; 93220297Sadrian sc->sc_dci.sc_bus.devices = sc->sc_dci.sc_devices; 94220297Sadrian sc->sc_dci.sc_bus.devices_max = DOTG_MAX_DEVICES; 95220297Sadrian 96220297Sadrian /* get all DMA memory */ 97220297Sadrian if (usb_bus_mem_alloc_all(&sc->sc_dci.sc_bus, 98220297Sadrian USB_GET_DMA_TAG(dev), NULL)) { 99220297Sadrian printf("No mem\n"); 100220297Sadrian return (ENOMEM); 101220297Sadrian } 102220297Sadrian sc->sc_dci.sc_mem_rid = 0; 103220297Sadrian sc->sc_dci.sc_mem_res = 104220297Sadrian bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_dci.sc_irq_rid, 105220297Sadrian RF_ACTIVE); 106220297Sadrian if (!(sc->sc_dci.sc_mem_res)) { 107220297Sadrian printf("Can`t alloc MEM\n"); 108220297Sadrian goto error; 109220297Sadrian } 110220297Sadrian sc->sc_dci.sc_bst = rman_get_bustag(sc->sc_dci.sc_mem_res); 111220297Sadrian sc->sc_dci.sc_bsh = rman_get_bushandle(sc->sc_dci.sc_mem_res); 112220297Sadrian 113220297Sadrian sc->sc_dci.sc_irq_rid = 0; 114220297Sadrian sc->sc_dci.sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 115220297Sadrian &sc->sc_dci.sc_irq_rid, RF_SHAREABLE| RF_ACTIVE); 116220297Sadrian if (!(sc->sc_dci.sc_irq_res)) { 117220297Sadrian printf("Can`t alloc IRQ\n"); 118220297Sadrian goto error; 119220297Sadrian } 120220297Sadrian 121220297Sadrian sc->sc_dci.sc_bus.bdev = device_add_child(dev, "usbus", -1); 122220297Sadrian if (!(sc->sc_dci.sc_bus.bdev)) { 123220297Sadrian printf("Can`t add usbus\n"); 124220297Sadrian goto error; 125220297Sadrian } 126220297Sadrian device_set_ivars(sc->sc_dci.sc_bus.bdev, &sc->sc_dci.sc_bus); 127220297Sadrian 128220297Sadrian#if (__FreeBSD_version >= 700031) 129220297Sadrian err = bus_setup_intr(dev, sc->sc_dci.sc_irq_res, 130220297Sadrian INTR_TYPE_BIO | INTR_MPSAFE, NULL, (driver_intr_t *)dotg_interrupt, 131220297Sadrian sc, &sc->sc_dci.sc_intr_hdl); 132220297Sadrian#else 133220297Sadrian err = bus_setup_intr(dev, sc->sc_dci.sc_irq_res, 134220297Sadrian INTR_TYPE_BIO | INTR_MPSAFE, (driver_intr_t *)dotg_interrupt, 135220297Sadrian sc, &sc->sc_dci.sc_intr_hdl); 136220297Sadrian#endif 137220297Sadrian if (err) { 138220297Sadrian sc->sc_dci.sc_intr_hdl = NULL; 139220297Sadrian printf("Can`t set IRQ handle\n"); 140220297Sadrian goto error; 141220297Sadrian } 142220297Sadrian 143220297Sadrian /* Run clock for OTG core */ 144220297Sadrian rt305x_sysctl_set(SYSCTL_CLKCFG1, rt305x_sysctl_get(SYSCTL_CLKCFG1) | 145220297Sadrian SYSCTL_CLKCFG1_OTG_CLK_EN); 146220297Sadrian rt305x_sysctl_set(SYSCTL_RSTCTRL, SYSCTL_RSTCTRL_OTG); 147220297Sadrian DELAY(100); 148220297Sadrian 149220297Sadrian err = dotg_init(&sc->sc_dci); 150220297Sadrian if (err) printf("dotg_init fail\n"); 151220297Sadrian if (!err) { 152220297Sadrian err = device_probe_and_attach(sc->sc_dci.sc_bus.bdev); 153220297Sadrian if (err) printf("device_probe_and_attach fail\n"); 154220297Sadrian } 155220297Sadrian if (err) { 156220297Sadrian goto error; 157220297Sadrian } 158220297Sadrian return (0); 159220297Sadrian 160220297Sadrianerror: 161220297Sadrian dotg_obio_detach(dev); 162220297Sadrian return (ENXIO); 163220297Sadrian} 164220297Sadrian 165220297Sadrianstatic int 166220297Sadriandotg_obio_detach(device_t dev) 167220297Sadrian{ 168220297Sadrian struct dotg_obio_softc *sc = device_get_softc(dev); 169220297Sadrian device_t bdev; 170220297Sadrian int err; 171220297Sadrian 172220297Sadrian if (sc->sc_dci.sc_bus.bdev) { 173220297Sadrian bdev = sc->sc_dci.sc_bus.bdev; 174220297Sadrian device_detach(bdev); 175220297Sadrian device_delete_child(dev, bdev); 176220297Sadrian } 177220297Sadrian /* during module unload there are lots of children leftover */ 178229118Shselasky device_delete_children(dev); 179220297Sadrian 180220297Sadrian if (sc->sc_dci.sc_irq_res && sc->sc_dci.sc_intr_hdl) { 181220297Sadrian /* 182220297Sadrian * only call dotg_obio_uninit() after dotg_obio_init() 183220297Sadrian */ 184220297Sadrian dotg_uninit(&sc->sc_dci); 185220297Sadrian 186220297Sadrian /* Stop OTG clock */ 187220297Sadrian rt305x_sysctl_set(SYSCTL_CLKCFG1, 188220297Sadrian rt305x_sysctl_get(SYSCTL_CLKCFG1) & 189220297Sadrian ~SYSCTL_CLKCFG1_OTG_CLK_EN); 190220297Sadrian 191220297Sadrian err = bus_teardown_intr(dev, sc->sc_dci.sc_irq_res, 192220297Sadrian sc->sc_dci.sc_intr_hdl); 193220297Sadrian sc->sc_dci.sc_intr_hdl = NULL; 194220297Sadrian } 195220297Sadrian if (sc->sc_dci.sc_irq_res) { 196220297Sadrian bus_release_resource(dev, SYS_RES_IRQ, 0, 197220297Sadrian sc->sc_dci.sc_irq_res); 198220297Sadrian sc->sc_dci.sc_irq_res = NULL; 199220297Sadrian } 200220297Sadrian if (sc->sc_dci.sc_mem_res) { 201220297Sadrian bus_release_resource(dev, SYS_RES_MEMORY, 0, 202220297Sadrian sc->sc_dci.sc_mem_res); 203220297Sadrian sc->sc_dci.sc_mem_res = NULL; 204220297Sadrian } 205220297Sadrian usb_bus_mem_free_all(&sc->sc_dci.sc_bus, NULL); 206220297Sadrian 207220297Sadrian return (0); 208220297Sadrian} 209220297Sadrian 210220297Sadrianstatic device_method_t dotg_obio_methods[] = { 211220297Sadrian /* Device interface */ 212220297Sadrian DEVMETHOD(device_probe, dotg_obio_probe), 213220297Sadrian DEVMETHOD(device_attach, dotg_obio_attach), 214220297Sadrian DEVMETHOD(device_detach, dotg_obio_detach), 215229096Shselasky DEVMETHOD(device_suspend, bus_generic_suspend), 216229096Shselasky DEVMETHOD(device_resume, bus_generic_resume), 217229096Shselasky DEVMETHOD(device_shutdown, bus_generic_shutdown), 218220297Sadrian 219229093Shselasky DEVMETHOD_END 220220297Sadrian}; 221220297Sadrian 222220297Sadrianstatic driver_t dotg_obio_driver = { 223229096Shselasky .name = "dotg", 224229096Shselasky .methods = dotg_obio_methods, 225229096Shselasky .size = sizeof(struct dotg_obio_softc), 226220297Sadrian}; 227220297Sadrian 228220297Sadrianstatic devclass_t dotg_obio_devclass; 229220297Sadrian 230220297SadrianDRIVER_MODULE(dotg, obio, dotg_obio_driver, dotg_obio_devclass, 0, 0); 231