summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorJett Rink <jettrink@chromium.org>2018-07-02 15:16:58 -0600
committerchrome-bot <chrome-bot@chromium.org>2018-07-12 14:06:11 -0700
commitcb9f7ab2bc851a542f3688740fc02b3da5dabf4b (patch)
treeea76eeeb8a74e143e3bfdde138a99ff287aeac89 /common
parent37ff3e662aacfbe796ee4e93771d25acde56aa7f (diff)
downloadchrome-ec-cb9f7ab2bc851a542f3688740fc02b3da5dabf4b.tar.gz
tcpc: disallow PD_SUSPEND if not enough power
We do not want to allow depthcharge to suspend the PD port for a firmware upgrade if there is not enough battery power to last us during the full firmware upgrade. We cannot use the active_charger function as the EC has just jumped to RW and has not fully initialized the charger state. We use Vbus presence as a good enough approximation that power may be coming in from that port. BRANCH=none BUG=b:78334391 TEST=No battery or deeply discharged battery will skip TCPC upgrade on a yorp if there is a usb charger in that port. Otherwise the upgrade will still be attempted. Change-Id: I9af9cb84cfae611b6ab051d318e2083962424de1 Signed-off-by: Jett Rink <jettrink@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1123314 Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Diffstat (limited to 'common')
-rw-r--r--common/usb_pd_protocol.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index e9525cb547..aba957c77f 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -36,6 +36,14 @@
BUILD_ASSERT(CONFIG_USB_PD_PORT_COUNT <= EC_USB_PD_MAX_PORTS);
/*
+ * If we are trying to upgrade the TCPC port that is supplying power, then we
+ * need to ensure that the battery has enough charge for the upgrade. 100mAh
+ * is about 5% of most batteries, and it should be enough charge to get us
+ * through the EC jump to RW and PD upgrade.
+ */
+#define MIN_BATTERY_FOR_TCPC_UPGRADE_MAH 100 /* mAH */
+
+/*
* Debug log level - higher number == more log
* Level 0: Log state transitions
* Level 1: Level 0, plus state name
@@ -4455,6 +4463,40 @@ static int pd_control(struct host_cmd_handler_args *args)
return EC_RES_ACCESS_DENIED;
if (cmd->subcmd == PD_SUSPEND) {
+ /*
+ * The AP is requesting to suspend PD traffic on the EC so it
+ * can perform a firmware upgrade. If Vbus is present on the
+ * connector (it is either a source or sink), then we will
+ * prevent the upgrade if there is not enough battery to finish
+ * the upgrade. We cannot rely on the EC's active charger data
+ * as the EC just rebooted into RW and has not necessarily
+ * picked the active charger yet.
+ */
+#ifdef HAS_TASK_CHARGER
+ if (pd_is_vbus_present(cmd->chip)) {
+ struct batt_params batt = { 0 };
+ /*
+ * The charger task has not re-initialized, so we need
+ * to ask the battery directly.
+ */
+ battery_get_params(&batt);
+ if (batt.remaining_capacity <
+ MIN_BATTERY_FOR_TCPC_UPGRADE_MAH ||
+ batt.flags & BATT_FLAG_BAD_REMAINING_CAPACITY) {
+ CPRINTS("C%d: Cannot suspend for upgrade, not "
+ "enough battery (%dmAh)!",
+ cmd->chip, batt.remaining_capacity);
+ return EC_RES_BUSY;
+ }
+ }
+#else
+ if (pd_is_vbus_present(cmd->chip)) {
+ CPRINTS("C%d: Cannot suspend for upgrade, Vbus "
+ "present!",
+ cmd->chip);
+ return EC_RES_BUSY;
+ }
+#endif
enable = 0;
} else if (cmd->subcmd == PD_RESUME) {
enable = 1;