OSDN Git Service

power: qpnp-fg-gen3: support JEITA thresholds configurable runtime
authorSubbaraman Narayanamurthy <subbaram@codeaurora.org>
Sat, 12 Aug 2017 02:24:24 +0000 (19:24 -0700)
committerSubbaraman Narayanamurthy <subbaram@codeaurora.org>
Fri, 1 Sep 2017 02:25:33 +0000 (19:25 -0700)
Currently, JEITA thresholds are configured through the device
tree properties. Allow them to be configured runtime through
power supply properties.

Change-Id: Ie93c7e447a4f8ac793e6e324f7a0269dbc14c7e5
Signed-off-by: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
drivers/power/supply/qcom/fg-core.h
drivers/power/supply/qcom/qpnp-fg-gen3.c

index 88dcdd8..606d9a6 100644 (file)
@@ -104,7 +104,7 @@ enum sram_access_flags {
 };
 
 /* JEITA */
-enum {
+enum jeita_levels {
        JEITA_COLD = 0,
        JEITA_COOL,
        JEITA_WARM,
index ab6c9b9..2c06404 100644 (file)
@@ -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;