summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorAseda Aboagye <aaboagye@google.com>2018-02-06 16:37:06 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2018-04-27 22:55:14 +0000
commitcb69fcae3374f6ebc03ced2fd75662848ea3d47d (patch)
tree1bea070cf3d73147e3a97e482f7ebee82a7b618f /common
parent433b9d770cd694dd10c5582b6e0b5bddc2a85f1f (diff)
downloadchrome-ec-cb69fcae3374f6ebc03ced2fd75662848ea3d47d.tar.gz
USB PD: Save explicit contract state for port 2.
pd_get/set_saved_active() made the assumption that there were only two ports. But now, we have a board that turned that port count all the way up to 3. This commit adds in that new port BBRAM index. It also turns the byte where the port information was stored into a byte of flags, where bit 0 indicates whether there was an explicit contract in place or not. BUG=b:72838807 BRANCH=None TEST=With some code to check for explicit contract state for port 2, verify it's functional. Change-Id: I6f062f67bd3c47dd43ea7e24e844a9286fa37af9 Signed-off-by: Aseda Aboagye <aaboagye@google.com> Reviewed-on: https://chromium-review.googlesource.com/905923 Commit-Ready: Aseda Aboagye <aaboagye@chromium.org> Tested-by: Aseda Aboagye <aaboagye@chromium.org> Reviewed-by: Jett Rink <jettrink@chromium.org> Reviewed-by: Vincent Palatin <vpalatin@chromium.org> (cherry picked from commit 7dc83bed4893cb48fb79782439d4b0b5e94aca66) Reviewed-on: https://chromium-review.googlesource.com/1033364 Reviewed-by: Philip Chen <philipchen@chromium.org> Commit-Queue: Philip Chen <philipchen@chromium.org> Tested-by: Philip Chen <philipchen@chromium.org>
Diffstat (limited to 'common')
-rw-r--r--common/usb_pd_protocol.c96
1 files changed, 72 insertions, 24 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index af623fbcbe..75c2573e0c 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -341,6 +341,56 @@ static void set_vconn(int port, int enable)
}
#endif /* defined(CONFIG_USBC_VCONN) */
+#ifdef CONFIG_USB_PD_DUAL_ROLE
+static int get_bbram_idx(int port)
+{
+ switch (port) {
+ case 2:
+ return SYSTEM_BBRAM_IDX_PD2;
+
+ case 1:
+ return SYSTEM_BBRAM_IDX_PD1;
+
+ case 0:
+ return SYSTEM_BBRAM_IDX_PD0;
+
+ default:
+ return -1;
+ }
+}
+
+static int pd_get_saved_port_flags(int port, uint8_t *flags)
+{
+ if (system_get_bbram(get_bbram_idx(port), flags) != EC_SUCCESS) {
+ CPRINTS("PD NVRAM FAIL");
+ return EC_ERROR_UNKNOWN;
+ }
+
+ return EC_SUCCESS;
+}
+
+static void pd_set_saved_port_flags(int port, uint8_t flags)
+{
+ if (system_set_bbram(get_bbram_idx(port), flags) != EC_SUCCESS)
+ CPRINTS("PD NVRAM FAIL");
+}
+
+static void pd_update_saved_port_flags(int port, uint8_t flag, uint8_t val)
+{
+ uint8_t saved_flags;
+
+ if (pd_get_saved_port_flags(port, &saved_flags) != EC_SUCCESS)
+ return;
+
+ if (val)
+ saved_flags |= flag;
+ else
+ saved_flags &= ~flag;
+
+ pd_set_saved_port_flags(port, saved_flags);
+}
+#endif /* defined(CONFIG_USB_PD_DUAL_ROLE) */
+
static inline void set_state(int port, enum pd_states next_state)
{
enum pd_states last_state = pd[port].task_state;
@@ -381,6 +431,8 @@ static inline void set_state(int port, enum pd_states next_state)
#ifdef CONFIG_USBC_VCONN
set_vconn(port, 0);
#endif /* defined(CONFIG_USBC_VCONN) */
+ pd_update_saved_port_flags(port, PD_BBRMFLG_EXPLICIT_CONTRACT,
+ 0);
#else /* CONFIG_USB_PD_DUAL_ROLE */
if (next_state == PD_STATE_SRC_DISCONNECTED) {
#endif
@@ -808,24 +860,6 @@ static int send_request(int port, uint32_t rdo)
return bit_len;
}
-static int pd_get_saved_active(int port)
-{
- uint8_t val;
-
- if (system_get_bbram(port ? SYSTEM_BBRAM_IDX_PD1 :
- SYSTEM_BBRAM_IDX_PD0, &val)) {
- CPRINTS("PD NVRAM FAIL");
- return 0;
- }
- return !!val;
-}
-
-static void pd_set_saved_active(int port, int val)
-{
- if (system_set_bbram(port ? SYSTEM_BBRAM_IDX_PD1 :
- SYSTEM_BBRAM_IDX_PD0, val))
- CPRINTS("PD NVRAM FAIL");
-}
#endif /* CONFIG_USB_PD_DUAL_ROLE */
#ifdef CONFIG_COMMON_RUNTIME
@@ -1140,6 +1174,10 @@ static void handle_data_request(int port, uint16_t head,
/* explicit contract is now in place */
pd[port].flags |= PD_FLAGS_EXPLICIT_CONTRACT;
+#ifdef CONFIG_USB_PD_DUAL_ROLE
+ pd_update_saved_port_flags(
+ port, PD_BBRMFLG_EXPLICIT_CONTRACT, 1);
+#endif /* CONFIG_USB_PD_DUAL_ROLE */
#ifdef CONFIG_USB_PD_REV30
/*
* Start Source-coordinated collision
@@ -1149,9 +1187,6 @@ static void handle_data_request(int port, uint16_t head,
pd[port].power_role == PD_ROLE_SOURCE)
sink_can_xmit(port, SINK_TX_OK);
#endif
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- pd_set_saved_active(port, 1);
-#endif
pd[port].requested_idx = RDO_POS(payload[0]);
set_state(port, PD_STATE_SRC_ACCEPTED);
return;
@@ -1434,15 +1469,23 @@ static void handle_ctrl_request(int port, uint16_t head,
} else if (pd[port].task_state == PD_STATE_SRC_SWAP_INIT) {
/* explicit contract goes away for power swap */
pd[port].flags &= ~PD_FLAGS_EXPLICIT_CONTRACT;
+ pd_update_saved_port_flags(port,
+ PD_BBRMFLG_EXPLICIT_CONTRACT,
+ 0);
set_state(port, PD_STATE_SRC_SWAP_SNK_DISABLE);
} else if (pd[port].task_state == PD_STATE_SNK_SWAP_INIT) {
/* explicit contract goes away for power swap */
pd[port].flags &= ~PD_FLAGS_EXPLICIT_CONTRACT;
+ pd_update_saved_port_flags(port,
+ PD_BBRMFLG_EXPLICIT_CONTRACT,
+ 0);
set_state(port, PD_STATE_SNK_SWAP_SNK_DISABLE);
} else if (pd[port].task_state == PD_STATE_SNK_REQUESTED) {
/* explicit contract is now in place */
pd[port].flags |= PD_FLAGS_EXPLICIT_CONTRACT;
- pd_set_saved_active(port, 1);
+ pd_update_saved_port_flags(port,
+ PD_BBRMFLG_EXPLICIT_CONTRACT,
+ 1);
set_state(port, PD_STATE_SNK_TRANSITION);
#endif
}
@@ -1841,13 +1884,18 @@ static int pd_is_power_swapping(int port)
static void pd_partner_port_reset(int port)
{
uint64_t timeout;
+ int explicit_contract_in_place;
+ uint8_t flags;
+
+ pd_get_saved_port_flags(port, &flags);
+ explicit_contract_in_place = (flags & PD_BBRMFLG_EXPLICIT_CONTRACT);
/*
* Check our battery-backed previous port state. If PD comms were
* active, and we didn't just lose power, make sure we
* don't boot into RO with a pre-existing power contract.
*/
- if (!pd_get_saved_active(port) ||
+ if (!explicit_contract_in_place ||
system_get_image_copy() != SYSTEM_IMAGE_RO ||
system_get_reset_flags() &
(RESET_FLAG_BROWNOUT | RESET_FLAG_POWER_ON))
@@ -1857,7 +1905,7 @@ static void pd_partner_port_reset(int port)
* Clear the active contract bit before we apply Rp in case we
* intentionally brown out because we cut off our only power supply.
*/
- pd_set_saved_active(port, 0);
+ pd_update_saved_port_flags(port, PD_BBRMFLG_EXPLICIT_CONTRACT, 0);
/* Provide Rp for 200 msec. or until we no longer have VBUS. */
tcpm_set_cc(port, TYPEC_CC_RP);