From 48d48298a9849ce98611b08753823ffb9e818a9f Mon Sep 17 00:00:00 2001 From: Diana Z Date: Tue, 20 Oct 2020 16:21:31 -0600 Subject: SM5803: Only run inits once per EC boot Ensure the SM5803 inits are run only once per EC boot. This will prevent the EC from re-running the init sequence if it is sysjumping (ex. due to an EC flash). BRANCH=None BUG=b:168169691 TEST=on drawlat, unplug battery and verify running a sysjump with the AP on doesn't brown out during init (instead, it browns out later when a hard reset is sent). Verify EC resets do result in inits being run again. Signed-off-by: Diana Z Change-Id: I700aabd51b45e2aff459f787c13978c6212026f5 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2493110 Reviewed-by: Aseda Aboagye --- driver/charger/sm5803.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/driver/charger/sm5803.c b/driver/charger/sm5803.c index 66d7f1144d..1b1de492d8 100644 --- a/driver/charger/sm5803.c +++ b/driver/charger/sm5803.c @@ -13,6 +13,7 @@ #include "hooks.h" #include "i2c.h" #include "sm5803.h" +#include "system.h" #include "throttle_ap.h" #include "timer.h" #include "usb_charge.h" @@ -349,6 +350,35 @@ enum ec_error_list sm5803_vbus_sink_enable(int chgnum, int enable) } +/* + * Track and store whether we've initialized the charger chips already on this + * boot. This should prevent us from re-running inits after sysjumps. + */ +static bool chip_inited[CHARGER_NUM]; +#define SM5803_SYSJUMP_TAG 0x534D /* SM */ +#define SM5803_HOOK_VERSION 1 + +static void init_status_preserve(void) +{ + system_add_jump_tag(SM5803_SYSJUMP_TAG, SM5803_HOOK_VERSION, + sizeof(chip_inited), &chip_inited); +} +DECLARE_HOOK(HOOK_SYSJUMP, init_status_preserve, HOOK_PRIO_DEFAULT); + +static void init_status_retrieve(void) +{ + const uint8_t *tag_contents; + int version, size; + + tag_contents = system_get_jump_tag(SM5803_SYSJUMP_TAG, + &version, &size); + if (tag_contents && (version == SM5803_HOOK_VERSION) && + (size == sizeof(chip_inited))) + /* Valid init status found, restore before charger chip init */ + memcpy(&chip_inited, tag_contents, size); +} +DECLARE_HOOK(HOOK_INIT, init_status_retrieve, HOOK_PRIO_FIRST); + static void sm5803_init(int chgnum) { enum ec_error_list rv; @@ -379,6 +409,15 @@ static void sm5803_init(int chgnum) return; } + /* + * A previous boot already ran inits, safe to return now that we've + * checked i2c communication to the chip and cached Vbus presence + */ + if (chip_inited[chgnum]) { + CPRINTS("%s %d: Already initialized", CHARGER_NAME, chgnum); + return; + } + rv |= charger_device_id(®); if (reg == 0x02) { /* --- Special register init --- @@ -664,6 +703,8 @@ static void sm5803_init(int chgnum) if (rv) CPRINTS("%s %d: Failed initialization", CHARGER_NAME, chgnum); + else + chip_inited[chgnum] = true; } static enum ec_error_list sm5803_post_init(int chgnum) -- cgit v1.2.1