From fe951556a7be3bc68b342dc941be13ff4f82f41b Mon Sep 17 00:00:00 2001 From: li feng Date: Fri, 21 Aug 2020 15:23:28 -0700 Subject: TCPMv2: support TBT Alt mode as UFP Implemented SVDM responders for TBT Alt mode BUG=b:148528713,b:157163664,b:162986785 BRANCH=none TEST=1. Build ec with CL:2382634; OS CPFE 13447, CB CPFE 13535 2. Boot up Volteer, run "pd trysrc 0" on EC console; 3. Then connect port 1 to TGL Windows RVP TBT port; 4. Thunderbolt connection is established. Volteer port 1 as UFP, Windows RVP TBT port as DFP. From host console, thunderbolt0 is listed as network interface in ifconfig. Signed-off-by: li feng Change-Id: If4c80418677f541e9c1c7c8c84446357000aaecb Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2370045 Reviewed-by: Vijay P Hiremath Reviewed-by: Aashay Shringarpure --- baseboard/volteer/usb_pd_policy.c | 137 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) (limited to 'baseboard/volteer/usb_pd_policy.c') diff --git a/baseboard/volteer/usb_pd_policy.c b/baseboard/volteer/usb_pd_policy.c index 39bbd918a5..a18e8c7149 100644 --- a/baseboard/volteer/usb_pd_policy.c +++ b/baseboard/volteer/usb_pd_policy.c @@ -4,9 +4,11 @@ */ /* Shared USB-C policy for Volteer boards */ #include "charge_manager.h" +#include "chipset.h" #include "compile_time_macros.h" #include "console.h" #include "gpio.h" +#include "usb_common.h" #include "usb_mux.h" #include "usbc_ppc.h" #include "usb_pd.h" @@ -79,3 +81,138 @@ int board_vbus_source_enabled(int port) { return ppc_is_sourcing_vbus(port); } + +/* ----------------- Vendor Defined Messages ------------------ */ +/* Responses specifically for the enablement of TBT mode in the role of UFP */ + +#define OPOS_TBT 1 +static union tbt_dev_mode_enter_cmd + ufp_enter_mode[CONFIG_USB_PD_PORT_MAX_COUNT]; + +static const union tbt_mode_resp_device vdo_tbt_modes[1] = { + { + .tbt_alt_mode = 0x0001, + .tbt_adapter = TBT_ADAPTER_TBT3, + .intel_spec_b0 = 0, + .vendor_spec_b0 = 0, + .vendor_spec_b1 = 0, + } +}; + +static const uint32_t vdo_idh = VDO_IDH( + 1, /* Data caps as USB host */ + 1, /* Data caps as USB device */ + IDH_PTYPE_PERIPH, + 1, /* Supports alt modes */ + USB_VID_GOOGLE); + +static const uint32_t vdo_idh_rev30 = VDO_IDH_REV30( + 1, /* Data caps as USB host */ + 1, /* Data caps as USB device */ + IDH_PTYPE_PERIPH, + 1, /* Supports alt modes */ + IDH_PTYPE_DFP_HOST, + USB_TYPEC_RECEPTACLE, + USB_VID_GOOGLE); + +/* TODO(b:157163664): add product version */ +static const uint32_t vdo_product = VDO_PRODUCT(CONFIG_USB_PID, 0); + +/* TODO(b/168890624): add USB4 to capability once USB4 response implemented */ +static const uint32_t vdo_ufp1 = VDO_UFP1( + (VDO_UFP1_CAPABILITY_USB20 + | VDO_UFP1_CAPABILITY_USB32), + USB_TYPEC_RECEPTACLE, + VDO_UFP1_ALT_MODE_TBT3, + USB_R30_SS_U40_GEN3); + +static const uint32_t vdo_dfp = VDO_DFP( + (VDO_DFP_HOST_CAPABILITY_USB20 + | VDO_DFP_HOST_CAPABILITY_USB32 + | VDO_DFP_HOST_CAPABILITY_USB4), + USB_TYPEC_RECEPTACLE, + 1 /* Port 1 */); + +static int svdm_tbt_compat_response_identity(int port, uint32_t *payload) +{ + /* TODO(b/154962766): Get an XID */ + payload[VDO_I(CSTAT)] = VDO_CSTAT(0); + payload[VDO_I(PRODUCT)] = vdo_product; + + if (pd_get_rev(port, TCPC_TX_SOP) == PD_REV30) { + /* PD Revision 3.0 */ + payload[VDO_I(IDH)] = vdo_idh_rev30; + payload[VDO_I(PTYPE_UFP1_VDO)] = vdo_ufp1; + /* TODO(b/156749387): Find power number for USB3/4 */ + payload[VDO_I(PTYPE_UFP2_VDO)] = 0; + payload[VDO_I(PTYPE_DFP_VDO)] = vdo_dfp; + return VDO_I(PTYPE_DFP_VDO) + 1; + } + + /* PD Revision 2.0 */ + payload[VDO_I(IDH)] = vdo_idh; + return VDO_I(PRODUCT) + 1; +} + +static int svdm_tbt_compat_response_svids(int port, uint32_t *payload) +{ + payload[1] = VDO_SVID(USB_VID_INTEL, 0); + return 2; +} + +static int svdm_tbt_compat_response_modes(int port, uint32_t *payload) +{ + if (PD_VDO_VID(payload[0]) == USB_VID_INTEL) { + memcpy(payload + 1, vdo_tbt_modes, sizeof(vdo_tbt_modes)); + return ARRAY_SIZE(vdo_tbt_modes) + 1; + } else { + return 0; /* NAK */ + } +} + +static int svdm_tbt_compat_response_enter_mode( + int port, uint32_t *payload) +{ + mux_state_t mux_state = 0; + + /* Do not enter mode while CPU is off. */ + if (chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF)) + return 0; /* NAK */ + + if ((PD_VDO_VID(payload[0]) != USB_VID_INTEL) || + (PD_VDO_OPOS(payload[0]) != OPOS_TBT)) + return 0; /* NAK */ + + mux_state = usb_mux_get(port); + /* + * Ref: USB PD 3.0 Spec figure 6-21 Successful Enter Mode sequence + * UFP (responder) should be in USB mode or safe mode before sending + * Enter Mode Command response. + */ + if ((mux_state & USB_PD_MUX_USB_ENABLED) || + (mux_state & USB_PD_MUX_SAFE_MODE)) { + + /* + * TODO(b:157163664): set retimer config for UFP + * Save TBT3 SOP VDO from request so retimer can use it + */ + ufp_enter_mode[port] = + (union tbt_dev_mode_enter_cmd)payload[1]; + + set_tbt_compat_mode_ready(port); + CPRINTS("UFP Enter TBT mode"); + return 1; /* ACK */ + } + + CPRINTS("UFP failed to enter TBT mode(mux=0x%x)", mux_state); + return 0; +} + +const struct svdm_response svdm_rsp = { + .identity = &svdm_tbt_compat_response_identity, + .svids = &svdm_tbt_compat_response_svids, + .modes = &svdm_tbt_compat_response_modes, + .enter_mode = &svdm_tbt_compat_response_enter_mode, + .amode = NULL, + .exit_mode = NULL, +}; -- cgit v1.2.1