libpayload: Enforce strict packet handling order in ChipIdea driver
First handle IN packets, then OUT packets and finally SETUP packets. This makes OS X happy. It isn't implemented as the data sheet recommends but it avoids implementing a state machine and should always produce observable effects identical to that of the stateful solution. BRANCH=none BUG=none TEST=`fastboot getvar version` on OSX works Change-Id: Ic7b27387771d6a7794fba12fc822fccc48770ea8 Signed-off-by: Patrick Georgi <pgeorgi@chromium.org> Original-Commit-Id: f0e59547519d50b1d34f6abdc6132330125f94f3 Original-Change-Id: Iada1cff011f11e7d5cb1a1b34896ab590f488ec7 Original-Signed-off-by: Patrick Georgi <pgeorgi@chromium.org> Original-Reviewed-on: https://chromium-review.googlesource.com/258062 Original-Reviewed-by: Furquan Shaikh <furquan@chromium.org> Reviewed-on: http://review.coreboot.org/9788 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
parent
49a80ce475
commit
e17d57ecab
|
@ -359,8 +359,47 @@ static int chipidea_poll(struct usbdev_ctrl *this)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sts & (USBSTS_UEI | USBSTS_UI)) {
|
if (sts & (USBSTS_UEI | USBSTS_UI)) {
|
||||||
uint32_t bitmap = readl(&p->opreg->epsetupstat);
|
uint32_t bitmap;
|
||||||
int ep = 0;
|
int ep;
|
||||||
|
|
||||||
|
/* This slightly deviates from the recommendation in the
|
||||||
|
* data sheets, but the strict ordering is to simplify
|
||||||
|
* handling control transfers, which are initialized in
|
||||||
|
* the third step with a SETUP packet, then proceed in
|
||||||
|
* the next poll loop with in transfers (either data or
|
||||||
|
* status phase), then optionally out transfers (status
|
||||||
|
* phase).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* in transfers */
|
||||||
|
bitmap = (readl(&p->opreg->epcomplete) >> 16) & 0xffff;
|
||||||
|
ep = 0;
|
||||||
|
while (bitmap) {
|
||||||
|
if (bitmap & 1) {
|
||||||
|
debug("incoming packet on EP %d (in)\n", ep);
|
||||||
|
handle_endpoint(this, ep, 1);
|
||||||
|
clear_ep(p, ep & 0xf, 1);
|
||||||
|
}
|
||||||
|
bitmap >>= 1;
|
||||||
|
ep++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* out transfers */
|
||||||
|
bitmap = readl(&p->opreg->epcomplete) & 0xffff;
|
||||||
|
ep = 0;
|
||||||
|
while (bitmap) {
|
||||||
|
if (bitmap & 1) {
|
||||||
|
debug("incoming packet on EP %d (out)\n", ep);
|
||||||
|
handle_endpoint(this, ep, 0);
|
||||||
|
clear_ep(p, ep, 0);
|
||||||
|
}
|
||||||
|
bitmap >>= 1;
|
||||||
|
ep++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* setup transfers */
|
||||||
|
bitmap = readl(&p->opreg->epsetupstat);
|
||||||
|
ep = 0;
|
||||||
while (bitmap) {
|
while (bitmap) {
|
||||||
if (bitmap & 1) {
|
if (bitmap & 1) {
|
||||||
debug("incoming packet on EP %d (setup)\n", ep);
|
debug("incoming packet on EP %d (setup)\n", ep);
|
||||||
|
@ -369,21 +408,6 @@ static int chipidea_poll(struct usbdev_ctrl *this)
|
||||||
bitmap >>= 1;
|
bitmap >>= 1;
|
||||||
ep++;
|
ep++;
|
||||||
}
|
}
|
||||||
bitmap = readl(&p->opreg->epcomplete);
|
|
||||||
ep = 0;
|
|
||||||
int dir_in = 0;
|
|
||||||
while (bitmap) {
|
|
||||||
if (bitmap & 1) {
|
|
||||||
debug("incoming packet on EP %d (%s)\n",
|
|
||||||
ep, dir_in ? "intr/in" : "out");
|
|
||||||
handle_endpoint(this, ep & 0xf, dir_in);
|
|
||||||
clear_ep(p, ep & 0xf, dir_in);
|
|
||||||
}
|
|
||||||
bitmap >>= 1;
|
|
||||||
ep++;
|
|
||||||
if (ep == 16)
|
|
||||||
dir_in = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
Loading…
Reference in New Issue