diff options
| author | Linux Build Service Account <lnxbuild@quicinc.com> | 2017-05-20 01:37:19 -0700 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-05-20 01:37:19 -0700 |
| commit | 60be71604a84d2e047215cb702d6324379a353bb (patch) | |
| tree | 7d40b7eb8889bee054c774abe322731679ffdc15 | |
| parent | 474a2a48ad5786b6e0bb154e3c85db1a765f7bd8 (diff) | |
| parent | db1755be6c5b8754c8cac5de2c8d69d6860531c4 (diff) | |
Merge "qpnp-smb2: fix FV and FCC reporting"
| -rw-r--r-- | drivers/power/supply/qcom/battery.c | 101 | ||||
| -rw-r--r-- | drivers/power/supply/qcom/qpnp-smb2.c | 5 | ||||
| -rw-r--r-- | drivers/power/supply/qcom/smb-lib.c | 41 | ||||
| -rw-r--r-- | drivers/power/supply/qcom/smb-lib.h | 3 |
4 files changed, 105 insertions, 45 deletions
diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c index 98d75f586b67..8b4067b17103 100644 --- a/drivers/power/supply/qcom/battery.c +++ b/drivers/power/supply/qcom/battery.c @@ -38,6 +38,8 @@ #define PL_VOTER "PL_VOTER" #define RESTRICT_CHG_VOTER "RESTRICT_CHG_VOTER" #define ICL_CHANGE_VOTER "ICL_CHANGE_VOTER" +#define PL_INDIRECT_VOTER "PL_INDIRECT_VOTER" +#define USBIN_I_VOTER "USBIN_I_VOTER" struct pl_data { int pl_mode; @@ -52,7 +54,8 @@ struct pl_data { struct votable *pl_awake_votable; struct votable *hvdcp_hw_inov_dis_votable; struct votable *usb_icl_votable; - struct work_struct status_change_work; + struct votable *pl_enable_votable_indirect; + struct delayed_work status_change_work; struct work_struct pl_disable_forever_work; struct delayed_work pl_taper_work; struct power_supply *main_psy; @@ -490,6 +493,7 @@ static int pl_fv_vote_callback(struct votable *votable, void *data, } #define ICL_STEP_UA 25000 +#define PL_DELAY_MS 3000 static int usb_icl_vote_callback(struct votable *votable, void *data, int icl_ua, const char *client) { @@ -511,6 +515,21 @@ static int usb_icl_vote_callback(struct votable *votable, void *data, */ vote(chip->pl_disable_votable, ICL_CHANGE_VOTER, true, 0); + /* + * if (ICL < 1400) + * disable parallel charger using USBIN_I_VOTER + * else + * instead of re-enabling here rely on status_changed_work + * (triggered via AICL completed or scheduled from here to + * unvote USBIN_I_VOTER) the status_changed_work enables + * USBIN_I_VOTER based on settled current. + */ + if (icl_ua <= 1400000) + vote(chip->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0); + else + schedule_delayed_work(&chip->status_change_work, + msecs_to_jiffies(PL_DELAY_MS)); + /* rerun AICL */ /* get the settled current */ rc = power_supply_get_property(chip->main_psy, @@ -642,6 +661,16 @@ static int pl_disable_vote_callback(struct votable *votable, return 0; } +static int pl_enable_indirect_vote_callback(struct votable *votable, + void *data, int pl_enable, const char *client) +{ + struct pl_data *chip = data; + + vote(chip->pl_disable_votable, PL_INDIRECT_VOTER, !pl_enable, 0); + + return 0; +} + static int pl_awake_vote_callback(struct votable *votable, void *data, int awake, const char *client) { @@ -774,6 +803,42 @@ static void handle_settled_icl_change(struct pl_data *chip) union power_supply_propval pval = {0, }; int new_total_settled_ua; int rc; + int main_settled_ua; + int main_limited; + int total_current_ua; + + total_current_ua = get_effective_result_locked(chip->usb_icl_votable); + + /* + * call aicl split only when USBIN_USBIN and enabled + * and if aicl changed + */ + rc = power_supply_get_property(chip->main_psy, + POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED, + &pval); + if (rc < 0) { + pr_err("Couldn't get aicl settled value rc=%d\n", rc); + return; + } + main_settled_ua = pval.intval; + + rc = power_supply_get_property(chip->batt_psy, + POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED, + &pval); + if (rc < 0) { + pr_err("Couldn't get aicl settled value rc=%d\n", rc); + return; + } + main_limited = pval.intval; + + if ((main_limited && (main_settled_ua + chip->pl_settled_ua) < 1400000) + || (main_settled_ua == 0) + || ((total_current_ua >= 0) && + (total_current_ua <= 1400000))) + vote(chip->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0); + else + vote(chip->pl_enable_votable_indirect, USBIN_I_VOTER, true, 0); + if (get_effective_result(chip->pl_disable_votable)) return; @@ -782,17 +847,10 @@ static void handle_settled_icl_change(struct pl_data *chip) || chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN_EXT) { /* * call aicl split only when USBIN_USBIN and enabled - * and if aicl changed + * and if settled current has changed by more than 300mA */ - rc = power_supply_get_property(chip->main_psy, - POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED, - &pval); - if (rc < 0) { - pr_err("Couldn't get aicl settled value rc=%d\n", rc); - return; - } - new_total_settled_ua = pval.intval + chip->pl_settled_ua; + new_total_settled_ua = main_settled_ua + chip->pl_settled_ua; pl_dbg(chip, PR_PARALLEL, "total_settled_ua=%d settled_ua=%d new_total_settled_ua=%d\n", chip->total_settled_ua, pval.intval, @@ -839,7 +897,7 @@ static void handle_parallel_in_taper(struct pl_data *chip) static void status_change_work(struct work_struct *work) { struct pl_data *chip = container_of(work, - struct pl_data, status_change_work); + struct pl_data, status_change_work.work); if (!chip->main_psy && is_main_available(chip)) { /* @@ -877,7 +935,7 @@ static int pl_notifier_call(struct notifier_block *nb, if ((strcmp(psy->desc->name, "parallel") == 0) || (strcmp(psy->desc->name, "battery") == 0) || (strcmp(psy->desc->name, "main") == 0)) - schedule_work(&chip->status_change_work); + schedule_delayed_work(&chip->status_change_work, 0); return NOTIFY_OK; } @@ -898,7 +956,7 @@ static int pl_register_notifier(struct pl_data *chip) static int pl_determine_initial_status(struct pl_data *chip) { - status_change_work(&chip->status_change_work); + status_change_work(&chip->status_change_work.work); return 0; } @@ -967,7 +1025,18 @@ int qcom_batt_init(void) goto destroy_votable; } - INIT_WORK(&chip->status_change_work, status_change_work); + chip->pl_enable_votable_indirect = create_votable("PL_ENABLE_INDIRECT", + VOTE_SET_ANY, + pl_enable_indirect_vote_callback, + chip); + if (IS_ERR(chip->pl_enable_votable_indirect)) { + rc = PTR_ERR(chip->pl_enable_votable_indirect); + return rc; + } + + vote(chip->pl_disable_votable, PL_INDIRECT_VOTER, true, 0); + + INIT_DELAYED_WORK(&chip->status_change_work, status_change_work); INIT_DELAYED_WORK(&chip->pl_taper_work, pl_taper_work); INIT_WORK(&chip->pl_disable_forever_work, pl_disable_forever_work); @@ -1000,6 +1069,7 @@ int qcom_batt_init(void) unreg_notifier: power_supply_unreg_notifier(&chip->nb); destroy_votable: + destroy_votable(chip->pl_enable_votable_indirect); destroy_votable(chip->pl_awake_votable); destroy_votable(chip->pl_disable_votable); destroy_votable(chip->fv_votable); @@ -1019,11 +1089,12 @@ void qcom_batt_deinit(void) if (chip == NULL) return; - cancel_work_sync(&chip->status_change_work); + cancel_delayed_work_sync(&chip->status_change_work); cancel_delayed_work_sync(&chip->pl_taper_work); cancel_work_sync(&chip->pl_disable_forever_work); power_supply_unreg_notifier(&chip->nb); + destroy_votable(chip->pl_enable_votable_indirect); destroy_votable(chip->pl_awake_votable); destroy_votable(chip->pl_disable_votable); destroy_votable(chip->fv_votable); diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c index b2597987292b..6bdf64433162 100644 --- a/drivers/power/supply/qcom/qpnp-smb2.c +++ b/drivers/power/supply/qcom/qpnp-smb2.c @@ -1046,7 +1046,8 @@ static int smb2_batt_get_prop(struct power_supply *psy, rc = smblib_get_prop_batt_voltage_now(chg, val); break; case POWER_SUPPLY_PROP_VOLTAGE_MAX: - val->intval = get_client_vote(chg->fv_votable, DEFAULT_VOTER); + val->intval = get_client_vote(chg->fv_votable, + BATT_PROFILE_VOTER); break; case POWER_SUPPLY_PROP_CHARGE_QNOVO_ENABLE: rc = smblib_get_prop_charge_qnovo_enable(chg, val); @@ -1064,7 +1065,7 @@ static int smb2_batt_get_prop(struct power_supply *psy, break; case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: val->intval = get_client_vote(chg->fcc_votable, - DEFAULT_VOTER); + BATT_PROFILE_VOTER); break; case POWER_SUPPLY_PROP_TEMP: rc = smblib_get_prop_batt_temp(chg, val); diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c index cc50e0f478d1..5a2af79eb568 100644 --- a/drivers/power/supply/qcom/smb-lib.c +++ b/drivers/power/supply/qcom/smb-lib.c @@ -1047,16 +1047,6 @@ static int smblib_chg_disable_vote_callback(struct votable *votable, void *data, return 0; } -static int smblib_pl_enable_indirect_vote_callback(struct votable *votable, - void *data, int chg_enable, const char *client) -{ - struct smb_charger *chg = data; - - vote(chg->pl_disable_votable, PL_INDIRECT_VOTER, !chg_enable, 0); - - return 0; -} - static int smblib_hvdcp_enable_vote_callback(struct votable *votable, void *data, int hvdcp_enable, const char *client) @@ -1652,6 +1642,7 @@ int smblib_get_prop_batt_health(struct smb_charger *chg, { union power_supply_propval pval; int rc; + int effective_fv_uv; u8 stat; rc = smblib_read(chg, BATTERY_CHARGER_STATUS_2_REG, &stat); @@ -1670,10 +1661,11 @@ int smblib_get_prop_batt_health(struct smb_charger *chg, * If Vbatt is within 40mV above Vfloat, then don't * treat it as overvoltage. */ - if (pval.intval >= - get_effective_result(chg->fv_votable) + 40000) { + effective_fv_uv = get_effective_result(chg->fv_votable); + if (pval.intval >= effective_fv_uv + 40000) { val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; - smblib_err(chg, "battery over-voltage\n"); + smblib_err(chg, "battery over-voltage vbat_fg = %duV, fv = %duV\n", + pval.intval, effective_fv_uv); goto done; } } @@ -4218,8 +4210,6 @@ static void smblib_icl_change_work(struct work_struct *work) } power_supply_changed(chg->usb_main_psy); - vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER, - settled_ua >= USB_WEAK_INPUT_UA, 0); smblib_dbg(chg, PR_INTERRUPT, "icl_settled=%d\n", settled_ua); } @@ -4315,7 +4305,16 @@ static int smblib_create_votables(struct smb_charger *chg) smblib_err(chg, "Couldn't find votable PL_DISABLE rc=%d\n", rc); return rc; } - vote(chg->pl_disable_votable, PL_INDIRECT_VOTER, true, 0); + + chg->pl_enable_votable_indirect = find_votable("PL_ENABLE_INDIRECT"); + if (chg->pl_enable_votable_indirect == NULL) { + rc = -EINVAL; + smblib_err(chg, + "Couldn't find votable PL_ENABLE_INDIRECT rc=%d\n", + rc); + return rc; + } + vote(chg->pl_disable_votable, PL_DELAY_VOTER, true, 0); chg->dc_suspend_votable = create_votable("DC_SUSPEND", VOTE_SET_ANY, @@ -4365,14 +4364,6 @@ static int smblib_create_votables(struct smb_charger *chg) return rc; } - chg->pl_enable_votable_indirect = create_votable("PL_ENABLE_INDIRECT", - VOTE_SET_ANY, - smblib_pl_enable_indirect_vote_callback, - chg); - if (IS_ERR(chg->pl_enable_votable_indirect)) { - rc = PTR_ERR(chg->pl_enable_votable_indirect); - return rc; - } chg->hvdcp_disable_votable_indirect = create_votable( "HVDCP_DISABLE_INDIRECT", @@ -4448,8 +4439,6 @@ static void smblib_destroy_votables(struct smb_charger *chg) destroy_votable(chg->awake_votable); if (chg->chg_disable_votable) destroy_votable(chg->chg_disable_votable); - if (chg->pl_enable_votable_indirect) - destroy_votable(chg->pl_enable_votable_indirect); if (chg->apsd_disable_votable) destroy_votable(chg->apsd_disable_votable); if (chg->hvdcp_hw_inov_dis_votable) diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h index 3fedff8897ee..00d144e9d6a0 100644 --- a/drivers/power/supply/qcom/smb-lib.h +++ b/drivers/power/supply/qcom/smb-lib.h @@ -36,9 +36,7 @@ enum print_reason { #define PL_USBIN_USBIN_VOTER "PL_USBIN_USBIN_VOTER" #define USB_PSY_VOTER "USB_PSY_VOTER" #define PL_TAPER_WORK_RUNNING_VOTER "PL_TAPER_WORK_RUNNING_VOTER" -#define PL_INDIRECT_VOTER "PL_INDIRECT_VOTER" #define PL_QNOVO_VOTER "PL_QNOVO_VOTER" -#define USBIN_I_VOTER "USBIN_I_VOTER" #define USBIN_V_VOTER "USBIN_V_VOTER" #define CHG_STATE_VOTER "CHG_STATE_VOTER" #define TYPEC_SRC_VOTER "TYPEC_SRC_VOTER" @@ -65,6 +63,7 @@ enum print_reason { #define QNOVO_VOTER "QNOVO_VOTER" #define BATT_PROFILE_VOTER "BATT_PROFILE_VOTER" #define OTG_DELAY_VOTER "OTG_DELAY_VOTER" +#define USBIN_I_VOTER "USBIN_I_VOTER" #define VCONN_MAX_ATTEMPTS 3 #define OTG_MAX_ATTEMPTS 3 |
