diff options
-rw-r--r-- | common/host_command_master.c | 6 | ||||
-rw-r--r-- | common/usb_pd_protocol.c | 39 | ||||
-rw-r--r-- | include/usb_pd.h | 3 |
3 files changed, 31 insertions, 17 deletions
diff --git a/common/host_command_master.c b/common/host_command_master.c index 11d0dbca06..39bbf37df5 100644 --- a/common/host_command_master.c +++ b/common/host_command_master.c @@ -11,15 +11,13 @@ #include "i2c.h" #include "task.h" #include "timer.h" +#include "usb_pd.h" #include "util.h" /* Console output macros */ #define CPUTS(outstr) cputs(CC_HOSTCMD, outstr) #define CPRINTF(format, args...) cprintf(CC_HOSTCMD, format, ## args) -/* Host command timeout */ -#define HOST_COMMAND_TIMEOUT_US SECOND - /* Number of attempts for each PD host command */ #define PD_HOST_COMMAND_ATTEMPTS 3 @@ -81,7 +79,7 @@ static int pd_host_command_internal(int command, int version, * length. */ i2c_lock(I2C_PORT_PD_MCU, 1); - i2c_set_timeout(I2C_PORT_PD_MCU, HOST_COMMAND_TIMEOUT_US); + i2c_set_timeout(I2C_PORT_PD_MCU, PD_HOST_COMMAND_TIMEOUT_US); ret = i2c_xfer(I2C_PORT_PD_MCU, CONFIG_USB_PD_I2C_SLAVE_ADDR, &req_buf[0], outsize + sizeof(rq) + 1, &resp_buf[0], 2, I2C_XFER_START); diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index 98b14a2736..9d9c9d2178 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -3053,6 +3053,7 @@ static int hc_remote_flash(struct host_cmd_handler_args *args) int port = p->port; const uint32_t *data = &(p->size) + 1; int i, size; + timestamp_t timeout; if (p->size + sizeof(*p) > args->params_size) return EC_RES_INVALID_PARAM; @@ -3073,23 +3074,24 @@ static int hc_remote_flash(struct host_cmd_handler_args *args) pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_REBOOT, NULL, 0); /* Delay to give time for device to reboot */ - usleep(900 * MSEC); + usleep(PD_HOST_COMMAND_TIMEOUT_US - 100*MSEC); return EC_RES_SUCCESS; case USB_PD_FW_FLASH_ERASE: pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_FLASH_ERASE, NULL, 0); - - /* Wait until VDM is done */ - while (pd[port].vdm_state > 0) - task_wait_event(100*MSEC); + /* + * TODO: Note, page erase for 2K is 20-40msec while host command + * timeout is 1sec so this can't be longer. In practice, + * for 32 pages, its passed. Better way to implement may be to + * push burden to HOST to manage latency. + */ + timeout.val = get_time().val + + PD_HOST_COMMAND_TIMEOUT_US - 100*MSEC; break; case USB_PD_FW_ERASE_SIG: pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_ERASE_SIG, NULL, 0); - - /* Wait until VDM is done */ - while (pd[port].vdm_state > 0) - task_wait_event(100*MSEC); + timeout.val = get_time().val + 500*MSEC; break; case USB_PD_FW_FLASH_WRITE: @@ -3101,22 +3103,33 @@ static int hc_remote_flash(struct host_cmd_handler_args *args) for (i = 0; i < size; i += VDO_MAX_SIZE - 1) { pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_FLASH_WRITE, data + i, MIN(size - i, VDO_MAX_SIZE - 1)); + timeout.val = get_time().val + 500*MSEC; /* Wait until VDM is done */ - while (pd[port].vdm_state > 0) + while ((pd[port].vdm_state > 0) && + (get_time().val < timeout.val)) task_wait_event(10*MSEC); + + if (pd[port].vdm_state > 0) + return EC_RES_TIMEOUT; } - break; + return EC_RES_SUCCESS; default: return EC_RES_INVALID_PARAM; break; } + /* Wait until VDM is done or timeout */ + while ((pd[port].vdm_state > 0) && (get_time().val < timeout.val)) + task_wait_event(50*MSEC); + if (pd[port].vdm_state < 0) return EC_RES_ERROR; - else - return EC_RES_SUCCESS; + if (pd[port].vdm_state > 0) + return EC_RES_TIMEOUT; + + return EC_RES_SUCCESS; } DECLARE_HOST_COMMAND(EC_CMD_USB_PD_FW_UPDATE, hc_remote_flash, diff --git a/include/usb_pd.h b/include/usb_pd.h index b1d72d1402..0f080c24e0 100644 --- a/include/usb_pd.h +++ b/include/usb_pd.h @@ -10,6 +10,9 @@ #include "common.h" +/* PD Host command timeout */ +#define PD_HOST_COMMAND_TIMEOUT_US SECOND + enum pd_errors { PD_ERR_INVAL = -1, /* Invalid packet */ PD_ERR_HARD_RESET = -2, /* Got a Hard-Reset packet */ |