summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2008-12-23 04:42:10 +0000
committersam <sam@FreeBSD.org>2008-12-23 04:42:10 +0000
commitbb64ee0d8690157aadd890072d66aece6a5c8c01 (patch)
tree344f5514b5ff42f0a84ac8bd8622880dbd1466ee /sys/dev
parent95b2457edfed9c954582bdeac5fbb5c317f21e76 (diff)
downloadFreeBSD-src-bb64ee0d8690157aadd890072d66aece6a5c8c01.zip
FreeBSD-src-bb64ee0d8690157aadd890072d66aece6a5c8c01.tar.gz
o add Transaction Translator support (still missing ISOC xfers)
o add EHCI_SCFLG_BIGEMMIO flag to force big-endian byte-select to be set in USBMODE o split reset work into new public routine ehci_reset so bus shim drivers can force big-endian byte-select before ehci_init
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/usb/ehci.c58
-rw-r--r--sys/dev/usb/ehcivar.h3
2 files changed, 40 insertions, 21 deletions
diff --git a/sys/dev/usb/ehci.c b/sys/dev/usb/ehci.c
index 1b4c0080..11a5e83 100644
--- a/sys/dev/usb/ehci.c
+++ b/sys/dev/usb/ehci.c
@@ -310,33 +310,18 @@ static struct usbd_pipe_methods ehci_device_isoc_methods = {
ehci_device_isoc_done,
};
-static usbd_status
-ehci_hcreset(ehci_softc_t *sc)
+usbd_status
+ehci_reset(ehci_softc_t *sc)
{
u_int32_t hcr;
u_int i;
- EOWRITE4(sc, EHCI_USBCMD, 0); /* Halt controller */
- for (i = 0; i < 100; i++) {
- usb_delay_ms(&sc->sc_bus, 1);
- hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH;
- if (hcr)
- break;
- }
- if (!hcr)
- /*
- * Fall through and try reset anyway even though
- * Table 2-9 in the EHCI spec says this will result
- * in undefined behavior.
- */
- device_printf(sc->sc_bus.bdev, "stop timeout\n");
-
EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET);
for (i = 0; i < 100; i++) {
usb_delay_ms(&sc->sc_bus, 1);
hcr = EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_HCRESET;
if (!hcr) {
- if (sc->sc_flags & EHCI_SCFLG_SETMODE) {
+ if (sc->sc_flags & (EHCI_SCFLG_SETMODE | EHCI_SCFLG_BIGEMMIO)) {
/*
* Force USBMODE as requested. Controllers
* may have multiple operating modes.
@@ -347,6 +332,11 @@ ehci_hcreset(ehci_softc_t *sc)
device_printf(sc->sc_bus.bdev,
"set host controller mode\n");
}
+ if (sc->sc_flags & EHCI_SCFLG_BIGEMMIO) {
+ usbmode = (usbmode &~ EHCI_UM_ES) | EHCI_UM_ES_BE;
+ device_printf(sc->sc_bus.bdev,
+ "set big-endian mode\n");
+ }
EOWRITE4(sc, EHCI_USBMODE, usbmode);
}
return (USBD_NORMAL_COMPLETION);
@@ -356,6 +346,30 @@ ehci_hcreset(ehci_softc_t *sc)
return (USBD_IOERROR);
}
+static usbd_status
+ehci_hcreset(ehci_softc_t *sc)
+{
+ u_int32_t hcr;
+ u_int i;
+
+ EOWRITE4(sc, EHCI_USBCMD, 0); /* Halt controller */
+ for (i = 0; i < 100; i++) {
+ usb_delay_ms(&sc->sc_bus, 1);
+ hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH;
+ if (hcr)
+ break;
+ }
+ if (!hcr)
+ /*
+ * Fall through and try reset anyway even though
+ * Table 2-9 in the EHCI spec says this will result
+ * in undefined behavior.
+ */
+ device_printf(sc->sc_bus.bdev, "stop timeout\n");
+
+ return ehci_reset(sc);
+}
+
usbd_status
ehci_init(ehci_softc_t *sc)
{
@@ -2008,7 +2022,7 @@ ehci_root_ctrl_start(usbd_xfer_handle xfer)
i = UPS_HIGH_SPEED;
- if (sc->sc_flags & EHCI_SCFLG_FORCESPEED) {
+ if (sc->sc_flags & (EHCI_SCFLG_FORCESPEED | EHCI_SCFLG_TT)) {
if ((v & 0xc000000) == 0x8000000)
i = UPS_HIGH_SPEED;
else if ((v & 0xc000000) == 0x4000000)
@@ -2056,7 +2070,8 @@ ehci_root_ctrl_start(usbd_xfer_handle xfer)
case UHF_PORT_RESET:
DPRINTFN(5,("ehci_root_ctrl_start: reset port %d\n",
index));
- if (EHCI_PS_IS_LOWSPEED(v)) {
+ if (EHCI_PS_IS_LOWSPEED(v) &&
+ (sc->sc_flags & EHCI_SCFLG_TT) == 0) {
/* Low speed device, give up ownership. */
ehci_disown(sc, index, 1);
break;
@@ -2089,7 +2104,8 @@ ehci_root_ctrl_start(usbd_xfer_handle xfer)
device_get_nameunit(sc->sc_bus.bdev));
return (USBD_TIMEOUT);
}
- if (!(v & EHCI_PS_PE)) {
+ if (!(v & EHCI_PS_PE) &&
+ (sc->sc_flags & EHCI_SCFLG_TT) == 0) {
/* Not a high speed device, give up ownership.*/
ehci_disown(sc, index, 0);
break;
diff --git a/sys/dev/usb/ehcivar.h b/sys/dev/usb/ehcivar.h
index 86720fe..fdd19ba 100644
--- a/sys/dev/usb/ehcivar.h
+++ b/sys/dev/usb/ehcivar.h
@@ -126,6 +126,8 @@ struct ehci_soft_islot {
#define EHCI_SCFLG_FORCESPEED 0x0008 /* force speed (Marvell) */
#define EHCI_SCFLG_NORESTERM 0x0010 /* don't terminate reset sequence (Marvell) */
#define EHCI_SCFLG_BIGEDESC 0x0020 /* big-endian byte order descriptors */
+#define EHCI_SCFLG_BIGEMMIO 0x0040 /* big-endian byte order MMIO */
+#define EHCI_SCFLG_TT 0x0080 /* transaction translator present */
typedef struct ehci_softc {
struct usbd_bus sc_bus; /* base device */
@@ -257,6 +259,7 @@ hc16toh(const struct ehci_softc *sc, const uint16_t v)
}
#endif
+usbd_status ehci_reset(ehci_softc_t *);
usbd_status ehci_init(ehci_softc_t *);
int ehci_intr(void *);
int ehci_detach(ehci_softc_t *, int);
OpenPOWER on IntegriCloud