diff options
author | Vijay Hiremath <vijay.p.hiremath@intel.com> | 2020-01-08 18:44:13 -0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-01-09 23:54:49 +0000 |
commit | f5e5148447da0df764dc330b05a5267f968c98c2 (patch) | |
tree | 2a39b6c98f5bdac4158aafdac45be9a1096cf63d /driver | |
parent | 35b85ea8dbd0ab0620f8c2b0218b835a911dc68c (diff) | |
download | chrome-ec-f5e5148447da0df764dc330b05a5267f968c98c2.tar.gz |
USB_MUX: correct setting the retimer data
Modified the USB MUX common driver to correctly configure the
retimer data based on the current USB MUX info.
BUG=b:145943811
BRANCH=none
TEST=DP works on Volteer
Change-Id: I5f37bcc0647f07b94fd9ee33913610cf6ae70c80
Signed-off-by: Vijay Hiremath <vijay.p.hiremath@intel.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1992842
Tested-by: Denis Brockus <dbrockus@chromium.org>
Reviewed-by: Denis Brockus <dbrockus@chromium.org>
Diffstat (limited to 'driver')
-rw-r--r-- | driver/usb_mux/usb_mux.c | 208 |
1 files changed, 118 insertions, 90 deletions
diff --git a/driver/usb_mux/usb_mux.c b/driver/usb_mux/usb_mux.c index 7fc4934001..e7849738bb 100644 --- a/driver/usb_mux/usb_mux.c +++ b/driver/usb_mux/usb_mux.c @@ -25,12 +25,98 @@ static uint8_t flags[CONFIG_USB_PD_PORT_MAX_COUNT]; #define USB_MUX_FLAG_IN_LPM BIT(0) /* Device is in low power mode. */ +enum mux_config_type { + USB_MUX_INIT, + USB_MUX_LOW_POWER, + USB_MUX_SET_MODE, + USB_MUX_GET_MODE, +}; + +/* Configure the retimer */ +static int configure_retimer(int port, enum mux_config_type config, + mux_state_t mux_state) +{ + int res = 0; -static void enter_low_power_mode(int port) + if (IS_ENABLED(CONFIG_USBC_MUX_RETIMER)) { + const struct usb_retimer *retimer = &usb_retimers[port]; + + if (!retimer->driver) + return 0; + + switch (config) { + case USB_MUX_INIT: + if (retimer->driver->init) + res = retimer->driver->init(port); + break; + case USB_MUX_LOW_POWER: + if (retimer->driver->enter_low_power_mode) + res = retimer->driver->enter_low_power_mode( + port); + break; + case USB_MUX_SET_MODE: + if (retimer->driver->set) + res = retimer->driver->set(port, mux_state); + break; + default: + break; + } + } + + return res; +} + +/* Configure the MUX */ +static int configure_mux(int port, enum mux_config_type config, + mux_state_t *mux_state) { const struct usb_mux *mux = &usb_muxes[port]; int res; + switch (config) { + case USB_MUX_INIT: + res = mux->driver->init(port); + if (res) + break; + + res = configure_retimer(port, config, USB_PD_MUX_NONE); + if (res) + break; + + /* Apply board specific initialization */ + if (mux->board_init) + res = mux->board_init(port); + + break; + case USB_MUX_LOW_POWER: + if (mux->driver->enter_low_power_mode) { + res = mux->driver->enter_low_power_mode(port); + if (res) + break; + } + res = configure_retimer(port, config, USB_PD_MUX_NONE); + break; + case USB_MUX_SET_MODE: + res = mux->driver->set(port, *mux_state); + if (res) + break; + res = configure_retimer(port, config, *mux_state); + break; + case USB_MUX_GET_MODE: + res = mux->driver->get(port, mux_state); + break; + } + + if (res) + CPRINTS("mux config:%d, port:%d, res:%d", config, port, res); + + return res; +} + +static void enter_low_power_mode(int port) +{ + mux_state_t mux_state = USB_PD_MUX_NONE; + /* * Set LPM flag regardless of method presence or method failure. We want * know know that we tried to put the device in low power mode so we can @@ -39,27 +125,7 @@ static void enter_low_power_mode(int port) flags[port] |= USB_MUX_FLAG_IN_LPM; /* Apply any low power customization if present */ - if (mux->driver->enter_low_power_mode) { - res = mux->driver->enter_low_power_mode(port); - if (res) { - CPRINTS("Err: %s mux port(%d): %d", - __func__, port, res); - return; - } - } - - if (IS_ENABLED(CONFIG_USBC_MUX_RETIMER)) { - const struct usb_retimer *retimer = &usb_retimers[port]; - - if (retimer->driver && retimer->driver->enter_low_power_mode) { - res = retimer->driver->enter_low_power_mode(port); - if (res) { - CPRINTS("Err: %s retimer port(%d): %d", - __func__, port, res); - return; - } - } - } + configure_mux(port, USB_MUX_LOW_POWER, &mux_state); } static inline void exit_low_power_mode(int port) @@ -71,40 +137,14 @@ static inline void exit_low_power_mode(int port) void usb_mux_init(int port) { - const struct usb_mux *mux = &usb_muxes[port]; - int res; + mux_state_t mux_state = USB_PD_MUX_NONE; ASSERT(port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); - res = mux->driver->init(port); - if (res) { - CPRINTS("Err: init mux port(%d): %d", port, res); - return; - } - - if (IS_ENABLED(CONFIG_USBC_MUX_RETIMER)) { - const struct usb_retimer *retimer = &usb_retimers[port]; - - if (retimer->driver && retimer->driver->init) { - res = retimer->driver->init(port); - if (res) { - CPRINTS("Err: init retimer port(%d): %d", - port, res); - return; - } - } - } + configure_mux(port, USB_MUX_INIT, &mux_state); /* Device is always out of LPM after initialization. */ flags[port] &= ~USB_MUX_FLAG_IN_LPM; - - /* Apply board specific initialization */ - if (mux->board_init) { - res = mux->board_init(port); - - if (res) - CPRINTS("Err: board_init mux port(%d): %d", port, res); - } } /* @@ -114,8 +154,6 @@ void usb_mux_init(int port) void usb_mux_set(int port, enum typec_mux mux_mode, enum usb_switch usb_mode, int polarity) { - const struct usb_mux *mux = &usb_muxes[port]; - int res; mux_state_t mux_state; const int should_enter_low_power_mode = mux_mode == TYPEC_MUX_NONE && usb_mode == USB_SWITCH_DISCONNECT; @@ -139,24 +177,8 @@ void usb_mux_set(int port, enum typec_mux mux_mode, ? mux_mode | MUX_POLARITY_INVERTED : mux_mode; - res = mux->driver->set(port, mux_state); - if (res) { - CPRINTS("Err: set mux port(%d): %d", port, res); + if (configure_mux(port, USB_MUX_SET_MODE, &mux_state)) return; - } - - if (IS_ENABLED(CONFIG_USBC_MUX_RETIMER)) { - const struct usb_retimer *retimer = &usb_retimers[port]; - - if (retimer->driver && retimer->driver->set) { - res = retimer->driver->set(port, mux_state); - if (res) { - CPRINTS("Err: set retimer port(%d): %d", - port, res); - return; - } - } - } if (enable_debug_prints) CPRINTS( @@ -173,43 +195,46 @@ void usb_mux_set(int port, enum typec_mux mux_mode, mux_state_t usb_mux_get(int port) { - const struct usb_mux *mux = &usb_muxes[port]; - int res; mux_state_t mux_state; exit_low_power_mode(port); - res = mux->driver->get(port, &mux_state); - if (res) { - CPRINTS("Err: get mux port(%d): %d", port, res); - return 0; - } + if (configure_mux(port, USB_MUX_GET_MODE, &mux_state)) + return USB_PD_MUX_NONE; return mux_state; } void usb_mux_flip(int port) { - const struct usb_mux *mux = &usb_muxes[port]; - int res; mux_state_t mux_state; exit_low_power_mode(port); - res = mux->driver->get(port, &mux_state); - if (res) { - CPRINTS("Err: get mux port(%d): %d", port, res); + if (configure_mux(port, USB_MUX_GET_MODE, &mux_state)) return; - } if (mux_state & MUX_POLARITY_INVERTED) mux_state &= ~MUX_POLARITY_INVERTED; else mux_state |= MUX_POLARITY_INVERTED; - res = mux->driver->set(port, mux_state); - if (res) - CPRINTS("Err: set mux port(%d): %d", port, res); + configure_mux(port, USB_MUX_SET_MODE, &mux_state); +} + +void usb_mux_hpd_update(int port, int hpd_lvl, int hpd_irq) +{ + const struct usb_mux *mux = &usb_muxes[port]; + mux_state_t mux_state; + + if (mux->hpd_update) + mux->hpd_update(port, hpd_lvl, hpd_irq); + + if (!configure_mux(port, USB_MUX_GET_MODE, &mux_state)) { + mux_state |= (hpd_lvl ? USB_PD_MUX_HPD_LVL : 0) | + (hpd_irq ? USB_PD_MUX_HPD_IRQ : 0); + configure_retimer(port, USB_MUX_SET_MODE, mux_state); + } } #ifdef CONFIG_CMD_TYPEC @@ -270,20 +295,23 @@ static enum ec_status hc_usb_pd_mux_info(struct host_cmd_handler_args *args) const struct ec_params_usb_pd_mux_info *p = args->params; struct ec_response_usb_pd_mux_info *r = args->response; int port = p->port; - const struct usb_mux *mux; + const struct usb_mux *mux = &usb_muxes[port]; + mux_state_t mux_state; if (port >= board_get_usb_pd_port_count()) return EC_RES_INVALID_PARAM; - mux = &usb_muxes[port]; - if (mux->driver->get(port, &r->flags) != EC_SUCCESS) + if (configure_mux(port, USB_MUX_GET_MODE, &mux_state)) return EC_RES_ERROR; + r->flags = mux_state; + /* 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) && - (mux->hpd_update == &virtual_hpd_update)) - mux->hpd_update(port, r->flags & USB_PD_MUX_HPD_LVL, 0); + (mux->hpd_update == &virtual_hpd_update)) { + usb_mux_hpd_update(port, r->flags & USB_PD_MUX_HPD_LVL, 0); + } args->response_size = sizeof(*r); return EC_RES_SUCCESS; |