1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2013 Oleksandr Tymoshenko <gonzo@freebsd.org> 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$"); 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/fdt/simplebus.h> 51#include <dev/ofw/openfirm.h> 52#include <dev/ofw/ofw_bus.h> 53#include <dev/ofw/ofw_bus_subr.h> 54 55#include <dev/usb/usb.h> 56#include <dev/usb/usbdi.h> 57 58#include <dev/usb/usb_core.h> 59#include <dev/usb/usb_busdma.h> 60#include <dev/usb/usb_process.h> 61#include <dev/usb/usb_util.h> 62 63#include <dev/usb/usb_controller.h> 64#include <dev/usb/usb_bus.h> 65#include <dev/usb/controller/musb_otg.h> 66#include <dev/usb/usb_debug.h> 67 68#include <sys/rman.h> 69 70#include <arm/ti/ti_prcm.h> 71#include <arm/ti/ti_scm.h> 72#include <arm/ti/am335x/am335x_scm.h> 73 74#define AM335X_USB_PORTS 2 75 76#define USBSS_REVREG 0x00 77#define USBSS_SYSCONFIG 0x10 78#define USBSS_SYSCONFIG_SRESET 1 79 80#define USBCTRL_REV 0x00 81#define USBCTRL_CTRL 0x14 82#define USBCTRL_STAT 0x18 83#define USBCTRL_IRQ_STAT0 0x30 84#define IRQ_STAT0_RXSHIFT 16 85#define IRQ_STAT0_TXSHIFT 0 86#define USBCTRL_IRQ_STAT1 0x34 87#define IRQ_STAT1_DRVVBUS (1 << 8) 88#define USBCTRL_INTEN_SET0 0x38 89#define USBCTRL_INTEN_SET1 0x3C 90#define USBCTRL_INTEN_USB_ALL 0x1ff 91#define USBCTRL_INTEN_USB_SOF (1 << 3) 92#define USBCTRL_INTEN_CLR0 0x40 93#define USBCTRL_INTEN_CLR1 0x44 94#define USBCTRL_UTMI 0xE0 95#define USBCTRL_UTMI_FSDATAEXT (1 << 1) 96#define USBCTRL_MODE 0xE8 97#define USBCTRL_MODE_IDDIG (1 << 8) 98#define USBCTRL_MODE_IDDIGMUX (1 << 7) 99 100#define USBSS_WRITE4(sc, reg, val) \ 101 bus_write_4((sc)->sc_mem_res, (reg), (val)) 102#define USBSS_READ4(sc, reg) \ 103 bus_read_4((sc)->sc_mem_res, (reg)) 104 105static device_probe_t usbss_probe; 106static device_attach_t usbss_attach; 107static device_detach_t usbss_detach; 108 109struct usbss_softc { 110 struct simplebus_softc simplebus_sc; 111 struct resource *sc_mem_res; 112 int sc_mem_rid; 113}; 114 115static int 116usbss_probe(device_t dev) 117{ 118 119 if (!ofw_bus_status_okay(dev)) 120 return (ENXIO); 121 122 if (!ofw_bus_is_compatible(dev, "ti,am33xx-usb")) 123 return (ENXIO); 124 125 device_set_desc(dev, "TI AM33xx integrated USB OTG controller"); 126 127 return (BUS_PROBE_DEFAULT); 128} 129 130static int 131usbss_attach(device_t dev) 132{ 133 struct usbss_softc *sc = device_get_softc(dev); 134 int i; 135 uint32_t rev; 136 phandle_t node; 137 138 /* Request the memory resources */ 139 sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 140 &sc->sc_mem_rid, RF_ACTIVE); 141 if (sc->sc_mem_res == NULL) { 142 device_printf(dev, 143 "Error: could not allocate mem resources\n"); 144 return (ENXIO); 145 } 146 147 /* Enable device clocks. */ 148 ti_prcm_clk_enable(MUSB0_CLK); 149 150 /* 151 * Reset USBSS, USB0 and USB1. 152 * The registers of USB subsystem must not be accessed while the 153 * reset pulse is active (200ns). 154 */ 155 USBSS_WRITE4(sc, USBSS_SYSCONFIG, USBSS_SYSCONFIG_SRESET); 156 DELAY(100); 157 i = 10; 158 while (USBSS_READ4(sc, USBSS_SYSCONFIG) & USBSS_SYSCONFIG_SRESET) { 159 DELAY(100); 160 if (i-- == 0) { 161 device_printf(dev, "reset timeout.\n"); 162 return (ENXIO); 163 } 164 } 165 166 /* Read the module revision. */ 167 rev = USBSS_READ4(sc, USBSS_REVREG); 168 device_printf(dev, "TI AM335X USBSS v%d.%d.%d\n", 169 (rev >> 8) & 7, (rev >> 6) & 3, rev & 63); 170 171 node = ofw_bus_get_node(dev); 172 173 if (node == -1) { 174 usbss_detach(dev); 175 return (ENXIO); 176 } 177 178 simplebus_init(dev, node); 179 180 /* 181 * Allow devices to identify. 182 */ 183 bus_generic_probe(dev); 184 185 /* 186 * Now walk the OFW tree and attach top-level devices. 187 */ 188 for (node = OF_child(node); node > 0; node = OF_peer(node)) 189 simplebus_add_device(dev, node, 0, NULL, -1, NULL); 190 191 return (bus_generic_attach(dev)); 192} 193 194static int 195usbss_detach(device_t dev) 196{ 197 struct usbss_softc *sc = device_get_softc(dev); 198 199 /* Free resources if any */ 200 if (sc->sc_mem_res) 201 bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mem_rid, 202 sc->sc_mem_res); 203 204 /* during module unload there are lots of children leftover */ 205 device_delete_children(dev); 206 207 return (0); 208} 209 210static device_method_t usbss_methods[] = { 211 /* Device interface */ 212 DEVMETHOD(device_probe, usbss_probe), 213 DEVMETHOD(device_attach, usbss_attach), 214 DEVMETHOD(device_detach, usbss_detach), 215 DEVMETHOD(device_suspend, bus_generic_suspend), 216 DEVMETHOD(device_resume, bus_generic_resume), 217 DEVMETHOD(device_shutdown, bus_generic_shutdown), 218 219 DEVMETHOD_END 220}; 221 222DEFINE_CLASS_1(usbss, usbss_driver, usbss_methods, 223 sizeof(struct usbss_softc), simplebus_driver); 224static devclass_t usbss_devclass; 225DRIVER_MODULE(usbss, simplebus, usbss_driver, usbss_devclass, 0, 0); 226MODULE_DEPEND(usbss, usb, 1, 1, 1); 227