libpayload: add support for 64-bit EHCI controllers
Initialize the high part of the address and use 64-bit compatible descriptors. (waste a few bytes on 32-bit but should be harmless) Read USB stick on a SandyBridge system which has 64-bit EHCI. Change-Id: I59cc842459acecdde8f8bdd4795ebfeccb842c8f Signed-off-by: Vincent Palatin <vpalatin@chromium.org> Signed-off-by: Gabe Black <gabeblack@google.com> Reviewed-on: http://review.coreboot.org/2650 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi <patrick@georgi-clan.de> Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net> Reviewed-by: Kimarie Hoot <kimarie.hoot@se-eng.com> Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
This commit is contained in:
parent
613c0f630a
commit
716375dd3e
|
@ -359,7 +359,7 @@ static int ehci_bulk (endpoint_t *ep, int size, u8 *data, int finalize)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
qtd_t *head = memalign(32, sizeof(qtd_t));
|
qtd_t *head = memalign(64, sizeof(qtd_t));
|
||||||
qtd_t *cur = head;
|
qtd_t *cur = head;
|
||||||
while (1) {
|
while (1) {
|
||||||
memset((void *)cur, 0, sizeof(qtd_t));
|
memset((void *)cur, 0, sizeof(qtd_t));
|
||||||
|
@ -375,14 +375,14 @@ static int ehci_bulk (endpoint_t *ep, int size, u8 *data, int finalize)
|
||||||
cur->next_qtd = virt_to_phys(0) | QTD_TERMINATE;
|
cur->next_qtd = virt_to_phys(0) | QTD_TERMINATE;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
qtd_t *next = memalign(32, sizeof(qtd_t));
|
qtd_t *next = memalign(64, sizeof(qtd_t));
|
||||||
cur->next_qtd = virt_to_phys(next);
|
cur->next_qtd = virt_to_phys(next);
|
||||||
cur = next;
|
cur = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create QH */
|
/* create QH */
|
||||||
ehci_qh_t *qh = memalign(32, sizeof(ehci_qh_t));
|
ehci_qh_t *qh = memalign(64, sizeof(ehci_qh_t));
|
||||||
memset((void *)qh, 0, sizeof(ehci_qh_t));
|
memset((void *)qh, 0, sizeof(ehci_qh_t));
|
||||||
qh->horiz_link_ptr = virt_to_phys(qh) | QH_QH;
|
qh->horiz_link_ptr = virt_to_phys(qh) | QH_QH;
|
||||||
qh->epchar = ep->dev->address |
|
qh->epchar = ep->dev->address |
|
||||||
|
@ -428,7 +428,7 @@ static int ehci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create qTDs */
|
/* create qTDs */
|
||||||
qtd_t *head = memalign(32, sizeof(qtd_t));
|
qtd_t *head = memalign(64, sizeof(qtd_t));
|
||||||
qtd_t *cur = head;
|
qtd_t *cur = head;
|
||||||
memset((void *)cur, 0, sizeof(qtd_t));
|
memset((void *)cur, 0, sizeof(qtd_t));
|
||||||
cur->token = QTD_ACTIVE |
|
cur->token = QTD_ACTIVE |
|
||||||
|
@ -438,7 +438,7 @@ static int ehci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq
|
||||||
if (fill_td(cur, devreq, drlen) != drlen) {
|
if (fill_td(cur, devreq, drlen) != drlen) {
|
||||||
usb_debug("ERROR: couldn't send the entire device request\n");
|
usb_debug("ERROR: couldn't send the entire device request\n");
|
||||||
}
|
}
|
||||||
qtd_t *next = memalign(32, sizeof(qtd_t));
|
qtd_t *next = memalign(64, sizeof(qtd_t));
|
||||||
cur->next_qtd = virt_to_phys(next);
|
cur->next_qtd = virt_to_phys(next);
|
||||||
cur->alt_next_qtd = QTD_TERMINATE;
|
cur->alt_next_qtd = QTD_TERMINATE;
|
||||||
|
|
||||||
|
@ -455,7 +455,7 @@ static int ehci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq
|
||||||
if (fill_td(cur, data, dalen) != dalen) {
|
if (fill_td(cur, data, dalen) != dalen) {
|
||||||
usb_debug("ERROR: couldn't send the entire control payload\n");
|
usb_debug("ERROR: couldn't send the entire control payload\n");
|
||||||
}
|
}
|
||||||
next = memalign(32, sizeof(qtd_t));
|
next = memalign(64, sizeof(qtd_t));
|
||||||
cur->next_qtd = virt_to_phys(next);
|
cur->next_qtd = virt_to_phys(next);
|
||||||
cur->alt_next_qtd = QTD_TERMINATE;
|
cur->alt_next_qtd = QTD_TERMINATE;
|
||||||
}
|
}
|
||||||
|
@ -472,7 +472,7 @@ static int ehci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq
|
||||||
cur->alt_next_qtd = QTD_TERMINATE;
|
cur->alt_next_qtd = QTD_TERMINATE;
|
||||||
|
|
||||||
/* create QH */
|
/* create QH */
|
||||||
ehci_qh_t *qh = memalign(32, sizeof(ehci_qh_t));
|
ehci_qh_t *qh = memalign(64, sizeof(ehci_qh_t));
|
||||||
memset((void *)qh, 0, sizeof(ehci_qh_t));
|
memset((void *)qh, 0, sizeof(ehci_qh_t));
|
||||||
qh->horiz_link_ptr = virt_to_phys(qh) | QH_QH;
|
qh->horiz_link_ptr = virt_to_phys(qh) | QH_QH;
|
||||||
qh->epchar = dev->address |
|
qh->epchar = dev->address |
|
||||||
|
@ -564,7 +564,7 @@ static void *ehci_create_intr_queue(
|
||||||
}
|
}
|
||||||
|
|
||||||
intr_queue_t *const intrq =
|
intr_queue_t *const intrq =
|
||||||
(intr_queue_t *)memalign(32, sizeof(intr_queue_t));
|
(intr_queue_t *)memalign(64, sizeof(intr_queue_t));
|
||||||
/*
|
/*
|
||||||
* reqcount data chunks
|
* reqcount data chunks
|
||||||
* plus one more spare, which we'll leave out of queue
|
* plus one more spare, which we'll leave out of queue
|
||||||
|
@ -577,7 +577,7 @@ static void *ehci_create_intr_queue(
|
||||||
intrq->reqsize = reqsize;
|
intrq->reqsize = reqsize;
|
||||||
|
|
||||||
/* create #reqcount transfer descriptors (qTDs) */
|
/* create #reqcount transfer descriptors (qTDs) */
|
||||||
intrq->head = (intr_qtd_t *)memalign(32, sizeof(intr_qtd_t));
|
intrq->head = (intr_qtd_t *)memalign(64, sizeof(intr_qtd_t));
|
||||||
intr_qtd_t *cur_td = intrq->head;
|
intr_qtd_t *cur_td = intrq->head;
|
||||||
for (i = 0; i < reqcount; ++i) {
|
for (i = 0; i < reqcount; ++i) {
|
||||||
fill_intr_queue_td(intrq, cur_td, data);
|
fill_intr_queue_td(intrq, cur_td, data);
|
||||||
|
@ -585,7 +585,7 @@ static void *ehci_create_intr_queue(
|
||||||
if (i < reqcount - 1) {
|
if (i < reqcount - 1) {
|
||||||
/* create one more qTD */
|
/* create one more qTD */
|
||||||
intr_qtd_t *const next_td =
|
intr_qtd_t *const next_td =
|
||||||
(intr_qtd_t *)memalign(32, sizeof(intr_qtd_t));
|
(intr_qtd_t *)memalign(64, sizeof(intr_qtd_t));
|
||||||
cur_td->td.next_qtd = virt_to_phys(&next_td->td);
|
cur_td->td.next_qtd = virt_to_phys(&next_td->td);
|
||||||
cur_td->next = next_td;
|
cur_td->next = next_td;
|
||||||
cur_td = next_td;
|
cur_td = next_td;
|
||||||
|
@ -594,7 +594,7 @@ static void *ehci_create_intr_queue(
|
||||||
intrq->tail = cur_td;
|
intrq->tail = cur_td;
|
||||||
|
|
||||||
/* create spare qTD */
|
/* create spare qTD */
|
||||||
intrq->spare = (intr_qtd_t *)memalign(32, sizeof(intr_qtd_t));
|
intrq->spare = (intr_qtd_t *)memalign(64, sizeof(intr_qtd_t));
|
||||||
fill_intr_queue_td(intrq, intrq->spare, data);
|
fill_intr_queue_td(intrq, intrq->spare, data);
|
||||||
|
|
||||||
/* initialize QH */
|
/* initialize QH */
|
||||||
|
@ -761,6 +761,10 @@ ehci_init (pcidev_t addr)
|
||||||
/* default value for frame length adjust */
|
/* default value for frame length adjust */
|
||||||
pci_write_config8(addr, FLADJ, FLADJ_framelength(60000));
|
pci_write_config8(addr, FLADJ, FLADJ_framelength(60000));
|
||||||
|
|
||||||
|
/* Set the high address word (aka segment) if controller is 64-bit */
|
||||||
|
if (EHCI_INST(controller)->capabilities->hccparams & 1)
|
||||||
|
EHCI_INST(controller)->operation->ctrldssegment = 0;
|
||||||
|
|
||||||
/* Enable operation of controller */
|
/* Enable operation of controller */
|
||||||
controller->start(controller);
|
controller->start(controller);
|
||||||
|
|
||||||
|
@ -778,7 +782,7 @@ ehci_init (pcidev_t addr)
|
||||||
* This helps with broken host controllers
|
* This helps with broken host controllers
|
||||||
* and doesn't violate the standard.
|
* and doesn't violate the standard.
|
||||||
*/
|
*/
|
||||||
EHCI_INST(controller)->dummy_qh = (ehci_qh_t *)memalign(32, sizeof(ehci_qh_t));
|
EHCI_INST(controller)->dummy_qh = (ehci_qh_t *)memalign(64, sizeof(ehci_qh_t));
|
||||||
memset((void *)EHCI_INST(controller)->dummy_qh, 0,
|
memset((void *)EHCI_INST(controller)->dummy_qh, 0,
|
||||||
sizeof(*EHCI_INST(controller)->dummy_qh));
|
sizeof(*EHCI_INST(controller)->dummy_qh));
|
||||||
EHCI_INST(controller)->dummy_qh->horiz_link_ptr = QH_TERMINATE;
|
EHCI_INST(controller)->dummy_qh->horiz_link_ptr = QH_TERMINATE;
|
||||||
|
|
Loading…
Reference in New Issue