/*
battery@0B{
compatible = "ti,bq40z50";
reg = <0x0B>;
};
*/
#define pr_fmt(fmt) "[bq40z50] %s: " fmt, __func__
#include <linux/module.h>
#include <linux/param.h>
#include <linux/jiffies.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/power_supply.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/interrupt.h>
#include <linux/gpio/consumer.h>
#define bq_info pr_info
#define bq_dbg pr_debug
#define bq_err pr_err
#ifdef CONFIG_BQ40Z50_DEBUG
#define bq_log pr_err
#else
#define bq_log pr_info
#endif
#define INVALID_REG_ADDR 0xFF
#define FG_FLAGS_FD BIT(4)
#define FG_FLAGS_FC BIT(5)
#define FG_FLAGS_DSG BIT(6)
#define FG_FLAGS_RCA BIT(9)
#define FG_BM_CAPM BIT(15)
#define FG_MBA_SAFE_CUV BIT(0)
#define FG_MBA_SAFE_COV BIT(1)
#define FG_MBA_SAFE_OCC1 BIT(2)
#define FG_MBA_SAFE_OCC2 BIT(3)
#define FG_MBA_SAFE_OCD1 BIT(4)
#define FG_MBA_SAFE_OCD2 BIT(5)
#define FG_MBA_SAFE_AOLD BIT(7)
#define FG_MBA_SAFE_ASCCL BIT(9)
#define FG_MBA_SAFE_ASCDL BIT(11)
#define FG_MBA_SAFE_OTC BIT(12)
#define FG_MBA_SAFE_OTD BIT(13)
#define FG_MBA_SAFE_CUVC BIT(14)
#define FG_MBA_SAFE_OTF BIT(16)
#define FG_MBA_SAFE_PTO BIT(18)
#define FG_MBA_SAFE_PTOS BIT(19)
#define FG_MBA_SAFE_CTO BIT(20)
#define FG_MBA_SAFE_CTOS BIT(21)
#define FG_MBA_SAFE_OC BIT(22)
#define FG_MBA_SAFE_CHGC BIT(23)
#define FG_MBA_SAFE_CHGV BIT(24)
#define FG_MBA_SAFE_PCHGC BIT(25)
#define FG_MBA_SAFE_UTC BIT(26)
#define FG_MBA_SAFE_UTD BIT(27)
#define FG_MBA_OPS_DSG BIT(1)
#define FG_MBA_OPS_CHG BIT(2)
#define FG_MBA_OPS_PCHG BIT(3)
#define FG_MBA_OPS_FUSE BIT(5)
#define FG_MBA_OPS_BTP_INT BIT(7)
#define FG_MBA_OPS_SEC0 BIT(8)
#define FG_MBA_OPS_SEC1 BIT(9)
#define FG_MBA_OPS_SDV BIT(10)
#define FG_MBA_OPS_SS BIT(11)
#define FG_MBA_OPS_PF BIT(12)
#define FG_MBA_OPS_XDSG BIT(13)
#define FG_MBA_OPS_XDHG BIT(14)
#define FG_MBA_OPS_SLEEP BIT(15)
#define FG_MBA_OPS_SDM BIT(16)
#define FG_MBA_OPS_LED BIT(17)
#define FG_MBA_OPS_AUTH BIT(18)
#define FG_MBA_OPS_AUTOCALM BIT(19)
#define FG_MBA_OPS_CAL BIT(20)
#define FG_MBA_OPS_CAL_OFF BIT(21)
#define FG_MBA_OPS_XL BIT(22)
#define FG_MBA_OPS_SLEEPM BIT(23)
#define FG_MBA_OPS_INIT BIT(24)
#define FG_MBA_OPS_SMBLCAL BIT(25)
#define FG_MBA_OPS_SLPAD BIT(26)
#define FG_MBA_OPS_SLPCC BIT(27)
#define FG_MBA_OPS_CB BIT(28)
#define FG_MBA_OPS_EMSHUT BIT(29)
#define FLAG_TO_BOOL(flag, var) (!!(flag & var))
// Once a minute
#define DEFAULT_POLL_INTERVAL 60
static unsigned int poll_interval = DEFAULT_POLL_INTERVAL;
module_param(poll_interval, uint, 0644);
MODULE_PARM_DESC(poll_interval, "battery polling interval in seconds. 0 disables polling");
enum bq_fg_reg_idx {
BQ_FG_REG_MAC = 0,
BQ_FG_REG_TEMP, /* Battery Temperature */
BQ_FG_REG_VOLT, /* Battery Voltage */
BQ_FG_REG_AI, /* Average Current */
BQ_FG_REG_BATT_STATUS, /* BatteryStatus */
BQ_FG_REG_TTE, /* Time to Empty */
BQ_FG_REG_TTF, /* Time to Full */
BQ_FG_REG_FCC, /* Full Charge Capacity */
BQ_FG_REG_RM, /* Remaining Capacity */
BQ_FG_REG_CC, /* Cycle Count */
BQ_FG_REG_SOC, /* Relative State of Charge */
BQ_FG_REG_SOH, /* State of Health */
BQ_FG_REG_DC, /* Design Capacity */
BQ_FG_REG_MBA, /* ManufacturerBlockAccess*/
BQ_FG_REG_SN, /* Serial Number */
BQ_FG_REG_DV, /* Design Voltage */
BQ_FG_REG_CCVM, /* Constant Max Voltage */
BQ_FG_REG_CCCM, /* Constant Max Current */
BQ_FG_REG_I, /* Momentary current */
BQ_FG_REG_BM, /* Battery Mode */
BQ_FG_REG_OP_STATUS,/* Operation Status */
NUM_REGS,
};
static u8 bq40z50_regs[NUM_REGS] = {
0x00, /* CONTROL */
0x08, /* TEMP */
0x09, /* VOLT */
0x0B, /* AVG CURRENT */
0x16, /* FLAGS */
0x12, /* Time to empty */
0x13, /* Time to full */
0x10, /* Full charge capacity */
0x0F, /* Remaining Capacity */
0x17, /* CycleCount */
0x0D, /* State of Charge */
0x4F, /* State of Health */
0x18, /* Design Capacity */
0x44, /* ManufacturerBlockAccess*/
0x1C, /* Serial Number */
0x19, /* Design Voltage */
0x15, /* Max Charge Voltage */
0x14, /* Max Charge Current */
0x0A, /* Momentary Current */
0x03, /* Battery Mode */
0x54, /* Operation Status */
};
char * bq_fg_reg_cmd_names[] = {
"Control",
"Temperature",
"Battery Voltage",
"Average Current",
"Battery Status",
"Time To Empty",
"Time To Full",
"Full Charge Capacity",
"Remaining Capacity",
"Cycle Count",
"Relative State of Charge",
"State of Health",
"Design Capacity",
"ManufacturerBlockAccess",
"Serial Number",
"Design Voltage",
"Constant Max Voltage",
"Constant Max Current",
"Momentary Current",
"Battery Mode",
"Operation Status"
};
enum bq_fg_mac_cmd {
FG_MAC_CMD_OP_STATUS_L = 0x0000,
FG_MAC_CMD_DEV_TYPE = 0x0001,
FG_MAC_CMD_FW_VER = 0x0002,
FG_MAC_CMD_HW_VER = 0x0003,
FG_MAC_CMD_IF_SIG = 0x0004,
FG_MAC_CMD_CHEM_ID = 0x0006,
FG_MAC_CMD_GAUGING = 0x0021,
FG_MAC_CMD_SEAL = 0x0030,
FG_MAC_CMD_DEV_RESET = 0x0041,
FG_MAC_CMD_SAFE_ALERT = 0x0050,
FG_MAC_CMD_SAFE_STATUS = 0x0051,
FG_MAC_CMD_GSTATUS_3 = 0x0075,
FG_MAC_CMD_OP_STATUS = 0x0054,
};
enum {
SEAL_STATE_RSVED,
SEAL_STATE_UNSEALED,
SEAL_STATE_SEALED,
SEAL_STATE_FA,
};
enum bq_fg_device {
BQ40Z50,
};
static const unsigned char *device2str[] = {
"bq40z50",
};
struct bq_fg_chip {
struct device *dev;
struct i2c_client *client;
struct mutex i2c_rw_lock;
struct mutex data_lock;
struct mutex irq_complete;
bool irq_waiting;
bool irq_disabled;
bool resume_completed;
int fw_ver;
int df_ver;
u8 chip;
u8 regs[NUM_REGS];
/* status tracking */
bool batt_fc;
bool batt_fd; /* full depleted */
bool batt_dsg;
bool batt_rca; /* remaining capacity alarm */
union{
u16 bm_intval;
struct{
unsigned bm_icc : 1; /* Internal Charge Controller */
unsigned bm_pbs : 1; /* Primary Battery Support */
unsigned bm_rsvd1 : 5; /* Reserved, do not use */
unsigned bm_cf : 1; /* Conditioning flag */
unsigned bm_cc : 1; /* Condition flag */
unsigned bm_pb : 1; /* Primary battery */
unsigned bm_rdvd2 : 3; /* Reserved, do not use */
unsigned bm_am : 1; /* Alarm Mode */
unsigned bm_chgm : 1; /* Charger Mode */
unsigned bm_capm : 1; /* Capacity reporting units */
};
};
int seal_state; /* 0 - Full Access, 1 - Unsealed, 2 - Sealed */
u16 batt_tte;
u16 batt_ttf;
u16 batt_soc;
u16 batt_fcc; /* Full charge capacity */
u16 batt_rm; /* Remaining capacity */
u16 batt_dc; /* Design Capacity */
u16 batt_dv; /* Design Volt */
u16 batt_volt;
u16 batt_temp;
s16 batt_curr;
s16 batt_curr_avg;
u16 batt_sn;
u16 batt_cccm;
u16 batt_ccvm;
u16 batt_cyclecnt; /* cycle count */
/* debug */
int skip_reads;
int skip_w
bq40z50电量计驱动程序
于 2024-01-11 10:02:53 首次发布