musb_otg_atmelarm.c revision 330897
1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28#include <sys/cdefs.h> 29__FBSDID("$FreeBSD: stable/11/sys/dev/usb/controller/musb_otg_atmelarm.c 330897 2018-03-14 03:19:51Z eadler $"); 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 50#include <dev/usb/usb.h> 51#include <dev/usb/usbdi.h> 52 53#include <dev/usb/usb_core.h> 54#include <dev/usb/usb_busdma.h> 55#include <dev/usb/usb_process.h> 56#include <dev/usb/usb_util.h> 57 58#include <dev/usb/usb_controller.h> 59#include <dev/usb/usb_bus.h> 60#include <dev/usb/controller/musb_otg.h> 61 62#include <sys/rman.h> 63 64static device_probe_t musbotg_probe; 65static device_attach_t musbotg_attach; 66static device_detach_t musbotg_detach; 67 68struct musbotg_super_softc { 69 struct musbotg_softc sc_otg; /* must be first */ 70}; 71 72static void 73musbotg_vbus_poll(struct musbotg_super_softc *sc) 74{ 75 uint8_t vbus_val = 1; /* fake VBUS on - TODO */ 76 77 /* just forward it */ 78 musbotg_vbus_interrupt(&sc->sc_otg, vbus_val); 79} 80 81static void 82musbotg_clocks_on(void *arg) 83{ 84#if 0 85 struct musbotg_super_softc *sc = arg; 86 87#endif 88} 89 90static void 91musbotg_clocks_off(void *arg) 92{ 93#if 0 94 struct musbotg_super_softc *sc = arg; 95 96#endif 97} 98 99static void 100musbotg_wrapper_interrupt(void *arg) 101{ 102 103 /* 104 * Nothing to do. 105 * Main driver takes care about everything 106 */ 107 musbotg_interrupt(arg, 0, 0, 0); 108} 109 110static void 111musbotg_ep_int_set(struct musbotg_softc *sc, int ep, int on) 112{ 113 /* 114 * Nothing to do. 115 * Main driver takes care about everything 116 */ 117} 118 119static int 120musbotg_probe(device_t dev) 121{ 122 device_set_desc(dev, "MUSB OTG integrated USB controller"); 123 return (0); 124} 125 126static int 127musbotg_attach(device_t dev) 128{ 129 struct musbotg_super_softc *sc = device_get_softc(dev); 130 int err; 131 int rid; 132 133 /* setup MUSB OTG USB controller interface softc */ 134 sc->sc_otg.sc_clocks_on = &musbotg_clocks_on; 135 sc->sc_otg.sc_clocks_off = &musbotg_clocks_off; 136 sc->sc_otg.sc_clocks_arg = sc; 137 138 /* initialise some bus fields */ 139 sc->sc_otg.sc_bus.parent = dev; 140 sc->sc_otg.sc_bus.devices = sc->sc_otg.sc_devices; 141 sc->sc_otg.sc_bus.devices_max = MUSB2_MAX_DEVICES; 142 sc->sc_otg.sc_bus.dma_bits = 32; 143 144 /* get all DMA memory */ 145 if (usb_bus_mem_alloc_all(&sc->sc_otg.sc_bus, 146 USB_GET_DMA_TAG(dev), NULL)) { 147 return (ENOMEM); 148 } 149 rid = 0; 150 sc->sc_otg.sc_io_res = 151 bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 152 153 if (!(sc->sc_otg.sc_io_res)) { 154 err = ENOMEM; 155 goto error; 156 } 157 sc->sc_otg.sc_io_tag = rman_get_bustag(sc->sc_otg.sc_io_res); 158 sc->sc_otg.sc_io_hdl = rman_get_bushandle(sc->sc_otg.sc_io_res); 159 sc->sc_otg.sc_io_size = rman_get_size(sc->sc_otg.sc_io_res); 160 161 rid = 0; 162 sc->sc_otg.sc_irq_res = 163 bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); 164 if (!(sc->sc_otg.sc_irq_res)) { 165 goto error; 166 } 167 sc->sc_otg.sc_bus.bdev = device_add_child(dev, "usbus", -1); 168 if (!(sc->sc_otg.sc_bus.bdev)) { 169 goto error; 170 } 171 device_set_ivars(sc->sc_otg.sc_bus.bdev, &sc->sc_otg.sc_bus); 172 173 sc->sc_otg.sc_id = 0; 174 sc->sc_otg.sc_platform_data = sc; 175 sc->sc_otg.sc_mode = MUSB2_DEVICE_MODE; 176 177#if (__FreeBSD_version >= 700031) 178 err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 179 NULL, (driver_intr_t *)musbotg_wrapper_interrupt, sc, &sc->sc_otg.sc_intr_hdl); 180#else 181 err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 182 (driver_intr_t *)musbotg_wrapper_interrupt, sc, &sc->sc_otg.sc_intr_hdl); 183#endif 184 if (err) { 185 sc->sc_otg.sc_intr_hdl = NULL; 186 goto error; 187 } 188 err = musbotg_init(&sc->sc_otg); 189 if (!err) { 190 err = device_probe_and_attach(sc->sc_otg.sc_bus.bdev); 191 } 192 if (err) { 193 goto error; 194 } else { 195 /* poll VBUS one time */ 196 musbotg_vbus_poll(sc); 197 } 198 return (0); 199 200error: 201 musbotg_detach(dev); 202 return (ENXIO); 203} 204 205static int 206musbotg_detach(device_t dev) 207{ 208 struct musbotg_super_softc *sc = device_get_softc(dev); 209 int err; 210 211 /* during module unload there are lots of children leftover */ 212 device_delete_children(dev); 213 214 if (sc->sc_otg.sc_irq_res && sc->sc_otg.sc_intr_hdl) { 215 /* 216 * only call musbotg_uninit() after musbotg_init() 217 */ 218 musbotg_uninit(&sc->sc_otg); 219 220 err = bus_teardown_intr(dev, sc->sc_otg.sc_irq_res, 221 sc->sc_otg.sc_intr_hdl); 222 sc->sc_otg.sc_intr_hdl = NULL; 223 } 224 /* free IRQ channel, if any */ 225 if (sc->sc_otg.sc_irq_res) { 226 bus_release_resource(dev, SYS_RES_IRQ, 0, 227 sc->sc_otg.sc_irq_res); 228 sc->sc_otg.sc_irq_res = NULL; 229 } 230 /* free memory resource, if any */ 231 if (sc->sc_otg.sc_io_res) { 232 bus_release_resource(dev, SYS_RES_MEMORY, 0, 233 sc->sc_otg.sc_io_res); 234 sc->sc_otg.sc_io_res = NULL; 235 } 236 usb_bus_mem_free_all(&sc->sc_otg.sc_bus, NULL); 237 238 return (0); 239} 240 241static device_method_t musbotg_methods[] = { 242 /* Device interface */ 243 DEVMETHOD(device_probe, musbotg_probe), 244 DEVMETHOD(device_attach, musbotg_attach), 245 DEVMETHOD(device_detach, musbotg_detach), 246 DEVMETHOD(device_suspend, bus_generic_suspend), 247 DEVMETHOD(device_resume, bus_generic_resume), 248 DEVMETHOD(device_shutdown, bus_generic_shutdown), 249 250 DEVMETHOD_END 251}; 252 253static driver_t musbotg_driver = { 254 .name = "musbotg", 255 .methods = musbotg_methods, 256 .size = sizeof(struct musbotg_super_softc), 257}; 258 259static devclass_t musbotg_devclass; 260 261DRIVER_MODULE(musbotg, atmelarm, musbotg_driver, musbotg_devclass, 0, 0); 262MODULE_DEPEND(musbotg, usb, 1, 1, 1); 263