diff options
-rw-r--r-- | driver/ppc/sn5s330.c | 63 | ||||
-rw-r--r-- | driver/ppc/sn5s330.h | 9 |
2 files changed, 58 insertions, 14 deletions
diff --git a/driver/ppc/sn5s330.c b/driver/ppc/sn5s330.c index 231d24b906..3f3423b058 100644 --- a/driver/ppc/sn5s330.c +++ b/driver/ppc/sn5s330.c @@ -342,6 +342,12 @@ static int sn5s330_init(int port) 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. */ @@ -401,6 +407,12 @@ 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; @@ -628,6 +640,20 @@ static int sn5s330_vbus_source_enable(int port, int enable) return sn5s330_pp_fet_enable(port, SN5S330_PP1, !!enable); } +#ifdef CONFIG_USBC_PPC_SBU +static int sn5s330_set_sbu(int port, int enable) +{ + int rv; + + if (enable) + rv = set_flags(port, SN5S330_FUNC_SET2, SN5S330_SBU_EN); + else + rv = clr_flags(port, SN5S330_FUNC_SET2, SN5S330_SBU_EN); + + return rv; +} +#endif /* CONFIG_USBC_PPC_SBU */ + static void sn5s330_handle_interrupt(int port) { int attempt = 0; @@ -642,6 +668,8 @@ static void sn5s330_handle_interrupt(int port) { int rise = 0; int fall = 0; + int regval = 0; + int retries = 0; attempt++; @@ -690,26 +718,33 @@ static void sn5s330_handle_interrupt(int port) 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); } } -#ifdef CONFIG_USBC_PPC_SBU -static int sn5s330_set_sbu(int port, int enable) -{ - int rv; - - if (enable) - rv = set_flags(port, SN5S330_FUNC_SET2, SN5S330_SBU_EN); - else - rv = clr_flags(port, SN5S330_FUNC_SET2, SN5S330_SBU_EN); - - return rv; -} -#endif /* CONFIG_USBC_PPC_SBU */ - static void sn5s330_irq_deferred(void) { int i; diff --git a/driver/ppc/sn5s330.h b/driver/ppc/sn5s330.h index cfb7bf7c96..94d0ab0f1e 100644 --- a/driver/ppc/sn5s330.h +++ b/driver/ppc/sn5s330.h @@ -144,6 +144,15 @@ enum sn5s330_pp_idx { #define SN5S330_VCONN_ILIM (1 << 1) /* + * INT_MASK_RISE/FALL_EDGE2 + * + * The OV_CC1_CON/OV_CC2_CON bit indicates an over-voltage occurred on + * C_CC1/C_CC2. + */ +#define SN5S330_CC1_CON (1 << 2) +#define SN5S330_CC2_CON (1 << 3) + +/* * INT_MASK_RISE/FALL_EDGE_3 * * The VBUS_GOOD bit indicates VBUS has increased beyond a 4.0V threshold. |