1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2010-2012 Semihalf
5 * Copyright (c) 2012 The FreeBSD Foundation
6 * Copyright (c) 2013 Ian Lepore <ian@freebsd.org>
7 * All rights reserved.
8 *
9 * Portions of this software were developed by Oleksandr Rybalko
10 * under sponsorship from the FreeBSD Foundation.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 /*
35 * EHCI driver for Freescale i.MX SoCs which incorporate the USBOH3 controller.
36 */
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/module.h>
42 #include <sys/bus.h>
43 #include <sys/condvar.h>
44 #include <sys/rman.h>
45
46 #include <dev/ofw/ofw_bus.h>
47 #include <dev/ofw/ofw_bus_subr.h>
48
49 #include <dev/usb/usb.h>
50 #include <dev/usb/usbdi.h>
51 #include <dev/usb/usb_busdma.h>
52 #include <dev/usb/usb_process.h>
53 #include <dev/usb/usb_controller.h>
54 #include <dev/usb/usb_bus.h>
55 #include <dev/usb/controller/ehci.h>
56 #include <dev/usb/controller/ehcireg.h>
57 #include "usbdevs.h"
58
59 #include <machine/bus.h>
60 #include <machine/resource.h>
61
62 #include <arm/freescale/imx/imx_ccmvar.h>
63
64 #include "opt_platform.h"
65
66 /*
67 * Notes on the hardware and related FDT data seen in the wild.
68 *
69 * There are two sets of registers in the USBOH3 implementation; documentation
70 * refers to them as "core" and "non-core" registers. A set of core register
71 * exists for each OTG or EHCI device. There is a single set of non-core
72 * registers per USBOH3, and they control aspects of operation not directly
73 * related to the USB specs, such as whether interrupts from each of the core
74 * devices are able to generate a SoC wakeup event.
75 *
76 * In the FreeBSD universe we might be inclined to describe the core and
77 * non-core registers by using a pair of resource address/size values (two
78 * entries in the reg property for each core). However, we have to work with
79 * existing FDT data (which mostly comes from the linux universe), and the way
80 * they've chosen to represent this is with an entry for a "usbmisc" device
81 * whose reg property describes the non-core registers. The way we handle FDT
82 * data, this means that the resources (memory-mapped register range) for the
83 * non-core registers belongs to a device other than the echi devices.
84 *
85 * Because the main ehci device cannot access registers in a range that's
86 * defined in the fdt data as belonging to another device, we implement a teeny
87 * little "usbmisc" driver which exists only to provide access to the usbmisc
88 * control register for each of the 4 usb controller instances. That little
89 * driver is implemented here in this file, before the main driver.
90 *
91 * In addition to the single usbmisc device, the existing FDT data defines a
92 * separate device for each of the OTG or EHCI cores within the USBOH3. Each of
93 * those devices has a set of core registers described by the reg property.
94 *
95 * The core registers for each of the four cores in the USBOH3 are divided into
96 * two parts: a set of imx-specific registers at an offset of 0 from the
97 * beginning of the register range, and the standard USB (EHCI or OTG) registers
98 * at an offset of 0x100 from the beginning of the register range. The FreeBSD
99 * way of dealing with this might be to map out two ranges in the reg property,
100 * but that's not what the alternate universe has done. To work with existing
101 * FDT data, we acquire the resource that maps all the core registers, then use
102 * bus_space_subregion() to create another resource that maps just the standard
103 * USB registers, which we provide to the standard USB code in the ehci_softc.
104 *
105 * The following compat strings have been seen for the OTG and EHCI cores. The
106 * FDT compat table in this driver contains all these strings, but as of this
107 * writing, not all of these SoCs have been tested with the driver. The fact
108 * that imx27 is common to all of them gives some hope that the driver will work
109 * on all these SoCs.
110 * - "fsl,imx23-usb", "fsl,imx27-usb";
111 * - "fsl,imx25-usb", "fsl,imx27-usb";
112 * - "fsl,imx28-usb", "fsl,imx27-usb";
113 * - "fsl,imx51-usb", "fsl,imx27-usb";
114 * - "fsl,imx53-usb", "fsl,imx27-usb";
115 * - "fsl,imx6q-usb", "fsl,imx27-usb";
116 *
117 * The FDT data for some SoCs contains the following properties, which we don't
118 * currently do anything with:
119 * - fsl,usbmisc = <&usbmisc 0>;
120 * - fsl,usbphy = <&usbphy0>;
121 *
122 * Some imx SoCs have FDT data related to USB PHY, some don't. We have separate
123 * usbphy drivers where needed; this data is mentioned here just to keep all the
124 * imx-FDT-usb-related info in one place. Here are the usbphy compat strings
125 * known to exist:
126 * - "nop-usbphy"
127 * - "usb-nop-xceiv";
128 * - "fsl,imx23-usbphy"
129 * - "fsl,imx28-usbphy", "fsl,imx23-usbphy";
130 * - "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
131 *
132 */
133
134 /*-----------------------------------------------------------------------------
135 * imx_usbmisc driver
136 *---------------------------------------------------------------------------*/
137
138 #define USBNC_OVER_CUR_POL (1u << 8)
139 #define USBNC_OVER_CUR_DIS (1u << 7)
140
141 struct imx_usbmisc_softc {
142 device_t dev;
143 struct resource *mmio;
144 };
145
146 static struct ofw_compat_data usbmisc_compat_data[] = {
147 {"fsl,imx6q-usbmisc", true},
148 {"fsl,imx51-usbmisc", true},
149 {"fsl,imx25-usbmisc", true},
150 {NULL, false},
151 };
152
153 static void
imx_usbmisc_set_ctrl(device_t dev,u_int index,uint32_t bits)154 imx_usbmisc_set_ctrl(device_t dev, u_int index, uint32_t bits)
155 {
156 struct imx_usbmisc_softc *sc;
157 uint32_t reg;
158
159 sc = device_get_softc(dev);
160 reg = bus_read_4(sc->mmio, index * sizeof(uint32_t));
161 bus_write_4(sc->mmio, index * sizeof(uint32_t), reg | bits);
162 }
163
164 #ifdef notyet
165 static void
imx_usbmisc_clr_ctrl(device_t dev,u_int index,uint32_t bits)166 imx_usbmisc_clr_ctrl(device_t dev, u_int index, uint32_t bits)
167 {
168 struct imx_usbmisc_softc *sc;
169 uint32_t reg;
170
171 sc = device_get_softc(dev);
172 reg = bus_read_4(sc->mmio, index * sizeof(uint32_t));
173 bus_write_4(sc->mmio, index * sizeof(uint32_t), reg & ~bits);
174 }
175 #endif
176
177 static int
imx_usbmisc_probe(device_t dev)178 imx_usbmisc_probe(device_t dev)
179 {
180
181 if (!ofw_bus_status_okay(dev))
182 return (ENXIO);
183
184 if (ofw_bus_search_compatible(dev, usbmisc_compat_data)->ocd_data) {
185 device_set_desc(dev, "i.MX USB Misc Control");
186 return (BUS_PROBE_DEFAULT);
187 }
188 return (ENXIO);
189 }
190
191 static int
imx_usbmisc_detach(device_t dev)192 imx_usbmisc_detach(device_t dev)
193 {
194 struct imx_usbmisc_softc *sc;
195
196 sc = device_get_softc(dev);
197
198 if (sc->mmio != NULL)
199 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mmio);
200
201 return (0);
202 }
203
204 static int
imx_usbmisc_attach(device_t dev)205 imx_usbmisc_attach(device_t dev)
206 {
207 struct imx_usbmisc_softc *sc;
208 int rid;
209
210 sc = device_get_softc(dev);
211
212 /* Allocate bus_space resources. */
213 rid = 0;
214 sc->mmio = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
215 RF_ACTIVE);
216 if (sc->mmio == NULL) {
217 device_printf(dev, "Cannot allocate memory resources\n");
218 return (ENXIO);
219 }
220
221 OF_device_register_xref(OF_xref_from_node(ofw_bus_get_node(dev)), dev);
222
223 return (0);
224 }
225
226 static device_method_t imx_usbmisc_methods[] = {
227 /* Device interface */
228 DEVMETHOD(device_probe, imx_usbmisc_probe),
229 DEVMETHOD(device_attach, imx_usbmisc_attach),
230 DEVMETHOD(device_detach, imx_usbmisc_detach),
231
232 DEVMETHOD_END
233 };
234
235 static driver_t imx_usbmisc_driver = {
236 "imx_usbmisc",
237 imx_usbmisc_methods,
238 sizeof(struct imx_usbmisc_softc)
239 };
240
241 /*
242 * This driver needs to start before the ehci driver, but later than the usual
243 * "special" drivers like clocks and cpu. Ehci starts at DEFAULT so
244 * DEFAULT-1000 seems good.
245 */
246 EARLY_DRIVER_MODULE(imx_usbmisc, simplebus, imx_usbmisc_driver,
247 0, 0, BUS_PASS_DEFAULT - 1000);
248
249 /*-----------------------------------------------------------------------------
250 * imx_ehci driver...
251 *---------------------------------------------------------------------------*/
252
253 /*
254 * Each EHCI device in the SoC has some SoC-specific per-device registers at an
255 * offset of 0, then the standard EHCI registers begin at an offset of 0x100.
256 */
257 #define IMX_EHCI_REG_OFF 0x100
258 #define IMX_EHCI_REG_SIZE 0x100
259
260 struct imx_ehci_softc {
261 ehci_softc_t ehci_softc;
262 device_t dev;
263 struct resource *ehci_mem_res; /* EHCI core regs. */
264 struct resource *ehci_irq_res; /* EHCI core IRQ. */
265 };
266
267 static struct ofw_compat_data compat_data[] = {
268 {"fsl,imx6q-usb", 1},
269 {"fsl,imx53-usb", 1},
270 {"fsl,imx51-usb", 1},
271 {"fsl,imx28-usb", 1},
272 {"fsl,imx27-usb", 1},
273 {"fsl,imx25-usb", 1},
274 {"fsl,imx23-usb", 1},
275 {NULL, 0},
276 };
277
278 static void
imx_ehci_post_reset(struct ehci_softc * ehci_softc)279 imx_ehci_post_reset(struct ehci_softc *ehci_softc)
280 {
281 uint32_t usbmode;
282
283 /* Force HOST mode */
284 usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM);
285 usbmode &= ~EHCI_UM_CM;
286 usbmode |= EHCI_UM_CM_HOST;
287 EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode);
288 }
289
290 static int
imx_ehci_probe(device_t dev)291 imx_ehci_probe(device_t dev)
292 {
293
294 if (!ofw_bus_status_okay(dev))
295 return (ENXIO);
296
297 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) {
298 device_set_desc(dev, "Freescale i.MX integrated USB controller");
299 return (BUS_PROBE_DEFAULT);
300 }
301 return (ENXIO);
302 }
303
304 static int
imx_ehci_detach(device_t dev)305 imx_ehci_detach(device_t dev)
306 {
307 struct imx_ehci_softc *sc;
308 ehci_softc_t *esc;
309 int err;
310
311 sc = device_get_softc(dev);
312
313 esc = &sc->ehci_softc;
314
315 /* First detach all children; we can't detach if that fails. */
316 if ((err = bus_generic_detach(dev)) != 0)
317 return (err);
318
319 if (esc->sc_flags & EHCI_SCFLG_DONEINIT)
320 ehci_detach(esc);
321 if (esc->sc_intr_hdl != NULL)
322 bus_teardown_intr(dev, esc->sc_irq_res,
323 esc->sc_intr_hdl);
324 if (sc->ehci_irq_res != NULL)
325 bus_release_resource(dev, SYS_RES_IRQ, 0,
326 sc->ehci_irq_res);
327 if (sc->ehci_mem_res != NULL)
328 bus_release_resource(dev, SYS_RES_MEMORY, 0,
329 sc->ehci_mem_res);
330
331 usb_bus_mem_free_all(&esc->sc_bus, &ehci_iterate_hw_softc);
332
333 return (0);
334 }
335
336 static void
imx_ehci_disable_oc(struct imx_ehci_softc * sc)337 imx_ehci_disable_oc(struct imx_ehci_softc *sc)
338 {
339 device_t usbmdev;
340 pcell_t usbmprops[2];
341 phandle_t node;
342 ssize_t size;
343 int index;
344
345 /* Get the reference to the usbmisc driver from the fdt data */
346 node = ofw_bus_get_node(sc->dev);
347 size = OF_getencprop(node, "fsl,usbmisc", usbmprops,
348 sizeof(usbmprops));
349 if (size < sizeof(usbmprops)) {
350 device_printf(sc->dev, "failed to retrieve fsl,usbmisc "
351 "property, cannot disable overcurrent protection");
352 return;
353 }
354 /* Retrieve the device_t via the xref handle. */
355 usbmdev = OF_device_from_xref(usbmprops[0]);
356 if (usbmdev == NULL) {
357 device_printf(sc->dev, "usbmisc device not found, "
358 "cannot disable overcurrent protection");
359 return;
360 }
361 /* Call the device routine to set the overcurrent disable bit. */
362 index = usbmprops[1];
363 imx_usbmisc_set_ctrl(usbmdev, index, USBNC_OVER_CUR_DIS);
364 }
365
366 static int
imx_ehci_attach(device_t dev)367 imx_ehci_attach(device_t dev)
368 {
369 struct imx_ehci_softc *sc;
370 ehci_softc_t *esc;
371 int err, rid;
372
373 sc = device_get_softc(dev);
374 sc->dev = dev;
375 esc = &sc->ehci_softc;
376 err = 0;
377
378 /* Allocate bus_space resources. */
379 rid = 0;
380 sc->ehci_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
381 RF_ACTIVE);
382 if (sc->ehci_mem_res == NULL) {
383 device_printf(dev, "Cannot allocate memory resources\n");
384 err = ENXIO;
385 goto out;
386 }
387
388 rid = 0;
389 sc->ehci_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
390 RF_ACTIVE);
391 if (sc->ehci_irq_res == NULL) {
392 device_printf(dev, "Cannot allocate IRQ resources\n");
393 err = ENXIO;
394 goto out;
395 }
396
397 esc->sc_io_tag = rman_get_bustag(sc->ehci_mem_res);
398 esc->sc_bus.parent = dev;
399 esc->sc_bus.devices = esc->sc_devices;
400 esc->sc_bus.devices_max = EHCI_MAX_DEVICES;
401 esc->sc_bus.dma_bits = 32;
402
403 /* allocate all DMA memory */
404 if (usb_bus_mem_alloc_all(&esc->sc_bus, USB_GET_DMA_TAG(dev),
405 &ehci_iterate_hw_softc) != 0) {
406 device_printf(dev, "usb_bus_mem_alloc_all() failed\n");
407 err = ENOMEM;
408 goto out;
409 }
410
411 /*
412 * Set handle to USB related registers subregion used by
413 * generic EHCI driver.
414 */
415 err = bus_space_subregion(esc->sc_io_tag,
416 rman_get_bushandle(sc->ehci_mem_res),
417 IMX_EHCI_REG_OFF, IMX_EHCI_REG_SIZE, &esc->sc_io_hdl);
418 if (err != 0) {
419 device_printf(dev, "bus_space_subregion() failed\n");
420 err = ENXIO;
421 goto out;
422 }
423
424 /* Setup interrupt handler. */
425 err = bus_setup_intr(dev, sc->ehci_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
426 NULL, (driver_intr_t *)ehci_interrupt, esc, &esc->sc_intr_hdl);
427 if (err != 0) {
428 device_printf(dev, "Could not setup IRQ\n");
429 goto out;
430 }
431
432 /* Turn on clocks. */
433 imx_ccm_usb_enable(dev);
434
435 /* Disable overcurrent detection, if configured to do so. */
436 if (OF_hasprop(ofw_bus_get_node(sc->dev), "disable-over-current"))
437 imx_ehci_disable_oc(sc);
438
439 /* Add USB bus device. */
440 esc->sc_bus.bdev = device_add_child(dev, "usbus", DEVICE_UNIT_ANY);
441 if (esc->sc_bus.bdev == NULL) {
442 device_printf(dev, "Could not add USB device\n");
443 goto out;
444 }
445 device_set_ivars(esc->sc_bus.bdev, &esc->sc_bus);
446
447 esc->sc_id_vendor = USB_VENDOR_FREESCALE;
448 strlcpy(esc->sc_vendor, "Freescale", sizeof(esc->sc_vendor));
449
450 /*
451 * Set flags that affect ehci_init() behavior, and hook our post-reset
452 * code into the standard controller code.
453 */
454 esc->sc_flags |= EHCI_SCFLG_NORESTERM | EHCI_SCFLG_TT;
455 esc->sc_vendor_post_reset = imx_ehci_post_reset;
456 esc->sc_vendor_get_port_speed = ehci_get_port_speed_portsc;
457
458 err = ehci_init(esc);
459 if (err != 0) {
460 device_printf(dev, "USB init failed, usb_err_t=%d\n",
461 err);
462 goto out;
463 }
464 esc->sc_flags |= EHCI_SCFLG_DONEINIT;
465
466 /* Probe the bus. */
467 err = device_probe_and_attach(esc->sc_bus.bdev);
468 if (err != 0) {
469 device_printf(dev,
470 "device_probe_and_attach() failed\n");
471 goto out;
472 }
473
474 err = 0;
475
476 out:
477
478 if (err != 0)
479 imx_ehci_detach(dev);
480
481 return (err);
482 }
483
484 static device_method_t ehci_methods[] = {
485 /* Device interface */
486 DEVMETHOD(device_probe, imx_ehci_probe),
487 DEVMETHOD(device_attach, imx_ehci_attach),
488 DEVMETHOD(device_detach, imx_ehci_detach),
489 DEVMETHOD(device_suspend, bus_generic_suspend),
490 DEVMETHOD(device_resume, bus_generic_resume),
491 DEVMETHOD(device_shutdown, bus_generic_shutdown),
492
493 /* Bus interface */
494 DEVMETHOD(bus_print_child, bus_generic_print_child),
495
496 DEVMETHOD_END
497 };
498
499 static driver_t ehci_driver = {
500 "ehci",
501 ehci_methods,
502 sizeof(struct imx_ehci_softc)
503 };
504
505 DRIVER_MODULE(imx_ehci, simplebus, ehci_driver, 0, 0);
506 MODULE_DEPEND(imx_ehci, usb, 1, 1, 1);
507