1 /* $NetBSD: ti_motg.c,v 1.5 2024/02/02 22:14:04 andvar 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.5 2024/02/02 22:14:04 andvar 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 attachment 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
ti_motg_match(device_t parent,cfdata_t match,void * aux)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
ti_motg_attach(device_t parent,device_t self,void * aux)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
ti_motg_intr(void * v)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
ti_motg_poll(void * v)217 ti_motg_poll(void *v)
218 {
219 ti_motg_intr(v);
220 }
221