xref: /netbsd-src/sys/arch/arm/ti/ti_motg.c (revision c865d5f42312d1ee2f6e7c6b7c4369aabae2f95d)
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