summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTing Shen <phoenixshen@google.com>2019-12-03 10:36:05 +0800
committerCommit Bot <commit-bot@chromium.org>2019-12-09 10:17:14 +0000
commit4fcabe7ac114ca097893746f3154b90e91e7c31f (patch)
treed76c87e09106a5bfe3c4168538dd83ee70ba5cee
parent7ab6523fe5a8badb379e93fe9bb07c85df40eac6 (diff)
downloadchrome-ec-4fcabe7ac114ca097893746f3154b90e91e7c31f.tar.gz
fusb302: implement vbus measurement using tcpc
Jacuzzi measure vbus using fusb302, add a config option CONFIG_USB_PD_VBUS_MEASURE_TCPC and related implementation. BUG=b:145376409 TEST=`ectool usbpdpower` BRANCH=none Change-Id: I84019a75338121f777a344a4b92710e2117a6bda Signed-off-by: Ting Shen <phoenixshen@google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1947507 Reviewed-by: Eric Yilun Lin <yllin@chromium.org> Commit-Queue: Ting Shen <phoenixshen@chromium.org> Tested-by: Ting Shen <phoenixshen@chromium.org>
-rw-r--r--common/charge_manager.c2
-rw-r--r--driver/tcpm/fusb302.c61
-rw-r--r--driver/tcpm/fusb302.h1
-rw-r--r--include/config.h15
-rw-r--r--include/usb_pd_tcpm.h9
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, &reg);
/* 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 */