summaryrefslogtreecommitdiff
path: root/driver/battery/bq27541.c
diff options
context:
space:
mode:
Diffstat (limited to 'driver/battery/bq27541.c')
-rw-r--r--driver/battery/bq27541.c79
1 files changed, 75 insertions, 4 deletions
diff --git a/driver/battery/bq27541.c b/driver/battery/bq27541.c
index 868b0215e8..0fa91db904 100644
--- a/driver/battery/bq27541.c
+++ b/driver/battery/bq27541.c
@@ -2,10 +2,11 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
- * Battery driver for BQ27541/BQ27741/BQ27742.
+ * Battery driver for BQ27541/BQ27542/BQ27741/BQ27742.
*/
#include "battery.h"
+#include "battery_smart.h"
#include "console.h"
#include "extpower.h"
#include "hooks.h"
@@ -14,6 +15,7 @@
#define BQ27541_ADDR_FLAGS 0x55
#define BQ27541_TYPE_ID 0x0541
+#define BQ27542_TYPE_ID 0x0542
#define BQ27741_TYPE_ID 0x0741
#define BQ27742_TYPE_ID 0x0742
@@ -39,12 +41,25 @@
#define REG_TT_EAT_CONSTANT_POWER 0x26
#define REG_CYCLE_COUNT 0x2a
#define REG_STATE_OF_CHARGE 0x2c
+#define REG_DATA_FLASH_BLOCK 0x3f
#define REG_DESIGN_CAPACITY 0x3c
+#define REG_MANUFACTURER_INFO 0x52
#define REG_DEVICE_NAME_LENGTH 0x62
#define MAX_DEVICE_NAME_LENGTH 7
#define REG_DEVICE_NAME 0x63
#define REG_PROTECTOR 0x6d
+/* Over-charge */
+#define BQ27542_FLAG_BATHI BIT(13)
+/* Over Temperature in discharge */
+#define BQ27542_FLAG_OTD BIT(11)
+/* Over Temperature in charge */
+#define BQ27542_FLAG_OTC BIT(7)
+/* Charge allowed */
+#define BQ27542_FLAG_CHG BIT(3)
+/* Discharge */
+#define BQ27542_FLAG_DSG BIT(0)
+
static int battery_type_id;
static int fake_state_of_charge = -1;
@@ -69,10 +84,12 @@ int bq27541_probe(void)
rv = bq27541_write(REG_CTRL, 0x1);
rv |= bq27541_read(REG_CTRL, &battery_type_id);
-
+ /* Read twice to get the right value */
+ rv |= bq27541_read(REG_CTRL, &battery_type_id);
if (rv)
return rv;
if (battery_type_id == BQ27541_TYPE_ID ||
+ battery_type_id == BQ27542_TYPE_ID ||
battery_type_id == BQ27741_TYPE_ID ||
battery_type_id == BQ27742_TYPE_ID)
return EC_SUCCESS;
@@ -95,6 +112,16 @@ int battery_device_name(char *device_name, int buf_size)
strzcpy(device_name, "<BATT>", len);
return 0;
}
+ /* Battery pack vendor specific */
+ if (battery_type_id == BQ27542_TYPE_ID) {
+ rv = bq27541_write(REG_DATA_FLASH_BLOCK, 0x1);
+ for (i = 0; i < len; ++i) {
+ rv |= bq27541_read8(REG_MANUFACTURER_INFO + i, &val);
+ device_name[i] = val;
+ }
+ device_name[i] = '\0';
+ return rv;
+ }
rv = bq27541_read8(REG_DEVICE_NAME_LENGTH, &val);
if (rv)
@@ -112,7 +139,7 @@ int battery_device_name(char *device_name, int buf_size)
int battery_state_of_charge_abs(int *percent)
{
- return EC_ERROR_UNIMPLEMENTED;
+ return bq27541_read(REG_STATE_OF_CHARGE, percent);
}
int battery_remaining_capacity(int *capacity)
@@ -149,6 +176,9 @@ int battery_time_at_rate(int rate, int *minutes)
{
int rv;
+ if (battery_type_id == BQ27542_TYPE_ID)
+ return EC_ERROR_UNIMPLEMENTED;
+
rv = bq27541_write(REG_AT_RATE, rate);
if (rv)
return rv;
@@ -197,7 +227,7 @@ static int battery_charging_allowed(int *allowed)
if (battery_type_id == BQ27541_TYPE_ID ||
battery_type_id == BQ27741_TYPE_ID)
*allowed = (val & 0x100);
- else /* BQ27742_TYPE_ID */
+ else /* BQ27742_TYPE_ID, BQ27542_TYPE_ID */
*allowed = (val & 0x8);
return EC_SUCCESS;
@@ -210,6 +240,25 @@ int battery_get_mode(int *mode)
int battery_status(int *status)
{
+ int rv;
+ int flag = 0;
+
+ *status = 0;
+ if (battery_type_id == BQ27542_TYPE_ID) {
+ rv = bq27541_read(REG_FLAGS, &flag);
+ if (rv)
+ return rv;
+
+ if (flag & (BQ27542_FLAG_OTC | BQ27542_FLAG_OTD))
+ *status |= STATUS_OVERTEMP_ALARM;
+ if (flag & BQ27542_FLAG_DSG)
+ *status |= STATUS_DISCHARGING;
+ if (flag & BQ27542_FLAG_BATHI)
+ *status |= STATUS_OVERCHARGED_ALARM;
+
+ return EC_SUCCESS;
+ }
+
return EC_ERROR_UNIMPLEMENTED;
}
@@ -249,6 +298,12 @@ void battery_get_params(struct batt_params *batt)
batt->flags |= BATT_FLAG_BAD_CURRENT;
batt->current = (int16_t)v;
+ if (battery_remaining_capacity(&batt->remaining_capacity))
+ batt->flags |= BATT_FLAG_BAD_REMAINING_CAPACITY;
+
+ if (battery_full_charge_capacity(&batt->full_capacity))
+ batt->flags |= BATT_FLAG_BAD_FULL_CAPACITY;
+
/* Default to not desiring voltage and current */
batt->desired_voltage = batt->desired_current = 0;
@@ -353,3 +408,19 @@ DECLARE_CONSOLE_COMMAND(battfake, command_battfake,
"percent (-1 = use real level)",
"Set fake battery level");
+#ifdef CONFIG_CMD_PWR_AVG
+int battery_get_avg_current(void)
+{
+ int current = -EC_ERROR_UNKNOWN;
+
+ bq27541_read(REG_AVERAGE_CURRENT, &current);
+ return current;
+}
+
+int battery_get_avg_voltage(void)
+{
+ /* BQ27541 does not have this parameter */
+ return -EC_ERROR_UNIMPLEMENTED;
+}
+#endif /* CONFIG_CMD_PWR_AVG */
+