Loading drivers/power/supply/qcom/qpnp-smb5.c +14 −4 Original line number Diff line number Diff line Loading @@ -860,7 +860,7 @@ static int smb5_usb_get_prop(struct power_supply *psy, rc = smblib_get_prop_usb_current_now(chg, val); break; case POWER_SUPPLY_PROP_CURRENT_MAX: rc = smblib_get_prop_input_current_settled(chg, val); rc = smblib_get_prop_input_current_max(chg, val); break; case POWER_SUPPLY_PROP_TYPE: val->intval = POWER_SUPPLY_TYPE_USB_PD; Loading Loading @@ -1503,6 +1503,15 @@ static int smb5_configure_typec(struct smb_charger *chg) smblib_apsd_enable(chg, true); rc = smblib_read(chg, TYPE_C_SNK_STATUS_REG, &value); if (rc < 0) { dev_err(chg->dev, "failed to read TYPE_C_SNK_STATUS_REG rc=%d\n", rc); return rc; } if (!(value & SNK_DAM_MASK)) { rc = smblib_masked_write(chg, TYPE_C_CFG_REG, BC1P2_START_ON_CC_BIT, 0); if (rc < 0) { Loading @@ -1511,6 +1520,7 @@ static int smb5_configure_typec(struct smb_charger *chg) return rc; } } /* Use simple write to clear interrupts */ rc = smblib_write(chg, TYPE_C_INTERRUPT_EN_CFG_1_REG, 0); Loading drivers/power/supply/qcom/smb5-lib.c +122 −91 Original line number Diff line number Diff line Loading @@ -1410,6 +1410,7 @@ static int smblib_get_pulse_cnt(struct smb_charger *chg, int *count) #define USBIN_150MA 150000 #define USBIN_500MA 500000 #define USBIN_900MA 900000 #define USBIN_1000MA 1000000 static int set_sdp_current(struct smb_charger *chg, int icl_ua) { int rc; Loading Loading @@ -4044,6 +4045,24 @@ int smblib_get_prop_input_current_settled(struct smb_charger *chg, return smblib_get_charge_param(chg, &chg->param.icl_stat, &val->intval); } int smblib_get_prop_input_current_max(struct smb_charger *chg, union power_supply_propval *val) { int icl_ua = 0, rc; rc = smblib_get_charge_param(chg, &chg->param.usb_icl, &icl_ua); if (rc < 0) return rc; if (is_override_vote_enabled_locked(chg->usb_icl_votable) && icl_ua < USBIN_1000MA) { val->intval = USBIN_1000MA; return 0; } return smblib_get_charge_param(chg, &chg->param.icl_stat, &val->intval); } int smblib_get_prop_input_voltage_settled(struct smb_charger *chg, int *val) { Loading Loading @@ -5400,12 +5419,115 @@ irqreturn_t smb5_icl_change_irq_handler(int irq, void *data) return IRQ_HANDLED; } static int smblib_role_switch_failure(struct smb_charger *chg) { int rc = 0; union power_supply_propval pval = {0, }; if (!chg->use_extcon) return 0; rc = smblib_get_prop_usb_present(chg, &pval); if (rc < 0) { smblib_err(chg, "Couldn't get usb presence status rc=%d\n", rc); return rc; } /* * When role switch fails notify the * current charger state to usb driver. */ if (pval.intval) { smblib_dbg(chg, PR_MISC, " Role reversal failed, notifying device mode to usb driver.\n"); smblib_notify_device_mode(chg, true); } return rc; } static int typec_partner_register(struct smb_charger *chg) { int typec_mode, rc = 0; mutex_lock(&chg->typec_lock); if (!chg->typec_port || chg->pr_swap_in_progress) goto unlock; if (!chg->typec_partner) { if (chg->sink_src_mode == AUDIO_ACCESS_MODE) chg->typec_partner_desc.accessory = TYPEC_ACCESSORY_AUDIO; else chg->typec_partner_desc.accessory = TYPEC_ACCESSORY_NONE; chg->typec_partner = typec_register_partner(chg->typec_port, &chg->typec_partner_desc); if (IS_ERR(chg->typec_partner)) { rc = PTR_ERR(chg->typec_partner); pr_err("failed to register typec_partner rc=%d\n", rc); goto unlock; } } typec_mode = smblib_get_prop_typec_mode(chg); if (typec_mode >= QTI_POWER_SUPPLY_TYPEC_SOURCE_DEFAULT || typec_mode == QTI_POWER_SUPPLY_TYPEC_NONE) { if (chg->typec_role_swap_failed) { rc = smblib_role_switch_failure(chg); if (rc < 0) smblib_err(chg, "Failed to role switch rc=%d\n", rc); chg->typec_role_swap_failed = false; } typec_set_data_role(chg->typec_port, TYPEC_DEVICE); typec_set_pwr_role(chg->typec_port, TYPEC_SINK); } else { typec_set_data_role(chg->typec_port, TYPEC_HOST); typec_set_pwr_role(chg->typec_port, TYPEC_SOURCE); } unlock: mutex_unlock(&chg->typec_lock); return rc; } static void typec_partner_unregister(struct smb_charger *chg) { mutex_lock(&chg->typec_lock); if (!chg->typec_port) goto unlock; if (chg->typec_partner && !chg->pr_swap_in_progress) { smblib_dbg(chg, PR_MISC, "Un-registering typeC partner\n"); typec_unregister_partner(chg->typec_partner); chg->typec_partner = NULL; } unlock: mutex_unlock(&chg->typec_lock); } static void smblib_micro_usb_plugin(struct smb_charger *chg, bool vbus_rising) { int rc = 0; if (!vbus_rising) { smblib_update_usb_type(chg); smblib_notify_device_mode(chg, false); smblib_uusb_removal(chg); typec_partner_unregister(chg); } else { rc = typec_partner_register(chg); if (rc < 0) smblib_err(chg, "Couldn't register partner rc =%d\n", rc); } } Loading Loading @@ -5988,97 +6110,6 @@ static void typec_ra_ra_insertion(struct smb_charger *chg) smblib_hvdcp_detect_enable(chg, true); } static int smblib_role_switch_failure(struct smb_charger *chg) { int rc = 0; union power_supply_propval pval = {0, }; if (!chg->use_extcon) return 0; rc = smblib_get_prop_usb_present(chg, &pval); if (rc < 0) { smblib_err(chg, "Couldn't get usb presence status rc=%d\n", rc); return rc; } /* * When role switch fails notify the * current charger state to usb driver. */ if (pval.intval) { smblib_dbg(chg, PR_MISC, " Role reversal failed, notifying device mode to usb driver.\n"); smblib_notify_device_mode(chg, true); } return rc; } static int typec_partner_register(struct smb_charger *chg) { int typec_mode, rc = 0; mutex_lock(&chg->typec_lock); if (!chg->typec_port || chg->pr_swap_in_progress) goto unlock; if (!chg->typec_partner) { if (chg->sink_src_mode == AUDIO_ACCESS_MODE) chg->typec_partner_desc.accessory = TYPEC_ACCESSORY_AUDIO; else chg->typec_partner_desc.accessory = TYPEC_ACCESSORY_NONE; chg->typec_partner = typec_register_partner(chg->typec_port, &chg->typec_partner_desc); if (IS_ERR(chg->typec_partner)) { rc = PTR_ERR(chg->typec_partner); pr_err("failed to register typec_partner rc=%d\n", rc); goto unlock; } } typec_mode = smblib_get_prop_typec_mode(chg); if (typec_mode >= QTI_POWER_SUPPLY_TYPEC_SOURCE_DEFAULT || typec_mode == QTI_POWER_SUPPLY_TYPEC_NONE) { if (chg->typec_role_swap_failed) { rc = smblib_role_switch_failure(chg); if (rc < 0) smblib_err(chg, "Failed to role switch rc=%d\n", rc); chg->typec_role_swap_failed = false; } typec_set_data_role(chg->typec_port, TYPEC_DEVICE); typec_set_pwr_role(chg->typec_port, TYPEC_SINK); } else { typec_set_data_role(chg->typec_port, TYPEC_HOST); typec_set_pwr_role(chg->typec_port, TYPEC_SOURCE); } unlock: mutex_unlock(&chg->typec_lock); return rc; } static void typec_partner_unregister(struct smb_charger *chg) { mutex_lock(&chg->typec_lock); if (chg->typec_partner && !chg->pr_swap_in_progress) { smblib_dbg(chg, PR_MISC, "Un-registering typeC partner\n"); typec_unregister_partner(chg->typec_partner); chg->typec_partner = NULL; } mutex_unlock(&chg->typec_lock); } static const char * const dr_mode_text[] = { "ufp", "dfp", "none" }; Loading drivers/power/supply/qcom/smb5-lib.h +2 −0 Original line number Diff line number Diff line Loading @@ -765,6 +765,8 @@ int smblib_get_die_health(struct smb_charger *chg, int *val); int smblib_get_prop_smb_health(struct smb_charger *chg); int smblib_get_prop_connector_health(struct smb_charger *chg); int smblib_get_prop_input_current_max(struct smb_charger *chg, union power_supply_propval *val); int smblib_set_prop_thermal_overheat(struct smb_charger *chg, int therm_overheat); int smblib_get_skin_temp_status(struct smb_charger *chg); Loading drivers/power/supply/qcom/smb5-reg.h +1 −0 Original line number Diff line number Diff line Loading @@ -335,6 +335,7 @@ enum { ********************************/ #define TYPE_C_SNK_STATUS_REG (TYPEC_BASE + 0x06) #define DETECTED_SRC_TYPE_MASK GENMASK(6, 0) #define SNK_DAM_MASK GENMASK(6, 4) #define SNK_DAM_500MA_BIT BIT(6) #define SNK_DAM_1500MA_BIT BIT(5) #define SNK_DAM_3000MA_BIT BIT(4) Loading Loading
drivers/power/supply/qcom/qpnp-smb5.c +14 −4 Original line number Diff line number Diff line Loading @@ -860,7 +860,7 @@ static int smb5_usb_get_prop(struct power_supply *psy, rc = smblib_get_prop_usb_current_now(chg, val); break; case POWER_SUPPLY_PROP_CURRENT_MAX: rc = smblib_get_prop_input_current_settled(chg, val); rc = smblib_get_prop_input_current_max(chg, val); break; case POWER_SUPPLY_PROP_TYPE: val->intval = POWER_SUPPLY_TYPE_USB_PD; Loading Loading @@ -1503,6 +1503,15 @@ static int smb5_configure_typec(struct smb_charger *chg) smblib_apsd_enable(chg, true); rc = smblib_read(chg, TYPE_C_SNK_STATUS_REG, &value); if (rc < 0) { dev_err(chg->dev, "failed to read TYPE_C_SNK_STATUS_REG rc=%d\n", rc); return rc; } if (!(value & SNK_DAM_MASK)) { rc = smblib_masked_write(chg, TYPE_C_CFG_REG, BC1P2_START_ON_CC_BIT, 0); if (rc < 0) { Loading @@ -1511,6 +1520,7 @@ static int smb5_configure_typec(struct smb_charger *chg) return rc; } } /* Use simple write to clear interrupts */ rc = smblib_write(chg, TYPE_C_INTERRUPT_EN_CFG_1_REG, 0); Loading
drivers/power/supply/qcom/smb5-lib.c +122 −91 Original line number Diff line number Diff line Loading @@ -1410,6 +1410,7 @@ static int smblib_get_pulse_cnt(struct smb_charger *chg, int *count) #define USBIN_150MA 150000 #define USBIN_500MA 500000 #define USBIN_900MA 900000 #define USBIN_1000MA 1000000 static int set_sdp_current(struct smb_charger *chg, int icl_ua) { int rc; Loading Loading @@ -4044,6 +4045,24 @@ int smblib_get_prop_input_current_settled(struct smb_charger *chg, return smblib_get_charge_param(chg, &chg->param.icl_stat, &val->intval); } int smblib_get_prop_input_current_max(struct smb_charger *chg, union power_supply_propval *val) { int icl_ua = 0, rc; rc = smblib_get_charge_param(chg, &chg->param.usb_icl, &icl_ua); if (rc < 0) return rc; if (is_override_vote_enabled_locked(chg->usb_icl_votable) && icl_ua < USBIN_1000MA) { val->intval = USBIN_1000MA; return 0; } return smblib_get_charge_param(chg, &chg->param.icl_stat, &val->intval); } int smblib_get_prop_input_voltage_settled(struct smb_charger *chg, int *val) { Loading Loading @@ -5400,12 +5419,115 @@ irqreturn_t smb5_icl_change_irq_handler(int irq, void *data) return IRQ_HANDLED; } static int smblib_role_switch_failure(struct smb_charger *chg) { int rc = 0; union power_supply_propval pval = {0, }; if (!chg->use_extcon) return 0; rc = smblib_get_prop_usb_present(chg, &pval); if (rc < 0) { smblib_err(chg, "Couldn't get usb presence status rc=%d\n", rc); return rc; } /* * When role switch fails notify the * current charger state to usb driver. */ if (pval.intval) { smblib_dbg(chg, PR_MISC, " Role reversal failed, notifying device mode to usb driver.\n"); smblib_notify_device_mode(chg, true); } return rc; } static int typec_partner_register(struct smb_charger *chg) { int typec_mode, rc = 0; mutex_lock(&chg->typec_lock); if (!chg->typec_port || chg->pr_swap_in_progress) goto unlock; if (!chg->typec_partner) { if (chg->sink_src_mode == AUDIO_ACCESS_MODE) chg->typec_partner_desc.accessory = TYPEC_ACCESSORY_AUDIO; else chg->typec_partner_desc.accessory = TYPEC_ACCESSORY_NONE; chg->typec_partner = typec_register_partner(chg->typec_port, &chg->typec_partner_desc); if (IS_ERR(chg->typec_partner)) { rc = PTR_ERR(chg->typec_partner); pr_err("failed to register typec_partner rc=%d\n", rc); goto unlock; } } typec_mode = smblib_get_prop_typec_mode(chg); if (typec_mode >= QTI_POWER_SUPPLY_TYPEC_SOURCE_DEFAULT || typec_mode == QTI_POWER_SUPPLY_TYPEC_NONE) { if (chg->typec_role_swap_failed) { rc = smblib_role_switch_failure(chg); if (rc < 0) smblib_err(chg, "Failed to role switch rc=%d\n", rc); chg->typec_role_swap_failed = false; } typec_set_data_role(chg->typec_port, TYPEC_DEVICE); typec_set_pwr_role(chg->typec_port, TYPEC_SINK); } else { typec_set_data_role(chg->typec_port, TYPEC_HOST); typec_set_pwr_role(chg->typec_port, TYPEC_SOURCE); } unlock: mutex_unlock(&chg->typec_lock); return rc; } static void typec_partner_unregister(struct smb_charger *chg) { mutex_lock(&chg->typec_lock); if (!chg->typec_port) goto unlock; if (chg->typec_partner && !chg->pr_swap_in_progress) { smblib_dbg(chg, PR_MISC, "Un-registering typeC partner\n"); typec_unregister_partner(chg->typec_partner); chg->typec_partner = NULL; } unlock: mutex_unlock(&chg->typec_lock); } static void smblib_micro_usb_plugin(struct smb_charger *chg, bool vbus_rising) { int rc = 0; if (!vbus_rising) { smblib_update_usb_type(chg); smblib_notify_device_mode(chg, false); smblib_uusb_removal(chg); typec_partner_unregister(chg); } else { rc = typec_partner_register(chg); if (rc < 0) smblib_err(chg, "Couldn't register partner rc =%d\n", rc); } } Loading Loading @@ -5988,97 +6110,6 @@ static void typec_ra_ra_insertion(struct smb_charger *chg) smblib_hvdcp_detect_enable(chg, true); } static int smblib_role_switch_failure(struct smb_charger *chg) { int rc = 0; union power_supply_propval pval = {0, }; if (!chg->use_extcon) return 0; rc = smblib_get_prop_usb_present(chg, &pval); if (rc < 0) { smblib_err(chg, "Couldn't get usb presence status rc=%d\n", rc); return rc; } /* * When role switch fails notify the * current charger state to usb driver. */ if (pval.intval) { smblib_dbg(chg, PR_MISC, " Role reversal failed, notifying device mode to usb driver.\n"); smblib_notify_device_mode(chg, true); } return rc; } static int typec_partner_register(struct smb_charger *chg) { int typec_mode, rc = 0; mutex_lock(&chg->typec_lock); if (!chg->typec_port || chg->pr_swap_in_progress) goto unlock; if (!chg->typec_partner) { if (chg->sink_src_mode == AUDIO_ACCESS_MODE) chg->typec_partner_desc.accessory = TYPEC_ACCESSORY_AUDIO; else chg->typec_partner_desc.accessory = TYPEC_ACCESSORY_NONE; chg->typec_partner = typec_register_partner(chg->typec_port, &chg->typec_partner_desc); if (IS_ERR(chg->typec_partner)) { rc = PTR_ERR(chg->typec_partner); pr_err("failed to register typec_partner rc=%d\n", rc); goto unlock; } } typec_mode = smblib_get_prop_typec_mode(chg); if (typec_mode >= QTI_POWER_SUPPLY_TYPEC_SOURCE_DEFAULT || typec_mode == QTI_POWER_SUPPLY_TYPEC_NONE) { if (chg->typec_role_swap_failed) { rc = smblib_role_switch_failure(chg); if (rc < 0) smblib_err(chg, "Failed to role switch rc=%d\n", rc); chg->typec_role_swap_failed = false; } typec_set_data_role(chg->typec_port, TYPEC_DEVICE); typec_set_pwr_role(chg->typec_port, TYPEC_SINK); } else { typec_set_data_role(chg->typec_port, TYPEC_HOST); typec_set_pwr_role(chg->typec_port, TYPEC_SOURCE); } unlock: mutex_unlock(&chg->typec_lock); return rc; } static void typec_partner_unregister(struct smb_charger *chg) { mutex_lock(&chg->typec_lock); if (chg->typec_partner && !chg->pr_swap_in_progress) { smblib_dbg(chg, PR_MISC, "Un-registering typeC partner\n"); typec_unregister_partner(chg->typec_partner); chg->typec_partner = NULL; } mutex_unlock(&chg->typec_lock); } static const char * const dr_mode_text[] = { "ufp", "dfp", "none" }; Loading
drivers/power/supply/qcom/smb5-lib.h +2 −0 Original line number Diff line number Diff line Loading @@ -765,6 +765,8 @@ int smblib_get_die_health(struct smb_charger *chg, int *val); int smblib_get_prop_smb_health(struct smb_charger *chg); int smblib_get_prop_connector_health(struct smb_charger *chg); int smblib_get_prop_input_current_max(struct smb_charger *chg, union power_supply_propval *val); int smblib_set_prop_thermal_overheat(struct smb_charger *chg, int therm_overheat); int smblib_get_skin_temp_status(struct smb_charger *chg); Loading
drivers/power/supply/qcom/smb5-reg.h +1 −0 Original line number Diff line number Diff line Loading @@ -335,6 +335,7 @@ enum { ********************************/ #define TYPE_C_SNK_STATUS_REG (TYPEC_BASE + 0x06) #define DETECTED_SRC_TYPE_MASK GENMASK(6, 0) #define SNK_DAM_MASK GENMASK(6, 4) #define SNK_DAM_500MA_BIT BIT(6) #define SNK_DAM_1500MA_BIT BIT(5) #define SNK_DAM_3000MA_BIT BIT(4) Loading