summaryrefslogtreecommitdiff
path: root/drivers/power
diff options
context:
space:
mode:
authorAbhijeet Dharmapurikar <adharmap@codeaurora.org>2017-03-23 14:07:07 -0700
committerAshay Jaiswal <ashayj@codeaurora.org>2017-04-05 10:19:20 +0530
commit347cdf228abe816a694204fa15b80dba2436073d (patch)
tree76855961c112b26a792f4a3dacec7f6f3c30103f /drivers/power
parent69d321dceeeb492e645d100906f54ac492330089 (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.c42
-rw-r--r--drivers/power/supply/qcom/smb-lib.c2
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;
}