smb-lib: fix slave BCL for HVDCP3

Currently, fixed 5V adapter voltage is used for calculating slave FCC.
When HVDCP 3.0 is used it skews the desired FCC distribution. Fix this
by using the HVDCP3 pulse count to determine the actual adapter voltage
when limiting the slave battery current.

Change-Id: Ib4735ffe7b6287a3e57e0f74eb24c13c6a2b7a5a
Signed-off-by: Fenglin Wu <fenglinw@codeaurora.org>
Signed-off-by: Nicholas Troast <ntroast@codeaurora.org>
This commit is contained in:
Fenglin Wu 2017-01-11 18:16:25 +08:00 committed by Nicholas Troast
parent d86ba09f57
commit 13c4202dde
4 changed files with 59 additions and 25 deletions

View file

@ -247,12 +247,11 @@ done:
* FCC *
**********/
#define EFFICIENCY_PCT 80
#define MICRO_5V 5000000
static void split_fcc(struct pl_data *chip, int total_ua,
int *master_ua, int *slave_ua)
{
int rc, effective_total_ua, slave_limited_ua, hw_cc_delta_ua = 0,
aicl_settled_ua, input_limited_fcc_ua;
icl_ua, adapter_uv, bcl_ua;
union power_supply_propval pval = {0, };
rc = power_supply_get_property(chip->main_psy,
@ -262,24 +261,30 @@ static void split_fcc(struct pl_data *chip, int total_ua,
else
hw_cc_delta_ua = pval.intval;
input_limited_fcc_ua = INT_MAX;
bcl_ua = INT_MAX;
if (chip->pl_mode == POWER_SUPPLY_PARALLEL_MID_MID) {
rc = power_supply_get_property(chip->main_psy,
POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
&pval);
if (rc < 0)
aicl_settled_ua = 0;
else
aicl_settled_ua = pval.intval;
POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED, &pval);
if (rc < 0) {
pr_err("Couldn't get aicl settled value rc=%d\n", rc);
return;
}
icl_ua = pval.intval;
input_limited_fcc_ua = div64_s64(
(s64)aicl_settled_ua * MICRO_5V * EFFICIENCY_PCT,
(s64)get_effective_result(chip->fv_votable)
* 100);
rc = power_supply_get_property(chip->main_psy,
POWER_SUPPLY_PROP_INPUT_VOLTAGE_SETTLED, &pval);
if (rc < 0) {
pr_err("Couldn't get adaptive voltage rc=%d\n", rc);
return;
}
adapter_uv = pval.intval;
bcl_ua = div64_s64((s64)icl_ua * adapter_uv * EFFICIENCY_PCT,
(s64)get_effective_result(chip->fv_votable) * 100);
}
effective_total_ua = max(0, total_ua + hw_cc_delta_ua);
slave_limited_ua = min(effective_total_ua, input_limited_fcc_ua);
slave_limited_ua = min(effective_total_ua, bcl_ua);
*slave_ua = (slave_limited_ua * chip->slave_pct) / 100;
*slave_ua = (*slave_ua * chip->taper_pct) / 100;
*master_ua = max(0, total_ua - *slave_ua);

View file

@ -613,6 +613,7 @@ static enum power_supply_property smb2_usb_main_props[] = {
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
POWER_SUPPLY_PROP_TYPE,
POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
POWER_SUPPLY_PROP_INPUT_VOLTAGE_SETTLED,
POWER_SUPPLY_PROP_FCC_DELTA,
/*
* TODO move the TEMP and TEMP_MAX properties here,
@ -645,6 +646,9 @@ static int smb2_usb_main_get_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
rc = smblib_get_prop_input_current_settled(chg, val);
break;
case POWER_SUPPLY_PROP_INPUT_VOLTAGE_SETTLED:
rc = smblib_get_prop_input_voltage_settled(chg, val);
break;
case POWER_SUPPLY_PROP_FCC_DELTA:
rc = smblib_get_prop_fcc_delta(chg, val);
break;

View file

@ -331,7 +331,6 @@ static const struct apsd_result *smblib_get_apsd_result(struct smb_charger *chg)
return result;
}
/********************
* REGISTER SETTERS *
********************/
@ -1998,6 +1997,39 @@ int smblib_get_prop_input_current_settled(struct smb_charger *chg,
return smblib_get_charge_param(chg, &chg->param.icl_stat, &val->intval);
}
#define HVDCP3_STEP_UV 200000
int smblib_get_prop_input_voltage_settled(struct smb_charger *chg,
union power_supply_propval *val)
{
const struct apsd_result *apsd_result = smblib_get_apsd_result(chg);
int rc, pulses;
u8 stat;
val->intval = MICRO_5V;
if (apsd_result == NULL) {
smblib_err(chg, "APSD result is NULL\n");
return 0;
}
switch (apsd_result->pst) {
case POWER_SUPPLY_TYPE_USB_HVDCP_3:
rc = smblib_read(chg, QC_PULSE_COUNT_STATUS_REG, &stat);
if (rc < 0) {
smblib_err(chg,
"Couldn't read QC_PULSE_COUNT rc=%d\n", rc);
return 0;
}
pulses = (stat & QC_PULSE_COUNT_MASK);
val->intval = MICRO_5V + HVDCP3_STEP_UV * pulses;
break;
default:
val->intval = MICRO_5V;
break;
}
return 0;
}
int smblib_get_prop_pd_in_hard_reset(struct smb_charger *chg,
union power_supply_propval *val)
{
@ -2887,6 +2919,7 @@ static void smblib_hvdcp_adaptive_voltage_change(struct smb_charger *chg)
u8 stat;
int pulses;
power_supply_changed(chg->usb_main_psy);
if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_HVDCP) {
rc = smblib_read(chg, QC_CHANGE_STATUS_REG, &stat);
if (rc < 0) {
@ -2939,13 +2972,6 @@ static void smblib_hvdcp_adaptive_voltage_change(struct smb_charger *chg)
}
}
static void smblib_handle_adaptive_voltage_done(struct smb_charger *chg,
bool rising)
{
smblib_dbg(chg, PR_INTERRUPT, "IRQ: adaptive-voltage-done %s\n",
rising ? "rising" : "falling");
}
/* triggers when HVDCP 3.0 authentication has finished */
static void smblib_handle_hvdcp_3p0_auth_done(struct smb_charger *chg,
bool rising)
@ -3087,9 +3113,6 @@ irqreturn_t smblib_handle_usb_source_change(int irq, void *data)
smblib_handle_hvdcp_3p0_auth_done(chg,
(bool)(stat & QC_AUTH_DONE_STATUS_BIT));
smblib_handle_adaptive_voltage_done(chg,
(bool)(stat & VADP_CHANGE_DONE_AFTER_AUTH_BIT));
smblib_handle_sdp_enumeration_done(chg,
(bool)(stat & ENUMERATION_DONE_BIT));

View file

@ -377,6 +377,8 @@ int smblib_get_prop_pd_allowed(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_input_current_settled(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_input_voltage_settled(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_pd_in_hard_reset(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_pe_start(struct smb_charger *chg,