summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlec Berg <alecaberg@chromium.org>2014-12-03 03:06:54 -0800
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-12-08 21:51:38 +0000
commit8bb26a29b04c39a81c4094de9d7fba5f85123f54 (patch)
treef8486a9a75adf169d8f8cf11f687c46a77590b7c
parent3c780a915c6294fe5b3e9bde227585c562a65c85 (diff)
downloadchrome-ec-8bb26a29b04c39a81c4094de9d7fba5f85123f54.tar.gz
pd: before sysjump send soft reset and then disable PD comms
Before sysjump we need to send a soft reset to any attached devices and then disable PD communication so that we don't re-negotiate again before the sysjump. This will guarantee expected message ID is cleared for after the sysjump. This also moves executing soft reset from before sending the soft reset command to after the port partner accepts a soft reset. BUG=none BRANCH=samus TEST=test on samus. without this change, when sysjumping the PD MCU has time to re-negotiate (at least partially) before the sysjump, which causes various problems. with this change, when sysjumping, the PD MCU sends soft reset, and then does not send anything else. Change-Id: Id7a60c62c8908ee4ab33dfbe995ef136b0aa83de Signed-off-by: Alec Berg <alecaberg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/233751
-rw-r--r--common/system.c9
-rw-r--r--common/usb_pd_protocol.c36
-rw-r--r--include/usb_pd.h2
3 files changed, 31 insertions, 16 deletions
diff --git a/common/system.c b/common/system.c
index 5db3681c26..268e393b1b 100644
--- a/common/system.c
+++ b/common/system.c
@@ -402,13 +402,10 @@ static void jump_to_image(uintptr_t init_addr)
#ifdef CONFIG_USB_POWER_DELIVERY
/*
- * On sysjump, we are most definitely going to drop pings (if any)
- * and lose all of our PD state. Instead of trying to remember all
- * the states and deal with on-going transmission, let's send soft
- * reset here so that the communication starts over without dropping
- * power.
+ * Notify USB PD module that we are about to sysjump and give it time
+ * to do what it needs.
*/
- pd_soft_reset();
+ pd_prepare_sysjump();
usleep(5*MSEC);
#endif
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index 131a441913..b9ed705d65 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -240,6 +240,7 @@ static int pd_src_cap_cnt[PD_PORT_COUNT];
#define PD_FLAGS_GET_SNK_CAP_SENT (1 << 5) /* get sink cap sent */
#define PD_FLAGS_NEW_CONTRACT (1 << 6) /* new power contract established */
#define PD_FLAGS_EXPLICIT_CONTRACT (1 << 7) /* explicit pwr contract in place */
+#define PD_FLAGS_SFT_RST_DIS_COMM (1 << 8) /* disable comms after soft reset */
/* Flags to clear on a disconnect */
#define PD_FLAGS_RESET_ON_DISCONNECT_MASK (PD_FLAGS_PARTNER_DR_POWER | \
PD_FLAGS_PARTNER_DR_DATA | \
@@ -255,7 +256,7 @@ static struct pd_protocol {
/* current port data role (DFP or UFP) */
uint8_t data_role;
/* port flags, see PD_FLAGS_* */
- uint8_t flags;
+ uint16_t flags;
/* 3-bit rolling message ID counter */
uint8_t msg_id;
/* Port polarity : 0 => CC1 is CC line, 1 => CC2 is CC line */
@@ -751,6 +752,10 @@ static void execute_soft_reset(int port)
#else
set_state(port, PD_STATE_SRC_DISCOVERY);
#endif
+ /* if flag to disable PD comms after soft reset, then disable comms */
+ if (pd[port].flags & PD_FLAGS_SFT_RST_DIS_COMM)
+ pd_comm_enable(0);
+
CPRINTF("Soft Reset\n");
}
@@ -765,6 +770,25 @@ void pd_soft_reset(void)
}
}
+void pd_prepare_sysjump(void)
+{
+ int i;
+
+ /*
+ * On sysjump, we are most definitely going to drop pings (if any)
+ * and lose all of our PD state. Instead of trying to remember all
+ * the states and deal with on-going transmission, let's send soft
+ * reset here and then disable PD communication until after sysjump
+ * is complete so that the communication starts over without dropping
+ * power.
+ */
+ for (i = 0; i < PD_PORT_COUNT; ++i)
+ if (pd_is_connected(i))
+ pd[i].flags |= PD_FLAGS_SFT_RST_DIS_COMM;
+
+ pd_soft_reset();
+}
+
#ifdef CONFIG_USB_PD_DUAL_ROLE
static void pd_store_src_cap(int port, int cnt, uint32_t *src_caps)
{
@@ -982,13 +1006,7 @@ static void handle_ctrl_request(int port, uint16_t head,
break;
case PD_CTRL_ACCEPT:
if (pd[port].task_state == PD_STATE_SOFT_RESET) {
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- set_state(port, pd[port].power_role == PD_ROLE_SINK ?
- PD_STATE_SNK_DISCOVERY :
- PD_STATE_SRC_DISCOVERY);
-#else
- set_state(port, PD_STATE_SRC_DISCOVERY);
-#endif
+ execute_soft_reset(port);
} else if (pd[port].task_state == PD_STATE_SRC_DR_SWAP) {
/* switch data role */
pd_dr_swap(port);
@@ -1402,7 +1420,6 @@ int pd_get_partner_data_swap_capable(int port)
void pd_comm_enable(int enable)
{
pd_comm_enabled = enable;
-
#ifdef CONFIG_USB_PD_DUAL_ROLE
/*
* If communications are enabled, start hard reset timer for
@@ -2139,7 +2156,6 @@ void pd_task(void)
#endif /* CONFIG_USB_PD_DUAL_ROLE */
case PD_STATE_SOFT_RESET:
if (pd[port].last_state != pd[port].task_state) {
- execute_soft_reset(port);
res = send_control(port, PD_CTRL_SOFT_RESET);
/* if soft reset failed, try hard reset. */
diff --git a/include/usb_pd.h b/include/usb_pd.h
index 7418988236..7c7532d08f 100644
--- a/include/usb_pd.h
+++ b/include/usb_pd.h
@@ -1168,6 +1168,8 @@ void pd_ping_enable(int port, int enable);
/* Issue PD soft reset */
void pd_soft_reset(void);
+/* Prepare PD communication for sysjump */
+void pd_prepare_sysjump(void);
/**
* Signal power request to indicate a charger update that affects the port.