Cr50: Fix USB two-stage control transfers

This cleans up a great deal of flakiness that we've seen on the
USB for a long time. I was misinterpreting and/or misimplementing
some of the documentation. This seems to make all the difference.

BUG=chrome-os-partner:50370
BRANCH=none
CQ-DEPEND=CL:328979,CL:*249229
TEST=make buildall, and test on Cr50

Before this CL, the USB connection would only work on USB2.0
buses, connected directly to my workstation. With this CL, it
works on USB2.0, USB3.0, through hubs, etc. Yay!

Change-Id: Icfa1910bf34f73332e2f8fc4f0d6789541549493
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/329262
Reviewed-by: Patrick Georgi <pgeorgi@chromium.org>
This commit is contained in:
Bill Richardson
2016-02-24 15:45:59 -08:00
committed by chrome-bot
parent 4f15d2189f
commit a58c24ee37

View File

@@ -893,11 +893,9 @@ static void ep0_interrupt(uint32_t intr_on_out, uint32_t intr_on_in)
case NO_DATA_STAGE:
if (intr_on_in && (diepint & DIEPINT_XFERCOMPL)) {
print_later("Status phase complete", 0, 0, 0, 0, 0);
print_later("IN descriptor processed", 0, 0, 0, 0, 0);
/* Let the IN proceed */
GR_USB_DIEPCTL(0) = DXEPCTL_EPENA;
/* We've already prepared the OUT descriptor. */
what_am_i_doing = WAITING_FOR_SETUP_PACKET;
}
/* Done unless we got an OUT interrupt */
@@ -906,6 +904,8 @@ static void ep0_interrupt(uint32_t intr_on_out, uint32_t intr_on_in)
if (tc == TABLE_CASE_B) {
print_later("IN has been detected...", 0, 0, 0, 0, 0);
/* Let the IN proceed */
GR_USB_DIEPCTL(0) = DXEPCTL_CNAK | DXEPCTL_EPENA;
/* Reenable the previously prepared OUT descriptor. */
GR_USB_DOEPCTL(0) = DXEPCTL_CNAK | DXEPCTL_EPENA;
break;
@@ -920,8 +920,9 @@ static void ep0_interrupt(uint32_t intr_on_out, uint32_t intr_on_in)
}
}
/* Some other kind of OUT interrupt instead. */
report_error(tc);
/* Anything else means get ready for a Setup packet */
print_later("Status phase complete. Maybe.",
0, 0, 0, 0, 0);
expect_setup_packet();
break;
}