summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/drawcia/board.c11
-rw-r--r--board/waddledee/board.c11
-rw-r--r--driver/charger/sm5803.c74
-rw-r--r--driver/charger/sm5803.h13
4 files changed, 107 insertions, 2 deletions
diff --git a/board/drawcia/board.c b/board/drawcia/board.c
index 4a012aafa8..3adcbb819a 100644
--- a/board/drawcia/board.c
+++ b/board/drawcia/board.c
@@ -424,6 +424,17 @@ void board_init(void)
}
DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT);
+void board_hibernate(void)
+{
+ /*
+ * Put all charger ICs present into low power mode before entering
+ * z-state.
+ */
+ sm5803_hibernate(CHARGER_PRIMARY);
+ if (board_get_charger_chip_count() > 1)
+ sm5803_hibernate(CHARGER_SECONDARY);
+}
+
__override void board_ocpc_init(struct ocpc_data *ocpc)
{
/* There's no provision to measure Isys */
diff --git a/board/waddledee/board.c b/board/waddledee/board.c
index 91a99272c7..96f0b8841c 100644
--- a/board/waddledee/board.c
+++ b/board/waddledee/board.c
@@ -270,6 +270,17 @@ void board_init(void)
}
DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT);
+void board_hibernate(void)
+{
+ /*
+ * Put all charger ICs present into low power mode before entering
+ * z-state.
+ */
+ sm5803_hibernate(CHARGER_PRIMARY);
+ if (board_get_charger_chip_count() > 1)
+ sm5803_hibernate(CHARGER_SECONDARY);
+}
+
__override void board_ocpc_init(struct ocpc_data *ocpc)
{
/* There's no provision to measure Isys */
diff --git a/driver/charger/sm5803.c b/driver/charger/sm5803.c
index 85bd9ce081..30f9826ff6 100644
--- a/driver/charger/sm5803.c
+++ b/driver/charger/sm5803.c
@@ -527,8 +527,32 @@ static void sm5803_init(int chgnum)
rv |= main_write8(chgnum, 0x1F, 0x0);
}
- /* Disable Ibus PROCHOT comparator */
- rv = chg_read8(chgnum, SM5803_REG_PHOT1, &reg);
+ /* Enable LDO bits */
+ rv |= main_read8(chgnum, SM5803_REG_REFERENCE, &reg);
+ reg &= ~(BIT(0) | BIT(1));
+ rv |= main_write8(chgnum, SM5803_REG_REFERENCE, reg);
+
+ /* Set a higher clock speed in case it was lowered for z-state */
+ rv |= main_read8(chgnum, SM5803_REG_CLOCK_SEL, &reg);
+ reg &= ~SM5803_CLOCK_SEL_LOW;
+ rv |= main_write8(chgnum, SM5803_REG_CLOCK_SEL, reg);
+
+ /* Turn on GPADCs to default */
+ rv |= meas_write8(chgnum, SM5803_REG_GPADC_CONFIG1, 0xF3);
+
+ /* Enable Psys DAC */
+ rv |= meas_read8(chgnum, SM5803_REG_PSYS1, &reg);
+ reg |= SM5803_PSYS1_DAC_EN;
+ rv |= meas_write8(chgnum, SM5803_REG_PSYS1, reg);
+
+ /* Enable ADC sigma delta */
+ rv |= chg_read8(chgnum, SM5803_REG_CC_CONFIG1, &reg);
+ reg |= SM5803_CC_CONFIG1_SD_PWRUP;
+ rv |= chg_write8(chgnum, SM5803_REG_CC_CONFIG1, reg);
+
+ /* Enable PROCHOT comparators except Ibus */
+ rv |= chg_read8(chgnum, SM5803_REG_PHOT1, &reg);
+ reg |= SM5803_PHOT1_COMPARATOR_EN;
reg &= ~SM5803_PHOT1_IBUS_PHOT_COMP_EN;
rv |= chg_write8(chgnum, SM5803_REG_PHOT1, reg);
@@ -632,6 +656,52 @@ static enum ec_error_list sm5803_post_init(int chgnum)
return EC_SUCCESS;
}
+void sm5803_hibernate(int chgnum)
+{
+ enum ec_error_list rv;
+ int reg;
+
+ rv = main_read8(chgnum, SM5803_REG_REFERENCE, &reg);
+ if (rv) {
+ CPRINTS("%s %d: Failed to read REFERENCE reg", CHARGER_NAME,
+ chgnum);
+ return;
+ }
+
+ /* Disable LDO bits - note the primary LDO should not be disabled */
+ if (chgnum != CHARGER_PRIMARY) {
+ reg |= (BIT(0) | BIT(1));
+ rv |= main_write8(chgnum, SM5803_REG_REFERENCE, reg);
+ }
+
+ /* Slow the clock speed */
+ rv |= main_read8(chgnum, SM5803_REG_CLOCK_SEL, &reg);
+ reg |= SM5803_CLOCK_SEL_LOW;
+ rv |= main_write8(chgnum, SM5803_REG_CLOCK_SEL, reg);
+
+ /* Turn off GPADCs */
+ rv |= meas_write8(chgnum, SM5803_REG_GPADC_CONFIG1, 0);
+ rv |= meas_write8(chgnum, SM5803_REG_GPADC_CONFIG2, 0);
+
+ /* Disable Psys DAC */
+ rv |= meas_read8(chgnum, SM5803_REG_PSYS1, &reg);
+ reg &= ~SM5803_PSYS1_DAC_EN;
+ rv |= meas_write8(chgnum, SM5803_REG_PSYS1, reg);
+
+ /* Disable ADC sigma delta */
+ rv |= chg_read8(chgnum, SM5803_REG_CC_CONFIG1, &reg);
+ reg &= ~SM5803_CC_CONFIG1_SD_PWRUP;
+ rv |= chg_write8(chgnum, SM5803_REG_CC_CONFIG1, reg);
+
+ /* Disable PROCHOT comparators */
+ rv |= chg_read8(chgnum, SM5803_REG_PHOT1, &reg);
+ reg &= ~SM5803_PHOT1_COMPARATOR_EN;
+ rv |= chg_write8(chgnum, SM5803_REG_PHOT1, reg);
+
+ if (rv)
+ CPRINTS("%s %d: Failed to set hibernate", 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 7c0eaca78b..fe71314b1a 100644
--- a/driver/charger/sm5803.h
+++ b/driver/charger/sm5803.h
@@ -84,6 +84,9 @@
#define SM5803_REFERENCE_LDO3P3_PGOOD BIT(4)
#define SM5803_REFERENCE_LDO5_PGOOD BIT(5)
+#define SM5803_REG_CLOCK_SEL 0x2A
+#define SM5803_CLOCK_SEL_LOW BIT(0)
+
#define SM5803_REG_GPIO0_CTRL 0x30
#define SM5803_GPIO0_VAL BIT(0)
#define SM5803_GPIO0_MODE_MASK GENMASK(2, 1)
@@ -121,6 +124,11 @@ enum sm5803_gpio0_modes {
#define SM5803_GPADCC1_VSYS_EN BIT(6) /* NOTE: DO NOT CLEAR */
#define SM5803_GPADCC1_TINT_EN BIT(7)
+#define SM5803_REG_GPADC_CONFIG2 0x02
+
+#define SM5803_REG_PSYS1 0x04
+#define SM5803_PSYS1_DAC_EN BIT(0)
+
/* Note: Threshold registers all assume lower 2 bits are 0 */
#define SM5803_REG_VBUS_LOW_TH 0x1A
#define SM5803_REG_VBUS_HIGH_TH 0x2A
@@ -168,6 +176,9 @@ enum sm5803_gpio0_modes {
/* Charger registers (address 0x32) */
+#define SM5803_REG_CC_CONFIG1 0x01
+#define SM5803_CC_CONFIG1_SD_PWRUP BIT(3)
+
#define SM5803_REG_FLOW1 0x1C
#define SM5803_FLOW1_MODE GENMASK(1, 0)
#define SM5803_FLOW1_DIRECTCHG_SRC_EN BIT(2)
@@ -288,6 +299,7 @@ enum sm5803_charger_modes {
#define SM5803_PHOT1_IBUS_PHOT_COMP_EN BIT(1)
#define SM5803_PHOT1_VSYS_MON_EN BIT(2)
#define SM5803_PHOT1_VBUS_MON_EN BIT(3)
+#define SM5803_PHOT1_COMPARATOR_EN GENMASK(3, 0)
#define SM5803_PHOT1_DURATION GENMASK(6, 4)
#define SM5803_PHOT1_DURATION_SHIFT 4
#define SM5803_PHOT1_IRQ_MODE BIT(7)
@@ -320,6 +332,7 @@ enum ec_error_list sm5803_get_chg_det(int chgnum, int *chg_det);
enum ec_error_list sm5803_set_vbus_disch(int chgnum, int enable);
enum ec_error_list sm5803_vbus_sink_enable(int chgnum, int enable);
+void sm5803_hibernate(int chgnum);
void sm5803_interrupt(int chgnum);
extern const struct charger_drv sm5803_drv;