xref: /openbsd-src/sys/arch/armv7/omap/omohci.c (revision ea05d060d200e3b3c0cc54eab5d48fb53a7250b8)
1*ea05d060Sderaadt /*	$OpenBSD: omohci.c,v 1.5 2024/08/20 16:24:50 deraadt Exp $ */
28eda2d14Spatrick 
38eda2d14Spatrick /*
48eda2d14Spatrick  * Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
58eda2d14Spatrick  *
68eda2d14Spatrick  * Permission to use, copy, modify, and distribute this software for any
78eda2d14Spatrick  * purpose with or without fee is hereby granted, provided that the above
88eda2d14Spatrick  * copyright notice and this permission notice appear in all copies.
98eda2d14Spatrick  *
108eda2d14Spatrick  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
118eda2d14Spatrick  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
128eda2d14Spatrick  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
138eda2d14Spatrick  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
148eda2d14Spatrick  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
158eda2d14Spatrick  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
168eda2d14Spatrick  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
178eda2d14Spatrick  */
188eda2d14Spatrick 
198eda2d14Spatrick #include <sys/param.h>
208eda2d14Spatrick #include <sys/systm.h>
218eda2d14Spatrick #include <sys/device.h>
228eda2d14Spatrick #include <sys/kernel.h>
238eda2d14Spatrick #include <sys/timeout.h>
248eda2d14Spatrick 
258eda2d14Spatrick #include <machine/intr.h>
268eda2d14Spatrick #include <machine/bus.h>
278eda2d14Spatrick 
288eda2d14Spatrick #include <dev/usb/usb.h>
298eda2d14Spatrick #include <dev/usb/usbdi.h>
308eda2d14Spatrick #include <dev/usb/usbdivar.h>
318eda2d14Spatrick #include <dev/usb/usb_mem.h>
328eda2d14Spatrick 
338eda2d14Spatrick #include <dev/usb/ohcireg.h>
348eda2d14Spatrick #include <dev/usb/ohcivar.h>
358eda2d14Spatrick #include <armv7/omap/prcmvar.h>
368eda2d14Spatrick 
378eda2d14Spatrick #define HOSTUEADDR		0x0E0
388eda2d14Spatrick #define HOSTUESTATUS		0x0E4
398eda2d14Spatrick #define HOSTTIMEOUTCTRL		0x0E8
408eda2d14Spatrick #define HOSTREVISION		0x0EC
418eda2d14Spatrick #define WHM_REVID_REGISTER	0x0F4
428eda2d14Spatrick #define WHM_TEST_OBSV		0x0F8
438eda2d14Spatrick #define WHM_TEST_CTL		0x0FC
448eda2d14Spatrick #define HHC_TEST_CFG		0x100
458eda2d14Spatrick #define HHC_TEST_CTL		0x104
468eda2d14Spatrick #define HHC_TEST_OBSV		0x108
478eda2d14Spatrick #define REVDEV			0x200 /* 16 bit */
488eda2d14Spatrick #define EP_NUM			0x204 /* 16 bit */
498eda2d14Spatrick #define DATA			0x208 /* 16 bit */
508eda2d14Spatrick #define CTRL			0x20C /* 16 bit */
518eda2d14Spatrick #define STAT_FLG		0x210 /* 16 bit */
528eda2d14Spatrick #define RXFSTAT			0x214 /* 16 bit */
538eda2d14Spatrick #define SYSCON1			0x218 /* 16 bit */
548eda2d14Spatrick #define SYSCON2			0x21C /* 16 bit */
558eda2d14Spatrick #define DEVSTAT			0x220 /* 16 bit */
568eda2d14Spatrick #define SOFREG			0x224 /* 16 bit */
578eda2d14Spatrick #define IRQ_EN			0x228 /* 16 bit */
588eda2d14Spatrick #define DMA_IRQ_EN		0x22C /* 16 bit */
598eda2d14Spatrick #define IRQ_SRC			0x230 /* 16 bit */
608eda2d14Spatrick #define EPN_STAT		0x234 /* 16 bit */
618eda2d14Spatrick #define DMAN_STAT		0x238 /* 16 bit */
628eda2d14Spatrick #define RXDMA_CFG		0x240 /* 16 bit */
638eda2d14Spatrick #define TXDMA_CFG		0x244 /* 16 bit */
648eda2d14Spatrick 
658eda2d14Spatrick #define TXDMA0			0x250
668eda2d14Spatrick #define TXDMA1		0x254
678eda2d14Spatrick #define TXDMA2		0x258
688eda2d14Spatrick #define RXDMA0		0x260
698eda2d14Spatrick #define RXDMA1		0x264
708eda2d14Spatrick #define RXDMA2		0x268
718eda2d14Spatrick 
728eda2d14Spatrick #define EP0	 	0x280
738eda2d14Spatrick #define EP_RX(x)	0x280 + (x * 4)
748eda2d14Spatrick #define EP_TX(x)	0x2C0 + (x * 4)
758eda2d14Spatrick 
768eda2d14Spatrick #define OTG_REV		0x300
778eda2d14Spatrick #define OTG_SYSCON_1	0x304
788eda2d14Spatrick #define OTG_SYSCON_2	0x308
798eda2d14Spatrick #define		OTG_SYSCON2_OTG_EN		0x80000000
808eda2d14Spatrick #define		OTG_SYSCON2_UHOST_EN		0x00000100
818eda2d14Spatrick #define		OTG_SYSCON2_MODE_DISABLED	0x00000000
828eda2d14Spatrick #define		OTG_SYSCON2_MODE_CLIENT		0x00000001
838eda2d14Spatrick #define		OTG_SYSCON2_MODE_HOST		0x00000004
848eda2d14Spatrick #define OTG_CTRL	0x30C
858eda2d14Spatrick #if 0
868eda2d14Spatrick #define OTG_IRQ_EN	0x310 /* 16 bit */
878eda2d14Spatrick #define OTG_IRQ_SRC	0x314 /* 16 bit */
888eda2d14Spatrick #define OTG_OUTCTRL	0x318 /* 16 bit */
898eda2d14Spatrick #define OTG_TEST	0x320 /* 16 bit */
908eda2d14Spatrick #endif
918eda2d14Spatrick #define OTG_VC		0x3FC
928eda2d14Spatrick 
938eda2d14Spatrick 
948eda2d14Spatrick int	omohci_match(struct device *, void *, void *);
958eda2d14Spatrick void	omohci_attach(struct device *, struct device *, void *);
968eda2d14Spatrick int	omohci_detach(struct device *, int);
978eda2d14Spatrick int	omohci_activate(struct device *, int);
988eda2d14Spatrick 
998eda2d14Spatrick struct omohci_softc {
1008eda2d14Spatrick 	struct ohci_softc	sc;
1018eda2d14Spatrick 	void			*sc_ihc0;
1028eda2d14Spatrick 	void			*sc_ihc1;
1038eda2d14Spatrick 	void			*sc_ihc2;
1048eda2d14Spatrick 	void			*sc_ih0;
1058eda2d14Spatrick 	void			*sc_ih1;
1068eda2d14Spatrick 	void			*sc_ihotg;
1078eda2d14Spatrick };
1088eda2d14Spatrick 
1098eda2d14Spatrick void	omohci_enable(struct omohci_softc *);
1108eda2d14Spatrick void	omohci_disable(struct omohci_softc *);
1118eda2d14Spatrick 
1129fdf0c62Smpi const struct cfattach omohci_ca = {
1138eda2d14Spatrick         sizeof (struct omohci_softc), omohci_match, omohci_attach,
1148eda2d14Spatrick 	omohci_detach, omohci_detach
1158eda2d14Spatrick };
1168eda2d14Spatrick 
1178eda2d14Spatrick int
1188eda2d14Spatrick omohci_match(struct device *parent, void *match, void *aux)
1198eda2d14Spatrick {
1208eda2d14Spatrick #if 0
1218eda2d14Spatrick 	if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) != CPU_ID_PXA27X)
1228eda2d14Spatrick 		return (0);
1238eda2d14Spatrick #endif
1248eda2d14Spatrick 
1258eda2d14Spatrick 	return (1);
1268eda2d14Spatrick }
1278eda2d14Spatrick 
1288eda2d14Spatrick void
1298eda2d14Spatrick omohci_attach(struct device *parent, struct device *self, void *aux)
1308eda2d14Spatrick {
1318eda2d14Spatrick 	struct omohci_softc	*sc = (struct omohci_softc *)self;
1328eda2d14Spatrick         struct ahb_attach_args	*aa = aux;
1338eda2d14Spatrick 	usbd_status		r;
1348eda2d14Spatrick 
1358eda2d14Spatrick 	sc->sc.iot = aa->aa_iot;
1368eda2d14Spatrick 	sc->sc.sc_bus.dmatag = aa->aa_dmat;
1378eda2d14Spatrick 	sc->sc_ih0 = NULL;
1388eda2d14Spatrick 	sc->sc_ih1 = NULL;
1398eda2d14Spatrick 	sc->sc_ihc0 = NULL;
1408eda2d14Spatrick 	sc->sc_ihc1 = NULL;
1418eda2d14Spatrick 	sc->sc_ihc2 = NULL;
1428eda2d14Spatrick 	sc->sc_ihotg = NULL;
1438eda2d14Spatrick 	sc->sc.sc_size = 0;
1448eda2d14Spatrick 
1458eda2d14Spatrick 	/* Map I/O space */
1468eda2d14Spatrick 	if (bus_space_map(sc->sc.iot, aa->aa_addr, aa->aa_size, 0,
1478eda2d14Spatrick 	    &sc->sc.ioh)) {
1488eda2d14Spatrick 		printf(": cannot map mem space\n");
1498eda2d14Spatrick 		return;
1508eda2d14Spatrick 	}
1518eda2d14Spatrick 	sc->sc.sc_size = aa->aa_size;
1528eda2d14Spatrick 
1538eda2d14Spatrick 	/* XXX copied from ohci_pci.c. needed? */
1548eda2d14Spatrick 	bus_space_barrier(sc->sc.iot, sc->sc.ioh, 0, sc->sc.sc_size,
1558eda2d14Spatrick 	    BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
1568eda2d14Spatrick 
1578eda2d14Spatrick #if 0
1588eda2d14Spatrick 	/* start the usb clock */
1598eda2d14Spatrick 	pxa2x0_clkman_config(CKEN_USBHC, 1);
1608eda2d14Spatrick #endif
1618eda2d14Spatrick 	omohci_enable(sc);
1628eda2d14Spatrick 
1638eda2d14Spatrick 	/* Disable interrupts, so we don't get any spurious ones. */
1648eda2d14Spatrick 	bus_space_write_4(sc->sc.iot, sc->sc.ioh, OHCI_INTERRUPT_DISABLE,
1658eda2d14Spatrick 	    OHCI_MIE);
1668eda2d14Spatrick 
1678eda2d14Spatrick 	sc->sc_ihc0 = arm_intr_establish(aa->aa_intr, IPL_USB,
1688eda2d14Spatrick 	    ohci_intr, &sc->sc, sc->sc.sc_bus.bdev.dv_xname);
1698eda2d14Spatrick 	sc->sc_ihc1 = arm_intr_establish(aa->aa_intr+1, IPL_USB,
1708eda2d14Spatrick 	    ohci_intr, &sc->sc, sc->sc.sc_bus.bdev.dv_xname);
1718eda2d14Spatrick 	sc->sc_ihc2 = arm_intr_establish(aa->aa_intr+2, IPL_USB,
1728eda2d14Spatrick 	    ohci_intr, &sc->sc, sc->sc.sc_bus.bdev.dv_xname);
1738eda2d14Spatrick 	sc->sc_ih0 = arm_intr_establish(aa->aa_intr+3, IPL_USB,
1748eda2d14Spatrick 	    ohci_intr, &sc->sc, sc->sc.sc_bus.bdev.dv_xname);
1758eda2d14Spatrick 	sc->sc_ih1 = arm_intr_establish(aa->aa_intr+4, IPL_USB,
1768eda2d14Spatrick 	    ohci_intr, &sc->sc, sc->sc.sc_bus.bdev.dv_xname);
1778eda2d14Spatrick 	sc->sc_ihotg = arm_intr_establish(aa->aa_intr+5, IPL_USB,
1788eda2d14Spatrick 	    ohci_intr, &sc->sc, sc->sc.sc_bus.bdev.dv_xname);
1798eda2d14Spatrick 	if (sc->sc_ih0 == NULL ||
1808eda2d14Spatrick 	    sc->sc_ih1 == NULL ||
1818eda2d14Spatrick 	    sc->sc_ihc0 == NULL ||
1828eda2d14Spatrick 	    sc->sc_ihc1 == NULL ||
1838eda2d14Spatrick 	    sc->sc_ihc2 == NULL ||
1848eda2d14Spatrick 	    sc->sc_ihotg == NULL) {
1858eda2d14Spatrick 		printf(": unable to establish interrupt\n");
1868eda2d14Spatrick 		omohci_disable(sc);
1878eda2d14Spatrick #if 0
1888eda2d14Spatrick 		pxa2x0_clkman_config(CKEN_USBHC, 0);
1898eda2d14Spatrick #endif
1908eda2d14Spatrick 		bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
1918eda2d14Spatrick 		sc->sc.sc_size = 0;
1928eda2d14Spatrick 		return;
1938eda2d14Spatrick 	}
1948eda2d14Spatrick 
1958eda2d14Spatrick 	prcm_enablemodule(PRCM_USB);
1968eda2d14Spatrick 
1978eda2d14Spatrick 	bus_space_write_4(sc->sc.iot, sc->sc.ioh, OTG_SYSCON_2,
1988eda2d14Spatrick 	    OTG_SYSCON2_UHOST_EN | OTG_SYSCON2_MODE_HOST);
1998eda2d14Spatrick 
2008eda2d14Spatrick 	strlcpy(sc->sc.sc_vendor, "OMAP24xx", sizeof(sc->sc.sc_vendor));
2018eda2d14Spatrick 	r = ohci_init(&sc->sc);
2028eda2d14Spatrick 	if (r != USBD_NORMAL_COMPLETION) {
2038eda2d14Spatrick 		printf("%s: init failed, error=%d\n",
2048eda2d14Spatrick 		    sc->sc.sc_bus.bdev.dv_xname, r);
2058eda2d14Spatrick 		arm_intr_disestablish(sc->sc_ih0);
2068eda2d14Spatrick 		arm_intr_disestablish(sc->sc_ih1);
2078eda2d14Spatrick 		arm_intr_disestablish(sc->sc_ihc0);
2088eda2d14Spatrick 		arm_intr_disestablish(sc->sc_ihc1);
2098eda2d14Spatrick 		arm_intr_disestablish(sc->sc_ihc2);
2108eda2d14Spatrick 		arm_intr_disestablish(sc->sc_ihotg);
2118eda2d14Spatrick 		sc->sc_ih0 = NULL;
2128eda2d14Spatrick 		sc->sc_ih1 = NULL;
2138eda2d14Spatrick 		sc->sc_ihc0 = NULL;
2148eda2d14Spatrick 		sc->sc_ihc1 = NULL;
2158eda2d14Spatrick 		sc->sc_ihc2 = NULL;
2168eda2d14Spatrick 		sc->sc_ihotg = NULL;
2178eda2d14Spatrick 		omohci_disable(sc);
2188eda2d14Spatrick #if 0
2198eda2d14Spatrick 		pxa2x0_clkman_config(CKEN_USBHC, 0);
2208eda2d14Spatrick #endif
2218eda2d14Spatrick 		bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
2228eda2d14Spatrick 		sc->sc.sc_size = 0;
2238eda2d14Spatrick 		return;
2248eda2d14Spatrick 	}
2258eda2d14Spatrick 
226ad21ef77Smpi 	config_found(self, &sc->sc.sc_bus, usbctlprint);
2278eda2d14Spatrick }
2288eda2d14Spatrick 
2298eda2d14Spatrick int
2308eda2d14Spatrick omohci_detach(struct device *self, int flags)
2318eda2d14Spatrick {
2328eda2d14Spatrick 	struct omohci_softc		*sc = (struct omohci_softc *)self;
2338eda2d14Spatrick 	int				rv;
2348eda2d14Spatrick 
235ad21ef77Smpi 	rv = ohci_detach(self, flags);
2368eda2d14Spatrick 	if (rv)
2378eda2d14Spatrick 		return (rv);
2388eda2d14Spatrick 
2398eda2d14Spatrick 	if (sc->sc_ih0 != NULL) {
2408eda2d14Spatrick 		arm_intr_disestablish(sc->sc_ih0);
2418eda2d14Spatrick 		arm_intr_disestablish(sc->sc_ih1);
2428eda2d14Spatrick 		arm_intr_disestablish(sc->sc_ihc0);
2438eda2d14Spatrick 		arm_intr_disestablish(sc->sc_ihc1);
2448eda2d14Spatrick 		arm_intr_disestablish(sc->sc_ihc2);
2458eda2d14Spatrick 		arm_intr_disestablish(sc->sc_ihotg);
2468eda2d14Spatrick 		sc->sc_ih0 = NULL;
2478eda2d14Spatrick 		sc->sc_ih1 = NULL;
2488eda2d14Spatrick 		sc->sc_ihc0 = NULL;
2498eda2d14Spatrick 		sc->sc_ihc1 = NULL;
2508eda2d14Spatrick 		sc->sc_ihc2 = NULL;
2518eda2d14Spatrick 		sc->sc_ihotg = NULL;
2528eda2d14Spatrick 	}
2538eda2d14Spatrick 
2548eda2d14Spatrick 	omohci_disable(sc);
2558eda2d14Spatrick 
2568eda2d14Spatrick 	/* stop clock */
2578eda2d14Spatrick #if 0
2588eda2d14Spatrick 	pxa2x0_clkman_config(CKEN_USBHC, 0);
2598eda2d14Spatrick #endif
2608eda2d14Spatrick 
2618eda2d14Spatrick 	if (sc->sc.sc_size) {
2628eda2d14Spatrick 		bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
2638eda2d14Spatrick 		sc->sc.sc_size = 0;
2648eda2d14Spatrick 	}
2658eda2d14Spatrick 
2668eda2d14Spatrick 	return (0);
2678eda2d14Spatrick }
2688eda2d14Spatrick 
2698eda2d14Spatrick 
2708eda2d14Spatrick int
2718eda2d14Spatrick omohci_activate(struct device *self, int act)
2728eda2d14Spatrick {
2738eda2d14Spatrick 	struct omohci_softc *sc = (struct omohci_softc *)self;
274*ea05d060Sderaadt 	int rv;
2758eda2d14Spatrick 
2768eda2d14Spatrick 	switch (act) {
2778eda2d14Spatrick 	case DVACT_SUSPEND:
2788eda2d14Spatrick 		sc->sc.sc_bus.use_polling++;
2798eda2d14Spatrick 		ohci_power(why, &sc->sc);
2808eda2d14Spatrick #if 0
2818eda2d14Spatrick 		pxa2x0_clkman_config(CKEN_USBHC, 0);
2828eda2d14Spatrick #endif
2838eda2d14Spatrick 		sc->sc.sc_bus.use_polling--;
284*ea05d060Sderaadt 		rv = config_activate_children(self, act);
2858eda2d14Spatrick 		break;
2868eda2d14Spatrick 
2878eda2d14Spatrick 	case DVACT_RESUME:
288*ea05d060Sderaadt 		rv = config_activate_children(self, act);
2898eda2d14Spatrick 		sc->sc.sc_bus.use_polling++;
2908eda2d14Spatrick #if 0
2918eda2d14Spatrick 		pxa2x0_clkman_config(CKEN_USBHC, 1);
2928eda2d14Spatrick #endif
2938eda2d14Spatrick 		omohci_enable(sc);
2948eda2d14Spatrick 		ohci_power(why, &sc->sc);
2958eda2d14Spatrick 		sc->sc.sc_bus.use_polling--;
2968eda2d14Spatrick 		break;
297*ea05d060Sderaadt 	default:
298*ea05d060Sderaadt 		rv = config_activate_children(self, act);
299*ea05d060Sderaadt 		break;
3008eda2d14Spatrick 	}
301*ea05d060Sderaadt 	return rv;
3028eda2d14Spatrick }
3038eda2d14Spatrick 
3048eda2d14Spatrick void
3058eda2d14Spatrick omohci_enable(struct omohci_softc *sc)
3068eda2d14Spatrick {
3078eda2d14Spatrick #if 0
3088eda2d14Spatrick 	u_int32_t			hr;
3098eda2d14Spatrick 
3108eda2d14Spatrick 	/* Full host reset */
3118eda2d14Spatrick 	hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR);
3128eda2d14Spatrick 	bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR,
3138eda2d14Spatrick 	    (hr & USBHC_HR_MASK) | USBHC_HR_FHR);
3148eda2d14Spatrick 
3158eda2d14Spatrick 	DELAY(USBHC_RST_WAIT);
3168eda2d14Spatrick 
3178eda2d14Spatrick 	hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR);
3188eda2d14Spatrick 	bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR,
3198eda2d14Spatrick 	    (hr & USBHC_HR_MASK) & ~(USBHC_HR_FHR));
3208eda2d14Spatrick 
3218eda2d14Spatrick 	/* Force system bus interface reset */
3228eda2d14Spatrick 	hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR);
3238eda2d14Spatrick 	bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR,
3248eda2d14Spatrick 	    (hr & USBHC_HR_MASK) | USBHC_HR_FSBIR);
3258eda2d14Spatrick 
3268eda2d14Spatrick 	while (bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR) & \
3278eda2d14Spatrick 	    USBHC_HR_FSBIR)
3288eda2d14Spatrick 		DELAY(3);
3298eda2d14Spatrick 
3308eda2d14Spatrick 	/* Enable the ports (physically only one, only enable that one?) */
3318eda2d14Spatrick 	hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR);
3328eda2d14Spatrick 	bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR,
3338eda2d14Spatrick 	    (hr & USBHC_HR_MASK) & ~(USBHC_HR_SSE));
3348eda2d14Spatrick 	hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR);
3358eda2d14Spatrick 	bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR,
3368eda2d14Spatrick 	    (hr & USBHC_HR_MASK) & ~(USBHC_HR_SSEP2));
3378eda2d14Spatrick #endif
3388eda2d14Spatrick }
3398eda2d14Spatrick 
3408eda2d14Spatrick void
3418eda2d14Spatrick omohci_disable(struct omohci_softc *sc)
3428eda2d14Spatrick {
3438eda2d14Spatrick #if 0
3448eda2d14Spatrick 	u_int32_t			hr;
3458eda2d14Spatrick 
3468eda2d14Spatrick 	/* Full host reset */
3478eda2d14Spatrick 	hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR);
3488eda2d14Spatrick 	bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR,
3498eda2d14Spatrick 	    (hr & USBHC_HR_MASK) | USBHC_HR_FHR);
3508eda2d14Spatrick 
3518eda2d14Spatrick 	DELAY(USBHC_RST_WAIT);
3528eda2d14Spatrick 
3538eda2d14Spatrick 	hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR);
3548eda2d14Spatrick 	bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR,
3558eda2d14Spatrick 	    (hr & USBHC_HR_MASK) & ~(USBHC_HR_FHR));
3568eda2d14Spatrick #endif
3578eda2d14Spatrick }
358