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:
parent
482af6d15c
commit
aee44fa37d
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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 };
|
||||||
|
Loading…
x
Reference in New Issue
Block a user