diff options
author | matt_wang <matt_wang@compal.corp-partner.google.com> | 2019-02-13 20:59:23 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2019-02-26 16:49:14 -0800 |
commit | c2c2776e3a5ee68a1d2a2bab09635692418db998 (patch) | |
tree | 6c8b4676216febe6fa2185a3b5c5e38e3f2d599f | |
parent | 219b09e87f61ffb410fe1a1dbaed4983460fefb4 (diff) | |
download | chrome-ec-c2c2776e3a5ee68a1d2a2bab09635692418db998.tar.gz |
Battery: add support battery-cutoff SMBus block write function
Implements battery-cutoff SMBus write block function
BUG=b:122944526
BRANCH=None
TEST=Verify battery cuff on fleex via SMBus block write.
Change-Id: Ib52146cd3042c4a6d2dbafadd430591936230891
Signed-off-by: matt_wang <matt_wang@compal.corp-partner.google.com>
Reviewed-on: https://chromium-review.googlesource.com/1470462
Commit-Ready: Justin TerAvest <teravest@chromium.org>
Tested-by: Justin TerAvest <teravest@chromium.org>
Tested-by: Elmo Lan <elmo_lan@compal.corp-partner.google.com>
Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
Reviewed-by: Jett Rink <jettrink@chromium.org>
Reviewed-by: Justin TerAvest <teravest@chromium.org>
Reviewed-by: Elmo Lan <elmo_lan@compal.corp-partner.google.com>
-rw-r--r-- | common/battery_fuel_gauge.c | 57 | ||||
-rw-r--r-- | driver/battery/smart.c | 15 | ||||
-rw-r--r-- | include/battery_fuel_gauge.h | 23 | ||||
-rw-r--r-- | include/battery_smart.h | 10 |
4 files changed, 94 insertions, 11 deletions
diff --git a/common/battery_fuel_gauge.c b/common/battery_fuel_gauge.c index 476ca52570..a0dd250899 100644 --- a/common/battery_fuel_gauge.c +++ b/common/battery_fuel_gauge.c @@ -9,6 +9,7 @@ #include "battery_smart.h" #include "console.h" #include "hooks.h" +#include "i2c.h" #include "util.h" #define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) @@ -89,26 +90,60 @@ const struct battery_info *battery_get_info(void) return &get_batt_params()->batt_info; } +int cut_off_battery_block_write(const struct ship_mode_info *ship_mode) +{ + int rv; + + uint8_t cutdata[3] = { + 0x02, + ship_mode->reg_data[0] & 0xFF, + ship_mode->reg_data[0] >> 8, + }; + + /* SMBus protocols are block write, which include byte count + * byte. Byte count segments are required to communicate + * required action and the number of data bytes. + * Due to ship mode command requires writing data values twice + * to cutoff the battery, so byte count is 0x02. + */ + rv = sb_write_block(ship_mode->reg_addr, cutdata, sizeof(cutdata)); + if (rv) + return rv; + + /* Use the next set of values */ + cutdata[1] = ship_mode->reg_data[1] & 0xFF; + cutdata[2] = ship_mode->reg_data[1] >> 8; + + return sb_write_block(ship_mode->reg_addr, cutdata, sizeof(cutdata)); +} + +int cut_off_battery_sb_write(const struct ship_mode_info *ship_mode) +{ + int rv; + + /* Ship mode command requires writing 2 data values */ + rv = sb_write(ship_mode->reg_addr, ship_mode->reg_data[0]); + if (rv) + return rv; + + return sb_write(ship_mode->reg_addr, ship_mode->reg_data[1]); +} + int board_cut_off_battery(void) { int rv; - int cmd; - int data; int type = get_battery_type(); /* If battery type is unknown can't send ship mode command */ if (type == BATTERY_TYPE_COUNT) return EC_RES_ERROR; - /* Ship mode command requires writing 2 data values */ - cmd = board_battery_info[type].fuel_gauge.ship_mode.reg_addr; - data = board_battery_info[type].fuel_gauge.ship_mode.reg_data[0]; - rv = sb_write(cmd, data); - if (rv != EC_SUCCESS) - return EC_RES_ERROR; - - data = board_battery_info[type].fuel_gauge.ship_mode.reg_data[1]; - rv = sb_write(cmd, data); + if (board_battery_info[type].fuel_gauge.ship_mode.wb_support) + rv = cut_off_battery_block_write( + &board_battery_info[type].fuel_gauge.ship_mode); + else + rv = cut_off_battery_sb_write( + &board_battery_info[type].fuel_gauge.ship_mode); return rv ? EC_RES_ERROR : EC_RES_SUCCESS; } diff --git a/driver/battery/smart.c b/driver/battery/smart.c index 758a60f546..f06da84e9f 100644 --- a/driver/battery/smart.c +++ b/driver/battery/smart.c @@ -108,6 +108,21 @@ int sb_read_mfgacc(int cmd, int block, uint8_t *data, int len) return EC_SUCCESS; } +int sb_write_block(int reg, const uint8_t *val, int len) +{ +#ifdef CONFIG_BATTERY_CUT_OFF + /* + * Some batteries would wake up after cut-off if we talk to it. + */ + if (battery_is_cut_off()) + return EC_RES_ACCESS_DENIED; +#endif + + /* TODO: implement smbus_write_block. */ + return i2c_write_block(I2C_PORT_BATTERY, BATTERY_ADDR, reg, val, len); + +} + int battery_get_mode(int *mode) { return sb_read(SB_BATTERY_MODE, mode); diff --git a/include/battery_fuel_gauge.h b/include/battery_fuel_gauge.h index 9c3b0b12da..d610b7e417 100644 --- a/include/battery_fuel_gauge.h +++ b/include/battery_fuel_gauge.h @@ -14,6 +14,13 @@ #define SHIP_MODE_WRITES 2 struct ship_mode_info { + /* + * Write Block Support. If wb_support is true, then we use a i2c write + * block command instead of a 16-bit write. The effective difference is + * that the i2c transaction will prefix the length (2) when wb_support + * is enabled. + */ + const uint8_t wb_support; const uint8_t reg_addr; const uint16_t reg_data[SHIP_MODE_WRITES]; }; @@ -61,4 +68,20 @@ int battery_bq4050_imbalance_mv(void); #endif +/** + * Battery cut off command via SMBus write block. + * + * @param ship_mode Battery ship mode information + * @return non-zero if error + */ +int cut_off_battery_block_write(const struct ship_mode_info *ship_mode); + +/** + * Battery cut off command via SMBus write word. + * + * @param ship_mode Battery ship mode information + * @return non-zero if error + */ +int cut_off_battery_sb_write(const struct ship_mode_info *ship_mode); + #endif /* __CROS_EC_BATTERY_FUEL_GAUGE_H */ diff --git a/include/battery_smart.h b/include/battery_smart.h index 1cbcf295f1..e4931dad71 100644 --- a/include/battery_smart.h +++ b/include/battery_smart.h @@ -147,6 +147,16 @@ int sb_read_string(int offset, uint8_t *data, int len); /* Write to battery */ int sb_write(int cmd, int param); +/** + * Write block to do battery cutoff + * + * @param reg Battery cutoff register + * @param val Battery cutoff data value + * @param len Param val data length + * @return non-zero if error + */ +int sb_write_block(int reg, const uint8_t *val, int len); + /* Read manufactures access data from the battery */ int sb_read_mfgacc(int cmd, int block, uint8_t *data, int len); |