From aee44fa37d780cfec95c444f43defd89ded021f0 Mon Sep 17 00:00:00 2001 From: Nico Huber Date: Thu, 6 Jun 2013 10:20:35 +0200 Subject: libpayload: usb: Add interval attribute to endpoints Read bInterval from endpoint descriptors and store it in our endpoint_t struct. The interval is encoded dependently on the device' speed and the endpoint's type. Therefore, it will be normalized to the binary logarithm of the number of microframes, i.e. t = 125us * 2^interval The interval attribute will be used in the xHCI driver. Change-Id: I65a8eda6145faf34666800789f0292e640a8141b Signed-off-by: Nico Huber Reviewed-on: http://review.coreboot.org/3449 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer --- payloads/libpayload/drivers/usb/usb.c | 44 +++++++++++++++++++++++++++++++++++ payloads/libpayload/include/usb/usb.h | 2 ++ 2 files changed, 46 insertions(+) diff --git a/payloads/libpayload/drivers/usb/usb.c b/payloads/libpayload/drivers/usb/usb.c index 54a5935c1a..47f8eb6e3a 100644 --- a/payloads/libpayload/drivers/usb/usb.c +++ b/payloads/libpayload/drivers/usb/usb.c @@ -278,6 +278,48 @@ generic_set_address (hci_t *controller, int speed, int hubport, int hubaddr) return adr; } +/* Normalize bInterval to log2 of microframes */ +static int +usb_decode_interval(const int speed, const endpoint_type type, const unsigned char bInterval) +{ +#define LOG2(a) ((sizeof(unsigned) << 3) - __builtin_clz(a) - 1) + switch (speed) { + case LOW_SPEED: + switch (type) { + case ISOCHRONOUS: case INTERRUPT: + return LOG2(bInterval) + 3; + default: + return 0; + } + case FULL_SPEED: + switch (type) { + case ISOCHRONOUS: + return (bInterval - 1) + 3; + case INTERRUPT: + return LOG2(bInterval) + 3; + default: + return 0; + } + case HIGH_SPEED: + switch (type) { + case ISOCHRONOUS: case INTERRUPT: + return bInterval - 1; + default: + return LOG2(bInterval); + } + case SUPER_SPEED: + switch (type) { + case ISOCHRONOUS: case INTERRUPT: + return bInterval - 1; + default: + return 0; + } + default: + return 0; + } +#undef LOG2 +} + static int set_address (hci_t *controller, int speed, int hubport, int hubaddr) { @@ -357,6 +399,7 @@ set_address (hci_t *controller, int speed, int hubport, int hubaddr) dev->endpoints[0].maxpacketsize = dd->bMaxPacketSize0; dev->endpoints[0].direction = SETUP; dev->endpoints[0].type = CONTROL; + dev->endpoints[0].interval = usb_decode_interval(dev->speed, CONTROL, endp->bInterval); for (j = 1; j <= current->bNumEndpoints; j++) { #ifdef USB_DEBUG static const char *transfertypes[4] = { @@ -374,6 +417,7 @@ set_address (hci_t *controller, int speed, int hubport, int hubaddr) ((endp->bEndpointAddress & 0x80) == 0) ? OUT : IN; ep->type = endp->bmAttributes; + ep->interval = usb_decode_interval(dev->speed, ep->type, endp->bInterval); endp = (endpoint_descriptor_t *) (((char *) endp) + endp->bLength); } diff --git a/payloads/libpayload/include/usb/usb.h b/payloads/libpayload/include/usb/usb.h index 3aac2aee6c..ab457088f8 100644 --- a/payloads/libpayload/include/usb/usb.h +++ b/payloads/libpayload/include/usb/usb.h @@ -91,6 +91,8 @@ typedef struct { int toggle; int maxpacketsize; endpoint_type type; + int interval; /* expressed as binary logarithm of the number + of microframes (i.e. t = 125us * 2^interval) */ } endpoint_t; enum { FULL_SPEED = 0, LOW_SPEED = 1, HIGH_SPEED = 2, SUPER_SPEED = 3 }; -- cgit v1.2.3