1 /* $NetBSD: ti_motg.c,v 1.4 2021/01/27 03:10:20 thorpej 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.4 2021/01/27 03:10:20 thorpej 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 56 extern 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 64 static const struct device_compatible_entry compat_data[] = { 65 { .compat = "ti,musb-am33xx" }, 66 DEVICE_COMPAT_EOL 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 75 struct 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 83 static int ti_motg_match(device_t, cfdata_t, void *); 84 static void ti_motg_attach(device_t, device_t, void *); 85 static int ti_motg_intr(void *); 86 static void ti_motg_poll(void *); 87 88 CFATTACH_DECL_NEW(ti_motg, sizeof(struct ti_motg_softc), 89 ti_motg_match, ti_motg_attach, NULL, NULL); 90 91 static int 92 ti_motg_match(device_t parent, cfdata_t match, void *aux) 93 { 94 struct fdt_attach_args * const faa = aux; 95 96 return of_compatible_match(faa->faa_phandle, compat_data); 97 } 98 99 static void 100 ti_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_xname(phandle, 0, IPL_USB, 0, 130 ti_motg_intr, sc, device_xname(self)); 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 185 static int 186 ti_motg_intr(void *v) 187 { 188 struct ti_motg_softc *sc = v; 189 uint32_t stat, stat0, stat1; 190 int rv; 191 192 MOTGHIST_FUNC(); MOTGHIST_CALLED(); 193 194 mutex_spin_enter(&sc->sc_motg.sc_intr_lock); 195 stat = TIOTG_USBC_READ4(sc, USBCTRL_STAT); 196 stat0 = TIOTG_USBC_READ4(sc, USBCTRL_IRQ_STAT0); 197 stat1 = TIOTG_USBC_READ4(sc, USBCTRL_IRQ_STAT1); 198 DPRINTF("USB %jd 0x%jx 0x%jx stat %jd", 199 sc->sc_ctrlport, stat0, stat1, stat); 200 201 if (stat0) { 202 TIOTG_USBC_WRITE4(sc, USBCTRL_IRQ_STAT0, stat0); 203 } 204 if (stat1) { 205 TIOTG_USBC_WRITE4(sc, USBCTRL_IRQ_STAT1, stat1); 206 } 207 if (stat1 & USBCTRL_IRQ_STAT1_DRVVBUS) { 208 motg_intr_vbus(&sc->sc_motg, stat & 0x1); 209 } 210 rv = motg_intr(&sc->sc_motg, ((stat0 >> 16) & 0xffff), 211 stat0 & 0xffff, stat1 & 0xff); 212 mutex_spin_exit(&sc->sc_motg.sc_intr_lock); 213 return rv; 214 } 215 216 static void 217 ti_motg_poll(void *v) 218 { 219 ti_motg_intr(v); 220 } 221