Merge "qpnp-smb2: support setting FCC and float voltage in battery power supply"
This commit is contained in:
commit
058ab0e221
4 changed files with 156 additions and 112 deletions
|
@ -351,6 +351,7 @@ static enum power_supply_property smb2_usb_props[] = {
|
||||||
POWER_SUPPLY_PROP_PD_ACTIVE,
|
POWER_SUPPLY_PROP_PD_ACTIVE,
|
||||||
POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
|
POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
|
||||||
POWER_SUPPLY_PROP_INPUT_CURRENT_NOW,
|
POWER_SUPPLY_PROP_INPUT_CURRENT_NOW,
|
||||||
|
POWER_SUPPLY_PROP_PE_START,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int smb2_usb_get_prop(struct power_supply *psy,
|
static int smb2_usb_get_prop(struct power_supply *psy,
|
||||||
|
@ -422,6 +423,9 @@ static int smb2_usb_get_prop(struct power_supply *psy,
|
||||||
case POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED:
|
case POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED:
|
||||||
val->intval = chg->system_suspend_supported;
|
val->intval = chg->system_suspend_supported;
|
||||||
break;
|
break;
|
||||||
|
case POWER_SUPPLY_PROP_PE_START:
|
||||||
|
rc = smblib_get_pe_start(chg, val);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
pr_err("get prop %d is not supported\n", psp);
|
pr_err("get prop %d is not supported\n", psp);
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
|
@ -633,7 +637,9 @@ static enum power_supply_property smb2_batt_props[] = {
|
||||||
POWER_SUPPLY_PROP_CHARGER_TEMP_MAX,
|
POWER_SUPPLY_PROP_CHARGER_TEMP_MAX,
|
||||||
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED,
|
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED,
|
||||||
POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
||||||
|
POWER_SUPPLY_PROP_VOLTAGE_MAX,
|
||||||
POWER_SUPPLY_PROP_CURRENT_NOW,
|
POWER_SUPPLY_PROP_CURRENT_NOW,
|
||||||
|
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
|
||||||
POWER_SUPPLY_PROP_TEMP,
|
POWER_SUPPLY_PROP_TEMP,
|
||||||
POWER_SUPPLY_PROP_TECHNOLOGY,
|
POWER_SUPPLY_PROP_TECHNOLOGY,
|
||||||
POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED,
|
POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED,
|
||||||
|
@ -690,9 +696,16 @@ static int smb2_batt_get_prop(struct power_supply *psy,
|
||||||
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
||||||
rc = smblib_get_prop_batt_voltage_now(chg, val);
|
rc = smblib_get_prop_batt_voltage_now(chg, val);
|
||||||
break;
|
break;
|
||||||
|
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
|
||||||
|
val->intval = get_client_vote(chg->fv_votable, DEFAULT_VOTER);
|
||||||
|
break;
|
||||||
case POWER_SUPPLY_PROP_CURRENT_NOW:
|
case POWER_SUPPLY_PROP_CURRENT_NOW:
|
||||||
rc = smblib_get_prop_batt_current_now(chg, val);
|
rc = smblib_get_prop_batt_current_now(chg, val);
|
||||||
break;
|
break;
|
||||||
|
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
|
||||||
|
val->intval = get_client_vote(chg->fcc_max_votable,
|
||||||
|
DEFAULT_VOTER);
|
||||||
|
break;
|
||||||
case POWER_SUPPLY_PROP_TEMP:
|
case POWER_SUPPLY_PROP_TEMP:
|
||||||
rc = smblib_get_prop_batt_temp(chg, val);
|
rc = smblib_get_prop_batt_temp(chg, val);
|
||||||
break;
|
break;
|
||||||
|
@ -748,6 +761,12 @@ static int smb2_batt_set_prop(struct power_supply *psy,
|
||||||
chg->pl.slave_pct = val->intval;
|
chg->pl.slave_pct = val->intval;
|
||||||
rerun_election(chg->fcc_votable);
|
rerun_election(chg->fcc_votable);
|
||||||
break;
|
break;
|
||||||
|
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
|
||||||
|
vote(chg->fv_votable, DEFAULT_VOTER, true, val->intval);
|
||||||
|
break;
|
||||||
|
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
|
||||||
|
vote(chg->fcc_max_votable, DEFAULT_VOTER, true, val->intval);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -471,9 +471,8 @@ static int try_rerun_apsd_for_hvdcp(struct smb_charger *chg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int smblib_update_usb_type(struct smb_charger *chg)
|
static const struct apsd_result *smblib_update_usb_type(struct smb_charger *chg)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
|
||||||
const struct apsd_result *apsd_result;
|
const struct apsd_result *apsd_result;
|
||||||
|
|
||||||
/* if PD is active, APSD is disabled so won't have a valid result */
|
/* if PD is active, APSD is disabled so won't have a valid result */
|
||||||
|
@ -484,7 +483,7 @@ static int smblib_update_usb_type(struct smb_charger *chg)
|
||||||
|
|
||||||
apsd_result = smblib_get_apsd_result(chg);
|
apsd_result = smblib_get_apsd_result(chg);
|
||||||
chg->usb_psy_desc.type = apsd_result->pst;
|
chg->usb_psy_desc.type = apsd_result->pst;
|
||||||
return rc;
|
return apsd_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int smblib_notifier_call(struct notifier_block *nb,
|
static int smblib_notifier_call(struct notifier_block *nb,
|
||||||
|
@ -1767,7 +1766,7 @@ int smblib_get_prop_typec_power_role(struct smb_charger *chg,
|
||||||
int smblib_get_prop_pd_allowed(struct smb_charger *chg,
|
int smblib_get_prop_pd_allowed(struct smb_charger *chg,
|
||||||
union power_supply_propval *val)
|
union power_supply_propval *val)
|
||||||
{
|
{
|
||||||
val->intval = get_effective_result_locked(chg->pd_allowed_votable);
|
val->intval = get_effective_result(chg->pd_allowed_votable);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1793,6 +1792,19 @@ int smblib_get_prop_pd_in_hard_reset(struct smb_charger *chg,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int smblib_get_pe_start(struct smb_charger *chg,
|
||||||
|
union power_supply_propval *val)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* hvdcp timeout voter is the last one to allow pd. Use its vote
|
||||||
|
* to indicate start of pe engine
|
||||||
|
*/
|
||||||
|
val->intval
|
||||||
|
= !get_client_vote_locked(chg->pd_disallowed_votable_indirect,
|
||||||
|
HVDCP_TIMEOUT_VOTER);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*******************
|
/*******************
|
||||||
* USB PSY SETTERS *
|
* USB PSY SETTERS *
|
||||||
* *****************/
|
* *****************/
|
||||||
|
@ -1963,6 +1975,13 @@ int smblib_set_prop_pd_active(struct smb_charger *chg,
|
||||||
smblib_update_usb_type(chg);
|
smblib_update_usb_type(chg);
|
||||||
power_supply_changed(chg->usb_psy);
|
power_supply_changed(chg->usb_psy);
|
||||||
|
|
||||||
|
rc = smblib_masked_write(chg, TYPE_C_CFG_3_REG, EN_TRYSINK_MODE_BIT,
|
||||||
|
chg->pd_active ? 0 : EN_TRYSINK_MODE_BIT);
|
||||||
|
if (rc < 0) {
|
||||||
|
dev_err(chg->dev, "Couldn't set TRYSINK_MODE rc=%d\n", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2298,13 +2317,12 @@ static void smblib_handle_hvdcp_detect_done(struct smb_charger *chg,
|
||||||
#define HVDCP_DET_MS 2500
|
#define HVDCP_DET_MS 2500
|
||||||
static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising)
|
static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising)
|
||||||
{
|
{
|
||||||
int rc;
|
|
||||||
const struct apsd_result *apsd_result;
|
const struct apsd_result *apsd_result;
|
||||||
|
|
||||||
if (!rising)
|
if (!rising)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
apsd_result = smblib_get_apsd_result(chg);
|
apsd_result = smblib_update_usb_type(chg);
|
||||||
switch (apsd_result->bit) {
|
switch (apsd_result->bit) {
|
||||||
case SDP_CHARGER_BIT:
|
case SDP_CHARGER_BIT:
|
||||||
case CDP_CHARGER_BIT:
|
case CDP_CHARGER_BIT:
|
||||||
|
@ -2323,10 +2341,6 @@ static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = smblib_update_usb_type(chg);
|
|
||||||
if (rc < 0)
|
|
||||||
smblib_err(chg, "Couldn't update usb type rc=%d\n", rc);
|
|
||||||
|
|
||||||
smblib_dbg(chg, PR_INTERRUPT, "IRQ: apsd-done rising; %s detected\n",
|
smblib_dbg(chg, PR_INTERRUPT, "IRQ: apsd-done rising; %s detected\n",
|
||||||
apsd_result->name);
|
apsd_result->name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -310,6 +310,8 @@ int smblib_get_prop_input_current_settled(struct smb_charger *chg,
|
||||||
union power_supply_propval *val);
|
union power_supply_propval *val);
|
||||||
int smblib_get_prop_pd_in_hard_reset(struct smb_charger *chg,
|
int smblib_get_prop_pd_in_hard_reset(struct smb_charger *chg,
|
||||||
union power_supply_propval *val);
|
union power_supply_propval *val);
|
||||||
|
int smblib_get_pe_start(struct smb_charger *chg,
|
||||||
|
union power_supply_propval *val);
|
||||||
int smblib_get_prop_charger_temp(struct smb_charger *chg,
|
int smblib_get_prop_charger_temp(struct smb_charger *chg,
|
||||||
union power_supply_propval *val);
|
union power_supply_propval *val);
|
||||||
int smblib_get_prop_charger_temp_max(struct smb_charger *chg,
|
int smblib_get_prop_charger_temp_max(struct smb_charger *chg,
|
||||||
|
|
|
@ -299,7 +299,6 @@ struct usbpd {
|
||||||
enum power_supply_typec_mode typec_mode;
|
enum power_supply_typec_mode typec_mode;
|
||||||
enum power_supply_type psy_type;
|
enum power_supply_type psy_type;
|
||||||
bool vbus_present;
|
bool vbus_present;
|
||||||
bool pd_allowed;
|
|
||||||
|
|
||||||
enum data_role current_dr;
|
enum data_role current_dr;
|
||||||
enum power_role current_pr;
|
enum power_role current_pr;
|
||||||
|
@ -498,6 +497,7 @@ static void pd_send_hard_reset(struct usbpd *pd)
|
||||||
ret = pd_phy_signal(HARD_RESET_SIG, 5); /* tHardResetComplete */
|
ret = pd_phy_signal(HARD_RESET_SIG, 5); /* tHardResetComplete */
|
||||||
if (!ret)
|
if (!ret)
|
||||||
pd->hard_reset = true;
|
pd->hard_reset = true;
|
||||||
|
pd->in_pr_swap = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kick_sm(struct usbpd *pd, int ms)
|
static void kick_sm(struct usbpd *pd, int ms)
|
||||||
|
@ -828,7 +828,15 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pd->pd_allowed)
|
ret = power_supply_get_property(pd->usb_psy,
|
||||||
|
POWER_SUPPLY_PROP_PD_ALLOWED, &val);
|
||||||
|
if (ret) {
|
||||||
|
usbpd_err(&pd->dev, "Unable to read USB PROP_PD_ALLOWED: %d\n",
|
||||||
|
ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!val.intval)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Reset protocol layer */
|
/* Reset protocol layer */
|
||||||
|
@ -906,8 +914,6 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PE_SNK_TRANSITION_TO_DEFAULT:
|
case PE_SNK_TRANSITION_TO_DEFAULT:
|
||||||
pd->hard_reset = false;
|
|
||||||
|
|
||||||
if (pd->current_dr != DR_UFP) {
|
if (pd->current_dr != DR_UFP) {
|
||||||
extcon_set_cable_state_(pd->extcon, EXTCON_USB_HOST, 0);
|
extcon_set_cable_state_(pd->extcon, EXTCON_USB_HOST, 0);
|
||||||
|
|
||||||
|
@ -1455,6 +1461,7 @@ static void usbpd_sm(struct work_struct *w)
|
||||||
power_supply_set_property(pd->usb_psy,
|
power_supply_set_property(pd->usb_psy,
|
||||||
POWER_SUPPLY_PROP_PD_IN_HARD_RESET, &val);
|
POWER_SUPPLY_PROP_PD_IN_HARD_RESET, &val);
|
||||||
|
|
||||||
|
pd->in_pr_swap = false;
|
||||||
reset_vdm_state(pd);
|
reset_vdm_state(pd);
|
||||||
|
|
||||||
if (pd->current_pr == PR_SINK)
|
if (pd->current_pr == PR_SINK)
|
||||||
|
@ -1822,6 +1829,12 @@ static void usbpd_sm(struct work_struct *w)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PE_SNK_TRANSITION_TO_DEFAULT:
|
case PE_SNK_TRANSITION_TO_DEFAULT:
|
||||||
|
pd->hard_reset = false;
|
||||||
|
|
||||||
|
val.intval = 0;
|
||||||
|
power_supply_set_property(pd->usb_psy,
|
||||||
|
POWER_SUPPLY_PROP_PD_IN_HARD_RESET, &val);
|
||||||
|
|
||||||
if (pd->vbus_present) {
|
if (pd->vbus_present) {
|
||||||
usbpd_set_state(pd, PE_SNK_STARTUP);
|
usbpd_set_state(pd, PE_SNK_STARTUP);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2036,33 +2049,11 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr)
|
||||||
struct usbpd *pd = container_of(nb, struct usbpd, psy_nb);
|
struct usbpd *pd = container_of(nb, struct usbpd, psy_nb);
|
||||||
union power_supply_propval val;
|
union power_supply_propval val;
|
||||||
enum power_supply_typec_mode typec_mode;
|
enum power_supply_typec_mode typec_mode;
|
||||||
bool do_work = false;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (ptr != pd->usb_psy || evt != PSY_EVENT_PROP_CHANGED)
|
if (ptr != pd->usb_psy || evt != PSY_EVENT_PROP_CHANGED)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = power_supply_get_property(pd->usb_psy,
|
|
||||||
POWER_SUPPLY_PROP_PD_ALLOWED, &val);
|
|
||||||
if (ret) {
|
|
||||||
usbpd_err(&pd->dev, "Unable to read USB PROP_PD_ALLOWED: %d\n",
|
|
||||||
ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pd->pd_allowed != val.intval)
|
|
||||||
do_work = true;
|
|
||||||
pd->pd_allowed = val.intval;
|
|
||||||
|
|
||||||
ret = power_supply_get_property(pd->usb_psy,
|
|
||||||
POWER_SUPPLY_PROP_PRESENT, &val);
|
|
||||||
if (ret) {
|
|
||||||
usbpd_err(&pd->dev, "Unable to read USB PRESENT: %d\n", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
pd->vbus_present = val.intval;
|
|
||||||
|
|
||||||
ret = power_supply_get_property(pd->usb_psy,
|
ret = power_supply_get_property(pd->usb_psy,
|
||||||
POWER_SUPPLY_PROP_TYPEC_MODE, &val);
|
POWER_SUPPLY_PROP_TYPEC_MODE, &val);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -2072,6 +2063,28 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr)
|
||||||
|
|
||||||
typec_mode = val.intval;
|
typec_mode = val.intval;
|
||||||
|
|
||||||
|
ret = power_supply_get_property(pd->usb_psy,
|
||||||
|
POWER_SUPPLY_PROP_PE_START, &val);
|
||||||
|
if (ret) {
|
||||||
|
usbpd_err(&pd->dev, "Unable to read USB PROP_PE_START: %d\n",
|
||||||
|
ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't proceed if PE_START=0 as other props may still change */
|
||||||
|
if (!val.intval && !pd->pd_connected &&
|
||||||
|
typec_mode != POWER_SUPPLY_TYPEC_NONE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = power_supply_get_property(pd->usb_psy,
|
||||||
|
POWER_SUPPLY_PROP_PRESENT, &val);
|
||||||
|
if (ret) {
|
||||||
|
usbpd_err(&pd->dev, "Unable to read USB PRESENT: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
pd->vbus_present = val.intval;
|
||||||
|
|
||||||
ret = power_supply_get_property(pd->usb_psy,
|
ret = power_supply_get_property(pd->usb_psy,
|
||||||
POWER_SUPPLY_PROP_TYPE, &val);
|
POWER_SUPPLY_PROP_TYPE, &val);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -2079,24 +2092,23 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pd->psy_type != val.intval)
|
|
||||||
do_work = true;
|
|
||||||
pd->psy_type = val.intval;
|
pd->psy_type = val.intval;
|
||||||
|
|
||||||
|
if (pd->typec_mode == typec_mode)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
pd->typec_mode = typec_mode;
|
||||||
|
|
||||||
usbpd_dbg(&pd->dev, "typec mode:%d present:%d type:%d orientation:%d\n",
|
usbpd_dbg(&pd->dev, "typec mode:%d present:%d type:%d orientation:%d\n",
|
||||||
typec_mode, pd->vbus_present, pd->psy_type,
|
typec_mode, pd->vbus_present, pd->psy_type,
|
||||||
usbpd_get_plug_orientation(pd));
|
usbpd_get_plug_orientation(pd));
|
||||||
|
|
||||||
if (pd->typec_mode != typec_mode) {
|
|
||||||
pd->typec_mode = typec_mode;
|
|
||||||
do_work = true;
|
|
||||||
|
|
||||||
switch (typec_mode) {
|
switch (typec_mode) {
|
||||||
/* Disconnect */
|
/* Disconnect */
|
||||||
case POWER_SUPPLY_TYPEC_NONE:
|
case POWER_SUPPLY_TYPEC_NONE:
|
||||||
if (pd->in_pr_swap) {
|
if (pd->in_pr_swap) {
|
||||||
usbpd_dbg(&pd->dev, "Ignoring disconnect due to PR swap\n");
|
usbpd_dbg(&pd->dev, "Ignoring disconnect due to PR swap\n");
|
||||||
do_work = false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2122,7 +2134,7 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr)
|
||||||
pd->current_state ==
|
pd->current_state ==
|
||||||
PE_SNK_TRANSITION_TO_DEFAULT) {
|
PE_SNK_TRANSITION_TO_DEFAULT) {
|
||||||
usbpd_dbg(&pd->dev, "Ignoring disconnect due to hard reset\n");
|
usbpd_dbg(&pd->dev, "Ignoring disconnect due to hard reset\n");
|
||||||
do_work = false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -2158,12 +2170,9 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr)
|
||||||
typec_mode);
|
typec_mode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* only queue state machine if CC state or PD_ALLOWED changes */
|
/* queue state machine due to CC state change */
|
||||||
if (do_work)
|
|
||||||
kick_sm(pd, 0);
|
kick_sm(pd, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue