From d6e0cf48db2665f00dd6a80dd14765f90ce976ba Mon Sep 17 00:00:00 2001 From: Harry Yang Date: Tue, 7 Feb 2017 13:29:57 -0800 Subject: [PATCH 1/4] qcom: smb-lib: remove FCC_MAX votable FCC_MAX votable was introduced as an intermediate votable used by Qnovo driver for fast charge current vote, but does not fit in the new requirement that Qnovo force its vote value. Remove it. CRs-Fixed: 2004173 Change-Id: Iff8b74113550f808546d61ef864f3935fc5d61fa Signed-off-by: Harry Yang --- drivers/power/supply/qcom/qpnp-smb2.c | 10 +--------- drivers/power/supply/qcom/smb-lib.c | 18 ------------------ drivers/power/supply/qcom/smb-lib.h | 2 -- 3 files changed, 1 insertion(+), 29 deletions(-) diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c index f8bca0645340..2fd2619f890d 100644 --- a/drivers/power/supply/qcom/qpnp-smb2.c +++ b/drivers/power/supply/qcom/qpnp-smb2.c @@ -834,7 +834,6 @@ static enum power_supply_property smb2_batt_props[] = { POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_VOLTAGE_MAX, POWER_SUPPLY_PROP_CURRENT_NOW, - POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, POWER_SUPPLY_PROP_TEMP, POWER_SUPPLY_PROP_TECHNOLOGY, POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED, @@ -898,10 +897,6 @@ static int smb2_batt_get_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_CURRENT_NOW: rc = smblib_get_prop_batt_current_now(chg, val); break; - case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: - val->intval = get_client_vote(chg->fcc_max_votable, - DEFAULT_VOTER); - break; case POWER_SUPPLY_PROP_TEMP: rc = smblib_get_prop_batt_temp(chg, val); break; @@ -958,9 +953,6 @@ static int smb2_batt_set_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_VOLTAGE_MAX: vote(chg->fv_votable, DEFAULT_VOTER, true, val->intval); break; - case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: - vote(chg->fcc_max_votable, DEFAULT_VOTER, true, val->intval); - break; case POWER_SUPPLY_PROP_SET_SHIP_MODE: /* Not in ship mode as long as the device is active */ if (!val->intval) @@ -1375,7 +1367,7 @@ static int smb2_init_hw(struct smb2 *chip) DEFAULT_VOTER, chip->dt.no_battery, 0); vote(chg->dc_suspend_votable, DEFAULT_VOTER, chip->dt.no_battery, 0); - vote(chg->fcc_max_votable, + vote(chg->fcc_votable, DEFAULT_VOTER, true, chip->dt.fcc_ua); vote(chg->fv_votable, DEFAULT_VOTER, true, chip->dt.fv_uv); diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c index f56c70beb5f0..f523333390bc 100644 --- a/drivers/power/supply/qcom/smb-lib.c +++ b/drivers/power/supply/qcom/smb-lib.c @@ -763,14 +763,6 @@ static int smblib_dc_suspend_vote_callback(struct votable *votable, void *data, return smblib_set_dc_suspend(chg, (bool)suspend); } -static int smblib_fcc_max_vote_callback(struct votable *votable, void *data, - int fcc_ua, const char *client) -{ - struct smb_charger *chg = data; - - return vote(chg->fcc_votable, FCC_MAX_RESULT_VOTER, true, fcc_ua); -} - #define USBIN_25MA 25000 #define USBIN_100MA 100000 #define USBIN_150MA 150000 @@ -3756,14 +3748,6 @@ static int smblib_create_votables(struct smb_charger *chg) return rc; } - chg->fcc_max_votable = create_votable("FCC_MAX", VOTE_MAX, - smblib_fcc_max_vote_callback, - chg); - if (IS_ERR(chg->fcc_max_votable)) { - rc = PTR_ERR(chg->fcc_max_votable); - return rc; - } - chg->usb_icl_votable = create_votable("USB_ICL", VOTE_MIN, smblib_usb_icl_vote_callback, chg); @@ -3857,8 +3841,6 @@ static void smblib_destroy_votables(struct smb_charger *chg) destroy_votable(chg->usb_suspend_votable); if (chg->dc_suspend_votable) destroy_votable(chg->dc_suspend_votable); - if (chg->fcc_max_votable) - destroy_votable(chg->fcc_max_votable); if (chg->usb_icl_votable) destroy_votable(chg->usb_icl_votable); if (chg->dc_icl_votable) diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h index 864e7d691a43..c8e32789cde1 100644 --- a/drivers/power/supply/qcom/smb-lib.h +++ b/drivers/power/supply/qcom/smb-lib.h @@ -40,7 +40,6 @@ enum print_reason { #define CHG_STATE_VOTER "CHG_STATE_VOTER" #define TYPEC_SRC_VOTER "TYPEC_SRC_VOTER" #define TAPER_END_VOTER "TAPER_END_VOTER" -#define FCC_MAX_RESULT_VOTER "FCC_MAX_RESULT_VOTER" #define THERMAL_DAEMON_VOTER "THERMAL_DAEMON_VOTER" #define CC_DETACHED_VOTER "CC_DETACHED_VOTER" #define HVDCP_TIMEOUT_VOTER "HVDCP_TIMEOUT_VOTER" @@ -202,7 +201,6 @@ struct smb_charger { /* votables */ struct votable *usb_suspend_votable; struct votable *dc_suspend_votable; - struct votable *fcc_max_votable; struct votable *fcc_votable; struct votable *fv_votable; struct votable *usb_icl_votable; From 5e55ca1847b0d05b23b5c5462c0e61dc29f76058 Mon Sep 17 00:00:00 2001 From: Harry Yang Date: Tue, 7 Feb 2017 16:53:28 -0800 Subject: [PATCH 2/4] power_supply: Add CURRENT_QNOVO and VOLTAGE_QNOVO properties CURRENT_QNOVO - force fast charge current value VOLTAGE_QNOVO - force float voltage value CRs-Fixed: 2004173 Change-Id: I7569052fd2cb6d1ce9a3a8e69e79b950a6c62d57 Signed-off-by: Harry Yang --- drivers/power/power_supply_sysfs.c | 2 ++ include/linux/power_supply.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index a9bb96df56c9..168119fcf7d1 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c @@ -263,6 +263,8 @@ static struct device_attribute power_supply_attrs[] = { POWER_SUPPLY_ATTR(dp_dm), POWER_SUPPLY_ATTR(input_current_limited), POWER_SUPPLY_ATTR(input_current_now), + POWER_SUPPLY_ATTR(current_qnovo), + POWER_SUPPLY_ATTR(voltage_qnovo), POWER_SUPPLY_ATTR(rerun_aicl), POWER_SUPPLY_ATTR(cycle_count_id), POWER_SUPPLY_ATTR(safety_timer_expired), diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 41568e45c024..b9b4c7b8fe06 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -215,6 +215,8 @@ enum power_supply_property { POWER_SUPPLY_PROP_DP_DM, POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED, POWER_SUPPLY_PROP_INPUT_CURRENT_NOW, + POWER_SUPPLY_PROP_CURRENT_QNOVO, + POWER_SUPPLY_PROP_VOLTAGE_QNOVO, POWER_SUPPLY_PROP_RERUN_AICL, POWER_SUPPLY_PROP_CYCLE_COUNT_ID, POWER_SUPPLY_PROP_SAFETY_TIMER_EXPIRED, From 491c847cd23313c987cab1cdd70e6a7dabea5db7 Mon Sep 17 00:00:00 2001 From: Harry Yang Date: Thu, 9 Feb 2017 17:45:12 -0800 Subject: [PATCH 3/4] qpnp-smb2: expose forcing fcc/fv values via battery psy CURRENT_QNOVO and VOLTAGE_QNOVO allow "forcing" fast charge current and float voltage value, implemented around votable such that one can have previlige in FCC and FV voting. CRs-Fixed: 2004173 Change-Id: I2df30220aa89e15c4bace9980990f227218a5bdd Signed-off-by: Harry Yang --- drivers/power/supply/qcom/battery.c | 36 ++++++++++++++++++++++++--- drivers/power/supply/qcom/qpnp-smb2.c | 14 +++++++++++ drivers/power/supply/qcom/smb-lib.c | 2 ++ drivers/power/supply/qcom/smb-lib.h | 4 +++ 4 files changed, 52 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c index efa88c239379..6f083f1bbe80 100644 --- a/drivers/power/supply/qcom/battery.c +++ b/drivers/power/supply/qcom/battery.c @@ -298,6 +298,19 @@ static int pl_fcc_vote_callback(struct votable *votable, void *data, if (!chip->main_psy) return 0; + if (chip->batt_psy) { + rc = power_supply_get_property(chip->batt_psy, + POWER_SUPPLY_PROP_CURRENT_QNOVO, + &pval); + if (rc < 0) { + pr_err("Couldn't get qnovo fcc, rc=%d\n", rc); + return rc; + } + + if (pval.intval != -EINVAL) + total_fcc_ua = pval.intval; + } + if (chip->pl_mode == POWER_SUPPLY_PARALLEL_NONE || get_effective_result_locked(chip->pl_disable_votable)) { pval.intval = total_fcc_ua; @@ -343,6 +356,7 @@ static int pl_fv_vote_callback(struct votable *votable, void *data, struct pl_data *chip = data; union power_supply_propval pval = {0, }; int rc = 0; + int effective_fv_uv = fv_uv; if (fv_uv < 0) return 0; @@ -350,7 +364,21 @@ static int pl_fv_vote_callback(struct votable *votable, void *data, if (!chip->main_psy) return 0; - pval.intval = fv_uv; + if (chip->batt_psy) { + rc = power_supply_get_property(chip->batt_psy, + POWER_SUPPLY_PROP_VOLTAGE_QNOVO, + &pval); + if (rc < 0) { + pr_err("Couldn't get qnovo fv, rc=%d\n", rc); + return rc; + } + + if (pval.intval != -EINVAL) + effective_fv_uv = pval.intval; + } + + pval.intval = effective_fv_uv; + rc = power_supply_set_property(chip->main_psy, POWER_SUPPLY_PROP_VOLTAGE_MAX, &pval); if (rc < 0) { @@ -359,7 +387,7 @@ static int pl_fv_vote_callback(struct votable *votable, void *data, } if (chip->pl_mode != POWER_SUPPLY_PARALLEL_NONE) { - pval.intval = fv_uv + PARALLEL_FLOAT_VOLTAGE_DELTA_UV; + pval.intval += PARALLEL_FLOAT_VOLTAGE_DELTA_UV; rc = power_supply_set_property(chip->pl_psy, POWER_SUPPLY_PROP_VOLTAGE_MAX, &pval); if (rc < 0) { @@ -514,9 +542,9 @@ static bool is_parallel_available(struct pl_data *chip) return false; } /* - * Note that pl_mode only be udpated to anything other than a _NONE + * Note that pl_mode will be updated to anything other than a _NONE * only after pl_psy is found. IOW pl_mode != _NONE implies that - * pl_psy is present and valid + * pl_psy is present and valid. */ chip->pl_mode = pval.intval; vote(chip->pl_disable_votable, PARALLEL_PSY_VOTER, false, 0); diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c index 2fd2619f890d..ced66122a156 100644 --- a/drivers/power/supply/qcom/qpnp-smb2.c +++ b/drivers/power/supply/qcom/qpnp-smb2.c @@ -894,9 +894,15 @@ static int smb2_batt_get_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_VOLTAGE_MAX: val->intval = get_client_vote(chg->fv_votable, DEFAULT_VOTER); break; + case POWER_SUPPLY_PROP_VOLTAGE_QNOVO: + val->intval = chg->qnovo_fv_uv; + break; case POWER_SUPPLY_PROP_CURRENT_NOW: rc = smblib_get_prop_batt_current_now(chg, val); break; + case POWER_SUPPLY_PROP_CURRENT_QNOVO: + val->intval = chg->qnovo_fcc_ua; + break; case POWER_SUPPLY_PROP_TEMP: rc = smblib_get_prop_batt_temp(chg, val); break; @@ -953,6 +959,14 @@ static int smb2_batt_set_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_VOLTAGE_MAX: vote(chg->fv_votable, DEFAULT_VOTER, true, val->intval); break; + case POWER_SUPPLY_PROP_VOLTAGE_QNOVO: + chg->qnovo_fv_uv = val->intval; + rc = rerun_election(chg->fv_votable); + break; + case POWER_SUPPLY_PROP_CURRENT_QNOVO: + chg->qnovo_fcc_ua = val->intval; + rc = rerun_election(chg->fcc_votable); + break; case POWER_SUPPLY_PROP_SET_SHIP_MODE: /* Not in ship mode as long as the device is active */ if (!val->intval) diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c index f523333390bc..64c5f3e99bb1 100644 --- a/drivers/power/supply/qcom/smb-lib.c +++ b/drivers/power/supply/qcom/smb-lib.c @@ -3891,6 +3891,8 @@ int smblib_init(struct smb_charger *chg) switch (chg->mode) { case PARALLEL_MASTER: + chg->qnovo_fcc_ua = -EINVAL; + chg->qnovo_fv_uv = -EINVAL; rc = smblib_create_votables(chg); if (rc < 0) { smblib_err(chg, "Couldn't create votables rc=%d\n", diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h index c8e32789cde1..a220ad4d214b 100644 --- a/drivers/power/supply/qcom/smb-lib.h +++ b/drivers/power/supply/qcom/smb-lib.h @@ -257,6 +257,10 @@ struct smb_charger { bool usb_ever_removed; int icl_reduction_ua; + + /* qnovo */ + int qnovo_fcc_ua; + int qnovo_fv_uv; }; int smblib_read(struct smb_charger *chg, u16 addr, u8 *val); From 8a3c043c63ba6893087954dc3325521d33e7d578 Mon Sep 17 00:00:00 2001 From: Harry Yang Date: Tue, 7 Feb 2017 21:33:19 -0800 Subject: [PATCH 4/4] qcom: qnovo: Update fcc and fv through batt psy To force qnovo FCC and FV through parallel framework more conveniently, batt psy is bridged to replace votable in qnovo driver. The two properties are - POWER_SUPPLY_PROP_CURRENT_QNOVO and POWER_SUPPLY_PROP_VOLTAGE_QNOVO. CRs-Fixed: 2004173 Change-Id: I40b179fe5535e0209fcdbc1cb7e64cbfdf45a14b Signed-off-by: Harry Yang --- drivers/power/supply/qcom/qpnp-qnovo.c | 80 ++++++++++++++++---------- 1 file changed, 51 insertions(+), 29 deletions(-) diff --git a/drivers/power/supply/qcom/qpnp-qnovo.c b/drivers/power/supply/qcom/qpnp-qnovo.c index 078bbaaad5a2..f720f6c907f7 100644 --- a/drivers/power/supply/qcom/qpnp-qnovo.c +++ b/drivers/power/supply/qcom/qpnp-qnovo.c @@ -148,8 +148,6 @@ struct qnovo { struct work_struct status_change_work; int fv_uV_request; int fcc_uA_request; - struct votable *fcc_max_votable; - struct votable *fv_votable; }; static int debug_mask; @@ -226,6 +224,50 @@ unlock: return rc; } +static bool is_batt_available(struct qnovo *chip) +{ + if (!chip->batt_psy) + chip->batt_psy = power_supply_get_by_name("battery"); + + if (!chip->batt_psy) + return false; + + return true; +} + +static int qnovo_batt_psy_update(struct qnovo *chip, bool disable) +{ + union power_supply_propval pval = {0}; + int rc = 0; + + if (!is_batt_available(chip)) + return -EINVAL; + + if (chip->fv_uV_request != -EINVAL) { + pval.intval = disable ? -EINVAL : chip->fv_uV_request; + rc = power_supply_set_property(chip->batt_psy, + POWER_SUPPLY_PROP_VOLTAGE_QNOVO, + &pval); + if (rc < 0) { + pr_err("Couldn't set prop qnovo_fv rc = %d\n", rc); + return -EINVAL; + } + } + + if (chip->fcc_uA_request != -EINVAL) { + pval.intval = disable ? -EINVAL : chip->fcc_uA_request; + rc = power_supply_set_property(chip->batt_psy, + POWER_SUPPLY_PROP_CURRENT_QNOVO, + &pval); + if (rc < 0) { + pr_err("Couldn't set prop qnovo_fcc rc = %d\n", rc); + return -EINVAL; + } + } + + return rc; +} + static int qnovo_disable_cb(struct votable *votable, void *data, int disable, const char *client) { @@ -233,15 +275,9 @@ static int qnovo_disable_cb(struct votable *votable, void *data, int disable, int rc = 0; if (disable) { - if (chip->fv_uV_request != -EINVAL) { - if (chip->fv_votable) - vote(chip->fv_votable, QNOVO_VOTER, false, 0); - } - if (chip->fcc_uA_request != -EINVAL) { - if (chip->fcc_max_votable) - vote(chip->fcc_max_votable, QNOVO_VOTER, - false, 0); - } + rc = qnovo_batt_psy_update(chip, true); + if (rc < 0) + return rc; } rc = qnovo_masked_write(chip, QNOVO_PTRAIN_EN, QNOVO_PTRAIN_EN_BIT, @@ -253,20 +289,9 @@ static int qnovo_disable_cb(struct votable *votable, void *data, int disable, } if (!disable) { - if (chip->fv_uV_request != -EINVAL) { - if (!chip->fv_votable) - chip->fv_votable = find_votable("FV"); - if (chip->fv_votable) - vote(chip->fv_votable, QNOVO_VOTER, - true, chip->fv_uV_request); - } - if (chip->fcc_uA_request != -EINVAL) { - if (!chip->fcc_max_votable) - chip->fcc_max_votable = find_votable("FCC_MAX"); - if (chip->fcc_max_votable) - vote(chip->fcc_max_votable, QNOVO_VOTER, - true, chip->fcc_uA_request); - } + rc = qnovo_batt_psy_update(chip, false); + if (rc < 0) + return rc; } return rc; @@ -979,10 +1004,7 @@ static ssize_t batt_prop_show(struct class *c, struct class_attribute *attr, int prop = params[i].start_addr; union power_supply_propval pval = {0}; - if (!chip->batt_psy) - chip->batt_psy = power_supply_get_by_name("battery"); - - if (!chip->batt_psy) + if (!is_batt_available(chip)) return -EINVAL; rc = power_supply_get_property(chip->batt_psy, prop, &pval);