Merge "power: qpnp-smb5: Do not set BC1P2_START_ON_CC on DAM"

This commit is contained in:
qctecmdr 2020-09-06 10:39:37 -07:00 • committed by Gerrit - the friendly Code Review server
commit 4bb9d8e08b
4 changed files with 139 additions and 95 deletions

View file

@ -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;
@ -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) {

View file

@ -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)
{
@ -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);
}
}
@ -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"
};

View file

@ -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);

View file

@ -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)