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:
		
				
					committed by
					
						
						Stefan Reinauer
					
				
			
			
				
	
			
			
			
						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 };
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user