diff options
-rw-r--r-- | common/charge_manager.c | 2 | ||||
-rw-r--r-- | driver/tcpm/fusb302.c | 61 | ||||
-rw-r--r-- | driver/tcpm/fusb302.h | 1 | ||||
-rw-r--r-- | include/config.h | 15 | ||||
-rw-r--r-- | include/usb_pd_tcpm.h | 9 |
5 files changed, 88 insertions, 0 deletions
diff --git a/common/charge_manager.c b/common/charge_manager.c index 2d7763e5bd..7f50e50b68 100644 --- a/common/charge_manager.c +++ b/common/charge_manager.c @@ -460,6 +460,8 @@ static void charge_manager_fill_power_info(int port, else { #if defined(CONFIG_USB_PD_VBUS_MEASURE_CHARGER) r->meas.voltage_now = charger_get_vbus_voltage(port); +#elif defined(CONFIG_USB_PD_VBUS_MEASURE_TCPC) + r->meas.voltage_now = tcpc_get_vbus_voltage(port); #elif defined(CONFIG_USB_PD_VBUS_MEASURE_ADC_EACH_PORT) r->meas.voltage_now = adc_read_channel(board_get_vbus_adc(port)); diff --git a/driver/tcpm/fusb302.c b/driver/tcpm/fusb302.c index bbb6015e56..c6465cd162 100644 --- a/driver/tcpm/fusb302.c +++ b/driver/tcpm/fusb302.c @@ -36,6 +36,8 @@ static struct fusb302_chip_state { uint8_t mdac_rd; } state[CONFIG_USB_PD_PORT_MAX_COUNT]; +static struct mutex measure_lock; + /* * Bring the FUSB302 out of reset after Hard Reset signaling. This will * automatically flush both the Rx and Tx FIFOs. @@ -112,6 +114,8 @@ static int measure_cc_pin_source(int port, int cc_measure) int reg; int cc_lvl; + mutex_lock(&measure_lock); + /* Read status register */ tcpc_read(port, TCPC_REG_SWITCHES0, ®); /* Save current value */ @@ -159,6 +163,8 @@ static int measure_cc_pin_source(int port, int cc_measure) /* Restore SWITCHES0 register to its value prior */ tcpc_write(port, TCPC_REG_SWITCHES0, switches0_reg); + mutex_unlock(&measure_lock); + return cc_lvl; } @@ -194,6 +200,8 @@ static void detect_cc_pin_sink(int port, enum tcpc_cc_voltage_status *cc1, int bc_lvl_cc1; int bc_lvl_cc2; + mutex_lock(&measure_lock); + /* * Measure CC1 first. */ @@ -264,6 +272,8 @@ static void detect_cc_pin_sink(int port, enum tcpc_cc_voltage_status *cc1, reg &= ~TCPC_REG_SWITCHES0_MEAS_CC2; tcpc_write(port, TCPC_REG_SWITCHES0, reg); + + mutex_unlock(&measure_lock); } /* Parse header bytes for the size of packet */ @@ -1077,6 +1087,57 @@ static int fusb302_tcpm_enter_low_power_mode(int port) } #endif +/* + * Compare VBUS voltage with given mdac reference voltage. + * returns non-zero if VBUS voltage >= (mdac + 1) * 420 mV + */ +static int fusb302_compare_mdac(int port, int mdac) +{ + int orig_reg, status0; + + mutex_lock(&measure_lock); + + /* backup REG_MEASURE */ + tcpc_read(port, TCPC_REG_MEASURE, &orig_reg); + /* set reg_measure bit 0~5 to mdac, and bit6 to 1(measure vbus) */ + tcpc_write(port, TCPC_REG_MEASURE, + (mdac & TCPC_REG_MEASURE_MDAC_MASK) | TCPC_REG_MEASURE_VBUS); + + /* Wait on measurement */ + usleep(350); + + /* + * Read status register, if STATUS0_COMP=1 then vbus is higher than + * (mdac + 1) * 0.42V + */ + tcpc_read(port, TCPC_REG_STATUS0, &status0); + /* write back original value */ + tcpc_write(port, TCPC_REG_MEASURE, orig_reg); + + mutex_unlock(&measure_lock); + + return status0 & TCPC_REG_STATUS0_COMP; +} + +int tcpc_get_vbus_voltage(int port) +{ + int mdac = 0, i; + + /* + * Implement by comparing VBUS with MDAC reference voltage, and binary + * search the value of MDAC. + * + * MDAC register has 6 bits, so we can simply search 1 bit per + * iteration, from MSB to LSB. + */ + for (i = 5; i >= 0; i--) { + if (fusb302_compare_mdac(port, mdac | BIT(i))) + mdac |= BIT(i); + } + + return (mdac + 1) * 420; +} + const struct tcpm_drv fusb302_tcpm_drv = { .init = &fusb302_tcpm_init, .release = &fusb302_tcpm_release, diff --git a/driver/tcpm/fusb302.h b/driver/tcpm/fusb302.h index b4a8599ea8..fee246aeb2 100644 --- a/driver/tcpm/fusb302.h +++ b/driver/tcpm/fusb302.h @@ -49,6 +49,7 @@ #define TCPC_REG_SWITCHES1_TXCC1_EN (1<<0) #define TCPC_REG_MEASURE 0x04 +#define TCPC_REG_MEASURE_MDAC_MASK 0x3F #define TCPC_REG_MEASURE_VBUS (1<<6) /* * MDAC reference voltage step size is 42 mV. Round our thresholds to reduce diff --git a/include/config.h b/include/config.h index f9784cc258..8a0d5edf1f 100644 --- a/include/config.h +++ b/include/config.h @@ -3901,6 +3901,12 @@ /* Define if the there is no hardware to measure Vbus voltage */ #undef CONFIG_USB_PD_VBUS_MEASURE_NOT_PRESENT +/* Define if charger on the board supports VBUS measurement */ +#undef CONFIG_USB_PD_VBUS_MEASURE_CHARGER + +/* Define if tcpc on the board supports VBUS measurement */ +#undef CONFIG_USB_PD_VBUS_MEASURE_TCPC + /* Define the type-c port controller I2C base address. */ #define CONFIG_TCPC_I2C_BASE_ADDR_FLAGS 0x4E @@ -4684,6 +4690,15 @@ /*****************************************************************************/ /* + * Define CONFIG_USB_PD_VBUS_MEASURE_TCPC if the tcpc on the board supports + * VBUS measurement. + */ +#if defined(CONFIG_USB_PD_TCPM_FUSB302) +#define CONFIG_USB_PD_VBUS_MEASURE_TCPC +#endif + +/*****************************************************************************/ +/* * Define CONFIG_CHARGER_NARROW_VDC for chargers that use a Narrow VDC power * architecture. */ diff --git a/include/usb_pd_tcpm.h b/include/usb_pd_tcpm.h index 7a7bd0b3a1..cfd7692852 100644 --- a/include/usb_pd_tcpm.h +++ b/include/usb_pd_tcpm.h @@ -435,4 +435,13 @@ int board_tcpc_post_init(int port) __attribute__((weak)); */ void board_pd_vconn_ctrl(int port, enum usbpd_cc_pin cc_pin, int enabled); +/** + * Get the VBUS voltage from TCPC + * + * @param port Type-C port number + * + * @return VBUS voltage in mV. + */ +int tcpc_get_vbus_voltage(int port); + #endif /* __CROS_EC_USB_PD_TCPM_H */ |