diff options
author | Diana Z <dzigterman@chromium.org> | 2020-08-07 10:57:28 -0600 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-08-11 20:24:38 +0000 |
commit | d3ba2c4d0b2eeac179322f1ffd477130029e8e83 (patch) | |
tree | 3c9df4273a70a52bd69a72230535b38b781b77db | |
parent | c1231644fa6bfa46ff9867419d40a5d01dd00c14 (diff) | |
download | chrome-ec-d3ba2c4d0b2eeac179322f1ffd477130029e8e83.tar.gz |
SM5803: Flow 1 register updates
This commit adds:
- bit names updated to the most recent SM5803A datasheet
- centralized control of FLOW1 updates after init in one function
- verification of charger register 0x5C contents before enabling
charging
- correction of init charger disable behavior
BRANCH=None
BUG=None
TEST=on drawcia, observe that sink mode is enabled when charger is
plugged in to MB, OTG bits are enabled with dongles plugged in
Signed-off-by: Diana Z <dzigterman@chromium.org>
Change-Id: I4e841e8288f85eeb8b4ee6afe953ea0f8df61fa0
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2343604
Reviewed-by: Aseda Aboagye <aaboagye@chromium.org>
-rw-r--r-- | driver/charger/sm5803.c | 103 | ||||
-rw-r--r-- | driver/charger/sm5803.h | 11 |
2 files changed, 84 insertions, 30 deletions
diff --git a/driver/charger/sm5803.c b/driver/charger/sm5803.c index 59dcef0642..3950a94634 100644 --- a/driver/charger/sm5803.c +++ b/driver/charger/sm5803.c @@ -50,6 +50,7 @@ static struct mutex flow1_access_lock[CHARGER_NUM]; static int charger_vbus[CHARGER_NUM]; static int sm5803_is_sourcing_otg_power(int chgnum, int port); +static enum ec_error_list sm5803_get_dev_id(int chgnum, int *id); static inline enum ec_error_list chg_read8(int chgnum, int offset, int *value) { @@ -108,6 +109,49 @@ static inline enum ec_error_list test_update8(int chgnum, const int offset, SM5803_ADDR_TEST_FLAGS, offset, mask, action); } +static enum ec_error_list sm5803_flow1_update(int chgnum, const uint8_t mask, + const enum mask_update_action action) +{ + int reg, rv, dev_id; + + /* + * On Si rev 3, confirm that init value in 0x5C is intact before + * enabling charging. + */ + rv = sm5803_get_dev_id(chgnum, &dev_id); + if (rv) + return rv; + + if (dev_id == 0x03) { + rv = chg_read8(chgnum, 0x5C, ®); + if (rv) { + CPRINTS("%s %d: Failed 0x5C read", + CHARGER_NAME, chgnum); + return rv; + } + + if (reg != 0x7A) { + CPRINTS("%s %d: Unexpected 0x5C reg: 0x%02x. File bug", + CHARGER_NAME, chgnum, reg); + + /* Fix it before enabling charging */ + rv = chg_write8(chgnum, 0x5C, 0x7A); + } + } + + /* Safety checks done, onto the actual register update */ + mutex_lock(&flow1_access_lock[chgnum]); + + rv = i2c_update8(chg_chips[chgnum].i2c_port, + chg_chips[chgnum].i2c_addr_flags, + SM5803_REG_FLOW1, + mask, action); + + mutex_unlock(&flow1_access_lock[chgnum]); + + return rv; +} + int sm5803_is_vbus_present(int chgnum) { return charger_vbus[chgnum]; @@ -223,8 +267,7 @@ static void sm5803_init(int chgnum) * No charger connected, disable CHG_EN * (note other bits default to 0) */ - rv = chg_write8(chgnum, SM5803_FLOW1_CHG_EN, - 0); + rv = chg_write8(chgnum, SM5803_REG_FLOW1, 0); } else if (!sm5803_is_sourcing_otg_power(chgnum, chgnum)) { charger_vbus[chgnum] = 1; } @@ -560,7 +603,9 @@ static enum ec_error_list sm5803_get_status(int chgnum, int *status) if (rv) return rv; - if (!(reg & SM5803_FLOW1_CHG_EN)) + + if ((reg & SM5803_FLOW1_MODE) == CHARGER_MODE_DISABLED && + !(reg & SM5803_FLOW1_LINEAR_CHARGE_EN)) *status |= CHARGER_CHARGE_INHIBITED; return EC_SUCCESS; @@ -569,11 +614,10 @@ static enum ec_error_list sm5803_get_status(int chgnum, int *status) static enum ec_error_list sm5803_set_mode(int chgnum, int mode) { enum ec_error_list rv; - int flow1_reg, flow2_reg; + int flow2_reg; int dev_id; rv = sm5803_get_dev_id(chgnum, &dev_id); - mutex_lock(&flow1_access_lock[chgnum]); /* New silicon version requires a new procedure to start charging. */ if ((dev_id >= 3) && (!(mode & CHARGE_FLAG_INHIBIT_CHARGE))) { @@ -587,11 +631,8 @@ static enum ec_error_list sm5803_set_mode(int chgnum, int mode) } rv |= chg_read8(chgnum, SM5803_REG_FLOW2, &flow2_reg); - rv |= chg_read8(chgnum, SM5803_REG_FLOW1, &flow1_reg); - if (rv) { - mutex_unlock(&flow1_access_lock[chgnum]); + if (rv) return rv; - } /* * Note: Charge may be enabled while OTG is enabled, but charge inhibit @@ -599,18 +640,21 @@ static enum ec_error_list sm5803_set_mode(int chgnum, int mode) * when battery is present. */ if (mode & CHARGE_FLAG_INHIBIT_CHARGE) { - flow1_reg = 0; + rv |= sm5803_flow1_update(chgnum, 0xFF, MASK_CLR); flow2_reg &= ~SM5803_FLOW2_AUTO_ENABLED; } else { - flow1_reg |= SM5803_FLOW1_CHG_EN; + /* + * TODO(b/163511546): SM5803: Consolidate flow control changes + * + * Should be a part of an initial sink enable function + */ + rv |= sm5803_flow1_update(chgnum, CHARGER_MODE_SINK, MASK_SET); if (battery_get_disconnect_state() == BATTERY_NOT_DISCONNECTED) flow2_reg |= SM5803_FLOW2_AUTO_ENABLED; } - rv = chg_write8(chgnum, SM5803_REG_FLOW1, flow1_reg); rv |= chg_write8(chgnum, SM5803_REG_FLOW2, flow2_reg); - mutex_unlock(&flow1_access_lock[chgnum]); return rv; } @@ -754,8 +798,12 @@ static enum ec_error_list sm5803_set_option(int chgnum, int option) enum ec_error_list rv; int reg; + mutex_lock(&flow1_access_lock[chgnum]); + reg = option & 0xFF; rv = chg_write8(chgnum, SM5803_REG_FLOW1, reg); + + mutex_unlock(&flow1_access_lock[chgnum]); if (rv) return rv; @@ -820,13 +868,6 @@ static enum ec_error_list sm5803_enable_otg_power(int chgnum, int enabled) reg &= ~SM5803_PHOT1_VBUS_MON_EN; rv |= chg_write8(chgnum, SM5803_REG_PHOT1, reg); - mutex_lock(&flow1_access_lock[chgnum]); - rv |= chg_read8(chgnum, SM5803_REG_FLOW1, ®); - if (rv) { - mutex_unlock(&flow1_access_lock[chgnum]); - return rv; - } - /* * Enable: CHG_EN - turns on buck-boost * VBUSIN_DISCH_EN - enable discharge on Vbus @@ -837,14 +878,20 @@ static enum ec_error_list sm5803_enable_otg_power(int chgnum, int enabled) * disabled through set_mode. */ if (enabled) - reg |= (SM5803_FLOW1_CHG_EN | SM5803_FLOW1_VBUSIN_DISCHG_EN | - SM5803_FLOW1_DIRECTCHG_SRC_EN); + rv = sm5803_flow1_update(chgnum, CHARGER_MODE_SOURCE | + SM5803_FLOW1_DIRECTCHG_SRC_EN, + MASK_SET); else - reg &= ~(SM5803_FLOW1_VBUSIN_DISCHG_EN | - SM5803_FLOW1_DIRECTCHG_SRC_EN); + /* + * TODO(b/163511546): SM5803: Consolidate flow control changes + * + * May be able to disable mode entirely if PD task usage remains + * consistent. + */ + rv = sm5803_flow1_update(chgnum, BIT(1) | + SM5803_FLOW1_DIRECTCHG_SRC_EN, + MASK_CLR); - rv = chg_write8(chgnum, SM5803_REG_FLOW1, reg); - mutex_unlock(&flow1_access_lock[chgnum]); return rv; } @@ -857,8 +904,8 @@ static int sm5803_is_sourcing_otg_power(int chgnum, int port) if (rv) return 0; - reg &= (SM5803_FLOW1_CHG_EN | SM5803_FLOW1_VBUSIN_DISCHG_EN); - return reg == (SM5803_FLOW1_CHG_EN | SM5803_FLOW1_VBUSIN_DISCHG_EN); + reg &= SM5803_FLOW1_MODE; + return reg == CHARGER_MODE_SOURCE; } #ifdef CONFIG_CMD_CHARGER_DUMP diff --git a/driver/charger/sm5803.h b/driver/charger/sm5803.h index c0a3ec70e5..9fc04de0f4 100644 --- a/driver/charger/sm5803.h +++ b/driver/charger/sm5803.h @@ -151,11 +151,18 @@ enum sm5803_gpio0_modes { /* Charger registers (address 0x32) */ #define SM5803_REG_FLOW1 0x1C -#define SM5803_FLOW1_CHG_EN BIT(0) -#define SM5803_FLOW1_VBUSIN_DISCHG_EN BIT(1) +#define SM5803_FLOW1_MODE GENMASK(1, 0) #define SM5803_FLOW1_DIRECTCHG_SRC_EN BIT(2) +#define SM5803_FLOW1_LINEAR_CHARGE_EN BIT(3) #define SM5803_FLOW1_USB_SUSP BIT(7) +enum sm5803_charger_modes { + CHARGER_MODE_DISABLED, + CHARGER_MODE_SINK, + CHARGER_MODE_RESERVED, + CHARGER_MODE_SOURCE, +}; + #define SM5803_REG_FLOW2 0x1D #define SM5803_FLOW2_AUTO_TRKL_EN BIT(0) #define SM5803_FLOW2_AUTO_PRECHG_EN BIT(1) |