summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMadhusudanarao Amara <madhusudanarao.amara@intel.corp-partner.google.com>2021-01-15 22:21:15 +0530
committerCommit Bot <commit-bot@chromium.org>2021-01-26 00:02:01 +0000
commitaffbf150d56d16cbb881e239b78a38512152e777 (patch)
tree9dd274dbc855cdd6cef8b6a2a9a62f3d2327fded
parent7ebc7659f157e2dc787660773bf12b5641993c6b (diff)
downloadchrome-ec-affbf150d56d16cbb881e239b78a38512152e777.tar.gz
usb_mux: Send missed disconnect mode in S3/S0ix
If the Type-C devices are connected in S0 and when DUT enters S3/S0ix, if the type-C devices are disconnected and re-connected, Kernel won't receive the disconnected state from EC once DUT boots to S0 as EC moves on and updates the new connected state to Kernel Mux driver. This leads to failure of Type-C device detection on resuming to S0 from S3/S0iX. To overcome this scenario, adding an explicit condition to send previous disconnect state to Kernel Mux driver once initial mux request is received upon resuming from S3/S0iX. Missing Disconnect mode Patch Details: Set disconnect latch flag for the init and disconnect requests For AP to EC PD command: EC_CMD_USB_PD_CONTROL -Check disconnect latch flag if it is true set pd.enabled = 0 For AP to EC mux command: EC_CMD_USB_PD_MUX_INFO -Check the disconnect latch flag if it is true then send disconnect mode -Reset the disconnect latch flag -Send host event EC_HOST_EVENT_USB_MUX for configuring the virtual mux with the latest Mux configuration BUG=b:176604380 BRANCH=None TEST=Type C devices in s0ix disconnect/connect or swapping across the ports scenarios tested Change-Id: Ic38d3632cb0fadb29393405e13ed3606a740c81e Signed-off-by: Madhusudanarao Amara <madhusudanarao.amara@intel.corp-partner.google.com> Signed-off-by: Ayushee Shah <ayushee.shah@intel.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2632551 Reviewed-by: Keith Short <keithshort@chromium.org> Commit-Queue: Keith Short <keithshort@chromium.org>
-rw-r--r--common/usb_pd_host_cmd.c23
-rw-r--r--driver/usb_mux/usb_mux.c53
-rw-r--r--include/usb_mux.h18
3 files changed, 86 insertions, 8 deletions
diff --git a/common/usb_pd_host_cmd.c b/common/usb_pd_host_cmd.c
index c08332621b..7cb620c7ed 100644
--- a/common/usb_pd_host_cmd.c
+++ b/common/usb_pd_host_cmd.c
@@ -351,13 +351,22 @@ static enum ec_status hc_usb_pd_control(struct host_cmd_handler_args *args)
break;
case 1:
case 2:
- r_v2->enabled =
- (pd_comm_is_enabled(p->port) ?
- PD_CTRL_RESP_ENABLED_COMMS : 0) |
- (pd_is_connected(p->port) ?
- PD_CTRL_RESP_ENABLED_CONNECTED : 0) |
- (pd_capable(p->port) ?
- PD_CTRL_RESP_ENABLED_PD_CAPABLE : 0);
+ /*
+ * Set enabled to 0 if disconnect latch flag=true, needed this
+ * to configure Virtual mux in disconnect mode.
+ */
+ if (IS_ENABLED(CONFIG_USB_MUX_VIRTUAL) &&
+ usb_mux_get_disconnect_latch_flag(p->port)) {
+ r_v2->enabled = 0;
+ } else {
+ r_v2->enabled =
+ (pd_comm_is_enabled(p->port) ?
+ PD_CTRL_RESP_ENABLED_COMMS : 0) |
+ (pd_is_connected(p->port) ?
+ PD_CTRL_RESP_ENABLED_CONNECTED : 0) |
+ (pd_capable(p->port) ?
+ PD_CTRL_RESP_ENABLED_PD_CAPABLE : 0);
+ }
r_v2->role = pd_get_role_flags(p->port);
r_v2->polarity = pd_get_polarity(p->port);
diff --git a/driver/usb_mux/usb_mux.c b/driver/usb_mux/usb_mux.c
index 22be81843d..743b9a6203 100644
--- a/driver/usb_mux/usb_mux.c
+++ b/driver/usb_mux/usb_mux.c
@@ -31,7 +31,11 @@ static int enable_debug_prints;
*/
static uint32_t flags[CONFIG_USB_PD_PORT_MAX_COUNT];
-#define USB_MUX_FLAG_IN_LPM BIT(0) /* Device is in low power mode. */
+/* Device is in low power mode. */
+#define USB_MUX_FLAG_IN_LPM BIT(0)
+
+/* The following bit is used to configure virtual mux in disconnect mode */
+#define USB_MUX_FLAG_DISCONNECT_LATCH BIT(1)
enum mux_config_type {
USB_MUX_INIT,
@@ -58,6 +62,11 @@ static int configure_mux(int port,
*mux_state = USB_PD_MUX_NONE;
}
+ if ((config == USB_MUX_SET_MODE && *mux_state == USB_PD_MUX_NONE) ||
+ config == USB_MUX_INIT) {
+ usb_mux_set_disconnect_latch_flag(port, true);
+ }
+
/*
* a MUX for a particular port can be a linked list chain of
* MUXes. So when we change one, we traverse the whole list
@@ -247,6 +256,35 @@ mux_state_t usb_mux_get(int port)
return rv ? USB_PD_MUX_NONE : mux_state;
}
+/* Get USB MUX (virtual MUX) disconnect flag */
+bool usb_mux_get_disconnect_latch_flag(int port)
+{
+ bool rv = false;
+
+ if (port >= board_get_usb_pd_port_count())
+ return rv;
+
+ if (!IS_ENABLED(CONFIG_USB_MUX_VIRTUAL))
+ return rv;
+
+ return !!(flags[port] & USB_MUX_FLAG_DISCONNECT_LATCH);
+}
+
+/* Set USB MUX (virtual MUX) disconnect flag */
+void usb_mux_set_disconnect_latch_flag(int port, bool enable)
+{
+ if (port >= board_get_usb_pd_port_count())
+ return;
+
+ if (!IS_ENABLED(CONFIG_USB_MUX_VIRTUAL))
+ return;
+
+ if (enable)
+ atomic_or(&flags[port], USB_MUX_FLAG_DISCONNECT_LATCH);
+ else
+ atomic_clear_bits(&flags[port], USB_MUX_FLAG_DISCONNECT_LATCH);
+}
+
void usb_mux_flip(int port)
{
mux_state_t mux_state;
@@ -366,6 +404,19 @@ static enum ec_status hc_usb_pd_mux_info(struct host_cmd_handler_args *args)
r->flags = mux_state;
+ /*
+ * Force disconnect mode if disconnect latch flag is set.
+ * Send host event for configuring the latest mux state
+ */
+ if (IS_ENABLED(CONFIG_USB_MUX_VIRTUAL) &&
+ usb_mux_get_disconnect_latch_flag(port)) {
+ r->flags = USB_PD_MUX_NONE;
+ usb_mux_set_disconnect_latch_flag(port, false);
+ args->response_size = sizeof(*r);
+ host_set_single_event(EC_HOST_EVENT_USB_MUX);
+ return EC_RES_SUCCESS;
+ }
+
/* Clear HPD IRQ event since we're about to inform host of it. */
if (IS_ENABLED(CONFIG_USB_MUX_VIRTUAL) &&
(r->flags & USB_PD_MUX_HPD_IRQ)) {
diff --git a/include/usb_mux.h b/include/usb_mux.h
index 251ae9d6ec..5ce198c73d 100644
--- a/include/usb_mux.h
+++ b/include/usb_mux.h
@@ -240,4 +240,22 @@ void usb_mux_flip(int port);
*/
void usb_mux_hpd_update(int port, int hpd_lvl, int hpd_irq);
+/**
+ * Get the disconnect latch flag so that the Kernel Mux driver doesn't
+ * miss the unnoticed disconnection status.
+ *
+ * @param port port number.
+ * @return status of disconnect latch flag
+ */
+bool usb_mux_get_disconnect_latch_flag(int port);
+
+/**
+ * Set the disconnect latch flag if the Type-C devices are disconnected and
+ * the information is not yet updated to Kernel Mux driver.
+ *
+ * @param port port number
+ * @param enable whether to enable or disable the disconnect latch flag
+ */
+void usb_mux_set_disconnect_latch_flag(int port, bool enable);
+
#endif