Module Name: src Committed By: matt Date: Tue Jan 18 08:29:24 UTC 2011
Modified Files: src/sys/dev/usb: ehci.c ehcireg.h ehcivar.h usb.h Log Message: Add preliminary support for Embedded Transaction Translator Function (as found on the MPC8536 and AR9334) which allows low/full devices to be connected to an EHCI root hub. To generate a diff of this commit: cvs rdiff -u -r1.171 -r1.172 src/sys/dev/usb/ehci.c cvs rdiff -u -r1.31 -r1.32 src/sys/dev/usb/ehcireg.h cvs rdiff -u -r1.37 -r1.38 src/sys/dev/usb/ehcivar.h cvs rdiff -u -r1.90 -r1.91 src/sys/dev/usb/usb.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/usb/ehci.c diff -u src/sys/dev/usb/ehci.c:1.171 src/sys/dev/usb/ehci.c:1.172 --- src/sys/dev/usb/ehci.c:1.171 Wed Nov 3 22:34:23 2010 +++ src/sys/dev/usb/ehci.c Tue Jan 18 08:29:24 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: ehci.c,v 1.171 2010/11/03 22:34:23 dyoung Exp $ */ +/* $NetBSD: ehci.c,v 1.172 2011/01/18 08:29:24 matt Exp $ */ /* * Copyright (c) 2004-2008 The NetBSD Foundation, Inc. @@ -52,7 +52,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.171 2010/11/03 22:34:23 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.172 2011/01/18 08:29:24 matt Exp $"); #include "ohci.h" #include "uhci.h" @@ -354,6 +354,7 @@ sc->sc_ncomp = ncomp; } if (sc->sc_ncomp > 0) { + KASSERT(!(sc->sc_flags & EHCIF_ETTF)); aprint_normal("%s: companion controller%s, %d port%s each:", device_xname(sc->sc_dev), sc->sc_ncomp!=1 ? "s" : "", EHCI_HCS_N_PCC(sparams), @@ -395,6 +396,17 @@ if (sc->sc_vendor_init) sc->sc_vendor_init(sc); + /* + * If we are doing embedded transaction translation function, force + * the controller to host mode. + */ + if (sc->sc_flags & EHCIF_ETTF) { + uint32_t usbmode = EREAD4(sc, EHCI_USBMODE); + usbmode &= ~EHCI_USBMODE_CM; + usbmode |= EHCI_USBMODE_CM_HOST; + EWRITE4(sc, EHCI_USBMODE, usbmode); + } + /* XXX need proper intr scheduling */ sc->sc_rand = 96; @@ -1535,7 +1547,17 @@ pipe, addr, ed->bEndpointAddress, sc->sc_addr)); if (dev->myhsport) { - hshubaddr = dev->myhsport->parent->address; + /* + * When directly attached FS/LS device while doing embedded + * transaction translations and we are the hub, set the hub + * adddress to 0 (us). + */ + if (!(sc->sc_flags & EHCIF_ETTF) + || (dev->myhsport->parent->address != sc->sc_addr)) { + hshubaddr = dev->myhsport->parent->address; + } else { + hshubaddr = 0; + } hshubport = dev->myhsport->portno; } else { hshubaddr = 0; @@ -2249,7 +2271,18 @@ v = EOREAD4(sc, EHCI_PORTSC(index)); DPRINTFN(8,("ehci_root_ctrl_start: port status=0x%04x\n", v)); - i = UPS_HIGH_SPEED; + + if (sc->sc_flags & EHCIF_ETTF) { + /* + * If we are doing embedded transaction translation, + * then directly attached LS/FS devices are reset by + * the EHCI controller itself. PSPD is encoded + * the same way as in USBSTATUS. + */ + i = __SHIFTOUT(v, EHCI_PS_PSPD) * UPS_LOW_SPEED; + } else { + i = UPS_HIGH_SPEED; + } if (v & EHCI_PS_CS) i |= UPS_CURRENT_CONNECT_STATUS; if (v & EHCI_PS_PE) i |= UPS_PORT_ENABLED; if (v & EHCI_PS_SUSP) i |= UPS_SUSPEND; @@ -2293,8 +2326,13 @@ case UHF_PORT_RESET: DPRINTFN(5,("ehci_root_ctrl_start: reset port %d\n", index)); - if (EHCI_PS_IS_LOWSPEED(v) && sc->sc_ncomp > 0) { - /* Low speed device, give up ownership. */ + if (EHCI_PS_IS_LOWSPEED(v) + && sc->sc_ncomp > 0 + && !(sc->sc_flags & EHCIF_ETTF)) { + /* + * Low speed device on non-ETTF controller or + * unaccompanied controller, give up ownership. + */ ehci_disown(sc, index, 1); break; } @@ -2307,15 +2345,24 @@ err = USBD_IOERROR; goto ret; } - /* Terminate reset sequence. */ - v = EOREAD4(sc, port); - EOWRITE4(sc, port, v & ~EHCI_PS_PR); - /* Wait for HC to complete reset. */ - usb_delay_ms(&sc->sc_bus, EHCI_PORT_RESET_COMPLETE); - if (sc->sc_dying) { - err = USBD_IOERROR; - goto ret; + /* + * An embedded transaction translater will automatically + * terminate the reset sequence so there's no need to + * it. + */ + if (!(sc->sc_flags & EHCIF_ETTF)) { + /* Terminate reset sequence. */ + v = EOREAD4(sc, port); + EOWRITE4(sc, port, v); + /* Wait for HC to complete reset. */ + usb_delay_ms(&sc->sc_bus, + EHCI_PORT_RESET_COMPLETE); + if (sc->sc_dying) { + err = USBD_IOERROR; + goto ret; + } } + v = EOREAD4(sc, port); DPRINTF(("ehci after reset, status=0x%08x\n", v)); if (v & EHCI_PS_PR) { Index: src/sys/dev/usb/ehcireg.h diff -u src/sys/dev/usb/ehcireg.h:1.31 src/sys/dev/usb/ehcireg.h:1.32 --- src/sys/dev/usb/ehcireg.h:1.31 Wed Jun 2 18:53:39 2010 +++ src/sys/dev/usb/ehcireg.h Tue Jan 18 08:29:24 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: ehcireg.h,v 1.31 2010/06/02 18:53:39 jakllsch Exp $ */ +/* $NetBSD: ehcireg.h,v 1.32 2011/01/18 08:29:24 matt Exp $ */ /* * Copyright (c) 2001, 2004 The NetBSD Foundation, Inc. @@ -76,6 +76,8 @@ #define EHCI_HCIVERSION 0x02 /* RO Interface version number */ #define EHCI_HCSPARAMS 0x04 /* RO Structural parameters */ +#define EHCI_HCS_N_TT(x) (((x) >> 20) & 0xf) /* # of xacts xlater ETTF */ +#define EHCI_HCS_N_PTT(x) (((x) >> 20) & 0xf) /* ports per xlater ETTF */ #define EHCI_HCS_DEBUGPORT(x) (((x) >> 20) & 0xf) #define EHCI_HCS_P_INDICATOR(x) ((x) & 0x10000) #define EHCI_HCS_N_CC(x) (((x) >> 12) & 0xf) /* # of companion ctlrs */ @@ -147,6 +149,10 @@ #define EHCI_CONF_CF 0x00000001 /* RW configure flag */ #define EHCI_PORTSC(n) (0x40+4*(n)) /* RO, RW, RWC Port Status reg */ +#define EHCI_PS_PSPD 0x03000000 /* RO port speed (ETTF) */ +#define EHCI_PS_PSPD_FS 0x00000000 /* Full speed (ETTF) */ +#define EHCI_PS_PSPD_LS 0x01000000 /* Low speed (ETTF) */ +#define EHCI_PS_PSPD_HS 0x02000000 /* High speed (ETTF) */ #define EHCI_PS_WKOC_E 0x00400000 /* RW wake on over current ena */ #define EHCI_PS_WKDSCNNT_E 0x00200000 /* RW wake on disconnect ena */ #define EHCI_PS_WKCNNT_E 0x00100000 /* RW wake on connect ena */ @@ -169,6 +175,15 @@ #define EHCI_PORT_RESET_COMPLETE 2 /* ms */ +#define EHCI_USBMODE 0xa8 /* USB Device mode */ +#define EHCI_USBMODE_SDIS __BIT(4) /* Stream disable mode 1=act */ +#define EHCI_USBMODE_SLOM __BIT(3) /* setup lockouts on */ +#define EHCI_USBMODE_ES __BIT(2) /* Endian Select ES=1 */ +#define EHCI_USBMODE_CM __BITS(0,1) /* Controller Mode */ +#define EHCI_USBMODE_CM_IDLE 0x00 /* Idle (combo host/device) */ +#define EHCI_USBMODE_CM_DEV 0x02 /* Device Controller */ +#define EHCI_USBMODE_CM_HOST 0x03 /* Host Controller */ + #define EHCI_FLALIGN_ALIGN 0x1000 #define EHCI_MAX_PORTS 16 /* only 4 bits available in EHCI_HCS_N_PORTS */ Index: src/sys/dev/usb/ehcivar.h diff -u src/sys/dev/usb/ehcivar.h:1.37 src/sys/dev/usb/ehcivar.h:1.38 --- src/sys/dev/usb/ehcivar.h:1.37 Sat Oct 16 05:23:42 2010 +++ src/sys/dev/usb/ehcivar.h Tue Jan 18 08:29:24 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: ehcivar.h,v 1.37 2010/10/16 05:23:42 kiyohara Exp $ */ +/* $NetBSD: ehcivar.h,v 1.38 2011/01/18 08:29:24 matt Exp $ */ /* * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -116,6 +116,7 @@ u_int sc_offs; /* offset to operational regs */ int sc_flags; /* misc flags */ #define EHCIF_DROPPED_INTR_WORKAROUND 0x01 +#define EHCIF_ETTF 0x02 /* Emb. Transaction Translater func. */ char sc_vendor[32]; /* vendor string for root hub */ int sc_id_vendor; /* vendor ID for root hub */ Index: src/sys/dev/usb/usb.h diff -u src/sys/dev/usb/usb.h:1.90 src/sys/dev/usb/usb.h:1.91 --- src/sys/dev/usb/usb.h:1.90 Sat Dec 25 15:27:08 2010 +++ src/sys/dev/usb/usb.h Tue Jan 18 08:29:24 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: usb.h,v 1.90 2010/12/25 15:27:08 wiz Exp $ */ +/* $NetBSD: usb.h,v 1.91 2011/01/18 08:29:24 matt Exp $ */ /* $FreeBSD: src/sys/dev/usb/usb.h,v 1.14 1999/11/17 22:33:46 n_hibma Exp $ */ /* @@ -436,6 +436,7 @@ #define UPS_OVERCURRENT_INDICATOR 0x0008 #define UPS_RESET 0x0010 #define UPS_PORT_POWER 0x0100 +#define UPS_FULL_SPEED 0x0000 /* for completeness */ #define UPS_LOW_SPEED 0x0200 #define UPS_HIGH_SPEED 0x0400 #define UPS_PORT_TEST 0x0800