usb: pd: Improve sink hard reset handling
During hard reset in sink mode, move the wait for VBUS to reconnect to the PE_SNK_TRANSITION_TO_DEFAULT state. Use the hrtimer to wait up to the maximum expected time for VBUS to come back, which is triggered by the CC notification from psy_changed(). This simplifies PE_SNK_STARTUP to only be invoked when VBUS is already present and eliminates the PE_SNK_DISCOVERY state. When a non-PD source is connected, as the engine attempts to wait for source capabilities this will result in hard reset getting attempted 3 times with the hrtimer reaching full timeout each time (for a total of ~6s) before settling. Change-Id: Iee74c206b28fea9b75df2d234609a7939bc3d93c Signed-off-by: Jack Pham <jackp@codeaurora.org>
This commit is contained in:
parent
773f15cdab
commit
172cec3a2c
1 changed files with 26 additions and 32 deletions
|
@ -170,6 +170,9 @@ static void *usbpd_ipc_log;
|
||||||
#define PS_SOURCE_OFF 750
|
#define PS_SOURCE_OFF 750
|
||||||
#define VDM_BUSY_TIME 50
|
#define VDM_BUSY_TIME 50
|
||||||
|
|
||||||
|
/* tPSHardReset + tSafe0V + tSrcRecover + tSrcTurnOn */
|
||||||
|
#define SNK_HARD_RESET_RECOVER_TIME (35 + 650 + 1000 + 275)
|
||||||
|
|
||||||
#define PD_CAPS_COUNT 50
|
#define PD_CAPS_COUNT 50
|
||||||
|
|
||||||
#define PD_MAX_MSG_ID 7
|
#define PD_MAX_MSG_ID 7
|
||||||
|
@ -800,18 +803,6 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
|
||||||
pd->in_pr_swap = false;
|
pd->in_pr_swap = false;
|
||||||
pd->current_voltage = 5000000;
|
pd->current_voltage = 5000000;
|
||||||
|
|
||||||
if (!pd->vbus_present) {
|
|
||||||
/* can get here during a hard reset and we lost vbus */
|
|
||||||
pd->current_state = PE_SNK_DISCOVERY;
|
|
||||||
hrtimer_start(&pd->timer, ms_to_ktime(2000),
|
|
||||||
HRTIMER_MODE_REL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If VBUS is already present go and skip ahead to
|
|
||||||
* PE_SNK_WAIT_FOR_CAPABILITIES.
|
|
||||||
*/
|
|
||||||
pd->current_state = PE_SNK_WAIT_FOR_CAPABILITIES;
|
pd->current_state = PE_SNK_WAIT_FOR_CAPABILITIES;
|
||||||
/* fall-through */
|
/* fall-through */
|
||||||
|
|
||||||
|
@ -882,8 +873,10 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
|
||||||
POWER_SUPPLY_PROP_VOLTAGE_MAX, &val);
|
POWER_SUPPLY_PROP_VOLTAGE_MAX, &val);
|
||||||
pd->current_voltage = pd->requested_voltage;
|
pd->current_voltage = pd->requested_voltage;
|
||||||
|
|
||||||
/* recursive call; go back to beginning state */
|
/* max time for hard reset to toggle vbus off/on */
|
||||||
usbpd_set_state(pd, PE_SNK_STARTUP);
|
hrtimer_start(&pd->timer,
|
||||||
|
ms_to_ktime(SNK_HARD_RESET_RECOVER_TIME),
|
||||||
|
HRTIMER_MODE_REL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -1465,21 +1458,6 @@ static void usbpd_sm(struct work_struct *w)
|
||||||
usbpd_set_state(pd, PE_SRC_TRANSITION_TO_DEFAULT);
|
usbpd_set_state(pd, PE_SRC_TRANSITION_TO_DEFAULT);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PE_SNK_DISCOVERY:
|
|
||||||
if (!pd->vbus_present) {
|
|
||||||
/* Hard reset and VBUS didn't come back? */
|
|
||||||
power_supply_get_property(pd->usb_psy,
|
|
||||||
POWER_SUPPLY_PROP_TYPE, &val);
|
|
||||||
if (val.intval == POWER_SUPPLY_TYPEC_NONE) {
|
|
||||||
pd->typec_mode = POWER_SUPPLY_TYPEC_NONE;
|
|
||||||
queue_work(pd->wq, &pd->sm_work);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
usbpd_set_state(pd, PE_SNK_WAIT_FOR_CAPABILITIES);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PE_SNK_WAIT_FOR_CAPABILITIES:
|
case PE_SNK_WAIT_FOR_CAPABILITIES:
|
||||||
if (data_recvd == MSG_SOURCE_CAPABILITIES) {
|
if (data_recvd == MSG_SOURCE_CAPABILITIES) {
|
||||||
val.intval = 1;
|
val.intval = 1;
|
||||||
|
@ -1611,6 +1589,20 @@ static void usbpd_sm(struct work_struct *w)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PE_SNK_TRANSITION_TO_DEFAULT:
|
||||||
|
if (pd->vbus_present) {
|
||||||
|
usbpd_set_state(pd, PE_SNK_STARTUP);
|
||||||
|
} else {
|
||||||
|
/* Hard reset and VBUS didn't come back? */
|
||||||
|
power_supply_get_property(pd->usb_psy,
|
||||||
|
POWER_SUPPLY_PROP_TYPEC_MODE, &val);
|
||||||
|
if (val.intval == POWER_SUPPLY_TYPEC_NONE) {
|
||||||
|
pd->typec_mode = POWER_SUPPLY_TYPEC_NONE;
|
||||||
|
queue_work(pd->wq, &pd->sm_work);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case PE_SRC_SOFT_RESET:
|
case PE_SRC_SOFT_RESET:
|
||||||
case PE_SNK_SOFT_RESET:
|
case PE_SNK_SOFT_RESET:
|
||||||
/* Reset protocol layer */
|
/* Reset protocol layer */
|
||||||
|
@ -1846,11 +1838,12 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr)
|
||||||
* until the HW bug is fixed: in which disconnection won't be reported
|
* until the HW bug is fixed: in which disconnection won't be reported
|
||||||
* on VBUS loss alone unless pullup is also removed from CC.
|
* on VBUS loss alone unless pullup is also removed from CC.
|
||||||
*/
|
*/
|
||||||
if ((pd->hard_reset || pd->in_pr_swap) &&
|
if ((pd->current_state == PE_SNK_TRANSITION_TO_DEFAULT ||
|
||||||
|
pd->in_pr_swap) &&
|
||||||
typec_mode == POWER_SUPPLY_TYPEC_NONE &&
|
typec_mode == POWER_SUPPLY_TYPEC_NONE &&
|
||||||
pd->psy_type != POWER_SUPPLY_TYPE_USB) {
|
pd->psy_type != POWER_SUPPLY_TYPE_USB) {
|
||||||
usbpd_dbg(&pd->dev, "Ignoring disconnect due to %s\n",
|
usbpd_dbg(&pd->dev, "Ignoring disconnect due to %s\n",
|
||||||
pd->hard_reset ? "hard reset" : "PR swap");
|
pd->in_pr_swap ? "PR swap" : "hard reset");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1885,7 +1878,8 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr)
|
||||||
case POWER_SUPPLY_TYPEC_SOURCE_HIGH:
|
case POWER_SUPPLY_TYPEC_SOURCE_HIGH:
|
||||||
usbpd_info(&pd->dev, "Type-C Source (%s) connected\n",
|
usbpd_info(&pd->dev, "Type-C Source (%s) connected\n",
|
||||||
src_current(typec_mode));
|
src_current(typec_mode));
|
||||||
if (pd->current_pr != PR_SINK) {
|
if (pd->current_pr != PR_SINK ||
|
||||||
|
pd->current_state == PE_SNK_TRANSITION_TO_DEFAULT) {
|
||||||
pd->current_pr = PR_SINK;
|
pd->current_pr = PR_SINK;
|
||||||
queue_work(pd->wq, &pd->sm_work);
|
queue_work(pd->wq, &pd->sm_work);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue