summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormatt_wang <matt_wang@compal.corp-partner.google.com>2019-02-13 20:59:23 +0800
committerchrome-bot <chrome-bot@chromium.org>2019-02-26 16:49:14 -0800
commitc2c2776e3a5ee68a1d2a2bab09635692418db998 (patch)
tree6c8b4676216febe6fa2185a3b5c5e38e3f2d599f
parent219b09e87f61ffb410fe1a1dbaed4983460fefb4 (diff)
downloadchrome-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.c57
-rw-r--r--driver/battery/smart.c15
-rw-r--r--include/battery_fuel_gauge.h23
-rw-r--r--include/battery_smart.h10
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);