usb: hub: Parse and save TT details from device descriptor
A high speed hub has a special responsibility to handle full speed/
low speed devices connected on downstream ports. In this case, the
hub must isolate the high speed signaling environment from the full
speed/low speed signaling environment with the help of Transaction
Translator (TT). TT details are provided by hub descriptors and we
parse and save it to hub uclass_priv for later use.
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
diff --git a/common/usb_hub.c b/common/usb_hub.c
index 18c366a..bbb1155 100644
--- a/common/usb_hub.c
+++ b/common/usb_hub.c
@@ -700,6 +700,56 @@
break;
}
+ switch (dev->descriptor.bDeviceProtocol) {
+ case USB_HUB_PR_FS:
+ break;
+ case USB_HUB_PR_HS_SINGLE_TT:
+ debug("Single TT\n");
+ break;
+ case USB_HUB_PR_HS_MULTI_TT:
+ ret = usb_set_interface(dev, 0, 1);
+ if (ret == 0) {
+ debug("TT per port\n");
+ hub->tt.multi = true;
+ } else {
+ debug("Using single TT (err %d)\n", ret);
+ }
+ break;
+ case USB_HUB_PR_SS:
+ /* USB 3.0 hubs don't have a TT */
+ break;
+ default:
+ debug("Unrecognized hub protocol %d\n",
+ dev->descriptor.bDeviceProtocol);
+ break;
+ }
+
+ /* Note 8 FS bit times == (8 bits / 12000000 bps) ~= 666ns */
+ switch (hubCharacteristics & HUB_CHAR_TTTT) {
+ case HUB_TTTT_8_BITS:
+ if (dev->descriptor.bDeviceProtocol != 0) {
+ hub->tt.think_time = 666;
+ debug("TT requires at most %d FS bit times (%d ns)\n",
+ 8, hub->tt.think_time);
+ }
+ break;
+ case HUB_TTTT_16_BITS:
+ hub->tt.think_time = 666 * 2;
+ debug("TT requires at most %d FS bit times (%d ns)\n",
+ 16, hub->tt.think_time);
+ break;
+ case HUB_TTTT_24_BITS:
+ hub->tt.think_time = 666 * 3;
+ debug("TT requires at most %d FS bit times (%d ns)\n",
+ 24, hub->tt.think_time);
+ break;
+ case HUB_TTTT_32_BITS:
+ hub->tt.think_time = 666 * 4;
+ debug("TT requires at most %d FS bit times (%d ns)\n",
+ 32, hub->tt.think_time);
+ break;
+ }
+
debug("power on to power good time: %dms\n",
descriptor->bPwrOn2PwrGood * 2);
debug("hub controller current requirement: %dmA\n",
diff --git a/include/usb.h b/include/usb.h
index f71da52..58b4549 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -537,6 +537,21 @@
unsigned short wHubChange;
} __attribute__ ((packed));
+/*
+ * Hub Device descriptor
+ * USB Hub class device protocols
+ */
+#define USB_HUB_PR_FS 0 /* Full speed hub */
+#define USB_HUB_PR_HS_NO_TT 0 /* Hi-speed hub without TT */
+#define USB_HUB_PR_HS_SINGLE_TT 1 /* Hi-speed hub with single TT */
+#define USB_HUB_PR_HS_MULTI_TT 2 /* Hi-speed hub with multiple TT */
+#define USB_HUB_PR_SS 3 /* Super speed hub */
+
+/* Transaction Translator Think Times, in bits */
+#define HUB_TTTT_8_BITS 0x00
+#define HUB_TTTT_16_BITS 0x20
+#define HUB_TTTT_24_BITS 0x40
+#define HUB_TTTT_32_BITS 0x60
/* Hub descriptor */
struct usb_hub_descriptor {
@@ -571,6 +586,7 @@
ulong query_delay; /* Device query delay in ms */
int overcurrent_count[USB_MAXCHILDREN]; /* Over-current counter */
int hub_depth; /* USB 3.0 hub depth */
+ struct usb_tt tt; /* Transaction Translator */
};
#ifdef CONFIG_DM_USB
diff --git a/include/usb_defs.h b/include/usb_defs.h
index 273337f..b7f2ead 100644
--- a/include/usb_defs.h
+++ b/include/usb_defs.h
@@ -293,6 +293,7 @@
#define HUB_CHAR_LPSM 0x0003
#define HUB_CHAR_COMPOUND 0x0004
#define HUB_CHAR_OCPM 0x0018
+#define HUB_CHAR_TTTT 0x0060 /* TT Think Time mask */
/*
* Hub Status & Hub Change bit masks
@@ -310,6 +311,17 @@
#define USB_REQ_SET_HUB_DEPTH 0x0c
/*
+ * As of USB 2.0, full/low speed devices are segregated into trees.
+ * One type grows from USB 1.1 host controllers (OHCI, UHCI etc).
+ * The other type grows from high speed hubs when they connect to
+ * full/low speed devices using "Transaction Translators" (TTs).
+ */
+struct usb_tt {
+ bool multi; /* true means one TT per port */
+ unsigned think_time; /* think time in ns */
+};
+
+/*
* CBI style
*/