summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaveh Jalali <caveh@google.com>2017-08-24 02:15:36 -0700
committerchrome-bot <chrome-bot@chromium.org>2017-08-29 22:08:20 -0700
commitc1e5671e561c82c9532cb29b17fc7cf4061ab20a (patch)
tree22348963ba0441bf7c4f93e1c88d481438c78b3e
parentc191bf9f4d5b4c2e45583820307d95592d2221ba (diff)
downloadchrome-ec-c1e5671e561c82c9532cb29b17fc7cf4061ab20a.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: I967898dd906f21bdc5bc4ce9c1dff9f873d198c1 Signed-off-by: Caveh Jalali <caveh@google.com> Reviewed-on: https://chromium-review.googlesource.com/631976
-rw-r--r--board/coral/board.c39
-rw-r--r--board/eve/board.c25
-rw-r--r--board/poppy/board.c31
-rw-r--r--board/reef/board.c40
-rw-r--r--common/usb_pd_protocol.c15
-rw-r--r--driver/tcpm/anx74xx.c2
-rw-r--r--driver/tcpm/anx74xx.h14
7 files changed, 108 insertions, 58 deletions
diff --git a/board/coral/board.c b/board/coral/board.c
index 9ec589aea3..6c1768ce6e 100644
--- a/board/coral/board.c
+++ b/board/coral/board.c
@@ -310,7 +310,13 @@ const int usb_port_enable[CONFIG_USB_PORT_POWER_SMART_PORT_COUNT] = {
GPIO_USB1_ENABLE,
};
-/* 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 != USB_PD_PORT_ANX74XX)
@@ -319,13 +325,14 @@ void board_set_tcpc_power_mode(int port, int mode)
switch (mode) {
case ANX74XX_NORMAL_MODE:
gpio_set_level(GPIO_EN_USB_TCPC_PWR, 1);
- msleep(10);
+ msleep(ANX74XX_PWR_H_RST_H_DELAY_MS);
gpio_set_level(GPIO_USB_C0_PD_RST_L, 1);
break;
case ANX74XX_STANDBY_MODE:
gpio_set_level(GPIO_USB_C0_PD_RST_L, 0);
- msleep(1);
+ msleep(ANX74XX_RST_L_PWR_L_DELAY_MS);
gpio_set_level(GPIO_EN_USB_TCPC_PWR, 0);
+ msleep(ANX74XX_PWR_L_PWR_H_DELAY_MS);
break;
default:
break;
@@ -333,32 +340,32 @@ void board_set_tcpc_power_mode(int port, int mode)
}
/**
- * Reset PD MCU -- currently only called from handle_pending_reboot() in
- * common/power.c just before hard resetting the system. This logic is likely
- * not needed as the PP3300_A rail should be dropped on EC reset.
+ * Reset all system PD/TCPC MCUs -- currently only called from
+ * handle_pending_reboot() in common/power.c just before hard
+ * resetting the system. This logic is likely not needed as the
+ * PP3300_A rail should be dropped on EC reset.
*/
void board_reset_pd_mcu(void)
{
- /* Assert reset to TCPC1 */
+ /* Assert reset to TCPC1 (ps8751) */
gpio_set_level(GPIO_USB_C1_PD_RST_ODL, 0);
- /* Assert reset to TCPC0 */
- board_set_tcpc_power_mode(0, 0);
+ /* Assert reset to TCPC0 (anx3429) */
+ gpio_set_level(GPIO_USB_C0_PD_RST_L, 0);
/* TCPC1 (ps8751) requires 1ms reset down assertion */
- msleep(1);
+ msleep(MAX(1, ANX74XX_RST_L_PWR_L_DELAY_MS));
/* Deassert reset to TCPC1 */
gpio_set_level(GPIO_USB_C1_PD_RST_ODL, 1);
+ /* Disable TCPC0 power */
+ gpio_set_level(GPIO_EN_USB_TCPC_PWR, 0);
/*
- * TCPC0 requires 10ms reset/power down assertion
- * minus the 1ms for the TCPC1.
+ * anx3429 requires 10ms reset/power down assertion
*/
- msleep(9);
-
- /* Deassert reset to TCPC0 */
- board_set_tcpc_power_mode(0, 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/board/eve/board.c b/board/eve/board.c
index dd0b744573..38926113bd 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);
@@ -990,4 +998,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 7ad690bae5..2e3c3e33b7 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) &&
@@ -408,20 +410,27 @@ struct pi3usb9281_config pi3usb9281_chips[] = {
BUILD_ASSERT(ARRAY_SIZE(pi3usb9281_chips) ==
CONFIG_BC12_DETECT_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);
}
}
@@ -430,16 +439,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/board/reef/board.c b/board/reef/board.c
index 0e6b01fca2..8abb856141 100644
--- a/board/reef/board.c
+++ b/board/reef/board.c
@@ -306,7 +306,13 @@ const int usb_port_enable[CONFIG_USB_PORT_POWER_SMART_PORT_COUNT] = {
GPIO_USB1_ENABLE,
};
-/* 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 != USB_PD_PORT_ANX74XX)
@@ -315,13 +321,14 @@ void board_set_tcpc_power_mode(int port, int mode)
switch (mode) {
case ANX74XX_NORMAL_MODE:
gpio_set_level(GPIO_EN_USB_TCPC_PWR, 1);
- msleep(10);
+ msleep(ANX74XX_PWR_H_RST_H_DELAY_MS);
gpio_set_level(GPIO_USB_C0_PD_RST_L, 1);
break;
case ANX74XX_STANDBY_MODE:
gpio_set_level(GPIO_USB_C0_PD_RST_L, 0);
- msleep(1);
+ msleep(ANX74XX_RST_L_PWR_L_DELAY_MS);
gpio_set_level(GPIO_EN_USB_TCPC_PWR, 0);
+ msleep(ANX74XX_PWR_L_PWR_H_DELAY_MS);
break;
default:
break;
@@ -329,32 +336,31 @@ void board_set_tcpc_power_mode(int port, int mode)
}
/**
- * Reset PD MCU -- currently only called from handle_pending_reboot() in
- * common/power.c just before hard resetting the system. This logic is likely
- * not needed as the PP3300_A rail should be dropped on EC reset.
+ * Reset all system PD/TCPC MCUs -- currently only called from
+ * handle_pending_reboot() in common/power.c just before hard
+ * resetting the system. This logic is likely not needed as the
+ * PP3300_A rail should be dropped on EC reset.
*/
void board_reset_pd_mcu(void)
{
- /* Assert reset to TCPC1 */
+ /* Assert reset to TCPC1 (ps8751) */
gpio_set_level(GPIO_USB_C1_PD_RST_ODL, 0);
- /* Assert reset to TCPC0 */
- board_set_tcpc_power_mode(0, 0);
-
+ /* Assert reset to TCPC0 (anx3429) */
+ gpio_set_level(GPIO_USB_C0_PD_RST_L, 0);
/* TCPC1 (ps8751) requires 1ms reset down assertion */
- msleep(1);
+ msleep(MAX(1, ANX74XX_RST_L_PWR_L_DELAY_MS));
/* Deassert reset to TCPC1 */
gpio_set_level(GPIO_USB_C1_PD_RST_ODL, 1);
+ /* Disable TCPC0 power */
+ gpio_set_level(GPIO_EN_USB_TCPC_PWR, 0);
/*
- * TCPC0 requires 10ms reset/power down assertion
- * minus the 1ms for the TCPC1.
+ * anx3429 requires 10ms reset/power down assertion
*/
- msleep(9);
-
- /* Deassert reset to TCPC0 */
- board_set_tcpc_power_mode(0, 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 4c882eae0c..021839d68c 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -1640,6 +1640,17 @@ static void pd_init_tasks(void)
}
#endif /* CONFIG_COMMON_RUNTIME */
+#ifndef CONFIG_USB_PD_TCPC
+static int pd_restart_tcpc(int port)
+{
+ if (board_set_tcpc_power_mode) {
+ /* force chip reset */
+ board_set_tcpc_power_mode(port, 0);
+ }
+ return tcpm_init(port);
+}
+#endif
+
void pd_task(void *u)
{
int head;
@@ -2332,9 +2343,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;