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.c219
1 files changed, 219 insertions, 0 deletions
diff --git a/driver/battery/bq27541.c b/driver/battery/bq27541.c
new file mode 100644
index 0000000000..3dce19ea54
--- /dev/null
+++ b/driver/battery/bq27541.c
@@ -0,0 +1,219 @@
+/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Battery driver for BQ27541.
+ */
+
+#include "battery.h"
+#include "console.h"
+#include "i2c.h"
+#include "util.h"
+
+#define BQ27541_ADDR 0xaa
+#define BQ27541_TYPE_ID 0x0541
+
+#define REG_CTRL 0x00
+#define REG_AT_RATE 0x02
+#define REG_AT_RATE_TIME_TO_EMPTY 0x04
+#define REG_TEMPERATURE 0x06
+#define REG_VOLTAGE 0x08
+#define REG_FLAGS 0x0a
+#define REG_NOMINAL_CAPACITY 0x0c
+#define REG_FULL_AVAILABLE_CAPACITY 0x0e
+#define REG_REMAINING_CAPACITY 0x10
+#define REG_FULL_CHARGE_CAPACITY 0x12
+#define REG_AVERAGE_CURRENT 0x14
+#define REG_TIME_TO_EMPTY 0x16
+#define REG_TIME_TO_FULL 0x18
+#define REG_STANDBY_CURRENT 0x1a
+#define REG_STANDBY_TIME_TO_EMPTY 0x1c
+#define REG_MAX_LOAD_CURRENT 0x1e
+#define REG_MAX_LOAD_TIME_TO_EMPTY 0x20
+#define REG_AVAILABLE_ENERGY 0x22
+#define REG_AVERAGE_POEWR 0x24
+#define REG_TT_EAT_CONSTANT_POWER 0x26
+#define REG_CYCLE_COUNT 0x2a
+#define REG_STATE_OF_CHARGE 0x2c
+#define REG_DESIGN_CAPACITY 0x3c
+#define REG_DEVICE_NAME_LENGTH 0x62
+#define MAX_DEVICE_NAME_LENGTH 7
+#define REG_DEVICE_NAME 0x63
+
+static int bq27541_read(int offset, int *data)
+{
+ return i2c_read16(I2C_PORT_HOST, BQ27541_ADDR, offset, data);
+}
+
+static int bq27541_read8(int offset, int *data)
+{
+ return i2c_read8(I2C_PORT_HOST, BQ27541_ADDR, offset, data);
+}
+
+static int bq27541_write(int offset, int data)
+{
+ return i2c_write16(I2C_PORT_HOST, BQ27541_ADDR, offset, data);
+}
+
+int bq27541_probe(void)
+{
+ int rv;
+ int dev_type;
+
+ rv = bq27541_write(REG_CTRL, 0x1);
+ rv |= bq27541_read(REG_CTRL, &dev_type);
+
+ if (rv)
+ return rv;
+ return (dev_type == BQ27541_TYPE_ID) ? EC_SUCCESS : EC_ERROR_UNKNOWN;
+}
+
+int battery_device_name(char *device_name, int buf_size)
+{
+ int rv, i, val;
+ int len = MIN(7, buf_size - 1);
+
+ rv = bq27541_read8(REG_DEVICE_NAME_LENGTH, &val);
+ if (rv)
+ return rv;
+ len = MIN(len, val);
+
+ for (i = 0; i < len; ++i) {
+ rv |= bq27541_read8(REG_DEVICE_NAME + i, &val);
+ device_name[i] = val;
+ }
+ device_name[i] = '\0';
+
+ return rv;
+}
+
+int battery_temperature(int *deci_kelvin)
+{
+ return bq27541_read(REG_TEMPERATURE, deci_kelvin);
+}
+
+int battery_voltage(int *voltage)
+{
+ return bq27541_read(REG_VOLTAGE, voltage);
+}
+
+int battery_state_of_charge(int *percent)
+{
+ return bq27541_read(REG_STATE_OF_CHARGE, percent);
+}
+
+int battery_state_of_charge_abs(int *percent)
+{
+ return battery_state_of_charge(percent);
+}
+
+int battery_remaining_capacity(int *capacity)
+{
+ return bq27541_read(REG_REMAINING_CAPACITY, capacity);
+}
+
+int battery_full_charge_capacity(int *capacity)
+{
+ return bq27541_read(REG_FULL_CHARGE_CAPACITY, capacity);
+}
+
+int battery_time_to_empty(int *minutes)
+{
+ return bq27541_read(REG_TIME_TO_EMPTY, minutes);
+}
+
+int battery_time_to_full(int *minutes)
+{
+ return bq27541_read(REG_TIME_TO_FULL, minutes);
+}
+
+int battery_cycle_count(int *count)
+{
+ return bq27541_read(REG_CYCLE_COUNT, count);
+}
+
+int battery_design_capacity(int *capacity)
+{
+ return bq27541_read(REG_DESIGN_CAPACITY, capacity);
+}
+
+int battery_average_current(int *current)
+{
+ int rv = bq27541_read(REG_AVERAGE_CURRENT, current);
+ *current = (int)((int16_t)*current);
+ return rv;
+}
+
+int battery_current(int *current)
+{
+ return battery_average_current(current);
+}
+
+int battery_time_at_rate(int rate, int *minutes)
+{
+ int rv;
+
+ rv = bq27541_write(REG_AT_RATE, rate);
+ if (rv)
+ return rv;
+ return bq27541_read(REG_AT_RATE_TIME_TO_EMPTY, minutes);
+}
+
+int battery_manufacturer_name(char *dest, int size)
+{
+ return EC_ERROR_UNIMPLEMENTED;
+}
+
+int battery_device_chemistry(char *dest, int size)
+{
+ return EC_ERROR_UNIMPLEMENTED;
+}
+
+int battery_serial_number(int *serial)
+{
+ return EC_ERROR_UNIMPLEMENTED;
+}
+
+int battery_desired_voltage(int *voltage)
+{
+ return EC_ERROR_UNIMPLEMENTED;
+}
+
+int battery_design_voltage(int *voltage)
+{
+ return EC_ERROR_UNIMPLEMENTED;
+}
+
+int battery_charging_allowed(int *allowed)
+{
+ int rv, val;
+
+ rv = bq27541_read(REG_FLAGS, &val);
+ if (rv)
+ return rv;
+ *allowed = (val & 0x100);
+ return EC_SUCCESS;
+}
+
+int battery_desired_current(int *current)
+{
+ return EC_ERROR_UNIMPLEMENTED;
+}
+
+int battery_get_mode(int *mode)
+{
+ return EC_ERROR_UNIMPLEMENTED;
+}
+
+int battery_is_in_10mw_mode(int *val)
+{
+ /* Always using mAh unit */
+ *val = 0;
+ return EC_SUCCESS;
+}
+
+int battery_set_10mw_mode(int enabled)
+{
+ /* Not supported by this battery chip */
+ return EC_ERROR_INVAL;
+}