Merge "usb: pd: Observe PSHardResetTimer for source hard reset"

This commit is contained in:
Linux Build Service Account 2016-10-31 06:59:11 -07:00 committed by Gerrit - the friendly Code Review server
commit aae17b0582

View file

@ -274,7 +274,7 @@ struct usbpd {
struct extcon_dev *extcon;
enum usbpd_state current_state;
bool hard_reset;
bool hard_reset_recvd;
u8 rx_msg_type;
u8 rx_msg_len;
u32 rx_payload[7];
@ -487,16 +487,12 @@ static int pd_eval_src_caps(struct usbpd *pd, const u32 *src_caps)
static void pd_send_hard_reset(struct usbpd *pd)
{
int ret;
usbpd_dbg(&pd->dev, "send hard reset");
/* Force CC logic to source/sink to keep Rp/Rd unchanged */
set_power_role(pd, pd->current_pr);
pd->hard_reset_count++;
ret = pd_phy_signal(HARD_RESET_SIG, 5); /* tHardResetComplete */
if (!ret)
pd->hard_reset = true;
pd_phy_signal(HARD_RESET_SIG, 5); /* tHardResetComplete */
pd->in_pr_swap = false;
}
@ -522,7 +518,7 @@ static void phy_sig_received(struct usbpd *pd, enum pd_sig_type type)
/* Force CC logic to source/sink to keep Rp/Rd unchanged */
set_power_role(pd, pd->current_pr);
pd->hard_reset = true;
pd->hard_reset_recvd = true;
kick_sm(pd, 0);
}
@ -753,40 +749,6 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
kobject_uevent(&pd->dev.kobj, KOBJ_CHANGE);
break;
case PE_SRC_TRANSITION_TO_DEFAULT:
pd->hard_reset = false;
if (pd->vconn_enabled)
regulator_disable(pd->vconn);
regulator_disable(pd->vbus);
if (pd->current_dr != DR_DFP) {
extcon_set_cable_state_(pd->extcon, EXTCON_USB, 0);
pd->current_dr = DR_DFP;
pd_phy_update_roles(pd->current_dr, pd->current_pr);
}
msleep(SRC_RECOVER_TIME);
ret = regulator_enable(pd->vbus);
if (ret)
usbpd_err(&pd->dev, "Unable to enable vbus\n");
if (pd->vconn_enabled) {
ret = regulator_enable(pd->vconn);
if (ret) {
usbpd_err(&pd->dev, "Unable to enable vconn\n");
pd->vconn_enabled = false;
}
}
val.intval = 0;
power_supply_set_property(pd->usb_psy,
POWER_SUPPLY_PROP_PD_IN_HARD_RESET, &val);
usbpd_set_state(pd, PE_SRC_STARTUP);
break;
case PE_SRC_HARD_RESET:
case PE_SNK_HARD_RESET:
/* hard reset may sleep; handle it in the workqueue */
@ -1403,7 +1365,7 @@ static void usbpd_sm(struct work_struct *w)
pd->in_pr_swap = false;
pd->pd_connected = false;
pd->in_explicit_contract = false;
pd->hard_reset = false;
pd->hard_reset_recvd = false;
pd->caps_count = 0;
pd->hard_reset_count = 0;
pd->src_cap_id = 0;
@ -1456,7 +1418,9 @@ static void usbpd_sm(struct work_struct *w)
}
/* Hard reset? */
if (pd->hard_reset) {
if (pd->hard_reset_recvd) {
pd->hard_reset_recvd = false;
val.intval = 1;
power_supply_set_property(pd->usb_psy,
POWER_SUPPLY_PROP_PD_IN_HARD_RESET, &val);
@ -1464,10 +1428,12 @@ static void usbpd_sm(struct work_struct *w)
pd->in_pr_swap = false;
reset_vdm_state(pd);
if (pd->current_pr == PR_SINK)
if (pd->current_pr == PR_SINK) {
usbpd_set_state(pd, PE_SNK_TRANSITION_TO_DEFAULT);
else
usbpd_set_state(pd, PE_SRC_TRANSITION_TO_DEFAULT);
} else {
pd->current_state = PE_SRC_TRANSITION_TO_DEFAULT;
kick_sm(pd, PS_HARD_RESET_TIME);
}
goto sm_done;
}
@ -1632,6 +1598,38 @@ static void usbpd_sm(struct work_struct *w)
}
break;
case PE_SRC_TRANSITION_TO_DEFAULT:
if (pd->vconn_enabled)
regulator_disable(pd->vconn);
regulator_disable(pd->vbus);
if (pd->current_dr != DR_DFP) {
extcon_set_cable_state_(pd->extcon, EXTCON_USB, 0);
pd->current_dr = DR_DFP;
pd_phy_update_roles(pd->current_dr, pd->current_pr);
}
msleep(SRC_RECOVER_TIME);
ret = regulator_enable(pd->vbus);
if (ret)
usbpd_err(&pd->dev, "Unable to enable vbus\n");
if (pd->vconn_enabled) {
ret = regulator_enable(pd->vconn);
if (ret) {
usbpd_err(&pd->dev, "Unable to enable vconn\n");
pd->vconn_enabled = false;
}
}
val.intval = 0;
power_supply_set_property(pd->usb_psy,
POWER_SUPPLY_PROP_PD_IN_HARD_RESET, &val);
usbpd_set_state(pd, PE_SRC_STARTUP);
break;
case PE_SRC_HARD_RESET:
val.intval = 1;
power_supply_set_property(pd->usb_psy,
@ -1641,9 +1639,8 @@ static void usbpd_sm(struct work_struct *w)
pd->in_explicit_contract = false;
reset_vdm_state(pd);
usleep_range(PS_HARD_RESET_TIME * USEC_PER_MSEC,
(PS_HARD_RESET_TIME + 5) * USEC_PER_MSEC);
usbpd_set_state(pd, PE_SRC_TRANSITION_TO_DEFAULT);
pd->current_state = PE_SRC_TRANSITION_TO_DEFAULT;
kick_sm(pd, PS_HARD_RESET_TIME);
break;
case PE_SNK_STARTUP:
@ -1829,8 +1826,6 @@ static void usbpd_sm(struct work_struct *w)
break;
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);
@ -2117,11 +2112,11 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr)
* During hard reset when VBUS goes to 0 the CC logic
* will report this as a disconnection. In those cases
* it can be ignored, however the downside is that
* pd->hard_reset can be momentarily true even when a
* non-PD capable source is attached, and can't be
* distinguished from a physical disconnect. In that
* case, allow for the common case of disconnecting
* from an SDP.
* we can also happen to be in the SNK_Transition_to_default
* state due to a hard reset attempt even with a non-PD
* capable source, in which a physical disconnect may get
* masked. In that case, allow for the common case of
* disconnecting from an SDP.
*
* The less common case is a PD-capable SDP which will
* result in a hard reset getting treated like a