power: qpnp-fg-gen3: support JEITA thresholds configurable runtime

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>
This commit is contained in:
Subbaraman Narayanamurthy 2017-08-11 19:24:24 -07:00
parent 063d7870ec
commit 2f006f97f5
2 changed files with 146 additions and 15 deletions

View file

@ -104,7 +104,7 @@ enum sram_access_flags {
};
/* JEITA */
enum {
enum jeita_levels {
JEITA_COLD = 0,
JEITA_COOL,
JEITA_WARM,

View 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;