mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-10 17:41:54 +00:00
pd: samus: support vconn swap and enable on Samus when in S0/S3
Support VCONN swap on samus and always accept VCONN swap when in S0 or S3. In S5, we can't provide VCONN, so reject VCONN swap requests. BUG=chrome-os-partner:34978 BRANCH=samus TEST=load on two samus' and use "pd 1 swap vconn" to swap which side is source vconn. also run in S5 and verify swap request is rejected. Change-Id: I04be8d1d910a2d6c5ad8b27a790f8e33121c86ee Signed-off-by: Alec Berg <alecaberg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/264856 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
This commit is contained in:
committed by
ChromeOS Commit Bot
parent
007fadda59
commit
f224ae87bd
@@ -61,6 +61,7 @@
|
||||
#define CONFIG_USB_SWITCH_PI3USB9281_MUX_GPIO GPIO_USB_C_BC12_SEL
|
||||
#define CONFIG_USBC_SS_MUX
|
||||
#define CONFIG_USBC_VCONN
|
||||
#define CONFIG_USBC_VCONN_SWAP
|
||||
#define CONFIG_VBOOT_HASH
|
||||
#undef CONFIG_WATCHDOG_HELP
|
||||
|
||||
|
||||
@@ -301,6 +301,9 @@ static inline int pd_snk_is_vbus_provided(int port)
|
||||
#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */
|
||||
#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */
|
||||
|
||||
/* delay to turn on/off vconn */
|
||||
#define PD_VCONN_SWAP_DELAY 5000 /* us */
|
||||
|
||||
/* Define typical operating power and max power */
|
||||
#define PD_OPERATING_POWER_MW 15000
|
||||
#define PD_MAX_POWER_MW 60000
|
||||
|
||||
@@ -151,6 +151,12 @@ int pd_check_data_swap(int port, int data_role)
|
||||
return (data_role == PD_ROLE_UFP) ? 1 : 0;
|
||||
}
|
||||
|
||||
int pd_check_vconn_swap(int port)
|
||||
{
|
||||
/* in S5, do not allow vconn swap since pp5000 rail is off */
|
||||
return gpio_get_level(GPIO_PCH_SLP_S5_L);
|
||||
}
|
||||
|
||||
void pd_execute_data_swap(int port, int data_role)
|
||||
{
|
||||
/* Open USB switches when taking UFP role */
|
||||
|
||||
@@ -313,6 +313,9 @@ static const char * const pd_state_names[] = {
|
||||
#ifdef CONFIG_USB_PD_DUAL_ROLE
|
||||
"SRC_SWAP_INIT", "SRC_SWAP_SNK_DISABLE", "SRC_SWAP_SRC_DISABLE",
|
||||
"SRC_SWAP_STANDBY",
|
||||
#ifdef CONFIG_USBC_VCONN_SWAP
|
||||
"VCONN_SWAP_SEND", "VCONN_SWAP_INIT", "VCONN_SWAP_READY",
|
||||
#endif /* CONFIG_USBC_VCONN_SWAP */
|
||||
#endif /* CONFIG_USB_PD_DUAL_ROLE */
|
||||
"SOFT_RESET", "HARD_RESET_SEND", "HARD_RESET_EXECUTE", "BIST_RX",
|
||||
"BIST_TX",
|
||||
@@ -1189,6 +1192,15 @@ static void handle_ctrl_request(int port, uint16_t head,
|
||||
pd[port].msg_id = 0;
|
||||
pd[port].power_role = PD_ROLE_SINK;
|
||||
set_state(port, PD_STATE_SNK_DISCOVERY);
|
||||
#ifdef CONFIG_USBC_VCONN_SWAP
|
||||
} else if (pd[port].task_state == PD_STATE_VCONN_SWAP_INIT) {
|
||||
/*
|
||||
* If VCONN is on, then this PS_RDY tells us it's
|
||||
* ok to turn VCONN off
|
||||
*/
|
||||
if (pd[port].flags & PD_FLAGS_VCONN_ON)
|
||||
set_state(port, PD_STATE_VCONN_SWAP_READY);
|
||||
#endif
|
||||
} else if (pd[port].task_state == PD_STATE_SNK_DISCOVERY) {
|
||||
/* Don't know what power source is ready. Reset. */
|
||||
set_state(port, PD_STATE_HARD_RESET_SEND);
|
||||
@@ -1210,6 +1222,10 @@ static void handle_ctrl_request(int port, uint16_t head,
|
||||
case PD_CTRL_WAIT:
|
||||
if (pd[port].task_state == PD_STATE_DR_SWAP)
|
||||
set_state(port, READY_RETURN_STATE(port));
|
||||
#ifdef CONFIG_USBC_VCONN_SWAP
|
||||
else if (pd[port].task_state == PD_STATE_VCONN_SWAP_SEND)
|
||||
set_state(port, READY_RETURN_STATE(port));
|
||||
#endif
|
||||
#ifdef CONFIG_USB_PD_DUAL_ROLE
|
||||
else if (pd[port].task_state == PD_STATE_SRC_SWAP_INIT)
|
||||
set_state(port, PD_STATE_SRC_READY);
|
||||
@@ -1227,9 +1243,13 @@ static void handle_ctrl_request(int port, uint16_t head,
|
||||
/* switch data role */
|
||||
pd_dr_swap(port);
|
||||
set_state(port, READY_RETURN_STATE(port));
|
||||
}
|
||||
#ifdef CONFIG_USB_PD_DUAL_ROLE
|
||||
else if (pd[port].task_state == PD_STATE_SRC_SWAP_INIT) {
|
||||
#ifdef CONFIG_USBC_VCONN_SWAP
|
||||
} else if (pd[port].task_state == PD_STATE_VCONN_SWAP_SEND) {
|
||||
/* switch vconn */
|
||||
set_state(port, PD_STATE_VCONN_SWAP_INIT);
|
||||
#endif
|
||||
} else if (pd[port].task_state == PD_STATE_SRC_SWAP_INIT) {
|
||||
/* explicit contract goes away for power swap */
|
||||
pd[port].flags &= ~PD_FLAGS_EXPLICIT_CONTRACT;
|
||||
set_state(port, PD_STATE_SRC_SWAP_SNK_DISABLE);
|
||||
@@ -1241,8 +1261,8 @@ static void handle_ctrl_request(int port, uint16_t head,
|
||||
/* explicit contract is now in place */
|
||||
pd[port].flags |= PD_FLAGS_EXPLICIT_CONTRACT;
|
||||
set_state(port, PD_STATE_SNK_TRANSITION);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case PD_CTRL_SOFT_RESET:
|
||||
execute_soft_reset(port);
|
||||
@@ -1284,7 +1304,20 @@ static void handle_ctrl_request(int port, uint16_t head,
|
||||
}
|
||||
break;
|
||||
case PD_CTRL_VCONN_SWAP:
|
||||
#ifdef CONFIG_USBC_VCONN_SWAP
|
||||
if (pd[port].task_state == PD_STATE_SRC_READY ||
|
||||
pd[port].task_state == PD_STATE_SNK_READY) {
|
||||
if (pd_check_vconn_swap(port)) {
|
||||
if (send_control(port, PD_CTRL_ACCEPT) > 0)
|
||||
set_state(port,
|
||||
PD_STATE_VCONN_SWAP_INIT);
|
||||
} else {
|
||||
send_control(port, PD_CTRL_REJECT);
|
||||
}
|
||||
}
|
||||
#else
|
||||
send_control(port, PD_CTRL_REJECT);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
CPRINTF("Unhandled ctrl message type %d\n", type);
|
||||
@@ -1985,6 +2018,7 @@ void pd_task(void)
|
||||
|
||||
#ifdef CONFIG_USBC_VCONN
|
||||
pd_set_vconn(port, pd[port].polarity, 1);
|
||||
pd[port].flags |= PD_FLAGS_VCONN_ON;
|
||||
#endif
|
||||
|
||||
pd[port].flags |= PD_FLAGS_CHECK_PR_ROLE |
|
||||
@@ -2652,6 +2686,76 @@ void pd_task(void)
|
||||
set_state(port, PD_STATE_SRC_DISCOVERY);
|
||||
timeout = 10*MSEC;
|
||||
break;
|
||||
#ifdef CONFIG_USBC_VCONN_SWAP
|
||||
case PD_STATE_VCONN_SWAP_SEND:
|
||||
if (pd[port].last_state != pd[port].task_state) {
|
||||
res = send_control(port, PD_CTRL_VCONN_SWAP);
|
||||
if (res < 0) {
|
||||
timeout = 10*MSEC;
|
||||
/*
|
||||
* If failed to get goodCRC, send
|
||||
* soft reset, otherwise ignore
|
||||
* failure.
|
||||
*/
|
||||
set_state(port, res == -1 ?
|
||||
PD_STATE_SOFT_RESET :
|
||||
READY_RETURN_STATE(port));
|
||||
break;
|
||||
}
|
||||
/* Wait for accept or reject */
|
||||
set_state_timeout(port,
|
||||
get_time().val +
|
||||
PD_T_SENDER_RESPONSE,
|
||||
READY_RETURN_STATE(port));
|
||||
}
|
||||
break;
|
||||
case PD_STATE_VCONN_SWAP_INIT:
|
||||
if (pd[port].last_state != pd[port].task_state) {
|
||||
if (!(pd[port].flags & PD_FLAGS_VCONN_ON)) {
|
||||
/* Turn VCONN on and wait for it */
|
||||
pd_set_vconn(port, pd[port].polarity,
|
||||
1);
|
||||
set_state_timeout(port,
|
||||
get_time().val + PD_VCONN_SWAP_DELAY,
|
||||
PD_STATE_VCONN_SWAP_READY);
|
||||
} else {
|
||||
set_state_timeout(port,
|
||||
get_time().val + PD_T_VCONN_SOURCE_ON,
|
||||
READY_RETURN_STATE(port));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PD_STATE_VCONN_SWAP_READY:
|
||||
if (pd[port].last_state != pd[port].task_state) {
|
||||
if (!(pd[port].flags & PD_FLAGS_VCONN_ON)) {
|
||||
/* VCONN is now on, send PS_RDY */
|
||||
pd[port].flags |= PD_FLAGS_VCONN_ON;
|
||||
res = send_control(port,
|
||||
PD_CTRL_PS_RDY);
|
||||
if (res == -1) {
|
||||
timeout = 10*MSEC;
|
||||
/*
|
||||
* If failed to get goodCRC,
|
||||
* send soft reset
|
||||
*/
|
||||
set_state(port,
|
||||
PD_STATE_SOFT_RESET);
|
||||
break;
|
||||
}
|
||||
set_state(port,
|
||||
READY_RETURN_STATE(port));
|
||||
} else {
|
||||
/* Turn VCONN off and wait for it */
|
||||
pd_set_vconn(port, pd[port].polarity,
|
||||
0);
|
||||
pd[port].flags &= ~PD_FLAGS_VCONN_ON;
|
||||
set_state_timeout(port,
|
||||
get_time().val + PD_VCONN_SWAP_DELAY,
|
||||
READY_RETURN_STATE(port));
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif /* CONFIG_USBC_VCONN_SWAP */
|
||||
#endif /* CONFIG_USB_PD_DUAL_ROLE */
|
||||
case PD_STATE_SOFT_RESET:
|
||||
if (pd[port].last_state != pd[port].task_state) {
|
||||
@@ -3144,12 +3248,18 @@ static int command_pd(int argc, char **argv)
|
||||
if (argc < 4)
|
||||
return EC_ERROR_PARAM_COUNT;
|
||||
|
||||
if (!strncasecmp(argv[3], "power", 5))
|
||||
if (!strncasecmp(argv[3], "power", 5)) {
|
||||
pd_request_power_swap(port);
|
||||
else if (!strncasecmp(argv[3], "data", 4))
|
||||
} else if (!strncasecmp(argv[3], "data", 4)) {
|
||||
pd_request_data_swap(port);
|
||||
else
|
||||
#ifdef CONFIG_USBC_VCONN_SWAP
|
||||
} else if (!strncasecmp(argv[3], "vconn", 5)) {
|
||||
set_state(port, PD_STATE_VCONN_SWAP_SEND);
|
||||
task_wake(PORT_TO_TASK_ID(port));
|
||||
#endif
|
||||
} else {
|
||||
return EC_ERROR_PARAM3;
|
||||
}
|
||||
} else if (!strncasecmp(argv[2], "ping", 4)) {
|
||||
int enable;
|
||||
|
||||
@@ -3192,11 +3302,12 @@ static int command_pd(int argc, char **argv)
|
||||
} else
|
||||
#endif
|
||||
if (!strncasecmp(argv[2], "state", 5)) {
|
||||
ccprintf("Port C%d, %s - Role: %s-%s Polarity: CC%d "
|
||||
ccprintf("Port C%d, %s - Role: %s-%s%s Polarity: CC%d "
|
||||
"Flags: 0x%04x, State: %s\n",
|
||||
port, pd_comm_enabled ? "Ena" : "Dis",
|
||||
pd[port].power_role == PD_ROLE_SOURCE ? "SRC" : "SNK",
|
||||
pd[port].data_role == PD_ROLE_DFP ? "DFP" : "UFP",
|
||||
(pd[port].flags & PD_FLAGS_VCONN_ON) ? "-VC" : "",
|
||||
pd[port].polarity + 1,
|
||||
pd[port].flags,
|
||||
pd_state_names[pd[port].task_state]);
|
||||
|
||||
@@ -1279,6 +1279,9 @@
|
||||
/* Support for USB type-c vconn. Not needed for captive cables. */
|
||||
#undef CONFIG_USBC_VCONN
|
||||
|
||||
/* Support VCONN swap */
|
||||
#undef CONFIG_USBC_VCONN_SWAP
|
||||
|
||||
/* USB Binary device Object Store support */
|
||||
#undef CONFIG_USB_BOS
|
||||
|
||||
|
||||
@@ -136,6 +136,7 @@ enum pd_errors {
|
||||
#define PD_T_NO_RESPONSE (5500*MSEC) /* between 4.5s and 5.5s */
|
||||
#define PD_T_BIST_TRANSMIT (50*MSEC) /* 50ms (used for task_wait arg) */
|
||||
#define PD_T_BIST_RECEIVE (60*MSEC) /* 60ms (max time to process bist) */
|
||||
#define PD_T_VCONN_SOURCE_ON (100*MSEC) /* 100ms */
|
||||
|
||||
/* number of edges and time window to detect CC line is not idle */
|
||||
#define PD_RX_TRANSITION_COUNT 3
|
||||
@@ -621,6 +622,12 @@ enum pd_states {
|
||||
PD_STATE_SRC_SWAP_SNK_DISABLE,
|
||||
PD_STATE_SRC_SWAP_SRC_DISABLE,
|
||||
PD_STATE_SRC_SWAP_STANDBY,
|
||||
|
||||
#ifdef CONFIG_USBC_VCONN_SWAP
|
||||
PD_STATE_VCONN_SWAP_SEND,
|
||||
PD_STATE_VCONN_SWAP_INIT,
|
||||
PD_STATE_VCONN_SWAP_READY,
|
||||
#endif /* CONFIG_USBC_VCONN_SWAP */
|
||||
#endif /* CONFIG_USB_PD_DUAL_ROLE */
|
||||
|
||||
PD_STATE_SOFT_RESET,
|
||||
@@ -647,6 +654,7 @@ enum pd_states {
|
||||
#define PD_FLAGS_CHECK_PR_ROLE (1 << 9) /* check power role in READY */
|
||||
#define PD_FLAGS_CHECK_DR_ROLE (1 << 10)/* check data role in READY */
|
||||
#define PD_FLAGS_PARTNER_EXTPOWER (1 << 11)/* port partner has external pwr */
|
||||
#define PD_FLAGS_VCONN_ON (1 << 12)/* vconn is being sourced */
|
||||
/* Flags to clear on a disconnect */
|
||||
#define PD_FLAGS_RESET_ON_DISCONNECT_MASK (PD_FLAGS_PARTNER_DR_POWER | \
|
||||
PD_FLAGS_PARTNER_DR_DATA | \
|
||||
@@ -657,7 +665,8 @@ enum pd_states {
|
||||
PD_FLAGS_PREVIOUS_PD_CONN | \
|
||||
PD_FLAGS_CHECK_PR_ROLE | \
|
||||
PD_FLAGS_CHECK_DR_ROLE | \
|
||||
PD_FLAGS_PARTNER_EXTPOWER)
|
||||
PD_FLAGS_PARTNER_EXTPOWER | \
|
||||
PD_FLAGS_VCONN_ON)
|
||||
|
||||
|
||||
enum pd_cc_states {
|
||||
@@ -736,11 +745,15 @@ enum pd_data_msg_type {
|
||||
#define PD_REV10 0
|
||||
#define PD_REV20 1
|
||||
|
||||
/* Port role */
|
||||
/* Power role */
|
||||
#define PD_ROLE_SINK 0
|
||||
#define PD_ROLE_SOURCE 1
|
||||
/* Data role */
|
||||
#define PD_ROLE_UFP 0
|
||||
#define PD_ROLE_DFP 1
|
||||
/* Vconn role */
|
||||
#define PD_ROLE_VCONN_OFF 0
|
||||
#define PD_ROLE_VCONN_ON 1
|
||||
|
||||
/* build message header */
|
||||
#define PD_HEADER(type, prole, drole, id, cnt) \
|
||||
@@ -908,6 +921,15 @@ int pd_check_power_swap(int port);
|
||||
*/
|
||||
int pd_check_data_swap(int port, int data_role);
|
||||
|
||||
/**
|
||||
* Check if vconn swap is allowed.
|
||||
*
|
||||
* @param port USB-C port number
|
||||
* @return True if vconn swap is allowed, False otherwise
|
||||
*/
|
||||
|
||||
int pd_check_vconn_swap(int port);
|
||||
|
||||
/**
|
||||
* Check current power role for potential power swap
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user