power: qcom-charger: add support for USBIN-USBIN parallel configuration

Add support for USBIN-USBIN configuration based parallel charging. This
involves splitting Input Current Limit(ICL) between the main and the
parallel charger, ICL re-split is done when the settled AICL of the main
charger changes by 300mA.

Change-Id: I5b916f1503a2267ca1e73b24096cb60a304e3c19
Signed-off-by: Ashay Jaiswal <ashayj@codeaurora.org>
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
This commit is contained in:
Ashay Jaiswal 2017-02-06 23:31:29 +05:30
parent 23d22ee4bf
commit 504aeb1158
4 changed files with 37 additions and 10 deletions

View file

@ -2,7 +2,7 @@ obj-$(CONFIG_QPNP_SMBCHARGER) += qpnp-smbcharger.o batterydata-lib.o pmic-voter.
obj-$(CONFIG_QPNP_FG) += qpnp-fg.o
obj-$(CONFIG_QPNP_FG_GEN3) += qpnp-fg-gen3.o fg-memif.o fg-util.o
obj-$(CONFIG_SMB135X_CHARGER) += smb135x-charger.o pmic-voter.o
obj-$(CONFIG_SMB1351_USB_CHARGER) += smb1351-charger.o pmic-voter.o
obj-$(CONFIG_SMB1351_USB_CHARGER) += smb1351-charger.o pmic-voter.o battery.o
obj-$(CONFIG_MSM_BCL_CTL) += msm_bcl.o
obj-$(CONFIG_MSM_BCL_PERIPHERAL_CTL) += bcl_peripheral.o
obj-$(CONFIG_BATTERY_BCL) += battery_current_limit.o

View file

@ -34,6 +34,7 @@
#define PL_TAPER_EARLY_BAD_VOTER "PL_TAPER_EARLY_BAD_VOTER"
#define PARALLEL_PSY_VOTER "PARALLEL_PSY_VOTER"
#define PL_HW_ABSENT_VOTER "PL_HW_ABSENT_VOTER"
#define PL_VOTER "PL_VOTER"
struct pl_data {
int pl_mode;
@ -50,8 +51,9 @@ struct pl_data {
struct power_supply *main_psy;
struct power_supply *pl_psy;
struct power_supply *batt_psy;
int settled_ua;
int charge_type;
int main_settled_ua;
int pl_settled_ua;
struct class qcom_batt_class;
struct wakeup_source *pl_ws;
struct notifier_block nb;
@ -85,7 +87,7 @@ enum {
static void split_settled(struct pl_data *chip)
{
int slave_icl_pct;
int slave_ua = 0;
int slave_ua = 0, main_settled_ua = 0;
union power_supply_propval pval = {0, };
int rc;
@ -108,10 +110,11 @@ static void split_settled(struct pl_data *chip)
pr_err("Couldn't get aicl settled value rc=%d\n", rc);
return;
}
chip->settled_ua = pval.intval;
main_settled_ua = pval.intval;
/* slave gets 10 percent points less for ICL */
slave_icl_pct = max(0, chip->slave_pct - 10);
slave_ua = (chip->settled_ua * slave_icl_pct) / 100;
slave_ua = ((main_settled_ua + chip->pl_settled_ua)
* slave_icl_pct) / 100;
}
/* ICL_REDUCTION on main could be 0mA when pl is disabled */
@ -131,6 +134,11 @@ static void split_settled(struct pl_data *chip)
pr_err("Couldn't set parallel icl, rc=%d\n", rc);
return;
}
/* main_settled_ua represents the total capability of adapter */
if (!chip->main_settled_ua)
chip->main_settled_ua = main_settled_ua;
chip->pl_settled_ua = slave_ua;
}
static ssize_t version_show(struct class *c, struct class_attribute *attr,
@ -379,8 +387,9 @@ static int pl_disable_vote_callback(struct votable *votable,
union power_supply_propval pval = {0, };
int rc;
chip->settled_ua = 0;
chip->taper_pct = 100;
chip->main_settled_ua = 0;
chip->pl_settled_ua = 0;
if (!pl_disable) { /* enable */
rc = power_supply_get_property(chip->pl_psy,
@ -561,6 +570,7 @@ static void handle_main_charge_type(struct pl_data *chip)
chip->charge_type = pval.intval;
}
#define MIN_ICL_CHANGE_DELTA_UA 300000
static void handle_settled_aicl_split(struct pl_data *chip)
{
union power_supply_propval pval = {0, };
@ -579,10 +589,11 @@ static void handle_settled_aicl_split(struct pl_data *chip)
pr_err("Couldn't get aicl settled value rc=%d\n", rc);
return;
}
if (chip->settled_ua != pval.intval) {
chip->settled_ua = pval.intval;
/* If ICL change is small skip splitting */
if (abs((chip->main_settled_ua - chip->pl_settled_ua)
- pval.intval) > MIN_ICL_CHANGE_DELTA_UA)
split_settled(chip);
}
}
}

View file

@ -1380,6 +1380,18 @@ static int smb2_init_hw(struct smb2 *chip)
vote(chg->hvdcp_enable_votable, MICRO_USB_VOTER,
chg->micro_usb_mode, 0);
/*
* AICL configuration:
* start from min and AICL ADC disable
*/
rc = smblib_masked_write(chg, USBIN_AICL_OPTIONS_CFG_REG,
USBIN_AICL_START_AT_MAX_BIT
| USBIN_AICL_ADC_EN_BIT, 0);
if (rc < 0) {
dev_err(chg->dev, "Couldn't configure AICL rc=%d\n", rc);
return rc;
}
/* Configure charge enable for software control; active high */
rc = smblib_masked_write(chg, CHGR_CFG2_REG,
CHG_EN_POLARITY_BIT |

View file

@ -774,13 +774,17 @@ static int smblib_usb_icl_vote_callback(struct votable *votable, void *data,
if (chg->usb_psy_desc.type != POWER_SUPPLY_TYPE_USB) {
if (client) {
rc = smblib_set_charge_param(chg, &chg->param.usb_icl,
icl_ua);
icl_ua - chg->icl_reduction_ua);
if (rc < 0) {
smblib_err(chg, "Couldn't set HC ICL rc=%d\n",
rc);
return rc;
}
}
smblib_dbg(chg, PR_PARALLEL,
"icl_ua=%d icl_reduction=%d\n",
icl_ua, chg->icl_reduction_ua);
goto out;
}