diff options
Diffstat (limited to 'driver/battery')
-rw-r--r-- | driver/battery/bq20z453.c | 35 | ||||
-rw-r--r-- | driver/battery/bq27541.c | 432 | ||||
-rw-r--r-- | driver/battery/bq27621_g1.c | 747 | ||||
-rw-r--r-- | driver/battery/bq4050.c | 39 | ||||
-rw-r--r-- | driver/battery/max17055.c | 692 | ||||
-rw-r--r-- | driver/battery/max17055.h | 250 | ||||
-rw-r--r-- | driver/battery/mm8013.c | 250 | ||||
-rw-r--r-- | driver/battery/mm8013.h | 40 | ||||
-rw-r--r-- | driver/battery/smart.c | 695 |
9 files changed, 0 insertions, 3180 deletions
diff --git a/driver/battery/bq20z453.c b/driver/battery/bq20z453.c deleted file mode 100644 index 3cd16e8b8f..0000000000 --- a/driver/battery/bq20z453.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright 2012 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. - * - * Smart battery driver for BQ20Z453. - */ - -#include "battery_smart.h" -#include "hooks.h" -#include "host_command.h" - -#define PARAM_CUT_OFF 0x0010 - -static void cutoff(void) -{ - /* Claim i2c and send cutoff command to battery. */ - sb_write(SB_MANUFACTURER_ACCESS, PARAM_CUT_OFF); -} -DECLARE_DEFERRED(cutoff); - -enum ec_status battery_command_cut_off(struct host_cmd_handler_args *args) -{ - /* - * Queue battery cutoff. This must be deferred so we can send the - * response to the host first. Some platforms (snow) share an I2C bus - * between the EC, AP, and battery, so we need the host to complete the - * transaction and release the I2C bus before we'll be abl eto send the - * cutoff command. - */ - hook_call_deferred(&cutoff_data, 1000); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_BATTERY_CUT_OFF, battery_command_cut_off, - EC_VER_MASK(0)); diff --git a/driver/battery/bq27541.c b/driver/battery/bq27541.c deleted file mode 100644 index b39147092f..0000000000 --- a/driver/battery/bq27541.c +++ /dev/null @@ -1,432 +0,0 @@ -/* Copyright 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/BQ27542/BQ27741/BQ27742. - */ - -#include "battery.h" -#include "battery_smart.h" -#include "console.h" -#include "extpower.h" -#include "hooks.h" -#include "i2c.h" -#include "util.h" - -#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 - -#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_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; - -static int bq27541_read(int offset, int *data) -{ - return i2c_read16(I2C_PORT_BATTERY, BQ27541_ADDR, offset, data); -} - -static int bq27541_read8(int offset, int *data) -{ - return i2c_read8(I2C_PORT_BATTERY, BQ27541_ADDR, offset, data); -} - -static int bq27541_write(int offset, int data) -{ - return i2c_write16(I2C_PORT_BATTERY, BQ27541_ADDR, offset, data); -} - -int bq27541_probe(void) -{ - int rv; - - 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; - return EC_ERROR_UNKNOWN; -} - -static void probe_type_id(void) -{ - bq27541_probe(); -} -DECLARE_HOOK(HOOK_INIT, probe_type_id, HOOK_PRIO_DEFAULT); - -int battery_device_name(char *device_name, int buf_size) -{ - int rv, i, val; - int len = MIN(7, buf_size - 1); - - if (battery_type_id == BQ27742_TYPE_ID) { - /* No device name register available */ - 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) - 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_state_of_charge_abs(int *percent) -{ - return bq27541_read(REG_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_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; - return bq27541_read(REG_AT_RATE_TIME_TO_EMPTY, minutes); -} - -int battery_device_chemistry(char *dest, int size) -{ - strzcpy(dest, "<unkn>", size); - - return EC_SUCCESS; -} - -int battery_serial_number(int *serial) -{ - *serial = 0x0BAD0BAD; - - return EC_SUCCESS; -} - -int battery_manufacture_date(int *year, int *month, int *day) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_design_voltage(int *voltage) -{ - *voltage = battery_get_info()->voltage_normal; - - return EC_SUCCESS; -} - -/** - * Check if battery allows charging. - * - * @param allowed Non-zero if charging allowed; zero if not allowed. - * @return non-zero if error. - */ -static int battery_charging_allowed(int *allowed) -{ - int rv, val; - - rv = bq27541_read(REG_FLAGS, &val); - if (rv) - return rv; - if (battery_type_id == BQ27541_TYPE_ID || - battery_type_id == BQ27741_TYPE_ID) - *allowed = (val & 0x100); - else /* BQ27742_TYPE_ID, BQ27542_TYPE_ID */ - *allowed = (val & 0x8); - - 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; - 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; -} - -enum battery_present battery_is_present(void) -{ - int v; - if (bq27541_read(REG_TEMPERATURE, &v)) - return BP_NO; - return BP_YES; -} - -void battery_get_params(struct batt_params *batt) -{ - int v; - const uint32_t flags_to_check = BATT_FLAG_BAD_TEMPERATURE | - BATT_FLAG_BAD_STATE_OF_CHARGE | - BATT_FLAG_BAD_VOLTAGE | - BATT_FLAG_BAD_CURRENT; - - /* Reset flags */ - batt->flags = 0; - - if (bq27541_read(REG_TEMPERATURE, &batt->temperature)) - batt->flags |= BATT_FLAG_BAD_TEMPERATURE; - - if (bq27541_read8(REG_STATE_OF_CHARGE, &v) && fake_state_of_charge < 0) - batt->flags |= BATT_FLAG_BAD_STATE_OF_CHARGE; - - batt->state_of_charge = fake_state_of_charge >= 0 ? - fake_state_of_charge : v; - - if (bq27541_read(REG_VOLTAGE, &batt->voltage)) - batt->flags |= BATT_FLAG_BAD_VOLTAGE; - - v = 0; - if (bq27541_read(REG_AVERAGE_CURRENT, &v)) - 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; - - /* If any of those reads worked, the battery is responsive */ - if ((batt->flags & flags_to_check) != flags_to_check) { - batt->flags |= BATT_FLAG_RESPONSIVE; - batt->is_present = BP_YES; - } else { - - /* If all of those reads error, the battery is not present */ - batt->is_present = BP_NO; - } - - /* update the battery status */ - if (battery_status(&batt->status)) - batt->flags |= BATT_FLAG_BAD_STATUS; - - v = 0; - if (battery_charging_allowed(&v)) { - batt->flags |= BATT_FLAG_BAD_ANY; - } else if (v) { - batt->flags |= BATT_FLAG_WANT_CHARGE; - - /* - * Desired voltage and current are not provided by the battery. - * So ask for battery's max voltage and an arbitrarily large - * current. - */ - batt->desired_voltage = battery_get_info()->voltage_max; - batt->desired_current = 4096; - } -} - -/* Wait until battery is totally stable */ -int battery_wait_for_stable(void) -{ - /* TODO(crosbug.com/p/30426): implement me */ - return EC_SUCCESS; -} - -#ifdef CONFIG_BATTERY_REVIVE_DISCONNECT -/* - * Check if battery is in disconnect state, a state entered by pulling - * BATT_DISCONN_N low, and clear that state if we have external power plugged - * and no battery faults are detected. Disconnect state resembles battery - * shutdown mode, but extra steps must be taken to get the battery out of this - * mode. - */ -enum battery_disconnect_state battery_get_disconnect_state(void) -{ - int val, rv; - /* - * Take note if we find that the battery isn't in disconnect state, - * and always return NOT_DISCONNECTED without probing the battery. - * This assumes the battery will not go to disconnect state during - * runtime. - */ - static int not_disconnected; - - if (not_disconnected) - return BATTERY_NOT_DISCONNECTED; - - if (extpower_is_present()) { - /* Check DSG_OFF bit */ - rv = bq27541_read(REG_PROTECTOR, &val); - if (rv) - return BATTERY_DISCONNECT_ERROR; - if (!(val & BIT(6))) { - not_disconnected = 1; - return BATTERY_NOT_DISCONNECTED; - } - - /* DSG_OFF is set. Verify this is not due to a safety fault */ - if (val & 0x3f) - return BATTERY_DISCONNECT_ERROR; - rv = bq27541_read(REG_FLAGS, &val); - if (rv) - return BATTERY_DISCONNECT_ERROR; - if (val & 0xfc60) - return BATTERY_DISCONNECT_ERROR; - return BATTERY_DISCONNECTED; - } - not_disconnected = 1; - return BATTERY_NOT_DISCONNECTED; -} -#endif /* CONFIG_BATTERY_REVIVE_DISCONNECT */ - -static int command_battfake(int argc, char **argv) -{ - char *e; - int v; - - if (argc == 2) { - v = strtoi(argv[1], &e, 0); - if (*e || v < -1 || v > 100) - return EC_ERROR_PARAM1; - - fake_state_of_charge = v; - } - - if (fake_state_of_charge >= 0) - ccprintf("Fake batt %d%%\n", - fake_state_of_charge); - - return EC_SUCCESS; -} -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, ¤t); - return current; -} - -int battery_get_avg_voltage(void) -{ - /* BQ27541 does not have this parameter */ - return -EC_ERROR_UNIMPLEMENTED; -} -#endif /* CONFIG_CMD_PWR_AVG */ - diff --git a/driver/battery/bq27621_g1.c b/driver/battery/bq27621_g1.c deleted file mode 100644 index dbda6f9c65..0000000000 --- a/driver/battery/bq27621_g1.c +++ /dev/null @@ -1,747 +0,0 @@ -/* Copyright 2014 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 BQ27621-G1 - */ - -#include "battery.h" -#include "console.h" -#include "extpower.h" -#include "hooks.h" -#include "i2c.h" -#include "util.h" -#include "timer.h" - -#define BQ27621_ADDR_FLAGS 0x55 -#define BQ27621_TYPE_ID 0x0621 - -#define REG_CTRL 0x00 -#define REG_TEMPERATURE 0x02 -#define REG_VOLTAGE 0x04 -#define REG_FLAGS 0x06 -#define REG_NOMINAL_CAPACITY 0x08 -#define REG_FULL_AVAILABLE_CAPACITY 0x0a -#define REG_REMAINING_CAPACITY 0x0c -#define REG_FULL_CHARGE_CAPACITY 0x0e -#define REG_EFFECTIVE_CURRENT 0x10 -#define REG_AVERAGE_POWER 0x18 -#define REG_STATE_OF_CHARGE 0x1c -#define REG_INTERNAL_TEMPERATURE 0x1e -#define REG_REMAINING_CAPACITY_UNFILTERED 0x28 -#define REG_REMAINING_CAPACITY_FILTERED 0x2a -#define REG_FULL_CHARGE_CAPACITY_UNFILTERED 0x28 -#define REG_FULL_CHARGE_CAPACITY_FILTERED 0x2a -#define REG_STATE_OF_CHARGE_UNFILTERED 0x30 -#define REG_OP_CONFIG 0x3a -#define REG_DESIGN_CAPACITY 0x3c -#define REG_DATA_CLASS 0x3e -#define REG_DATA_BLOCK 0x3f -#define REG_BLOCK_DATA_CHECKSUM 0x60 -#define REG_BLOCK_DATA_CONTROL 0x61 - -#define REGISTERS_BLOCK_OFFSET 64 -#define REGISTERS_BLOCK_OP_CONFIG 0x40 -#define REGISTERS_BLOCK_OP_CONFIG_B 0x42 -#define REGISTERS_BLOCK_DF_VERSION 0x43 - -/* State block */ -#define STATE_BLOCK_OFFSET 82 -#define STATE_BLOCK_DESIGN_CAPACITY 0x43 -#define STATE_BLOCK_DESIGN_ENERGY 0x45 -#define STATE_BLOCK_TERMINATE_VOLTAGE 0x49 -#define STATE_BLOCK_TAPER_RATE 0x54 - -/* BQ27621 Control subcommands */ -#define CONTROL_CONTROL_STATUS 0x00 -#define CONTROL_DEVICE_TYPE 0x01 -#define CONTROL_FW_VERSION 0x02 -#define CONTROL_PREV_MACWRITE 0x07 -#define CONTROL_CHEM_ID 0x08 -#define CONTROL_BAT_INSERT 0x0C -#define CONTROL_BAT_REMOVE 0x0D -#define CONTROL_TOGGLE_POWERMIN 0x10 -#define CONTROL_SET_HIBERNATE 0x11 -#define CONTROL_CLEAR_HIBERNATE 0x12 -#define CONTROL_SET_CFGUPDATE 0x13 -#define CONTROL_SHUTDOWN_ENABLE 0x1B -#define CONTROL_SHUTDOWN 0x1C -#define CONTROL_SEALED 0x20 -#define CONTROL_TOGGLE_GPOUT 0x23 -#define CONTROL_ALT_CHEM1 0x31 -#define CONTROL_ALT_CHEM2 0x32 -#define CONTROL_RESET 0x41 -#define CONTROL_SOFT_RESET 0x42 -#define CONTROL_EXIT_CFGUPDATE 0x43 -#define CONTROL_EXIT_RESIM 0x44 -#define CONTROL_UNSEAL 0x8000 - -/* BQ27621 Status bits */ -#define STATUS_SHUTDOWNEN 0x8000 -#define STATUS_WDRESET 0x4000 -#define STATUS_SS 0x2000 -#define STATUS_CALMODE 0x1000 -#define STATUS_OCVCMDCOMP 0x0200 -#define STATUS_OCVFAIL 0x0100 -#define STATUS_INITCOMP 0x0080 -#define STATUS_HIBERNATE 0x0040 -#define STATUS_POWERMIN 0x0020 -#define STATUS_SLEEP 0x0010 -#define STATUS_LDMD 0x0008 -#define STATUS_CHEMCHNG 0x0001 - -/* BQ27621 Flags bits */ -#define FLAGS_OT 0x8000 -#define FLAGS_UT 0x4000 -#define FLAGS_FC 0x0200 -#define FLAGS_CHG 0x0100 -#define FLAGS_OCVTAKEN 0x0080 -#define FLAGS_ITPOR 0x0020 -#define FLAGS_CFGUPD 0x0010 -#define FLAGS_BAT_DET 0x0008 -#define FLAGS_SOC1 0x0004 -#define FLAGS_SOCF 0x0002 -#define FLAGS_DSG 0x0001 - -/* - * There are some parameters that need to be defined in the board file: - * BQ27621_TOGGLE_POWER_MIN - Put it in minimum power mode - * (may affect I2C timing) - * BQ27621_DESIGN_CAPACITY - mAh - * BQ27621_DESIGN_ENERGY - Design Capacity x 3.7 - * BQ27621_TERMINATE_VOLTAGE - mV - * BQ27621_TAPER_CURRENT - mA - * BQ27621_CHEM_ID - 0x1202 (DEFAULT) 0x1210 (ALT_CHEM1) - * 0x354 (ALT_CHEM2) - * - * For extra large or extra small batteries, this driver scales everything but - * voltages. The recommended range is 150mAh - 6Ah - * - */ - -#define BQ27621_SCALE_FACTOR (BQ27621_DESIGN_CAPACITY < 150 ? 10.0 : \ - (BQ27621_DESIGN_CAPACITY > 6000 ? 0.1 : 1)) - -#define BQ27621_UNSCALE(x) (BQ27621_SCALE_FACTOR == 10 ? (x) / 10 : \ - (BQ27621_SCALE_FACTOR == 0.1 ? (x) * 10 : (x))) - -#define BQ27621_TAPER_RATE ((int)(BQ27621_DESIGN_CAPACITY/ \ - (0.1 * BQ27621_TAPER_CURRENT))) - -#define BQ27621_SCALED_DESIGN_CAPACITY ((int)(BQ27621_DESIGN_CAPACITY * \ - BQ27621_SCALE_FACTOR)) -#define BQ27621_SCALED_DESIGN_ENERGY ((int)(BQ27621_DESIGN_CAPACITY * \ - BQ27621_SCALE_FACTOR)) - -/* - *Everything is LSB first. Parameters need to be converted. - * - * The values from the data sheet are already LSB-first. - */ - -#define ENDIAN_SWAP_2B(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8)) -#define DESIGN_CAPACITY ENDIAN_SWAP_2B(BQ27621_SCALED_DESIGN_CAPACITY) -#define DESIGN_ENERGY ENDIAN_SWAP_2B(BQ27621_SCALED_DESIGN_ENERGY) -#define TAPER_RATE ENDIAN_SWAP_2B(BQ27621_TAPER_RATE) -#define TERMINATE_VOLTAGE ENDIAN_SWAP_2B(BQ27621_TERMINATE_VOLTAGE) - -struct battery_info battery_params; - -static int bq27621_read(int offset, int *data) -{ - return i2c_read16(I2C_PORT_BATTERY, BQ27621_ADDR, offset, data); -} - -static int bq27621_read8(int offset, int *data) -{ - return i2c_read8(I2C_PORT_BATTERY, BQ27621_ADDR, offset, data); -} - -static int bq27621_write(int offset, int data) -{ - return i2c_write16(I2C_PORT_BATTERY, BQ27621_ADDR, offset, data); -} - -static int bq27621_write8(int offset, int data) -{ - return i2c_write8(I2C_PORT_BATTERY, BQ27621_ADDR, offset, data); -} - -static int bq27621_probe(void) -{ - int rv; - int battery_type_id; - - /* Delays need to be added for correct operation at > 100Kbps */ - ASSERT(i2c_ports[I2C_PORT_BATTERY].kbps <= 100); - - rv = bq27621_write(REG_CTRL, CONTROL_DEVICE_TYPE); - rv |= bq27621_read(REG_CTRL, &battery_type_id); - - if (rv) - return rv; - if (battery_type_id == BQ27621_TYPE_ID) { - battery_params.voltage_max = BATTERY_VOLTAGE_MAX; - battery_params.voltage_normal = BATTERY_VOLTAGE_NORMAL; - battery_params.voltage_min = BATTERY_VOLTAGE_MIN; - return EC_SUCCESS; - } - return EC_ERROR_UNKNOWN; -} - -static inline int bq27621_unseal(void) -{ - return bq27621_write(REG_CTRL, CONTROL_UNSEAL) | - bq27621_write(REG_CTRL, CONTROL_UNSEAL); -} - -static int bq27621_enter_config_update(void) -{ - int tries, flags = 0, rv = EC_SUCCESS; - - /* Enter Config Update Mode (Can take up to a second) */ - for (tries = 2000; tries > 0 && !(flags & FLAGS_CFGUPD) && - (rv == EC_SUCCESS); tries--) { - rv |= bq27621_write(REG_CTRL, CONTROL_SET_CFGUPDATE); - rv |= bq27621_read(REG_FLAGS, &flags); - } - - if (tries == 0) - return EC_ERROR_TIMEOUT; - else - return EC_SUCCESS; -} - -static int bq27621_enter_block_mode(int block) -{ - int rv; - rv = bq27621_write8(REG_BLOCK_DATA_CONTROL, 0); - rv |= bq27621_write8(REG_DATA_CLASS, block); - rv |= bq27621_write8(REG_DATA_BLOCK, 0); - udelay(500); /* Shouldn't be needed, doesn't work without it. */ - return rv; -} - -static int bq27621_seal(void) -{ - int rv = 0; - int status = 0, param = 0, checksum = 0; - - rv |= bq27621_write(REG_CTRL, CONTROL_CONTROL_STATUS); - rv |= bq27621_read(REG_CTRL, &status); - - if (status & STATUS_SS) /* Already sealed */ - return EC_SUCCESS; - - /* Enter Config Update Mode */ - rv = bq27621_enter_config_update(); - - if (rv) - return rv; - - /* Set up block RAM update */ - rv = bq27621_enter_block_mode(REGISTERS_BLOCK_OFFSET); - - if (rv) - return rv; - - rv = bq27621_read8(REG_BLOCK_DATA_CHECKSUM, &checksum); - - if (rv) - return rv; - - checksum = 0xff - checksum; - - rv = bq27621_read8(REGISTERS_BLOCK_OP_CONFIG_B, ¶m); - checksum -= param; /* 1B */ - - param |= 1<<5; /* Set DEF_SEAL */ - - rv = bq27621_write8(REGISTERS_BLOCK_OP_CONFIG_B, param); - checksum += param; /* 1B */ - - checksum = 0xff - (0xff & checksum); - - rv = bq27621_write8(REG_BLOCK_DATA_CHECKSUM, checksum); - - if (rv) - return rv; - - /* Exit Update */ - rv = bq27621_write(REG_CTRL, CONTROL_SOFT_RESET); - - return rv; -} - -#define CHECKSUM_2B(x) ((x & 0xff) + ((x>>8) & 0xff)) - -static int bq27621_init(void) -{ - int rv; - int status = 0, param = 0, checksum = 0; - - rv = bq27621_probe(); - - if (rv) - return rv; - - /* Unseal the device if necessary */ - rv |= bq27621_write(REG_CTRL, CONTROL_CONTROL_STATUS); - rv |= bq27621_read(REG_CTRL, &status); - - if (status & STATUS_SS) - rv |= bq27621_unseal(); - - if (rv) - return rv; - - /* Select the alternate chemistry if needed */ - rv = bq27621_write(REG_CTRL, CONTROL_CHEM_ID); - rv |= bq27621_read(REG_CTRL, ¶m); - - if (param != BQ27621_CHEM_ID) { /* Change needed */ - - if (BQ27621_CHEM_ID == 0x1202) { /* Return to default */ - rv |= bq27621_write(REG_CTRL, CONTROL_RESET); - } else { - rv |= bq27621_enter_config_update(); - - if (BQ27621_CHEM_ID == 0x1210) - rv |= bq27621_write(REG_CTRL, - CONTROL_ALT_CHEM1); - if (BQ27621_CHEM_ID == 0x0354) - rv |= bq27621_write(REG_CTRL, - CONTROL_ALT_CHEM2); - - /* - * The datasheet recommends checking the status here. - * - * If the CHEMCHG is active, it wasn't successful. - * - * There's no recommendation for what to do if it isn't. - */ - - rv |= bq27621_write(REG_CTRL, CONTROL_EXIT_CFGUPDATE); - } - } - - if (rv) - return rv; - - rv = bq27621_enter_config_update(); - - if (rv) - return rv; - - /* Set up block RAM update */ - rv = bq27621_enter_block_mode(STATE_BLOCK_OFFSET); - - if (rv) - return rv; - - rv = bq27621_read8(REG_BLOCK_DATA_CHECKSUM, &checksum); - if (rv) - return rv; - - checksum = 0xff - checksum; - - rv = bq27621_read(STATE_BLOCK_DESIGN_CAPACITY, ¶m); - checksum -= CHECKSUM_2B(param); - - rv |= bq27621_read(STATE_BLOCK_DESIGN_ENERGY, ¶m); - checksum -= CHECKSUM_2B(param); - - rv |= bq27621_read(STATE_BLOCK_TERMINATE_VOLTAGE, ¶m); - checksum -= CHECKSUM_2B(param); - - rv |= bq27621_read(STATE_BLOCK_TAPER_RATE, ¶m); - checksum -= CHECKSUM_2B(param); - - if (rv) - return rv; - - rv = bq27621_write(STATE_BLOCK_DESIGN_CAPACITY, DESIGN_CAPACITY); - checksum += CHECKSUM_2B(DESIGN_CAPACITY); - - rv |= bq27621_write(STATE_BLOCK_DESIGN_ENERGY, DESIGN_ENERGY); - checksum += CHECKSUM_2B(DESIGN_ENERGY); - - rv |= bq27621_write(STATE_BLOCK_TERMINATE_VOLTAGE, TERMINATE_VOLTAGE); - checksum += CHECKSUM_2B(TERMINATE_VOLTAGE); - - rv |= bq27621_write(STATE_BLOCK_TAPER_RATE, TAPER_RATE); - checksum += CHECKSUM_2B(TAPER_RATE); - - checksum = 0xff - (0xff & checksum); - - - if (rv) - return rv; - - rv = bq27621_write8(REG_BLOCK_DATA_CHECKSUM, checksum); - - rv |= bq27621_write(REG_CTRL, CONTROL_SOFT_RESET); - - if (rv) - return rv; - - bq27621_seal(); - - return rv; -} - -static void probe_type_id_init(void) -{ - int rv = EC_SUCCESS; - - rv = bq27621_probe(); - - if (rv) - return; - - rv = bq27621_init(); - - if (rv) { /* Try it once more */ - rv = bq27621_write(REG_CTRL, CONTROL_RESET); - rv |= bq27621_init(); - } -} - -DECLARE_HOOK(HOOK_INIT, probe_type_id_init, HOOK_PRIO_DEFAULT); - -/* Some of the functions to make this battery "smart" */ - -int battery_device_name(char *device_name, int buf_size) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_state_of_charge_abs(int *percent) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_remaining_capacity(int *capacity) -{ - int scaled_value, err_code; - - err_code = bq27621_read(REG_REMAINING_CAPACITY, &scaled_value); - - *capacity = BQ27621_UNSCALE(scaled_value); - - return err_code; -} - -int battery_full_charge_capacity(int *capacity) -{ - int scaled_value, err_code; - - err_code = bq27621_read(REG_FULL_CHARGE_CAPACITY, &scaled_value); - - *capacity = BQ27621_UNSCALE(scaled_value); - - return err_code; -} - -int battery_time_to_empty(int *minutes) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_time_to_full(int *minutes) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_cycle_count(int *count) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_design_capacity(int *capacity) -{ - int scaled_value, err_code; - - err_code = bq27621_read(REG_DESIGN_CAPACITY, &scaled_value); - - *capacity = BQ27621_UNSCALE(scaled_value); - - return err_code; -} - -int battery_time_at_rate(int rate, int *minutes) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_device_chemistry(char *dest, int size) -{ - uint32_t rv; - int param; - - rv = bq27621_write(REG_CTRL, CONTROL_CHEM_ID); - rv |= bq27621_read(REG_CTRL, ¶m); - - if (param == 0x1202) - strzcpy(dest, "0x1202 (default)", size); - if (param == 0x1210) - strzcpy(dest, "0x1210 (ALT_CHEM1)", size); - if (param == 0x0354) - strzcpy(dest, "0x0354 (ALT_CHEM2)", size); - - return EC_SUCCESS; -} - -int battery_serial_number(int *serial) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_manufacture_date(int *year, int *month, int *day) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_design_voltage(int *voltage) -{ - *voltage = BATTERY_VOLTAGE_NORMAL; - - return EC_SUCCESS; -} - -int battery_get_mode(int *mode) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_status(int *status) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -enum battery_present battery_is_present(void) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -void battery_get_params(struct batt_params *batt) -{ - /* Reset flags */ - batt->flags = 0; - - if (bq27621_read(REG_TEMPERATURE, &batt->temperature)) - batt->flags |= BATT_FLAG_BAD_TEMPERATURE; - else - batt->flags |= BATT_FLAG_RESPONSIVE; /* Battery is responding */ - - if (bq27621_read8(REG_STATE_OF_CHARGE, &batt->state_of_charge)) - batt->flags |= BATT_FLAG_BAD_STATE_OF_CHARGE; - - if (bq27621_read(REG_VOLTAGE, &batt->voltage)) - batt->flags |= BATT_FLAG_BAD_VOLTAGE; - - batt->flags |= BATT_FLAG_BAD_CURRENT; - batt->current = 0; - - /* Default to not desiring voltage and current */ - batt->desired_voltage = batt->desired_current = 0; -} - -/* Wait until battery is totally stable */ -int battery_wait_for_stable(void) -{ - /* TODO(crosbug.com/p/30426): implement me */ - return EC_SUCCESS; -} - -#ifdef CONFIG_CMD_BATDEBUG - #define CPRINTF(format, args...) cprintf(CC_I2C, format, ## args) -#else - #define CPRINTF(format, args...) -#endif - -#ifdef CONFIG_CMD_BATDEBUG - -static int command_fgunseal(int argc, char **argv) -{ - int rv = EC_SUCCESS; - - if (argc > 1) - return EC_ERROR_PARAM_COUNT; - - rv = bq27621_unseal(); - - return rv; -} - -DECLARE_CONSOLE_COMMAND(fgunseal, command_fgunseal, - "", - "Unseal the fg"); - -static int command_fgseal(int argc, char **argv) -{ - int rv = EC_SUCCESS; - - if (argc > 1) - return EC_ERROR_PARAM_COUNT; - - rv = bq27621_seal(); - - return rv; -} - -DECLARE_CONSOLE_COMMAND(fgseal, command_fgseal, - "", - "Seal the fg"); - -static int command_fginit(int argc, char **argv) -{ - int rv = EC_SUCCESS; - int force = 0; - int flags = 0; - int unconfigured = 0; - char *e; - - if (argc > 2) - return EC_ERROR_PARAM_COUNT; - - if (argc == 2) { - force = strtoi(argv[1], &e, 0); - if (*e) - return EC_ERROR_PARAM1; - } - - rv = bq27621_read(REG_FLAGS, &flags); - unconfigured = flags & FLAGS_ITPOR; - - if (!unconfigured && force) { - rv |= bq27621_write(REG_CTRL, CONTROL_RESET); - unconfigured = (rv == EC_SUCCESS); - } - - if (unconfigured) - rv |= bq27621_init(); - - return rv; -} - -DECLARE_CONSOLE_COMMAND(fginit, command_fginit, - "[force]", - "Initialize the fg"); - -static int command_fgprobe(int argc, char **argv) -{ - int rv = EC_SUCCESS; - - if (argc != 1) - return EC_ERROR_PARAM_COUNT; - - rv = bq27621_probe(); - - return rv; -} - -DECLARE_CONSOLE_COMMAND(fgprobe, command_fgprobe, - "", - "Probe the fg"); - -static int command_fgrd(int argc, char **argv) -{ - int cmd, len; - int rv = EC_SUCCESS; - int data; - char *e; - - if (argc < 3) - return EC_ERROR_PARAM_COUNT; - - cmd = strtoi(argv[1], &e, 0); - if (*e) - return EC_ERROR_PARAM1; - - len = strtoi(argv[2], &e, 0); - if (*e) - return EC_ERROR_PARAM2; - - if (len == 2) - rv = bq27621_read(cmd, &data); - else if (len == 1) - rv = bq27621_read8(cmd, &data); - else - return EC_ERROR_PARAM2; - - CPRINTF("Read %d bytes @0xaa %0x: 0x%0x\n", len, cmd, data); - - return rv; -} - -DECLARE_CONSOLE_COMMAND(fgrd, command_fgrd, - "cmd len", - "Read _len_ words from the fg"); - -static int command_fgcmd(int argc, char **argv) -{ - int cmd, data, byte = 0; - char *e; - - if (argc < 3 || argc > 4) - return EC_ERROR_PARAM_COUNT; - - cmd = strtoi(argv[1], &e, 0); - if (*e) - return EC_ERROR_PARAM1; - - data = strtoi(argv[2], &e, 0); - if (*e) - return EC_ERROR_PARAM2; - - if (argc >= 4) { - byte = strtoi(argv[3], &e, 0); - if (*e) - return EC_ERROR_PARAM3; - } - - if (byte) { - CPRINTF("Write a byte @0xaa %0x: 0x%0x\n", cmd, data); - return bq27621_write8(cmd, data); - } else { - CPRINTF("Write 2 bytes @0xaa %0x: 0x%0x\n", cmd, data); - return bq27621_write(cmd, data); - } - -} - -DECLARE_CONSOLE_COMMAND(fgcmd, command_fgcmd, - "cmd data [byte]", - "Send a cmd to the fg"); - -static int command_fgcmdrd(int argc, char **argv) -{ - int cmd, data, val; - int rv = EC_SUCCESS; - char *e; - - if (argc < 3) - return EC_ERROR_PARAM_COUNT; - - cmd = strtoi(argv[1], &e, 0); - if (*e) - return EC_ERROR_PARAM1; - - data = strtoi(argv[2], &e, 0); - if (*e) - return EC_ERROR_PARAM2; - - rv = bq27621_write(cmd, data); - rv |= bq27621_read(cmd, &val); - - CPRINTF("Read: @0xaa (%x %x) %x\n", cmd, data, val); - return rv; -} - -DECLARE_CONSOLE_COMMAND(fgcmdrd, command_fgcmdrd, - "cmd data", - "Send a 2-byte cmd to the fg, read back the 2-byte result"); - -#endif /* CONFIG_CMD_BATDEBUG */ - diff --git a/driver/battery/bq4050.c b/driver/battery/bq4050.c deleted file mode 100644 index 684ade47e6..0000000000 --- a/driver/battery/bq4050.c +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright 2018 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. - * - * Smart battery driver for TI BQ4050 family, including BQ40Z50 (and -R1, -R2), - * BQ40Z552, and BQ40Z60. - */ - -#include "battery_smart.h" -#include "util.h" - -#include <stdint.h> - -int battery_bq4050_imbalance_mv(void) -{ - /* - * The BQ4050 family can manage up to four cells. In testing it always - * returns a voltage for each cell, regardless of the number of cells - * actually installed in the pack. Unpopulated cells read exactly zero. - */ - static const uint8_t cell_voltage_address[4] = { - 0x3c, 0x3d, 0x3e, 0x3f - }; - int i, res, cell_voltage; - int n_cells = 0; - int max_voltage = 0; - int min_voltage = 0xffff; - - for (i = 0; i != ARRAY_SIZE(cell_voltage_address); ++i) { - res = sb_read(cell_voltage_address[i], &cell_voltage); - if (res == EC_SUCCESS && cell_voltage != 0) { - n_cells++; - max_voltage = MAX(max_voltage, cell_voltage); - min_voltage = MIN(min_voltage, cell_voltage); - } - } - return (n_cells == 0) ? 0 : max_voltage - min_voltage; -} - diff --git a/driver/battery/max17055.c b/driver/battery/max17055.c deleted file mode 100644 index bb0b941937..0000000000 --- a/driver/battery/max17055.c +++ /dev/null @@ -1,692 +0,0 @@ -/* Copyright 2017 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 MAX17055. - */ - -#include "battery.h" -#include "console.h" -#include "extpower.h" -#include "hooks.h" -#include "i2c.h" -#include "max17055.h" -#include "printf.h" -#include "timer.h" -#include "util.h" - -/* Console output macros */ -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) - -/* - * For max17055 to finish battery presence detection, this is the minimal time - * we have to wait since the last POR. LSB = 175ms. - */ -#define RELIABLE_BATT_DETECT_TIME 0x10 - -/* - * Convert the register values to the units that match - * smart battery protocol. - */ - -/* Voltage reg value to mV */ -#define VOLTAGE_CONV(REG) ((REG * 5) >> 6) -/* Current reg value to mA */ -#define CURRENT_CONV(REG) (((REG * 25) >> 4) / BATTERY_MAX17055_RSENSE) -/* Capacity reg value to mAh */ -#define CAPACITY_CONV(REG) (REG * 5 / BATTERY_MAX17055_RSENSE) -/* Time reg value to minute */ -#define TIME_CONV(REG) ((REG * 3) >> 5) -/* Temperature reg value to 0.1K */ -#define TEMPERATURE_CONV(REG) (((REG * 10) >> 8) + 2731) -/* Percentage reg value to 1% */ -#define PERCENTAGE_CONV(REG) (REG >> 8) -/* Cycle count reg value (LSB = 1%) to absolute count (100%) */ -#define CYCLE_COUNT_CONV(REG) ((REG * 5) >> 9) - -/* Useful macros */ -#define MAX17055_READ_DEBUG(offset, ptr_reg) \ - do { \ - if (max17055_read(offset, ptr_reg)) { \ - CPRINTS("%s: failed to read reg %02x", \ - __func__, offset); \ - return; \ - } \ - } while (0) -#define MAX17055_WRITE_DEBUG(offset, reg) \ - do { \ - if (max17055_write(offset, reg)) { \ - CPRINTS("%s: failed to read reg %02x", \ - __func__, offset); \ - return; \ - } \ - } while (0) - -static int fake_state_of_charge = -1; - -static int max17055_read(int offset, int *data) -{ - return i2c_read16(I2C_PORT_BATTERY, MAX17055_ADDR_FLAGS, - offset, data); -} - -static int max17055_write(int offset, int data) -{ - return i2c_write16(I2C_PORT_BATTERY, MAX17055_ADDR_FLAGS, - offset, data); -} - -/* Return 1 if the device id is correct. */ -static int max17055_probe(void) -{ - int dev_id; - - if (max17055_read(REG_DEVICE_NAME, &dev_id)) - return 0; - if (dev_id == MAX17055_DEVICE_ID) - return 1; - return 0; -} - -int battery_device_name(char *device_name, int buf_size) -{ - int dev_id; - int rv; - - rv = max17055_read(REG_DEVICE_NAME, &dev_id); - if (!rv) - snprintf(device_name, buf_size, "0x%04x", dev_id); - - return rv; -} - -int battery_state_of_charge_abs(int *percent) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_remaining_capacity(int *capacity) -{ - int rv; - int reg; - - rv = max17055_read(REG_REMAINING_CAPACITY, ®); - if (!rv) - *capacity = CAPACITY_CONV(reg); - return rv; -} - -int battery_full_charge_capacity(int *capacity) -{ - int rv; - int reg; - - rv = max17055_read(REG_FULL_CHARGE_CAPACITY, ®); - if (!rv) - *capacity = CAPACITY_CONV(reg); - return rv; -} - -int battery_time_to_empty(int *minutes) -{ - int rv; - int reg; - - rv = max17055_read(REG_TIME_TO_EMPTY, ®); - if (!rv) - *minutes = TIME_CONV(reg); - return rv; -} - -int battery_time_to_full(int *minutes) -{ - int rv; - int reg; - - rv = max17055_read(REG_TIME_TO_FULL, ®); - if (!rv) - *minutes = TIME_CONV(reg); - return rv; -} - -int battery_cycle_count(int *count) -{ - int rv; - int reg; - - rv = max17055_read(REG_CYCLE_COUNT, ®); - if (!rv) - *count = CYCLE_COUNT_CONV(reg); - return rv; -} - -int battery_design_capacity(int *capacity) -{ - int rv; - int reg; - - rv = max17055_read(REG_DESIGN_CAPACITY, ®); - if (!rv) - *capacity = CAPACITY_CONV(reg); - return rv; -} - -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) -{ - /* TODO(philipchen): Implement this function. */ - *serial = 0xFFFFFFFF; - return EC_SUCCESS; -} - -int battery_manufacture_date(int *year, int *month, int *day) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -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 reg; - - *status = 0; - - rv = max17055_read(REG_FSTAT, ®); - if (rv) - return rv; - if (reg & FSTAT_FQ) - *status |= BATTERY_FULLY_CHARGED; - - rv = max17055_read(REG_AVERAGE_CURRENT, ®); - if (rv) - return rv; - if (reg >> 15) - *status |= BATTERY_DISCHARGING; - - return EC_SUCCESS; -} - -enum battery_present battery_is_present(void) -{ - int reg = 0; - static uint8_t batt_pres_sure; - - if (max17055_read(REG_STATUS, ®)) - return BP_NOT_SURE; - - if (reg & STATUS_BST) - return BP_NO; - - if (!batt_pres_sure) { - /* - * The battery detection result is not reliable within - * ~2.8 secs since POR. - */ - if (!max17055_read(REG_TIMERH, ®)) { - /* - * The LSB of TIMERH reg is 3.2 hrs. If the reg has a - * nonzero value, battery detection must have been - * settled. - */ - if (reg) { - batt_pres_sure = 1; - return BP_YES; - } - if (!max17055_read(REG_TIMER, ®) && - ((uint32_t)reg > RELIABLE_BATT_DETECT_TIME)) { - batt_pres_sure = 1; - return BP_YES; - } - } - return BP_NOT_SURE; - } - return BP_YES; -} - -void battery_get_params(struct batt_params *batt) -{ - int reg = 0; - struct batt_params batt_new = {0}; - - /* - * Assuming the battery is responsive as long as - * max17055 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 (max17055_read(REG_TEMPERATURE, ®)) - batt_new.flags |= BATT_FLAG_BAD_TEMPERATURE; - - batt_new.temperature = TEMPERATURE_CONV((int16_t)reg); - - if (max17055_read(REG_STATE_OF_CHARGE, ®) && - fake_state_of_charge < 0) - batt_new.flags |= BATT_FLAG_BAD_STATE_OF_CHARGE; - - batt_new.state_of_charge = fake_state_of_charge >= 0 ? - fake_state_of_charge : PERCENTAGE_CONV(reg); - - if (max17055_read(REG_VOLTAGE, ®)) - batt_new.flags |= BATT_FLAG_BAD_VOLTAGE; - - batt_new.voltage = VOLTAGE_CONV(reg); - - if (max17055_read(REG_AVERAGE_CURRENT, ®)) - batt_new.flags |= BATT_FLAG_BAD_CURRENT; - - batt_new.current = CURRENT_CONV((int16_t)reg); - - 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; - - /* - * Charging allowed if both desired voltage and current are nonzero - * and battery isn't full (and we read them all correctly). - */ - if (!(batt_new.flags & BATT_FLAG_BAD_STATE_OF_CHARGE) && - batt_new.desired_voltage && - batt_new.desired_current && - batt_new.state_of_charge < BATTERY_LEVEL_FULL) - 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(philipchen): Implement this function. */ - return EC_SUCCESS; -} - -static int max17055_poll_flag_clear(int regno, int mask, int timeout) -{ - int reg; - - do { - if (max17055_read(regno, ®)) - return EC_ERROR_UNKNOWN; - - if (!(mask & reg)) - return EC_SUCCESS; - - msleep(10); - timeout -= 10; - } while (timeout > 0); - - return EC_ERROR_TIMEOUT; -} - -static int max17055_load_ocv_table(const struct max17055_batt_profile *config) -{ - int i; - int reg; - int retries = 3; - - /* Unlock ocv table */ - if (max17055_write(REG_LOCK1, 0x0059) || - max17055_write(REG_LOCK2, 0x00c4)) - return EC_ERROR_UNKNOWN; - - ASSERT(config->ocv_table); - - /* Write ocv data */ - for (i = 0; i < MAX17055_OCV_TABLE_SIZE; i++) { - if (max17055_write(REG_OCV_TABLE_START + i, - config->ocv_table[i])) - return EC_ERROR_UNKNOWN; - } - - /* Read and compare ocv data */ - for (i = 0; i < MAX17055_OCV_TABLE_SIZE; i++) { - if (max17055_read(REG_OCV_TABLE_START + i, ®) || - reg != config->ocv_table[i]) - return EC_ERROR_UNKNOWN; - } - - while (--retries) { - /* Lock ocv table */ - if (max17055_write(REG_LOCK1, 0x0000) || - max17055_write(REG_LOCK2, 0x0000)) - return EC_ERROR_UNKNOWN; - - /* - * If the ocv table remains unlocked, the MAX17055 cannot - * monitor the capacity of the battery. Therefore, it is very - * critical that the ocv table is locked. To verify it is - * locked, simply read back the values. However, this time, - * all values should be read as 0x0000. - */ - for (i = 0; i < MAX17055_OCV_TABLE_SIZE; i++) { - reg = 0xff; - if (max17055_read(REG_OCV_TABLE_START + i, ®)) - return EC_ERROR_UNKNOWN; - if (reg) - break; - } - if (i == MAX17055_OCV_TABLE_SIZE) - break; - msleep(20); - } - if (!retries) - return EC_ERROR_TIMEOUT; - - /* - * Delay 180ms is to prepare the environment to load the custom - * battery parameters. Otherwise, the initialization operation - * has a very small probability of failure. - */ - msleep(180); - - return EC_SUCCESS; -} - -static int max17055_exit_hibernate(void) -{ - /* - * Write REG_COMMAND with 0x90 to force the firmware to stop running. - * Write REG_HIBCFG with 0x00 to exit hibernate mode immediately. - * Write REG_COMMAND with 0x00 to run the firmware again. - */ - if (max17055_write(REG_COMMAND, 0x90) || - max17055_write(REG_HIBCFG, 0x00) || - max17055_write(REG_COMMAND, 0x00)) - return EC_ERROR_UNKNOWN; - - return EC_SUCCESS; -} - -/* Configured MAX17055 with the battery parameters for full model. */ -static int max17055_load_batt_model_full(void) -{ - int reg; - int hib_cfg; - - const struct max17055_batt_profile *config; - - config = max17055_get_batt_profile(); - - /* Store the original HibCFG value. */ - if (max17055_read(REG_HIBCFG, &hib_cfg)) - return EC_ERROR_UNKNOWN; - - /* Force exit from hibernate */ - if (max17055_exit_hibernate()) - return EC_ERROR_UNKNOWN; - - /* Write LearnCFG with LS 7 */ - if (max17055_write(REG_LEARNCFG, config->learn_cfg | 0x0070)) - return EC_ERROR_UNKNOWN; - - /* - * Unlock ocv table access, write/compare/verify custom ocv table, - * lock ocv table access. - */ - if (max17055_load_ocv_table(config)) - return EC_ERROR_UNKNOWN; - - /* Write custom parameters */ - if (max17055_write(REG_DESIGN_CAPACITY, config->design_cap) || - max17055_write(REG_DQACC, config->design_cap >> 4) || - max17055_write(REG_DPACC, 0x0c80) || - max17055_write(REG_CHARGE_TERM_CURRENT, config->ichg_term) || - max17055_write(REG_EMPTY_VOLTAGE, config->v_empty_detect)) - return EC_ERROR_UNKNOWN; - - if (max17055_write(REG_RCOMP0, config->rcomp0) || - max17055_write(REG_TEMPCO, config->tempco) || - max17055_write(REG_QR_TABLE00, config->qr_table00) || - max17055_write(REG_QR_TABLE10, config->qr_table10)) - return EC_ERROR_UNKNOWN; - - /* Update required capacity registers */ - if (max17055_write(REG_REMAINING_CAPACITY, 0x0000) || - max17055_read(REG_VFSOC, ®)) - return EC_ERROR_UNKNOWN; - - if (max17055_write(REG_VFSOC0, reg) || - max17055_write(REG_FULL_CHARGE_CAPACITY, config->design_cap) || - max17055_write(REG_FULLCAPNOM, config->design_cap)) - return EC_ERROR_UNKNOWN; - - /* Prepare to Load Model */ - if (max17055_write(REG_REMAINING_CAPACITY, 0x0000) || - max17055_write(REG_MIXCAP, config->design_cap)) - return EC_ERROR_UNKNOWN; - - /* Initiate model loading */ - if (max17055_read(REG_CONFIG2, ®) || - max17055_write(REG_CONFIG2, reg | CONFIG2_LDMDL)) - return EC_ERROR_UNKNOWN; - - if (max17055_poll_flag_clear(REG_CONFIG2, CONFIG2_LDMDL, 500)) - return EC_ERROR_UNKNOWN; - - /* Write LearnCFG with LS 0 */ - if (max17055_write(REG_LEARNCFG, config->learn_cfg & 0xff8f) || - max17055_write(REG_QR_TABLE20, config->qr_table20) || - max17055_write(REG_QR_TABLE30, config->qr_table30)) - return EC_ERROR_UNKNOWN; - - /* Restore the original HibCFG value. */ - if (max17055_write(REG_HIBCFG, hib_cfg)) - return EC_ERROR_UNKNOWN; - - return EC_SUCCESS; -} - -/* - * Configured MAX17055 with the battery parameters for short model or ez model - */ -static int max17055_load_batt_model_short_or_ez(void) -{ - int hib_cfg; - int dqacc; - int dpacc; - - const struct max17055_batt_profile *config; - - config = max17055_get_batt_profile(); - - if (config->is_ez_config) { - dqacc = config->design_cap / 32; - /* Choose the model for charge voltage > 4.275V. */ - dpacc = dqacc * 51200 / config->design_cap; - } else { - dqacc = config->design_cap / 16; - dpacc = config->dpacc; - } - - if (max17055_write(REG_DESIGN_CAPACITY, config->design_cap) || - max17055_write(REG_DQACC, dqacc) || - max17055_write(REG_CHARGE_TERM_CURRENT, config->ichg_term) || - max17055_write(REG_EMPTY_VOLTAGE, config->v_empty_detect)) - return EC_ERROR_UNKNOWN; - - if (!config->is_ez_config) { - if (max17055_write(REG_LEARNCFG, config->learn_cfg)) - return EC_ERROR_UNKNOWN; - } - - /* Store the original HibCFG value. */ - if (max17055_read(REG_HIBCFG, &hib_cfg)) - return EC_ERROR_UNKNOWN; - - /* Force exit from hibernate */ - if (max17055_exit_hibernate()) - return EC_ERROR_UNKNOWN; - - if (max17055_write(REG_DPACC, dpacc) || - max17055_write(REG_MODELCFG, (MODELCFG_REFRESH | MODELCFG_VCHG))) - return EC_ERROR_UNKNOWN; - - /* Delay up to 500 ms until MODELCFG.REFRESH bit == 0. */ - if (max17055_poll_flag_clear(REG_MODELCFG, MODELCFG_REFRESH, 500)) - return EC_ERROR_UNKNOWN; - - if (!config->is_ez_config) { - if (max17055_write(REG_RCOMP0, config->rcomp0) || - max17055_write(REG_TEMPCO, config->tempco) || - max17055_write(REG_QR_TABLE00, config->qr_table00) || - max17055_write(REG_QR_TABLE10, config->qr_table10) || - max17055_write(REG_QR_TABLE20, config->qr_table20) || - max17055_write(REG_QR_TABLE30, config->qr_table30)) - return EC_ERROR_UNKNOWN; - } - - /* Restore the original HibCFG value. */ - if (max17055_write(REG_HIBCFG, hib_cfg)) - return EC_ERROR_UNKNOWN; - return EC_SUCCESS; -} - -static int max17055_load_batt_model(void) -{ - if (IS_ENABLED(CONFIG_BATTERY_MAX17055_FULL_MODEL)) - return max17055_load_batt_model_full(); - else - return max17055_load_batt_model_short_or_ez(); -} - -static void max17055_init(void) -{ - int reg; - int retries = 80; -#ifdef CONFIG_BATTERY_MAX17055_ALERT - const struct max17055_alert_profile *alert_profile = - max17055_get_alert_profile(); -#endif - - if (!max17055_probe()) { - CPRINTS("Wrong max17055 id!"); - return; - } - - /* - * Set CONFIG.TSEL to measure temperature using external thermistor. - * Set it as early as possible because max17055 takes up to 1000ms to - * have the first reliable external temperature reading. - */ - MAX17055_READ_DEBUG(REG_CONFIG, ®); - MAX17055_WRITE_DEBUG(REG_CONFIG, (reg | CONF_TSEL)); - - MAX17055_READ_DEBUG(REG_STATUS, ®); - - /* Check for POR */ - if (STATUS_POR & reg) { - /* Delay up to 800 ms until FSTAT.DNR bit == 0. */ - while (--retries) { - MAX17055_READ_DEBUG(REG_FSTAT, ®); - if (!(FSTAT_DNR & reg)) - break; - msleep(10); - } - if (!retries) { - CPRINTS("%s: timeout waiting for FSTAT.DNR cleared", - __func__); - return; - } - - if (max17055_load_batt_model()) { - CPRINTS("max17055 configuration failed!"); - return; - } - - /* Clear POR bit */ - MAX17055_READ_DEBUG(REG_STATUS, ®); - MAX17055_WRITE_DEBUG(REG_STATUS, (reg & ~STATUS_POR)); - } else { - const struct max17055_batt_profile *config; - - config = max17055_get_batt_profile(); - MAX17055_READ_DEBUG(REG_DESIGN_CAPACITY, ®); - - /* - * Reload the battery model if the current running one - * is wrong. - */ - if (config->design_cap != reg) { - CPRINTS("max17055 reconfig..."); - if (max17055_load_batt_model()) { - CPRINTS("max17055 configuration failed!"); - return; - } - } - } - -#ifdef CONFIG_BATTERY_MAX17055_ALERT - /* Set voltage alert range */ - MAX17055_WRITE_DEBUG(REG_VALRTTH, alert_profile->v_alert_mxmn); - /* Set temperature alert range */ - MAX17055_WRITE_DEBUG(REG_TALRTTH, alert_profile->t_alert_mxmn); - /* Set state-of-charge alert range */ - MAX17055_WRITE_DEBUG(REG_SALRTTH, alert_profile->s_alert_mxmn); - /* Set current alert range */ - MAX17055_WRITE_DEBUG(REG_IALRTTH, alert_profile->i_alert_mxmn); - - /* Disable all sticky bits; enable alert AEN */ - MAX17055_READ_DEBUG(REG_CONFIG, ®); - MAX17055_WRITE_DEBUG(REG_CONFIG, (reg & ~CONF_ALL_STICKY) | CONF_AEN); - - /* Clear alerts */ - MAX17055_READ_DEBUG(REG_STATUS, ®); - MAX17055_WRITE_DEBUG(REG_STATUS, reg & ~STATUS_ALL_ALRT); -#endif - - CPRINTS("max17055 configuration succeeded!"); -} -DECLARE_HOOK(HOOK_INIT, max17055_init, HOOK_PRIO_DEFAULT); diff --git a/driver/battery/max17055.h b/driver/battery/max17055.h deleted file mode 100644 index 0f97fb90f0..0000000000 --- a/driver/battery/max17055.h +++ /dev/null @@ -1,250 +0,0 @@ -/* Copyright 2017 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 MAX17055. - */ - -#ifndef __CROS_EC_MAX17055_H -#define __CROS_EC_MAX17055_H - -#define MAX17055_ADDR_FLAGS 0x36 -#define MAX17055_DEVICE_ID 0x4010 -#define MAX17055_OCV_TABLE_SIZE 48 - -#define REG_STATUS 0x00 -#define REG_VALRTTH 0x01 -#define REG_TALRTTH 0x02 -#define REG_SALRTTH 0x03 -#define REG_AT_RATE 0x04 -#define REG_REMAINING_CAPACITY 0x05 -#define REG_STATE_OF_CHARGE 0x06 -#define REG_TEMPERATURE 0x08 -#define REG_VOLTAGE 0x09 -#define REG_CURRENT 0x0a -#define REG_AVERAGE_CURRENT 0x0b -#define REG_MIXCAP 0x0f -#define REG_FULL_CHARGE_CAPACITY 0x10 -#define REG_TIME_TO_EMPTY 0x11 -#define REG_QR_TABLE00 0x12 -#define REG_CONFIG 0x1D -#define REG_AVERAGE_TEMPERATURE 0x16 -#define REG_CYCLE_COUNT 0x17 -#define REG_DESIGN_CAPACITY 0x18 -#define REG_AVERAGE_VOLTAGE 0x19 -#define REG_MAX_MIN_TEMP 0x1a -#define REG_MAX_MIN_VOLT 0x1b -#define REG_MAX_MIN_CURR 0x1c -#define REG_CHARGE_TERM_CURRENT 0x1e -#define REG_TIME_TO_FULL 0x20 -#define REG_DEVICE_NAME 0x21 -#define REG_QR_TABLE10 0x22 -#define REG_FULLCAPNOM 0x23 -#define REG_LEARNCFG 0x28 -#define REG_QR_TABLE20 0x32 -#define REG_RCOMP0 0x38 -#define REG_TEMPCO 0x39 -#define REG_EMPTY_VOLTAGE 0x3a -#define REG_FSTAT 0x3d -#define REG_TIMER 0x3e -#define REG_QR_TABLE30 0x42 -#define REG_DQACC 0x45 -#define REG_DPACC 0x46 -#define REG_VFSOC0 0x48 -#define REG_COMMAND 0x60 -#define REG_LOCK1 0x62 -#define REG_LOCK2 0x63 -#define REG_OCV_TABLE_START 0x80 -#define REG_STATUS2 0xb0 -#define REG_IALRTTH 0xb4 -#define REG_HIBCFG 0xba -#define REG_CONFIG2 0xbb -#define REG_TIMERH 0xbe -#define REG_MODELCFG 0xdb -#define REG_VFSOC 0xff - -/* Status reg (0x00) flags */ -#define STATUS_POR BIT(1) -#define STATUS_IMN BIT(2) -#define STATUS_BST BIT(3) -#define STATUS_IMX BIT(6) -#define STATUS_VMN BIT(8) -#define STATUS_TMN BIT(9) -#define STATUS_SMN BIT(10) -#define STATUS_VMX BIT(12) -#define STATUS_TMX BIT(13) -#define STATUS_SMX BIT(14) -#define STATUS_ALL_ALRT \ - (STATUS_IMN | STATUS_IMX | STATUS_VMN | STATUS_VMX | STATUS_TMN | \ - STATUS_TMX | STATUS_SMN | STATUS_SMX) - -/* Alert disable values (0x01, 0x02, 0x03, 0xb4) */ -#define VALRT_DISABLE 0xff00 -#define TALRT_DISABLE 0x7f80 -#define SALRT_DISABLE 0xff00 -#define IALRT_DISABLE 0x7f80 - -/* Config reg (0x1d) flags */ -#define CONF_AEN BIT(2) -#define CONF_IS BIT(11) -#define CONF_VS BIT(12) -#define CONF_TS BIT(13) -#define CONF_SS BIT(14) -#define CONF_TSEL BIT(15) -#define CONF_ALL_STICKY (CONF_IS | CONF_VS | CONF_TS | CONF_SS) - -/* FStat reg (0x3d) flags */ -#define FSTAT_DNR 0x0001 -#define FSTAT_FQ 0x0080 - -/* Config2 reg (0xbb) flags */ -#define CONFIG2_LDMDL BIT(5) - -/* ModelCfg reg (0xdb) flags */ -#define MODELCFG_REFRESH BIT(15) -#define MODELCFG_VCHG BIT(10) - -/* Smart battery status bits (sbs reg 0x16) */ -#define BATTERY_DISCHARGING 0x40 -#define BATTERY_FULLY_CHARGED 0x20 - -/* - * Before we have the battery fully characterized, we use these macros to - * convert basic battery parameters to max17055 reg values for ez config. - */ - -/* Convert design capacity in mAh to max17055 0x18 reg value */ -#define MAX17055_DESIGNCAP_REG(bat_cap_mah) \ - (bat_cap_mah * BATTERY_MAX17055_RSENSE / 5) -/* Convert charge termination current in mA to max17055 0x1e reg value */ -#define MAX17055_ICHGTERM_REG(term_cur_ma) \ - (((term_cur_ma * BATTERY_MAX17055_RSENSE) << 4) / 25) -/* - * This macro converts empty voltage target (VE) and recovery voltage (VR) - * in mV to max17055 0x3a reg value. max17055 declares 0% (empty battery) at - * VE. max17055 reenables empty detection when the cell voltage rises above VR. - * VE ranges from 0 to 5110mV, and VR ranges from 0 to 5080mV. - */ -#define MAX17055_VEMPTY_REG(ve_mv, vr_mv) \ - (((ve_mv / 10) << 7) | (vr_mv / 40)) - -#define MAX17055_MAX_MIN_REG(mx, mn) ((((int16_t)(mx)) << 8) | ((mn))) -/* Converts voltages alert range for VALRTTH_REG */ -#define MAX17055_VALRTTH_RESOLUTION 20 -#define MAX17055_VALRTTH_REG(mx, mn) \ - MAX17055_MAX_MIN_REG((uint8_t)(mx / MAX17055_VALRTTH_RESOLUTION), \ - (uint8_t)(mn / MAX17055_VALRTTH_RESOLUTION)) -/* Converts temperature alert range for TALRTTH_REG */ -#define MAX17055_TALRTTH_REG(mx, mn) \ - MAX17055_MAX_MIN_REG((int8_t)(mx), (int8_t)(mn)) -/* Converts state-of-charge alert range for SALRTTH_REG */ -#define MAX17055_SALRTTH_REG(mx, mn) \ - MAX17055_MAX_MIN_REG((uint8_t)(mx), (uint8_t)(mn)) -/* Converts current alert range for IALRTTH_REG */ -/* Current resolution: 0.4mV/RSENSE */ -#define MAX17055_IALRTTH_MUL (10 * BATTERY_MAX17055_RSENSE) -#define MAX17055_IALRTTH_DIV 4 -#define MAX17055_IALRTTH_REG(mx, mn) \ - MAX17055_MAX_MIN_REG( \ - (int8_t)(mx * MAX17055_IALRTTH_MUL / MAX17055_IALRTTH_DIV), \ - (int8_t)(mn * MAX17055_IALRTTH_MUL / MAX17055_IALRTTH_DIV)) - -/* - * max17055 needs some special battery parameters for fuel gauge - * learning algorithm. Maxim can help characterize the battery pack - * to get a full parameter list. We create a data structure to store - * the battery parameters in the format of max17055 register values. - */ -struct max17055_batt_profile { - /* Design capacity of the cell (LSB = 5uVH / Rsense) */ - uint16_t design_cap; - /* Charge termination current (LSB = 1.5625uV / Rsense) */ - uint16_t ichg_term; - /* The combination of empty voltage target and recovery voltage */ - uint16_t v_empty_detect; - - /* - * The parameters below are used for advanced (non-EZ) config - * (dpacc, learn_cfg, tempco, qr_table00, qr_table10, - * qr_table20, and qr_table30) - */ - - /* Change in battery SOC between relaxation points (LSB = pct / 16) */ - uint16_t dpacc; - /* Magic cell tuning parameters */ - uint16_t learn_cfg; - uint16_t rcomp0; - uint16_t tempco; - uint16_t qr_table00; - uint16_t qr_table10; - uint16_t qr_table20; - uint16_t qr_table30; - - /* - * If is_ez_config is nonzero, we only use design_cap, ichg_term, - * and v_empty_detect to config max17055 (a.k.a. EZ-config). - */ - uint8_t is_ez_config; - - /* Used only for full model */ - const uint16_t *ocv_table; -}; - -/* Return the special battery parameters max17055 needs. */ -const struct max17055_batt_profile *max17055_get_batt_profile(void); - -#ifdef CONFIG_BATTERY_MAX17055_ALERT -/* - * max17055 supports alert on voltage, current, state-of-charge, and - * temperature. To enable this feature, the information of the limit range is - * needed. - */ -struct max17055_alert_profile { - /* - * Sets voltage upper and lower limits that generate an alert if - * voltage is outside of the v_alert_mxmn range. - * The upper 8 bits set the maximum value and the lower 8 bits set the - * minimum value. Interrupt threshold limits are selectable with 20mV - * resolution. - * Use MAX17055_VALRTTH_REG(max, min) to setup the desired range, - * VALRT_DISABLE to disable the alert. - */ - const uint16_t v_alert_mxmn; - /* - * Sets temperature upper and lower limits that generate an alert if - * temperature is outside of the t_alert_mxmn range. - * The upper 8 bits set the maximum value and the lower 8 bits set the - * minimum value. Interrupt threshold limits are stored in - * 2’s-complement format with 1°C resolution. - * Use MAX17055_TALRTTH_REG(max, min) to setup the desired range, - * TALRT_DISABLE to disable the alert. - */ - const uint16_t t_alert_mxmn; - /* - * Sets reported state-of-charge upper and lower limits that generate - * an alert if SOC is outside of the s_alert_mxmn range. - * The upper 8 bits set the maximum value and the lower 8 bits set the - * minimum value. Interrupt threshold limits are configurable with 1% - * resolution. - * Use MAX17055_SALRTTH_REG(max, min) to setup the desired range, - * SALRT_DISABLE to disable the alert. - */ - const uint16_t s_alert_mxmn; - /* - * Sets current upper and lower limits that generate an alert if - * current is outside of the i_alert_mxmn range. - * The upper 8 bits set the maximum value and the lower 8 bits set the - * minimum value. Interrupt threshold limits are selectable with - * 0.4mV/R SENSE resolution. - * Use MAX17055_IALRTTH_REG(max, min) to setup the desired range, - * IALRT_DISABLE to disable the alert. - */ - const uint16_t i_alert_mxmn; -}; - -/* - * Return the battery/system's alert threshoulds that max17055 needs. - */ -const struct max17055_alert_profile *max17055_get_alert_profile(void); -#endif /* CONFIG_BATTERY_MAX17055_ALERT */ -#endif /* __CROS_EC_MAX17055_H */ diff --git a/driver/battery/mm8013.c b/driver/battery/mm8013.c deleted file mode 100644 index 04503da2f5..0000000000 --- a/driver/battery/mm8013.c +++ /dev/null @@ -1,250 +0,0 @@ -/* 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_FLAGS, 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_FLAGS, - 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_manufacture_date(int *year, int *month, int *day) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -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_NO; - 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_status(&batt_new.status)) - batt_new.flags |= BATT_FLAG_BAD_STATUS; - - if (!battery_flag(&flag) && (flag & MM8013_FLAG_CHG)) - batt_new.flags |= BATT_FLAG_WANT_CHARGE; - -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/mm8013.h b/driver/battery/mm8013.h deleted file mode 100644 index 2ffaca7b5d..0000000000 --- a/driver/battery/mm8013.h +++ /dev/null @@ -1,40 +0,0 @@ -/* 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. - */ - -#ifndef __CROS_EC_MM8013_H -#define __CROS_EC_MM8013_H - -#define MM8013_ADDR_FLAGS 0x55 - -#define REG_TEMPERATURE 0x06 -#define REG_VOLTAGE 0x08 -#define REG_FLAGS 0x0a -#define REG_FULL_CHARGE_CAPACITY 0x0e -#define REG_REMAINING_CAPACITY 0x10 -#define REG_AVERAGE_CURRENT 0x14 -#define REG_AVERAGE_TIME_TO_EMPTY 0x16 -#define REG_AVERAGE_TIME_TO_FULL 0x18 -#define REG_STATE_OF_CHARGE 0x2c -#define REG_CYCLE_COUNT 0x2a -#define REG_DESIGN_CAPACITY 0x3c -#define REG_PRODUCT_INFORMATION 0x64 - -/* Over Temperature in charge */ -#define MM8013_FLAG_OTC BIT(15) -/* Over Temperature in discharge */ -#define MM8013_FLAG_OTD BIT(14) -/* Over-charge */ -#define MM8013_FLAG_BATHI BIT(13) -/* Full Charge */ -#define MM8013_FLAG_FC BIT(9) -/* Charge allowed */ -#define MM8013_FLAG_CHG BIT(8) -/* Discharge */ -#define MM8013_FLAG_DSG BIT(0) - - -#endif /* __CROS_EC_MM8013_H */ diff --git a/driver/battery/smart.c b/driver/battery/smart.c deleted file mode 100644 index 3704618e36..0000000000 --- a/driver/battery/smart.c +++ /dev/null @@ -1,695 +0,0 @@ -/* Copyright 2012 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. - * - * Smart battery driver. - */ - -#include "battery.h" -#include "battery_smart.h" -#include "console.h" -#include "host_command.h" -#include "i2c.h" -#include "timer.h" -#include "util.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_CHARGER, outstr); -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) - -#define BATTERY_NO_RESPONSE_TIMEOUT (1000*MSEC) - -static int fake_state_of_charge = -1; -static int fake_temperature = -1; - -static int battery_supports_pec(void) -{ - static int supports_pec = -1; - - if (!IS_ENABLED(CONFIG_SMBUS_PEC)) - return 0; - - if (supports_pec < 0) { - int spec_info; - int rv = i2c_read16(I2C_PORT_BATTERY, BATTERY_ADDR_FLAGS, - SB_SPECIFICATION_INFO, &spec_info); - /* failed, assuming not support and try again later */ - if (rv) - return 0; - - supports_pec = (BATTERY_SPEC_VERSION(spec_info) == - BATTERY_SPEC_VER_1_1_WITH_PEC); - CPRINTS("battery supports pec: %d", supports_pec); - } - return supports_pec; -} - -test_mockable int sb_read(int cmd, int *param) -{ - uint16_t addr_flags = BATTERY_ADDR_FLAGS; - -#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 - if (battery_supports_pec()) - addr_flags |= I2C_FLAG_PEC; - - return i2c_read16(I2C_PORT_BATTERY, addr_flags, cmd, param); -} - -test_mockable int sb_write(int cmd, int param) -{ - uint16_t addr_flags = BATTERY_ADDR_FLAGS; - -#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 - if (battery_supports_pec()) - addr_flags |= I2C_FLAG_PEC; - - return i2c_write16(I2C_PORT_BATTERY, addr_flags, cmd, param); -} - -int sb_read_string(int offset, uint8_t *data, int len) -{ - uint16_t addr_flags = BATTERY_ADDR_FLAGS; - -#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 - if (battery_supports_pec()) - addr_flags |= I2C_FLAG_PEC; - - return i2c_read_string(I2C_PORT_BATTERY, addr_flags, offset, data, len); -} - -int sb_read_mfgacc(int cmd, int block, uint8_t *data, int len) -{ - int rv; - - /* - * First two bytes returned from read are command sent hence read - * doesn't yield anything if the length is less than 3 bytes. - */ - if (len < 3) - return EC_ERROR_INVAL; - - /* Send manufacturer access command */ - rv = sb_write(SB_MANUFACTURER_ACCESS, cmd); - if (rv) - return rv; - - /* - * Read data on the register block. - * First two bytes returned are command sent, - * rest are actual data LSB to MSB. - */ - rv = sb_read_string(block, data, len); - if (rv) - return rv; - if ((data[0] | data[1] << 8) != cmd) - return EC_ERROR_UNKNOWN; - - return EC_SUCCESS; -} - -int sb_write_block(int reg, const uint8_t *val, int len) -{ - uint16_t addr_flags = BATTERY_ADDR_FLAGS; - -#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 - - if (battery_supports_pec()) - addr_flags |= I2C_FLAG_PEC; - - /* TODO: implement smbus_write_block. */ - return i2c_write_block(I2C_PORT_BATTERY, addr_flags, reg, val, len); -} - -int battery_get_mode(int *mode) -{ - return sb_read(SB_BATTERY_MODE, mode); -} - -/** - * Force battery to mAh mode (instead of 10mW mode) for reporting capacity. - * - * @return non-zero if error. - */ - -static int battery_force_mah_mode(void) -{ - int val, rv; - rv = battery_get_mode(&val); - if (rv) - return rv; - - if (val & MODE_CAPACITY) - rv = sb_write(SB_BATTERY_MODE, val & ~MODE_CAPACITY); - - return rv; -} - -int battery_state_of_charge_abs(int *percent) -{ - return sb_read(SB_ABSOLUTE_STATE_OF_CHARGE, percent); -} - -int battery_remaining_capacity(int *capacity) -{ - int rv = battery_force_mah_mode(); - if (rv) - return rv; - - return sb_read(SB_REMAINING_CAPACITY, capacity); -} - -int battery_full_charge_capacity(int *capacity) -{ - int rv = battery_force_mah_mode(); - if (rv) - return rv; - - return sb_read(SB_FULL_CHARGE_CAPACITY, capacity); -} - -int battery_time_to_empty(int *minutes) -{ - return sb_read(SB_AVERAGE_TIME_TO_EMPTY, minutes); -} - -int battery_run_time_to_empty(int *minutes) -{ - return sb_read(SB_RUN_TIME_TO_EMPTY, minutes); -} - -int battery_time_to_full(int *minutes) -{ - return sb_read(SB_AVERAGE_TIME_TO_FULL, minutes); -} - -/* Read battery status */ -int battery_status(int *status) -{ - return sb_read(SB_BATTERY_STATUS, status); -} - -/* Battery charge cycle count */ -int battery_cycle_count(int *count) -{ - return sb_read(SB_CYCLE_COUNT, count); -} - -int battery_design_capacity(int *capacity) -{ - int rv = battery_force_mah_mode(); - if (rv) - return rv; - - return sb_read(SB_DESIGN_CAPACITY, capacity); -} - -/* Designed battery output voltage - * unit: mV - */ -int battery_design_voltage(int *voltage) -{ - return sb_read(SB_DESIGN_VOLTAGE, voltage); -} - -/* Read serial number */ -int battery_serial_number(int *serial) -{ - return sb_read(SB_SERIAL_NUMBER, serial); -} - -test_mockable int battery_time_at_rate(int rate, int *minutes) -{ - int rv; - int ok, time; - int loop, cmd, output_sign; - - if (rate == 0) { - *minutes = 0; - return EC_ERROR_INVAL; - } - - rv = sb_write(SB_AT_RATE, rate); - if (rv) - return rv; - loop = 5; - while (loop--) { - rv = sb_read(SB_AT_RATE_OK, &ok); - if (rv) - return rv; - if (ok) { - if (rate > 0) { - cmd = SB_AT_RATE_TIME_TO_FULL; - output_sign = -1; - } else { - cmd = SB_AT_RATE_TIME_TO_EMPTY; - output_sign = 1; - } - rv = sb_read(cmd, &time); - if (rv) - return rv; - - *minutes = (time == 0xffff) ? 0 : output_sign * time; - return EC_SUCCESS; - } else { - /* wait 10ms for AT_RATE_OK */ - msleep(10); - } - } - return EC_ERROR_TIMEOUT; -} - -test_mockable int battery_manufacture_date(int *year, int *month, int *day) -{ - int rv; - int ymd; - - rv = sb_read(SB_MANUFACTURE_DATE, &ymd); - if (rv) - return rv; - - /* battery date format: - * ymd = day + month * 32 + (year - 1980) * 512 - */ - *year = ((ymd & MANUFACTURE_DATE_YEAR_MASK) >> - MANUFACTURE_DATE_YEAR_SHIFT) + MANUFACTURE_DATE_YEAR_OFFSET; - *month = (ymd & MANUFACTURE_DATE_MONTH_MASK) >> - MANUFACTURE_DATE_MONTH_SHIFT; - *day = (ymd & MANUFACTURE_DATE_DAY_MASK) >> - MANUFACTURE_DATE_DAY_SHIFT; - - return EC_SUCCESS; -} - -int get_battery_manufacturer_name(char *dest, int size) -{ - return sb_read_string(SB_MANUFACTURER_NAME, dest, size); -} - -/* Read device name */ -test_mockable int battery_device_name(char *dest, int size) -{ - return sb_read_string(SB_DEVICE_NAME, dest, size); -} - -/* Read battery type/chemistry */ -test_mockable int battery_device_chemistry(char *dest, int size) -{ - return sb_read_string(SB_DEVICE_CHEMISTRY, dest, size); -} - -int battery_get_avg_current(void) -{ - int current; - - /* This is a signed 16-bit value. */ - sb_read(SB_AVERAGE_CURRENT, ¤t); - return (int16_t)current; -} - -#ifdef CONFIG_CMD_PWR_AVG -/* - * Technically returns only the instantaneous reading, but tests showed that - * for the majority of charge states above 3% this varies by less than 40mV - * every minute, so we accept the inaccuracy here. - */ -int battery_get_avg_voltage(void) -{ - int voltage = -EC_ERROR_UNKNOWN; - - sb_read(SB_VOLTAGE, &voltage); - return voltage; -} -#endif /* CONFIG_CMD_PWR_AVG */ - -static void apply_fake_state_of_charge(struct batt_params *batt) -{ - int full; - - if (fake_state_of_charge < 0) - return; - - if (batt->flags & BATT_FLAG_BAD_FULL_CAPACITY) - battery_design_capacity(&full); - else - full = batt->full_capacity; - - batt->state_of_charge = fake_state_of_charge; - batt->remaining_capacity = full * fake_state_of_charge / 100; - battery_compensate_params(batt); - batt->flags &= ~BATT_FLAG_BAD_STATE_OF_CHARGE; - batt->flags &= ~BATT_FLAG_BAD_REMAINING_CAPACITY; -} - -void battery_get_params(struct batt_params *batt) -{ - struct batt_params batt_new = {0}; - int v; - - if (sb_read(SB_TEMPERATURE, &batt_new.temperature) - && fake_temperature < 0) - batt_new.flags |= BATT_FLAG_BAD_TEMPERATURE; - - /* If temperature is faked, override with faked data */ - if (fake_temperature >= 0) - batt_new.temperature = fake_temperature; - - if (sb_read(SB_RELATIVE_STATE_OF_CHARGE, &batt_new.state_of_charge) - && fake_state_of_charge < 0) - batt_new.flags |= BATT_FLAG_BAD_STATE_OF_CHARGE; - - if (sb_read(SB_VOLTAGE, &batt_new.voltage)) - batt_new.flags |= BATT_FLAG_BAD_VOLTAGE; - - /* This is a signed 16-bit value. */ - if (sb_read(SB_CURRENT, &v)) - batt_new.flags |= BATT_FLAG_BAD_CURRENT; - else - batt_new.current = (int16_t)v; - - if (sb_read(SB_AVERAGE_CURRENT, &v)) - batt_new.flags |= BATT_FLAG_BAD_AVERAGE_CURRENT; - if (sb_read(SB_CHARGING_VOLTAGE, &batt_new.desired_voltage)) - batt_new.flags |= BATT_FLAG_BAD_DESIRED_VOLTAGE; - - if (sb_read(SB_CHARGING_CURRENT, &batt_new.desired_current)) - batt_new.flags |= BATT_FLAG_BAD_DESIRED_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_status(&batt_new.status)) - batt_new.flags |= BATT_FLAG_BAD_STATUS; - - /* If any of those reads worked, the battery is responsive */ - if ((batt_new.flags & BATT_FLAG_BAD_ANY) != BATT_FLAG_BAD_ANY) - batt_new.flags |= BATT_FLAG_RESPONSIVE; - -#ifdef CONFIG_BATTERY_MEASURE_IMBALANCE - if (battery_imbalance_mv() > CONFIG_BATTERY_MAX_IMBALANCE_MV) - batt_new.flags |= BATT_FLAG_IMBALANCED_CELL; -#endif - -#if defined(CONFIG_BATTERY_PRESENT_CUSTOM) || \ - defined(CONFIG_BATTERY_PRESENT_GPIO) - /* Hardware can tell us for certain */ - batt_new.is_present = battery_is_present(); -#else - /* No hardware test, so we only know it's there if it responds */ - if (batt_new.flags & BATT_FLAG_RESPONSIVE) - batt_new.is_present = BP_YES; - else - batt_new.is_present = BP_NOT_SURE; -#endif - - /* - * Charging allowed if both desired voltage and current are nonzero - * and battery isn't full (and we read them all correctly). - */ - if (!(batt_new.flags & (BATT_FLAG_BAD_DESIRED_VOLTAGE | - BATT_FLAG_BAD_DESIRED_CURRENT | - BATT_FLAG_BAD_STATE_OF_CHARGE)) && -#ifdef CONFIG_BATTERY_REQUESTS_NIL_WHEN_DEAD - /* - * TODO (crosbug.com/p/29467): remove this workaround - * for dead battery that requests no voltage/current - */ - ((batt_new.desired_voltage && - batt_new.desired_current && - batt_new.state_of_charge < BATTERY_LEVEL_FULL) || - (batt_new.desired_voltage == 0 && - batt_new.desired_current == 0 && - batt_new.state_of_charge == 0))) -#else - batt_new.desired_voltage && - batt_new.desired_current && - batt_new.state_of_charge < BATTERY_LEVEL_FULL) -#endif - batt_new.flags |= BATT_FLAG_WANT_CHARGE; - else - /* Force both to zero */ - batt_new.desired_voltage = batt_new.desired_current = 0; - -#ifdef HAS_TASK_HOSTCMD - /* if there is no host, we don't care about compensation */ - battery_compensate_params(&batt_new); - board_battery_compensate_params(&batt_new); -#endif - - if (IS_ENABLED(CONFIG_CMD_BATTFAKE)) - apply_fake_state_of_charge(&batt_new); - - /* Update visible battery parameters */ - memcpy(batt, &batt_new, sizeof(*batt)); -} - -/* Wait until battery is totally stable */ -int battery_wait_for_stable(void) -{ - int status; - uint64_t wait_timeout = get_time().val + BATTERY_NO_RESPONSE_TIMEOUT; - - CPRINTS("Wait for battery stabilized during %d", - BATTERY_NO_RESPONSE_TIMEOUT); - while (get_time().val < wait_timeout) { - /* Starting pinging battery */ - if (battery_status(&status) == EC_SUCCESS) { - /* Battery is stable */ - CPRINTS("battery responded with status %x", status); - return EC_SUCCESS; - } - msleep(25); /* clock stretching could hold 25ms */ - } - CPRINTS("battery not responding"); - return EC_ERROR_NOT_POWERED; -} - -#if defined(CONFIG_CMD_BATTFAKE) -static int command_battfake(int argc, char **argv) -{ - char *e; - int v; - - if (argc == 2) { - v = strtoi(argv[1], &e, 0); - if (*e || v < -1 || v > 100) - return EC_ERROR_PARAM1; - - fake_state_of_charge = v; - } - - if (fake_state_of_charge >= 0) - ccprintf("Fake batt %d%%\n", fake_state_of_charge); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(battfake, command_battfake, - "percent (-1 = use real level)", - "Set fake battery level"); - -static int command_batttempfake(int argc, char **argv) -{ - char *e; - int t; - - if (argc == 2) { - t = strtoi(argv[1], &e, 0); - if (*e || t < -1 || t > 5000) - return EC_ERROR_PARAM1; - - fake_temperature = t; - } - - if (fake_temperature >= 0) - ccprintf("Fake batt temperature %d.%d K\n", - fake_temperature / 10, fake_temperature % 10); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(batttempfake, command_batttempfake, - "temperature (-1 = use real temperature)", - "Set fake battery temperature in deciKelvin (2731 = 273.1 K = 0 deg C)"); -#endif - -#ifdef CONFIG_CMD_BATT_MFG_ACCESS -static int command_batt_mfg_access_read(int argc, char **argv) -{ - char *e; - uint8_t data[32]; - int cmd, block, len = 6; - int rv; - - if (argc < 3 || argc > 4) - return EC_ERROR_PARAM_COUNT; - - cmd = strtoi(argv[1], &e, 0); - if (*e || cmd < 0) - return EC_ERROR_PARAM1; - - block = strtoi(argv[2], &e, 0); - if (*e || block < 0) - return EC_ERROR_PARAM2; - - if (argc > 3) { - len = strtoi(argv[3], &e, 0); - len += 2; - if (*e || len < 3 || len > sizeof(data)) - return EC_ERROR_PARAM3; - } - - rv = sb_read_mfgacc(cmd, block, data, len); - if (rv) - return rv; - - ccprintf("data[MSB->LSB]=0x"); - do { - len--; - ccprintf("%02x ", data[len]); - } while (len > 2); - ccprintf("\n"); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(battmfgacc, command_batt_mfg_access_read, - "cmd block | len", - "Read battery manufacture access data"); -#endif /* CONFIG_CMD_BATT_MFG_ACCESS */ - -/*****************************************************************************/ -/* Smart battery pass-through - */ -#ifdef CONFIG_SB_PASSTHROUGH -static enum ec_status -host_command_sb_read_word(struct host_cmd_handler_args *args) -{ - int rv; - int val; - const struct ec_params_sb_rd *p = args->params; - struct ec_response_sb_rd_word *r = args->response; - - if (p->reg > 0x1c) - return EC_RES_INVALID_PARAM; - rv = sb_read(p->reg, &val); - if (rv) - return EC_RES_ERROR; - - r->value = val; - args->response_size = sizeof(struct ec_response_sb_rd_word); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_SB_READ_WORD, - host_command_sb_read_word, - EC_VER_MASK(0)); - -static enum ec_status -host_command_sb_write_word(struct host_cmd_handler_args *args) -{ - int rv; - const struct ec_params_sb_wr_word *p = args->params; - - if (p->reg > 0x1c) - return EC_RES_INVALID_PARAM; - rv = sb_write(p->reg, p->value); - if (rv) - return EC_RES_ERROR; - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_SB_WRITE_WORD, - host_command_sb_write_word, - EC_VER_MASK(0)); - -static enum ec_status -host_command_sb_read_block(struct host_cmd_handler_args *args) -{ - int rv; - const struct ec_params_sb_rd *p = args->params; - struct ec_response_sb_rd_block *r = args->response; - - if ((p->reg != SB_MANUFACTURER_NAME) && - (p->reg != SB_DEVICE_NAME) && - (p->reg != SB_DEVICE_CHEMISTRY) && - (p->reg != SB_MANUFACTURER_DATA)) - return EC_RES_INVALID_PARAM; - rv = sb_read_string(p->reg, r->data, 32); - if (rv) - return EC_RES_ERROR; - - args->response_size = sizeof(struct ec_response_sb_rd_block); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_SB_READ_BLOCK, - host_command_sb_read_block, - EC_VER_MASK(0)); - -static enum ec_status -host_command_sb_write_block(struct host_cmd_handler_args *args) -{ - /* Not implemented */ - return EC_RES_INVALID_COMMAND; -} -DECLARE_HOST_COMMAND(EC_CMD_SB_WRITE_BLOCK, - host_command_sb_write_block, - EC_VER_MASK(0)); -#endif - -#ifdef CONFIG_CMD_I2C_STRESS_TEST_BATTERY -test_mockable int sb_i2c_test_read(int cmd, int *param) -{ - char chemistry[sizeof(CONFIG_BATTERY_DEVICE_CHEMISTRY) + 1]; - int rv; - - if (cmd == SB_DEVICE_CHEMISTRY) { - rv = battery_device_chemistry(chemistry, - sizeof(CONFIG_BATTERY_DEVICE_CHEMISTRY)); - if (rv) - return rv; - if (strcasecmp(chemistry, CONFIG_BATTERY_DEVICE_CHEMISTRY)) - return EC_ERROR_UNKNOWN; - - *param = EC_SUCCESS; - return EC_SUCCESS; - } - - - return sb_read(cmd, param); -} - -struct i2c_stress_test_dev battery_i2c_stress_test_dev = { - .reg_info = { - .read_reg = SB_DEVICE_CHEMISTRY, - .read_val = EC_SUCCESS, - .write_reg = SB_AT_RATE, - }, - .i2c_read_dev = &sb_i2c_test_read, - .i2c_write_dev = &sb_write, -}; -#endif /* CONFIG_CMD_I2C_STRESS_TEST_BATTERY */ |