Loading drivers/power/supply/qcom/qpnp-smb5.c +17 −3 Original line number Diff line number Diff line Loading @@ -52,6 +52,13 @@ static struct smb_params smb5_pmi632_params = { .max_u = 3000000, .step_u = 50000, }, .icl_max_stat = { .name = "dcdc icl max status", .reg = ICL_MAX_STATUS_REG, .min_u = 0, .max_u = 3000000, .step_u = 50000, }, .icl_stat = { .name = "input current limit status", .reg = AICL_ICL_STATUS_REG, Loading Loading @@ -90,7 +97,7 @@ static struct smb_params smb5_pmi632_params = { }, }; static struct smb_params smb5_pmi855_params = { static struct smb_params smb5_pm855b_params = { .fcc = { .name = "fast charge current", .reg = CHGR_FAST_CHARGE_CURRENT_CFG_REG, Loading @@ -112,8 +119,15 @@ static struct smb_params smb5_pmi855_params = { .max_u = 5000000, .step_u = 50000, }, .icl_max_stat = { .name = "dcdc icl max status", .reg = ICL_MAX_STATUS_REG, .min_u = 0, .max_u = 5000000, .step_u = 50000, }, .icl_stat = { .name = "input current limit status", .name = "aicl icl status", .reg = AICL_ICL_STATUS_REG, .min_u = 0, .max_u = 5000000, Loading Loading @@ -221,7 +235,7 @@ static int smb5_chg_config_init(struct smb5 *chip) switch (pmic_rev_id->pmic_subtype) { case PM855B_SUBTYPE: chip->chg.smb_version = PM855B_SUBTYPE; chg->param = smb5_pmi855_params; chg->param = smb5_pm855b_params; chg->name = "pm855b_charger"; break; case PMI632_SUBTYPE: Loading drivers/power/supply/qcom/smb5-lib.c +135 −59 Original line number Diff line number Diff line Loading @@ -39,6 +39,10 @@ __func__, ##__VA_ARGS__); \ } while (0) #define typec_rp_med_high(chg, typec_mode) \ ((typec_mode == POWER_SUPPLY_TYPEC_SOURCE_MEDIUM \ || typec_mode == POWER_SUPPLY_TYPEC_SOURCE_HIGH) \ && !chg->typec_legacy) int smblib_read(struct smb_charger *chg, u16 addr, u8 *val) { Loading Loading @@ -654,7 +658,7 @@ int smblib_mapping_cc_delta_from_field_value(struct smb_chg_param *param, return 0; } #define USBIN_100MA 100000 #define SDP_100_MA 100000 static void smblib_uusb_removal(struct smb_charger *chg) { int rc; Loading @@ -679,6 +683,7 @@ static void smblib_uusb_removal(struct smb_charger *chg) /* reset both usbin current and voltage votes */ vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0); vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, false, 0); vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, SDP_100_MA); vote(chg->usb_icl_votable, SW_QC3_VOTER, false, 0); /* reconfigure allowed voltage for HVDCP */ Loading @@ -701,8 +706,6 @@ static void smblib_uusb_removal(struct smb_charger *chg) smblib_err(chg, "Couldn't write float charger options rc=%d\n", rc); /* leave the ICL configured to 100mA for next insertion */ vote(chg->usb_icl_votable, DEFAULT_100MA_VOTER, true, USBIN_100MA); /* clear USB ICL vote for USB_PSY_VOTER */ rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); if (rc < 0) Loading Loading @@ -768,6 +771,7 @@ static int smblib_get_pulse_cnt(struct smb_charger *chg, int *count) } #define USBIN_25MA 25000 #define USBIN_100MA 100000 #define USBIN_150MA 150000 #define USBIN_500MA 500000 #define USBIN_900MA 900000 Loading Loading @@ -881,6 +885,10 @@ int smblib_set_icl_current(struct smb_charger *chg, int icl_ua) set_mode: rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG, USBIN_MODE_CHG_BIT, hc_mode ? USBIN_MODE_CHG_BIT : 0); if (rc < 0) { smblib_err(chg, "Couldn't set USBIN_ICL_OPTIONS rc=%d\n", rc); goto out; } /* unsuspend after configuring current and override */ rc = smblib_set_usb_suspend(chg, false); Loading Loading @@ -921,7 +929,8 @@ int smblib_get_icl_current(struct smb_charger *chg, int *icl_ua) return INT_MAX; /* override is set */ rc = smblib_get_charge_param(chg, &chg->param.usb_icl, icl_ua); rc = smblib_get_charge_param(chg, &chg->param.icl_max_stat, icl_ua); if (rc < 0) { smblib_err(chg, "Couldn't get HC ICL rc=%d\n", rc); return rc; Loading Loading @@ -2103,24 +2112,40 @@ static int smblib_handle_usb_current(struct smb_charger *chg, if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_FLOAT) { if (usb_current == -ETIMEDOUT) { if ((chg->float_cfg & FLOAT_OPTIONS_MASK) == FORCE_FLOAT_SDP_CFG_BIT) { /* * Valid FLOAT charger, report the current based * of Rp * Confiugure USB500 mode if Float charger is * configured for SDP. */ rc = set_sdp_current(chg, USBIN_500MA); if (rc < 0) smblib_err(chg, "Couldn't set SDP ICL rc=%d\n", rc); return rc; } if (chg->connector_type == POWER_SUPPLY_CONNECTOR_TYPEC) { /* * Valid FLOAT charger, report the current * based of Rp. */ typec_mode = smblib_get_prop_typec_mode(chg); rp_ua = get_rp_based_dcp_current(chg, typec_mode); rc = vote(chg->usb_icl_votable, DYNAMIC_RP_VOTER, true, rp_ua); if (rc < 0) { pr_err("Couldn't vote ICL DYNAMIC_RP_VOTER rc=%d\n", rc); SW_ICL_MAX_VOTER, true, rp_ua); if (rc < 0) return rc; } else { rc = vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, DCP_CURRENT_UA); if (rc < 0) return rc; } } /* No specific handling required for micro-USB */ } else { /* * FLOAT charger detected as SDP by USB driver, Loading @@ -2130,11 +2155,12 @@ static int smblib_handle_usb_current(struct smb_charger *chg, chg->real_charger_type = POWER_SUPPLY_TYPE_USB; rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, true, usb_current); if (rc < 0) { pr_err("Couldn't vote ICL USB_PSY_VOTER rc=%d\n", rc); if (rc < 0) return rc; rc = vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, false, 0); if (rc < 0) return rc; } } } else { rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, Loading @@ -2144,14 +2170,14 @@ static int smblib_handle_usb_current(struct smb_charger *chg, return rc; } } rc = vote(chg->usb_icl_votable, DEFAULT_100MA_VOTER, false, 0); rc = vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, false, 0); if (rc < 0) { pr_err("Couldn't unvote ICL DEFAULT_100MA_VOTER rc=%d\n", rc); pr_err("Couldn't remove SW_ICL_MAX vote rc=%d\n", rc); return rc; } } return 0; } Loading Loading @@ -2285,7 +2311,9 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, * pd_current_max */ vote(chg->usb_icl_votable, PD_VOTER, true, USBIN_500MA); vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, false, 0); } else { vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, SDP_100_MA); vote(chg->usb_icl_votable, PD_VOTER, false, 0); vote(chg->usb_irq_enable_votable, PD_VOTER, false, 0); Loading Loading @@ -2828,18 +2856,17 @@ static void smblib_handle_hvdcp_check_timeout(struct smb_charger *chg, { if (rising) { if (qc_charger) { /* enable HDC and ICL irq for QC2/3 charger */ if (qc_charger) vote(chg->usb_irq_enable_votable, QC_VOTER, true, 0); else /* * HVDCP detection timeout done * If adapter is not QC2.0/QC3.0 - it is a plain old DCP. * enforce DCP ICL if specified */ vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, HVDCP_CURRENT_UA); } else { /* A plain DCP, enforce DCP ICL if specified */ vote(chg->usb_icl_votable, DCP_VOTER, chg->dcp_icl_ua != -EINVAL, chg->dcp_icl_ua); } } smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s %s\n", __func__, rising ? "rising" : "falling"); Loading @@ -2853,6 +2880,69 @@ static void smblib_handle_hvdcp_detect_done(struct smb_charger *chg, rising ? "rising" : "falling"); } static void update_sw_icl_max(struct smb_charger *chg, int pst) { int typec_mode; int rp_ua; /* while PD is active it should have complete ICL control */ if (chg->pd_active) return; /* * HVDCP 2/3, handled separately * For UNKNOWN(input not present) return without updating ICL */ if (pst == POWER_SUPPLY_TYPE_USB_HVDCP || pst == POWER_SUPPLY_TYPE_USB_HVDCP_3 || pst == POWER_SUPPLY_TYPE_UNKNOWN) return; /* TypeC rp med or high, use rp value */ typec_mode = smblib_get_prop_typec_mode(chg); if (typec_rp_med_high(chg, typec_mode)) { rp_ua = get_rp_based_dcp_current(chg, typec_mode); vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, rp_ua); return; } /* rp-std or legacy, USB BC 1.2 */ switch (pst) { case POWER_SUPPLY_TYPE_USB: /* * USB_PSY will vote to increase the current to 500/900mA once * enumeration is done. */ if (!is_client_vote_enabled(chg->usb_icl_votable, USB_PSY_VOTER)) vote(chg->usb_icl_votable, USB_PSY_VOTER, true, SDP_100_MA); vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, false, 0); break; case POWER_SUPPLY_TYPE_USB_CDP: vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, CDP_CURRENT_UA); break; case POWER_SUPPLY_TYPE_USB_DCP: vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, DCP_CURRENT_UA); break; case POWER_SUPPLY_TYPE_USB_FLOAT: /* * limit ICL to 100mA, the USB driver will enumerate to check * if this is a SDP and appropriately set the current */ vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, SDP_100_MA); break; default: smblib_err(chg, "Unknown APSD %d; forcing 500mA\n", pst); vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, SDP_CURRENT_UA); break; } } static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising) { const struct apsd_result *apsd_result; Loading @@ -2862,6 +2952,8 @@ static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising) apsd_result = smblib_update_usb_type(chg); update_sw_icl_max(chg, apsd_result->pst); switch (apsd_result->bit) { case SDP_CHARGER_BIT: case CDP_CHARGER_BIT: Loading @@ -2872,7 +2964,6 @@ static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising) break; case OCP_CHARGER_BIT: case DCP_CHARGER_BIT: vote(chg->usb_icl_votable, DEFAULT_100MA_VOTER, false, 0); break; default: break; Loading Loading @@ -3028,7 +3119,7 @@ static void typec_src_removal(struct smb_charger *chg) cancel_delayed_work_sync(&chg->pl_enable_work); /* reset input current limit voters */ vote(chg->usb_icl_votable, DEFAULT_100MA_VOTER, true, USBIN_100MA); vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, SDP_100_MA); vote(chg->usb_icl_votable, PD_VOTER, false, 0); vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); vote(chg->usb_icl_votable, DCP_VOTER, false, 0); Loading @@ -3036,7 +3127,6 @@ static void typec_src_removal(struct smb_charger *chg) vote(chg->usb_icl_votable, SW_QC3_VOTER, false, 0); vote(chg->usb_icl_votable, OTG_VOTER, false, 0); vote(chg->usb_icl_votable, CTM_VOTER, false, 0); vote(chg->usb_icl_votable, DYNAMIC_RP_VOTER, false, 0); /* reset usb irq voters */ vote(chg->usb_irq_enable_votable, PD_VOTER, false, 0); Loading Loading @@ -3081,41 +3171,27 @@ static void typec_src_removal(struct smb_charger *chg) static void smblib_handle_rp_change(struct smb_charger *chg, int typec_mode) { int rp_ua; const struct apsd_result *apsd = smblib_get_apsd_result(chg); if ((apsd->pst != POWER_SUPPLY_TYPE_USB_DCP) && (apsd->pst != POWER_SUPPLY_TYPE_USB_FLOAT)) return; /* * if APSD indicates FLOAT and the USB stack had detected SDP, * do not respond to Rp changes as we do not confirm that its * a legacy cable */ if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB) return; /* * We want the ICL vote @ 100mA for a FLOAT charger * until the detection by the USB stack is complete. * Ignore the Rp changes unless there is a * pre-existing valid vote. * pre-existing valid vote or FLOAT is configured for * SDP current. */ if (apsd->pst == POWER_SUPPLY_TYPE_USB_FLOAT && (get_client_vote(chg->usb_icl_votable, DEFAULT_100MA_VOTER) <= USBIN_100MA)) if (apsd->pst == POWER_SUPPLY_TYPE_USB_FLOAT) { if (get_client_vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER) <= USBIN_100MA || (chg->float_cfg & FLOAT_OPTIONS_MASK) == FORCE_FLOAT_SDP_CFG_BIT) return; } update_sw_icl_max(chg, apsd->pst); /* * handle Rp change for DCP/FLOAT/OCP. * Update the current only if the Rp is different from * the last Rp value. */ smblib_dbg(chg, PR_MISC, "CC change old_mode=%d new_mode=%d\n", chg->typec_mode, typec_mode); rp_ua = get_rp_based_dcp_current(chg, typec_mode); vote(chg->usb_icl_votable, DYNAMIC_RP_VOTER, true, rp_ua); } irqreturn_t typec_or_rid_detection_change_irq_handler(int irq, void *data) Loading drivers/power/supply/qcom/smb5-lib.h +2 −2 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ enum print_reason { #define CTM_VOTER "CTM_VOTER" #define SW_QC3_VOTER "SW_QC3_VOTER" #define AICL_RERUN_VOTER "AICL_RERUN_VOTER" #define SW_ICL_MAX_VOTER "SW_ICL_MAX_VOTER" #define QNOVO_VOTER "QNOVO_VOTER" #define BATT_PROFILE_VOTER "BATT_PROFILE_VOTER" #define OTG_DELAY_VOTER "OTG_DELAY_VOTER" Loading @@ -65,8 +66,6 @@ enum print_reason { #define PL_FCC_LOW_VOTER "PL_FCC_LOW_VOTER" #define WBC_VOTER "WBC_VOTER" #define HW_LIMIT_VOTER "HW_LIMIT_VOTER" #define DYNAMIC_RP_VOTER "DYNAMIC_RP_VOTER" #define DEFAULT_100MA_VOTER "DEFAULT_100MA_VOTER" #define FORCE_RECHARGE_VOTER "FORCE_RECHARGE_VOTER" #define BOOST_BACK_STORM_COUNT 3 Loading Loading @@ -234,6 +233,7 @@ struct smb_params { struct smb_chg_param fcc; struct smb_chg_param fv; struct smb_chg_param usb_icl; struct smb_chg_param icl_max_stat; struct smb_chg_param icl_stat; struct smb_chg_param otg_cl; struct smb_chg_param jeita_cc_comp_hot; Loading drivers/power/supply/qcom/smb5-reg.h +2 −0 Original line number Diff line number Diff line Loading @@ -105,6 +105,8 @@ enum { /******************************** * DCDC Peripheral Registers * ********************************/ #define ICL_MAX_STATUS_REG (DCDC_BASE + 0x06) #define AICL_ICL_STATUS_REG (DCDC_BASE + 0x08) #define AICL_STATUS_REG (DCDC_BASE + 0x0A) Loading Loading
drivers/power/supply/qcom/qpnp-smb5.c +17 −3 Original line number Diff line number Diff line Loading @@ -52,6 +52,13 @@ static struct smb_params smb5_pmi632_params = { .max_u = 3000000, .step_u = 50000, }, .icl_max_stat = { .name = "dcdc icl max status", .reg = ICL_MAX_STATUS_REG, .min_u = 0, .max_u = 3000000, .step_u = 50000, }, .icl_stat = { .name = "input current limit status", .reg = AICL_ICL_STATUS_REG, Loading Loading @@ -90,7 +97,7 @@ static struct smb_params smb5_pmi632_params = { }, }; static struct smb_params smb5_pmi855_params = { static struct smb_params smb5_pm855b_params = { .fcc = { .name = "fast charge current", .reg = CHGR_FAST_CHARGE_CURRENT_CFG_REG, Loading @@ -112,8 +119,15 @@ static struct smb_params smb5_pmi855_params = { .max_u = 5000000, .step_u = 50000, }, .icl_max_stat = { .name = "dcdc icl max status", .reg = ICL_MAX_STATUS_REG, .min_u = 0, .max_u = 5000000, .step_u = 50000, }, .icl_stat = { .name = "input current limit status", .name = "aicl icl status", .reg = AICL_ICL_STATUS_REG, .min_u = 0, .max_u = 5000000, Loading Loading @@ -221,7 +235,7 @@ static int smb5_chg_config_init(struct smb5 *chip) switch (pmic_rev_id->pmic_subtype) { case PM855B_SUBTYPE: chip->chg.smb_version = PM855B_SUBTYPE; chg->param = smb5_pmi855_params; chg->param = smb5_pm855b_params; chg->name = "pm855b_charger"; break; case PMI632_SUBTYPE: Loading
drivers/power/supply/qcom/smb5-lib.c +135 −59 Original line number Diff line number Diff line Loading @@ -39,6 +39,10 @@ __func__, ##__VA_ARGS__); \ } while (0) #define typec_rp_med_high(chg, typec_mode) \ ((typec_mode == POWER_SUPPLY_TYPEC_SOURCE_MEDIUM \ || typec_mode == POWER_SUPPLY_TYPEC_SOURCE_HIGH) \ && !chg->typec_legacy) int smblib_read(struct smb_charger *chg, u16 addr, u8 *val) { Loading Loading @@ -654,7 +658,7 @@ int smblib_mapping_cc_delta_from_field_value(struct smb_chg_param *param, return 0; } #define USBIN_100MA 100000 #define SDP_100_MA 100000 static void smblib_uusb_removal(struct smb_charger *chg) { int rc; Loading @@ -679,6 +683,7 @@ static void smblib_uusb_removal(struct smb_charger *chg) /* reset both usbin current and voltage votes */ vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0); vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, false, 0); vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, SDP_100_MA); vote(chg->usb_icl_votable, SW_QC3_VOTER, false, 0); /* reconfigure allowed voltage for HVDCP */ Loading @@ -701,8 +706,6 @@ static void smblib_uusb_removal(struct smb_charger *chg) smblib_err(chg, "Couldn't write float charger options rc=%d\n", rc); /* leave the ICL configured to 100mA for next insertion */ vote(chg->usb_icl_votable, DEFAULT_100MA_VOTER, true, USBIN_100MA); /* clear USB ICL vote for USB_PSY_VOTER */ rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); if (rc < 0) Loading Loading @@ -768,6 +771,7 @@ static int smblib_get_pulse_cnt(struct smb_charger *chg, int *count) } #define USBIN_25MA 25000 #define USBIN_100MA 100000 #define USBIN_150MA 150000 #define USBIN_500MA 500000 #define USBIN_900MA 900000 Loading Loading @@ -881,6 +885,10 @@ int smblib_set_icl_current(struct smb_charger *chg, int icl_ua) set_mode: rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG, USBIN_MODE_CHG_BIT, hc_mode ? USBIN_MODE_CHG_BIT : 0); if (rc < 0) { smblib_err(chg, "Couldn't set USBIN_ICL_OPTIONS rc=%d\n", rc); goto out; } /* unsuspend after configuring current and override */ rc = smblib_set_usb_suspend(chg, false); Loading Loading @@ -921,7 +929,8 @@ int smblib_get_icl_current(struct smb_charger *chg, int *icl_ua) return INT_MAX; /* override is set */ rc = smblib_get_charge_param(chg, &chg->param.usb_icl, icl_ua); rc = smblib_get_charge_param(chg, &chg->param.icl_max_stat, icl_ua); if (rc < 0) { smblib_err(chg, "Couldn't get HC ICL rc=%d\n", rc); return rc; Loading Loading @@ -2103,24 +2112,40 @@ static int smblib_handle_usb_current(struct smb_charger *chg, if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_FLOAT) { if (usb_current == -ETIMEDOUT) { if ((chg->float_cfg & FLOAT_OPTIONS_MASK) == FORCE_FLOAT_SDP_CFG_BIT) { /* * Valid FLOAT charger, report the current based * of Rp * Confiugure USB500 mode if Float charger is * configured for SDP. */ rc = set_sdp_current(chg, USBIN_500MA); if (rc < 0) smblib_err(chg, "Couldn't set SDP ICL rc=%d\n", rc); return rc; } if (chg->connector_type == POWER_SUPPLY_CONNECTOR_TYPEC) { /* * Valid FLOAT charger, report the current * based of Rp. */ typec_mode = smblib_get_prop_typec_mode(chg); rp_ua = get_rp_based_dcp_current(chg, typec_mode); rc = vote(chg->usb_icl_votable, DYNAMIC_RP_VOTER, true, rp_ua); if (rc < 0) { pr_err("Couldn't vote ICL DYNAMIC_RP_VOTER rc=%d\n", rc); SW_ICL_MAX_VOTER, true, rp_ua); if (rc < 0) return rc; } else { rc = vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, DCP_CURRENT_UA); if (rc < 0) return rc; } } /* No specific handling required for micro-USB */ } else { /* * FLOAT charger detected as SDP by USB driver, Loading @@ -2130,11 +2155,12 @@ static int smblib_handle_usb_current(struct smb_charger *chg, chg->real_charger_type = POWER_SUPPLY_TYPE_USB; rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, true, usb_current); if (rc < 0) { pr_err("Couldn't vote ICL USB_PSY_VOTER rc=%d\n", rc); if (rc < 0) return rc; rc = vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, false, 0); if (rc < 0) return rc; } } } else { rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, Loading @@ -2144,14 +2170,14 @@ static int smblib_handle_usb_current(struct smb_charger *chg, return rc; } } rc = vote(chg->usb_icl_votable, DEFAULT_100MA_VOTER, false, 0); rc = vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, false, 0); if (rc < 0) { pr_err("Couldn't unvote ICL DEFAULT_100MA_VOTER rc=%d\n", rc); pr_err("Couldn't remove SW_ICL_MAX vote rc=%d\n", rc); return rc; } } return 0; } Loading Loading @@ -2285,7 +2311,9 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, * pd_current_max */ vote(chg->usb_icl_votable, PD_VOTER, true, USBIN_500MA); vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, false, 0); } else { vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, SDP_100_MA); vote(chg->usb_icl_votable, PD_VOTER, false, 0); vote(chg->usb_irq_enable_votable, PD_VOTER, false, 0); Loading Loading @@ -2828,18 +2856,17 @@ static void smblib_handle_hvdcp_check_timeout(struct smb_charger *chg, { if (rising) { if (qc_charger) { /* enable HDC and ICL irq for QC2/3 charger */ if (qc_charger) vote(chg->usb_irq_enable_votable, QC_VOTER, true, 0); else /* * HVDCP detection timeout done * If adapter is not QC2.0/QC3.0 - it is a plain old DCP. * enforce DCP ICL if specified */ vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, HVDCP_CURRENT_UA); } else { /* A plain DCP, enforce DCP ICL if specified */ vote(chg->usb_icl_votable, DCP_VOTER, chg->dcp_icl_ua != -EINVAL, chg->dcp_icl_ua); } } smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s %s\n", __func__, rising ? "rising" : "falling"); Loading @@ -2853,6 +2880,69 @@ static void smblib_handle_hvdcp_detect_done(struct smb_charger *chg, rising ? "rising" : "falling"); } static void update_sw_icl_max(struct smb_charger *chg, int pst) { int typec_mode; int rp_ua; /* while PD is active it should have complete ICL control */ if (chg->pd_active) return; /* * HVDCP 2/3, handled separately * For UNKNOWN(input not present) return without updating ICL */ if (pst == POWER_SUPPLY_TYPE_USB_HVDCP || pst == POWER_SUPPLY_TYPE_USB_HVDCP_3 || pst == POWER_SUPPLY_TYPE_UNKNOWN) return; /* TypeC rp med or high, use rp value */ typec_mode = smblib_get_prop_typec_mode(chg); if (typec_rp_med_high(chg, typec_mode)) { rp_ua = get_rp_based_dcp_current(chg, typec_mode); vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, rp_ua); return; } /* rp-std or legacy, USB BC 1.2 */ switch (pst) { case POWER_SUPPLY_TYPE_USB: /* * USB_PSY will vote to increase the current to 500/900mA once * enumeration is done. */ if (!is_client_vote_enabled(chg->usb_icl_votable, USB_PSY_VOTER)) vote(chg->usb_icl_votable, USB_PSY_VOTER, true, SDP_100_MA); vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, false, 0); break; case POWER_SUPPLY_TYPE_USB_CDP: vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, CDP_CURRENT_UA); break; case POWER_SUPPLY_TYPE_USB_DCP: vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, DCP_CURRENT_UA); break; case POWER_SUPPLY_TYPE_USB_FLOAT: /* * limit ICL to 100mA, the USB driver will enumerate to check * if this is a SDP and appropriately set the current */ vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, SDP_100_MA); break; default: smblib_err(chg, "Unknown APSD %d; forcing 500mA\n", pst); vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, SDP_CURRENT_UA); break; } } static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising) { const struct apsd_result *apsd_result; Loading @@ -2862,6 +2952,8 @@ static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising) apsd_result = smblib_update_usb_type(chg); update_sw_icl_max(chg, apsd_result->pst); switch (apsd_result->bit) { case SDP_CHARGER_BIT: case CDP_CHARGER_BIT: Loading @@ -2872,7 +2964,6 @@ static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising) break; case OCP_CHARGER_BIT: case DCP_CHARGER_BIT: vote(chg->usb_icl_votable, DEFAULT_100MA_VOTER, false, 0); break; default: break; Loading Loading @@ -3028,7 +3119,7 @@ static void typec_src_removal(struct smb_charger *chg) cancel_delayed_work_sync(&chg->pl_enable_work); /* reset input current limit voters */ vote(chg->usb_icl_votable, DEFAULT_100MA_VOTER, true, USBIN_100MA); vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, SDP_100_MA); vote(chg->usb_icl_votable, PD_VOTER, false, 0); vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); vote(chg->usb_icl_votable, DCP_VOTER, false, 0); Loading @@ -3036,7 +3127,6 @@ static void typec_src_removal(struct smb_charger *chg) vote(chg->usb_icl_votable, SW_QC3_VOTER, false, 0); vote(chg->usb_icl_votable, OTG_VOTER, false, 0); vote(chg->usb_icl_votable, CTM_VOTER, false, 0); vote(chg->usb_icl_votable, DYNAMIC_RP_VOTER, false, 0); /* reset usb irq voters */ vote(chg->usb_irq_enable_votable, PD_VOTER, false, 0); Loading Loading @@ -3081,41 +3171,27 @@ static void typec_src_removal(struct smb_charger *chg) static void smblib_handle_rp_change(struct smb_charger *chg, int typec_mode) { int rp_ua; const struct apsd_result *apsd = smblib_get_apsd_result(chg); if ((apsd->pst != POWER_SUPPLY_TYPE_USB_DCP) && (apsd->pst != POWER_SUPPLY_TYPE_USB_FLOAT)) return; /* * if APSD indicates FLOAT and the USB stack had detected SDP, * do not respond to Rp changes as we do not confirm that its * a legacy cable */ if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB) return; /* * We want the ICL vote @ 100mA for a FLOAT charger * until the detection by the USB stack is complete. * Ignore the Rp changes unless there is a * pre-existing valid vote. * pre-existing valid vote or FLOAT is configured for * SDP current. */ if (apsd->pst == POWER_SUPPLY_TYPE_USB_FLOAT && (get_client_vote(chg->usb_icl_votable, DEFAULT_100MA_VOTER) <= USBIN_100MA)) if (apsd->pst == POWER_SUPPLY_TYPE_USB_FLOAT) { if (get_client_vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER) <= USBIN_100MA || (chg->float_cfg & FLOAT_OPTIONS_MASK) == FORCE_FLOAT_SDP_CFG_BIT) return; } update_sw_icl_max(chg, apsd->pst); /* * handle Rp change for DCP/FLOAT/OCP. * Update the current only if the Rp is different from * the last Rp value. */ smblib_dbg(chg, PR_MISC, "CC change old_mode=%d new_mode=%d\n", chg->typec_mode, typec_mode); rp_ua = get_rp_based_dcp_current(chg, typec_mode); vote(chg->usb_icl_votable, DYNAMIC_RP_VOTER, true, rp_ua); } irqreturn_t typec_or_rid_detection_change_irq_handler(int irq, void *data) Loading
drivers/power/supply/qcom/smb5-lib.h +2 −2 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ enum print_reason { #define CTM_VOTER "CTM_VOTER" #define SW_QC3_VOTER "SW_QC3_VOTER" #define AICL_RERUN_VOTER "AICL_RERUN_VOTER" #define SW_ICL_MAX_VOTER "SW_ICL_MAX_VOTER" #define QNOVO_VOTER "QNOVO_VOTER" #define BATT_PROFILE_VOTER "BATT_PROFILE_VOTER" #define OTG_DELAY_VOTER "OTG_DELAY_VOTER" Loading @@ -65,8 +66,6 @@ enum print_reason { #define PL_FCC_LOW_VOTER "PL_FCC_LOW_VOTER" #define WBC_VOTER "WBC_VOTER" #define HW_LIMIT_VOTER "HW_LIMIT_VOTER" #define DYNAMIC_RP_VOTER "DYNAMIC_RP_VOTER" #define DEFAULT_100MA_VOTER "DEFAULT_100MA_VOTER" #define FORCE_RECHARGE_VOTER "FORCE_RECHARGE_VOTER" #define BOOST_BACK_STORM_COUNT 3 Loading Loading @@ -234,6 +233,7 @@ struct smb_params { struct smb_chg_param fcc; struct smb_chg_param fv; struct smb_chg_param usb_icl; struct smb_chg_param icl_max_stat; struct smb_chg_param icl_stat; struct smb_chg_param otg_cl; struct smb_chg_param jeita_cc_comp_hot; Loading
drivers/power/supply/qcom/smb5-reg.h +2 −0 Original line number Diff line number Diff line Loading @@ -105,6 +105,8 @@ enum { /******************************** * DCDC Peripheral Registers * ********************************/ #define ICL_MAX_STATUS_REG (DCDC_BASE + 0x06) #define AICL_ICL_STATUS_REG (DCDC_BASE + 0x08) #define AICL_STATUS_REG (DCDC_BASE + 0x0A) Loading