diff options
author | Abhijeet Dharmapurikar <adharmap@codeaurora.org> | 2017-04-17 12:26:26 -0700 |
---|---|---|
committer | Abhijeet Dharmapurikar <adharmap@codeaurora.org> | 2017-04-17 17:35:46 -0700 |
commit | fcc7e888ff106d5ac7b3e11dc96af9425cc36e6d (patch) | |
tree | d579263e2b055c4e53230d9ae648a0ef80d83ddc /drivers/power | |
parent | fd0747e34a4fddf2ed14ddc1d9b83d637924504f (diff) |
power: smb-lib: cache USB Type-C status
Currently the USB Type-C status is retrieved from the hardware in real
time. The Type-C change IRQ should trigger on every change of the Type-C
status, therefore it is not necessary to read the status registers
multiple times if a Type-C change IRQ has not triggered. Furthermore,
workarounds which force UFP/DFP mode, or disable Type-C altogether could
mislead the software into thinking a removal has happened.
Cache all of the USB Type-C status registers upon receiving a USB Type-C
change IRQ, and use the cached status where appropriate.
CRs-Fixed: 2020132
Change-Id: I99f2ff29633207898ae803672162db0c3cec80dc
Signed-off-by: Nicholas Troast <ntroast@codeaurora.org>
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/supply/qcom/smb-lib.c | 115 | ||||
-rw-r--r-- | drivers/power/supply/qcom/smb-lib.h | 1 |
2 files changed, 30 insertions, 86 deletions
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c index c9fcb2be8569..f2fb6154e9e2 100644 --- a/drivers/power/supply/qcom/smb-lib.c +++ b/drivers/power/supply/qcom/smb-lib.c @@ -1145,7 +1145,7 @@ static int smblib_usb_irq_enable_vote_callback(struct votable *votable, static int _smblib_vconn_regulator_enable(struct regulator_dev *rdev) { struct smb_charger *chg = rdev_get_drvdata(rdev); - u8 otg_stat, stat4; + u8 otg_stat, val; int rc = 0, i; if (!chg->external_vconn) { @@ -1176,17 +1176,12 @@ static int _smblib_vconn_regulator_enable(struct regulator_dev *rdev) * VCONN_EN_ORIENTATION is overloaded with overriding the CC pin used * for Vconn, and it should be set with reverse polarity of CC_OUT. */ - rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat4); - if (rc < 0) { - smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc); - return rc; - } - smblib_dbg(chg, PR_OTG, "enabling VCONN\n"); - stat4 = stat4 & CC_ORIENTATION_BIT ? 0 : VCONN_EN_ORIENTATION_BIT; + val = chg->typec_status[3] & + CC_ORIENTATION_BIT ? 0 : VCONN_EN_ORIENTATION_BIT; rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, VCONN_EN_VALUE_BIT | VCONN_EN_ORIENTATION_BIT, - VCONN_EN_VALUE_BIT | stat4); + VCONN_EN_VALUE_BIT | val); if (rc < 0) { smblib_err(chg, "Couldn't enable vconn setting rc=%d\n", rc); return rc; @@ -2147,23 +2142,13 @@ int smblib_get_prop_charger_temp_max(struct smb_charger *chg, int smblib_get_prop_typec_cc_orientation(struct smb_charger *chg, union power_supply_propval *val) { - int rc = 0; - u8 stat; - - rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat); - if (rc < 0) { - smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc); - return rc; - } - smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_4 = 0x%02x\n", - stat); - - if (stat & CC_ATTACHED_BIT) - val->intval = (bool)(stat & CC_ORIENTATION_BIT) + 1; + if (chg->typec_status[3] & CC_ATTACHED_BIT) + val->intval = + (bool)(chg->typec_status[3] & CC_ORIENTATION_BIT) + 1; else val->intval = 0; - return rc; + return 0; } static const char * const smblib_typec_mode_name[] = { @@ -2181,17 +2166,7 @@ static const char * const smblib_typec_mode_name[] = { static int smblib_get_prop_ufp_mode(struct smb_charger *chg) { - int rc; - u8 stat; - - rc = smblib_read(chg, TYPE_C_STATUS_1_REG, &stat); - if (rc < 0) { - smblib_err(chg, "Couldn't read TYPE_C_STATUS_1 rc=%d\n", rc); - return POWER_SUPPLY_TYPEC_NONE; - } - smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_1 = 0x%02x\n", stat); - - switch (stat) { + switch (chg->typec_status[0]) { case 0: return POWER_SUPPLY_TYPEC_NONE; case UFP_TYPEC_RDSTD_BIT: @@ -2209,17 +2184,7 @@ static int smblib_get_prop_ufp_mode(struct smb_charger *chg) static int smblib_get_prop_dfp_mode(struct smb_charger *chg) { - int rc; - u8 stat; - - rc = smblib_read(chg, TYPE_C_STATUS_2_REG, &stat); - if (rc < 0) { - smblib_err(chg, "Couldn't read TYPE_C_STATUS_2 rc=%d\n", rc); - return POWER_SUPPLY_TYPEC_NONE; - } - smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_2 = 0x%02x\n", stat); - - switch (stat & DFP_TYPEC_MASK) { + switch (chg->typec_status[1] & DFP_TYPEC_MASK) { case DFP_RA_RA_BIT: return POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER; case DFP_RD_RD_BIT: @@ -2240,28 +2205,17 @@ static int smblib_get_prop_dfp_mode(struct smb_charger *chg) int smblib_get_prop_typec_mode(struct smb_charger *chg, union power_supply_propval *val) { - int rc; - u8 stat; - - rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat); - if (rc < 0) { - smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc); + if (!(chg->typec_status[3] & TYPEC_DEBOUNCE_DONE_STATUS_BIT)) { val->intval = POWER_SUPPLY_TYPEC_NONE; - return rc; - } - smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_4 = 0x%02x\n", stat); - - if (!(stat & TYPEC_DEBOUNCE_DONE_STATUS_BIT)) { - val->intval = POWER_SUPPLY_TYPEC_NONE; - return rc; + return 0; } - if (stat & UFP_DFP_MODE_STATUS_BIT) + if (chg->typec_status[3] & UFP_DFP_MODE_STATUS_BIT) val->intval = smblib_get_prop_dfp_mode(chg); else val->intval = smblib_get_prop_ufp_mode(chg); - return rc; + return 0; } int smblib_get_prop_typec_power_role(struct smb_charger *chg, @@ -2549,18 +2503,11 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, const union power_supply_propval *val) { int rc; - u8 stat = 0; bool orientation; if (!get_effective_result(chg->pd_allowed_votable)) return -EINVAL; - rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat); - if (rc < 0) { - smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc); - return rc; - } - chg->pd_active = val->intval; if (chg->pd_active) { vote(chg->apsd_disable_votable, PD_VOTER, true, 0); @@ -2572,7 +2519,7 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, * line when TYPEC_SPARE_CFG_BIT (CC pin selection s/w override) * is set or when VCONN_EN_VALUE_BIT is set. */ - orientation = stat & CC_ORIENTATION_BIT; + orientation = chg->typec_status[3] & CC_ORIENTATION_BIT; rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, VCONN_EN_ORIENTATION_BIT, @@ -2623,8 +2570,9 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, smblib_err(chg, "Couldn't enable HW cc_out rc=%d\n", rc); - if ((stat & (TYPEC_DEBOUNCE_DONE_STATUS_BIT | UFP_DFP_MODE_BIT)) - == TYPEC_DEBOUNCE_DONE_STATUS_BIT) + if ((chg->typec_status[3] & + (TYPEC_DEBOUNCE_DONE_STATUS_BIT | UFP_DFP_MODE_BIT)) + == TYPEC_DEBOUNCE_DONE_STATUS_BIT) try_rerun_apsd_for_hvdcp(chg); } @@ -3732,37 +3680,32 @@ irqreturn_t smblib_handle_usb_typec_change_for_uusb(struct smb_charger *chg) static void smblib_usb_typec_change(struct smb_charger *chg) { int rc; - u8 stat4, stat5; bool debounce_done, sink_attached, legacy_cable; - rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat4); + rc = smblib_multibyte_read(chg, TYPE_C_STATUS_1_REG, + chg->typec_status, 5); if (rc < 0) { - smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc); - return; - } - - rc = smblib_read(chg, TYPE_C_STATUS_5_REG, &stat5); - if (rc < 0) { - smblib_err(chg, "Couldn't read TYPE_C_STATUS_5 rc=%d\n", rc); + smblib_err(chg, "Couldn't cache USB Type-C status rc=%d\n", rc); return; } - debounce_done = (bool)(stat4 & TYPEC_DEBOUNCE_DONE_STATUS_BIT); - sink_attached = (bool)(stat4 & UFP_DFP_MODE_STATUS_BIT); - legacy_cable = (bool)(stat5 & TYPEC_LEGACY_CABLE_STATUS_BIT); + debounce_done = + (bool)(chg->typec_status[3] & TYPEC_DEBOUNCE_DONE_STATUS_BIT); + sink_attached = + (bool)(chg->typec_status[3] & UFP_DFP_MODE_STATUS_BIT); + legacy_cable = + (bool)(chg->typec_status[4] & TYPEC_LEGACY_CABLE_STATUS_BIT); smblib_handle_typec_debounce_done(chg, debounce_done, sink_attached, legacy_cable); - if (stat4 & TYPEC_VBUS_ERROR_STATUS_BIT) + if (chg->typec_status[3] & TYPEC_VBUS_ERROR_STATUS_BIT) smblib_dbg(chg, PR_INTERRUPT, "IRQ: vbus-error\n"); - if (stat4 & TYPEC_VCONN_OVERCURR_STATUS_BIT) + if (chg->typec_status[3] & TYPEC_VCONN_OVERCURR_STATUS_BIT) schedule_work(&chg->vconn_oc_work); power_supply_changed(chg->usb_psy); - smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_4 = 0x%02x\n", stat4); - smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_5 = 0x%02x\n", stat5); } irqreturn_t smblib_handle_usb_typec_change(int irq, void *data) diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h index 877f62a77d1a..603628655567 100644 --- a/drivers/power/supply/qcom/smb-lib.h +++ b/drivers/power/supply/qcom/smb-lib.h @@ -309,6 +309,7 @@ struct smb_charger { bool uusb_apsd_rerun_done; bool pd_hard_reset; bool typec_present; + u8 typec_status[5]; /* workaround flag */ u32 wa_flags; |