From 405fc730ef06d30fb064dc562577f060832fc8c3 Mon Sep 17 00:00:00 2001 From: Sam Leffler Date: Tue, 23 Dec 2008 04:42:10 +0000 Subject: [PATCH] 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 --- sys/dev/usb/ehci.c | 68 ++++++++++++++++++++++++++----------------- sys/dev/usb/ehcivar.h | 3 ++ 2 files changed, 45 insertions(+), 26 deletions(-) diff --git a/sys/dev/usb/ehci.c b/sys/dev/usb/ehci.c index 1b4c00809b9..11a5e83cc3f 100644 --- a/sys/dev/usb/ehci.c +++ b/sys/dev/usb/ehci.c @@ -310,6 +310,42 @@ static struct usbd_pipe_methods ehci_device_isoc_methods = { ehci_device_isoc_done, }; +usbd_status +ehci_reset(ehci_softc_t *sc) +{ + u_int32_t hcr; + u_int i; + + 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 | EHCI_SCFLG_BIGEMMIO)) { + /* + * Force USBMODE as requested. Controllers + * may have multiple operating modes. + */ + uint32_t usbmode = EOREAD4(sc, EHCI_USBMODE); + if (sc->sc_flags & EHCI_SCFLG_SETMODE) { + usbmode = (usbmode &~ EHCI_UM_CM) | EHCI_UM_CM_HOST; + 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); + } + } + printf("%s: reset timeout\n", device_get_nameunit(sc->sc_bus.bdev)); + return (USBD_IOERROR); +} + static usbd_status ehci_hcreset(ehci_softc_t *sc) { @@ -331,29 +367,7 @@ ehci_hcreset(ehci_softc_t *sc) */ 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) { - /* - * Force USBMODE as requested. Controllers - * may have multiple operating modes. - */ - uint32_t usbmode = EOREAD4(sc, EHCI_USBMODE); - if (sc->sc_flags & EHCI_SCFLG_SETMODE) { - usbmode = (usbmode &~ EHCI_UM_CM) | EHCI_UM_CM_HOST; - device_printf(sc->sc_bus.bdev, - "set host controller mode\n"); - } - EOWRITE4(sc, EHCI_USBMODE, usbmode); - } - return (USBD_NORMAL_COMPLETION); - } - } - printf("%s: reset timeout\n", device_get_nameunit(sc->sc_bus.bdev)); - return (USBD_IOERROR); + return ehci_reset(sc); } usbd_status @@ -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 86720fe5942..fdd19bae2b6 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);