xref: /netbsd-src/sys/arch/mips/ralink/ralink_ehci.c (revision c7fb772b85b2b5d4cfb282f868f454b4701534fd)
1*c7fb772bSthorpej /*	$NetBSD: ralink_ehci.c,v 1.9 2021/08/07 16:18:59 thorpej Exp $	*/
20062f2f2Smatt /*-
30062f2f2Smatt  * Copyright (c) 2011 CradlePoint Technology, Inc.
40062f2f2Smatt  * All rights reserved.
50062f2f2Smatt  *
60062f2f2Smatt  *
70062f2f2Smatt  * Redistribution and use in source and binary forms, with or without
80062f2f2Smatt  * modification, are permitted provided that the following conditions
90062f2f2Smatt  * are met:
100062f2f2Smatt  * 1. Redistributions of source code must retain the above copyright
110062f2f2Smatt  *    notice, this list of conditions and the following disclaimer.
120062f2f2Smatt  * 2. Redistributions in binary form must reproduce the above copyright
130062f2f2Smatt  *    notice, this list of conditions and the following disclaimer in the
140062f2f2Smatt  *    documentation and/or other materials provided with the distribution.
150062f2f2Smatt  *
160062f2f2Smatt  * THIS SOFTWARE IS PROVIDED BY CRADLEPOINT TECHNOLOGY, INC. AND CONTRIBUTORS
170062f2f2Smatt  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
180062f2f2Smatt  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
190062f2f2Smatt  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
200062f2f2Smatt  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
210062f2f2Smatt  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
220062f2f2Smatt  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
230062f2f2Smatt  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
240062f2f2Smatt  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
250062f2f2Smatt  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
260062f2f2Smatt  * POSSIBILITY OF SUCH DAMAGE.
270062f2f2Smatt  */
280062f2f2Smatt 
290062f2f2Smatt /* ralink_ehci.c -- Ralink EHCI USB Driver */
300062f2f2Smatt 
310062f2f2Smatt #include <sys/cdefs.h>
32*c7fb772bSthorpej __KERNEL_RCSID(0, "$NetBSD: ralink_ehci.c,v 1.9 2021/08/07 16:18:59 thorpej Exp $");
330062f2f2Smatt 
340062f2f2Smatt #include <sys/param.h>
350062f2f2Smatt #include <sys/bus.h>
360062f2f2Smatt 
370062f2f2Smatt #include <dev/usb/usb.h>
380062f2f2Smatt #include <dev/usb/usbdi.h>
390062f2f2Smatt #include <dev/usb/usbdivar.h>
400062f2f2Smatt #include <dev/usb/usb_mem.h>
410062f2f2Smatt 
420062f2f2Smatt #include <dev/usb/ehcireg.h>
430062f2f2Smatt #include <dev/usb/ehcivar.h>
440062f2f2Smatt 
450062f2f2Smatt #include <mips/ralink/ralink_usbhcvar.h>
460062f2f2Smatt 
470062f2f2Smatt #include <mips/ralink/ralink_var.h>
480062f2f2Smatt #include <mips/ralink/ralink_reg.h>
490062f2f2Smatt 
500062f2f2Smatt struct ralink_ehci_softc {
510062f2f2Smatt 	struct ehci_softc	sc_ehci;
520062f2f2Smatt 	void			*sc_ih;
530062f2f2Smatt };
540062f2f2Smatt 
550062f2f2Smatt static int  ralink_ehci_match(device_t, cfdata_t, void *);
560062f2f2Smatt static void ralink_ehci_attach(device_t, device_t, void *);
570062f2f2Smatt static int  ralink_ehci_detach(device_t, int);
580062f2f2Smatt 
590062f2f2Smatt CFATTACH_DECL2_NEW(ralink_ehci, sizeof(struct ralink_ehci_softc),
600062f2f2Smatt 	ralink_ehci_match, ralink_ehci_attach, ralink_ehci_detach,
610062f2f2Smatt 	ehci_activate, NULL, ehci_childdet);
620062f2f2Smatt 
630062f2f2Smatt static TAILQ_HEAD(, ralink_usb_hc) ralink_usb_alldevs =
640062f2f2Smatt 	TAILQ_HEAD_INITIALIZER(ralink_usb_alldevs);
650062f2f2Smatt 
660062f2f2Smatt #if 0
670062f2f2Smatt struct usb_hc_alldevs ralink_usb_alldevs = TAILQ_HEAD_INITIALIZER(ralink_usb_alldevs);
680062f2f2Smatt #endif
690062f2f2Smatt 
700062f2f2Smatt /*
710062f2f2Smatt  * ralink_ehci_match
720062f2f2Smatt  */
730062f2f2Smatt static int
ralink_ehci_match(device_t parent,cfdata_t cf,void * aux)740062f2f2Smatt ralink_ehci_match(device_t parent, cfdata_t cf, void *aux)
750062f2f2Smatt {
760062f2f2Smatt 
770062f2f2Smatt 	return 1;
780062f2f2Smatt }
790062f2f2Smatt 
800062f2f2Smatt /*
810062f2f2Smatt  * ralink_ehci_attach
820062f2f2Smatt  */
830062f2f2Smatt static void
ralink_ehci_attach(device_t parent,device_t self,void * aux)840062f2f2Smatt ralink_ehci_attach(device_t parent, device_t self, void *aux)
850062f2f2Smatt {
860062f2f2Smatt 	struct ralink_ehci_softc * const sc = device_private(self);
870062f2f2Smatt 	const struct mainbus_attach_args *ma = aux;
880062f2f2Smatt 	struct ralink_usb_hc *ruh;
890062f2f2Smatt 	int error;
900062f2f2Smatt 
910062f2f2Smatt 	aprint_naive(": EHCI USB controller\n");
920062f2f2Smatt 	aprint_normal(": EHCI USB controller\n");
930062f2f2Smatt 
940062f2f2Smatt 	sc->sc_ehci.sc_dev = self;
954e8e6643Sskrll 	sc->sc_ehci.sc_bus.ub_hcpriv = sc;
960062f2f2Smatt 	sc->sc_ehci.iot = ma->ma_memt;
974e8e6643Sskrll 	sc->sc_ehci.sc_bus.ub_dmatag = ma->ma_dmat;
980062f2f2Smatt 
990062f2f2Smatt 	/* Map EHCI registers */
100272c0890Smatt 	if ((error = bus_space_map(sc->sc_ehci.iot, RA_USB_EHCI_BASE,
101272c0890Smatt 	    RA_USB_BLOCK_SIZE, 0, &sc->sc_ehci.ioh)) != 0) {
1020062f2f2Smatt 		aprint_error_dev(self, "can't map EHCI registers, "
1030062f2f2Smatt 			"error=%d\n", error);
1040062f2f2Smatt 		return;
1050062f2f2Smatt 	}
1060062f2f2Smatt 
107272c0890Smatt 	sc->sc_ehci.sc_size = RA_USB_BLOCK_SIZE;
1084e8e6643Sskrll 	sc->sc_ehci.sc_bus.ub_revision = USBREV_2_0;
1090062f2f2Smatt 
11086475f59Smatt #if defined(RALINK_EHCI_DEBUG)
11186475f59Smatt 	aprint_normal_dev(self, "sc %p ma %p\n", sc, ma);
11286475f59Smatt 	aprint_normal_dev(self, "memt %p dmat %p\n", ma->ma_memt, ma->ma_dmat);
11386475f59Smatt 	aprint_normal_dev(self, "EHCI HCCAPBASE=%#x\n",
1140062f2f2Smatt 		EREAD4(&sc->sc_ehci, EHCI_CAPLENGTH));
11586475f59Smatt 	aprint_normal_dev(self, "EHCI HCSPARAMS=%#x\n",
1160062f2f2Smatt 		EREAD4(&sc->sc_ehci, EHCI_HCSPARAMS));
11786475f59Smatt 	aprint_normal_dev(self, "EHCI HCCPARAMS=%#x\n",
1180062f2f2Smatt 		EREAD4(&sc->sc_ehci, EHCI_HCCPARAMS));
11986475f59Smatt 	aprint_normal_dev(self, "EHCI HCSP_PORTROUTE=%#x\n",
1200062f2f2Smatt 		EREAD4(&sc->sc_ehci, EHCI_HCSP_PORTROUTE));
1210062f2f2Smatt #endif
1220062f2f2Smatt 
1230062f2f2Smatt 	/* Disable EHCI interrupts. */
1240062f2f2Smatt 	sc->sc_ehci.sc_offs = EREAD1(&sc->sc_ehci, EHCI_CAPLENGTH);
12509fca0b7Smatt 	EOWRITE4(&sc->sc_ehci, EHCI_USBINTR, 0);
1260062f2f2Smatt 
12786475f59Smatt #if defined(RALINK_EHCI_DEBUG)
12886475f59Smatt 	aprint_normal_dev(self, "EHCI USBCMD=%#x USBSTS=%#x USBINTR=%#x\n",
12986475f59Smatt 		EOREAD4(&sc->sc_ehci, EHCI_USBCMD),
13086475f59Smatt 		EOREAD4(&sc->sc_ehci, EHCI_USBSTS),
1310062f2f2Smatt 		EOREAD4(&sc->sc_ehci, EHCI_USBINTR));
1320062f2f2Smatt #endif
1330062f2f2Smatt 
1340062f2f2Smatt 	/* Establish the MIPS level interrupt */
1350062f2f2Smatt 	sc->sc_ih = ra_intr_establish(RA_IRQ_USB, ehci_intr, sc, 1);
1360062f2f2Smatt 	if (sc->sc_ih == NULL) {
1370062f2f2Smatt 		aprint_error_dev(self, "unable to establish irq %d\n",
1380062f2f2Smatt 			RA_IRQ_USB);
1390062f2f2Smatt 		goto fail_0;
1400062f2f2Smatt 	}
1410062f2f2Smatt 
1420062f2f2Smatt 	/*
1430062f2f2Smatt 	 * Find companion controllers.  According to the spec they always
1440062f2f2Smatt 	 * have lower function numbers so they should be enumerated already.
1450062f2f2Smatt 	 */
1460062f2f2Smatt 	int ncomp = 0;
1470062f2f2Smatt 	TAILQ_FOREACH(ruh, &ralink_usb_alldevs, next) {
1480062f2f2Smatt 		aprint_normal_dev(self, "companion %s\n",
1490062f2f2Smatt 			device_xname(ruh->usb));
1500062f2f2Smatt 		sc->sc_ehci.sc_comps[ncomp++] = ruh->usb;
1510062f2f2Smatt 		if (ncomp >= EHCI_COMPANION_MAX)
1520062f2f2Smatt 			break;
1530062f2f2Smatt 	}
1540062f2f2Smatt 	sc->sc_ehci.sc_ncomp = ncomp;
1550062f2f2Smatt 
1560062f2f2Smatt 	/* Initialize EHCI */
1574e8e6643Sskrll 	int err = ehci_init(&sc->sc_ehci);
1584e8e6643Sskrll 	if (err) {
1594e8e6643Sskrll 		aprint_error_dev(self, "init failed, error=%d\n", err);
1600062f2f2Smatt 		goto fail_1;
1610062f2f2Smatt 	}
1620062f2f2Smatt 
1630062f2f2Smatt 	if (!pmf_device_register1(self, ehci_suspend, ehci_resume,
1640062f2f2Smatt 	    ehci_shutdown))
1650062f2f2Smatt 		aprint_error_dev(self, "couldn't establish power handler\n");
1660062f2f2Smatt 
1670062f2f2Smatt 	/* Attach usb device. */
1680062f2f2Smatt 	sc->sc_ehci.sc_child = config_found(self, &sc->sc_ehci.sc_bus,
169*c7fb772bSthorpej 		usbctlprint, CFARGS_NONE);
1700062f2f2Smatt 
1710062f2f2Smatt 	return;
1720062f2f2Smatt 
1730062f2f2Smatt  fail_1:
1740062f2f2Smatt 	ra_intr_disestablish(sc->sc_ih);
1750062f2f2Smatt 	sc->sc_ih = NULL;
1760062f2f2Smatt  fail_0:
1770062f2f2Smatt 	bus_space_unmap(sc->sc_ehci.iot, sc->sc_ehci.ioh, sc->sc_ehci.sc_size);
1780062f2f2Smatt 	sc->sc_ehci.sc_size = 0;
1790062f2f2Smatt }
1800062f2f2Smatt 
1810062f2f2Smatt static int
ralink_ehci_detach(device_t self,int flags)1820062f2f2Smatt ralink_ehci_detach(device_t self, int flags)
1830062f2f2Smatt {
1840062f2f2Smatt 	struct ralink_ehci_softc * const sc = device_private(self);
1850062f2f2Smatt 	int rv;
1860062f2f2Smatt 
1870062f2f2Smatt 	pmf_device_deregister(self);
1880062f2f2Smatt 
1890062f2f2Smatt 	rv = ehci_detach(&sc->sc_ehci, flags);
1900062f2f2Smatt 	if (rv)
1910062f2f2Smatt 		return rv;
1920062f2f2Smatt 
1930062f2f2Smatt 	if (sc->sc_ih != NULL) {
1940062f2f2Smatt 		ra_intr_disestablish(sc->sc_ih);
1950062f2f2Smatt 		sc->sc_ih = NULL;
1960062f2f2Smatt 	}
1970062f2f2Smatt 
1980062f2f2Smatt 	if (sc->sc_ehci.sc_size != 0) {
1990062f2f2Smatt 		bus_space_unmap(sc->sc_ehci.iot, sc->sc_ehci.ioh,
2000062f2f2Smatt 			sc->sc_ehci.sc_size);
2010062f2f2Smatt 		sc->sc_ehci.sc_size = 0;
2020062f2f2Smatt 	}
2030062f2f2Smatt 
2040062f2f2Smatt 	return 0;
2050062f2f2Smatt }
2060062f2f2Smatt 
2070062f2f2Smatt void
ralink_usb_hc_add(struct ralink_usb_hc * ruh,device_t usbp)2080062f2f2Smatt ralink_usb_hc_add(struct ralink_usb_hc *ruh, device_t usbp)
2090062f2f2Smatt {
2100062f2f2Smatt 	TAILQ_INSERT_TAIL(&ralink_usb_alldevs, ruh, next);
2110062f2f2Smatt 	ruh->usb = usbp;
2120062f2f2Smatt }
2130062f2f2Smatt 
2140062f2f2Smatt void
ralink_usb_hc_rem(struct ralink_usb_hc * ruh)2150062f2f2Smatt ralink_usb_hc_rem(struct ralink_usb_hc *ruh)
2160062f2f2Smatt {
2170062f2f2Smatt 	TAILQ_REMOVE(&ralink_usb_alldevs, ruh, next);
2180062f2f2Smatt }
219