From aa66f469cf4be213014d3e16440861e08ee57bca Mon Sep 17 00:00:00 2001 From: Divagar Mohandass Date: Tue, 15 Sep 2020 07:16:55 +0000 Subject: SM5803: add suspend/resume function for S0ix state add function to turn on/off features in SM5803 charger during S0ix state to save power. we are seeing ~8mW power saving per charger. BRANCH=None BUG=b:168591511 TEST=Check power saving in S0ix state and check charger and device functionality after resume. Signed-off-by: Divagar Mohandass Change-Id: I3ea32219040263f0abef8b9dd4c52edb31289fd7 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2409485 Reviewed-by: Aseda Aboagye --- board/drawcia/board.c | 16 +++++++ board/waddledee/board.c | 16 +++++++ driver/charger/sm5803.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++ driver/charger/sm5803.h | 4 ++ 4 files changed, 153 insertions(+) diff --git a/board/drawcia/board.c b/board/drawcia/board.c index 3adcbb819a..1b872683fa 100644 --- a/board/drawcia/board.c +++ b/board/drawcia/board.c @@ -424,6 +424,22 @@ void board_init(void) } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); +static void board_resume(void) +{ + sm5803_disable_low_power_mode(CHARGER_PRIMARY); + if (board_get_charger_chip_count() > 1) + sm5803_disable_low_power_mode(CHARGER_SECONDARY); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_resume, HOOK_PRIO_DEFAULT); + +static void board_suspend(void) +{ + sm5803_enable_low_power_mode(CHARGER_PRIMARY); + if (board_get_charger_chip_count() > 1) + sm5803_enable_low_power_mode(CHARGER_SECONDARY); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_suspend, HOOK_PRIO_DEFAULT); + void board_hibernate(void) { /* diff --git a/board/waddledee/board.c b/board/waddledee/board.c index 96f0b8841c..9a4b8432cc 100644 --- a/board/waddledee/board.c +++ b/board/waddledee/board.c @@ -270,6 +270,22 @@ void board_init(void) } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); +static void board_resume(void) +{ + sm5803_disable_low_power_mode(CHARGER_PRIMARY); + if (board_get_charger_chip_count() > 1) + sm5803_disable_low_power_mode(CHARGER_SECONDARY); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_resume, HOOK_PRIO_DEFAULT); + +static void board_suspend(void) +{ + sm5803_enable_low_power_mode(CHARGER_PRIMARY); + if (board_get_charger_chip_count() > 1) + sm5803_enable_low_power_mode(CHARGER_SECONDARY); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_suspend, HOOK_PRIO_DEFAULT); + void board_hibernate(void) { /* diff --git a/driver/charger/sm5803.c b/driver/charger/sm5803.c index 30f9826ff6..207404f96f 100644 --- a/driver/charger/sm5803.c +++ b/driver/charger/sm5803.c @@ -702,6 +702,123 @@ void sm5803_hibernate(int chgnum) CPRINTS("%s %d: Failed to set hibernate", CHARGER_NAME, chgnum); } +static void sm5803_disable_runtime_low_power_mode(void) +{ + enum ec_error_list rv; + int reg; + int chgnum = TASK_ID_TO_PD_PORT(task_get_current()); + + CPRINTS("%s %d: disable runtime low power mode", CHARGER_NAME, chgnum); + rv = main_read8(chgnum, SM5803_REG_REFERENCE, ®); + if (rv) { + CPRINTS("%s %d: Failed to read REFERENCE reg", CHARGER_NAME, + chgnum); + return; + } + /* Set a higher clock speed */ + rv |= main_read8(chgnum, SM5803_REG_CLOCK_SEL, ®); + reg &= ~SM5803_CLOCK_SEL_LOW; + rv |= main_write8(chgnum, SM5803_REG_CLOCK_SEL, reg); + + /* Enable ADC sigma delta */ + rv |= chg_read8(chgnum, SM5803_REG_CC_CONFIG1, ®); + reg |= SM5803_CC_CONFIG1_SD_PWRUP; + rv |= chg_write8(chgnum, SM5803_REG_CC_CONFIG1, reg); + + if (rv) + CPRINTS("%s %d: Failed to set in disable runtime LPM", + CHARGER_NAME, chgnum); +} +DECLARE_HOOK(HOOK_USB_PD_CONNECT, + sm5803_disable_runtime_low_power_mode, + HOOK_PRIO_FIRST); + +static void sm5803_enable_runtime_low_power_mode(void) +{ + enum ec_error_list rv; + int reg; + int chgnum = TASK_ID_TO_PD_PORT(task_get_current()); + + CPRINTS("%s %d: enable runtime low power mode", CHARGER_NAME, chgnum); + rv = main_read8(chgnum, SM5803_REG_REFERENCE, ®); + if (rv) { + CPRINTS("%s %d: Failed to read REFERENCE reg", CHARGER_NAME, + chgnum); + return; + } + /* Slow the clock speed */ + rv |= main_read8(chgnum, SM5803_REG_CLOCK_SEL, ®); + reg |= SM5803_CLOCK_SEL_LOW; + rv |= main_write8(chgnum, SM5803_REG_CLOCK_SEL, reg); + + /* Disable ADC sigma delta */ + rv |= chg_read8(chgnum, SM5803_REG_CC_CONFIG1, ®); + reg &= ~SM5803_CC_CONFIG1_SD_PWRUP; + rv |= chg_write8(chgnum, SM5803_REG_CC_CONFIG1, reg); + + if (rv) + CPRINTS("%s %d: Failed to set in enable runtime LPM", + CHARGER_NAME, chgnum); +} +DECLARE_HOOK(HOOK_USB_PD_DISCONNECT, + sm5803_enable_runtime_low_power_mode, + HOOK_PRIO_LAST); + +void sm5803_disable_low_power_mode(int chgnum) +{ + enum ec_error_list rv; + int reg; + + CPRINTS("%s %d: disable low power mode", CHARGER_NAME, chgnum); + rv = main_read8(chgnum, SM5803_REG_REFERENCE, ®); + if (rv) { + CPRINTS("%s %d: Failed to read REFERENCE reg", CHARGER_NAME, + chgnum); + return; + } + /* Enable Psys DAC */ + rv |= meas_read8(chgnum, SM5803_REG_PSYS1, ®); + reg |= SM5803_PSYS1_DAC_EN; + rv |= meas_write8(chgnum, SM5803_REG_PSYS1, reg); + + /* Enable PROCHOT comparators except Ibus */ + rv |= chg_read8(chgnum, SM5803_REG_PHOT1, ®); + reg |= SM5803_PHOT1_COMPARATOR_EN; + reg &= ~SM5803_PHOT1_IBUS_PHOT_COMP_EN; + rv |= chg_write8(chgnum, SM5803_REG_PHOT1, reg); + + if (rv) + CPRINTS("%s %d: Failed to set in disable low power mode", + CHARGER_NAME, chgnum); +} + +void sm5803_enable_low_power_mode(int chgnum) +{ + enum ec_error_list rv; + int reg; + + CPRINTS("%s %d: enable low power mode", CHARGER_NAME, chgnum); + rv = main_read8(chgnum, SM5803_REG_REFERENCE, ®); + if (rv) { + CPRINTS("%s %d: Failed to read REFERENCE reg", CHARGER_NAME, + chgnum); + return; + } + /* Disable Psys DAC */ + rv |= meas_read8(chgnum, SM5803_REG_PSYS1, ®); + reg &= ~SM5803_PSYS1_DAC_EN; + rv |= meas_write8(chgnum, SM5803_REG_PSYS1, reg); + + /* Disable PROCHOT comparators */ + rv |= chg_read8(chgnum, SM5803_REG_PHOT1, ®); + reg &= ~SM5803_PHOT1_COMPARATOR_EN; + rv |= chg_write8(chgnum, SM5803_REG_PHOT1, reg); + + if (rv) + CPRINTS("%s %d: Failed to set in enable low power mode", + CHARGER_NAME, chgnum); +} + /* * Process interrupt registers and report any Vbus changes. Alert the AP if the * charger has become too hot. diff --git a/driver/charger/sm5803.h b/driver/charger/sm5803.h index fe71314b1a..93cf9a462d 100644 --- a/driver/charger/sm5803.h +++ b/driver/charger/sm5803.h @@ -335,6 +335,10 @@ enum ec_error_list sm5803_vbus_sink_enable(int chgnum, int enable); void sm5803_hibernate(int chgnum); void sm5803_interrupt(int chgnum); +/* Expose low power mode functions */ +void sm5803_disable_low_power_mode(int chgnum); +void sm5803_enable_low_power_mode(int chgnum); + extern const struct charger_drv sm5803_drv; #endif -- cgit v1.2.1