From fbe977e7a603bf4d4e60854f462fecf496bec3c6 Mon Sep 17 00:00:00 2001 From: Edward Hill Date: Tue, 3 Dec 2019 12:31:56 -0700 Subject: ppc: Use hard reset to recover from CC overvoltage When sn5s330 PPC detects CC overvoltage, recover via hard reset and don't enable PP2 sink FET directly. Also clean up the interrupt unmasking in sn5s330_init(). BUG=b:144892533 BRANCH=grunt TEST=Do ESD test to trigger CC1/CC2 OVP, device recovers to sink Change-Id: I662bf164b55508be4d5cc1b3ad639c9613bd1935 Signed-off-by: Edward Hill Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1949264 Reviewed-by: Aseda Aboagye --- common/usb_common.c | 5 +++ driver/ppc/sn5s330.c | 93 +++++++++++++++------------------------------------- include/usb_pd.h | 7 ++++ 3 files changed, 39 insertions(+), 66 deletions(-) diff --git a/common/usb_common.c b/common/usb_common.c index af77e65ebc..033577249f 100644 --- a/common/usb_common.c +++ b/common/usb_common.c @@ -440,4 +440,9 @@ void pd_handle_overcurrent(int port) hook_call_deferred(&re_enable_ports_data, SECOND); } +void pd_handle_cc_overvoltage(int port) +{ + pd_send_hard_reset(port); +} + #endif /* CONFIG_USBC_PPC */ diff --git a/driver/ppc/sn5s330.c b/driver/ppc/sn5s330.c index cdc355a8ae..1c9b63f04f 100644 --- a/driver/ppc/sn5s330.c +++ b/driver/ppc/sn5s330.c @@ -335,18 +335,6 @@ static int sn5s330_init(int port) CPRINTS("ppc p%d: Failed to turn off PP1 FET!", port); } - /* - * Unmask the VCONN ILIM interrupt so we can print VCONN overcurrent - * events. - */ - clr_flags(port, SN5S330_INT_MASK_RISE_REG2, SN5S330_VCONN_ILIM); - - /* - * Unmask the CC1/CC2 OVP interrupt so we can print CC1/CC2 OVP events - */ - clr_flags(port, SN5S330_INT_MASK_RISE_REG2, SN5S330_CC1_CON); - clr_flags(port, SN5S330_INT_MASK_RISE_REG2, SN5S330_CC2_CON); - /* * Don't proceed with the rest of initialization if we're sysjumping. * We would have already done this before. @@ -368,15 +356,14 @@ static int sn5s330_init(int port) } /* - * Before turning on the PP2 FET, let's mask off all interrupts except - * for the PP1 overcurrent condition and then clear all pending - * interrupts. If PPC is being used to detect VBUS, then also enable - * interrupts for VBUS presence. + * Before turning on the PP2 FET, mask off all unwanted interrupts and + * then clear all pending interrupts. * * TODO(aaboagye): Unmask fast-role swap events once fast-role swap is * implemented in the PD stack. */ + /* Enable PP1 overcurrent interrupts. */ regval = ~SN5S330_ILIM_PP1_MASK; status = i2c_write8(i2c_port, i2c_addr_flags, SN5S330_INT_MASK_RISE_REG1, regval); @@ -386,15 +373,16 @@ static int sn5s330_init(int port) } status = i2c_write8(i2c_port, i2c_addr_flags, - SN5S330_INT_MASK_FALL_REG1, regval); + SN5S330_INT_MASK_FALL_REG1, 0xFF); if (status) { CPRINTS("ppc p%d: Failed to write INT_MASK_FALL1!", port); return status; } - /* Now mask all the other interrupts. */ + /* Enable VCONN overcurrent and CC1/CC2 overvoltage interrupts. */ + regval = ~(SN5S330_VCONN_ILIM | SN5S330_CC1_CON | SN5S330_CC2_CON); status = i2c_write8(i2c_port, i2c_addr_flags, - SN5S330_INT_MASK_RISE_REG2, 0xFF); + SN5S330_INT_MASK_RISE_REG2, regval); if (status) { CPRINTS("ppc p%d: Failed to write INT_MASK_RISE2!", port); return status; @@ -407,12 +395,6 @@ static int sn5s330_init(int port) return status; } - /* - * Unmask the CC1/CC2 OVP interrupt so we can print CC1/CC2 OVP events - */ - clr_flags(port, SN5S330_INT_MASK_RISE_REG2, SN5S330_CC1_CON); - clr_flags(port, SN5S330_INT_MASK_RISE_REG2, SN5S330_CC2_CON); - #if defined(CONFIG_USB_PD_VBUS_DETECT_PPC) && defined(CONFIG_USB_CHARGER) /* If PPC is being used to detect VBUS, enable VBUS interrupts. */ regval = ~SN5S330_VBUS_GOOD_MASK; @@ -668,8 +650,6 @@ static void sn5s330_handle_interrupt(int port) { int rise = 0; int fall = 0; - int regval = 0; - int retries = 0; attempt++; @@ -677,11 +657,6 @@ static void sn5s330_handle_interrupt(int port) CPRINTS("ppc p%d: Could not clear interrupts on first " "try, retrying", port); - /* - * The only interrupts that should be enabled are the PP1 - * overcurrent condition, and for VBUS_GOOD if PPC is being - * used to detect VBUS. - */ read_reg(port, SN5S330_INT_TRIP_RISE_REG1, &rise); read_reg(port, SN5S330_INT_TRIP_FALL_REG1, &fall); @@ -693,6 +668,26 @@ static void sn5s330_handle_interrupt(int port) write_reg(port, SN5S330_INT_TRIP_RISE_REG1, rise); write_reg(port, SN5S330_INT_TRIP_FALL_REG1, fall); + read_reg(port, SN5S330_INT_TRIP_RISE_REG2, &rise); + read_reg(port, SN5S330_INT_TRIP_FALL_REG2, &fall); + + /* + * VCONN may be latched off due to an overcurrent. Indicate + * when the VCONN overcurrent happens. + */ + if (rise & SN5S330_VCONN_ILIM) + CPRINTS("ppc p%d: VCONN OC!", port); + + /* Notify the system about the CC overvoltage event. */ + if (rise & SN5S330_CC1_CON || rise & SN5S330_CC2_CON) { + CPRINTS("ppc p%d: CC OV!", port); + pd_handle_cc_overvoltage(port); + } + + /* Clear the interrupt sources. */ + write_reg(port, SN5S330_INT_TRIP_RISE_REG2, rise); + write_reg(port, SN5S330_INT_TRIP_FALL_REG2, fall); + #if defined(CONFIG_USB_PD_VBUS_DETECT_PPC) && defined(CONFIG_USB_CHARGER) read_reg(port, SN5S330_INT_TRIP_RISE_REG3, &rise); read_reg(port, SN5S330_INT_TRIP_FALL_REG3, &fall); @@ -708,40 +703,6 @@ static void sn5s330_handle_interrupt(int port) write_reg(port, SN5S330_INT_TRIP_FALL_REG3, fall); #endif /* CONFIG_USB_PD_VBUS_DETECT_PPC && CONFIG_USB_CHARGER */ - /* - * VCONN may be latched off due to an overcurrent. Indicate - * when the VCONN overcurrent happens. - */ - read_reg(port, SN5S330_INT_TRIP_RISE_REG2, &rise); - read_reg(port, SN5S330_INT_TRIP_FALL_REG2, &fall); - - if (rise & SN5S330_VCONN_ILIM) - CPRINTS("ppc p%d: VCONN OC!", port); - - if (rise & SN5S330_CC1_CON || rise & SN5S330_CC2_CON) { - CPRINTS("ppc p%d: CC OVP!", port); - retries = 0; - do { - read_reg(port, SN5S330_INT_STATUS_REG3, - ®val); - if (regval & SN5S330_VBUS_GOOD) { - sn5s330_set_sbu(port, 1); - sn5s330_pp_fet_enable(port, - SN5S330_PP2, 1); - break; - } - retries++; - msleep(1); - } while (retries < 10); - - if (retries == 10) - CPRINTS("ppc p%d: Fail to release cc OVP." - , port); - } - - /* Clear the interrupt sources. */ - write_reg(port, SN5S330_INT_TRIP_RISE_REG2, rise); - write_reg(port, SN5S330_INT_TRIP_FALL_REG2, fall); } } diff --git a/include/usb_pd.h b/include/usb_pd.h index 08236b8813..4a979d14a2 100644 --- a/include/usb_pd.h +++ b/include/usb_pd.h @@ -2169,6 +2169,13 @@ int pd_get_partner_data_swap_capable(int port); */ void pd_handle_overcurrent(int port); +/** + * Handle a CC overvoltage protection event. + * + * @param port: USB-C port number. + */ +void pd_handle_cc_overvoltage(int port); + /** * Request power swap command to be issued * -- cgit v1.2.1