diff --git a/driver/charger/bq25703.c b/driver/charger/bq25703.c index 4a80f21e40..0054168a59 100644 --- a/driver/charger/bq25703.c +++ b/driver/charger/bq25703.c @@ -64,6 +64,40 @@ static inline int raw_write16(int offset, int value) return i2c_write16(I2C_PORT_CHARGER, BQ25703_I2C_ADDR1, offset, value); } +static int bq25703_get_low_power_mode(int *mode) +{ + int rv; + int reg; + + rv = raw_read16(BQ25703_REG_CHARGE_OPTION_0, ®); + if (rv) + return rv; + + *mode = !!(reg & BQ25703_CHARGE_OPTION_0_LOW_POWER_MODE); + + return EC_SUCCESS; +} + +static int bq25703_set_low_power_mode(int enable) +{ + int rv; + int reg; + + rv = raw_read16(BQ25703_REG_CHARGE_OPTION_0, ®); + if (rv) + return rv; + + if (enable) + reg |= BQ25703_CHARGE_OPTION_0_LOW_POWER_MODE; + else + reg &= ~BQ25703_CHARGE_OPTION_0_LOW_POWER_MODE; + + rv = raw_write16(BQ25703_REG_CHARGE_OPTION_0, reg); + if (rv) + return rv; + + return EC_SUCCESS; +} /* Charger interfaces */ @@ -257,19 +291,36 @@ int chg_ramp_is_detected(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 (bq25703_get_low_power_mode(&mode)) + goto error; + + /* Exit low power mode so ADC conversion takes typical time */ + if (bq25703_set_low_power_mode(0)) + goto error; + /* Turn on the ADC for one reading */ reg = BQ25703_ADC_OPTION_ADC_START | BQ25703_ADC_OPTION_EN_ADC_IIN; if (raw_write16(BQ25703_REG_ADC_OPTION, reg)) goto error; - /* Wait until the ADC operation completes. Typically 10ms */ + /* + * 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(BQ25703_REG_ADC_OPTION, ®); } while (--tries_left && (reg & BQ25703_ADC_OPTION_ADC_START)); + /* ADC reading attempt complete, go back to low power mode */ + if (bq25703_set_low_power_mode(mode)) + goto error; + /* Could not complete read */ if (reg & BQ25703_ADC_OPTION_ADC_START) goto error; @@ -282,7 +333,7 @@ int chg_ramp_get_current_limit(void) return reg * BQ25703_ADC_IIN_STEP_MA; error: - CPRINTF("Could not read input current limit ADC!"); + CPRINTF("Could not read input current limit ADC!\n"); return 0; } #endif /* CONFIG_CHARGE_RAMP_HW */ diff --git a/driver/charger/bq25703.h b/driver/charger/bq25703.h index ecb6131511..db7e50df52 100644 --- a/driver/charger/bq25703.h +++ b/driver/charger/bq25703.h @@ -39,6 +39,7 @@ #define BQ25703_REG_DEVICE_ADDRESS 0x2F /* ChargeOption0 Register */ +#define BQ25703_CHARGE_OPTION_0_LOW_POWER_MODE (1 << 15) #define BQ25703_CHARGE_OPTION_0_EN_LEARN (1 << 5) #define BQ25703_CHARGE_OPTION_0_CHRG_INHIBIT (1 << 0)