1db5ef4fcSRafal Jaworowski /*- 27282444bSPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 37282444bSPedro F. Giffuni * 4db5ef4fcSRafal Jaworowski * Copyright (C) 2008 MARVELL INTERNATIONAL LTD. 5db5ef4fcSRafal Jaworowski * All rights reserved. 6db5ef4fcSRafal Jaworowski * 7db5ef4fcSRafal Jaworowski * Developed by Semihalf. 8db5ef4fcSRafal Jaworowski * 9db5ef4fcSRafal Jaworowski * Redistribution and use in source and binary forms, with or without 10db5ef4fcSRafal Jaworowski * modification, are permitted provided that the following conditions 11db5ef4fcSRafal Jaworowski * are met: 12db5ef4fcSRafal Jaworowski * 1. Redistributions of source code must retain the above copyright 13db5ef4fcSRafal Jaworowski * notice, this list of conditions and the following disclaimer. 14db5ef4fcSRafal Jaworowski * 2. Redistributions in binary form must reproduce the above copyright 15db5ef4fcSRafal Jaworowski * notice, this list of conditions and the following disclaimer in the 16db5ef4fcSRafal Jaworowski * documentation and/or other materials provided with the distribution. 17db5ef4fcSRafal Jaworowski * 3. Neither the name of MARVELL nor the names of contributors 18db5ef4fcSRafal Jaworowski * may be used to endorse or promote products derived from this software 19db5ef4fcSRafal Jaworowski * without specific prior written permission. 20db5ef4fcSRafal Jaworowski * 21db5ef4fcSRafal Jaworowski * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 22db5ef4fcSRafal Jaworowski * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23db5ef4fcSRafal Jaworowski * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24db5ef4fcSRafal Jaworowski * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 25db5ef4fcSRafal Jaworowski * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26db5ef4fcSRafal Jaworowski * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27db5ef4fcSRafal Jaworowski * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28db5ef4fcSRafal Jaworowski * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29db5ef4fcSRafal Jaworowski * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30db5ef4fcSRafal Jaworowski * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31db5ef4fcSRafal Jaworowski * SUCH DAMAGE. 32db5ef4fcSRafal Jaworowski */ 33db5ef4fcSRafal Jaworowski 34db5ef4fcSRafal Jaworowski /* 35db5ef4fcSRafal Jaworowski * FDT attachment driver for the USB Enhanced Host Controller. 36db5ef4fcSRafal Jaworowski */ 37db5ef4fcSRafal Jaworowski 38db5ef4fcSRafal Jaworowski #include <sys/cdefs.h> 39db5ef4fcSRafal Jaworowski #include "opt_bus.h" 40db5ef4fcSRafal Jaworowski 41db5ef4fcSRafal Jaworowski #include <sys/stdint.h> 42db5ef4fcSRafal Jaworowski #include <sys/stddef.h> 43db5ef4fcSRafal Jaworowski #include <sys/param.h> 44db5ef4fcSRafal Jaworowski #include <sys/queue.h> 45db5ef4fcSRafal Jaworowski #include <sys/types.h> 46db5ef4fcSRafal Jaworowski #include <sys/systm.h> 47db5ef4fcSRafal Jaworowski #include <sys/kernel.h> 48db5ef4fcSRafal Jaworowski #include <sys/bus.h> 49db5ef4fcSRafal Jaworowski #include <sys/module.h> 50db5ef4fcSRafal Jaworowski #include <sys/lock.h> 51db5ef4fcSRafal Jaworowski #include <sys/mutex.h> 52db5ef4fcSRafal Jaworowski #include <sys/condvar.h> 53db5ef4fcSRafal Jaworowski #include <sys/sysctl.h> 54db5ef4fcSRafal Jaworowski #include <sys/sx.h> 55db5ef4fcSRafal Jaworowski #include <sys/unistd.h> 56db5ef4fcSRafal Jaworowski #include <sys/callout.h> 57db5ef4fcSRafal Jaworowski #include <sys/malloc.h> 58db5ef4fcSRafal Jaworowski #include <sys/priv.h> 59db5ef4fcSRafal Jaworowski 60db5ef4fcSRafal Jaworowski #include <dev/ofw/ofw_bus.h> 61db5ef4fcSRafal Jaworowski #include <dev/ofw/ofw_bus_subr.h> 62db5ef4fcSRafal Jaworowski 63db5ef4fcSRafal Jaworowski #include <dev/usb/usb.h> 64db5ef4fcSRafal Jaworowski #include <dev/usb/usbdi.h> 65db5ef4fcSRafal Jaworowski 66db5ef4fcSRafal Jaworowski #include <dev/usb/usb_core.h> 67db5ef4fcSRafal Jaworowski #include <dev/usb/usb_busdma.h> 68db5ef4fcSRafal Jaworowski #include <dev/usb/usb_process.h> 69db5ef4fcSRafal Jaworowski #include <dev/usb/usb_util.h> 70db5ef4fcSRafal Jaworowski 71db5ef4fcSRafal Jaworowski #include <dev/usb/usb_controller.h> 72db5ef4fcSRafal Jaworowski #include <dev/usb/usb_bus.h> 73db5ef4fcSRafal Jaworowski #include <dev/usb/controller/ehci.h> 74db5ef4fcSRafal Jaworowski #include <dev/usb/controller/ehcireg.h> 75db5ef4fcSRafal Jaworowski 766c2c6106SMarcin Wojtas #if !defined(__aarch64__) 77db5ef4fcSRafal Jaworowski #include <arm/mv/mvreg.h> 786c2c6106SMarcin Wojtas #endif 79db5ef4fcSRafal Jaworowski #include <arm/mv/mvvar.h> 80db5ef4fcSRafal Jaworowski 81db5ef4fcSRafal Jaworowski #define EHCI_VENDORID_MRVL 0x1286 82db5ef4fcSRafal Jaworowski #define EHCI_HC_DEVSTR "Marvell Integrated USB 2.0 controller" 83db5ef4fcSRafal Jaworowski 84db5ef4fcSRafal Jaworowski static device_attach_t mv_ehci_attach; 85db5ef4fcSRafal Jaworowski static device_detach_t mv_ehci_detach; 86db5ef4fcSRafal Jaworowski 87db5ef4fcSRafal Jaworowski static int err_intr(void *arg); 88db5ef4fcSRafal Jaworowski 89db5ef4fcSRafal Jaworowski static struct resource *irq_err; 90db5ef4fcSRafal Jaworowski static void *ih_err; 91db5ef4fcSRafal Jaworowski 92db5ef4fcSRafal Jaworowski /* EHCI HC regs start at this offset within USB range */ 93db5ef4fcSRafal Jaworowski #define MV_USB_HOST_OFST 0x0100 94db5ef4fcSRafal Jaworowski 95db5ef4fcSRafal Jaworowski #define USB_BRIDGE_INTR_CAUSE 0x210 96db5ef4fcSRafal Jaworowski #define USB_BRIDGE_INTR_MASK 0x214 976a9f4949SMarcel Moolenaar #define USB_BRIDGE_ERR_ADDR 0x21C 98db5ef4fcSRafal Jaworowski 99db5ef4fcSRafal Jaworowski #define MV_USB_ADDR_DECODE_ERR (1 << 0) 100db5ef4fcSRafal Jaworowski #define MV_USB_HOST_UNDERFLOW (1 << 1) 101db5ef4fcSRafal Jaworowski #define MV_USB_HOST_OVERFLOW (1 << 2) 102db5ef4fcSRafal Jaworowski #define MV_USB_DEVICE_UNDERFLOW (1 << 3) 103db5ef4fcSRafal Jaworowski 104be2d15eaSMarcin Wojtas enum mv_ehci_hwtype { 105be2d15eaSMarcin Wojtas HWTYPE_NONE = 0, 106be2d15eaSMarcin Wojtas HWTYPE_MV_EHCI_V1, 107be2d15eaSMarcin Wojtas HWTYPE_MV_EHCI_V2, 108be2d15eaSMarcin Wojtas }; 109be2d15eaSMarcin Wojtas 1105c8fae40SZbigniew Bodek static struct ofw_compat_data compat_data[] = { 111be2d15eaSMarcin Wojtas {"mrvl,usb-ehci", HWTYPE_MV_EHCI_V1}, 112be2d15eaSMarcin Wojtas {"marvell,orion-ehci", HWTYPE_MV_EHCI_V2}, 113be2d15eaSMarcin Wojtas {"marvell,armada-3700-ehci", HWTYPE_MV_EHCI_V2}, 114be2d15eaSMarcin Wojtas {NULL, HWTYPE_NONE} 1155c8fae40SZbigniew Bodek }; 1165c8fae40SZbigniew Bodek 117cdf4ec68SMichal Meloun static void 118cdf4ec68SMichal Meloun mv_ehci_post_reset(struct ehci_softc *ehci_softc) 119cdf4ec68SMichal Meloun { 120cdf4ec68SMichal Meloun uint32_t usbmode; 121cdf4ec68SMichal Meloun 122cdf4ec68SMichal Meloun /* Force HOST mode */ 123cdf4ec68SMichal Meloun usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM); 124cdf4ec68SMichal Meloun usbmode &= ~EHCI_UM_CM; 125cdf4ec68SMichal Meloun usbmode |= EHCI_UM_CM_HOST; 126cdf4ec68SMichal Meloun EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode); 127cdf4ec68SMichal Meloun } 128cdf4ec68SMichal Meloun 129db5ef4fcSRafal Jaworowski static int 130db5ef4fcSRafal Jaworowski mv_ehci_probe(device_t self) 131db5ef4fcSRafal Jaworowski { 132db5ef4fcSRafal Jaworowski 133add35ed5SIan Lepore if (!ofw_bus_status_okay(self)) 134add35ed5SIan Lepore return (ENXIO); 135add35ed5SIan Lepore 1365c8fae40SZbigniew Bodek if (!ofw_bus_search_compatible(self, compat_data)->ocd_data) 137db5ef4fcSRafal Jaworowski return (ENXIO); 138db5ef4fcSRafal Jaworowski 139db5ef4fcSRafal Jaworowski device_set_desc(self, EHCI_HC_DEVSTR); 140db5ef4fcSRafal Jaworowski 141db5ef4fcSRafal Jaworowski return (BUS_PROBE_DEFAULT); 142db5ef4fcSRafal Jaworowski } 143db5ef4fcSRafal Jaworowski 144db5ef4fcSRafal Jaworowski static int 145db5ef4fcSRafal Jaworowski mv_ehci_attach(device_t self) 146db5ef4fcSRafal Jaworowski { 147db5ef4fcSRafal Jaworowski ehci_softc_t *sc = device_get_softc(self); 148be2d15eaSMarcin Wojtas enum mv_ehci_hwtype hwtype; 149db5ef4fcSRafal Jaworowski bus_space_handle_t bsh; 150db5ef4fcSRafal Jaworowski int err; 151db5ef4fcSRafal Jaworowski int rid; 152db5ef4fcSRafal Jaworowski 153db5ef4fcSRafal Jaworowski /* initialise some bus fields */ 154db5ef4fcSRafal Jaworowski sc->sc_bus.parent = self; 155db5ef4fcSRafal Jaworowski sc->sc_bus.devices = sc->sc_devices; 156db5ef4fcSRafal Jaworowski sc->sc_bus.devices_max = EHCI_MAX_DEVICES; 157b217d184SHans Petter Selasky sc->sc_bus.dma_bits = 32; 158db5ef4fcSRafal Jaworowski 159be2d15eaSMarcin Wojtas hwtype = ofw_bus_search_compatible(self, compat_data)->ocd_data; 160be2d15eaSMarcin Wojtas if (hwtype == HWTYPE_NONE) { 161be2d15eaSMarcin Wojtas device_printf(self, "Wrong HW type flag detected\n"); 162be2d15eaSMarcin Wojtas return (ENXIO); 163be2d15eaSMarcin Wojtas } 164be2d15eaSMarcin Wojtas 165db5ef4fcSRafal Jaworowski /* get all DMA memory */ 166db5ef4fcSRafal Jaworowski if (usb_bus_mem_alloc_all(&sc->sc_bus, 167db5ef4fcSRafal Jaworowski USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) { 168db5ef4fcSRafal Jaworowski return (ENOMEM); 169db5ef4fcSRafal Jaworowski } 170db5ef4fcSRafal Jaworowski 171db5ef4fcSRafal Jaworowski rid = 0; 172db5ef4fcSRafal Jaworowski sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE); 173db5ef4fcSRafal Jaworowski if (!sc->sc_io_res) { 174db5ef4fcSRafal Jaworowski device_printf(self, "Could not map memory\n"); 175db5ef4fcSRafal Jaworowski goto error; 176db5ef4fcSRafal Jaworowski } 177db5ef4fcSRafal Jaworowski sc->sc_io_tag = rman_get_bustag(sc->sc_io_res); 178db5ef4fcSRafal Jaworowski bsh = rman_get_bushandle(sc->sc_io_res); 179db5ef4fcSRafal Jaworowski sc->sc_io_size = rman_get_size(sc->sc_io_res) - MV_USB_HOST_OFST; 180db5ef4fcSRafal Jaworowski 181db5ef4fcSRafal Jaworowski /* 182db5ef4fcSRafal Jaworowski * Marvell EHCI host controller registers start at certain offset 183db5ef4fcSRafal Jaworowski * within the whole USB registers range, so create a subregion for the 184db5ef4fcSRafal Jaworowski * host mode configuration purposes. 185db5ef4fcSRafal Jaworowski */ 186db5ef4fcSRafal Jaworowski 187db5ef4fcSRafal Jaworowski if (bus_space_subregion(sc->sc_io_tag, bsh, MV_USB_HOST_OFST, 188db5ef4fcSRafal Jaworowski sc->sc_io_size, &sc->sc_io_hdl) != 0) 189db5ef4fcSRafal Jaworowski panic("%s: unable to subregion USB host registers", 190db5ef4fcSRafal Jaworowski device_get_name(self)); 191db5ef4fcSRafal Jaworowski 192db5ef4fcSRafal Jaworowski rid = 0; 193be2d15eaSMarcin Wojtas if (hwtype == HWTYPE_MV_EHCI_V1) { 194db5ef4fcSRafal Jaworowski irq_err = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid, 195db5ef4fcSRafal Jaworowski RF_SHAREABLE | RF_ACTIVE); 196db5ef4fcSRafal Jaworowski if (irq_err == NULL) { 197db5ef4fcSRafal Jaworowski device_printf(self, "Could not allocate error irq\n"); 198db5ef4fcSRafal Jaworowski mv_ehci_detach(self); 199db5ef4fcSRafal Jaworowski return (ENXIO); 200db5ef4fcSRafal Jaworowski } 2015c8fae40SZbigniew Bodek rid = 1; 2025c8fae40SZbigniew Bodek } 203db5ef4fcSRafal Jaworowski 204db5ef4fcSRafal Jaworowski /* 205db5ef4fcSRafal Jaworowski * Notice: Marvell EHCI controller has TWO interrupt lines, so make 206db5ef4fcSRafal Jaworowski * sure to use the correct rid for the main one (controller interrupt) 207db5ef4fcSRafal Jaworowski * -- refer to DTS for the right resource number to use here. 208db5ef4fcSRafal Jaworowski */ 209db5ef4fcSRafal Jaworowski sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid, 210db5ef4fcSRafal Jaworowski RF_SHAREABLE | RF_ACTIVE); 211db5ef4fcSRafal Jaworowski if (sc->sc_irq_res == NULL) { 212db5ef4fcSRafal Jaworowski device_printf(self, "Could not allocate irq\n"); 213db5ef4fcSRafal Jaworowski goto error; 214db5ef4fcSRafal Jaworowski } 215db5ef4fcSRafal Jaworowski 2165b56413dSWarner Losh sc->sc_bus.bdev = device_add_child(self, "usbus", DEVICE_UNIT_ANY); 217db5ef4fcSRafal Jaworowski if (!sc->sc_bus.bdev) { 218db5ef4fcSRafal Jaworowski device_printf(self, "Could not add USB device\n"); 219db5ef4fcSRafal Jaworowski goto error; 220db5ef4fcSRafal Jaworowski } 221db5ef4fcSRafal Jaworowski device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); 222db5ef4fcSRafal Jaworowski device_set_desc(sc->sc_bus.bdev, EHCI_HC_DEVSTR); 223db5ef4fcSRafal Jaworowski 224db5ef4fcSRafal Jaworowski sprintf(sc->sc_vendor, "Marvell"); 225db5ef4fcSRafal Jaworowski 226be2d15eaSMarcin Wojtas if (hwtype == HWTYPE_MV_EHCI_V1) { 227c305730dSJohn Baldwin err = bus_setup_intr(self, irq_err, INTR_TYPE_BIO, 228db5ef4fcSRafal Jaworowski err_intr, NULL, sc, &ih_err); 229db5ef4fcSRafal Jaworowski if (err) { 230db5ef4fcSRafal Jaworowski device_printf(self, "Could not setup error irq, %d\n", err); 231db5ef4fcSRafal Jaworowski ih_err = NULL; 232db5ef4fcSRafal Jaworowski goto error; 233db5ef4fcSRafal Jaworowski } 2345c8fae40SZbigniew Bodek } 235db5ef4fcSRafal Jaworowski 236db5ef4fcSRafal Jaworowski EWRITE4(sc, USB_BRIDGE_INTR_MASK, MV_USB_ADDR_DECODE_ERR | 237db5ef4fcSRafal Jaworowski MV_USB_HOST_UNDERFLOW | MV_USB_HOST_OVERFLOW | 238db5ef4fcSRafal Jaworowski MV_USB_DEVICE_UNDERFLOW); 239db5ef4fcSRafal Jaworowski 240db5ef4fcSRafal Jaworowski err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 241db5ef4fcSRafal Jaworowski NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl); 242db5ef4fcSRafal Jaworowski if (err) { 243db5ef4fcSRafal Jaworowski device_printf(self, "Could not setup irq, %d\n", err); 244db5ef4fcSRafal Jaworowski sc->sc_intr_hdl = NULL; 245db5ef4fcSRafal Jaworowski goto error; 246db5ef4fcSRafal Jaworowski } 247db5ef4fcSRafal Jaworowski 248db5ef4fcSRafal Jaworowski /* 249db5ef4fcSRafal Jaworowski * Workaround for Marvell integrated EHCI controller: reset of 250db5ef4fcSRafal Jaworowski * the EHCI core clears the USBMODE register, which sets the core in 251db5ef4fcSRafal Jaworowski * an undefined state (neither host nor agent), so it needs to be set 252db5ef4fcSRafal Jaworowski * again for proper operation. 253db5ef4fcSRafal Jaworowski * 254db5ef4fcSRafal Jaworowski * Refer to errata document MV-S500832-00D.pdf (p. 5.24 GL USB-2) for 255db5ef4fcSRafal Jaworowski * details. 256db5ef4fcSRafal Jaworowski */ 257cdf4ec68SMichal Meloun sc->sc_vendor_post_reset = mv_ehci_post_reset; 258db5ef4fcSRafal Jaworowski if (bootverbose) 259db5ef4fcSRafal Jaworowski device_printf(self, "5.24 GL USB-2 workaround enabled\n"); 260db5ef4fcSRafal Jaworowski 261db5ef4fcSRafal Jaworowski /* XXX all MV chips need it? */ 262cdf4ec68SMichal Meloun sc->sc_flags |= EHCI_SCFLG_TT | EHCI_SCFLG_NORESTERM; 263cdf4ec68SMichal Meloun sc->sc_vendor_get_port_speed = ehci_get_port_speed_portsc; 264db5ef4fcSRafal Jaworowski err = ehci_init(sc); 265db5ef4fcSRafal Jaworowski if (!err) { 266db5ef4fcSRafal Jaworowski err = device_probe_and_attach(sc->sc_bus.bdev); 267db5ef4fcSRafal Jaworowski } 268db5ef4fcSRafal Jaworowski if (err) { 269db5ef4fcSRafal Jaworowski device_printf(self, "USB init failed err=%d\n", err); 270db5ef4fcSRafal Jaworowski goto error; 271db5ef4fcSRafal Jaworowski } 272db5ef4fcSRafal Jaworowski return (0); 273db5ef4fcSRafal Jaworowski 274db5ef4fcSRafal Jaworowski error: 275db5ef4fcSRafal Jaworowski mv_ehci_detach(self); 276db5ef4fcSRafal Jaworowski return (ENXIO); 277db5ef4fcSRafal Jaworowski } 278db5ef4fcSRafal Jaworowski 279db5ef4fcSRafal Jaworowski static int 280db5ef4fcSRafal Jaworowski mv_ehci_detach(device_t self) 281db5ef4fcSRafal Jaworowski { 282db5ef4fcSRafal Jaworowski ehci_softc_t *sc = device_get_softc(self); 283db5ef4fcSRafal Jaworowski int err; 284db5ef4fcSRafal Jaworowski 285db5ef4fcSRafal Jaworowski /* during module unload there are lots of children leftover */ 286*3ddaf820SJohn Baldwin err = bus_generic_detach(self); 287*3ddaf820SJohn Baldwin if (err != 0) 288*3ddaf820SJohn Baldwin return (err); 289db5ef4fcSRafal Jaworowski 290db5ef4fcSRafal Jaworowski /* 291b0a5e05fSHans Petter Selasky * disable interrupts that might have been switched on in mv_ehci_attach 292db5ef4fcSRafal Jaworowski */ 293db5ef4fcSRafal Jaworowski if (sc->sc_io_res) { 294db5ef4fcSRafal Jaworowski EWRITE4(sc, USB_BRIDGE_INTR_MASK, 0); 295db5ef4fcSRafal Jaworowski } 296db5ef4fcSRafal Jaworowski if (sc->sc_irq_res && sc->sc_intr_hdl) { 297db5ef4fcSRafal Jaworowski /* 298db5ef4fcSRafal Jaworowski * only call ehci_detach() after ehci_init() 299db5ef4fcSRafal Jaworowski */ 300db5ef4fcSRafal Jaworowski ehci_detach(sc); 301db5ef4fcSRafal Jaworowski 302db5ef4fcSRafal Jaworowski err = bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intr_hdl); 303db5ef4fcSRafal Jaworowski 304db5ef4fcSRafal Jaworowski if (err) 305db5ef4fcSRafal Jaworowski /* XXX or should we panic? */ 306db5ef4fcSRafal Jaworowski device_printf(self, "Could not tear down irq, %d\n", 307db5ef4fcSRafal Jaworowski err); 308db5ef4fcSRafal Jaworowski sc->sc_intr_hdl = NULL; 309db5ef4fcSRafal Jaworowski } 310db5ef4fcSRafal Jaworowski if (irq_err && ih_err) { 311db5ef4fcSRafal Jaworowski err = bus_teardown_intr(self, irq_err, ih_err); 312db5ef4fcSRafal Jaworowski 313db5ef4fcSRafal Jaworowski if (err) 314db5ef4fcSRafal Jaworowski device_printf(self, "Could not tear down irq, %d\n", 315db5ef4fcSRafal Jaworowski err); 316db5ef4fcSRafal Jaworowski ih_err = NULL; 317db5ef4fcSRafal Jaworowski } 318db5ef4fcSRafal Jaworowski if (irq_err) { 319db5ef4fcSRafal Jaworowski bus_release_resource(self, SYS_RES_IRQ, 0, irq_err); 320db5ef4fcSRafal Jaworowski irq_err = NULL; 321db5ef4fcSRafal Jaworowski } 322db5ef4fcSRafal Jaworowski if (sc->sc_irq_res) { 323db5ef4fcSRafal Jaworowski bus_release_resource(self, SYS_RES_IRQ, 1, sc->sc_irq_res); 324db5ef4fcSRafal Jaworowski sc->sc_irq_res = NULL; 325db5ef4fcSRafal Jaworowski } 326db5ef4fcSRafal Jaworowski if (sc->sc_io_res) { 327db5ef4fcSRafal Jaworowski bus_release_resource(self, SYS_RES_MEMORY, 0, 328db5ef4fcSRafal Jaworowski sc->sc_io_res); 329db5ef4fcSRafal Jaworowski sc->sc_io_res = NULL; 330db5ef4fcSRafal Jaworowski } 331db5ef4fcSRafal Jaworowski usb_bus_mem_free_all(&sc->sc_bus, &ehci_iterate_hw_softc); 332db5ef4fcSRafal Jaworowski 333db5ef4fcSRafal Jaworowski return (0); 334db5ef4fcSRafal Jaworowski } 335db5ef4fcSRafal Jaworowski 336db5ef4fcSRafal Jaworowski static int 337db5ef4fcSRafal Jaworowski err_intr(void *arg) 338db5ef4fcSRafal Jaworowski { 339db5ef4fcSRafal Jaworowski ehci_softc_t *sc = arg; 34062d42655SHans Petter Selasky unsigned cause; 341db5ef4fcSRafal Jaworowski 342db5ef4fcSRafal Jaworowski cause = EREAD4(sc, USB_BRIDGE_INTR_CAUSE); 343db5ef4fcSRafal Jaworowski if (cause) { 3446a9f4949SMarcel Moolenaar printf("USB error: "); 3456a9f4949SMarcel Moolenaar if (cause & MV_USB_ADDR_DECODE_ERR) { 3466a9f4949SMarcel Moolenaar uint32_t addr; 3476a9f4949SMarcel Moolenaar 3486a9f4949SMarcel Moolenaar addr = EREAD4(sc, USB_BRIDGE_ERR_ADDR); 3496a9f4949SMarcel Moolenaar printf("address decoding error (addr=%#x)\n", addr); 3506a9f4949SMarcel Moolenaar } 351db5ef4fcSRafal Jaworowski if (cause & MV_USB_HOST_UNDERFLOW) 3526a9f4949SMarcel Moolenaar printf("host underflow\n"); 353db5ef4fcSRafal Jaworowski if (cause & MV_USB_HOST_OVERFLOW) 3546a9f4949SMarcel Moolenaar printf("host overflow\n"); 355db5ef4fcSRafal Jaworowski if (cause & MV_USB_DEVICE_UNDERFLOW) 3566a9f4949SMarcel Moolenaar printf("device underflow\n"); 357db5ef4fcSRafal Jaworowski if (cause & ~(MV_USB_ADDR_DECODE_ERR | MV_USB_HOST_UNDERFLOW | 358db5ef4fcSRafal Jaworowski MV_USB_HOST_OVERFLOW | MV_USB_DEVICE_UNDERFLOW)) 3596a9f4949SMarcel Moolenaar printf("unknown cause (cause=%#x)\n", cause); 360db5ef4fcSRafal Jaworowski 361db5ef4fcSRafal Jaworowski EWRITE4(sc, USB_BRIDGE_INTR_CAUSE, 0); 362db5ef4fcSRafal Jaworowski } 363db5ef4fcSRafal Jaworowski return (FILTER_HANDLED); 364db5ef4fcSRafal Jaworowski } 365db5ef4fcSRafal Jaworowski 366db5ef4fcSRafal Jaworowski static device_method_t ehci_methods[] = { 367db5ef4fcSRafal Jaworowski /* Device interface */ 368db5ef4fcSRafal Jaworowski DEVMETHOD(device_probe, mv_ehci_probe), 369db5ef4fcSRafal Jaworowski DEVMETHOD(device_attach, mv_ehci_attach), 370db5ef4fcSRafal Jaworowski DEVMETHOD(device_detach, mv_ehci_detach), 3712e141748SHans Petter Selasky DEVMETHOD(device_suspend, bus_generic_suspend), 3722e141748SHans Petter Selasky DEVMETHOD(device_resume, bus_generic_resume), 3732e141748SHans Petter Selasky DEVMETHOD(device_shutdown, bus_generic_shutdown), 374db5ef4fcSRafal Jaworowski 3754b7ec270SMarius Strobl DEVMETHOD_END 376db5ef4fcSRafal Jaworowski }; 377db5ef4fcSRafal Jaworowski 378db5ef4fcSRafal Jaworowski static driver_t ehci_driver = { 379db5ef4fcSRafal Jaworowski "ehci", 380db5ef4fcSRafal Jaworowski ehci_methods, 381db5ef4fcSRafal Jaworowski sizeof(ehci_softc_t), 382db5ef4fcSRafal Jaworowski }; 383db5ef4fcSRafal Jaworowski 384bc9372d7SJohn Baldwin DRIVER_MODULE(ehci_mv, simplebus, ehci_driver, 0, 0); 3856c2c6106SMarcin Wojtas MODULE_DEPEND(ehci_mv, usb, 1, 1, 1); 386