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

Reply via email to