summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Hill <ecgh@chromium.org>2019-12-03 12:31:56 -0700
committerCommit Bot <commit-bot@chromium.org>2019-12-06 22:19:35 +0000
commit5fcb29ea3e6cb8839a008fd8b9d619968093e9a7 (patch)
tree4070cd054769df89d971b5421e9ff4fefdb93821
parentd3e5ed7540d2ad903aa70b67dad0ac02d694a78e (diff)
downloadchrome-ec-5fcb29ea3e6cb8839a008fd8b9d619968093e9a7.tar.gz
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 <ecgh@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1949264 Reviewed-by: Aseda Aboagye <aaboagye@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1949267
-rw-r--r--common/usb_pd_protocol.c6
-rw-r--r--driver/ppc/sn5s330.c93
-rw-r--r--include/usb_pd.h7
3 files changed, 40 insertions, 66 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index b2ece4ac08..b661dd5c42 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -4675,6 +4675,12 @@ void pd_handle_overcurrent(int port)
atomic_or(&port_oc_reset_req, (1 << port));
hook_call_deferred(&re_enable_ports_data, SECOND);
}
+
+void pd_handle_cc_overvoltage(int port)
+{
+ pd_send_hard_reset(port);
+}
+
#endif /* defined(CONFIG_USBC_PPC) */
static int command_pd(int argc, char **argv)
diff --git a/driver/ppc/sn5s330.c b/driver/ppc/sn5s330.c
index a94c2ae652..97e99b2b0a 100644
--- a/driver/ppc/sn5s330.c
+++ b/driver/ppc/sn5s330.c
@@ -336,18 +336,6 @@ static int sn5s330_init(int 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;
@@ -667,8 +649,6 @@ static void sn5s330_handle_interrupt(int port)
{
int rise = 0;
int fall = 0;
- int regval = 0;
- int retries = 0;
attempt++;
@@ -676,11 +656,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);
@@ -692,6 +667,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);
@@ -707,40 +702,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,
- &regval);
- 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 60af51cfb7..322e3055b6 100644
--- a/include/usb_pd.h
+++ b/include/usb_pd.h
@@ -1764,6 +1764,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
*
* @param port USB-C port number