diff options
author | Wai-Hong Tam <waihong@google.com> | 2019-12-18 11:56:27 -0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-01-16 21:50:13 +0000 |
commit | d57264e2872a5e54ae553c1c324ff3ef5b937263 (patch) | |
tree | 36f96860a65faf540dcde8838dbc1a2c5f805939 /board | |
parent | a5052d4e78d8d9d44506cb50b4cfd6ea08e4814d (diff) | |
download | chrome-ec-d57264e2872a5e54ae553c1c324ff3ef5b937263.tar.gz |
Trogdor: Restore and modify the custom USB PD policy
A USB PD policy refactoring (CL:1949052) moves logic to a common
place. It broke the Trogdor DP alt-mode, mostly due to the special
needs, like deferring setting the usb_mux until HPD goes high,
svdm_dp_attention() instead of svdm_dp_config(). The reason is
the AP only supports one DP phy. An external DP mux switches between
the two ports. Should switch those muxes when it is really used,
i.e. HPD high; otherwise, the real use case is preempted, like:
(1) plug a dongle without monitor connected to port-0,
(2) plug a dongle without monitor connected to port-1,
(3) plug a monitor to the port-1 dongle.
It is unlike other boards which have >=2 DP phy: the mux can be
turned on even if it is not used yet, done in svdm_dp_config().
So need to override the implementation of svdm_dp_config().
The common svdm_enter_dp_mode() disconnects the PPC SBU lines.
Need to reenable it on svdm_dp_attention().
Also add the logic to disconnect all muxes and deassert HPD on
svdm_exit_dp_mode().
BRANCH=None
BUG=b:143616352,chromium:1021724
TEST=Tested the DP alt-mode: plug a dongle without monitor connected
-> plug a monitor to it -> unplug the dongle.
Verified the muxes work as expected.
Change-Id: I6250555d61c44acaf74375ed9bd4a88b8dadc933
Signed-off-by: Wai-Hong Tam <waihong@google.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1974830
Reviewed-by: Aseda Aboagye <aaboagye@chromium.org>
Diffstat (limited to 'board')
-rw-r--r-- | board/trogdor/usb_pd_policy.c | 52 |
1 files changed, 51 insertions, 1 deletions
diff --git a/board/trogdor/usb_pd_policy.c b/board/trogdor/usb_pd_policy.c index e36f856acc..ce72340bd3 100644 --- a/board/trogdor/usb_pd_policy.c +++ b/board/trogdor/usb_pd_policy.c @@ -95,6 +95,32 @@ int pd_snk_is_vbus_provided(int port) /* ----------------- Vendor Defined Messages ------------------ */ #ifdef CONFIG_USB_PD_ALT_MODE_DFP +__override int svdm_dp_config(int port, uint32_t *payload) +{ + int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT); + uint8_t pin_mode = get_dp_pin_mode(port); + + if (!pin_mode) + return 0; + + /* + * Defer setting the usb_mux until HPD goes high, svdm_dp_attention(). + * The AP only supports one DP phy. An external DP mux switches between + * the two ports. Should switch those muxes when it is really used, + * i.e. HPD high; otherwise, the real use case is preempted, like: + * (1) plug a dongle without monitor connected to port-0, + * (2) plug a dongle without monitor connected to port-1, + * (3) plug a monitor to the port-1 dongle. + */ + + payload[0] = VDO(USB_SID_DISPLAYPORT, 1, + CMD_DP_CONFIG | VDO_OPOS(opos)); + payload[1] = VDO_DP_CFG(pin_mode, /* pin mode */ + 1, /* DPv1.3 signaling */ + 2); /* UFP connected */ + return 2; +}; + __override void svdm_dp_post_config(int port) { dp_flags[port] |= DP_FLAGS_DP_ON; @@ -142,15 +168,25 @@ __override int svdm_dp_attention(int port, uint32_t *payload) if (lvl) { if (is_dp_muxable(port)) { /* + * Enable and switch the DP port selection mux to the + * correct port. + * * TODO(waihong): Better to move switching DP mux to * the usb_mux abstraction. */ gpio_set_level(GPIO_DP_MUX_SEL, port == 1); gpio_set_level(GPIO_DP_MUX_OE_L, 0); + /* Connect the SBU lines in PPC chip. */ + if (IS_ENABLED(CONFIG_USBC_PPC_SBU)) + ppc_set_sbu(port, 1); + /* + * Connect the USB SS/DP lines in TCPC chip. + * * When mf_pref not true, still use the dock muxing - * because of the board USB-C topology. + * because of the board USB-C topology (limited to 2 + * lanes DP). */ usb_mux_set(port, TYPEC_MUX_DOCK, USB_SWITCH_CONNECT, pd_get_polarity(port)); @@ -160,7 +196,14 @@ __override int svdm_dp_attention(int port, uint32_t *payload) return 0; /* Nack */ } } else { + /* Disconnect the DP port selection mux. */ gpio_set_level(GPIO_DP_MUX_OE_L, 1); + + /* Disconnect the SBU lines in PPC chip. */ + if (IS_ENABLED(CONFIG_USBC_PPC_SBU)) + ppc_set_sbu(port, 0); + + /* Disconnect the DP but keep the USB SS lines in TCPC chip. */ usb_mux_set(port, TYPEC_MUX_USB, USB_SWITCH_CONNECT, pd_get_polarity(port)); } @@ -210,7 +253,14 @@ __override void svdm_exit_dp_mode(int port) { const struct usb_mux *mux = &usb_muxes[port]; + /* Disconnect the DP port selection mux. */ + gpio_set_level(GPIO_DP_MUX_OE_L, 1); + + /* Below svdm_safe_dp_mode() will disconnect SBU and DP/USB SS lines. */ svdm_safe_dp_mode(port); + + /* Signal AP for the HPD low event */ mux->hpd_update(port, 0, 0); + gpio_set_level(GPIO_DP_HOT_PLUG_DET, 0); } #endif /* CONFIG_USB_PD_ALT_MODE_DFP */ |