diff options
author | Eric Yilun Lin <yllin@chromium.org> | 2020-09-25 16:21:27 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-10-08 06:00:54 +0000 |
commit | 853e6337629e3ef27e430075b7f3276f3832fa03 (patch) | |
tree | c6d1b50a55c1440f65c43a3e40d04c19df494467 /common/usbc_ppc.c | |
parent | 5b62424750cd8b486966d851a5a4d34bfe430d39 (diff) | |
download | chrome-ec-853e6337629e3ef27e430075b7f3276f3832fa03.tar.gz |
usbc_ppc: inform the PPC of the power role of the connected device
On some of the PPC (e.g. syv682) that support manually force discharge
function doesn't automatically turn off discharge FET
when VBUS meets vSafe0V. The original flow is disabling discharge
on pd_set_power_supply_ready and enabling discharge on
pd_power_supply_reset, and since there is no automatic
turning off the discharge circuit, the FET will still be on
when a SNK device connected. We fix this by informing the PPC on
a device is connected or disconnected so that PPC can control the
FET by requests.
BUG=b:160548079, b:148870148, b:163143427
TEST=make buildall
TEST=TCPMv2: on asurada C0/C1(syv682) and volteer C0(sn5s330)/C1(syv682)
port, and enable force discharge mode (CL:2423665), plug sink
and source device and ensure Vconn and Vbus are off within
tVconnOff and tVBusOff respectively. Plug a DRP hub and then
plug adapter in it, and it meets tVconnOff and tVbusOff.
TEST=TCPMv1: tested the same steps as above on Asurada.
BRANCH=NONE
Change-Id: I8ed0e18fce2d402ff24fce6bab393cc618dfac09
Signed-off-by: Eric Yilun Lin <yllin@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2434590
Reviewed-by: Abe Levkoy <alevkoy@chromium.org>
Tested-by: Eric Herrmann <eherrmann@chromium.org>
Diffstat (limited to 'common/usbc_ppc.c')
-rw-r--r-- | common/usbc_ppc.c | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/common/usbc_ppc.c b/common/usbc_ppc.c index 7a334ae439..6724d75abf 100644 --- a/common/usbc_ppc.c +++ b/common/usbc_ppc.c @@ -10,6 +10,7 @@ #include "console.h" #include "hooks.h" #include "timer.h" +#include "usb_pd.h" #include "usbc_ppc.h" #include "util.h" @@ -46,7 +47,8 @@ int ppc_err_prints(const char *string, int port, int error) */ static uint8_t oc_event_cnt_tbl[CONFIG_USB_PD_PORT_MAX_COUNT]; -static uint32_t connected_ports; +/* A flag for ports with sink device connected. */ +static uint32_t snk_connected_ports; /* Simple wrappers to dispatch to the drivers. */ @@ -82,7 +84,7 @@ int ppc_add_oc_event(int port) oc_event_cnt_tbl[port]++; /* The port overcurrented, so don't clear it's OC events. */ - deprecated_atomic_clear_bits(&connected_ports, 1 << port); + deprecated_atomic_clear_bits(&snk_connected_ports, 1 << port); if (oc_event_cnt_tbl[port] >= PPC_OC_CNT_THRESH) ppc_prints("OC event limit reached! " @@ -100,7 +102,7 @@ static void clear_oc_tbl(void) * Only clear the table if the port partner is no longer * attached after debouncing. */ - if ((!(BIT(port) & connected_ports)) && + if ((!(BIT(port) & snk_connected_ports)) && oc_event_cnt_tbl[port]) { oc_event_cnt_tbl[port] = 0; ppc_prints("OC events cleared", port); @@ -256,17 +258,27 @@ int ppc_set_vconn(int port, int enable) } #endif -void ppc_sink_is_connected(int port, int is_connected) +int ppc_dev_is_connected(int port, enum ppc_device_role dev) { + int rv = EC_SUCCESS; + const struct ppc_config_t *ppc; + if ((port < 0) || (port >= ppc_cnt)) { CPRINTS("%s(%d) Invalid port!", __func__, port); - return; + return EC_ERROR_INVAL; } - if (is_connected) - deprecated_atomic_or(&connected_ports, 1 << port); + if (dev == PPC_DEV_SNK) + deprecated_atomic_or(&snk_connected_ports, 1 << port); else - deprecated_atomic_clear_bits(&connected_ports, 1 << port); + /* clear flag if it transitions to SRC or disconnected */ + deprecated_atomic_clear_bits(&snk_connected_ports, 1 << port); + + ppc = &ppc_chips[port]; + if (ppc->drv->dev_is_connected) + rv = ppc->drv->dev_is_connected(port, dev); + + return rv; } int ppc_vbus_sink_enable(int port, int enable) |