summaryrefslogtreecommitdiff
path: root/driver/usb_mux
diff options
context:
space:
mode:
authorDivya Sasidharan <divya.s.sasidharan@intel.com>2020-10-28 16:11:55 -0700
committerCommit Bot <commit-bot@chromium.org>2020-12-15 22:00:42 +0000
commit5316af00b3389dd9f1da04ce2c9bfe0a504e2d91 (patch)
tree821058f22b78f882dc28dc3f00578e75155846a8 /driver/usb_mux
parent49a18c25f8351d232a0065c67297a954caee8414 (diff)
downloadchrome-ec-5316af00b3389dd9f1da04ce2c9bfe0a504e2d91.tar.gz
virtual mux: Wait for mux config ACK from the kernel
This CL: 1. Add a new config CONFIG_USB_MUX_AP_ACK_REQUEST to enable request for ACK from AP 1. Adds a new feature flag to inform the AP that an ACK is needed for boards supporting Burnside bridge retimer. 2. Adds a new host command for the EC to wait for mux config ACK for entering and exiting the safe mode. 3. Adds 12.5msec delay after configuring retimer and SoC as recommended. BUG=b:166300460,b:161327513 BRANCH=none TEST=Verify Type-C dock is functional with multiple hotplugs and flipped orientation. Verify USB3.0 is detected and not downgraded. Verify no regression with TBT3 and USB4 dock. Cq-Depend: chromium:2530517 Change-Id: I5b8224648f0fc36b30e24ca3e7254d708c676149 Signed-off-by: Divya Sasidharan <divya.s.sasidharan@intel.com> Signed-off-by: Ayushee Shah <ayushee.shah@intel.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2366127 Commit-Queue: YH Lin <yueherngl@chromium.org> Commit-Queue: Abe Levkoy <alevkoy@chromium.org> Reviewed-by: Abe Levkoy <alevkoy@chromium.org>
Diffstat (limited to 'driver/usb_mux')
-rw-r--r--driver/usb_mux/usb_mux.c16
-rw-r--r--driver/usb_mux/virtual.c35
2 files changed, 49 insertions, 2 deletions
diff --git a/driver/usb_mux/usb_mux.c b/driver/usb_mux/usb_mux.c
index e311faf26a..246d6acff0 100644
--- a/driver/usb_mux/usb_mux.c
+++ b/driver/usb_mux/usb_mux.c
@@ -9,6 +9,7 @@
#include "console.h"
#include "hooks.h"
#include "host_command.h"
+#include "task.h"
#include "usb_mux.h"
#include "usbc_ppc.h"
#include "util.h"
@@ -388,3 +389,18 @@ static enum ec_status hc_usb_pd_mux_info(struct host_cmd_handler_args *args)
DECLARE_HOST_COMMAND(EC_CMD_USB_PD_MUX_INFO,
hc_usb_pd_mux_info,
EC_VER_MASK(0));
+
+static enum ec_status hc_usb_pd_mux_ack(struct host_cmd_handler_args *args)
+{
+ __maybe_unused const struct ec_params_usb_pd_mux_ack *p = args->params;
+
+ if (!IS_ENABLED(CONFIG_USB_MUX_AP_ACK_REQUEST))
+ return EC_RES_INVALID_COMMAND;
+
+ task_set_event(PD_PORT_TO_TASK_ID(p->port), PD_EVENT_AP_MUX_DONE);
+
+ return EC_RES_SUCCESS;
+}
+DECLARE_HOST_COMMAND(EC_CMD_USB_PD_MUX_ACK,
+ hc_usb_pd_mux_ack,
+ EC_VER_MASK(0));
diff --git a/driver/usb_mux/virtual.c b/driver/usb_mux/virtual.c
index 02564edc95..c424c14303 100644
--- a/driver/usb_mux/virtual.c
+++ b/driver/usb_mux/virtual.c
@@ -8,6 +8,8 @@
#include "common.h"
#include "console.h"
#include "host_command.h"
+#include "task.h"
+#include "timer.h"
#include "usb_mux.h"
#include "util.h"
@@ -26,10 +28,39 @@ static mux_state_t virtual_mux_state[CONFIG_USB_PD_PORT_MAX_COUNT];
static inline void virtual_mux_update_state(int port, mux_state_t mux_state)
{
+ mux_state_t previous_mux_state = virtual_mux_state[port];
+
virtual_mux_state[port] = mux_state;
-#ifdef CONFIG_HOSTCMD_EVENTS
+
+ if (!IS_ENABLED(CONFIG_HOSTCMD_EVENTS))
+ return;
+
host_set_single_event(EC_HOST_EVENT_USB_MUX);
-#endif
+
+ if (!IS_ENABLED(CONFIG_USB_MUX_AP_ACK_REQUEST))
+ return;
+
+ /* This should only be called from the PD task */
+ assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
+
+ /*
+ * EC waits for the ACK from kernel indicating that TCSS Mux
+ * configuration is completed. This mechanism is implemented for
+ * entering and exiting the safe mode. This is needed to remove
+ * timing senstivity between BB retimer and TCSS Mux to allow better
+ * synchronization between them and thereby remain in the same state
+ * for achieving proper safe state terminations.
+ *
+ * Note: While the EC waits for the ACK, the value of usb_mux_get
+ * won't match the most recently set value with usb_mux_set.
+ */
+ if ((!(previous_mux_state & USB_PD_MUX_SAFE_MODE) &&
+ (mux_state & USB_PD_MUX_SAFE_MODE)) ||
+ ((previous_mux_state & USB_PD_MUX_SAFE_MODE) &&
+ !(mux_state & USB_PD_MUX_SAFE_MODE))) {
+ task_wait_event_mask(PD_EVENT_AP_MUX_DONE, 100*MSEC);
+ usleep(12.5 * MSEC);
+ }
}
static int virtual_init(const struct usb_mux *me)