summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/host_command_master.c6
-rw-r--r--common/usb_pd_protocol.c39
-rw-r--r--include/usb_pd.h3
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 */