usb_pd: Request Vconn swap to communicating with the cable

Before sending SOP' requests to cable plug, the port checks if
the port is the Vconn source. If the port isn't the Vconn source,
it can't talk to the cable.

From USB PD spec 1.3 sections 2.6.1 and 2.6.2, during an explicit
contract, after the data and power role swaps, if any, source/sink
can initiate or receive a request for exchanging the Vconn source.

Hence, adding support for the port to request Vconn swap, if it
hasn't already been swapped.

BUG=b:147209888
BRANCH=None
TEST=Checked on volteer, able to communicate with the cable plug

Change-Id: I36d896eda6319970b1a0a9bd7cc4efcbc381c8b1
Signed-off-by: Ayushee <ayushee.shah@intel.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1988234
Tested-by: Vijay P Hiremath <vijay.p.hiremath@intel.com>
Reviewed-by: Diana Z <dzigterman@chromium.org>
This commit is contained in:
Ayushee 2020-01-06 12:02:14 -08:00 committed by Commit Bot
parent d9d96d1b01
commit d3cef73e45
4 changed files with 62 additions and 1 deletions

View File

@ -655,6 +655,17 @@ __overridable void pd_execute_data_swap(int port,
{
}
__overridable void pd_try_execute_vconn_swap(int port, int flags)
{
/*
* If partner is dual-role power and vconn swap is enabled, consider
* if vconn swapping is necessary.
*/
if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE) &&
IS_ENABLED(CONFIG_USBC_VCONN_SWAP))
pd_try_vconn_src(port);
}
__overridable int pd_is_valid_input_voltage(int mv)
{
return 1;

View File

@ -3635,6 +3635,15 @@ void pd_task(void *u)
pd_check_pr_role(port, PD_ROLE_SOURCE,
pd[port].flags);
pd[port].flags &= ~PD_FLAGS_CHECK_PR_ROLE;
/*
* USB PD version 1.3 section 2.6.1:
* During Explicit contract the Sink can
* initiate or receive a request an exchange
* of VCONN Source. Hence, enable Vconn swap
* during explicit contract.
*/
pd[port].flags |= PD_FLAGS_CHECK_VCONN_STATE;
break;
}
@ -3646,6 +3655,14 @@ void pd_task(void *u)
break;
}
/* Check for Vconn source, which may trigger a swap */
if (pd[port].flags & PD_FLAGS_CHECK_VCONN_STATE) {
pd_try_execute_vconn_swap(port,
pd[port].flags);
pd[port].flags &= ~PD_FLAGS_CHECK_VCONN_STATE;
break;
}
/* Send discovery SVDMs last */
if (pd[port].data_role == PD_ROLE_DFP &&
(pd[port].flags & PD_FLAGS_CHECK_IDENTITY)) {
@ -4234,6 +4251,14 @@ void pd_task(void *u)
pd_check_pr_role(port, PD_ROLE_SINK,
pd[port].flags);
pd[port].flags &= ~PD_FLAGS_CHECK_PR_ROLE;
/*
* USB PD version 1.3 section 2.6.2:
* During Explicit contract the Sink can
* initiate or receive a request an exchange
* of VCONN Source. Hence, enable Vconn swap
* during explicit contract.
*/
pd[port].flags |= PD_FLAGS_CHECK_VCONN_STATE;
break;
}
@ -4245,6 +4270,14 @@ void pd_task(void *u)
break;
}
/* Check for Vconn source, which may trigger a swap */
if (pd[port].flags & PD_FLAGS_CHECK_VCONN_STATE) {
pd_try_execute_vconn_swap(port,
pd[port].flags);
pd[port].flags &= ~PD_FLAGS_CHECK_VCONN_STATE;
break;
}
/* If DFP, send discovery SVDMs */
if (pd[port].data_role == PD_ROLE_DFP &&
(pd[port].flags & PD_FLAGS_CHECK_IDENTITY)) {

View File

@ -19,3 +19,7 @@ int pd_check_vconn_swap(int port)
{
return 1;
}
__override void pd_try_vconn_src(int port)
{
}

View File

@ -834,6 +834,9 @@ enum pd_states {
*/
#define PD_FLAGS_SNK_WAITING_BATT BIT(20)
/* Check vconn state in READY */
#define PD_FLAGS_CHECK_VCONN_STATE BIT(21)
/* Flags to clear on a disconnect */
#define PD_FLAGS_RESET_ON_DISCONNECT_MASK (PD_FLAGS_PARTNER_DR_POWER | \
PD_FLAGS_PARTNER_DR_DATA | \
@ -850,7 +853,8 @@ enum pd_states {
PD_FLAGS_PARTNER_USB_COMM | \
PD_FLAGS_UPDATE_SRC_CAPS | \
PD_FLAGS_TS_DTS_PARTNER | \
PD_FLAGS_SNK_WAITING_BATT)
PD_FLAGS_SNK_WAITING_BATT | \
PD_FLAGS_CHECK_VCONN_STATE)
/* Per-port battery backed RAM flags */
#define PD_BBRMFLG_EXPLICIT_CONTRACT BIT(0)
@ -1411,6 +1415,15 @@ __override_proto void pd_check_dr_role(int port,
enum pd_data_role dr_role,
int flags);
/**
* Check for a potential Vconn swap if the port isn't
* supplying Vconn
*
* @param port USB-C port number
* @param flags PD flags
*/
__override_proto void pd_try_execute_vconn_swap(int port, int flags);
/**
* Check if we should charge from this device. This is
* basically a white-list for chargers that are dual-role,