ti_motg.c revision 1.1
1/* $NetBSD: ti_motg.c,v 1.1 2019/10/27 16:31:26 jmcneill Exp $ */ 2/* 3 * Copyright (c) 2013 Manuel Bouyer. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include <sys/cdefs.h> 27__KERNEL_RCSID(0, "$NetBSD: ti_motg.c,v 1.1 2019/10/27 16:31:26 jmcneill Exp $"); 28 29#include <sys/param.h> 30#include <sys/systm.h> 31#include <sys/device.h> 32#include <sys/conf.h> 33#include <sys/bus.h> 34#include <sys/proc.h> 35#include <sys/kernel.h> 36#include <sys/mutex.h> 37#include <sys/condvar.h> 38 39#include <arm/ti/ti_prcm.h> 40#include <arm/ti/ti_otgreg.h> 41 42#include <dev/usb/usb.h> 43#include <dev/usb/usbdi.h> 44#include <dev/usb/usbdivar.h> 45#include <dev/usb/usb_mem.h> 46#include <dev/usb/motgreg.h> 47#include <dev/usb/motgvar.h> 48#include <dev/usb/usbhist.h> 49 50#include <dev/fdt/fdtvar.h> 51 52#ifdef USB_DEBUG 53#ifndef MOTG_DEBUG 54#define motgdebug 0 55#else 56extern int motgdebug; 57#endif /* MOTG_DEBUG */ 58#endif /* USB_DEBUG */ 59 60#define DPRINTF(FMT,A,B,C,D) USBHIST_LOGN(motgdebug,1,FMT,A,B,C,D) 61#define MOTGHIST_FUNC() USBHIST_FUNC() 62#define MOTGHIST_CALLED(name) USBHIST_CALLED(motgdebug) 63 64static const char * compatible [] = { 65 "ti,musb-am33xx", 66 NULL 67}; 68 69/* 70 * motg device attachement and driver, 71 * for the per-port part of the controller: TI-specific part, phy and 72 * MI Mentor OTG. 73 */ 74 75struct ti_motg_softc { 76 struct motg_softc sc_motg; 77 bus_space_tag_t sc_ctrliot; 78 bus_space_handle_t sc_ctrlioh; 79 void * sc_ctrlih; 80 int sc_ctrlport; 81}; 82 83static int ti_motg_match(device_t, cfdata_t, void *); 84static void ti_motg_attach(device_t, device_t, void *); 85static int ti_motg_intr(void *); 86static void ti_motg_poll(void *); 87 88CFATTACH_DECL_NEW(ti_motg, sizeof(struct ti_motg_softc), 89 ti_motg_match, ti_motg_attach, NULL, NULL); 90 91static int 92ti_motg_match(device_t parent, cfdata_t match, void *aux) 93{ 94 struct fdt_attach_args * const faa = aux; 95 96 return of_match_compatible(faa->faa_phandle, compatible); 97} 98 99static void 100ti_motg_attach(device_t parent, device_t self, void *aux) 101{ 102 struct ti_motg_softc *sc = device_private(self); 103 struct fdt_attach_args * const faa = aux; 104 const int phandle = faa->faa_phandle; 105 char intrstr[128]; 106 bus_addr_t addr[2]; 107 bus_size_t size[2]; 108 uint32_t val; 109 110 MOTGHIST_FUNC(); MOTGHIST_CALLED(); 111 112 if (fdtbus_get_reg_byname(phandle, "mc", &addr[0], &size[0]) != 0 || 113 fdtbus_get_reg_byname(phandle, "control", &addr[1], &size[1])) { 114 aprint_error(": couldn't get registers\n"); 115 return; 116 } 117 118 if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) { 119 aprint_error(": couldn't decode interrupt\n"); 120 return; 121 } 122 123 sc->sc_motg.sc_dev = self; 124 sc->sc_ctrliot = faa->faa_bst; 125 if (bus_space_map(sc->sc_ctrliot, addr[1], size[1], 0, &sc->sc_ctrlioh) != 0) { 126 aprint_error(": couldn't map registers\n"); 127 return; 128 } 129 sc->sc_ctrlih = fdtbus_intr_establish(phandle, 0, IPL_USB, 0, 130 ti_motg_intr, sc); 131 sc->sc_motg.sc_bus.ub_dmatag = faa->faa_dmat; 132 133 val = TIOTG_USBC_READ4(sc, USBCTRL_REV); 134 aprint_normal(": 0x%x version v%d.%d.%d", val, 135 (val >> 8) & 7, (val >> 6) & 3, val & 63); 136 137 /* XXX configure mode */ 138#if 0 139 if (sc->sc_ctrlport == 0) 140 sc->sc_motg.sc_mode = MOTG_MODE_DEVICE; 141 else 142 sc->sc_motg.sc_mode = MOTG_MODE_HOST; 143#else 144 /* XXXXX 145 * Both ports always the host mode only. 146 * And motg(4) doesn't supports device and OTG modes. 147 */ 148 sc->sc_motg.sc_mode = MOTG_MODE_HOST; 149#endif 150 if (sc->sc_motg.sc_mode == MOTG_MODE_HOST) { 151 val = TIOTG_USBC_READ4(sc, USBCTRL_MODE); 152 val |= USBCTRL_MODE_IDDIGMUX; 153 val &= ~USBCTRL_MODE_IDDIG; 154 TIOTG_USBC_WRITE4(sc, USBCTRL_MODE, val); 155 TIOTG_USBC_WRITE4(sc, USBCTRL_UTMI, USBCTRL_UTMI_FSDATAEXT); 156 } else { 157 val = TIOTG_USBC_READ4(sc, USBCTRL_MODE); 158 val |= USBCTRL_MODE_IDDIGMUX; 159 val |= USBCTRL_MODE_IDDIG; 160 TIOTG_USBC_WRITE4(sc, USBCTRL_MODE, val); 161 } 162 163 aprint_normal("\n"); 164 aprint_naive("\n"); 165 166 aprint_normal_dev(self, "interrupting on %s\n", intrstr); 167 168 sc->sc_motg.sc_iot = faa->faa_bst; 169 if (bus_space_map(sc->sc_motg.sc_iot, addr[0], size[0], 0, 170 &sc->sc_motg.sc_ioh) != 0) { 171 aprint_error_dev(self, "couldn't map mc registers\n"); 172 return; 173 } 174 sc->sc_motg.sc_size = size[0]; 175 sc->sc_motg.sc_intr_poll = ti_motg_poll; 176 sc->sc_motg.sc_intr_poll_arg = sc; 177 delay(10); 178 motg_init(&sc->sc_motg); 179 /* enable interrupts */ 180 TIOTG_USBC_WRITE4(sc, USBCTRL_INTEN_SET0, 0xffffffff); 181 TIOTG_USBC_WRITE4(sc, USBCTRL_INTEN_SET1, 182 USBCTRL_INTEN_USB_ALL & ~USBCTRL_INTEN_USB_SOF); 183} 184 185static int 186ti_motg_intr(void *v) 187{ 188 struct ti_motg_softc *sc = v; 189 uint32_t stat, stat0, stat1; 190 int rv = 0; 191 int i; 192 193 MOTGHIST_FUNC(); MOTGHIST_CALLED(); 194 195 mutex_spin_enter(&sc->sc_motg.sc_intr_lock); 196 stat = TIOTG_USBC_READ4(sc, USBCTRL_STAT); 197 stat0 = TIOTG_USBC_READ4(sc, USBCTRL_IRQ_STAT0); 198 stat1 = TIOTG_USBC_READ4(sc, USBCTRL_IRQ_STAT1); 199 DPRINTF("USB %jd 0x%jx 0x%jx stat %jd", 200 sc->sc_ctrlport, stat0, stat1, stat); 201 /* try to deal with vbus errors */ 202 if (stat1 & MUSB2_MASK_IVBUSERR ) { 203 stat1 &= ~MUSB2_MASK_IVBUSERR; 204 for (i = 0; i < 1000; i++) { 205 TIOTG_USBC_WRITE4(sc, USBCTRL_IRQ_STAT1, 206 MUSB2_MASK_IVBUSERR); 207 motg_intr_vbus(&sc->sc_motg, stat & 0x1); 208 delay(1000); 209 stat = TIOTG_USBC_READ4(sc, USBCTRL_STAT); 210 if (stat & 0x1) 211 break; 212 } 213 } 214 if (stat0) { 215 TIOTG_USBC_WRITE4(sc, USBCTRL_IRQ_STAT0, stat0); 216 } 217 if (stat1) { 218 TIOTG_USBC_WRITE4(sc, USBCTRL_IRQ_STAT1, stat1); 219 } 220 if ((stat & 0x1) == 0) { 221 mutex_spin_exit(&sc->sc_motg.sc_intr_lock); 222 aprint_error_dev(sc->sc_motg.sc_dev, ": vbus error\n"); 223 return 1; 224 } 225 if (stat0 != 0 || stat1 != 0) { 226 rv = motg_intr(&sc->sc_motg, ((stat0 >> 16) & 0xffff), 227 stat0 & 0xffff, stat1 & 0xff); 228 } 229 mutex_spin_exit(&sc->sc_motg.sc_intr_lock); 230 return rv; 231} 232 233static void 234ti_motg_poll(void *v) 235{ 236 ti_motg_intr(v); 237} 238