summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/battery.c11
-rw-r--r--driver/battery/bq27541.c7
-rw-r--r--driver/battery/bq27621_g1.c5
-rw-r--r--driver/battery/max17055.c7
-rw-r--r--driver/battery/mm8013.c244
-rw-r--r--driver/battery/smart.c3
-rw-r--r--include/battery.h11
7 files changed, 267 insertions, 21 deletions
diff --git a/common/battery.c b/common/battery.c
index 21e6563b2b..9d7277479c 100644
--- a/common/battery.c
+++ b/common/battery.c
@@ -556,3 +556,14 @@ static void battery_init(void)
DECLARE_HOOK(HOOK_INIT, battery_init, HOOK_PRIO_DEFAULT);
#endif /* HAS_TASK_HOSTCMD */
#endif /* CONFIG_BATTERY_V2 */
+
+__attribute__((weak)) int get_battery_manufacturer_name(char *dest, int size)
+{
+ strzcpy(dest, "<unkn>", size);
+ return EC_SUCCESS;
+}
+
+int battery_manufacturer_name(char *dest, int size)
+{
+ return get_battery_manufacturer_name(dest, size);
+}
diff --git a/driver/battery/bq27541.c b/driver/battery/bq27541.c
index 760a367b9c..b01aef3714 100644
--- a/driver/battery/bq27541.c
+++ b/driver/battery/bq27541.c
@@ -155,13 +155,6 @@ int battery_time_at_rate(int rate, int *minutes)
return bq27541_read(REG_AT_RATE_TIME_TO_EMPTY, minutes);
}
-int battery_manufacturer_name(char *dest, int size)
-{
- strzcpy(dest, "<unkn>", size);
-
- return EC_SUCCESS;
-}
-
int battery_device_chemistry(char *dest, int size)
{
strzcpy(dest, "<unkn>", size);
diff --git a/driver/battery/bq27621_g1.c b/driver/battery/bq27621_g1.c
index c55d452c87..304fe67241 100644
--- a/driver/battery/bq27621_g1.c
+++ b/driver/battery/bq27621_g1.c
@@ -474,11 +474,6 @@ int battery_time_at_rate(int rate, int *minutes)
return EC_ERROR_UNIMPLEMENTED;
}
-int battery_manufacturer_name(char *dest, int size)
-{
- return EC_ERROR_UNIMPLEMENTED;
-}
-
int battery_device_chemistry(char *dest, int size)
{
uint32_t rv;
diff --git a/driver/battery/max17055.c b/driver/battery/max17055.c
index db8b798a3b..d0e0124468 100644
--- a/driver/battery/max17055.c
+++ b/driver/battery/max17055.c
@@ -168,13 +168,6 @@ int battery_time_at_rate(int rate, int *minutes)
return EC_ERROR_UNIMPLEMENTED;
}
-int battery_manufacturer_name(char *dest, int size)
-{
- strzcpy(dest, "<unkn>", size);
-
- return EC_SUCCESS;
-}
-
int battery_device_chemistry(char *dest, int size)
{
strzcpy(dest, "<unkn>", size);
diff --git a/driver/battery/mm8013.c b/driver/battery/mm8013.c
new file mode 100644
index 0000000000..012f3a25bd
--- /dev/null
+++ b/driver/battery/mm8013.c
@@ -0,0 +1,244 @@
+/* Copyright 2019 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 MM8013.
+ */
+
+#include "battery.h"
+#include "battery_smart.h"
+#include "console.h"
+#include "i2c.h"
+#include "mm8013.h"
+#include "timer.h"
+#include "util.h"
+
+#define BATTERY_PACK_INFO_LENGTH 8
+
+/* MM8013 requires a 100us wait time after a read operation. */
+#define I2C_WAIT_TIME 100
+
+static int mm8013_read16(int offset, int *data)
+{
+ int rv;
+
+ *data = 0;
+ rv = i2c_read16(I2C_PORT_BATTERY, MM8013_ADDR, offset, data);
+ usleep(I2C_WAIT_TIME);
+ if (rv)
+ return rv;
+ return EC_SUCCESS;
+}
+
+static int mm8013_read_block(int offset, uint8_t *data, int len)
+{
+ int rv;
+
+ rv = i2c_read_block(I2C_PORT_BATTERY, MM8013_ADDR, offset, data, len);
+ usleep(I2C_WAIT_TIME);
+ if (rv)
+ return rv;
+ return EC_SUCCESS;
+}
+
+static int battery_flag(int *flag)
+{
+ return mm8013_read16(REG_FLAGS, flag);
+}
+
+static int battery_current(int *current)
+{
+ int16_t tmp;
+ int rv;
+
+ rv = mm8013_read_block(REG_AVERAGE_CURRENT,
+ (uint8_t *)&tmp, sizeof(int16_t));
+ if (rv)
+ return rv;
+ *current = tmp;
+
+ return EC_SUCCESS;
+}
+
+int battery_device_name(char *device_name, int buf_size)
+{
+ int rv;
+ char out_buf[BATTERY_PACK_INFO_LENGTH + 1];
+
+ rv = mm8013_read_block(REG_PRODUCT_INFORMATION,
+ (uint8_t *)out_buf, BATTERY_PACK_INFO_LENGTH);
+ if (rv)
+ return rv;
+
+ out_buf[BATTERY_PACK_INFO_LENGTH] = '\0';
+ strzcpy(device_name, out_buf, buf_size);
+
+ return EC_SUCCESS;
+}
+
+int battery_state_of_charge_abs(int *percent)
+{
+ return mm8013_read16(REG_STATE_OF_CHARGE, percent);
+}
+
+int battery_remaining_capacity(int *capacity)
+{
+ return mm8013_read16(REG_REMAINING_CAPACITY, capacity);
+}
+
+int battery_full_charge_capacity(int *capacity)
+{
+ return mm8013_read16(REG_FULL_CHARGE_CAPACITY, capacity);
+}
+
+int battery_time_to_empty(int *minutes)
+{
+ return mm8013_read16(REG_AVERAGE_TIME_TO_EMPTY, minutes);
+}
+
+int battery_time_to_full(int *minutes)
+{
+ return mm8013_read16(REG_AVERAGE_TIME_TO_FULL, minutes);
+}
+
+int battery_cycle_count(int *count)
+{
+ return mm8013_read16(REG_CYCLE_COUNT, count);
+}
+
+int battery_design_capacity(int *capacity)
+{
+ return mm8013_read16(REG_DESIGN_CAPACITY, capacity);
+}
+
+int battery_time_at_rate(int rate, int *minutes)
+{
+ return EC_ERROR_UNIMPLEMENTED;
+}
+
+int battery_device_chemistry(char *dest, int size)
+{
+ strzcpy(dest, "<unkn>", size);
+
+ return EC_SUCCESS;
+}
+
+int battery_serial_number(int *serial)
+{
+ *serial = 0xFFFFFFFF;
+ return EC_SUCCESS;
+}
+
+int battery_design_voltage(int *voltage)
+{
+ *voltage = battery_get_info()->voltage_normal;
+
+ return EC_SUCCESS;
+}
+
+int battery_get_mode(int *mode)
+{
+ return EC_ERROR_UNIMPLEMENTED;
+}
+
+int battery_status(int *status)
+{
+ int rv;
+ int flag = 0;
+
+ *status = 0;
+
+ rv = battery_flag(&flag);
+ if (rv)
+ return rv;
+
+ if (flag & (MM8013_FLAG_OTC | MM8013_FLAG_OTD))
+ *status |= STATUS_OVERTEMP_ALARM;
+ if (flag & MM8013_FLAG_FC)
+ *status |= STATUS_FULLY_CHARGED;
+ if (flag & MM8013_FLAG_DSG)
+ *status |= STATUS_DISCHARGING;
+ if (flag & MM8013_FLAG_BATHI)
+ *status |= STATUS_OVERCHARGED_ALARM;
+
+ return EC_SUCCESS;
+}
+
+enum battery_present battery_is_present(void)
+{
+ int temp;
+
+ if (mm8013_read16(REG_TEMPERATURE, &temp))
+ return BP_NOT_SURE;
+ return BP_YES;
+}
+
+void battery_get_params(struct batt_params *batt)
+{
+ struct batt_params batt_new = {0};
+ int flag = 0;
+
+ /*
+ * Assuming the battery is responsive as long as
+ * mm8013 finds battery is present.
+ */
+ batt_new.is_present = battery_is_present();
+
+ if (batt_new.is_present == BP_YES)
+ batt_new.flags |= BATT_FLAG_RESPONSIVE;
+ else if (batt_new.is_present == BP_NO)
+ /* Battery is not present, gauge won't report useful info. */
+ goto batt_out;
+
+ if (mm8013_read16(REG_TEMPERATURE, &batt_new.temperature))
+ batt_new.flags |= BATT_FLAG_BAD_TEMPERATURE;
+
+ if (mm8013_read16(REG_STATE_OF_CHARGE, &batt_new.state_of_charge))
+ batt_new.flags |= BATT_FLAG_BAD_STATE_OF_CHARGE;
+
+ if (mm8013_read16(REG_VOLTAGE, &batt_new.voltage))
+ batt_new.flags |= BATT_FLAG_BAD_VOLTAGE;
+
+ if (battery_current(&batt_new.current))
+ batt_new.flags |= BATT_FLAG_BAD_CURRENT;
+
+ batt_new.desired_voltage = battery_get_info()->voltage_max;
+ batt_new.desired_current = BATTERY_DESIRED_CHARGING_CURRENT;
+
+ if (battery_remaining_capacity(&batt_new.remaining_capacity))
+ batt_new.flags |= BATT_FLAG_BAD_REMAINING_CAPACITY;
+
+ if (battery_full_charge_capacity(&batt_new.full_capacity))
+ batt_new.flags |= BATT_FLAG_BAD_FULL_CAPACITY;
+
+ if (battery_flag(&flag) && (flag & MM8013_FLAG_CHG))
+ batt_new.flags |= BATT_FLAG_WANT_CHARGE;
+
+ if (battery_status(&batt_new.status))
+ batt_new.flags |= BATT_FLAG_BAD_STATUS;
+
+batt_out:
+ /* Update visible battery parameters */
+ memcpy(batt, &batt_new, sizeof(*batt));
+}
+
+#ifdef CONFIG_CMD_PWR_AVG
+int battery_get_avg_current(void)
+{
+ /* TODO(crbug.com/752320) implement this */
+ return -EC_ERROR_UNIMPLEMENTED;
+}
+
+int battery_get_avg_voltage(void)
+{
+ /* TODO(crbug.com/752320) implement this */
+ return -EC_ERROR_UNIMPLEMENTED;
+}
+#endif /* CONFIG_CMD_PWR_AVG */
+
+/* Wait until battery is totally stable. */
+int battery_wait_for_stable(void)
+{
+ /* TODO(phoenixshen): Implement this function. */
+ return EC_SUCCESS;
+}
diff --git a/driver/battery/smart.c b/driver/battery/smart.c
index 1bdde9bf1e..7a494e8eab 100644
--- a/driver/battery/smart.c
+++ b/driver/battery/smart.c
@@ -280,8 +280,7 @@ test_mockable int battery_manufacture_date(int *year, int *month, int *day)
return EC_SUCCESS;
}
-/* Read manufacturer name */
-test_mockable int battery_manufacturer_name(char *dest, int size)
+int get_battery_manufacturer_name(char *dest, int size)
{
return sb_read_string(SB_MANUFACTURER_NAME, dest, size);
}
diff --git a/include/battery.h b/include/battery.h
index 96eb1ea705..30ec6fdab7 100644
--- a/include/battery.h
+++ b/include/battery.h
@@ -302,6 +302,17 @@ int battery_serial_number(int *serial);
int battery_manufacturer_name(char *dest, int size);
/**
+ * Read manufacturer name.
+ *
+ * This can be overridden to return a chip or board custom string.
+ *
+ * @param dest Destination buffer.
+ * @param size Length of destination buffer in chars.
+ * @return non-zero if error.
+ */
+int get_battery_manufacturer_name(char *dest, int size);
+
+/**
* Read device name.
*
* @param dest Destination buffer.