From d7d6e7e660901fb73275ca41090115bed590e137 Mon Sep 17 00:00:00 2001 From: Vincent Palatin Date: Thu, 7 May 2015 08:43:07 -0700 Subject: ryu: update PD swaps configuration - allow power swap only when we are dual-role toggling (ie in S0). - enable the VCONN swap feature to support more type-C dongles. and allow it using the same rule as power swap. - become a power sink when we are connected to an externally powered DRP. - by default, try to be a data UFP for USB. so Dual Role Device such as laptops can get our data. - add a message to inform the AP that our USB role has changed (but the host events are fully wired yet on Ryu) Signed-off-by: Vincent Palatin BRANCH=none BUG=none TEST=make buildall Change-Id: Id0f9027b140cb20f105bcdbc00cac5cb5f44c9e0 Reviewed-on: https://chromium-review.googlesource.com/269857 Reviewed-by: Alec Berg Trybot-Ready: Vincent Palatin Commit-Queue: Vincent Palatin Tested-by: Vincent Palatin --- board/ryu/board.h | 1 + board/ryu/usb_pd_config.h | 3 +++ board/ryu/usb_pd_policy.c | 45 +++++++++++++++++++++++++++++++++++------- board/ryu_p4p5/board.c | 6 ++++++ board/ryu_p4p5/board.h | 4 ++++ board/ryu_p4p5/usb_pd_config.h | 3 +++ board/ryu_p4p5/usb_pd_policy.c | 45 +++++++++++++++++++++++++++++++++++------- include/ec_commands.h | 1 + 8 files changed, 94 insertions(+), 14 deletions(-) diff --git a/board/ryu/board.h b/board/ryu/board.h index f0210f8f5d..ad017a48b6 100644 --- a/board/ryu/board.h +++ b/board/ryu/board.h @@ -33,6 +33,7 @@ #define CONFIG_USB_SWITCH_PI3USB9281 #define CONFIG_USBC_SS_MUX #define CONFIG_USBC_VCONN +#define CONFIG_USBC_VCONN_SWAP #define CONFIG_ADC #define CONFIG_ADC_SAMPLE_TIME 3 #define CONFIG_HW_CRC diff --git a/board/ryu/usb_pd_config.h b/board/ryu/usb_pd_config.h index 9d6784beb4..c6d6882b0f 100644 --- a/board/ryu/usb_pd_config.h +++ b/board/ryu/usb_pd_config.h @@ -220,6 +220,9 @@ static inline int pd_snk_is_vbus_provided(int port) #define PD_POWER_SUPPLY_TURN_ON_DELAY 40000 /* us */ #define PD_POWER_SUPPLY_TURN_OFF_DELAY 20000 /* 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 10000 #define PD_MAX_POWER_MW 24000 diff --git a/board/ryu/usb_pd_policy.c b/board/ryu/usb_pd_policy.c index d423fe22f0..b171e3e9aa 100644 --- a/board/ryu/usb_pd_policy.c +++ b/board/ryu/usb_pd_policy.c @@ -114,27 +114,58 @@ int pd_board_checks(void) int pd_check_power_swap(int port) { /* TODO: use battery level to decide to accept/reject power swap */ - /* Always allow power swap */ - return 1; + /* + * Allow power swap as long as we are acting as a dual role device, + * otherwise assume our role is fixed (not in S0 or console command + * to fix our role). + */ + return pd_get_dual_role() == PD_DRP_TOGGLE_ON ? 1 : 0; } int pd_check_data_swap(int port, int data_role) { - /* Always allow data swap */ + /* Always allow data swap: we can be DFP or UFP for USB */ return 1; } -void pd_check_pr_role(int port, int pr_role, int flags) +int pd_check_vconn_swap(int port) { + /* + * VCONN is provided directly by the battery(PPVAR_SYS) + * but use the same rules as power swap + */ + return pd_get_dual_role() == PD_DRP_TOGGLE_ON ? 1 : 0; } -void pd_check_dr_role(int port, int dr_role, int flags) +void pd_execute_data_swap(int port, int data_role) { + /* inform the host controller to change role */ + pd_send_host_event(PD_EVENT_DATA_SWAP); } -void pd_execute_data_swap(int port, int data_role) +void pd_check_pr_role(int port, int pr_role, int flags) +{ + /* + * If partner is dual-role power and dualrole toggling is on, consider + * if a power swap is necessary. + */ + if ((flags & PD_FLAGS_PARTNER_DR_POWER) && + pd_get_dual_role() == PD_DRP_TOGGLE_ON) { + /* + * If we are source and partner is externally powered, + * swap to become a sink. + */ + if ((flags & PD_FLAGS_PARTNER_EXTPOWER) && + pr_role == PD_ROLE_SOURCE) + pd_request_power_swap(port); + } +} + +void pd_check_dr_role(int port, int dr_role, int flags) { - /* TODO: what do we need to do to change host controller data role? */ + /* if the partner is a DRP (e.g. laptop), try to switch to UFP */ + if ((flags & PD_FLAGS_PARTNER_DR_DATA) && dr_role == PD_ROLE_DFP) + pd_request_data_swap(port); } /* ----------------- Vendor Defined Messages ------------------ */ diff --git a/board/ryu_p4p5/board.c b/board/ryu_p4p5/board.c index e00dec962d..6694612210 100644 --- a/board/ryu_p4p5/board.c +++ b/board/ryu_p4p5/board.c @@ -585,6 +585,12 @@ void board_set_charge_limit(int charge_ma) CPRINTS("Failed to set input current limit for PD"); } +/* Send host event up to AP */ +void pd_send_host_event(int mask) +{ + /* TODO(crosbug.com/p/33194): implement host events */ +} + /** * Return whether ramping is allowed for given supplier */ diff --git a/board/ryu_p4p5/board.h b/board/ryu_p4p5/board.h index 104e3d0fb9..6c5479d49a 100644 --- a/board/ryu_p4p5/board.h +++ b/board/ryu_p4p5/board.h @@ -32,6 +32,7 @@ #define CONFIG_USB_SWITCH_PI3USB9281 #define CONFIG_USBC_SS_MUX #define CONFIG_USBC_VCONN +#define CONFIG_USBC_VCONN_SWAP #define CONFIG_ADC #define CONFIG_ADC_SAMPLE_TIME 3 #define CONFIG_HW_CRC @@ -194,6 +195,9 @@ int board_discharge_on_ac(int enable); /* Set the charge current limit. */ void board_set_charge_limit(int charge_ma); +/* Send host event to AP */ +void pd_send_host_event(int mask); + /* PP1800 transition GPIO interrupt handler */ void pp1800_on_off_evt(enum gpio_signal signal); diff --git a/board/ryu_p4p5/usb_pd_config.h b/board/ryu_p4p5/usb_pd_config.h index a100ddb2ac..bb7392f450 100644 --- a/board/ryu_p4p5/usb_pd_config.h +++ b/board/ryu_p4p5/usb_pd_config.h @@ -215,6 +215,9 @@ static inline int pd_snk_is_vbus_provided(int port) #define PD_POWER_SUPPLY_TURN_ON_DELAY 20000 /* us */ #define PD_POWER_SUPPLY_TURN_OFF_DELAY 20000 /* 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 10000 #define PD_MAX_POWER_MW 24000 diff --git a/board/ryu_p4p5/usb_pd_policy.c b/board/ryu_p4p5/usb_pd_policy.c index b7550b1480..b20c0774cc 100644 --- a/board/ryu_p4p5/usb_pd_policy.c +++ b/board/ryu_p4p5/usb_pd_policy.c @@ -109,27 +109,58 @@ int pd_board_checks(void) int pd_check_power_swap(int port) { /* TODO: use battery level to decide to accept/reject power swap */ - /* Always allow power swap */ - return 1; + /* + * Allow power swap as long as we are acting as a dual role device, + * otherwise assume our role is fixed (not in S0 or console command + * to fix our role). + */ + return pd_get_dual_role() == PD_DRP_TOGGLE_ON ? 1 : 0; } int pd_check_data_swap(int port, int data_role) { - /* Always allow data swap */ + /* Always allow data swap: we can be DFP or UFP for USB */ return 1; } -void pd_check_pr_role(int port, int pr_role, int flags) +int pd_check_vconn_swap(int port) { + /* + * VCONN is provided directly by the battery(PPVAR_SYS) + * but use the same rules as power swap + */ + return pd_get_dual_role() == PD_DRP_TOGGLE_ON ? 1 : 0; } -void pd_check_dr_role(int port, int dr_role, int flags) +void pd_execute_data_swap(int port, int data_role) { + /* inform the host controller to change role */ + pd_send_host_event(PD_EVENT_DATA_SWAP); } -void pd_execute_data_swap(int port, int data_role) +void pd_check_pr_role(int port, int pr_role, int flags) +{ + /* + * If partner is dual-role power and dualrole toggling is on, consider + * if a power swap is necessary. + */ + if ((flags & PD_FLAGS_PARTNER_DR_POWER) && + pd_get_dual_role() == PD_DRP_TOGGLE_ON) { + /* + * If we are source and partner is externally powered, + * swap to become a sink. + */ + if ((flags & PD_FLAGS_PARTNER_EXTPOWER) && + pr_role == PD_ROLE_SOURCE) + pd_request_power_swap(port); + } +} + +void pd_check_dr_role(int port, int dr_role, int flags) { - /* TODO: what do we need to do to change host controller data role? */ + /* if the partner is a DRP (e.g. laptop), try to switch to UFP */ + if ((flags & PD_FLAGS_PARTNER_DR_DATA) && dr_role == PD_ROLE_DFP) + pd_request_data_swap(port); } int pd_custom_vdm(int port, int cnt, uint32_t *payload, diff --git a/include/ec_commands.h b/include/ec_commands.h index cb064b9588..ad3056e3e8 100644 --- a/include/ec_commands.h +++ b/include/ec_commands.h @@ -2927,6 +2927,7 @@ struct ec_response_pd_status { #define PD_EVENT_UPDATE_DEVICE (1 << 0) #define PD_EVENT_POWER_CHANGE (1 << 1) #define PD_EVENT_IDENTITY_RECEIVED (1 << 2) +#define PD_EVENT_DATA_SWAP (1 << 3) struct ec_response_host_event_status { uint32_t status; /* PD MCU host event status */ } __packed; -- cgit v1.2.1