summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Feng <li1.feng@intel.com>2022-05-06 13:59:32 -0700
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-07-27 18:19:05 +0000
commiteed55e6c19c2f957aa2b36369bbfbfbdf4364a03 (patch)
tree0b5c090b8ff1fe974f2c9b8390254e021e27f572
parent33e5ebfbe3bb4f49bc44e18769e09e3aced91dbd (diff)
downloadchrome-ec-eed55e6c19c2f957aa2b36369bbfbfbdf4364a03.tar.gz
retimer: resume PD port if system shutdown unexpectly
During NDA PD port retimer firmware update, PD port is suspended; at this moment, user may press power button to shut down system. PD task is kept in suspended state; system will not respond if plug in PD charger or TBT device to this port. Even when system powers up after this, this PD port is in suspended state unless it's being resumed explicitly. For any reason the system is shut down during retimer firmware update, this scenario will happen. This CL adds the tracking of port state. Upon AP shudown, if the port is suspended by retimer update, then restore the port by setting it resumed. BUG=b:223468686 BRANCH=none TEST=On Redrix, OS 14580 with fwupd retimer firmware update enabled, Port 0 and port 1 no device attached, boot up system to OS, when retimer firmware update starts, click "shut down" on screen. Wait a short time, plug in PD charger to port 0, then port 1, charger LED is on. Confirm on EC console with "chgstate", also PD task is enabled. Signed-off-by: Li Feng <li1.feng@intel.com> Change-Id: I74d0d17fc05063ba0ac0e33a4c0b6faa67d59d0e Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3631424 Reviewed-by: Abe Levkoy <alevkoy@chromium.org> Reviewed-by: Scott Chao <scott_chao@wistron.corp-partner.google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3788140 Commit-Queue: YH Lin <yueherngl@chromium.org> Reviewed-by: YH Lin <yueherngl@chromium.org>
-rw-r--r--common/usbc/usb_retimer_fw_update.c48
1 files changed, 46 insertions, 2 deletions
diff --git a/common/usbc/usb_retimer_fw_update.c b/common/usbc/usb_retimer_fw_update.c
index 1ff198c78f..4d56fd1969 100644
--- a/common/usbc/usb_retimer_fw_update.c
+++ b/common/usbc/usb_retimer_fw_update.c
@@ -53,6 +53,8 @@ static int cur_port;
static int last_op; /* Operation received from AP via ACPI_WRITE */
/* Operation result returned to ACPI_READ */
static int last_result;
+/* Track port state: SUSPEND or RESUME */
+static int port_state[CONFIG_USB_PD_PORT_MAX_COUNT];
int usb_retimer_fw_update_get_result(void)
{
@@ -85,9 +87,35 @@ int usb_retimer_fw_update_get_result(void)
return result;
}
+static void retimer_fw_update_set_port_state(int port, int state)
+{
+ port_state[port] = state;
+}
+
+static int retimer_fw_update_get_port_state(int port)
+{
+ return port_state[port];
+}
+
+/**
+ * @brief Suspend or resume PD task and update the state of the port.
+ *
+ * @param port PD port
+ * @param state
+ * SUSPEND: suspend PD task for firmware update; and set state to SUSPEND
+ * RESUME: resume PD task after firmware update is done; and set state
+ * to RESUME.
+ *
+ */
+static void retimer_fw_update_port_handler(int port, int state)
+{
+ pd_set_suspend(port, state);
+ retimer_fw_update_set_port_state(port, state);
+}
+
static void deferred_pd_suspend(void)
{
- pd_set_suspend(cur_port, SUSPEND);
+ retimer_fw_update_port_handler(cur_port, SUSPEND);
}
DECLARE_DEFERRED(deferred_pd_suspend);
@@ -120,7 +148,7 @@ void usb_retimer_fw_update_process_op_cb(int port)
hook_call_deferred(&deferred_pd_suspend_data, 0);
break;
case USB_RETIMER_FW_UPDATE_RESUME_PD:
- pd_set_suspend(port, RESUME);
+ retimer_fw_update_port_handler(port, RESUME);
break;
case USB_RETIMER_FW_UPDATE_GET_MUX:
last_result = retimer_fw_update_usb_mux_get(port);
@@ -187,3 +215,19 @@ void usb_retimer_fw_update_process_op(int port, int op)
break;
}
}
+
+/*
+ * If due to any reason system shuts down during firmware update, resume
+ * the PD port; otherwise, PD port is suspended even system powers up again.
+ * In normal case, system should not allow shutdown during firmware update.
+ */
+static void restore_port(void)
+{
+ int port;
+
+ for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) {
+ if (retimer_fw_update_get_port_state(port))
+ retimer_fw_update_port_handler(port, RESUME);
+ }
+}
+DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, restore_port, HOOK_PRIO_DEFAULT);