diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h index 88dcdd8fd7be..606d9a6d7bf7 100644 --- a/drivers/power/supply/qcom/fg-core.h +++ b/drivers/power/supply/qcom/fg-core.h @@ -104,7 +104,7 @@ enum sram_access_flags { }; /* JEITA */ -enum { +enum jeita_levels { JEITA_COLD = 0, JEITA_COOL, JEITA_WARM, diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c index ab6c9b9d925f..2c064047215a 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen3.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c @@ -576,6 +576,41 @@ static int fg_get_charge_counter(struct fg_chip *chip, int *val) return 0; } +static int fg_get_jeita_threshold(struct fg_chip *chip, + enum jeita_levels level, int *temp_decidegC) +{ + int rc; + u8 val; + u16 reg; + + switch (level) { + case JEITA_COLD: + reg = BATT_INFO_JEITA_TOO_COLD(chip); + break; + case JEITA_COOL: + reg = BATT_INFO_JEITA_COLD(chip); + break; + case JEITA_WARM: + reg = BATT_INFO_JEITA_HOT(chip); + break; + case JEITA_HOT: + reg = BATT_INFO_JEITA_TOO_HOT(chip); + break; + default: + return -EINVAL; + } + + rc = fg_read(chip, reg, &val, 1); + if (rc < 0) { + pr_err("Error in reading jeita level %d, rc=%d\n", level, rc); + return rc; + } + + /* Resolution is 0.5C. Base is -30C. */ + *temp_decidegC = (((5 * val) / 10) - 30) * 10; + return 0; +} + #define BATT_TEMP_NUMR 1 #define BATT_TEMP_DENR 1 static int fg_get_battery_temp(struct fg_chip *chip, int *val) @@ -978,12 +1013,6 @@ static int fg_get_batt_profile(struct fg_chip *chip) return 0; } -static inline void get_temp_setpoint(int threshold, u8 *val) -{ - /* Resolution is 0.5C. Base is -30C. */ - *val = DIV_ROUND_CLOSEST((threshold + 30) * 10, 5); -} - static inline void get_batt_temp_delta(int delta, u8 *val) { switch (delta) { @@ -1863,6 +1892,44 @@ static int fg_rconn_config(struct fg_chip *chip) return 0; } +static int fg_set_jeita_threshold(struct fg_chip *chip, + enum jeita_levels level, int temp_decidegC) +{ + int rc; + u8 val; + u16 reg; + + if (temp_decidegC < -300 || temp_decidegC > 970) + return -EINVAL; + + /* Resolution is 0.5C. Base is -30C. */ + val = DIV_ROUND_CLOSEST(((temp_decidegC / 10) + 30) * 10, 5); + switch (level) { + case JEITA_COLD: + reg = BATT_INFO_JEITA_TOO_COLD(chip); + break; + case JEITA_COOL: + reg = BATT_INFO_JEITA_COLD(chip); + break; + case JEITA_WARM: + reg = BATT_INFO_JEITA_HOT(chip); + break; + case JEITA_HOT: + reg = BATT_INFO_JEITA_TOO_HOT(chip); + break; + default: + return -EINVAL; + } + + rc = fg_write(chip, reg, &val, 1); + if (rc < 0) { + pr_err("Error in setting jeita level %d, rc=%d\n", level, rc); + return rc; + } + + return 0; +} + static int fg_set_constant_chg_voltage(struct fg_chip *chip, int volt_uv) { u8 buf[2]; @@ -3377,6 +3444,34 @@ static int fg_psy_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_TEMP: rc = fg_get_battery_temp(chip, &pval->intval); break; + case POWER_SUPPLY_PROP_COLD_TEMP: + rc = fg_get_jeita_threshold(chip, JEITA_COLD, &pval->intval); + if (rc < 0) { + pr_err("Error in reading jeita_cold, rc=%d\n", rc); + return rc; + } + break; + case POWER_SUPPLY_PROP_COOL_TEMP: + rc = fg_get_jeita_threshold(chip, JEITA_COOL, &pval->intval); + if (rc < 0) { + pr_err("Error in reading jeita_cool, rc=%d\n", rc); + return rc; + } + break; + case POWER_SUPPLY_PROP_WARM_TEMP: + rc = fg_get_jeita_threshold(chip, JEITA_WARM, &pval->intval); + if (rc < 0) { + pr_err("Error in reading jeita_warm, rc=%d\n", rc); + return rc; + } + break; + case POWER_SUPPLY_PROP_HOT_TEMP: + rc = fg_get_jeita_threshold(chip, JEITA_HOT, &pval->intval); + if (rc < 0) { + pr_err("Error in reading jeita_hot, rc=%d\n", rc); + return rc; + } + break; case POWER_SUPPLY_PROP_RESISTANCE: rc = fg_get_battery_resistance(chip, &pval->intval); break; @@ -3514,6 +3609,34 @@ static int fg_psy_set_property(struct power_supply *psy, if (rc < 0) pr_err("Error in saving learned_cc_uah, rc=%d\n", rc); break; + case POWER_SUPPLY_PROP_COLD_TEMP: + rc = fg_set_jeita_threshold(chip, JEITA_COLD, pval->intval); + if (rc < 0) { + pr_err("Error in writing jeita_cold, rc=%d\n", rc); + return rc; + } + break; + case POWER_SUPPLY_PROP_COOL_TEMP: + rc = fg_set_jeita_threshold(chip, JEITA_COOL, pval->intval); + if (rc < 0) { + pr_err("Error in writing jeita_cool, rc=%d\n", rc); + return rc; + } + break; + case POWER_SUPPLY_PROP_WARM_TEMP: + rc = fg_set_jeita_threshold(chip, JEITA_WARM, pval->intval); + if (rc < 0) { + pr_err("Error in writing jeita_warm, rc=%d\n", rc); + return rc; + } + break; + case POWER_SUPPLY_PROP_HOT_TEMP: + rc = fg_set_jeita_threshold(chip, JEITA_HOT, pval->intval); + if (rc < 0) { + pr_err("Error in writing jeita_hot, rc=%d\n", rc); + return rc; + } + break; default: break; } @@ -3530,6 +3653,10 @@ static int fg_property_is_writeable(struct power_supply *psy, case POWER_SUPPLY_PROP_CC_STEP: case POWER_SUPPLY_PROP_CC_STEP_SEL: case POWER_SUPPLY_PROP_CHARGE_FULL: + case POWER_SUPPLY_PROP_COLD_TEMP: + case POWER_SUPPLY_PROP_COOL_TEMP: + case POWER_SUPPLY_PROP_WARM_TEMP: + case POWER_SUPPLY_PROP_HOT_TEMP: return 1; default: break; @@ -3571,6 +3698,10 @@ static int fg_notifier_cb(struct notifier_block *nb, static enum power_supply_property fg_psy_props[] = { POWER_SUPPLY_PROP_CAPACITY, POWER_SUPPLY_PROP_TEMP, + POWER_SUPPLY_PROP_COLD_TEMP, + POWER_SUPPLY_PROP_COOL_TEMP, + POWER_SUPPLY_PROP_WARM_TEMP, + POWER_SUPPLY_PROP_HOT_TEMP, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_VOLTAGE_OCV, POWER_SUPPLY_PROP_CURRENT_NOW, @@ -3749,29 +3880,29 @@ static int fg_hw_init(struct fg_chip *chip) } } - get_temp_setpoint(chip->dt.jeita_thresholds[JEITA_COLD], &val); - rc = fg_write(chip, BATT_INFO_JEITA_TOO_COLD(chip), &val, 1); + rc = fg_set_jeita_threshold(chip, JEITA_COLD, + chip->dt.jeita_thresholds[JEITA_COLD] * 10); if (rc < 0) { pr_err("Error in writing jeita_cold, rc=%d\n", rc); return rc; } - get_temp_setpoint(chip->dt.jeita_thresholds[JEITA_COOL], &val); - rc = fg_write(chip, BATT_INFO_JEITA_COLD(chip), &val, 1); + rc = fg_set_jeita_threshold(chip, JEITA_COOL, + chip->dt.jeita_thresholds[JEITA_COOL] * 10); if (rc < 0) { pr_err("Error in writing jeita_cool, rc=%d\n", rc); return rc; } - get_temp_setpoint(chip->dt.jeita_thresholds[JEITA_WARM], &val); - rc = fg_write(chip, BATT_INFO_JEITA_HOT(chip), &val, 1); + rc = fg_set_jeita_threshold(chip, JEITA_WARM, + chip->dt.jeita_thresholds[JEITA_WARM] * 10); if (rc < 0) { pr_err("Error in writing jeita_warm, rc=%d\n", rc); return rc; } - get_temp_setpoint(chip->dt.jeita_thresholds[JEITA_HOT], &val); - rc = fg_write(chip, BATT_INFO_JEITA_TOO_HOT(chip), &val, 1); + rc = fg_set_jeita_threshold(chip, JEITA_HOT, + chip->dt.jeita_thresholds[JEITA_HOT] * 10); if (rc < 0) { pr_err("Error in writing jeita_hot, rc=%d\n", rc); return rc;