diff options
author | Jett Rink <jettrink@chromium.org> | 2018-07-02 15:16:58 -0600 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-07-12 14:06:11 -0700 |
commit | cb9f7ab2bc851a542f3688740fc02b3da5dabf4b (patch) | |
tree | ea76eeeb8a74e143e3bfdde138a99ff287aeac89 /common | |
parent | 37ff3e662aacfbe796ee4e93771d25acde56aa7f (diff) | |
download | chrome-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.c | 42 |
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; |