summaryrefslogtreecommitdiff
path: root/drivers/power
diff options
context:
space:
mode:
authorAbhijeet Dharmapurikar <adharmap@codeaurora.org>2017-04-17 12:26:26 -0700
committerAbhijeet Dharmapurikar <adharmap@codeaurora.org>2017-04-17 17:35:46 -0700
commitfcc7e888ff106d5ac7b3e11dc96af9425cc36e6d (patch)
treed579263e2b055c4e53230d9ae648a0ef80d83ddc /drivers/power
parentfd0747e34a4fddf2ed14ddc1d9b83d637924504f (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.c115
-rw-r--r--drivers/power/supply/qcom/smb-lib.h1
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;