diff options
author | Eric Herrmann <eherrmann@chromium.org> | 2020-12-03 09:53:20 -0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-12-08 01:32:22 +0000 |
commit | a0f2c4640c879521d2e9893317fe50ee1a4c76ee (patch) | |
tree | b360d3a3ba168d3cdbcb0ef02396b71556986425 | |
parent | de6407f867863eb2976194b3d55d0fe4d4e33a6f (diff) | |
download | chrome-ec-a0f2c4640c879521d2e9893317fe50ee1a4c76ee.tar.gz |
SYV682: Disable VCONN on VCONN OCP
The SYV682 has a 'soft' overcurrent protection on VCONN which current
limits to ~600mA. If the cause is a short it will eventually hit thermal
shutdown. Instead, we should disable VCONN when we get an OCP event. We
must allow current spikes for at least 1ms, so disable with a deglitch.
BUG=b:170441866,b:172710638
TEST=make buildall
TEST=On Voxel, short VCONN to ground for at least 100ms, then observe
that VCONN is disabled and 'VCONN OC!' is printed in the EC console.
BRANCH=None
Signed-off-by: Eric Herrmann <eherrmann@chromium.org>
Change-Id: I6712543b73072c959597c73cd493f248267a42ae
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2572237
Reviewed-by: Keith Short <keithshort@chromium.org>
Tested-by: Keith Short <keithshort@chromium.org>
-rw-r--r-- | driver/ppc/syv682x.c | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/driver/ppc/syv682x.c b/driver/ppc/syv682x.c index b4c48f1365..43561b4bfb 100644 --- a/driver/ppc/syv682x.c +++ b/driver/ppc/syv682x.c @@ -30,7 +30,8 @@ static uint32_t irq_pending; /* Bitmask of ports signaling an interrupt. */ static uint8_t flags[CONFIG_USB_PD_PORT_MAX_COUNT]; -static timestamp_t oc_timer[CONFIG_USB_PD_PORT_MAX_COUNT]; +static timestamp_t vbus_oc_timer[CONFIG_USB_PD_PORT_MAX_COUNT]; +static timestamp_t vconn_oc_timer[CONFIG_USB_PD_PORT_MAX_COUNT]; #define SYV682X_VBUS_DET_THRESH_MV 4000 /* Longest time that can be programmed in DSG_TIME field */ @@ -39,6 +40,7 @@ static timestamp_t oc_timer[CONFIG_USB_PD_PORT_MAX_COUNT]; #define INTERRUPT_DELAY_MS 10 /* Deglitch in ms of sourcing overcurrent detection */ #define SOURCE_OC_DEGLITCH_MS 100 +#define VCONN_OC_DEGLITCH_MS 100 #if SOURCE_OC_DEGLITCH_MS < INTERRUPT_DELAY_MS #error "SOURCE_OC_DEGLITCH_MS should be at least INTERRUPT_DELAY_MS" @@ -245,11 +247,11 @@ static void syv682x_handle_status_interrupt(int port, int regval) */ if (syv682x_interrupt_filter(port, regval, SYV682X_STATUS_OC_5V, SYV682X_FLAGS_5V_OC)) { - oc_timer[port].val = + vbus_oc_timer[port].val = get_time().val + SOURCE_OC_DEGLITCH_MS * MSEC; } else if ((regval & SYV682X_STATUS_OC_5V) && - (get_time().val > oc_timer[port].val)) { - oc_timer[port].val = UINT64_MAX; + (get_time().val > vbus_oc_timer[port].val)) { + vbus_oc_timer[port].val = UINT64_MAX; flags[port] &= ~SYV682X_FLAGS_5V_OC; syv682x_vbus_source_enable(port, 0); pd_handle_overcurrent(port); @@ -274,8 +276,28 @@ static void syv682x_handle_status_interrupt(int port, int regval) static void syv682x_handle_control_4_interrupt(int port, int regval) { + /* + * VCONN OC is actually notifying that it is current limiting + * to 600mA. If this happens for a long time, we will trip TSD + * which will disable the channel. We should disable the sourcing path + * before that happens for safety reasons. + * + * On first check, set the flag and set the timer. This also clears the + * flag if the OC is gone. + */ if (syv682x_interrupt_filter(port, regval, SYV682X_CONTROL_4_VCONN_OCP, SYV682X_FLAGS_VCONN_OCP)) { + vconn_oc_timer[port].val = + get_time().val + VCONN_OC_DEGLITCH_MS * MSEC; + } else if ((regval & SYV682X_CONTROL_4_VCONN_OCP) && + (get_time().val > vconn_oc_timer[port].val)) { + vconn_oc_timer[port].val = UINT64_MAX; + flags[port] &= ~SYV682X_FLAGS_VCONN_OCP; + /* Disable VCONN */ + regval &= + ~(SYV682X_CONTROL_4_VCONN2 | SYV682X_CONTROL_4_VCONN1); + write_reg(port, SYV682X_CONTROL_4_REG, regval); + ppc_prints("VCONN OC!", port); } |