summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbhijeet Dharmapurikar <adharmap@codeaurora.org>2016-10-05 15:15:10 -0700
committerAbhijeet Dharmapurikar <adharmap@codeaurora.org>2016-10-17 11:54:07 -0700
commitb9bcc03fb1f87e36732aaeaeb6730bc932ea8d9f (patch)
tree40b38705aa296f3ba4f64a8eb1ab0c45d5a85044
parent665d020cda7c25577c52b0d979b010dc96c09867 (diff)
qcom-charger: Allow PD for hvdcp
Currently the code prevents pd if an hvdcp is detected. We want to change that in that we want to prevent pd only while hvdcp detection is in progress. Once completed, we need to enable pd even if an hvdcp is detected. Enabling PD even for hvdcp allows us to detect a QC 4.0 which communicates over PD. Currently we model the pd_allowed votable as an enable votable i.e. if any one of the voters enable it, pd_allowed gets enabled. Change that to a disable votable named pd_disallowed_votable, which gets disabled when CC is detached, and hvdcp2.0 detection is not yet completed. Change-Id: I2ae261c71694695b41d8a31c4b40542d5e227c3a Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
-rw-r--r--drivers/power/qcom-charger/qpnp-smb2.c4
-rw-r--r--drivers/power/qcom-charger/smb-lib.c66
-rw-r--r--drivers/power/qcom-charger/smb-lib.h4
3 files changed, 53 insertions, 21 deletions
diff --git a/drivers/power/qcom-charger/qpnp-smb2.c b/drivers/power/qcom-charger/qpnp-smb2.c
index 9340b98dc883..b7369a300e95 100644
--- a/drivers/power/qcom-charger/qpnp-smb2.c
+++ b/drivers/power/qcom-charger/qpnp-smb2.c
@@ -1037,6 +1037,10 @@ static int smb2_init_hw(struct smb2 *chip)
DEFAULT_VOTER, true, chip->dt.dc_icl_ua);
vote(chg->hvdcp_disable_votable, DEFAULT_VOTER,
chip->dt.hvdcp_disable, 0);
+ vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER,
+ true, 0);
+ vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
+ true, 0);
/* Configure charge enable for software control; active high */
rc = smblib_masked_write(chg, CHGR_CFG2_REG,
diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c
index b9f8202e0a9e..3e4d39303641 100644
--- a/drivers/power/qcom-charger/smb-lib.c
+++ b/drivers/power/qcom-charger/smb-lib.c
@@ -442,7 +442,7 @@ static int smblib_update_usb_type(struct smb_charger *chg)
return rc;
}
-static int smblib_detach_usb(struct smb_charger *chg)
+static int smblib_detach_typec(struct smb_charger *chg)
{
int rc;
@@ -469,7 +469,9 @@ static int smblib_detach_usb(struct smb_charger *chg)
return rc;
}
- vote(chg->pd_allowed_votable, DEFAULT_VOTER, false, 0);
+ /* cc removed, disable pd_allowed */
+ vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER, true, 0);
+ vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER, true, 0);
return rc;
}
@@ -777,6 +779,18 @@ suspend:
return rc;
}
+static int smblib_pd_disallowed_votable_indirect_callback(
+ struct votable *votable, void *data, int disallowed, const char *client)
+{
+ struct smb_charger *chg = data;
+ int rc;
+
+ rc = vote(chg->pd_allowed_votable, PD_DISALLOWED_INDIRECT_VOTER,
+ !disallowed, 0);
+
+ return rc;
+}
+
static int smblib_awake_vote_callback(struct votable *votable, void *data,
int awake, const char *client)
{
@@ -2154,10 +2168,10 @@ static void smblib_handle_hvdcp_3p0_auth_done(struct smb_charger *chg,
static void smblib_handle_hvdcp_check_timeout(struct smb_charger *chg,
bool rising, bool qc_charger)
{
- if (rising && !qc_charger) {
- vote(chg->pd_allowed_votable, DEFAULT_VOTER, true, 0);
- power_supply_changed(chg->usb_psy);
- }
+ /* Hold off PD only until hvdcp 2.0 detection timeout */
+ if (rising)
+ vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
+ false, 0);
smblib_dbg(chg, PR_INTERRUPT, "IRQ: smblib_handle_hvdcp_check_timeout %s\n",
rising ? "rising" : "falling");
@@ -2191,7 +2205,9 @@ static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising)
case CDP_CHARGER_BIT:
case OCP_CHARGER_BIT:
case FLOAT_CHARGER_BIT:
- vote(chg->pd_allowed_votable, DEFAULT_VOTER, true, 0);
+ /* if not DCP then no hvdcp timeout happens. Enable pd here */
+ vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
+ false, 0);
break;
case DCP_CHARGER_BIT:
if (chg->wa_flags & QC_CHARGER_DETECTION_WA_BIT)
@@ -2256,7 +2272,7 @@ static void smblib_handle_typec_cc(struct smb_charger *chg, bool attached)
int rc;
if (!attached) {
- rc = smblib_detach_usb(chg);
+ rc = smblib_detach_typec(chg);
if (rc < 0)
dev_err(chg->dev, "Couldn't detach USB rc=%d\n", rc);
}
@@ -2266,14 +2282,15 @@ static void smblib_handle_typec_cc(struct smb_charger *chg, bool attached)
}
static void smblib_handle_typec_debounce_done(struct smb_charger *chg,
- bool rising, bool sink_attached)
+ bool attached, bool rising, bool sink_attached)
{
int rc;
union power_supply_propval pval = {0, };
- /* allow PD for attached sinks */
- if (rising && sink_attached)
- vote(chg->pd_allowed_votable, DEFAULT_VOTER, true, 0);
+ /* allow PD when cc is attached and debounced */
+ if (attached && rising)
+ vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER,
+ false, 0);
rc = smblib_get_prop_typec_mode(chg, &pval);
if (rc < 0)
@@ -2317,6 +2334,7 @@ irqreturn_t smblib_handle_usb_typec_change(int irq, void *data)
smblib_handle_typec_cc(chg,
(bool)(stat & CC_ATTACHED_BIT));
smblib_handle_typec_debounce_done(chg,
+ (bool)(stat & CC_ATTACHED_BIT),
(bool)(stat & TYPEC_DEBOUNCE_DONE_STATUS_BIT),
(bool)(stat & UFP_DFP_MODE_STATUS_BIT));
@@ -2348,14 +2366,10 @@ static void smblib_hvdcp_detect_work(struct work_struct *work)
{
struct smb_charger *chg = container_of(work, struct smb_charger,
hvdcp_detect_work.work);
- const struct apsd_result *apsd_result;
- apsd_result = smblib_get_apsd_result(chg);
- if (apsd_result->bit &&
- !(apsd_result->bit & (QC_2P0_BIT | QC_3P0_BIT))) {
- vote(chg->pd_allowed_votable, DEFAULT_VOTER, true, 0);
- power_supply_changed(chg->usb_psy);
- }
+ vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
+ false, 0);
+ power_supply_changed(chg->usb_psy);
}
static void bms_update_work(struct work_struct *work)
@@ -2496,8 +2510,16 @@ static int smblib_create_votables(struct smb_charger *chg)
return rc;
}
- chg->pd_allowed_votable = create_votable("PD_ALLOWED", VOTE_SET_ANY,
- NULL, NULL);
+ chg->pd_disallowed_votable_indirect
+ = create_votable("PD_DISALLOWED_INDIRECT", VOTE_SET_ANY,
+ smblib_pd_disallowed_votable_indirect_callback, chg);
+ if (IS_ERR(chg->pd_disallowed_votable_indirect)) {
+ rc = PTR_ERR(chg->pd_disallowed_votable_indirect);
+ return rc;
+ }
+
+ chg->pd_allowed_votable = create_votable("PD_ALLOWED",
+ VOTE_SET_ANY, NULL, NULL);
if (IS_ERR(chg->pd_allowed_votable)) {
rc = PTR_ERR(chg->pd_allowed_votable);
return rc;
@@ -2563,6 +2585,8 @@ static void smblib_destroy_votables(struct smb_charger *chg)
destroy_votable(chg->usb_icl_votable);
if (chg->dc_icl_votable)
destroy_votable(chg->dc_icl_votable);
+ if (chg->pd_disallowed_votable_indirect)
+ destroy_votable(chg->pd_disallowed_votable_indirect);
if (chg->pd_allowed_votable)
destroy_votable(chg->pd_allowed_votable);
if (chg->awake_votable)
diff --git a/drivers/power/qcom-charger/smb-lib.h b/drivers/power/qcom-charger/smb-lib.h
index e2a525a525b1..c6a1203f6bdb 100644
--- a/drivers/power/qcom-charger/smb-lib.h
+++ b/drivers/power/qcom-charger/smb-lib.h
@@ -37,6 +37,9 @@ enum print_reason {
#define TAPER_END_VOTER "TAPER_END_VOTER"
#define FCC_MAX_RESULT_VOTER "FCC_MAX_RESULT_VOTER"
#define THERMAL_DAEMON_VOTER "THERMAL_DAEMON_VOTER"
+#define CC_DETACHED_VOTER "CC_DETACHED_VOTER"
+#define HVDCP_TIMEOUT_VOTER "HVDCP_TIMEOUT_VOTER"
+#define PD_DISALLOWED_INDIRECT_VOTER "PD_DISALLOWED_INDIRECT_VOTER"
enum smb_mode {
PARALLEL_MASTER = 0,
@@ -144,6 +147,7 @@ struct smb_charger {
struct votable *fv_votable;
struct votable *usb_icl_votable;
struct votable *dc_icl_votable;
+ struct votable *pd_disallowed_votable_indirect;
struct votable *pd_allowed_votable;
struct votable *awake_votable;
struct votable *pl_disable_votable;