From bfd3e5a9bf19e2066ad58f36f7dd9248cdf0b930 Mon Sep 17 00:00:00 2001 From: Eric Yilun Lin Date: Fri, 5 Mar 2021 14:01:47 +0800 Subject: ppc/syv682x: support C version C version won't block I2C accessing to CONTROL4(to on/off Vconn) reg when smart discahrge enabled. This allows us to re-enable the smart discahrge on boards using SYV682C. This CL support the feature by adding: 1. CONFIG_USBC_PPC_SYV682C 2. CONFIG_USBC_PPC_SYV682X_SMART_DISCHARGE also, hayato uses different SYV682 versions across revisions, add a overridable function syv682x_board_is_syv682c() for handling board revision issue. BUG=b:160548079 b:176876036 TEST=Hayato meets tVconnOff, and tVbusDischarge BRANCH=asurada Change-Id: I89b57b8c20907249d5d97140289fb0570bd58b46 Signed-off-by: Eric Yilun Lin Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2738506 Reviewed-by: Ting Shen --- driver/ppc/syv682x.c | 49 ++++++++++++++++++++++++++++++++++++++----------- driver/ppc/syv682x.h | 12 ++++++++++++ 2 files changed, 50 insertions(+), 11 deletions(-) (limited to 'driver/ppc') diff --git a/driver/ppc/syv682x.c b/driver/ppc/syv682x.c index e66411fd0a..0e49abdf6a 100644 --- a/driver/ppc/syv682x.c +++ b/driver/ppc/syv682x.c @@ -82,16 +82,29 @@ static int read_reg(uint8_t port, int reg, int *regval) regval); } +#ifdef CONFIG_USBC_PPC_SYV682C +__overridable int syv682x_board_is_syv682c(int port) +{ + return true; +} +#endif + /* - * During channel transition or discharge, the SYV682A silently ignores I2C + * During channel transition or discharge, the SYV682X silently ignores I2C * writes. Poll the BUSY bit until the SYV682A is ready. */ -static int syv682x_wait_for_ready(int port) +static int syv682x_wait_for_ready(int port, int reg) { int regval; int rv; timestamp_t deadline; +#ifdef CONFIG_USBC_PPC_SYV682C + /* On SYV682C, busy bit is not applied to CONTROL_4 */ + if (syv682x_board_is_syv682c(port) && reg == SYV682X_CONTROL_4_REG) + return EC_SUCCESS; +#endif + deadline.val = get_time().val + (SYV682X_MAX_VBUS_DISCHARGE_TIME_MS * MSEC); @@ -118,7 +131,7 @@ static int write_reg(uint8_t port, int reg, int regval) { int rv; - rv = syv682x_wait_for_ready(port); + rv = syv682x_wait_for_ready(port, reg); if (rv) return rv; @@ -135,6 +148,7 @@ static int syv682x_is_sourcing_vbus(int port) static int syv682x_discharge_vbus(int port, int enable) { +#ifndef CONFIG_USBC_PPC_SYV682X_SMART_DISCHARGE int regval; int rv; @@ -148,7 +162,12 @@ static int syv682x_discharge_vbus(int port, int enable) regval &= ~SYV682X_CONTROL_2_FDSG; return write_reg(port, SYV682X_CONTROL_2_REG, regval); - +#else + /* + * Smart discharge mode is enabled, nothing to do + */ + return EC_SUCCESS; +#endif } static int syv682x_vbus_source_enable(int port, int enable) @@ -654,6 +673,7 @@ static int syv682x_set_frs_enable(int port, int enable) } #endif /*CONFIG_USB_PD_FRS_PPC*/ +#ifndef CONFIG_USBC_PPC_SYV682X_SMART_DISCHARGE static int syv682x_dev_is_connected(int port, enum ppc_device_role dev) { /* @@ -667,6 +687,7 @@ static int syv682x_dev_is_connected(int port, enum ppc_device_role dev) return EC_SUCCESS; } +#endif static bool syv682x_is_sink(uint8_t control_1) { @@ -745,15 +766,19 @@ static int syv682x_init(int port) return rv; /* - * Set Control Reg 2 to defaults. - * Note: do not enable smart discharge since it would block - * i2c transactions for 50ms (discharge time) and this prevents - * us from disabling Vconn when stop sourcing Vbus and has tVconnOff - * (35ms) timeout. + * Set Control Reg 2 to defaults except 50ms smart discharge time. + * Note: On SYV682A/B, enable smart discharge would block i2c + * transactions for 50ms (discharge time) and this + * prevents us from disabling Vconn when stop sourcing Vbus and has + * tVconnOff (35ms) timeout. + * On SYV682C, we are allowed to access CONTROL4 while the i2c busy. */ regval = (SYV682X_OC_DELAY_10MS << SYV682X_OC_DELAY_SHIFT) - | (SYV682X_DSG_TIME_200MS << SYV682X_DSG_TIME_SHIFT) - | (SYV682X_DSG_RON_200_OHM << SYV682X_DSG_RON_SHIFT); + | (SYV682X_DSG_RON_200_OHM << SYV682X_DSG_RON_SHIFT) + | (SYV682X_DSG_TIME_50MS << SYV682X_DSG_TIME_SHIFT); + + if (IS_ENABLED(CONFIG_USBC_PPC_SYV682X_SMART_DISCHARGE)) + regval |= SYV682X_CONTROL_2_SDSG; rv = write_reg(port, SYV682X_CONTROL_2_REG, regval); if (rv) @@ -800,7 +825,9 @@ const struct ppc_drv syv682x_drv = { #endif /* defined(CONFIG_USB_PD_VBUS_DETECT_PPC) */ .set_vbus_source_current_limit = &syv682x_set_vbus_source_current_limit, .discharge_vbus = &syv682x_discharge_vbus, +#ifndef CONFIG_USBC_PPC_SYV682X_SMART_DISCHARGE .dev_is_connected = &syv682x_dev_is_connected, +#endif /* defined(CONFIG_USBC_PPC_SYV682X_SMART_DISCHARGE) */ #ifdef CONFIG_USBC_PPC_POLARITY .set_polarity = &syv682x_set_polarity, #endif diff --git a/driver/ppc/syv682x.h b/driver/ppc/syv682x.h index 3ecbede18c..d9416f47f1 100644 --- a/driver/ppc/syv682x.h +++ b/driver/ppc/syv682x.h @@ -8,6 +8,7 @@ #ifndef __CROS_EC_SYV682X_H #define __CROS_EC_SYV682X_H +#include "common.h" #include "driver/ppc/syv682x_public.h" /* Source OC deglitch implemented in HW for SYV682B */ @@ -97,4 +98,15 @@ #define SYV682X_CONTROL_4_CC_FRS BIT(1) #define SYV682X_CONTROL_4_INT_MASK 0x0c +/* + * syv682x_board_is_syv682c + * + * b:160548079 This is a function to workaround that some board revisions + * might have different SYV682 sub-version. + * + * @param port the query port + * @return 1 if the PPC is SYV682C else 0 + */ +__override_proto int syv682x_board_is_syv682c(int port); + #endif /* defined(__CROS_EC_SYV682X_H) */ -- cgit v1.2.1