From b1ab97d70d37c79a14bc98547d8a4aa11a481c25 Mon Sep 17 00:00:00 2001 From: Kavya Nunna Date: Mon, 31 Aug 2020 11:52:35 +0530 Subject: [PATCH 1/3] power: smb5-lib: Add support for microusb Add support for typec class registration for micro usb platform for switching USB composition from UI. Change-Id: I13e87b4ab099dd5efa56b121da6be227c81f961d Signed-off-by: Kavya Nunna Signed-off-by: Anirudh Ghayal --- drivers/power/supply/qcom/smb5-lib.c | 194 ++++++++++++++------------- 1 file changed, 103 insertions(+), 91 deletions(-) diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index a96742c4c76b..8f3580dc58bd 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -5400,12 +5400,115 @@ irqreturn_t 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); } } @@ -5988,97 +6091,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" }; From fa7a9cba6e864dd9539adbabb614733ca100fa72 Mon Sep 17 00:00:00 2001 From: Anirudh Ghayal Date: Tue, 30 Jun 2020 15:14:17 +0530 Subject: [PATCH 2/3] power: smb5-lib: Report the CURRENT_MAX as 1A in CC-mode Userspace uses the CURRENT_MAX power-supply property to determine the strength of the charger. In CC-mode of operation the main-charger's ICL is configured low and hence the CURRENT_MAX reported is lower attributing it as a weak-charger. Fix this by reporting a fixed value of 1A during CC-mode. Change-Id: Id8745b54c3909d01df69376a823396ea4c94eeb1 Signed-off-by: Anirudh Ghayal --- drivers/power/supply/qcom/qpnp-smb5.c | 2 +- drivers/power/supply/qcom/smb5-lib.c | 19 +++++++++++++++++++ drivers/power/supply/qcom/smb5-lib.h | 2 ++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index 879e398a53cd..619cfe4b81ea 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -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; diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index 8f3580dc58bd..5fb1622281f1 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -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; @@ -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) { diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h index bc6bb76c04ad..4f74e731446d 100644 --- a/drivers/power/supply/qcom/smb5-lib.h +++ b/drivers/power/supply/qcom/smb5-lib.h @@ -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); From 2dbb68e04eabc1d9ef3abe10a2bc9a9a45000967 Mon Sep 17 00:00:00 2001 From: Kiran Gunda Date: Tue, 9 Jun 2020 11:53:29 +0530 Subject: [PATCH 3/3] power: qpnp-smb5: Do not set BC1P2_START_ON_CC on DAM Do not set BC1P2_START_ON_CC on detecting a DAM cable to avoid a device brown-out. Change-Id: I9192c6d2e89170585b98cbbaa8762aeffe66949e Signed-off-by: Kiran Gunda --- drivers/power/supply/qcom/qpnp-smb5.c | 16 +++++++++++++--- drivers/power/supply/qcom/smb5-reg.h | 1 + 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index 619cfe4b81ea..8f20931e3252 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -1503,15 +1503,25 @@ static int smb5_configure_typec(struct smb_charger *chg) smblib_apsd_enable(chg, true); - rc = smblib_masked_write(chg, TYPE_C_CFG_REG, - BC1P2_START_ON_CC_BIT, 0); + rc = smblib_read(chg, TYPE_C_SNK_STATUS_REG, &value); if (rc < 0) { - dev_err(chg->dev, "failed to write TYPE_C_CFG_REG rc=%d\n", + 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) { + dev_err(chg->dev, "failed to write TYPE_C_CFG_REG rc=%d\n", + rc); + + return rc; + } + } + /* Use simple write to clear interrupts */ rc = smblib_write(chg, TYPE_C_INTERRUPT_EN_CFG_1_REG, 0); if (rc < 0) { diff --git a/drivers/power/supply/qcom/smb5-reg.h b/drivers/power/supply/qcom/smb5-reg.h index 3aa2c2ea1d90..71b4de85c159 100644 --- a/drivers/power/supply/qcom/smb5-reg.h +++ b/drivers/power/supply/qcom/smb5-reg.h @@ -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)