linux 驱动
描述:cw2015驱动源码在实际项目中验证过,可以放心使用,驱动代码功能正常。
CW2015 驱动源码
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/power_supply.h>
#include <linux/regmap.h>
#include <linux/types.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/gpio.h>#include <linux/acpi.h>
#include <linux/of.h>
#include <linux/of_gpio.h>#ifdef CONFIG_ARCH_SUNXI
#include <linux/sunxi-gpio.h>
#endif#define CW2015_REG_VERSION 0x00
#define CW2015_REG_VCELL0 0x02
#define CW2015_REG_VCELL1 0x03
#define CW2015_REG_SOC0 0x04
#define CW2015_REG_SOC1 0x05
#define CW2015_REG_RRT_ALRT0 0x06
#define CW2015_REG_RRT_ALRT1 0x07
#define CW2015_REG_CONFIG 0x08
#define CW2015_REG_MODE 0x0A#define CW2015_REG_BATINFO 0x10
#define CW2015_MODE_SLEEP (6)
#define CW2015_MODE_QSTRT (4)
#define CW2015_MODE_POR (0)#define CW2015_SLEEP_STAT_MASK 0xC0
#define CW2015_MANUFACTURER "CellWise"
//#define BAT_LOW_INTERRUPT
#define BAT_LOW_INTERRUPT_PIN "cw,irq"#define UI_FULL 100
#define SIZE_BATINFO 64#define UFG 0x2
/* 电池建模信息,客户拿到自己电池匹配的建模信息后请替换 */
//battery model
static unsigned char cw_bat_config_info[SIZE_BATINFO] = {0x14,0xDB,0x6E,0x67,0x64,0x63,0x61,0x60,
0x60,0x5B,0x59,0x54,0x4F,0x4F,0x40,0x30,
0x27,0x24,0x25,0x28,0x33,0x47,0x55,0x5A,
0x4B,0x5B,0x08,0xF6,0x26,0x46,0x55,0x67,
0x70,0x6E,0x6B,0x6D,0x3D,0x1A,0x7F,0x1A,
0x08,0x1C,0x4A,0x80,0x8E,0x90,0x90,0x32,
0x5D,0x84,0x93,0x97,0x80,0x99,0xC4,0xCB,
0x2F,0x00,0x64,0xA5,0xB5,0x22,0x10,0x19
};struct cw2015_device {
struct i2c_client *client;
struct device *dev;
struct power_supply *charger;
struct delayed_work bat_monitor;struct regmap *rmap;
u32 alrt_threshold;
u32 emerg_threshold;
bool warning_on;int voltage_mv;
struct mutex lock; /* protect state data */
};int g_battery_exist_flag = 0;
//unsigned char if_quickstart =0;
unsigned char reset_loop =0, wakeup_loop =0;static int cw2015_hw_init(struct cw2015_device *cw);
static bool cw2015_is_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case CW2015_REG_VERSION:
case CW2015_REG_VCELL0:
case CW2015_REG_VCELL1:
case CW2015_REG_SOC0:
case CW2015_REG_SOC1:
return false;default:
return true;
}
}static const struct regmap_config cw2015_regmap_config = {
.reg_bits = 8,
.val_bits = 8,.max_register = CW2015_REG_MODE,
.cache_type = REGCACHE_NONE,.volatile_reg = cw2015_is_volatile_reg,
};static int cw2015_por(struct cw2015_device *cw)
{
int ret = -1;printk("Reset cw2015!\n");
regmap_write(cw->rmap, CW2015_REG_MODE, 0xA0); //MODE Register (0x0A): 1100 0000 SLEEP MODE
mdelay(30); //delay 30msregmap_write(cw->rmap, CW2015_REG_MODE, 0x00); //MODE Register (0x0A): 0000 0000 Normal MODE
mdelay(10); //delay 10ms
/* reset */
regmap_write(cw->rmap, CW2015_REG_MODE, 0x0f); //MODE Register (0x0A): 0000 1111 reset MODE
mdelay(10); //delay 10msregmap_write(cw->rmap, CW2015_REG_MODE, 0x00); //MODE Register (0x0A): 0000 0000 Normal MODE
mdelay(10); //delay 10msret = cw2015_hw_init(cw);
return ret;
}#ifdef BAT_LOW_INTERRUPT
/*当一次alrt 事件到来时,cw2015 ic会拉低arlt pin产生中断,这时需要对06寄存器的最高bit位清0,才能让cw2015 ic释放alrt pin 下面函数的作用是释放alrt pin*/
static int cw2015_release_alrt_pin(struct cw2015_device *cw)
{
unsigned int reg_val;
int alrt = 0;
regmap_read(cw->rmap, CW2015_REG_RRT_ALRT0, ®_val);
printk("cw2015_irq_handler_thread val=%08x\n", reg_val);
alrt = reg_val & 0x80;
if (alrt)
{
reg_val = reg_val & 0x7f;
regmap_update_bits(cw->rmap, CW2015_REG_RRT_ALRT0, 0