summaryrefslogtreecommitdiff
path: root/driver
diff options
context:
space:
mode:
authorPhilip Chen <philipchen@chromium.org>2019-02-20 16:57:49 -0800
committerchrome-bot <chrome-bot@chromium.org>2019-03-01 01:09:11 -0800
commiteba16b7ea42651e9e3d67cc643d67c870dd3fcc4 (patch)
treedbf0d63ef9f3699cba9ea1502c22f1061cbb2a78 /driver
parent6b63d866effc09a1e61bcf4e9d8413ac11c27fa8 (diff)
downloadchrome-ec-eba16b7ea42651e9e3d67cc643d67c870dd3fcc4.tar.gz
bq25710: Add support for Vbus measurement by ADC
This CL factors out some existing ADC code to bq25710_adc_start() and then use it to implement charger_get_vbus_voltage(). BUG=b:124968142 BRANCH=none TEST=verify VBUS measurement via 'ectool usbpdpower' Change-Id: Ifd3108d459bef02acd20d6a6959fd586fc3a9ca6 Signed-off-by: Philip Chen <philipchen@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1479876 Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com> Reviewed-by: Aseda Aboagye <aaboagye@chromium.org> Reviewed-by: Scott Collyer <scollyer@chromium.org>
Diffstat (limited to 'driver')
-rw-r--r--driver/charger/bq25710.c111
-rw-r--r--driver/charger/bq25710.h7
2 files changed, 83 insertions, 35 deletions
diff --git a/driver/charger/bq25710.c b/driver/charger/bq25710.c
index 1738904954..bbb05032bc 100644
--- a/driver/charger/bq25710.c
+++ b/driver/charger/bq25710.c
@@ -60,7 +60,8 @@ static inline int raw_write16(int offset, int value)
value);
}
-#ifdef CONFIG_CHARGE_RAMP_HW
+#if defined(CONFIG_CHARGE_RAMP_HW) || \
+ defined(CONFIG_USB_PD_VBUS_MEASURE_CHARGER)
static int bq25710_get_low_power_mode(int *mode)
{
int rv;
@@ -95,6 +96,50 @@ static int bq25710_set_low_power_mode(int enable)
return EC_SUCCESS;
}
+
+static int bq25710_adc_start(int adc_en_mask)
+{
+ int reg;
+ int mode;
+ int tries_left = 8;
+
+ /* Save current mode to restore same state after ADC read */
+ if (bq25710_get_low_power_mode(&mode))
+ return EC_ERROR_UNKNOWN;
+
+ /* Exit low power mode so ADC conversion takes typical time */
+ if (bq25710_set_low_power_mode(0))
+ return EC_ERROR_UNKNOWN;
+
+ /*
+ * Turn on the ADC for one reading. Note that adc_en_mask
+ * maps to bit[7:0] in ADCOption register.
+ */
+ reg = (adc_en_mask & BQ25710_ADC_OPTION_EN_ADC_ALL) |
+ BQ25710_ADC_OPTION_ADC_START;
+ if (raw_write16(BQ25710_REG_ADC_OPTION, reg))
+ return EC_ERROR_UNKNOWN;
+
+ /*
+ * Wait until the ADC operation completes. The spec says typical
+ * conversion time is 10 msec. If low power mode isn't exited first,
+ * then the conversion time jumps to ~60 msec.
+ */
+ do {
+ msleep(2);
+ raw_read16(BQ25710_REG_ADC_OPTION, &reg);
+ } while (--tries_left && (reg & BQ25710_ADC_OPTION_ADC_START));
+
+ /* ADC reading attempt complete, go back to low power mode */
+ if (bq25710_set_low_power_mode(mode))
+ return EC_ERROR_UNKNOWN;
+
+ /* Could not complete read */
+ if (reg & BQ25710_ADC_OPTION_ADC_START)
+ return EC_ERROR_TIMEOUT;
+
+ return EC_SUCCESS;
+}
#endif
/* Charger interfaces */
@@ -254,6 +299,30 @@ int charger_device_id(int *id)
return raw_read16(BQ25710_REG_DEVICE_ADDRESS, id);
}
+#ifdef CONFIG_USB_PD_VBUS_MEASURE_CHARGER
+int charger_get_vbus_voltage(int port)
+{
+ int reg, rv;
+
+ rv = bq25710_adc_start(BQ25710_ADC_OPTION_EN_ADC_VBUS);
+ if (rv)
+ goto error;
+
+ /* Read ADC value */
+ rv = raw_read16(BQ25710_REG_ADC_VBUS_PSYS, &reg);
+ if (rv)
+ goto error;
+
+ /* LSB => 64mV */
+ return (reg >> BQ25710_ADC_VBUS_STEP_BIT_OFFSET) *
+ BQ25710_ADC_VBUS_STEP_MV + BQ25710_ADC_VBUS_BASE_MV;
+
+error:
+ CPRINTF("Could not read VBUS ADC! Error: %d\n", rv);
+ return 0;
+}
+#endif
+
int charger_get_option(int *option)
{
/* There are 4 option registers, but we only need the first for now. */
@@ -339,43 +408,15 @@ int chg_ramp_is_stable(void)
int chg_ramp_get_current_limit(void)
{
- int reg;
- int mode;
- int tries_left = 8;
-
- /* Save current mode to restore same state after ADC read */
- if (bq25710_get_low_power_mode(&mode))
- goto error;
+ int reg, rv;
- /* Exit low power mode so ADC conversion takes typical time */
- if (bq25710_set_low_power_mode(0))
- goto error;
-
- /* Turn on the ADC for one reading */
- reg = BQ25710_ADC_OPTION_ADC_START | BQ25710_ADC_OPTION_EN_ADC_IIN;
- if (raw_write16(BQ25710_REG_ADC_OPTION, reg))
- goto error;
-
- /*
- * Wait until the ADC operation completes. The spec says typical
- * conversion time is 10 msec. If low power mode isn't exited first,
- * then the conversion time jumps to ~60 msec.
- */
- do {
- msleep(2);
- raw_read16(BQ25710_REG_ADC_OPTION, &reg);
- } while (--tries_left && (reg & BQ25710_ADC_OPTION_ADC_START));
-
- /* ADC reading attempt complete, go back to low power mode */
- if (bq25710_set_low_power_mode(mode))
- goto error;
-
- /* Could not complete read */
- if (reg & BQ25710_ADC_OPTION_ADC_START)
+ rv = bq25710_adc_start(BQ25710_ADC_OPTION_EN_ADC_IIN);
+ if (rv)
goto error;
/* Read ADC value */
- if (raw_read16(BQ25710_REG_ADC_CMPIN_IIN, &reg))
+ rv = raw_read16(BQ25710_REG_ADC_CMPIN_IIN, &reg);
+ if (rv)
goto error;
/* LSB => 50mA */
@@ -383,7 +424,7 @@ int chg_ramp_get_current_limit(void)
BQ25710_ADC_IIN_STEP_MA;
error:
- CPRINTF("Could not read input current limit ADC!\n");
+ CPRINTF("Could not read input current limit ADC! Error: %d\n", rv);
return 0;
}
#endif /* CONFIG_CHARGE_RAMP_HW */
diff --git a/driver/charger/bq25710.h b/driver/charger/bq25710.h
index 902ea17d82..faccfdec0d 100644
--- a/driver/charger/bq25710.h
+++ b/driver/charger/bq25710.h
@@ -58,7 +58,14 @@
/* ADCOption Register */
#define BQ25710_ADC_OPTION_ADC_START (1 << 14)
+#define BQ25710_ADC_OPTION_EN_ADC_VBUS (1 << 6)
#define BQ25710_ADC_OPTION_EN_ADC_IIN (1 << 4)
+#define BQ25710_ADC_OPTION_EN_ADC_ALL 0xFF
+
+/* ADCVBUS/PSYS Register */
+#define BQ25710_ADC_VBUS_STEP_MV 64
+#define BQ25710_ADC_VBUS_BASE_MV 3200
+#define BQ25710_ADC_VBUS_STEP_BIT_OFFSET 8
/* ADCIIN Register */
#define BQ25710_ADC_IIN_STEP_MA 50