From 13c4202dde3542875c19cc206544e0019e1b7ef7 Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Wed, 11 Jan 2017 18:16:25 +0800 Subject: [PATCH] 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 Signed-off-by: Nicholas Troast --- drivers/power/supply/qcom/battery.c | 35 +++++++++++++++------------ drivers/power/supply/qcom/qpnp-smb2.c | 4 ++++ drivers/power/supply/qcom/smb-lib.c | 45 ++++++++++++++++++++++++++--------- drivers/power/supply/qcom/smb-lib.h | 2 ++ 4 files changed, 60 insertions(+), 26 deletions(-) diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c index efa88c239379..bd84de1b8bc1 100644 --- a/drivers/power/supply/qcom/battery.c +++ b/drivers/power/supply/qcom/battery.c @@ -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; - - input_limited_fcc_ua = div64_s64( - (s64)aicl_settled_ua * MICRO_5V * EFFICIENCY_PCT, - (s64)get_effective_result(chip->fv_votable) - * 100); + 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; + + 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); diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c index f8bca0645340..1fb0cab6c364 100644 --- a/drivers/power/supply/qcom/qpnp-smb2.c +++ b/drivers/power/supply/qcom/qpnp-smb2.c @@ -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; diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c index f56c70beb5f0..c42552bc6444 100644 --- a/drivers/power/supply/qcom/smb-lib.c +++ b/drivers/power/supply/qcom/smb-lib.c @@ -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)); diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h index 864e7d691a43..5516f339026f 100644 --- a/drivers/power/supply/qcom/smb-lib.h +++ b/drivers/power/supply/qcom/smb-lib.h @@ -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, -- 2.11.0