diff options
author | Aseda Aboagye <aaboagye@google.com> | 2018-02-06 16:37:06 -0800 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2018-04-27 22:55:14 +0000 |
commit | cb69fcae3374f6ebc03ced2fd75662848ea3d47d (patch) | |
tree | 1bea070cf3d73147e3a97e482f7ebee82a7b618f | |
parent | 433b9d770cd694dd10c5582b6e0b5bddc2a85f1f (diff) | |
download | chrome-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>
-rw-r--r-- | common/usb_pd_protocol.c | 96 | ||||
-rw-r--r-- | include/usb_pd.h | 3 |
2 files changed, 75 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); diff --git a/include/usb_pd.h b/include/usb_pd.h index ac3d16cbc5..62d83cc2a7 100644 --- a/include/usb_pd.h +++ b/include/usb_pd.h @@ -734,6 +734,9 @@ enum pd_states { PD_FLAGS_UPDATE_SRC_CAPS | \ PD_FLAGS_TS_DTS_PARTNER) +/* Per-port battery backed RAM flags */ +#define PD_BBRMFLG_EXPLICIT_CONTRACT (1 << 0) + enum pd_cc_states { PD_CC_NONE, |