diff options
author | Abhijeet Dharmapurikar <adharmap@codeaurora.org> | 2016-10-07 19:04:33 -0700 |
---|---|---|
committer | Abhijeet Dharmapurikar <adharmap@codeaurora.org> | 2016-10-17 11:54:13 -0700 |
commit | 139548f446756f667f9719960839e50397b38b8d (patch) | |
tree | d6c006a07e3bde412b8c72be0b16fbf87e669e2b | |
parent | 2cdfc35e0b9cc3c25fad123a0581f80cae51c507 (diff) |
smb-lib: support separate current settings from usb and pd
Add support to set current limits from usb and pd.
Ensure that the limit from the pd is only enforced when pd is active
and that the limit from usb is enforced only when pd is inactive.
There is one situation when the input needs to be suspended as
per the usb driver's request when pd sets system_suspend_supported.
For that allow the usb voter to set that low current value to
suspend.
Also ensure that the pd and usb votes are nullified when source
is removed.
In addition, the return the individual valid votes from usb and pd
when their current_max are read.
Change-Id: I215e9e82f44061c4083a4df8cab400beadf6322d
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
-rw-r--r-- | drivers/power/qcom-charger/qpnp-smb2.c | 13 | ||||
-rw-r--r-- | drivers/power/qcom-charger/smb-lib.c | 42 | ||||
-rw-r--r-- | drivers/power/qcom-charger/smb-lib.h | 6 |
3 files changed, 58 insertions, 3 deletions
diff --git a/drivers/power/qcom-charger/qpnp-smb2.c b/drivers/power/qcom-charger/qpnp-smb2.c index 57ab9fe758c7..57fa63c6835c 100644 --- a/drivers/power/qcom-charger/qpnp-smb2.c +++ b/drivers/power/qcom-charger/qpnp-smb2.c @@ -346,6 +346,7 @@ static enum power_supply_property smb2_usb_props[] = { POWER_SUPPLY_PROP_VOLTAGE_MIN, POWER_SUPPLY_PROP_VOLTAGE_MAX, POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_PD_CURRENT_MAX, POWER_SUPPLY_PROP_CURRENT_MAX, POWER_SUPPLY_PROP_TYPE, POWER_SUPPLY_PROP_TYPEC_MODE, @@ -385,6 +386,9 @@ static int smb2_usb_get_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_VOLTAGE_NOW: rc = smblib_get_prop_usb_voltage_now(chg, val); break; + case POWER_SUPPLY_PROP_PD_CURRENT_MAX: + rc = smblib_get_prop_pd_current_max(chg, val); + break; case POWER_SUPPLY_PROP_CURRENT_MAX: rc = smblib_get_prop_usb_current_max(chg, val); break; @@ -425,6 +429,9 @@ static int smb2_usb_get_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_PD_IN_HARD_RESET: rc = smblib_get_prop_pd_in_hard_reset(chg, val); break; + case POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED: + val->intval = chg->system_suspend_supported; + break; default: pr_err("get prop %d is not supported\n", psp); rc = -EINVAL; @@ -452,6 +459,9 @@ static int smb2_usb_set_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_VOLTAGE_MAX: rc = smblib_set_prop_usb_voltage_max(chg, val); break; + case POWER_SUPPLY_PROP_PD_CURRENT_MAX: + rc = smblib_set_prop_pd_current_max(chg, val); + break; case POWER_SUPPLY_PROP_CURRENT_MAX: rc = smblib_set_prop_usb_current_max(chg, val); break; @@ -467,6 +477,9 @@ static int smb2_usb_set_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_PD_IN_HARD_RESET: rc = smblib_set_prop_pd_in_hard_reset(chg, val); break; + case POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED: + chg->system_suspend_supported = val->intval; + 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 dda029a3907a..f445b1b7a482 100644 --- a/drivers/power/qcom-charger/smb-lib.c +++ b/drivers/power/qcom-charger/smb-lib.c @@ -1491,10 +1491,18 @@ int smblib_get_prop_usb_voltage_now(struct smb_charger *chg, return iio_read_channel_processed(chg->iio.usbin_v_chan, &val->intval); } +int smblib_get_prop_pd_current_max(struct smb_charger *chg, + union power_supply_propval *val) +{ + val->intval = get_client_vote_locked(chg->usb_icl_votable, PD_VOTER); + return 0; +} + int smblib_get_prop_usb_current_max(struct smb_charger *chg, union power_supply_propval *val) { - val->intval = get_effective_result_locked(chg->usb_icl_votable); + val->intval = get_client_vote_locked(chg->usb_icl_votable, + USB_PSY_VOTER); return 0; } @@ -1745,12 +1753,35 @@ int smblib_get_prop_pd_in_hard_reset(struct smb_charger *chg, * USB PSY SETTERS * * *****************/ +int smblib_set_prop_pd_current_max(struct smb_charger *chg, + const union power_supply_propval *val) +{ + int rc; + + if (chg->pd_active) + rc = vote(chg->usb_icl_votable, PD_VOTER, true, val->intval); + else + rc = -EPERM; + + return rc; +} + int smblib_set_prop_usb_current_max(struct smb_charger *chg, const union power_supply_propval *val) { int rc; - rc = vote(chg->usb_icl_votable, PD_VOTER, true, val->intval); + if (!chg->pd_active) { + rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, + true, val->intval); + } else if (chg->system_suspend_supported) { + if (val->intval <= USBIN_25MA) + rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, + true, val->intval); + else + rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, + false, 0); + } return rc; } @@ -2302,7 +2333,12 @@ static void typec_source_removal(struct smb_charger *chg) /* clear USB ICL vote for PD_VOTER */ rc = vote(chg->usb_icl_votable, PD_VOTER, false, 0); if (rc < 0) - dev_err(chg->dev, "Couldn't vote for USB ICL rc=%d\n", rc); + dev_err(chg->dev, "Couldn't un-vote for USB ICL rc=%d\n", rc); + + /* clear USB ICL vote for USB_PSY_VOTER */ + rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); + if (rc < 0) + dev_err(chg->dev, "Couldn't un-vote for USB ICL rc=%d\n", rc); } static void typec_source_insertion(struct smb_charger *chg) diff --git a/drivers/power/qcom-charger/smb-lib.h b/drivers/power/qcom-charger/smb-lib.h index 910a9f7b9a30..daa99a0a9e3e 100644 --- a/drivers/power/qcom-charger/smb-lib.h +++ b/drivers/power/qcom-charger/smb-lib.h @@ -27,6 +27,7 @@ enum print_reason { #define DEFAULT_VOTER "DEFAULT_VOTER" #define USER_VOTER "USER_VOTER" #define PD_VOTER "PD_VOTER" +#define USB_PSY_VOTER "USB_PSY_VOTER" #define PL_TAPER_WORK_RUNNING_VOTER "PL_TAPER_WORK_RUNNING_VOTER" #define PARALLEL_PSY_VOTER "PARALLEL_PSY_VOTER" #define PL_INDIRECT_VOTER "PL_INDIRECT_VOTER" @@ -173,6 +174,7 @@ struct smb_charger { int voltage_max_uv; int pd_active; bool vbus_present; + bool system_suspend_supported; int system_temp_level; int thermal_levels; @@ -284,6 +286,8 @@ int smblib_get_prop_usb_suspend(struct smb_charger *chg, union power_supply_propval *val); int smblib_get_prop_usb_voltage_now(struct smb_charger *chg, union power_supply_propval *val); +int smblib_get_prop_pd_current_max(struct smb_charger *chg, + union power_supply_propval *val); int smblib_get_prop_usb_current_max(struct smb_charger *chg, union power_supply_propval *val); int smblib_get_prop_usb_current_now(struct smb_charger *chg, @@ -304,6 +308,8 @@ 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, union power_supply_propval *val); +int smblib_set_prop_pd_current_max(struct smb_charger *chg, + const union power_supply_propval *val); int smblib_set_prop_usb_current_max(struct smb_charger *chg, const union power_supply_propval *val); int smblib_set_prop_usb_voltage_min(struct smb_charger *chg, |