summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbhijeet Dharmapurikar <adharmap@codeaurora.org>2016-10-07 18:46:45 -0700
committerAbhijeet Dharmapurikar <adharmap@codeaurora.org>2016-10-17 11:54:08 -0700
commitf080134002472e9fb20e331e0a3dddce587458fa (patch)
tree20f078b7b8dd7e53ee9971bb50116e4485c57e7e
parentb9bcc03fb1f87e36732aaeaeb6730bc932ea8d9f (diff)
qpnp-smb2: support exiting sink based on cc
While PD is under hard reset and the device is in sink mode, it shouldn't leave sink mode because VBUS goes away. Instead it should stay in sink mode while hard reset is being conducted and exit sink mode only if CC gets detached. Configure the exit state when hard reset is in progress. Also while hard reset is in progress disable APSD else a APSD could run and disturb SDP communication after VBUS recovers in hard reset procedure. Change-Id: I7f5046d4822438e949658356e683e74acfa664f7 Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
-rw-r--r--drivers/power/qcom-charger/qpnp-smb2.c6
-rw-r--r--drivers/power/qcom-charger/smb-lib.c72
-rw-r--r--drivers/power/qcom-charger/smb-lib.h7
-rw-r--r--drivers/power/qcom-charger/smb-reg.h2
4 files changed, 76 insertions, 11 deletions
diff --git a/drivers/power/qcom-charger/qpnp-smb2.c b/drivers/power/qcom-charger/qpnp-smb2.c
index b7369a300e95..b0edacb98edf 100644
--- a/drivers/power/qcom-charger/qpnp-smb2.c
+++ b/drivers/power/qcom-charger/qpnp-smb2.c
@@ -422,6 +422,9 @@ static int smb2_usb_get_prop(struct power_supply *psy,
val->intval = get_client_vote(chg->pl_disable_votable,
USER_VOTER);
break;
+ case POWER_SUPPLY_PROP_PD_IN_HARD_RESET:
+ rc = smblib_get_prop_pd_in_hard_reset(chg, val);
+ break;
default:
pr_err("get prop %d is not supported\n", psp);
rc = -EINVAL;
@@ -469,6 +472,9 @@ static int smb2_usb_set_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
vote(chg->pl_disable_votable, USER_VOTER, (bool)val->intval, 0);
break;
+ case POWER_SUPPLY_PROP_PD_IN_HARD_RESET:
+ rc = smblib_set_prop_pd_in_hard_reset(chg, val);
+ break;
default:
pr_err("set prop %d is not supported\n", psp);
rc = -EINVAL;
diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c
index 3e4d39303641..f5b0c6a21193 100644
--- a/drivers/power/qcom-charger/smb-lib.c
+++ b/drivers/power/qcom-charger/smb-lib.c
@@ -473,6 +473,8 @@ static int smblib_detach_typec(struct smb_charger *chg)
vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER, true, 0);
vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER, true, 0);
+ vote(chg->apsd_disable_votable, PD_VOTER, false, 0);
+
return rc;
}
@@ -889,6 +891,24 @@ static int smblib_hvdcp_disable_vote_callback(struct votable *votable,
return 0;
}
+static int smblib_apsd_disable_vote_callback(struct votable *votable,
+ void *data,
+ int apsd_disable, const char *client)
+{
+ struct smb_charger *chg = data;
+ int rc;
+
+ rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
+ AUTO_SRC_DETECT_BIT,
+ apsd_disable ? 0 : AUTO_SRC_DETECT_BIT);
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't %s APSD rc=%d\n",
+ apsd_disable ? "disable" : "enable", rc);
+ return rc;
+ }
+
+ return 0;
+}
/*****************
* OTG REGULATOR *
*****************/
@@ -1739,6 +1759,22 @@ 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_pd_in_hard_reset(struct smb_charger *chg,
+ union power_supply_propval *val)
+{
+ int rc;
+ u8 ctrl;
+
+ rc = smblib_read(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, &ctrl);
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't read TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG rc=%d\n",
+ rc);
+ return rc;
+ }
+ val->intval = ctrl & EXIT_SNK_BASED_ON_CC_BIT;
+ return 0;
+}
+
/*******************
* USB PSY SETTERS *
* *****************/
@@ -1838,15 +1874,7 @@ int smblib_set_prop_pd_active(struct smb_charger *chg,
return -EINVAL;
}
- rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
- AUTO_SRC_DETECT_BIT,
- val->intval ? 0 : AUTO_SRC_DETECT_BIT);
- if (rc < 0) {
- dev_err(chg->dev, "Couldn't %s APSD rc=%d\n",
- val->intval ? "disable" : "enable", rc);
- return rc;
- }
-
+ vote(chg->apsd_disable_votable, PD_VOTER, val->intval, 0);
vote(chg->pd_allowed_votable, PD_VOTER, val->intval, 0);
/*
@@ -1888,6 +1916,20 @@ int smblib_set_prop_pd_active(struct smb_charger *chg,
return rc;
}
+int smblib_set_prop_pd_in_hard_reset(struct smb_charger *chg,
+ const union power_supply_propval *val)
+{
+ int rc;
+
+ rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
+ EXIT_SNK_BASED_ON_CC_BIT,
+ (val->intval) ? EXIT_SNK_BASED_ON_CC_BIT : 0);
+
+ vote(chg->apsd_disable_votable, PD_HARD_RESET_VOTER, val->intval, 0);
+
+ return rc;
+}
+
/************************
* PARALLEL PSY GETTERS *
************************/
@@ -2566,6 +2608,16 @@ static int smblib_create_votables(struct smb_charger *chg)
rc = PTR_ERR(chg->hvdcp_disable_votable);
return rc;
}
+
+ chg->apsd_disable_votable = create_votable("APSD_DISABLE",
+ VOTE_SET_ANY,
+ smblib_apsd_disable_vote_callback,
+ chg);
+ if (IS_ERR(chg->apsd_disable_votable)) {
+ rc = PTR_ERR(chg->apsd_disable_votable);
+ return rc;
+ }
+
return rc;
}
@@ -2597,6 +2649,8 @@ static void smblib_destroy_votables(struct smb_charger *chg)
destroy_votable(chg->chg_disable_votable);
if (chg->pl_enable_votable_indirect)
destroy_votable(chg->pl_enable_votable_indirect);
+ if (chg->apsd_disable_votable)
+ destroy_votable(chg->apsd_disable_votable);
}
static void smblib_iio_deinit(struct smb_charger *chg)
diff --git a/drivers/power/qcom-charger/smb-lib.h b/drivers/power/qcom-charger/smb-lib.h
index c6a1203f6bdb..804c5bbff013 100644
--- a/drivers/power/qcom-charger/smb-lib.h
+++ b/drivers/power/qcom-charger/smb-lib.h
@@ -40,6 +40,7 @@ enum print_reason {
#define CC_DETACHED_VOTER "CC_DETACHED_VOTER"
#define HVDCP_TIMEOUT_VOTER "HVDCP_TIMEOUT_VOTER"
#define PD_DISALLOWED_INDIRECT_VOTER "PD_DISALLOWED_INDIRECT_VOTER"
+#define PD_HARD_RESET_VOTER "PD_HARD_RESET_VOTER"
enum smb_mode {
PARALLEL_MASTER = 0,
@@ -154,6 +155,7 @@ struct smb_charger {
struct votable *chg_disable_votable;
struct votable *pl_enable_votable_indirect;
struct votable *hvdcp_disable_votable;
+ struct votable *apsd_disable_votable;
/* work */
struct work_struct bms_update_work;
@@ -294,6 +296,8 @@ int smblib_get_prop_pd_allowed(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_input_current_settled(struct smb_charger *chg,
union power_supply_propval *val);
+int smblib_get_prop_pd_in_hard_reset(struct smb_charger *chg,
+ union power_supply_propval *val);
int smblib_get_prop_charger_temp(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_charger_temp_max(struct smb_charger *chg,
@@ -308,6 +312,8 @@ int smblib_set_prop_typec_power_role(struct smb_charger *chg,
const union power_supply_propval *val);
int smblib_set_prop_pd_active(struct smb_charger *chg,
const union power_supply_propval *val);
+int smblib_set_prop_pd_in_hard_reset(struct smb_charger *chg,
+ const union power_supply_propval *val);
int smblib_get_prop_slave_current_now(struct smb_charger *chg,
union power_supply_propval *val);
@@ -315,4 +321,3 @@ int smblib_get_prop_slave_current_now(struct smb_charger *chg,
int smblib_init(struct smb_charger *chg);
int smblib_deinit(struct smb_charger *chg);
#endif /* __SMB2_CHARGER_H */
-
diff --git a/drivers/power/qcom-charger/smb-reg.h b/drivers/power/qcom-charger/smb-reg.h
index 91d9ab08c90f..a499d354086c 100644
--- a/drivers/power/qcom-charger/smb-reg.h
+++ b/drivers/power/qcom-charger/smb-reg.h
@@ -613,7 +613,7 @@ enum {
#define TYPEC_VBUS_ASSERT_INT_EN_BIT BIT(0)
#define TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG (USBIN_BASE + 0x68)
-#define EXIT_SNK_BASED_ON_CC BIT(7)
+#define EXIT_SNK_BASED_ON_CC_BIT BIT(7)
#define VCONN_EN_ORIENTATION_BIT BIT(6)
#define TYPEC_VCONN_OVERCURR_INT_EN_BIT BIT(5)
#define VCONN_EN_SRC_BIT BIT(4)