diff options
author | Philip Chen <philipchen@chromium.org> | 2019-02-20 16:57:49 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2019-03-01 01:09:11 -0800 |
commit | eba16b7ea42651e9e3d67cc643d67c870dd3fcc4 (patch) | |
tree | dbf0d63ef9f3699cba9ea1502c22f1061cbb2a78 | |
parent | 6b63d866effc09a1e61bcf4e9d8413ac11c27fa8 (diff) | |
download | chrome-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>
-rw-r--r-- | driver/charger/bq25710.c | 111 | ||||
-rw-r--r-- | driver/charger/bq25710.h | 7 |
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, ®); + } 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, ®); + 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, ®); - } 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, ®)) + rv = raw_read16(BQ25710_REG_ADC_CMPIN_IIN, ®); + 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 |