diff options
-rw-r--r-- | common/battery.c | 11 | ||||
-rw-r--r-- | driver/battery/bq27541.c | 7 | ||||
-rw-r--r-- | driver/battery/bq27621_g1.c | 5 | ||||
-rw-r--r-- | driver/battery/max17055.c | 7 | ||||
-rw-r--r-- | driver/battery/mm8013.c | 244 | ||||
-rw-r--r-- | driver/battery/smart.c | 3 | ||||
-rw-r--r-- | include/battery.h | 11 |
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. |