summaryrefslogtreecommitdiff
path: root/payloads/libpayload/drivers
diff options
context:
space:
mode:
authorNico Huber <nico.huber@secunet.com>2013-06-06 10:20:35 +0200
committerStefan Reinauer <stefan.reinauer@coreboot.org>2013-06-13 22:16:39 +0200
commitaee44fa37d780cfec95c444f43defd89ded021f0 (patch)
tree55fc6d2955f6e8cfb0b452c24c33b4a47225a5d4 /payloads/libpayload/drivers
parent482af6d15ca8eed28b51edc11692815419326d65 (diff)
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 <nico.huber@secunet.com> Reviewed-on: http://review.coreboot.org/3449 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'payloads/libpayload/drivers')
-rw-r--r--payloads/libpayload/drivers/usb/usb.c44
1 files changed, 44 insertions, 0 deletions
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);
}