diff options
-rw-r--r-- | driver/usb_mux.c | 2 | ||||
-rw-r--r-- | driver/usb_mux_virtual.c | 38 | ||||
-rw-r--r-- | include/ec_commands.h | 9 |
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 */ |