From 5624dfd5aa91c244519ec60b40b4a42b4d9a43ca Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 19 Jul 2017 21:51:16 +0800 Subject: [PATCH] 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 Reviewed-by: Simon Glass --- common/usb_hub.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++ include/usb.h | 16 +++++++++++++++ include/usb_defs.h | 12 +++++++++++ 3 files changed, 78 insertions(+) diff --git a/common/usb_hub.c b/common/usb_hub.c index 18c366ab7e..bbb1155089 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -700,6 +700,56 @@ static int usb_hub_configure(struct usb_device *dev) 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 f71da52b55..58b4549065 100644 --- a/include/usb.h +++ b/include/usb.h @@ -537,6 +537,21 @@ struct usb_hub_status { 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 @@ struct usb_hub_device { 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 273337f46a..b7f2eada07 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 @@ -309,6 +310,17 @@ /* Hub class request codes */ #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 */ -- 2.39.2