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>
This commit is contained in:
Nico Huber 2013-06-06 10:20:35 +02:00 committed by Stefan Reinauer
parent 482af6d15c
commit aee44fa37d
2 changed files with 46 additions and 0 deletions

View File

@ -278,6 +278,48 @@ generic_set_address (hci_t *controller, int speed, int hubport, int hubaddr)
return adr; 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 static int
set_address (hci_t *controller, int speed, int hubport, int hubaddr) 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].maxpacketsize = dd->bMaxPacketSize0;
dev->endpoints[0].direction = SETUP; dev->endpoints[0].direction = SETUP;
dev->endpoints[0].type = CONTROL; dev->endpoints[0].type = CONTROL;
dev->endpoints[0].interval = usb_decode_interval(dev->speed, CONTROL, endp->bInterval);
for (j = 1; j <= current->bNumEndpoints; j++) { for (j = 1; j <= current->bNumEndpoints; j++) {
#ifdef USB_DEBUG #ifdef USB_DEBUG
static const char *transfertypes[4] = { static const char *transfertypes[4] = {
@ -374,6 +417,7 @@ set_address (hci_t *controller, int speed, int hubport, int hubaddr)
((endp->bEndpointAddress & 0x80) == ((endp->bEndpointAddress & 0x80) ==
0) ? OUT : IN; 0) ? OUT : IN;
ep->type = endp->bmAttributes; ep->type = endp->bmAttributes;
ep->interval = usb_decode_interval(dev->speed, ep->type, endp->bInterval);
endp = (endpoint_descriptor_t endp = (endpoint_descriptor_t
*) (((char *) endp) + endp->bLength); *) (((char *) endp) + endp->bLength);
} }

View File

@ -91,6 +91,8 @@ typedef struct {
int toggle; int toggle;
int maxpacketsize; int maxpacketsize;
endpoint_type type; endpoint_type type;
int interval; /* expressed as binary logarithm of the number
of microframes (i.e. t = 125us * 2^interval) */
} endpoint_t; } endpoint_t;
enum { FULL_SPEED = 0, LOW_SPEED = 1, HIGH_SPEED = 2, SUPER_SPEED = 3 }; enum { FULL_SPEED = 0, LOW_SPEED = 1, HIGH_SPEED = 2, SUPER_SPEED = 3 };