usbdebug: Fix control messages

Add support for control messages with a write of data stage.

Add status stage after a read of non-zero length data stage.

Do not retry control message if device responds with STALL.

Change-Id: I16fb9ae39630b975af5461b63d050b9adaccef0f
Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-on: http://review.coreboot.org/3867
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@google.com>
This commit is contained in:
Kyösti Mälkki 2013-08-10 10:08:38 +03:00
parent e29584c141
commit dcccbd1396
1 changed files with 31 additions and 6 deletions

View File

@ -192,6 +192,11 @@ retry:
ret = -DBGP_ERR_BAD; ret = -DBGP_ERR_BAD;
} }
/* Abort on STALL handshake for endpoint 0.*/
else if ((lpid == USB_PID_STALL) && (pipe->endpoint == 0x0)) {
ret = -DBGP_ERR_BAD;
}
return ret; return ret;
} }
@ -307,10 +312,10 @@ static int dbgp_control_msg(struct ehci_dbg_port *ehci_debug, unsigned devnum, i
u32 pids, addr, ctrl; u32 pids, addr, ctrl;
struct usb_ctrlrequest req; struct usb_ctrlrequest req;
int read; int read;
int ret; int ret, ret2;
read = (requesttype & USB_DIR_IN) != 0; read = (requesttype & USB_DIR_IN) != 0;
if (size > (read ? DBGP_MAX_PACKET:0)) if (size > DBGP_MAX_PACKET)
return -1; return -1;
/* Compute the control message */ /* Compute the control message */
@ -329,9 +334,8 @@ static int dbgp_control_msg(struct ehci_dbg_port *ehci_debug, unsigned devnum, i
ctrl = read32((unsigned long)&ehci_debug->control); ctrl = read32((unsigned long)&ehci_debug->control);
ctrl = DBGP_LEN_UPDATE(ctrl, sizeof(req)); ctrl = DBGP_LEN_UPDATE(ctrl, sizeof(req));
ctrl |= DBGP_OUT; ctrl |= DBGP_OUT;
ctrl |= DBGP_GO;
/* Send the setup message */ /* Setup stage */
dbgp_set_data(ehci_debug, &req, sizeof(req)); dbgp_set_data(ehci_debug, &req, sizeof(req));
write32((unsigned long)&ehci_debug->address, addr); write32((unsigned long)&ehci_debug->address, addr);
write32((unsigned long)&ehci_debug->pids, pids); write32((unsigned long)&ehci_debug->pids, pids);
@ -339,8 +343,29 @@ static int dbgp_control_msg(struct ehci_dbg_port *ehci_debug, unsigned devnum, i
if (ret < 0) if (ret < 0)
return ret; return ret;
/* Read the result */ /* Data stage (optional) */
ret = dbgp_bulk_read(ehci_debug, pipe, data, size, DBGP_LOOPS); if (read && size)
ret = dbgp_bulk_read(ehci_debug, pipe, data, size, DBGP_LOOPS);
else if (!read && size)
ret = dbgp_bulk_write(ehci_debug, pipe, data, size);
/* Status stage in opposite direction */
pipe->pid = USB_PID_DATA1;
ctrl = read32((unsigned long)&ehci_debug->control);
ctrl = DBGP_LEN_UPDATE(ctrl, 0);
if (read) {
pids = DBGP_PID_SET(pipe->pid, USB_PID_OUT);
ctrl |= DBGP_OUT;
} else {
pids = DBGP_PID_SET(pipe->pid, USB_PID_IN);
ctrl &= ~DBGP_OUT;
}
write32((unsigned long)&ehci_debug->pids, pids);
ret2 = dbgp_wait_until_done(ehci_debug, pipe, ctrl, DBGP_LOOPS);
if (ret2 < 0)
return ret2;
return ret; return ret;
} }