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>
This commit is contained in:
Abhijeet Dharmapurikar 2017-03-23 14:07:07 -07:00 committed by Ashay Jaiswal
parent 69d321dcee
commit 347cdf228a
2 changed files with 40 additions and 4 deletions

View file

@ -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;
}

View file

@ -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;
}