diff options
author | Abhijeet Dharmapurikar <adharmap@codeaurora.org> | 2017-03-23 14:07:07 -0700 |
---|---|---|
committer | Ashay Jaiswal <ashayj@codeaurora.org> | 2017-04-05 10:19:20 +0530 |
commit | 347cdf228abe816a694204fa15b80dba2436073d (patch) | |
tree | 76855961c112b26a792f4a3dacec7f6f3c30103f /drivers/power | |
parent | 69d321dceeeb492e645d100906f54ac492330089 (diff) |
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 <ashayj@codeaurora.org>
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/supply/qcom/battery.c | 42 | ||||
-rw-r--r-- | 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 <linux/device.h> +#include <linux/delay.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/regmap.h> @@ -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; } |