diff options
-rw-r--r-- | driver/charger/rt946x.c | 71 |
1 files changed, 63 insertions, 8 deletions
diff --git a/driver/charger/rt946x.c b/driver/charger/rt946x.c index 589dda1960..342aa704f7 100644 --- a/driver/charger/rt946x.c +++ b/driver/charger/rt946x.c @@ -263,6 +263,21 @@ static inline uint8_t rt946x_closest_reg(uint16_t min, uint16_t max, return (target - min) / step; } +static int rt946x_get_ieoc(uint32_t *ieoc) +{ + int ret, reg_ieoc; + + ret = rt946x_read8(RT946X_REG_CHGCTRL9, ®_ieoc); + if (ret) + return ret; + + *ieoc = RT946X_IEOC_MIN + + RT946X_IEOC_STEP * + ((reg_ieoc & RT946X_MASK_IEOC) >> RT946X_SHIFT_IEOC); + + return EC_SUCCESS; +} + #ifdef CONFIG_CHARGER_MT6370 static int mt6370_enable_hidden_mode(int en) { @@ -382,15 +397,15 @@ static int rt946x_enable_bc12_detection(int en) static int rt946x_set_ieoc(unsigned int ieoc) { - uint8_t reg_ieoc = 0; + uint8_t reg_ieoc; reg_ieoc = rt946x_closest_reg(RT946X_IEOC_MIN, RT946X_IEOC_MAX, - RT946X_IEOC_STEP, ieoc); + RT946X_IEOC_STEP, ieoc); CPRINTF("%s ieoc = %d(0x%02X)\n", __func__, ieoc, reg_ieoc); return rt946x_update_bits(RT946X_REG_CHGCTRL9, RT946X_MASK_IEOC, - reg_ieoc << RT946X_SHIFT_IEOC); + reg_ieoc << RT946X_SHIFT_IEOC); } static int rt946x_set_mivr(unsigned int mivr) @@ -757,14 +772,54 @@ int charger_get_current(int *current) int charger_set_current(int current) { - uint8_t reg_icc = 0; - const struct charger_info * const info = charger_get_info(); + int rv; + uint8_t reg_icc; + static int workaround; + const struct charger_info *const info = charger_get_info(); + + /* + * mt6370's minimun regulated current is 500mA REG17[7:2] 0b100, + * values below 0b100 are preserved. + */ + if (IS_ENABLED(CONFIG_CHARGER_MT6370)) + current = MAX(500, current); + reg_icc = rt946x_closest_reg(info->current_min, info->current_max, - info->current_step, current); + info->current_step, current); + + rv = rt946x_update_bits(RT946X_REG_CHGCTRL7, RT946X_MASK_ICHG, + reg_icc << RT946X_SHIFT_ICHG); + if (rv) + return rv; + + if (IS_ENABLED(CONFIG_CHARGER_RT9466) || + IS_ENABLED(CONFIG_CHARGER_MT6370)) { + uint32_t curr_ieoc; + + /* + * workaround to make IEOC accurate: + * witht normal charging (ICC >= 900mA), the power path is fully + * turned on. But at low charging current state (ICC < 900mA), + * the power path will only be partially turned on. So under + * such situation, the IEOC is inaccurate. + */ + rv = rt946x_get_ieoc(&curr_ieoc); + if (rv) + return rv; + + if (current < 900 && !workaround) { + /* raise IEOC if charge current is under 900 */ + rv = rt946x_set_ieoc(curr_ieoc + 100); + workaround = 1; + } else if (current >= 900 && workaround) { + /* reset IEOC if charge current is above 900 */ + workaround = 0; + rv = rt946x_set_ieoc(curr_ieoc - 100); + } + } - return rt946x_update_bits(RT946X_REG_CHGCTRL7, RT946X_MASK_ICHG, - reg_icc << RT946X_SHIFT_ICHG); + return rv; } int charger_get_voltage(int *voltage) |