summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--driver/usb_mux.c2
-rw-r--r--driver/usb_mux_virtual.c38
-rw-r--r--include/ec_commands.h9
3 files changed, 35 insertions, 14 deletions
diff --git a/driver/usb_mux.c b/driver/usb_mux.c
index f1b687e24a..5ef11d7ac1 100644
--- a/driver/usb_mux.c
+++ b/driver/usb_mux.c
@@ -244,7 +244,7 @@ static int hc_usb_pd_mux_info(struct host_cmd_handler_args *args)
/* Clear HPD IRQ event since we're about to inform host of it. */
if ((r->flags & USB_PD_MUX_HPD_IRQ) &&
mux->hpd_update == &virtual_hpd_update)
- mux->hpd_update(port, 0, 0);
+ mux->hpd_update(port, r->flags & USB_PD_MUX_HPD_LVL, 0);
#endif
args->response_size = sizeof(*r);
diff --git a/driver/usb_mux_virtual.c b/driver/usb_mux_virtual.c
index 433c5bcdbe..b82cdf307a 100644
--- a/driver/usb_mux_virtual.c
+++ b/driver/usb_mux_virtual.c
@@ -11,8 +11,24 @@
#include "usb_mux.h"
#include "util.h"
+/*
+ * USB PD protocol configures the USB & DP mux state and USB PD policy
+ * configures the HPD mux state. Both states are independent of each other
+ * may differ when the PD role changes when in dock mode.
+ */
+#define USB_PD_MUX_HPD_STATE (USB_PD_MUX_HPD_LVL | USB_PD_MUX_HPD_IRQ)
+#define USB_PD_MUX_USB_DP_STATE (USB_PD_MUX_USB_ENABLED | \
+ USB_PD_MUX_DP_ENABLED | USB_PD_MUX_POLARITY_INVERTED)
+
static mux_state_t virtual_mux_state[CONFIG_USB_PD_PORT_COUNT];
-static int hpd_irq_state[CONFIG_USB_PD_PORT_COUNT];
+
+static inline void virtual_mux_update_state(int port, mux_state_t mux_state)
+{
+ if (virtual_mux_state[port] != mux_state) {
+ virtual_mux_state[port] = mux_state;
+ host_set_single_event(EC_HOST_EVENT_USB_MUX);
+ }
+}
static int virtual_init(int port)
{
@@ -25,10 +41,12 @@ static int virtual_init(int port)
*/
static int virtual_set_mux(int port, mux_state_t mux_state)
{
- if (virtual_mux_state[port] != mux_state) {
- virtual_mux_state[port] = mux_state;
- host_set_single_event(EC_HOST_EVENT_USB_MUX);
- }
+ /* Current USB & DP mux status + existing HPD related mux status */
+ mux_state_t new_mux_state = (mux_state & ~USB_PD_MUX_HPD_STATE) |
+ (virtual_mux_state[port] & USB_PD_MUX_HPD_STATE);
+
+ virtual_mux_update_state(port, new_mux_state);
+
return EC_SUCCESS;
}
@@ -40,16 +58,18 @@ static int virtual_set_mux(int port, mux_state_t mux_state)
static int virtual_get_mux(int port, mux_state_t *mux_state)
{
*mux_state = virtual_mux_state[port];
- *mux_state |= hpd_irq_state[port] ? USB_PD_MUX_HPD_IRQ : 0;
return EC_SUCCESS;
}
void virtual_hpd_update(int port, int hpd_lvl, int hpd_irq)
{
- hpd_irq_state[port] = hpd_irq;
- if (hpd_irq)
- host_set_single_event(EC_HOST_EVENT_USB_MUX);
+ /* Current HPD related mux status + existing USB & DP mux status */
+ mux_state_t new_mux_state = (hpd_lvl ? USB_PD_MUX_HPD_LVL : 0) |
+ (hpd_irq ? USB_PD_MUX_HPD_IRQ : 0) |
+ (virtual_mux_state[port] & USB_PD_MUX_USB_DP_STATE);
+
+ virtual_mux_update_state(port, new_mux_state);
}
const struct usb_mux_driver virtual_usb_mux_driver = {
diff --git a/include/ec_commands.h b/include/ec_commands.h
index 45198db0dc..82e1dab1a6 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -4925,10 +4925,11 @@ struct ec_params_usb_pd_mux_info {
} __ec_align1;
/* Flags representing mux state */
-#define USB_PD_MUX_USB_ENABLED (1 << 0)
-#define USB_PD_MUX_DP_ENABLED (1 << 1)
-#define USB_PD_MUX_POLARITY_INVERTED (1 << 2)
-#define USB_PD_MUX_HPD_IRQ (1 << 3)
+#define USB_PD_MUX_USB_ENABLED (1 << 0) /* USB connected */
+#define USB_PD_MUX_DP_ENABLED (1 << 1) /* DP connected */
+#define USB_PD_MUX_POLARITY_INVERTED (1 << 2) /* CC line Polarity inverted */
+#define USB_PD_MUX_HPD_IRQ (1 << 3) /* HPD IRQ is asserted */
+#define USB_PD_MUX_HPD_LVL (1 << 4) /* HPD level is asserted */
struct ec_response_usb_pd_mux_info {
uint8_t flags; /* USB_PD_MUX_*-encoded USB mux state */