From 347cdf228abe816a694204fa15b80dba2436073d Mon Sep 17 00:00:00 2001 From: Abhijeet Dharmapurikar Date: Thu, 23 Mar 2017 14:07:07 -0700 Subject: [PATCH] qcom: battery: update parallel algorithm for ICL change Update the parallel algorithm for ICL change request. Following steps are performed for every ICL change: - disable parallel charger using ICL_CHANGE_VOTER - update the new ICL and re-run AICL. - re-enable parallel charger by removing vote of ICL_CHANGE_VOTER. While at it, update the 'smblib_get_prop_usb_online' function to use voter library's locked API to get the usb_icl_vote, this fixes the lockup that happens when charging is enabled/disabled from usb_icl_votable's callback function. CRs-Fixed: 2014572 Change-Id: I7deb6a50d67471ab1aa5e1db6fff880574b4bafb Signed-off-by: Ashay Jaiswal Signed-off-by: Abhijeet Dharmapurikar --- drivers/power/supply/qcom/battery.c | 42 ++++++++++++++++++++++++++--- drivers/power/supply/qcom/smb-lib.c | 2 +- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c index 4d18a48f56ee..53e6a4138f04 100644 --- a/drivers/power/supply/qcom/battery.c +++ b/drivers/power/supply/qcom/battery.c @@ -13,6 +13,7 @@ #define pr_fmt(fmt) "QCOM-BATT: %s: " fmt, __func__ #include +#include #include #include #include @@ -36,6 +37,7 @@ #define PL_HW_ABSENT_VOTER "PL_HW_ABSENT_VOTER" #define PL_VOTER "PL_VOTER" #define RESTRICT_CHG_VOTER "RESTRICT_CHG_VOTER" +#define ICL_CHANGE_VOTER "ICL_CHANGE_VOTER" struct pl_data { int pl_mode; @@ -505,9 +507,11 @@ static int pl_fv_vote_callback(struct votable *votable, void *data, return 0; } +#define ICL_STEP_UV 25000 static int usb_icl_vote_callback(struct votable *votable, void *data, int icl_ua, const char *client) { + int rc; struct pl_data *chip = data; union power_supply_propval pval = {0, }; @@ -517,9 +521,41 @@ static int usb_icl_vote_callback(struct votable *votable, void *data, if (client == NULL) icl_ua = INT_MAX; - pval.intval = icl_ua; - return power_supply_set_property(chip->main_psy, - POWER_SUPPLY_PROP_INPUT_CURRENT_MAX, &pval); + /* + * Disable parallel for new ICL vote - the call to split_settled will + * ensure that all the input current limit gets assigned to the main + * charger. + */ + vote(chip->pl_disable_votable, ICL_CHANGE_VOTER, true, 0); + + /* rerun AICL */ + /* get the settled current */ + 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 rc; + } + + /* rerun AICL if new ICL is above settled ICL */ + if (icl_ua > pval.intval) { + /* set a lower ICL */ + pval.intval = max(pval.intval - ICL_STEP_UV, ICL_STEP_UV); + power_supply_set_property(chip->main_psy, + POWER_SUPPLY_PROP_CURRENT_MAX, + &pval); + /* wait for ICL change */ + msleep(100); + + pval.intval = icl_ua; + power_supply_set_property(chip->main_psy, + POWER_SUPPLY_PROP_CURRENT_MAX, + &pval); + /* wait for ICL change */ + msleep(100); + } + vote(chip->pl_disable_votable, ICL_CHANGE_VOTER, false, 0); return 0; } diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c index cf16d9082466..3d6503c42e2f 100644 --- a/drivers/power/supply/qcom/smb-lib.c +++ b/drivers/power/supply/qcom/smb-lib.c @@ -2019,7 +2019,7 @@ int smblib_get_prop_usb_online(struct smb_charger *chg, int rc = 0; u8 stat; - if (get_client_vote(chg->usb_icl_votable, USER_VOTER) == 0) { + if (get_client_vote_locked(chg->usb_icl_votable, USER_VOTER) == 0) { val->intval = false; return rc; }