Loading drivers/power/power_supply_sysfs.c +7 −1 Original line number Diff line number Diff line Loading @@ -60,7 +60,7 @@ static ssize_t power_supply_show_property(struct device *dev, "Unknown", "Good", "Overheat", "Dead", "Over voltage", "Unspecified failure", "Cold", "Watchdog timer expire", "Safety timer expire", "Warm", "Cool" "Warm", "Cool", "Hot" }; static char *technology_text[] = { "Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe", "NiCd", Loading Loading @@ -122,6 +122,10 @@ static ssize_t power_supply_show_property(struct device *dev, return sprintf(buf, "%s\n", typec_text[value.intval]); else if (off == POWER_SUPPLY_PROP_TYPEC_POWER_ROLE) return sprintf(buf, "%s\n", typec_pr_text[value.intval]); else if (off == POWER_SUPPLY_PROP_DIE_HEALTH) return sprintf(buf, "%s\n", health_text[value.intval]); else if (off == POWER_SUPPLY_PROP_CONNECTOR_HEALTH) return sprintf(buf, "%s\n", health_text[value.intval]); else if (off >= POWER_SUPPLY_PROP_MODEL_NAME) return sprintf(buf, "%s\n", value.strval); Loading Loading @@ -283,6 +287,8 @@ static struct device_attribute power_supply_attrs[] = { POWER_SUPPLY_ATTR(icl_reduction), POWER_SUPPLY_ATTR(parallel_mode), POWER_SUPPLY_ATTR(connector_therm_zone), POWER_SUPPLY_ATTR(die_health), POWER_SUPPLY_ATTR(connector_health), /* Local extensions of type int64_t */ POWER_SUPPLY_ATTR(charge_counter_ext), /* Properties of type `const char *' */ Loading drivers/power/supply/qcom/qpnp-smb2.c +6 −4 Original line number Diff line number Diff line Loading @@ -664,8 +664,7 @@ static int smb2_usb_main_set_prop(struct power_supply *psy, rc = smblib_set_charge_param(chg, &chg->param.fv, val->intval); break; case POWER_SUPPLY_PROP_ICL_REDUCTION: chg->icl_reduction_ua = val->intval; rc = rerun_election(chg->usb_icl_votable); rc = smblib_set_icl_reduction(chg, val->intval); break; case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: rc = smblib_set_charge_param(chg, &chg->param.fcc, val->intval); Loading Loading @@ -1317,9 +1316,10 @@ static int smb2_init_hw(struct smb2 *chip) if (chip->dt.fv_uv < 0) smblib_get_charge_param(chg, &chg->param.fv, &chip->dt.fv_uv); if (chip->dt.usb_icl_ua < 0) smblib_get_charge_param(chg, &chg->param.usb_icl, &chip->dt.usb_icl_ua); &chg->default_icl_ua); if (chip->dt.usb_icl_ua < 0) chip->dt.usb_icl_ua = chg->default_icl_ua; if (chip->dt.dc_icl_ua < 0) smblib_get_charge_param(chg, &chg->param.dc_icl, Loading Loading @@ -1581,6 +1581,7 @@ static int smb2_chg_config_init(struct smb2 *chip) switch (pmic_rev_id->pmic_subtype) { case PMI8998_SUBTYPE: chip->chg.smb_version = PMI8998_SUBTYPE; chip->chg.wa_flags |= BOOST_BACK_WA; if (pmic_rev_id->rev4 == PMI8998_V1P1_REV4) /* PMI rev 1.1 */ chg->wa_flags |= QC_CHARGER_DETECTION_WA_BIT; Loading @@ -1595,6 +1596,7 @@ static int smb2_chg_config_init(struct smb2 *chip) chg->chg_freq.freq_above_otg_threshold = 800; break; case PM660_SUBTYPE: chip->chg.smb_version = PM660_SUBTYPE; chip->chg.wa_flags |= BOOST_BACK_WA; chg->param.freq_buck = pm660_params.freq_buck; chg->param.freq_boost = pm660_params.freq_boost; Loading drivers/power/supply/qcom/smb-lib.c +198 −41 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include <linux/iio/consumer.h> #include <linux/power_supply.h> #include <linux/regulator/driver.h> #include <linux/qpnp/qpnp-revid.h> #include <linux/input/qpnp-power-on.h> #include <linux/irq.h> #include "smb-lib.h" Loading Loading @@ -156,11 +157,24 @@ int smblib_icl_override(struct smb_charger *chg, bool override) int rc; bool override_status; u8 stat; u16 reg; rc = smblib_read(chg, APSD_RESULT_STATUS_REG, &stat); switch (chg->smb_version) { case PMI8998_SUBTYPE: reg = APSD_RESULT_STATUS_REG; break; case PM660_SUBTYPE: reg = AICL_STATUS_REG; break; default: smblib_dbg(chg, PR_MISC, "Unknown chip version=%x\n", chg->smb_version); return -EINVAL; } rc = smblib_read(chg, reg, &stat); if (rc < 0) { smblib_err(chg, "Couldn't read APSD_RESULT_STATUS_REG rc=%d\n", rc); smblib_err(chg, "Couldn't read reg=%x rc=%d\n", reg, rc); return rc; } override_status = (bool)(stat & ICL_OVERRIDE_LATCH_BIT); Loading Loading @@ -640,6 +654,19 @@ static void smblib_uusb_removal(struct smb_charger *chg) rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); if (rc < 0) smblib_err(chg, "Couldn't un-vote for USB ICL rc=%d\n", rc); /* clear USB ICL vote for DCP_VOTER */ rc = vote(chg->usb_icl_votable, DCP_VOTER, false, 0); if (rc < 0) smblib_err(chg, "Couldn't un-vote DCP from USB ICL rc=%d\n", rc); /* clear USB ICL vote for PL_USBIN_USBIN_VOTER */ rc = vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, false, 0); if (rc < 0) smblib_err(chg, "Couldn't un-vote PL_USBIN_USBIN from USB ICL rc=%d\n", rc); } static bool smblib_sysok_reason_usbin(struct smb_charger *chg) Loading Loading @@ -2203,12 +2230,19 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, return rc; } /* remove DCP_VOTER */ /* clear USB ICL vote for DCP_VOTER */ rc = vote(chg->usb_icl_votable, DCP_VOTER, false, 0); if (rc < 0) { smblib_err(chg, "Couldn't unvote DCP rc=%d\n", rc); return rc; } if (rc < 0) smblib_err(chg, "Couldn't un-vote DCP from USB ICL rc=%d\n", rc); /* clear USB ICL vote for PL_USBIN_USBIN_VOTER */ rc = vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, false, 0); if (rc < 0) smblib_err(chg, "Couldn't un-vote PL_USBIN_USBIN from USB ICL rc=%d\n", rc); /* remove USB_PSY_VOTER */ rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); Loading Loading @@ -2255,39 +2289,6 @@ int smblib_set_prop_ship_mode(struct smb_charger *chg, return rc; } /*********************** * USB MAIN PSY GETTERS * *************************/ int smblib_get_prop_fcc_delta(struct smb_charger *chg, union power_supply_propval *val) { int rc, jeita_cc_delta_ua, step_cc_delta_ua, hw_cc_delta_ua = 0; rc = smblib_get_step_cc_delta(chg, &step_cc_delta_ua); if (rc < 0) { smblib_err(chg, "Couldn't get step cc delta rc=%d\n", rc); step_cc_delta_ua = 0; } else { hw_cc_delta_ua = step_cc_delta_ua; } rc = smblib_get_jeita_cc_delta(chg, &jeita_cc_delta_ua); if (rc < 0) { smblib_err(chg, "Couldn't get jeita cc delta rc=%d\n", rc); jeita_cc_delta_ua = 0; } else if (jeita_cc_delta_ua < 0) { /* HW will take the min between JEITA and step charge */ hw_cc_delta_ua = min(hw_cc_delta_ua, jeita_cc_delta_ua); } val->intval = hw_cc_delta_ua; return 0; } /*********************** * USB MAIN PSY SETTERS * *************************/ int smblib_reg_block_update(struct smb_charger *chg, struct reg_info *entry) { Loading Loading @@ -2463,6 +2464,155 @@ int smblib_set_prop_pd_in_hard_reset(struct smb_charger *chg, return rc; } /*********************** * USB MAIN PSY GETTERS * *************************/ int smblib_get_prop_fcc_delta(struct smb_charger *chg, union power_supply_propval *val) { int rc, jeita_cc_delta_ua, step_cc_delta_ua, hw_cc_delta_ua = 0; rc = smblib_get_step_cc_delta(chg, &step_cc_delta_ua); if (rc < 0) { smblib_err(chg, "Couldn't get step cc delta rc=%d\n", rc); step_cc_delta_ua = 0; } else { hw_cc_delta_ua = step_cc_delta_ua; } rc = smblib_get_jeita_cc_delta(chg, &jeita_cc_delta_ua); if (rc < 0) { smblib_err(chg, "Couldn't get jeita cc delta rc=%d\n", rc); jeita_cc_delta_ua = 0; } else if (jeita_cc_delta_ua < 0) { /* HW will take the min between JEITA and step charge */ hw_cc_delta_ua = min(hw_cc_delta_ua, jeita_cc_delta_ua); } val->intval = hw_cc_delta_ua; return 0; } /*********************** * USB MAIN PSY SETTERS * *************************/ #define SDP_CURRENT_MA 500000 #define CDP_CURRENT_MA 1500000 #define DCP_CURRENT_MA 1500000 #define HVDCP_CURRENT_MA 3000000 #define TYPEC_DEFAULT_CURRENT_MA 900000 #define TYPEC_MEDIUM_CURRENT_MA 1500000 #define TYPEC_HIGH_CURRENT_MA 3000000 static int smblib_get_charge_current(struct smb_charger *chg, int *total_current_ua) { const struct apsd_result *apsd_result = smblib_update_usb_type(chg); union power_supply_propval val = {0, }; int rc, typec_source_rd, current_ua; bool non_compliant; u8 stat5; rc = smblib_read(chg, TYPE_C_STATUS_5_REG, &stat5); if (rc < 0) { smblib_err(chg, "Couldn't read TYPE_C_STATUS_5 rc=%d\n", rc); return rc; } non_compliant = stat5 & TYPEC_NONCOMP_LEGACY_CABLE_STATUS_BIT; /* get settled ICL */ rc = smblib_get_prop_input_current_settled(chg, &val); if (rc < 0) { smblib_err(chg, "Couldn't get settled ICL rc=%d\n", rc); return rc; } typec_source_rd = smblib_get_prop_ufp_mode(chg); /* QC 2.0/3.0 adapter */ if (apsd_result->bit & (QC_3P0_BIT | QC_2P0_BIT)) { *total_current_ua = HVDCP_CURRENT_MA; return 0; } if (non_compliant) { switch (apsd_result->bit) { case CDP_CHARGER_BIT: current_ua = CDP_CURRENT_MA; break; case DCP_CHARGER_BIT: case OCP_CHARGER_BIT: case FLOAT_CHARGER_BIT: current_ua = DCP_CURRENT_MA; break; default: current_ua = 0; break; } *total_current_ua = max(current_ua, val.intval); return 0; } switch (typec_source_rd) { case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT: switch (apsd_result->bit) { case CDP_CHARGER_BIT: current_ua = CDP_CURRENT_MA; break; case DCP_CHARGER_BIT: case OCP_CHARGER_BIT: case FLOAT_CHARGER_BIT: current_ua = chg->default_icl_ua; break; default: current_ua = 0; break; } break; case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM: current_ua = TYPEC_MEDIUM_CURRENT_MA; break; case POWER_SUPPLY_TYPEC_SOURCE_HIGH: current_ua = TYPEC_HIGH_CURRENT_MA; break; case POWER_SUPPLY_TYPEC_NON_COMPLIANT: case POWER_SUPPLY_TYPEC_NONE: default: current_ua = 0; break; } *total_current_ua = max(current_ua, val.intval); return 0; } int smblib_set_icl_reduction(struct smb_charger *chg, int reduction_ua) { int current_ua, rc; if (reduction_ua == 0) { chg->icl_reduction_ua = 0; vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, false, 0); } else { /* * No usb_icl voter means we are defaulting to hw chosen * max limit. We need a vote from s/w to enforce the reduction. */ if (get_effective_result(chg->usb_icl_votable) == -EINVAL) { rc = smblib_get_charge_current(chg, ¤t_ua); if (rc < 0) { pr_err("Failed to get ICL rc=%d\n", rc); return rc; } vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, true, current_ua); } } return rerun_election(chg->usb_icl_votable); } /************************ * PARALLEL PSY GETTERS * ************************/ Loading Loading @@ -2984,6 +3134,13 @@ static void typec_source_removal(struct smb_charger *chg) if (rc < 0) smblib_err(chg, "Couldn't un-vote DCP from USB ICL rc=%d\n", rc); /* clear USB ICL vote for PL_USBIN_USBIN_VOTER */ rc = vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, false, 0); if (rc < 0) smblib_err(chg, "Couldn't un-vote PL_USBIN_USBIN from USB ICL rc=%d\n", rc); } static void typec_source_insertion(struct smb_charger *chg) Loading drivers/power/supply/qcom/smb-lib.h +4 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ enum print_reason { #define USER_VOTER "USER_VOTER" #define PD_VOTER "PD_VOTER" #define DCP_VOTER "DCP_VOTER" #define PL_USBIN_USBIN_VOTER "PL_USBIN_USBIN_VOTER" #define USB_PSY_VOTER "USB_PSY_VOTER" #define PL_TAPER_WORK_RUNNING_VOTER "PL_TAPER_WORK_RUNNING_VOTER" #define PL_INDIRECT_VOTER "PL_INDIRECT_VOTER" Loading Loading @@ -171,6 +172,7 @@ struct smb_charger { enum smb_mode mode; bool external_vconn; struct smb_chg_freq chg_freq; int smb_version; /* locks */ struct mutex write_lock; Loading Loading @@ -244,6 +246,7 @@ struct smb_charger { bool vconn_en; int otg_attempts; int vconn_attempts; int default_icl_ua; /* workaround flag */ u32 wa_flags; Loading Loading @@ -408,6 +411,7 @@ int smblib_rerun_apsd_if_required(struct smb_charger *chg); 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_init(struct smb_charger *chg); int smblib_deinit(struct smb_charger *chg); Loading include/linux/power_supply.h +3 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,7 @@ enum { POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE, POWER_SUPPLY_HEALTH_WARM, POWER_SUPPLY_HEALTH_COOL, POWER_SUPPLY_HEALTH_HOT, }; enum { Loading Loading @@ -238,6 +239,8 @@ enum power_supply_property { POWER_SUPPLY_PROP_ICL_REDUCTION, POWER_SUPPLY_PROP_PARALLEL_MODE, POWER_SUPPLY_PROP_CONNECTOR_THERM_ZONE, POWER_SUPPLY_PROP_DIE_HEALTH, POWER_SUPPLY_PROP_CONNECTOR_HEALTH, /* Local extensions of type int64_t */ POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT, /* Properties of type `const char *' */ Loading Loading
drivers/power/power_supply_sysfs.c +7 −1 Original line number Diff line number Diff line Loading @@ -60,7 +60,7 @@ static ssize_t power_supply_show_property(struct device *dev, "Unknown", "Good", "Overheat", "Dead", "Over voltage", "Unspecified failure", "Cold", "Watchdog timer expire", "Safety timer expire", "Warm", "Cool" "Warm", "Cool", "Hot" }; static char *technology_text[] = { "Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe", "NiCd", Loading Loading @@ -122,6 +122,10 @@ static ssize_t power_supply_show_property(struct device *dev, return sprintf(buf, "%s\n", typec_text[value.intval]); else if (off == POWER_SUPPLY_PROP_TYPEC_POWER_ROLE) return sprintf(buf, "%s\n", typec_pr_text[value.intval]); else if (off == POWER_SUPPLY_PROP_DIE_HEALTH) return sprintf(buf, "%s\n", health_text[value.intval]); else if (off == POWER_SUPPLY_PROP_CONNECTOR_HEALTH) return sprintf(buf, "%s\n", health_text[value.intval]); else if (off >= POWER_SUPPLY_PROP_MODEL_NAME) return sprintf(buf, "%s\n", value.strval); Loading Loading @@ -283,6 +287,8 @@ static struct device_attribute power_supply_attrs[] = { POWER_SUPPLY_ATTR(icl_reduction), POWER_SUPPLY_ATTR(parallel_mode), POWER_SUPPLY_ATTR(connector_therm_zone), POWER_SUPPLY_ATTR(die_health), POWER_SUPPLY_ATTR(connector_health), /* Local extensions of type int64_t */ POWER_SUPPLY_ATTR(charge_counter_ext), /* Properties of type `const char *' */ Loading
drivers/power/supply/qcom/qpnp-smb2.c +6 −4 Original line number Diff line number Diff line Loading @@ -664,8 +664,7 @@ static int smb2_usb_main_set_prop(struct power_supply *psy, rc = smblib_set_charge_param(chg, &chg->param.fv, val->intval); break; case POWER_SUPPLY_PROP_ICL_REDUCTION: chg->icl_reduction_ua = val->intval; rc = rerun_election(chg->usb_icl_votable); rc = smblib_set_icl_reduction(chg, val->intval); break; case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: rc = smblib_set_charge_param(chg, &chg->param.fcc, val->intval); Loading Loading @@ -1317,9 +1316,10 @@ static int smb2_init_hw(struct smb2 *chip) if (chip->dt.fv_uv < 0) smblib_get_charge_param(chg, &chg->param.fv, &chip->dt.fv_uv); if (chip->dt.usb_icl_ua < 0) smblib_get_charge_param(chg, &chg->param.usb_icl, &chip->dt.usb_icl_ua); &chg->default_icl_ua); if (chip->dt.usb_icl_ua < 0) chip->dt.usb_icl_ua = chg->default_icl_ua; if (chip->dt.dc_icl_ua < 0) smblib_get_charge_param(chg, &chg->param.dc_icl, Loading Loading @@ -1581,6 +1581,7 @@ static int smb2_chg_config_init(struct smb2 *chip) switch (pmic_rev_id->pmic_subtype) { case PMI8998_SUBTYPE: chip->chg.smb_version = PMI8998_SUBTYPE; chip->chg.wa_flags |= BOOST_BACK_WA; if (pmic_rev_id->rev4 == PMI8998_V1P1_REV4) /* PMI rev 1.1 */ chg->wa_flags |= QC_CHARGER_DETECTION_WA_BIT; Loading @@ -1595,6 +1596,7 @@ static int smb2_chg_config_init(struct smb2 *chip) chg->chg_freq.freq_above_otg_threshold = 800; break; case PM660_SUBTYPE: chip->chg.smb_version = PM660_SUBTYPE; chip->chg.wa_flags |= BOOST_BACK_WA; chg->param.freq_buck = pm660_params.freq_buck; chg->param.freq_boost = pm660_params.freq_boost; Loading
drivers/power/supply/qcom/smb-lib.c +198 −41 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include <linux/iio/consumer.h> #include <linux/power_supply.h> #include <linux/regulator/driver.h> #include <linux/qpnp/qpnp-revid.h> #include <linux/input/qpnp-power-on.h> #include <linux/irq.h> #include "smb-lib.h" Loading Loading @@ -156,11 +157,24 @@ int smblib_icl_override(struct smb_charger *chg, bool override) int rc; bool override_status; u8 stat; u16 reg; rc = smblib_read(chg, APSD_RESULT_STATUS_REG, &stat); switch (chg->smb_version) { case PMI8998_SUBTYPE: reg = APSD_RESULT_STATUS_REG; break; case PM660_SUBTYPE: reg = AICL_STATUS_REG; break; default: smblib_dbg(chg, PR_MISC, "Unknown chip version=%x\n", chg->smb_version); return -EINVAL; } rc = smblib_read(chg, reg, &stat); if (rc < 0) { smblib_err(chg, "Couldn't read APSD_RESULT_STATUS_REG rc=%d\n", rc); smblib_err(chg, "Couldn't read reg=%x rc=%d\n", reg, rc); return rc; } override_status = (bool)(stat & ICL_OVERRIDE_LATCH_BIT); Loading Loading @@ -640,6 +654,19 @@ static void smblib_uusb_removal(struct smb_charger *chg) rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); if (rc < 0) smblib_err(chg, "Couldn't un-vote for USB ICL rc=%d\n", rc); /* clear USB ICL vote for DCP_VOTER */ rc = vote(chg->usb_icl_votable, DCP_VOTER, false, 0); if (rc < 0) smblib_err(chg, "Couldn't un-vote DCP from USB ICL rc=%d\n", rc); /* clear USB ICL vote for PL_USBIN_USBIN_VOTER */ rc = vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, false, 0); if (rc < 0) smblib_err(chg, "Couldn't un-vote PL_USBIN_USBIN from USB ICL rc=%d\n", rc); } static bool smblib_sysok_reason_usbin(struct smb_charger *chg) Loading Loading @@ -2203,12 +2230,19 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, return rc; } /* remove DCP_VOTER */ /* clear USB ICL vote for DCP_VOTER */ rc = vote(chg->usb_icl_votable, DCP_VOTER, false, 0); if (rc < 0) { smblib_err(chg, "Couldn't unvote DCP rc=%d\n", rc); return rc; } if (rc < 0) smblib_err(chg, "Couldn't un-vote DCP from USB ICL rc=%d\n", rc); /* clear USB ICL vote for PL_USBIN_USBIN_VOTER */ rc = vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, false, 0); if (rc < 0) smblib_err(chg, "Couldn't un-vote PL_USBIN_USBIN from USB ICL rc=%d\n", rc); /* remove USB_PSY_VOTER */ rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); Loading Loading @@ -2255,39 +2289,6 @@ int smblib_set_prop_ship_mode(struct smb_charger *chg, return rc; } /*********************** * USB MAIN PSY GETTERS * *************************/ int smblib_get_prop_fcc_delta(struct smb_charger *chg, union power_supply_propval *val) { int rc, jeita_cc_delta_ua, step_cc_delta_ua, hw_cc_delta_ua = 0; rc = smblib_get_step_cc_delta(chg, &step_cc_delta_ua); if (rc < 0) { smblib_err(chg, "Couldn't get step cc delta rc=%d\n", rc); step_cc_delta_ua = 0; } else { hw_cc_delta_ua = step_cc_delta_ua; } rc = smblib_get_jeita_cc_delta(chg, &jeita_cc_delta_ua); if (rc < 0) { smblib_err(chg, "Couldn't get jeita cc delta rc=%d\n", rc); jeita_cc_delta_ua = 0; } else if (jeita_cc_delta_ua < 0) { /* HW will take the min between JEITA and step charge */ hw_cc_delta_ua = min(hw_cc_delta_ua, jeita_cc_delta_ua); } val->intval = hw_cc_delta_ua; return 0; } /*********************** * USB MAIN PSY SETTERS * *************************/ int smblib_reg_block_update(struct smb_charger *chg, struct reg_info *entry) { Loading Loading @@ -2463,6 +2464,155 @@ int smblib_set_prop_pd_in_hard_reset(struct smb_charger *chg, return rc; } /*********************** * USB MAIN PSY GETTERS * *************************/ int smblib_get_prop_fcc_delta(struct smb_charger *chg, union power_supply_propval *val) { int rc, jeita_cc_delta_ua, step_cc_delta_ua, hw_cc_delta_ua = 0; rc = smblib_get_step_cc_delta(chg, &step_cc_delta_ua); if (rc < 0) { smblib_err(chg, "Couldn't get step cc delta rc=%d\n", rc); step_cc_delta_ua = 0; } else { hw_cc_delta_ua = step_cc_delta_ua; } rc = smblib_get_jeita_cc_delta(chg, &jeita_cc_delta_ua); if (rc < 0) { smblib_err(chg, "Couldn't get jeita cc delta rc=%d\n", rc); jeita_cc_delta_ua = 0; } else if (jeita_cc_delta_ua < 0) { /* HW will take the min between JEITA and step charge */ hw_cc_delta_ua = min(hw_cc_delta_ua, jeita_cc_delta_ua); } val->intval = hw_cc_delta_ua; return 0; } /*********************** * USB MAIN PSY SETTERS * *************************/ #define SDP_CURRENT_MA 500000 #define CDP_CURRENT_MA 1500000 #define DCP_CURRENT_MA 1500000 #define HVDCP_CURRENT_MA 3000000 #define TYPEC_DEFAULT_CURRENT_MA 900000 #define TYPEC_MEDIUM_CURRENT_MA 1500000 #define TYPEC_HIGH_CURRENT_MA 3000000 static int smblib_get_charge_current(struct smb_charger *chg, int *total_current_ua) { const struct apsd_result *apsd_result = smblib_update_usb_type(chg); union power_supply_propval val = {0, }; int rc, typec_source_rd, current_ua; bool non_compliant; u8 stat5; rc = smblib_read(chg, TYPE_C_STATUS_5_REG, &stat5); if (rc < 0) { smblib_err(chg, "Couldn't read TYPE_C_STATUS_5 rc=%d\n", rc); return rc; } non_compliant = stat5 & TYPEC_NONCOMP_LEGACY_CABLE_STATUS_BIT; /* get settled ICL */ rc = smblib_get_prop_input_current_settled(chg, &val); if (rc < 0) { smblib_err(chg, "Couldn't get settled ICL rc=%d\n", rc); return rc; } typec_source_rd = smblib_get_prop_ufp_mode(chg); /* QC 2.0/3.0 adapter */ if (apsd_result->bit & (QC_3P0_BIT | QC_2P0_BIT)) { *total_current_ua = HVDCP_CURRENT_MA; return 0; } if (non_compliant) { switch (apsd_result->bit) { case CDP_CHARGER_BIT: current_ua = CDP_CURRENT_MA; break; case DCP_CHARGER_BIT: case OCP_CHARGER_BIT: case FLOAT_CHARGER_BIT: current_ua = DCP_CURRENT_MA; break; default: current_ua = 0; break; } *total_current_ua = max(current_ua, val.intval); return 0; } switch (typec_source_rd) { case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT: switch (apsd_result->bit) { case CDP_CHARGER_BIT: current_ua = CDP_CURRENT_MA; break; case DCP_CHARGER_BIT: case OCP_CHARGER_BIT: case FLOAT_CHARGER_BIT: current_ua = chg->default_icl_ua; break; default: current_ua = 0; break; } break; case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM: current_ua = TYPEC_MEDIUM_CURRENT_MA; break; case POWER_SUPPLY_TYPEC_SOURCE_HIGH: current_ua = TYPEC_HIGH_CURRENT_MA; break; case POWER_SUPPLY_TYPEC_NON_COMPLIANT: case POWER_SUPPLY_TYPEC_NONE: default: current_ua = 0; break; } *total_current_ua = max(current_ua, val.intval); return 0; } int smblib_set_icl_reduction(struct smb_charger *chg, int reduction_ua) { int current_ua, rc; if (reduction_ua == 0) { chg->icl_reduction_ua = 0; vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, false, 0); } else { /* * No usb_icl voter means we are defaulting to hw chosen * max limit. We need a vote from s/w to enforce the reduction. */ if (get_effective_result(chg->usb_icl_votable) == -EINVAL) { rc = smblib_get_charge_current(chg, ¤t_ua); if (rc < 0) { pr_err("Failed to get ICL rc=%d\n", rc); return rc; } vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, true, current_ua); } } return rerun_election(chg->usb_icl_votable); } /************************ * PARALLEL PSY GETTERS * ************************/ Loading Loading @@ -2984,6 +3134,13 @@ static void typec_source_removal(struct smb_charger *chg) if (rc < 0) smblib_err(chg, "Couldn't un-vote DCP from USB ICL rc=%d\n", rc); /* clear USB ICL vote for PL_USBIN_USBIN_VOTER */ rc = vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, false, 0); if (rc < 0) smblib_err(chg, "Couldn't un-vote PL_USBIN_USBIN from USB ICL rc=%d\n", rc); } static void typec_source_insertion(struct smb_charger *chg) Loading
drivers/power/supply/qcom/smb-lib.h +4 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ enum print_reason { #define USER_VOTER "USER_VOTER" #define PD_VOTER "PD_VOTER" #define DCP_VOTER "DCP_VOTER" #define PL_USBIN_USBIN_VOTER "PL_USBIN_USBIN_VOTER" #define USB_PSY_VOTER "USB_PSY_VOTER" #define PL_TAPER_WORK_RUNNING_VOTER "PL_TAPER_WORK_RUNNING_VOTER" #define PL_INDIRECT_VOTER "PL_INDIRECT_VOTER" Loading Loading @@ -171,6 +172,7 @@ struct smb_charger { enum smb_mode mode; bool external_vconn; struct smb_chg_freq chg_freq; int smb_version; /* locks */ struct mutex write_lock; Loading Loading @@ -244,6 +246,7 @@ struct smb_charger { bool vconn_en; int otg_attempts; int vconn_attempts; int default_icl_ua; /* workaround flag */ u32 wa_flags; Loading Loading @@ -408,6 +411,7 @@ int smblib_rerun_apsd_if_required(struct smb_charger *chg); 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_init(struct smb_charger *chg); int smblib_deinit(struct smb_charger *chg); Loading
include/linux/power_supply.h +3 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,7 @@ enum { POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE, POWER_SUPPLY_HEALTH_WARM, POWER_SUPPLY_HEALTH_COOL, POWER_SUPPLY_HEALTH_HOT, }; enum { Loading Loading @@ -238,6 +239,8 @@ enum power_supply_property { POWER_SUPPLY_PROP_ICL_REDUCTION, POWER_SUPPLY_PROP_PARALLEL_MODE, POWER_SUPPLY_PROP_CONNECTOR_THERM_ZONE, POWER_SUPPLY_PROP_DIE_HEALTH, POWER_SUPPLY_PROP_CONNECTOR_HEALTH, /* Local extensions of type int64_t */ POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT, /* Properties of type `const char *' */ Loading