am335x_usbss.c revision 283276
1/*- 2 * Copyright (c) 2013 Oleksandr Tymoshenko <gonzo@freebsd.org> 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26#include <sys/cdefs.h> 27__FBSDID("$FreeBSD: head/sys/arm/ti/am335x/am335x_usbss.c 283276 2015-05-22 03:16:18Z gonzo $"); 28 29#include <sys/stdint.h> 30#include <sys/stddef.h> 31#include <sys/param.h> 32#include <sys/queue.h> 33#include <sys/types.h> 34#include <sys/systm.h> 35#include <sys/kernel.h> 36#include <sys/bus.h> 37#include <sys/module.h> 38#include <sys/lock.h> 39#include <sys/mutex.h> 40#include <sys/condvar.h> 41#include <sys/sysctl.h> 42#include <sys/sx.h> 43#include <sys/unistd.h> 44#include <sys/callout.h> 45#include <sys/malloc.h> 46#include <sys/priv.h> 47 48#include <dev/fdt/fdt_common.h> 49#include <dev/fdt/simplebus.h> 50#include <dev/ofw/openfirm.h> 51#include <dev/ofw/ofw_bus.h> 52#include <dev/ofw/ofw_bus_subr.h> 53 54#include <dev/usb/usb.h> 55#include <dev/usb/usbdi.h> 56 57#include <dev/usb/usb_core.h> 58#include <dev/usb/usb_busdma.h> 59#include <dev/usb/usb_process.h> 60#include <dev/usb/usb_util.h> 61 62#include <dev/usb/usb_controller.h> 63#include <dev/usb/usb_bus.h> 64#include <dev/usb/controller/musb_otg.h> 65#include <dev/usb/usb_debug.h> 66 67#include <sys/rman.h> 68 69#include <arm/ti/ti_prcm.h> 70#include <arm/ti/ti_scm.h> 71#include <arm/ti/am335x/am335x_scm.h> 72 73#define AM335X_USB_PORTS 2 74 75#define USBSS_REVREG 0x00 76#define USBSS_SYSCONFIG 0x10 77#define USBSS_SYSCONFIG_SRESET 1 78 79#define USBCTRL_REV 0x00 80#define USBCTRL_CTRL 0x14 81#define USBCTRL_STAT 0x18 82#define USBCTRL_IRQ_STAT0 0x30 83#define IRQ_STAT0_RXSHIFT 16 84#define IRQ_STAT0_TXSHIFT 0 85#define USBCTRL_IRQ_STAT1 0x34 86#define IRQ_STAT1_DRVVBUS (1 << 8) 87#define USBCTRL_INTEN_SET0 0x38 88#define USBCTRL_INTEN_SET1 0x3C 89#define USBCTRL_INTEN_USB_ALL 0x1ff 90#define USBCTRL_INTEN_USB_SOF (1 << 3) 91#define USBCTRL_INTEN_CLR0 0x40 92#define USBCTRL_INTEN_CLR1 0x44 93#define USBCTRL_UTMI 0xE0 94#define USBCTRL_UTMI_FSDATAEXT (1 << 1) 95#define USBCTRL_MODE 0xE8 96#define USBCTRL_MODE_IDDIG (1 << 8) 97#define USBCTRL_MODE_IDDIGMUX (1 << 7) 98 99#define USBSS_WRITE4(sc, reg, val) \ 100 bus_write_4((sc)->sc_mem_res, (reg), (val)) 101#define USBSS_READ4(sc, reg) \ 102 bus_read_4((sc)->sc_mem_res, (reg)) 103 104static device_probe_t usbss_probe; 105static device_attach_t usbss_attach; 106static device_detach_t usbss_detach; 107 108struct usbss_softc { 109 struct simplebus_softc simplebus_sc; 110 struct resource *sc_mem_res; 111 int sc_mem_rid; 112}; 113 114static int 115usbss_probe(device_t dev) 116{ 117 118 if (!ofw_bus_status_okay(dev)) 119 return (ENXIO); 120 121 if (!ofw_bus_is_compatible(dev, "ti,am33xx-usb")) 122 return (ENXIO); 123 124 device_set_desc(dev, "TI AM33xx integrated USB OTG controller"); 125 126 return (BUS_PROBE_DEFAULT); 127} 128 129static int 130usbss_attach(device_t dev) 131{ 132 struct usbss_softc *sc = device_get_softc(dev); 133 int i; 134 uint32_t rev; 135 phandle_t node; 136 137 /* Request the memory resources */ 138 sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 139 &sc->sc_mem_rid, RF_ACTIVE); 140 if (sc->sc_mem_res == NULL) { 141 device_printf(dev, 142 "Error: could not allocate mem resources\n"); 143 return (ENXIO); 144 } 145 146 /* Enable device clocks. */ 147 ti_prcm_clk_enable(MUSB0_CLK); 148 149 /* 150 * Reset USBSS, USB0 and USB1. 151 * The registers of USB subsystem must not be accessed while the 152 * reset pulse is active (200ns). 153 */ 154 USBSS_WRITE4(sc, USBSS_SYSCONFIG, USBSS_SYSCONFIG_SRESET); 155 DELAY(100); 156 i = 10; 157 while (USBSS_READ4(sc, USBSS_SYSCONFIG) & USBSS_SYSCONFIG_SRESET) { 158 DELAY(100); 159 if (i-- == 0) { 160 device_printf(dev, "reset timeout.\n"); 161 return (ENXIO); 162 } 163 } 164 165 /* Read the module revision. */ 166 rev = USBSS_READ4(sc, USBSS_REVREG); 167 device_printf(dev, "TI AM335X USBSS v%d.%d.%d\n", 168 (rev >> 8) & 7, (rev >> 6) & 3, rev & 63); 169 170 node = ofw_bus_get_node(dev); 171 172 if (node == -1) { 173 usbss_detach(dev); 174 return (ENXIO); 175 } 176 177 simplebus_init(dev, node); 178 179 /* 180 * Allow devices to identify. 181 */ 182 bus_generic_probe(dev); 183 184 /* 185 * Now walk the OFW tree and attach top-level devices. 186 */ 187 for (node = OF_child(node); node > 0; node = OF_peer(node)) 188 simplebus_add_device(dev, node, 0, NULL, -1, NULL); 189 190 return (bus_generic_attach(dev)); 191} 192 193static int 194usbss_detach(device_t dev) 195{ 196 struct usbss_softc *sc = device_get_softc(dev); 197 198 /* Free resources if any */ 199 if (sc->sc_mem_res) 200 bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mem_rid, 201 sc->sc_mem_res); 202 203 /* during module unload there are lots of children leftover */ 204 device_delete_children(dev); 205 206 return (0); 207} 208 209static device_method_t usbss_methods[] = { 210 /* Device interface */ 211 DEVMETHOD(device_probe, usbss_probe), 212 DEVMETHOD(device_attach, usbss_attach), 213 DEVMETHOD(device_detach, usbss_detach), 214 DEVMETHOD(device_suspend, bus_generic_suspend), 215 DEVMETHOD(device_resume, bus_generic_resume), 216 DEVMETHOD(device_shutdown, bus_generic_shutdown), 217 218 DEVMETHOD_END 219}; 220 221DEFINE_CLASS_1(usbss, usbss_driver, usbss_methods, 222 sizeof(struct usbss_softc), simplebus_driver); 223static devclass_t usbss_devclass; 224DRIVER_MODULE(usbss, simplebus, usbss_driver, usbss_devclass, 0, 0); 225MODULE_DEPEND(usbss, usb, 1, 1, 1); 226