diff options
-rw-r--r-- | Documentation/devicetree/bindings/power/supply/qcom/smb1351-charger.txt | 2 | ||||
-rw-r--r-- | drivers/power/supply/qcom/battery.c | 48 | ||||
-rw-r--r-- | drivers/power/supply/qcom/qpnp-smb2.c | 16 | ||||
-rw-r--r-- | drivers/power/supply/qcom/smb-lib.c | 244 | ||||
-rw-r--r-- | drivers/power/supply/qcom/smb-lib.h | 7 | ||||
-rw-r--r-- | drivers/power/supply/qcom/smb-reg.h | 3 | ||||
-rw-r--r-- | drivers/power/supply/qcom/smb1351-charger.c | 9 | ||||
-rw-r--r-- | drivers/power/supply/qcom/smb138x-charger.c | 2 | ||||
-rw-r--r-- | include/linux/power_supply.h | 7 |
9 files changed, 308 insertions, 30 deletions
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/smb1351-charger.txt b/Documentation/devicetree/bindings/power/supply/qcom/smb1351-charger.txt index ab0ac32e444e..c200f9423384 100644 --- a/Documentation/devicetree/bindings/power/supply/qcom/smb1351-charger.txt +++ b/Documentation/devicetree/bindings/power/supply/qcom/smb1351-charger.txt @@ -69,6 +69,8 @@ Optional Properties: via pin in a parallel-charger configuration. 0 - Active low and 1 - Active high. If not specified the default value is active-low. +- qcom,parallel-external-current-sense If present specifies external rsense is + used for charge current sensing. Example for standalone charger: diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c index 35dc3842017b..4039b4312e93 100644 --- a/drivers/power/supply/qcom/battery.c +++ b/drivers/power/supply/qcom/battery.c @@ -45,6 +45,7 @@ struct pl_data { struct votable *fv_votable; struct votable *pl_disable_votable; struct votable *pl_awake_votable; + struct votable *hvdcp_hw_inov_dis_votable; struct work_struct status_change_work; struct work_struct pl_disable_forever_work; struct delayed_work pl_taper_work; @@ -96,7 +97,8 @@ static void split_settled(struct pl_data *chip) * for desired split */ - if (chip->pl_mode != POWER_SUPPLY_PARALLEL_USBIN_USBIN) + if ((chip->pl_mode != POWER_SUPPLY_PL_USBIN_USBIN) + && (chip->pl_mode != POWER_SUPPLY_PL_USBIN_USBIN_EXT)) return; if (!chip->main_psy) @@ -262,7 +264,7 @@ static void split_fcc(struct pl_data *chip, int total_ua, hw_cc_delta_ua = pval.intval; bcl_ua = INT_MAX; - if (chip->pl_mode == POWER_SUPPLY_PARALLEL_MID_MID) { + if (chip->pl_mode == POWER_SUPPLY_PL_USBMID_USBMID) { rc = power_supply_get_property(chip->main_psy, POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED, &pval); if (rc < 0) { @@ -287,7 +289,15 @@ static void split_fcc(struct pl_data *chip, int total_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); + /* + * In USBIN_USBIN configuration with internal rsense parallel + * charger's current goes through main charger's BATFET, keep + * the main charger's FCC to the votable result. + */ + if (chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN) + *master_ua = max(0, total_ua); + else + *master_ua = max(0, total_ua - *slave_ua); } static int pl_fcc_vote_callback(struct votable *votable, void *data, @@ -316,7 +326,7 @@ static int pl_fcc_vote_callback(struct votable *votable, void *data, total_fcc_ua = pval.intval; } - if (chip->pl_mode == POWER_SUPPLY_PARALLEL_NONE + if (chip->pl_mode == POWER_SUPPLY_PL_NONE || get_effective_result_locked(chip->pl_disable_votable)) { pval.intval = total_fcc_ua; rc = power_supply_set_property(chip->main_psy, @@ -391,7 +401,7 @@ static int pl_fv_vote_callback(struct votable *votable, void *data, return rc; } - if (chip->pl_mode != POWER_SUPPLY_PARALLEL_NONE) { + if (chip->pl_mode != POWER_SUPPLY_PL_NONE) { pval.intval += PARALLEL_FLOAT_VOLTAGE_DELTA_UV; rc = power_supply_set_property(chip->pl_psy, POWER_SUPPLY_PROP_VOLTAGE_MAX, &pval); @@ -411,6 +421,10 @@ static void pl_disable_forever_work(struct work_struct *work) /* Disable Parallel charger forever */ vote(chip->pl_disable_votable, PL_HW_ABSENT_VOTER, true, 0); + + /* Re-enable autonomous mode */ + if (chip->hvdcp_hw_inov_dis_votable) + vote(chip->hvdcp_hw_inov_dis_votable, PL_VOTER, false, 0); } static int pl_disable_vote_callback(struct votable *votable, @@ -451,7 +465,8 @@ static int pl_disable_vote_callback(struct votable *votable, pr_err("Couldn't change slave suspend state rc=%d\n", rc); - if (chip->pl_mode == POWER_SUPPLY_PARALLEL_USBIN_USBIN) + if ((chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN) + || (chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN_EXT)) split_settled(chip); /* * we could have been enabled while in taper mode, @@ -469,7 +484,8 @@ static int pl_disable_vote_callback(struct votable *votable, } } } else { - if (chip->pl_mode == POWER_SUPPLY_PARALLEL_USBIN_USBIN) + if ((chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN) + || (chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN_EXT)) split_settled(chip); /* pl_psy may be NULL while in the disable branch */ @@ -552,6 +568,21 @@ static bool is_parallel_available(struct pl_data *chip) * pl_psy is present and valid. */ chip->pl_mode = pval.intval; + + /* Disable autonomous votage increments for USBIN-USBIN */ + if ((chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN) + || (chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN_EXT)) { + if (!chip->hvdcp_hw_inov_dis_votable) + chip->hvdcp_hw_inov_dis_votable = + find_votable("HVDCP_HW_INOV_DIS"); + if (chip->hvdcp_hw_inov_dis_votable) + /* Read current pulse count */ + vote(chip->hvdcp_hw_inov_dis_votable, PL_VOTER, + true, 0); + else + return false; + } + vote(chip->pl_disable_votable, PARALLEL_PSY_VOTER, false, 0); return true; @@ -610,7 +641,8 @@ static void handle_settled_aicl_split(struct pl_data *chip) int rc; if (!get_effective_result(chip->pl_disable_votable) - && chip->pl_mode == POWER_SUPPLY_PARALLEL_USBIN_USBIN) { + && (chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN + || chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN_EXT)) { /* * call aicl split only when USBIN_USBIN and enabled * and if aicl changed diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c index 773e8b00c1c0..7e5b239cea96 100644 --- a/drivers/power/supply/qcom/qpnp-smb2.c +++ b/drivers/power/supply/qcom/qpnp-smb2.c @@ -848,6 +848,8 @@ static enum power_supply_property smb2_batt_props[] = { POWER_SUPPLY_PROP_PARALLEL_DISABLE, POWER_SUPPLY_PROP_SET_SHIP_MODE, POWER_SUPPLY_PROP_DIE_HEALTH, + POWER_SUPPLY_PROP_RERUN_AICL, + POWER_SUPPLY_PROP_DP_DM, }; static int smb2_batt_get_prop(struct power_supply *psy, @@ -933,6 +935,12 @@ static int smb2_batt_get_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_DIE_HEALTH: rc = smblib_get_prop_die_health(chg, val); break; + case POWER_SUPPLY_PROP_DP_DM: + val->intval = chg->pulse_cnt; + break; + case POWER_SUPPLY_PROP_RERUN_AICL: + val->intval = 0; + break; default: pr_err("batt power supply prop %d not supported\n", psp); return -EINVAL; @@ -986,6 +994,12 @@ static int smb2_batt_set_prop(struct power_supply *psy, break; rc = smblib_set_prop_ship_mode(chg, val); break; + case POWER_SUPPLY_PROP_RERUN_AICL: + rc = smblib_rerun_aicl(chg); + break; + case POWER_SUPPLY_PROP_DP_DM: + rc = smblib_dp_dm(chg, val->intval); + break; default: rc = -EINVAL; } @@ -1001,6 +1015,8 @@ static int smb2_batt_prop_is_writeable(struct power_supply *psy, case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL: case POWER_SUPPLY_PROP_CAPACITY: case POWER_SUPPLY_PROP_PARALLEL_DISABLE: + case POWER_SUPPLY_PROP_DP_DM: + case POWER_SUPPLY_PROP_RERUN_AICL: return 1; default: break; diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c index 47228664e03f..ce2e077c4f07 100644 --- a/drivers/power/supply/qcom/smb-lib.c +++ b/drivers/power/supply/qcom/smb-lib.c @@ -58,6 +58,12 @@ int smblib_read(struct smb_charger *chg, u16 addr, u8 *val) return rc; } +int smblib_multibyte_read(struct smb_charger *chg, u16 addr, u8 *val, + int count) +{ + return regmap_bulk_read(chg->regmap, addr, val, count); +} + int smblib_masked_write(struct smb_charger *chg, u16 addr, u8 mask, u8 val) { int rc = 0; @@ -652,6 +658,8 @@ static void smblib_uusb_removal(struct smb_charger *chg) chg->voltage_min_uv = MICRO_5V; chg->voltage_max_uv = MICRO_5V; + chg->usb_icl_delta_ua = 0; + chg->pulse_cnt = 0; /* clear USB ICL vote for USB_PSY_VOTER */ rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); @@ -741,6 +749,40 @@ int smblib_rerun_apsd_if_required(struct smb_charger *chg) return 0; } +static int smblib_get_pulse_cnt(struct smb_charger *chg, int *count) +{ + int rc; + u8 val[2]; + + switch (chg->smb_version) { + case PMI8998_SUBTYPE: + rc = smblib_read(chg, QC_PULSE_COUNT_STATUS_REG, val); + if (rc) { + pr_err("failed to read QC_PULSE_COUNT_STATUS_REG rc=%d\n", + rc); + return rc; + } + *count = val[0] & QC_PULSE_COUNT_MASK; + break; + case PM660_SUBTYPE: + rc = smblib_multibyte_read(chg, + QC_PULSE_COUNT_STATUS_1_REG, val, 2); + if (rc) { + pr_err("failed to read QC_PULSE_COUNT_STATUS_1_REG rc=%d\n", + rc); + return rc; + } + *count = (val[1] << 8) | val[0]; + break; + default: + smblib_dbg(chg, PR_PARALLEL, "unknown SMB chip %d\n", + chg->smb_version); + return -EINVAL; + } + + return 0; +} + /********************* * VOTABLE CALLBACKS * *********************/ @@ -975,8 +1017,10 @@ static int smblib_hvdcp_enable_vote_callback(struct votable *votable, { struct smb_charger *chg = data; int rc; - u8 val = HVDCP_AUTH_ALG_EN_CFG_BIT - | HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT | HVDCP_EN_BIT; + u8 val = HVDCP_AUTH_ALG_EN_CFG_BIT | HVDCP_EN_BIT; + + /* vote to enable/disable HW autonomous INOV */ + vote(chg->hvdcp_hw_inov_dis_votable, client, !hvdcp_enable, 0); /* * Disable the autonomous bit and auth bit for disabling hvdcp. @@ -987,9 +1031,7 @@ static int smblib_hvdcp_enable_vote_callback(struct votable *votable, val = HVDCP_EN_BIT; rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG, - HVDCP_EN_BIT - | HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT - | HVDCP_AUTH_ALG_EN_CFG_BIT, + HVDCP_EN_BIT | HVDCP_AUTH_ALG_EN_CFG_BIT, val); if (rc < 0) { smblib_err(chg, "Couldn't %s hvdcp rc=%d\n", @@ -1058,6 +1100,37 @@ static int smblib_apsd_disable_vote_callback(struct votable *votable, return 0; } +static int smblib_hvdcp_hw_inov_dis_vote_callback(struct votable *votable, + void *data, int disable, const char *client) +{ + struct smb_charger *chg = data; + int rc; + + if (disable) { + /* + * the pulse count register get zeroed when autonomous mode is + * disabled. Track that in variables before disabling + */ + rc = smblib_get_pulse_cnt(chg, &chg->pulse_cnt); + if (rc < 0) { + pr_err("failed to read QC_PULSE_COUNT_STATUS_REG rc=%d\n", + rc); + return rc; + } + } + + rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG, + HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT, + disable ? 0 : HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT); + if (rc < 0) { + smblib_err(chg, "Couldn't %s hvdcp rc=%d\n", + disable ? "disable" : "enable", rc); + return rc; + } + + return rc; +} + /******************* * VCONN REGULATOR * * *****************/ @@ -1645,6 +1718,98 @@ int smblib_set_prop_system_temp_level(struct smb_charger *chg, return 0; } +int smblib_rerun_aicl(struct smb_charger *chg) +{ + int rc = 0; + u8 val; + + /* + * Use restart_AICL instead of trigger_AICL as it runs the + * complete AICL instead of starting from the last settled value. + * + * 8998 only supports trigger_AICL return error for 8998 + */ + switch (chg->smb_version) { + case PMI8998_SUBTYPE: + smblib_dbg(chg, PR_PARALLEL, "AICL rerun not supported\n"); + return -EINVAL; + case PM660_SUBTYPE: + val = RESTART_AICL_BIT; + break; + default: + smblib_dbg(chg, PR_PARALLEL, "unknown SMB chip %d\n", + chg->smb_version); + return -EINVAL; + } + rc = smblib_masked_write(chg, CMD_HVDCP_2_REG, val, val); + if (rc < 0) + smblib_err(chg, "Couldn't write to CMD_HVDCP_2_REG rc=%d\n", + rc); + + return rc; +} + +static int smblib_dp_pulse(struct smb_charger *chg) +{ + int rc; + + /* QC 3.0 increment */ + rc = smblib_masked_write(chg, CMD_HVDCP_2_REG, SINGLE_INCREMENT_BIT, + SINGLE_INCREMENT_BIT); + if (rc < 0) + smblib_err(chg, "Couldn't write to CMD_HVDCP_2_REG rc=%d\n", + rc); + + return rc; +} + +static int smblib_dm_pulse(struct smb_charger *chg) +{ + int rc; + + /* QC 3.0 decrement */ + rc = smblib_masked_write(chg, CMD_HVDCP_2_REG, SINGLE_DECREMENT_BIT, + SINGLE_DECREMENT_BIT); + if (rc < 0) + smblib_err(chg, "Couldn't write to CMD_HVDCP_2_REG rc=%d\n", + rc); + + return rc; +} + +int smblib_dp_dm(struct smb_charger *chg, int val) +{ + int target_icl_ua, rc = 0; + + switch (val) { + case POWER_SUPPLY_DP_DM_DP_PULSE: + rc = smblib_dp_pulse(chg); + if (!rc) + chg->pulse_cnt++; + smblib_dbg(chg, PR_PARALLEL, "DP_DM_DP_PULSE rc=%d cnt=%d\n", + rc, chg->pulse_cnt); + break; + case POWER_SUPPLY_DP_DM_DM_PULSE: + rc = smblib_dm_pulse(chg); + if (!rc && chg->pulse_cnt) + chg->pulse_cnt--; + smblib_dbg(chg, PR_PARALLEL, "DP_DM_DM_PULSE rc=%d cnt=%d\n", + rc, chg->pulse_cnt); + break; + case POWER_SUPPLY_DP_DM_ICL_DOWN: + chg->usb_icl_delta_ua -= 100000; + target_icl_ua = get_effective_result(chg->usb_icl_votable); + vote(chg->usb_icl_votable, SW_QC3_VOTER, true, + target_icl_ua + chg->usb_icl_delta_ua); + break; + case POWER_SUPPLY_DP_DM_ICL_UP: + default: + break; + } + + return rc; +} + /******************* * DC PSY GETTERS * *******************/ @@ -2915,26 +3080,38 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data) } #define USB_WEAK_INPUT_UA 1400000 +#define ICL_CHANGE_DELAY_MS 1000 irqreturn_t smblib_handle_icl_change(int irq, void *data) { + u8 stat; + int rc, settled_ua, delay = ICL_CHANGE_DELAY_MS; struct smb_irq_data *irq_data = data; struct smb_charger *chg = irq_data->parent_data; - int rc, settled_ua; - - rc = smblib_get_charge_param(chg, &chg->param.icl_stat, &settled_ua); - if (rc < 0) { - smblib_err(chg, "Couldn't get ICL status rc=%d\n", rc); - return IRQ_HANDLED; - } if (chg->mode == PARALLEL_MASTER) { - power_supply_changed(chg->usb_main_psy); - vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER, - settled_ua >= USB_WEAK_INPUT_UA, 0); + rc = smblib_read(chg, AICL_STATUS_REG, &stat); + if (rc < 0) { + smblib_err(chg, "Couldn't read AICL_STATUS rc=%d\n", + rc); + return IRQ_HANDLED; + } + + rc = smblib_get_charge_param(chg, &chg->param.icl_stat, + &settled_ua); + if (rc < 0) { + smblib_err(chg, "Couldn't get ICL status rc=%d\n", rc); + return IRQ_HANDLED; + } + + /* If AICL settled then schedule work now */ + if ((settled_ua == get_effective_result(chg->usb_icl_votable)) + || (stat & AICL_DONE_BIT)) + delay = 0; + + schedule_delayed_work(&chg->icl_change_work, + msecs_to_jiffies(delay)); } - smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s icl_settled=%d\n", - irq_data->name, settled_ua); return IRQ_HANDLED; } @@ -3279,6 +3456,8 @@ static void smblib_handle_typec_removal(struct smb_charger *chg) chg->vconn_attempts = 0; chg->otg_attempts = 0; + chg->pulse_cnt = 0; + chg->usb_icl_delta_ua = 0; chg->usb_ever_removed = true; @@ -3801,6 +3980,25 @@ static void smblib_otg_ss_done_work(struct work_struct *work) mutex_unlock(&chg->otg_oc_lock); } +static void smblib_icl_change_work(struct work_struct *work) +{ + struct smb_charger *chg = container_of(work, struct smb_charger, + icl_change_work.work); + int rc, settled_ua; + + rc = smblib_get_charge_param(chg, &chg->param.icl_stat, &settled_ua); + if (rc < 0) { + smblib_err(chg, "Couldn't get ICL status rc=%d\n", rc); + return; + } + + power_supply_changed(chg->usb_main_psy); + vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER, + settled_ua >= USB_WEAK_INPUT_UA, 0); + + smblib_dbg(chg, PR_INTERRUPT, "icl_settled=%d\n", settled_ua); +} + static int smblib_create_votables(struct smb_charger *chg) { int rc = 0; @@ -3917,6 +4115,15 @@ static int smblib_create_votables(struct smb_charger *chg) return rc; } + chg->hvdcp_hw_inov_dis_votable = create_votable("HVDCP_HW_INOV_DIS", + VOTE_SET_ANY, + smblib_hvdcp_hw_inov_dis_vote_callback, + chg); + if (IS_ERR(chg->hvdcp_hw_inov_dis_votable)) { + rc = PTR_ERR(chg->hvdcp_hw_inov_dis_votable); + return rc; + } + return rc; } @@ -3940,6 +4147,8 @@ static void smblib_destroy_votables(struct smb_charger *chg) destroy_votable(chg->pl_enable_votable_indirect); if (chg->apsd_disable_votable) destroy_votable(chg->apsd_disable_votable); + if (chg->hvdcp_hw_inov_dis_votable) + destroy_votable(chg->hvdcp_hw_inov_dis_votable); } static void smblib_iio_deinit(struct smb_charger *chg) @@ -3970,6 +4179,7 @@ int smblib_init(struct smb_charger *chg) INIT_WORK(&chg->otg_oc_work, smblib_otg_oc_work); INIT_WORK(&chg->vconn_oc_work, smblib_vconn_oc_work); INIT_DELAYED_WORK(&chg->otg_ss_done_work, smblib_otg_ss_done_work); + INIT_DELAYED_WORK(&chg->icl_change_work, smblib_icl_change_work); chg->fake_capacity = -EINVAL; switch (chg->mode) { diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h index bf2d863933ae..7c29954b3bff 100644 --- a/drivers/power/supply/qcom/smb-lib.h +++ b/drivers/power/supply/qcom/smb-lib.h @@ -56,6 +56,7 @@ enum print_reason { #define PD_SUSPEND_SUPPORTED_VOTER "PD_SUSPEND_SUPPORTED_VOTER" #define PL_DELAY_HVDCP_VOTER "PL_DELAY_HVDCP_VOTER" #define CTM_VOTER "CTM_VOTER" +#define SW_QC3_VOTER "SW_QC3_VOTER" #define VCONN_MAX_ATTEMPTS 3 #define OTG_MAX_ATTEMPTS 3 @@ -267,6 +268,7 @@ struct smb_charger { struct votable *hvdcp_disable_votable_indirect; struct votable *hvdcp_enable_votable; struct votable *apsd_disable_votable; + struct votable *hvdcp_hw_inov_dis_votable; /* work */ struct work_struct bms_update_work; @@ -278,6 +280,7 @@ struct smb_charger { struct work_struct otg_oc_work; struct work_struct vconn_oc_work; struct delayed_work otg_ss_done_work; + struct delayed_work icl_change_work; /* cached status */ int voltage_min_uv; @@ -315,6 +318,8 @@ struct smb_charger { /* qnovo */ int qnovo_fcc_ua; int qnovo_fv_uv; + int usb_icl_delta_ua; + int pulse_cnt; }; int smblib_read(struct smb_charger *chg, u16 addr, u8 *val); @@ -472,6 +477,8 @@ int smblib_get_prop_fcc_delta(struct smb_charger *chg, union power_supply_propval *val); int smblib_icl_override(struct smb_charger *chg, bool override); int smblib_set_icl_reduction(struct smb_charger *chg, int reduction_ua); +int smblib_dp_dm(struct smb_charger *chg, int val); +int smblib_rerun_aicl(struct smb_charger *chg); int smblib_init(struct smb_charger *chg); int smblib_deinit(struct smb_charger *chg); diff --git a/drivers/power/supply/qcom/smb-reg.h b/drivers/power/supply/qcom/smb-reg.h index e005a27e8dd9..54b6b38d134b 100644 --- a/drivers/power/supply/qcom/smb-reg.h +++ b/drivers/power/supply/qcom/smb-reg.h @@ -535,6 +535,8 @@ enum { #define USBIN_LT_3P6V_RT_STS_BIT BIT(1) #define USBIN_COLLAPSE_RT_STS_BIT BIT(0) +#define QC_PULSE_COUNT_STATUS_1_REG (USBIN_BASE + 0x30) + #define USBIN_CMD_IL_REG (USBIN_BASE + 0x40) #define BAT_2_SYS_FET_DIS_BIT BIT(1) #define USBIN_SUSPEND_BIT BIT(0) @@ -544,6 +546,7 @@ enum { #define APSD_RERUN_BIT BIT(0) #define CMD_HVDCP_2_REG (USBIN_BASE + 0x43) +#define RESTART_AICL_BIT BIT(7) #define TRIGGER_AICL_BIT BIT(6) #define FORCE_12V_BIT BIT(5) #define FORCE_9V_BIT BIT(4) diff --git a/drivers/power/supply/qcom/smb1351-charger.c b/drivers/power/supply/qcom/smb1351-charger.c index d0cf37b0613a..8467d167512f 100644 --- a/drivers/power/supply/qcom/smb1351-charger.c +++ b/drivers/power/supply/qcom/smb1351-charger.c @@ -460,6 +460,7 @@ struct smb1351_charger { int workaround_flags; int parallel_pin_polarity_setting; + int parallel_mode; bool parallel_charger; bool parallel_charger_suspended; bool bms_controlled_charging; @@ -1699,7 +1700,7 @@ static int smb1351_parallel_get_property(struct power_supply *psy, val->intval = 0; break; case POWER_SUPPLY_PROP_PARALLEL_MODE: - val->intval = POWER_SUPPLY_PARALLEL_USBIN_USBIN; + val->intval = chip->parallel_mode; break; default: return -EINVAL; @@ -3191,6 +3192,12 @@ static int smb1351_parallel_charger_probe(struct i2c_client *client, chip->parallel_pin_polarity_setting ? EN_BY_PIN_HIGH_ENABLE : EN_BY_PIN_LOW_ENABLE; + if (of_property_read_bool(node, + "qcom,parallel-external-current-sense")) + chip->parallel_mode = POWER_SUPPLY_PL_USBIN_USBIN_EXT; + else + chip->parallel_mode = POWER_SUPPLY_PL_USBIN_USBIN; + i2c_set_clientdata(client, chip); chip->parallel_psy_d.name = "parallel"; diff --git a/drivers/power/supply/qcom/smb138x-charger.c b/drivers/power/supply/qcom/smb138x-charger.c index 4180edc89a4c..6af9ce1c16df 100644 --- a/drivers/power/supply/qcom/smb138x-charger.c +++ b/drivers/power/supply/qcom/smb138x-charger.c @@ -493,7 +493,7 @@ static int smb138x_parallel_get_prop(struct power_supply *psy, val->strval = "smb138x"; break; case POWER_SUPPLY_PROP_PARALLEL_MODE: - val->intval = POWER_SUPPLY_PARALLEL_MID_MID; + val->intval = POWER_SUPPLY_PL_USBMID_USBMID; break; case POWER_SUPPLY_PROP_CONNECTOR_HEALTH: rc = smblib_get_prop_die_health(chg, val); diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 457d862cb9a8..1effc355d7d0 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -106,9 +106,10 @@ enum { }; enum { - POWER_SUPPLY_PARALLEL_NONE, - POWER_SUPPLY_PARALLEL_USBIN_USBIN, - POWER_SUPPLY_PARALLEL_MID_MID, + POWER_SUPPLY_PL_NONE, + POWER_SUPPLY_PL_USBIN_USBIN, + POWER_SUPPLY_PL_USBIN_USBIN_EXT, + POWER_SUPPLY_PL_USBMID_USBMID, }; enum power_supply_property { |