summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaveh Jalali <caveh@google.com>2017-08-24 02:15:36 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2018-02-12 19:49:38 +0000
commit8337000ec2a3c23f400268e329ce6b5294f04307 (patch)
treee851c2a5e80dec80e883d59de2eed88878d24221
parente401a035620aba9ee371644383eb83d8ed35c86a (diff)
downloadchrome-ec-8337000ec2a3c23f400268e329ce6b5294f04307.tar.gz
anx3429: force chip reset on PD_RESUME
we need to properly restart the anx3429 after a firmware update. simply initializing the chip doesn't seem to get it to reload its firmware - at least not the portion of the chip that implements the firmware version register. so, we explicitly power down and reset the chip before reinitializing it to force it to run the new firmware. the chip also needs a 10ms "off" time so the reset is properly seen by the chip, so i did a light refactoring of the code paths that reset the anx3429. TEST=used 2 different firmware blobs and verified it switches between them during software sync. BRANCH=none BUG=b:35586895 Change-Id: I11447c4039108a7530028c57cd5ce5ef6a78912a Signed-off-by: Duncan Laurie <dlaurie@google.com> Original-Commit-Id: c1e5671e561c82c9532cb29b17fc7cf4061ab20a Original-Change-Id: I967898dd906f21bdc5bc4ce9c1dff9f873d198c1 Original-Signed-off-by: Caveh Jalali <caveh@google.com> Original-Reviewed-on: https://chromium-review.googlesource.com/631976 Reviewed-on: https://chromium-review.googlesource.com/914659
-rw-r--r--board/eve/board.c25
-rw-r--r--board/poppy/board.c31
-rw-r--r--common/usb_pd_protocol.c13
-rw-r--r--driver/tcpm/anx74xx.c2
-rw-r--r--driver/tcpm/anx74xx.h14
5 files changed, 60 insertions, 25 deletions
diff --git a/board/eve/board.c b/board/eve/board.c
index 5934ba7bec..27d086bbd0 100644
--- a/board/eve/board.c
+++ b/board/eve/board.c
@@ -227,30 +227,38 @@ struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_COUNT] = {
},
};
-/* called from anx74xx_set_power_mode() */
+/**
+ * Power on (or off) a single TCPC.
+ * minimum on/off delays are included.
+ *
+ * @param port Port number of TCPC.
+ * @param mode 0: power off, 1: power on.
+ */
void board_set_tcpc_power_mode(int port, int mode)
{
switch (port) {
case 0:
if (mode) {
gpio_set_level(GPIO_USB_C0_TCPC_PWR, 1);
- msleep(10);
+ msleep(ANX74XX_PWR_H_RST_H_DELAY_MS);
gpio_set_level(GPIO_USB_C0_PD_RST_L, 1);
} else {
gpio_set_level(GPIO_USB_C0_PD_RST_L, 0);
- msleep(1);
+ msleep(ANX74XX_RST_L_PWR_L_DELAY_MS);
gpio_set_level(GPIO_USB_C0_TCPC_PWR, 0);
+ msleep(ANX74XX_PWR_L_PWR_H_DELAY_MS);
}
break;
case 1:
if (mode) {
gpio_set_level(GPIO_USB_C1_TCPC_PWR, 1);
- msleep(10);
+ msleep(ANX74XX_PWR_H_RST_H_DELAY_MS);
gpio_set_level(GPIO_USB_C1_PD_RST_L, 1);
} else {
gpio_set_level(GPIO_USB_C1_PD_RST_L, 0);
- msleep(1);
+ msleep(ANX74XX_RST_L_PWR_L_DELAY_MS);
gpio_set_level(GPIO_USB_C1_TCPC_PWR, 0);
+ msleep(ANX74XX_PWR_L_PWR_H_DELAY_MS);
}
break;
}
@@ -261,15 +269,15 @@ void board_reset_pd_mcu(void)
/* Assert reset */
gpio_set_level(GPIO_USB_C0_PD_RST_L, 0);
gpio_set_level(GPIO_USB_C1_PD_RST_L, 0);
- msleep(1);
+ msleep(ANX74XX_RST_L_PWR_L_DELAY_MS);
/* Disable power */
gpio_set_level(GPIO_USB_C0_TCPC_PWR, 0);
gpio_set_level(GPIO_USB_C1_TCPC_PWR, 0);
- msleep(10);
+ msleep(ANX74XX_PWR_L_PWR_H_DELAY_MS);
/* Enable power */
gpio_set_level(GPIO_USB_C0_TCPC_PWR, 1);
gpio_set_level(GPIO_USB_C1_TCPC_PWR, 1);
- msleep(10);
+ msleep(ANX74XX_PWR_H_RST_H_DELAY_MS);
/* Deassert reset */
gpio_set_level(GPIO_USB_C0_PD_RST_L, 1);
gpio_set_level(GPIO_USB_C1_PD_RST_L, 1);
@@ -1006,4 +1014,3 @@ const struct motion_sensor_t *motion_als_sensors[] = {
&motion_sensors[LID_LIGHT],
};
BUILD_ASSERT(ARRAY_SIZE(motion_als_sensors) == ALS_COUNT);
-
diff --git a/board/poppy/board.c b/board/poppy/board.c
index 717439c620..8dd6a45b11 100644
--- a/board/poppy/board.c
+++ b/board/poppy/board.c
@@ -55,6 +55,8 @@
#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args)
#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args)
+#define USB_PD_PORT_ANX74XX 0
+
static void tcpc_alert_event(enum gpio_signal signal)
{
if ((signal == GPIO_USB_C0_PD_INT_ODL) &&
@@ -342,20 +344,27 @@ struct pi3usb9281_config pi3usb9281_chips[] = {
BUILD_ASSERT(ARRAY_SIZE(pi3usb9281_chips) ==
CONFIG_USB_SWITCH_PI3USB9281_CHIP_COUNT);
-/* called from anx74xx_set_power_mode() */
+/**
+ * Power on (or off) a single TCPC.
+ * minimum on/off delays are included.
+ *
+ * @param port Port number of TCPC.
+ * @param mode 0: power off, 1: power on.
+ */
void board_set_tcpc_power_mode(int port, int mode)
{
- if (port != 0)
+ if (port != USB_PD_PORT_ANX74XX)
return;
if (mode) {
gpio_set_level(GPIO_USB_C0_TCPC_PWR, 1);
- msleep(10);
+ msleep(ANX74XX_PWR_H_RST_H_DELAY_MS);
gpio_set_level(GPIO_USB_C0_PD_RST_L, 1);
} else {
gpio_set_level(GPIO_USB_C0_PD_RST_L, 0);
- msleep(1);
+ msleep(ANX74XX_RST_L_PWR_L_DELAY_MS);
gpio_set_level(GPIO_USB_C0_TCPC_PWR, 0);
+ msleep(ANX74XX_PWR_L_PWR_H_DELAY_MS);
}
}
@@ -364,16 +373,14 @@ void board_reset_pd_mcu(void)
/* Assert reset */
gpio_set_level(GPIO_USB_C0_PD_RST_L, 0);
gpio_set_level(GPIO_USB_C1_PD_RST_L, 0);
- msleep(1);
+
+ msleep(MAX(1, ANX74XX_RST_L_PWR_L_DELAY_MS));
gpio_set_level(GPIO_USB_C1_PD_RST_L, 1);
- /* Disable power */
+ /* Disable TCPC0 (anx3429) power */
gpio_set_level(GPIO_USB_C0_TCPC_PWR, 0);
- msleep(10);
- /* Enable power */
- gpio_set_level(GPIO_USB_C0_TCPC_PWR, 1);
- msleep(10);
- /* Deassert reset */
- gpio_set_level(GPIO_USB_C0_PD_RST_L, 1);
+
+ msleep(ANX74XX_PWR_L_PWR_H_DELAY_MS);
+ board_set_tcpc_power_mode(USB_PD_PORT_ANX74XX, 1);
}
void board_tcpc_init(void)
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index b511aa4dd7..8fab462433 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -1611,6 +1611,15 @@ static void pd_init_tasks(void)
}
#endif /* CONFIG_COMMON_RUNTIME */
+#ifndef CONFIG_USB_PD_TCPC
+static int pd_restart_tcpc(int port)
+{
+ /* force chip reset */
+ board_set_tcpc_power_mode(port, 0);
+ return tcpm_init(port);
+}
+#endif
+
void pd_task(void *u)
{
int head;
@@ -2256,9 +2265,9 @@ void pd_task(void *u)
CPRINTS("TCPC p%d resumed!", port);
#else
if (rstatus != EC_ERROR_UNIMPLEMENTED &&
- tcpm_init(port) != 0) {
+ pd_restart_tcpc(port) != 0) {
/* stay in PD_STATE_SUSPENDED */
- CPRINTS("TCPC p%d init failed!", port);
+ CPRINTS("TCPC p%d restart failed!", port);
break;
}
set_state(port, PD_DEFAULT_STATE(port));
diff --git a/driver/tcpm/anx74xx.c b/driver/tcpm/anx74xx.c
index e2c1081ceb..e0b4957f69 100644
--- a/driver/tcpm/anx74xx.c
+++ b/driver/tcpm/anx74xx.c
@@ -702,7 +702,7 @@ static int anx74xx_tcpm_set_cc(int port, int pull)
#if defined(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) && \
defined(CONFIG_USB_PD_TCPC_LOW_POWER)
-void anx74xx_handle_power_mode(int port, int mode)
+static void anx74xx_handle_power_mode(int port, int mode)
{
if (mode == ANX74XX_STANDBY_MODE) {
anx74xx_set_power_mode(port, mode);
diff --git a/driver/tcpm/anx74xx.h b/driver/tcpm/anx74xx.h
index 06720650bd..11ae964af7 100644
--- a/driver/tcpm/anx74xx.h
+++ b/driver/tcpm/anx74xx.h
@@ -186,13 +186,25 @@
#define ANX74XX_CC_RD_MASK (BIT_VALUE_OF_SRC_CC_RD | \
(BIT_VALUE_OF_SRC_CC_RD << 4))
+/*
+ * RESETN low to PWR_EN low delay
+ */
+#define ANX74XX_RST_L_PWR_L_DELAY_MS 1
+/*
+ * minimum power off-to-on delay to reset chip
+ */
+#define ANX74XX_PWR_L_PWR_H_DELAY_MS 10
+/*
+ * parameter T4: PWR_EN high to RESETN high delay
+ */
+#define ANX74XX_PWR_H_RST_H_DELAY_MS 10
+
extern const struct tcpm_drv anx74xx_tcpm_drv;
extern const struct usb_mux_driver anx74xx_tcpm_usb_mux_driver;
void anx74xx_tcpc_set_vbus(int port, int enable);
void anx74xx_tcpc_update_hpd_status(int port, int hpd_lvl, int hpd_irq);
void anx74xx_tcpc_clear_hpd_status(int port);
int anx74xx_tcpc_get_fw_version(int port, int *version);
-void anx74xx_handle_power_mode(int port, int mode);
#ifdef CONFIG_CMD_I2C_STRESS_TEST_TCPC
extern struct i2c_stress_test_dev anx74xx_i2c_stress_test_dev;