rt305x_dotg.c revision 331722
1#include <sys/cdefs.h> 2__FBSDID("$FreeBSD: stable/11/sys/mips/rt305x/rt305x_dotg.c 331722 2018-03-29 02:50:57Z eadler $"); 3 4/*- 5 * Copyright (c) 2015 Stanislav Galabov. All rights reserved. 6 * Copyright (c) 2010,2011 Aleksandr Rybalko. All rights reserved. 7 * Copyright (c) 2007-2008 Hans Petter Selasky. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31#include <sys/stdint.h> 32#include <sys/stddef.h> 33#include <sys/param.h> 34#include <sys/queue.h> 35#include <sys/types.h> 36#include <sys/systm.h> 37#include <sys/kernel.h> 38#include <sys/bus.h> 39#include <sys/module.h> 40#include <sys/lock.h> 41#include <sys/mutex.h> 42#include <sys/condvar.h> 43#include <sys/sysctl.h> 44#include <sys/sx.h> 45#include <sys/unistd.h> 46#include <sys/callout.h> 47#include <sys/malloc.h> 48#include <sys/priv.h> 49#include <sys/rman.h> 50 51#include <dev/usb/usb.h> 52#include <dev/usb/usbdi.h> 53 54#include <dev/usb/usb_core.h> 55#include <dev/usb/usb_busdma.h> 56#include <dev/usb/usb_process.h> 57#include <dev/usb/usb_util.h> 58 59#include <dev/usb/usb_controller.h> 60#include <dev/usb/usb_bus.h> 61 62#include <dev/usb/controller/dwc_otg.h> 63#include <mips/rt305x/rt305xreg.h> 64#include <mips/rt305x/rt305x_sysctlvar.h> 65 66#define MEM_RID 0 67 68static device_probe_t dotg_obio_probe; 69static device_attach_t dotg_obio_attach; 70static device_detach_t dotg_obio_detach; 71 72static int 73dotg_obio_probe(device_t dev) 74{ 75 device_set_desc(dev, "DWC like USB OTG controller"); 76 return (0); 77} 78 79static int 80dotg_obio_attach(device_t dev) 81{ 82 struct dwc_otg_softc *sc = device_get_softc(dev); 83 uint32_t tmp; 84 int err, rid; 85 86 /* setup controller interface softc */ 87 88 /* initialise some bus fields */ 89 sc->sc_mode = DWC_MODE_HOST; 90 sc->sc_bus.parent = dev; 91 sc->sc_bus.devices = sc->sc_devices; 92 sc->sc_bus.devices_max = DWC_OTG_MAX_DEVICES; 93 sc->sc_bus.dma_bits = 32; 94 95 /* get all DMA memory */ 96 if (usb_bus_mem_alloc_all(&sc->sc_bus, 97 USB_GET_DMA_TAG(dev), NULL)) { 98 printf("No mem\n"); 99 return (ENOMEM); 100 } 101 rid = 0; 102 sc->sc_io_res = 103 bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 104 if (!(sc->sc_io_res)) { 105 printf("Can`t alloc MEM\n"); 106 goto error; 107 } 108 sc->sc_io_tag = rman_get_bustag(sc->sc_io_res); 109 sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res); 110 sc->sc_io_size = rman_get_size(sc->sc_io_res); 111 112 rid = 0; 113 sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 114 &rid, RF_ACTIVE); 115 if (!(sc->sc_irq_res)) { 116 printf("Can`t alloc IRQ\n"); 117 goto error; 118 } 119 120 sc->sc_bus.bdev = device_add_child(dev, "usbus", -1); 121 if (!(sc->sc_bus.bdev)) { 122 printf("Can`t add usbus\n"); 123 goto error; 124 } 125 device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); 126 127#if (__FreeBSD_version >= 700031) 128 err = bus_setup_intr(dev, sc->sc_irq_res, 129 INTR_TYPE_TTY | INTR_MPSAFE, dwc_otg_filter_interrupt, 130 dwc_otg_interrupt, sc, &sc->sc_intr_hdl); 131#else 132 #error error 133 err = bus_setup_intr(dev, sc->sc_irq_res, 134 INTR_TYPE_BIO | INTR_MPSAFE,(driver_intr_t*)dwc_otg_interrupt, 135 sc, &sc->sc_intr_hdl); 136#endif 137 if (err) { 138 sc->sc_intr_hdl = NULL; 139 printf("Can`t set IRQ handle\n"); 140 goto error; 141 } 142 143 /* Run clock for OTG core */ 144 rt305x_sysctl_set(SYSCTL_CLKCFG1, rt305x_sysctl_get(SYSCTL_CLKCFG1) | 145 SYSCTL_CLKCFG1_OTG_CLK_EN); 146 tmp = rt305x_sysctl_get(SYSCTL_RSTCTRL); 147 rt305x_sysctl_set(SYSCTL_RSTCTRL, tmp | SYSCTL_RSTCTRL_OTG); 148 DELAY(100); 149 /* 150 * Docs say that RSTCTRL bits for RT305x are W1C, so there should 151 * be no need for the below, but who really knows? 152 */ 153// rt305x_sysctl_set(SYSCTL_RSTCTRL, tmp & ~SYSCTL_RSTCTRL_OTG); 154// DELAY(100); 155 156 err = dwc_otg_init(sc); 157 if (err) printf("dotg_init fail\n"); 158 if (!err) { 159 err = device_probe_and_attach(sc->sc_bus.bdev); 160 if (err) printf("device_probe_and_attach fail %d\n", err); 161 } 162 if (err) { 163 goto error; 164 } 165 return (0); 166 167error: 168 dotg_obio_detach(dev); 169 return (ENXIO); 170} 171 172static int 173dotg_obio_detach(device_t dev) 174{ 175 struct dwc_otg_softc *sc = device_get_softc(dev); 176 int err; 177 178 /* during module unload there are lots of children leftover */ 179 device_delete_children(dev); 180 181 if (sc->sc_irq_res && sc->sc_intr_hdl) { 182 /* 183 * only call dotg_obio_uninit() after dotg_obio_init() 184 */ 185 dwc_otg_uninit(sc); 186 187 /* Stop OTG clock */ 188 rt305x_sysctl_set(SYSCTL_CLKCFG1, 189 rt305x_sysctl_get(SYSCTL_CLKCFG1) & 190 ~SYSCTL_CLKCFG1_OTG_CLK_EN); 191 192 err = bus_teardown_intr(dev, sc->sc_irq_res, 193 sc->sc_intr_hdl); 194 sc->sc_intr_hdl = NULL; 195 } 196 if (sc->sc_irq_res) { 197 bus_release_resource(dev, SYS_RES_IRQ, 0, 198 sc->sc_irq_res); 199 sc->sc_irq_res = NULL; 200 } 201 if (sc->sc_io_res) { 202 bus_release_resource(dev, SYS_RES_MEMORY, 0, 203 sc->sc_io_res); 204 sc->sc_io_res = NULL; 205 } 206 usb_bus_mem_free_all(&sc->sc_bus, NULL); 207 208 return (0); 209} 210 211static device_method_t dotg_obio_methods[] = { 212 /* Device interface */ 213 DEVMETHOD(device_probe, dotg_obio_probe), 214 DEVMETHOD(device_attach, dotg_obio_attach), 215 DEVMETHOD(device_detach, dotg_obio_detach), 216 DEVMETHOD(device_suspend, bus_generic_suspend), 217 DEVMETHOD(device_resume, bus_generic_resume), 218 DEVMETHOD(device_shutdown, bus_generic_shutdown), 219 220 DEVMETHOD_END 221}; 222 223static driver_t dotg_obio_driver = { 224 .name = "dwcotg", 225 .methods = dotg_obio_methods, 226 .size = sizeof(struct dwc_otg_softc), 227}; 228 229static devclass_t dotg_obio_devclass; 230 231DRIVER_MODULE(dwcotg, obio, dotg_obio_driver, dotg_obio_devclass, 0, 0); 232