Merge "usb: pd: Observe PSHardResetTimer for source hard reset"
This commit is contained in:
commit
aae17b0582
1 changed files with 51 additions and 56 deletions
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue