summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2016-10-02 06:36:39 +0000
committerkettenis <kettenis@openbsd.org>2016-10-02 06:36:39 +0000
commit9d524485a10715d8a443d4868a6899a3cf53e004 (patch)
tree0be1fb7deb73c72e414f4d76a323a3c5725cb519
parentsome minor tweaks; ok yasuoka (diff)
downloadwireguard-openbsd-9d524485a10715d8a443d4868a6899a3cf53e004.tar.xz
wireguard-openbsd-9d524485a10715d8a443d4868a6899a3cf53e004.zip
Save and restore the (non-standard) USBMODE register around a reset of the
controller. This register controls whether the controller is in device or host mode on many dual role controllers and gets reset during a reset of the controller, placing the controller in (non-functional) idle mode. By saving and restoring it, we keep the controller in host mode. Since this is a non-standard register, add a new EHCIF_USBMODE flag and only do the save and restore if it has been set. Makes the upper "OTG" port of the Cubox-i work. ok mpi@, jsg@
-rw-r--r--sys/arch/armv7/imx/imxehci.c10
-rw-r--r--sys/dev/usb/ehci.c10
-rw-r--r--sys/dev/usb/ehcireg.h9
-rw-r--r--sys/dev/usb/ehcivar.h3
4 files changed, 22 insertions, 10 deletions
diff --git a/sys/arch/armv7/imx/imxehci.c b/sys/arch/armv7/imx/imxehci.c
index 89fe44d0edd..a76d477f5e6 100644
--- a/sys/arch/armv7/imx/imxehci.c
+++ b/sys/arch/armv7/imx/imxehci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: imxehci.c,v 1.17 2016/08/13 11:08:58 kettenis Exp $ */
+/* $OpenBSD: imxehci.c,v 1.18 2016/10/02 06:36:39 kettenis Exp $ */
/*
* Copyright (c) 2012-2013 Patrick Wildt <patrick@blueri.se>
*
@@ -58,9 +58,6 @@
/* ehci */
#define USB_EHCI_OFFSET 0x100
-#define EHCI_USBMODE 0xa8
-
-#define EHCI_USBMODE_HOST (3 << 0)
#define EHCI_PS_PTS_UTMI_MASK ((1 << 25) | (3 << 30))
/* usb non-core */
@@ -144,6 +141,7 @@ imxehci_attach(struct device *parent, struct device *self, void *aux)
sc->sc.iot = faa->fa_iot;
sc->sc.sc_bus.dmatag = faa->fa_dmat;
sc->sc.sc_size = faa->fa_reg[0].size - USB_EHCI_OFFSET;
+ sc->sc.sc_flags = EHCIF_USBMODE;
/* Map I/O space */
if (bus_space_map(sc->sc.iot, faa->fa_reg[0].addr,
@@ -247,8 +245,8 @@ imxehci_attach(struct device *parent, struct device *self, void *aux)
USBPHY_CTRL_ENUTMILEVEL2 | USBPHY_CTRL_ENUTMILEVEL3);
/* set host mode */
- EWRITE4(&sc->sc, EHCI_USBMODE,
- EREAD4(&sc->sc, EHCI_USBMODE) | EHCI_USBMODE_HOST);
+ EOWRITE4(&sc->sc, EHCI_USBMODE,
+ EOREAD4(&sc->sc, EHCI_USBMODE) | EHCI_USBMODE_CM_HOST);
/* set to UTMI mode */
EOWRITE4(&sc->sc, EHCI_PORTSC(1),
diff --git a/sys/dev/usb/ehci.c b/sys/dev/usb/ehci.c
index 2d5c461cdad..5b5ddbebaff 100644
--- a/sys/dev/usb/ehci.c
+++ b/sys/dev/usb/ehci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ehci.c,v 1.193 2016/09/15 02:00:17 dlg Exp $ */
+/* $OpenBSD: ehci.c,v 1.194 2016/10/02 06:36:39 kettenis Exp $ */
/* $NetBSD: ehci.c,v 1.66 2004/06/30 03:11:56 mycroft Exp $ */
/*
@@ -1114,7 +1114,7 @@ ehci_activate(struct device *self, int act)
usbd_status
ehci_reset(struct ehci_softc *sc)
{
- u_int32_t hcr;
+ u_int32_t hcr, usbmode;
int i;
EOWRITE4(sc, EHCI_USBCMD, 0); /* Halt controller */
@@ -1128,6 +1128,9 @@ ehci_reset(struct ehci_softc *sc)
if (!hcr)
printf("%s: halt timeout\n", sc->sc_bus.bdev.dv_xname);
+ if (sc->sc_flags & EHCIF_USBMODE)
+ usbmode = EOREAD4(sc, EHCI_USBMODE);
+
EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET);
for (i = 0; i < 100; i++) {
usb_delay_ms(&sc->sc_bus, 1);
@@ -1141,6 +1144,9 @@ ehci_reset(struct ehci_softc *sc)
return (USBD_IOERROR);
}
+ if (sc->sc_flags & EHCIF_USBMODE)
+ EOWRITE4(sc, EHCI_USBMODE, usbmode);
+
return (USBD_NORMAL_COMPLETION);
}
diff --git a/sys/dev/usb/ehcireg.h b/sys/dev/usb/ehcireg.h
index f88c8f93d14..10c50a5cd4e 100644
--- a/sys/dev/usb/ehcireg.h
+++ b/sys/dev/usb/ehcireg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ehcireg.h,v 1.20 2015/04/10 13:56:42 mpi Exp $ */
+/* $OpenBSD: ehcireg.h,v 1.21 2016/10/02 06:36:39 kettenis Exp $ */
/* $NetBSD: ehcireg.h,v 1.17 2004/06/23 06:45:56 mycroft Exp $ */
/*
@@ -162,6 +162,13 @@
#define EHCI_PORT_RESET_COMPLETE 2 /* ms */
+/* Nonstandard register to set controller mode. */
+#define EHCI_USBMODE 0x68
+#define EHCI_USBMODE_CM_M 0x00000003
+#define EHCI_USBMODE_CM_IDLE 0x00000000
+#define EHCI_USBMODE_CM_DEVICE 0x00000002
+#define EHCI_USBMODE_CM_HOST 0x00000003
+
#define EHCI_FLALIGN_ALIGN 0x1000
/* No data structure may cross a page boundary. */
diff --git a/sys/dev/usb/ehcivar.h b/sys/dev/usb/ehcivar.h
index 86b36405ecc..8fd2c89e8da 100644
--- a/sys/dev/usb/ehcivar.h
+++ b/sys/dev/usb/ehcivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ehcivar.h,v 1.36 2015/11/02 14:55:41 mpi Exp $ */
+/* $OpenBSD: ehcivar.h,v 1.37 2016/10/02 06:36:39 kettenis Exp $ */
/* $NetBSD: ehcivar.h,v 1.19 2005/04/29 15:04:29 augustss Exp $ */
/*
@@ -130,6 +130,7 @@ struct ehci_softc {
int sc_flags; /* misc flags */
#define EHCIF_DROPPED_INTR_WORKAROUND 0x01
#define EHCIF_PCB_INTR 0x02
+#define EHCIF_USBMODE 0x04
char sc_vendor[16]; /* vendor string for root hub */
int sc_id_vendor; /* vendor ID for root hub */