summaryrefslogtreecommitdiff
path: root/driver
diff options
context:
space:
mode:
authorCaveh Jalali <caveh@chromium.org>2022-09-21 18:10:28 -0700
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-10-04 20:53:06 +0000
commit46e51dc78601066da3dfc91e8dc6fceb0e3ab88e (patch)
treef7f624950bddeb937ceef7e7bfc460d54483c8ba /driver
parentf079a846def4856bb955d3b038171ff44d4887bb (diff)
downloadchrome-ec-46e51dc78601066da3dfc91e8dc6fceb0e3ab88e.tar.gz
usb_mux: Add support for idling USB muxes
This adds support for putting USB muxes in a non-active mode on chipset suspend (S0ix, S3). Some USB muxes consume a significant amount of power when the AP goes into suspend mode which has prompted some board support files to explicitly power down the USB3 portion of the Burnside Bridge. So, add a more general interface for notifying mux chip drivers about AP power state changes. This interface is optional and only kicks in for mux drivers that implement the new .set_idle_mode() method and the board's mux config specifies USB_MUX_FLAG_CAN_IDLE in usb_mux.flags. If a port is already considered to be in low power mode, no actions are taken on chipset suspend/resume. USB_MUX_FLAG_CAN_IDLE is intended to give boards full control over enabling this feature for each mux chip. This feature flag is disabled by default. BRANCH=none BUG=b:245753005 TEST='make buildall' passes './twister -v -T zephyr/test' passes Signed-off-by: Caveh Jalali <caveh@chromium.org> Change-Id: I93eda041e816398806eb29eb0625cca97c69c2ac Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3914992 Reviewed-by: Boris Mittelberg <bmbm@google.com> Code-Coverage: Zoss <zoss-cl-coverage@prod.google.com> Reviewed-by: Diana Z <dzigterman@chromium.org>
Diffstat (limited to 'driver')
-rw-r--r--driver/usb_mux/usb_mux.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/driver/usb_mux/usb_mux.c b/driver/usb_mux/usb_mux.c
index 1edcf25179..edc9da5778 100644
--- a/driver/usb_mux/usb_mux.c
+++ b/driver/usb_mux/usb_mux.c
@@ -59,6 +59,8 @@ enum mux_config_type {
USB_MUX_LOW_POWER,
USB_MUX_SET_MODE,
USB_MUX_GET_MODE,
+ USB_MUX_CHIPSET_IDLE,
+ USB_MUX_CHIPSET_ACTIVE,
USB_MUX_CHIPSET_RESET,
USB_MUX_HPD_UPDATE,
};
@@ -306,6 +308,20 @@ static int configure_mux(int port, int index, enum mux_config_type config,
break;
+ case USB_MUX_CHIPSET_IDLE:
+ if ((mux_ptr->flags & USB_MUX_FLAG_CAN_IDLE) && drv &&
+ drv->set_idle_mode)
+ rv = drv->set_idle_mode(mux_ptr, true);
+
+ break;
+
+ case USB_MUX_CHIPSET_ACTIVE:
+ if ((mux_ptr->flags & USB_MUX_FLAG_CAN_IDLE) && drv &&
+ drv->set_idle_mode)
+ rv = drv->set_idle_mode(mux_ptr, false);
+
+ break;
+
case USB_MUX_CHIPSET_RESET:
if (drv && drv->chipset_reset)
rv = drv->chipset_reset(mux_ptr);
@@ -689,6 +705,34 @@ static void mux_chipset_reset(void)
}
DECLARE_HOOK(HOOK_CHIPSET_RESET, mux_chipset_reset, HOOK_PRIO_DEFAULT);
+static void mux_chipset_suspend(void)
+{
+ int port;
+
+ for (port = 0; port < board_get_usb_pd_port_count(); ++port) {
+ if (flags[port] & USB_MUX_FLAG_IN_LPM)
+ continue;
+
+ configure_mux(port, TYPEC_USB_MUX_SET_ALL_CHIPS,
+ USB_MUX_CHIPSET_IDLE, NULL);
+ }
+}
+DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, mux_chipset_suspend, HOOK_PRIO_DEFAULT);
+
+static void mux_chipset_resume(void)
+{
+ int port;
+
+ for (port = 0; port < board_get_usb_pd_port_count(); ++port) {
+ if (flags[port] & USB_MUX_FLAG_IN_LPM)
+ continue;
+
+ configure_mux(port, TYPEC_USB_MUX_SET_ALL_CHIPS,
+ USB_MUX_CHIPSET_ACTIVE, NULL);
+ }
+}
+DECLARE_HOOK(HOOK_CHIPSET_RESUME, mux_chipset_resume, HOOK_PRIO_DEFAULT);
+
/*
* For muxes which have powered off in G3, clear any cached INIT and LPM flags
* since the chip will need reset.