diff options
-rw-r--r-- | driver/ppc/aoz1380.c | 57 |
1 files changed, 49 insertions, 8 deletions
diff --git a/driver/ppc/aoz1380.c b/driver/ppc/aoz1380.c index 708d488e94..990bd41a73 100644 --- a/driver/ppc/aoz1380.c +++ b/driver/ppc/aoz1380.c @@ -11,6 +11,7 @@ * controlled PPC chips that are similar to the AOZ1380 */ +#include "atomic.h" #include "common.h" #include "console.h" #include "driver/ppc/aoz1380.h" @@ -27,7 +28,12 @@ static uint32_t irq_pending; /* Bitmask of ports signaling an interrupt. */ #define AOZ1380_FLAGS_SOURCE_ENABLED BIT(0) -static uint8_t flags[CONFIG_USB_PD_PORT_MAX_COUNT]; +#define AOZ1380_FLAGS_SINK_ENABLED BIT(1) +#define AOZ1380_FLAGS_INT_ON_DISCONNECT BIT(2) +static uint32_t flags[CONFIG_USB_PD_PORT_MAX_COUNT]; + +#define AOZ1380_SET_FLAG(port, flag) atomic_or(&flags[port], (flag)) +#define AOZ1380_CLR_FLAG(port, flag) atomic_clear(&flags[port], (flag)) static int aoz1380_init(int port) { @@ -41,8 +47,20 @@ static int aoz1380_vbus_sink_enable(int port, int enable) int rv; rv = tcpm_set_snk_ctrl(port, enable); + if (rv) + return rv; + + /* + * On enable, we want to indicate connection as a SINK. + * On disable, clear SINK and that we have interrupted. + */ + if (enable) + AOZ1380_SET_FLAG(port, AOZ1380_FLAGS_SINK_ENABLED); + else + AOZ1380_CLR_FLAG(port, (AOZ1380_FLAGS_SINK_ENABLED | + AOZ1380_FLAGS_INT_ON_DISCONNECT)); - return rv; + return EC_SUCCESS; } static int aoz1380_vbus_source_enable(int port, int enable) @@ -53,12 +71,17 @@ static int aoz1380_vbus_source_enable(int port, int enable) if (rv) return rv; + /* + * On enable, we want to indicate connection as a SOURCE. + * On disable, clear SOURCE and that we have interrupted. + */ if (enable) - flags[port] |= AOZ1380_FLAGS_SOURCE_ENABLED; + AOZ1380_SET_FLAG(port, AOZ1380_FLAGS_SOURCE_ENABLED); else - flags[port] &= ~AOZ1380_FLAGS_SOURCE_ENABLED; + AOZ1380_CLR_FLAG(port, (AOZ1380_FLAGS_SOURCE_ENABLED | + AOZ1380_FLAGS_INT_ON_DISCONNECT)); - return rv; + return EC_SUCCESS; } static int aoz1380_is_sourcing_vbus(int port) @@ -78,14 +101,32 @@ static int aoz1380_set_vbus_source_current_limit(int port, * This device only has a single over current/temperature interrupt. * TODO(b/141939343) Determine how to clear the interrupt * TODO(b/142076004) Test this to verify we shut off vbus current + * TODO(b/147359722) Verify correct fault functionality */ static void aoz1380_handle_interrupt(int port) { /* - * This is a over current/temperature condition + * We can get a false positive on disconnect that we + * had an over current/temperature event when we are no + * longer connected as sink or source. Ignore it if + * that is the case. */ - CPRINTS("C%d: PPC detected Vbus overcurrent/temperature!", port); - pd_handle_overcurrent(port); + if (flags[port] != 0) { + /* + * This is a over current/temperature condition + */ + CPRINTS("C%d PPC Vbus overcurrent/temperature", port); + pd_handle_overcurrent(port); + } else { + /* + * Just in case there is a condition that we will + * continue an interrupt storm, track that we have + * already been here once and will take the other + * path if we do this again before setting the + * sink/source as enabled or disabled again. + */ + AOZ1380_SET_FLAG(port, AOZ1380_FLAGS_INT_ON_DISCONNECT); + } } static void aoz1380_irq_deferred(void) |