summaryrefslogtreecommitdiff
path: root/common/usbc_ppc.c
diff options
context:
space:
mode:
authorEric Yilun Lin <yllin@chromium.org>2020-09-25 16:21:27 +0800
committerCommit Bot <commit-bot@chromium.org>2020-10-08 06:00:54 +0000
commit853e6337629e3ef27e430075b7f3276f3832fa03 (patch)
treec6d1b50a55c1440f65c43a3e40d04c19df494467 /common/usbc_ppc.c
parent5b62424750cd8b486966d851a5a4d34bfe430d39 (diff)
downloadchrome-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.c28
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)