// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Gas Gauge driver for SBS Compliant Batteries
*
* Copyright (c) 2010, NVIDIA Corporation.
*/
#include <linux/bits.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/property.h>
#include <linux/of_device.h>
#include <linux/power/sbs-battery.h>
#include <linux/power_supply.h>
#include <linux/slab.h>
#include <linux/stat.h>
enum {
REG_MANUFACTURER_DATA,
REG_BATTERY_MODE,
REG_TEMPERATURE,
REG_VOLTAGE,
REG_CURRENT_NOW,
REG_CURRENT_AVG,
REG_MAX_ERR,
REG_CAPACITY,
REG_TIME_TO_EMPTY,
REG_TIME_TO_FULL,
REG_STATUS,
REG_CAPACITY_LEVEL,
REG_CYCLE_COUNT,
REG_SERIAL_NUMBER,
REG_REMAINING_CAPACITY,
REG_REMAINING_CAPACITY_CHARGE,
REG_FULL_CHARGE_CAPACITY,
REG_FULL_CHARGE_CAPACITY_CHARGE,
REG_DESIGN_CAPACITY,
REG_DESIGN_CAPACITY_CHARGE,
REG_DESIGN_VOLTAGE_MIN,
REG_DESIGN_VOLTAGE_MAX,
REG_CHEMISTRY,
REG_MANUFACTURER,
REG_MODEL_NAME,
REG_CHARGE_CURRENT,
REG_CHARGE_VOLTAGE,
};
#define REG_ADDR_SPEC_INFO 0x1A
#define SPEC_INFO_VERSION_MASK GENMASK(7, 4)
#define SPEC_INFO_VERSION_SHIFT 4
#define SBS_VERSION_1_0 1
#define SBS_VERSION_1_1 2
#define SBS_VERSION_1_1_WITH_PEC 3
#define REG_ADDR_MANUFACTURE_DATE 0x1B
/* Battery Mode defines */
#define BATTERY_MODE_OFFSET 0x03
#define BATTERY_MODE_CAPACITY_MASK BIT(15)
enum sbs_capacity_mode {
CAPACITY_MODE_AMPS = 0,
CAPACITY_MODE_WATTS = BATTERY_MODE_CAPACITY_MASK
};
#define BATTERY_MODE_CHARGER_MASK (1<<14)
/* manufacturer access defines */
#define MANUFACTURER_ACCESS_STATUS 0x0006
#define MANUFACTURER_ACCESS_SLEEP 0x0011
/* battery status value bits */
#define BATTERY_INITIALIZED 0x80
#define BATTERY_DISCHARGING 0x40
#define BATTERY_FULL_CHARGED 0x20
#define BATTERY_FULL_DISCHARGED 0x10
/* min_value and max_value are only valid for numerical data */
#define SBS_DATA(_psp, _addr, _min_value, _max_value) { \
.psp = _psp, \
.addr = _addr, \
.min_value = _min_value, \
.max_value = _max_value, \
}
static const struct chip_data {
enum power_supply_property psp;
u8 addr;
int min_value;
int max_value;
} sbs_data[] = {
[REG_MANUFACTURER_DATA] =
SBS_DATA(POWER_SUPPLY_PROP_PRESENT, 0x00, 0, 65535),
[REG_BATTERY_MODE] =
SBS_DATA(-1, 0x03, 0, 65535),
[REG_TEMPERATURE] =
SBS_DATA(POWER_SUPPLY_PROP_TEMP, 0x08, 0, 65535),
[REG_VOLTAGE] =
SBS_DATA(POWER_SUPPLY_PROP_VOLTAGE_NOW, 0x09, 0, 20000),
[REG_CURRENT_NOW] =
SBS_DATA(POWER_SUPPLY_PROP_CURRENT_NOW, 0x0A, -32768, 32767),
[REG_CURRENT_AVG] =
SBS_DATA(POWER_SUPPLY_PROP_CURRENT_AVG, 0x0B, -32768, 32767),
[REG_MAX_ERR] =
SBS_DATA(POWER_SUPPLY_PROP_CAPACITY_ERROR_MARGIN, 0x0c, 0, 100),
[REG_CAPACITY] =
SBS_DATA(POWER_SUPPLY_PROP_CAPACITY, 0x0D, 0, 100),
[REG_REMAINING_CAPACITY] =
SBS_DATA(POWER_SUPPLY_PROP_ENERGY_NOW, 0x0F, 0, 65535),
[REG_REMAINING_CAPACITY_CHARGE] =
SBS_DATA(POWER_SUPPLY_PROP_CHARGE_NOW, 0x0F, 0, 65535),
[REG_FULL_CHARGE_CAPAC