1. 程式人生 > >電池bq15601 充電ic驅動i2c子系統 筆記

電池bq15601 充電ic驅動i2c子系統 筆記

電池bq15601 充電ic驅動i2c子系統 筆記


/* module_init(bq25601_init); */
/* module_exit(bq25601_exit); */
subsys_initcall(bq25601_subsys_init);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("I2C bq25601 Driver");


static int __init bq25601_subsys_init(void)  //回撥核心一開機就會自動呼叫
{
	int ret = 0;
	//檢測i2c上的電池bq25601_driver驅動
	if (i2c_add_driver(&bq25601_driver) != 0)
		battery_log(BAT_LOG_CRTI, "[bq24261_init] failed to register bq24261 i2c driver.\n");
	else
		battery_log(BAT_LOG_CRTI, "[bq24261_init] Success to register bq24261 i2c driver.\n");

	/* bq25601 user space access interface 使用者空間通道介面*///註冊平臺裝置dev和平臺驅動drvier
	ret = platform_device_register(&bq25601_user_space_device);//註冊平臺裝置dev
	if (ret) {
		battery_log(BAT_LOG_CRTI, "****[bq25601_init] Unable to device register(%d)\n", ret);
		return ret;
	}
	ret = platform_driver_register(&bq25601_user_space_driver);//註冊平臺驅動drvier
	if (ret) {
		battery_log(BAT_LOG_CRTI, "****[bq25601_init] Unable to register driver (%d)\n", ret);
		return ret;
	}

	return 0;
}


struct platform_device bq25601_user_space_device = {
	.name = "bq25601-user", //用於匹配
	.id = -1,
};

static struct platform_driver bq25601_user_space_driver = {
	.probe = bq25601_user_space_probe,
	.driver = {
		   .name = "bq25601-user",//用於匹配
		   },
};
static int bq25601_user_space_probe(struct platform_device *dev)
{
	int ret_device_file = 0;

	battery_log(BAT_LOG_CRTI, "******** bq25601_user_space_probe!! ********\n");

	ret_device_file = device_create_file(&(dev->dev), &dev_attr_bq25601_access);

	return 0;
}

static DEVICE_ATTR(bq25601_access, 0664, show_bq25601_access, store_bq25601_access);	/* 664 */

/**********************************************************
  *
  *   [platform_driver API]   平臺裝置驅動api
  *
  *********************************************************/
unsigned char g_reg_value_bq25601 = 0;
static ssize_t show_bq25601_access(struct device *dev, struct device_attribute *attr, char *buf)
{
	battery_log(BAT_LOG_CRTI, "[show_bq25601_access] 0x%x\n", g_reg_value_bq25601);
	return sprintf(buf, "%u\n", g_reg_value_bq25601);
}

static ssize_t store_bq25601_access(struct device *dev, struct device_attribute *attr,
				    const char *buf, size_t size)
{
	int ret = 0;
	char *pvalue = NULL, *addr, *val;
	unsigned int reg_value = 0;
	unsigned int reg_address = 0;

	battery_log(BAT_LOG_CRTI, "[store_bq25601_access]\n");

	if (buf != NULL && size != 0) {
		battery_log(BAT_LOG_CRTI, "[store_bq25601_access] buf is %s and size is %zu\n", buf, size);
		/*reg_address = kstrtoul(buf, 16, &pvalue);*/

		pvalue = (char *)buf;
		if (size > 3) { 
			addr = strsep(&pvalue, " "); //取地址
			ret = kstrtou32(addr, 16, (unsigned int *)&reg_address);
		} else
			ret = kstrtou32(pvalue, 16, (unsigned int *)&reg_address);

		if (size > 3) {
			val = strsep(&pvalue, " "); //取值
			ret = kstrtou32(val, 16, (unsigned int *)&reg_value);

			battery_log(BAT_LOG_CRTI,
			    "[store_bq25601_access] write bq25601 reg 0x%x with value 0x%x !\n",
			     reg_address, reg_value);
				 //引數1 暫存器的地址,引數2暫存器的 值 引數3 用於清零 引數4 移位的個數
				 //使能配置暫存器,通過i2c讀值在寫值
			ret = bq25601_config_interface(reg_address, reg_value, 0xFF, 0x0); 
		} else {////引數1 暫存器的地址,引數2暫存器的 值 引數3 用於清零 引數4 移位的個數
		//讀暫存器的值
			ret = bq25601_read_interface(reg_address, &g_reg_value_bq25601, 0xFF, 0x0);
			battery_log(BAT_LOG_CRTI,
			    "[store_bq25601_access] read bq25601 reg 0x%x with value 0x%x !\n",
			     reg_address, g_reg_value_bq25601);
			battery_log(BAT_LOG_CRTI,
			    "[store_bq25601_access] Please use \"cat bq25601_access\" to get value\r\n");
		}
	}
	return size;
}


/**********************************************************
  *
  *   [Internal Function]
  *
  *********************************************************/
void bq25601_hw_component_detect(void) //硬體探測通過i2c定址
{
	unsigned int ret = 0;
	unsigned char val = 0;

	ret = bq25601_read_interface(0x0B, &val, 0xF, 0x3);

	if (val == 0)
		g_bq25601_hw_exist = 0;
	else
		g_bq25601_hw_exist = 1;

	battery_log(BAT_LOG_CRTI, "[bq25601_hw_component_detect] exist=%d, Reg[0x0b][3-6]=0x%x\n", g_bq25601_hw_exist, val);
}

int is_bq25601_exist(void)
{
	battery_log(BAT_LOG_CRTI, "[is_bq25601_exist] g_bq25601_hw_exist=%d\n", g_bq25601_hw_exist);

	return g_bq25601_hw_exist;
}

void bq25601_dump_register(void)//讀bq25601所有儲存在暫存器的值
{
	int i = 0;

	battery_log(BAT_LOG_FULL, "[bq25601] ");
	for (i = 0; i < bq25601_REG_NUM; i++) {
		bq25601_read_byte(i, &bq25601_reg[i]);
		battery_log(BAT_LOG_CRTI, "bq25601_reg[0x%x]=0x%x\n", i, bq25601_reg[i]);
	}
	battery_log(BAT_LOG_FULL, "\n");
}


static void bq25601_parse_customer_setting(void)//解析充電狀態客製化
{
#ifdef CONFIG_OF
    struct pinctrl *pinctrl;
    struct pinctrl_state *ptrl_chren_low;
    pinctrl = devm_pinctrl_get(&new_client->dev);
    if (IS_ERR(pinctrl)) {
        battery_log(BAT_LOG_CRTI, "[%s]Cannot find drvvbus pinctrl, err=%d\n",
            __func__, (int)PTR_ERR(pinctrl));
        return;
    }
    ptrl_chren_low = pinctrl_lookup_state(pinctrl, "chren_low");
    if (IS_ERR(ptrl_chren_low)) {
        battery_log(BAT_LOG_CRTI, "[%s]Cannot find chren_low state, err=%d\n",
            __func__, (int)PTR_ERR(ptrl_chren_low));
        return;
    }
    pinctrl_select_state(pinctrl, ptrl_chren_low);
    devm_pinctrl_put(pinctrl);
    battery_log(BAT_LOG_CRTI, "[%s]pinctrl_select_state success\n", __func__);
#endif
}

static int bq25601_driver_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
	int err = 0;

	battery_log(BAT_LOG_CRTI, "[bq25601_driver_probe]\n");
	
	client->addr = 0x6b;
	//為new_client 分配一個記憶體空間
	new_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);

	if (!new_client) {
		err = -ENOMEM;
		goto exit;
	}
	memset(new_client, 0, sizeof(struct i2c_client));//清空new_client這個空間

	new_client = client;//把傳進去的client儲存
	
	//elink_charge_init(client);

	/* --------------------- */
	bq25601_hw_component_detect(); //硬體探測通過i2c定址
	bq25601_dump_register();//讀bq25601所有儲存在暫存器的值
	chargin_hw_init_done = KAL_TRUE; //將充電硬體初始化的標誌置位
    bq25601_parse_customer_setting();//解析充電狀態客製化

	return 0;

exit:
	return err;

}


/**********************************************************
  *
  *   [Internal Function]
  *
  *********************************************************/
/* CON0---------------------------------------------------- */
void bq25601_set_en_hiz(unsigned int val)  //使能
{ 
   啟用HIZ模式0-禁用(預設)1-啟用

	unsigned int ret = 0;
    printk("1111 bq25601_set_en_hiz\r\n");

	ret = bq25601_config_interface((unsigned char) (bq25601_CON0),
				       (unsigned char) (val),
				       (unsigned char) (CON0_EN_HIZ_MASK),
				       (unsigned char) (CON0_EN_HIZ_SHIFT)
	    );
}

void bq25601_set_ichg_mon(unsigned int val)
{
	unsigned int ret = 0;

	ret = bq25601_config_interface((unsigned char) (bq25601_CON0),
				       (unsigned char) (val),
				       (unsigned char) (CON0_ICHG_MON_MASK),
				       (unsigned char) (CON0_ICHG_MON_SHIFT)
	    );
}

void bq25601_set_iindpm(unsigned int val)
{
		輸入電流限制馬抵消:100範圍:100 mA (000000) -3.2 A (11111)預設:2400毫安(10111),
		最大輸入電流限制,不典型。輸入源檢測完成後,IINDPM位自動改變,PSEL = Hi = 500 mA PSEL = Lo= 2.4
		主機在輸入源檢測完成後,可以重寫IINDPM暫存器位。


	unsigned int ret = 0;

	ret = bq25601_config_interface((unsigned char) (bq25601_CON0),
				       (unsigned char) (val),
				       (unsigned char) (CON0_IINDPM_MASK),
				       (unsigned char) (CON0_IINDPM_SHIFT)
	    );
}

/* CON1---------------------------------------------------- */
void bq25601_set_pfm_dis(unsigned int val)
{

   評論預設值:0 -啟用
   
    unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON1), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON1_PFM_DIS_MASK),
                                    (unsigned char)(CON1_PFM_DIS_SHIFT)
                                    );
}

void bq25601_set_wdt_rst(unsigned int val)
{預設:正常(0)回到0後,看門狗定時器重置
    unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON1), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON1_WDT_RST_MASK),
                                    (unsigned char)(CON1_WDT_RST_SHIFT)
                                    );
}

void bq25601_set_otg_config(unsigned int val)
{預設:OTG禁用(0)1。OTG配置將超越。在CHG配置中啟用充電功能
    unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON1), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON1_OTG_CONFIG_MASK),
                                    (unsigned char)(CON1_OTG_CONFIG_SHIFT)
                                    );
}

void bq25601_set_chg_config(unsigned int val)
{0-電荷禁用1-電荷啟用 預設:充電電池(1)
	注意:1。在電荷cE引腳在拉低和chg_config是1這兩種情況下,電荷啟用。
    unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON1), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON1_CHG_CONFIG_MASK),
                                    (unsigned char)(CON1_CHG_CONFIG_SHIFT)
                                    );
}

void bq25601_set_sys_min(unsigned int val)
{
系統最小電壓
1000:2.6 v| 001:2.8 v|010: 3V 1011: 3.2V 100: 3.4 V 101: 3.5 V 110: 3.6 V| 111:3.7 v|預設值:3.5 V (101)
    unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON1), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON1_SYS_MIN_MASK),
                                    (unsigned char)(CON1_SYS_MIN_SHIFT)
                                    );
}

void bq25601_set_min_vbat_sel(unsigned int val)
{
0-2.8 V蝙蝠墜落,聖通過再保險1-2.5 V蝙蝠墜落
OTG模式的最小電池電壓。預設下降 2.8 V (0);
上升閾值 3.0 V (0)

    unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON1), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON1_MIN_VBAT_SEL_MASK),
                                    (unsigned char)(CON1_MIN_VBAT_SEL_SHIFT)
                                    );
}

/* CON2---------------------------------------------------- */

void bq25601_set_boost_lim(unsigned int val)
{預設值:1.2 A (1)•
列出的當前限制選項是。最小電流限制規格。

    unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON2), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON2_BOOST_LIM_MASK),
                                    (unsigned char)(CON2_BOOST_LIM_SHIFT)
                                    );
}

void bq25601_set_q1_fullon(unsigned int val)
{
當IINDPM <700mA(更準確)時0-使用較高的Q1 RDSON值1-使用較低的Q1 RDSON值(更有效)
在boost模式下,總是使用全場效應電晶體,而這個位沒有任何影響-使用較低的Q1 alwavs(效率更高)

    unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON2), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON2_Q1_FULLON_MASK),
                                    (unsigned char)(CON2_Q1_FULLON_SHIFT)
                                    );
}

void bq25601_set_ichg(unsigned int val)
{
快速充電電流預設值:2040mA(100010)
範圍:0mA (0000000)-3000 mA (110010)
注意:ICHG = 0 mA禁用電荷。
ICHG > 3000ma(110010夾緊註冊值3000ma (110010))
    unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON2), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON2_ICHG_MASK),
                                    (unsigned char)(CON2_ICHG_SHIFT)
                                    );
}

/* CON3---------------------------------------------------- */

void bq25601_set_iprechg(unsigned int val)
{
預先充電電流預設值:180ma (0010)抵消:60ma
注:IPRECHG> 780 mA夾緊到780 mA (1100)

    unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON3), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON3_IPRECHG_MASK),
                                    (unsigned char)(CON3_IPRECHG_SHIFT)
                                    );
}

void bq25601_set_iterm(unsigned int val)
{

終止充電電流預設值:180ma (0010)抵消:60ma
    unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON3), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON3_ITERM_MASK),
                                    (unsigned char)(CON3_ITERM_SHIFT)
                                    );
}

/* CON4---------------------------------------------------- */

void bq25601_set_vreg(unsigned int val)
{

Tg |512 mV T |256 mV | 128 mV gT64 mVgT 32 mV g
充電電壓抵消:3.856 V範圍:3.856 V至4.624 V (11000)
預設值:4.208 V (01011)特殊的價值:(01111):4.352 V注:超過11000 (4.624 V)的值夾緊,註冊值11000 (4.624 V)
    unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON4), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON4_VREG_MASK),
                                    (unsigned char)(CON4_VREG_SHIFT)
                                    );
}

void bq25601_set_topoff_timer(unsigned int val)
{
滿足終止條件後的延長時間。當禁用時,當滿足終止條件時充電終止
00-Disabled(預設)101 - 15分鐘10 - 30分鐘11-45分鐘
    unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON4), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON4_TOPOFF_TIMER_MASK),
                                    (unsigned char)(CON4_TOPOFF_TIMER_SHIFT)
                                    );
}

void bq25601_set_vrechg(unsigned int val)
{
充值閾值預設值:100mV (0)
    unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON4), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON4_VRECHG_MASK),
                                    (unsigned char)(CON4_VRECHG_SHIFT)
                                    );
}

/* CON5---------------------------------------------------- */

void bq25601_set_en_term(unsigned int val)
{0-禁用1-啟用預設:啟用終止(1)
    unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON5), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON5_EN_TERM_MASK),
                                    (unsigned char)(CON5_EN_TERM_SHIFT)
                                    );
}

void bq25601_set_watchdog(unsigned int val)
{ 
00-禁用定時器,01-40 s, 10 80 s。11-160 s預設值:40 s (01)
    unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON5), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON5_WATCHDOG_MASK),
                                    (unsigned char)(CON5_WATCHDOG_SHIFT)
                                    );
}

void bq25601_set_en_timer(unsigned int val)
{
| 0 -禁用
  1啟用快速充電和預充電計時器  預設值:使(1)  
    unsigned int ret=0;    

  unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON5), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON5_EN_TIMER_MASK),
                                    (unsigned char)(CON5_EN_TIMER_SHIFT)
                                    );
}

void bq25601_set_chg_timer(unsigned int val)
{ 
0-5小時
1-10小時  預設值:10小時(1)


    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON5), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON5_CHG_TIMER_MASK),
                                    (unsigned char)(CON5_CHG_TIMER_SHIFT)
                                    );
}

void bq25601_set_treg(unsigned int val)
{

熱調節閾值:  0-90°C   1 -   110°C
預設值:110°C(1)
    unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON5), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON5_TREG_MASK),
                                    (unsigned char)(CON5_TREG_SHIFT)
                                    );
}

void bq25601_set_jeita_iset(unsigned int val)
{
   0 -50% lCHG
   1-20% ICHG           預設值:20%(1)
	
	unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON5), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON5_JEITA_ISET_MASK),
                                    (unsigned char)(CON5_JEITA_ISET_SHIFT)
                                    );
}

/* CON6---------------------------------------------------- */

void bq25601_set_ovp(unsigned int val)
{
預設值 6.5v 01
VAC OVP閾值:00-55V
01-6.5 V (5-V輸入)
10-10.5 V (9-V輸入)
11    14v (12-V輸入)
unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON6), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON6_OVP_MASK),
                                    (unsigned char)(CON6_OVP_SHIFT)
                                    );
}

void bq25601_set_boostv(unsigned int val)
{
提升調節電壓:00-4.85V 01 - 5.00 v 10 - 5.15 v 11 - 5.30 v
    unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON6), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON6_BOOSTV_MASK),
                                    (unsigned char)(CON6_BOOSTV_SHIFT)
                                    );
}

void bq25601_set_vindpm(unsigned int val)
{
800 MV 400 MV 200 MV 100 MV
絕對VINDPM閾值。抵消:3.9 V範圍:3.9 V (0000)-5.4 (1111)у預設值:4.5 v(0110)
    unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON6), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON6_VINDPM_MASK),
                                    (unsigned char)(CON6_VINDPM_SHIFT)
                                    );
}

/* CON7---------------------------------------------------- */

void bq25601_set_iindet_en(unsigned int val)
{
    0-沒有輸入電流限制  1 檢測當VBUS存在時,力輸入電流極限檢測  輸入檢測完成後返回0
	unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON7), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON7_IINDET_EN_MASK),
                                    (unsigned char)(CON7_IINDET_EN_SHIFT)
                                    );
}
void bq25601_set_tmr2x_en(unsigned int val)
{
    0-Disable一1 -在輸入DPM (V和I)或JEITA cool或heat requlation期間,安全計時器減慢2倍
	
	unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON7), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON7_TMR2X_EN_MASK),
                                    (unsigned char)(CON7_TMR2X_EN_SHIFT)
                                    );
}

void bq25601_set_batfet_disable(unsigned int val)
{
    O -允許Q4開啟,1 -關閉第04ith預設:允許Q4開啟(0)推遲時間
	unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON7), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON7_BATFET_Disable_MASK),
                                    (unsigned char)(CON7_BATFET_Disable_SHIFT)
                                    );
}

void bq25601_set_jeita_vset(unsigned int val)
{
    0 將充電電壓設定為4.1v  1 將充電電壓設定為VREG
	unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON7), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON7_JEITA_VSET_MASK),
                                    (unsigned char)(CON7_JEITA_VSET_SHIFT)
                                    );
}

void bq25601_set_batfet_dly(unsigned int val)
{
    0  當BATFET DIS位被設定時,立即關閉BATEET 
	1 當BATEFT DIS位被設定時 ,在延時(typ。10秒
	)後關閉BATFET,
	-
	預設值:1在t後關閉BATFET,(typ。10秒
	)噹噹BATEFT DIS位被設定時
	
	unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON7), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON7_BATFET_DLY_MASK),
                                    (unsigned char)(CON7_BATFET_DLY_SHIFT)
                                    );
}

void bq25601_set_batfet_rst_en(unsigned int val)
{
0-禁用BATFET復位函式1-啟用BATFET復位函式預設值:1啟用BATFET復位功能。  

  unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON7), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON7_BATFET_RST_EN_MASK),
                                    (unsigned char)(CON7_BATFET_RST_EN_SHIFT)
                                    );
}

void bq25601_set_vdpm_bat_track(unsigned int val)
{
  00 -禁用功能(註冊設定VINDPM)   0 1 - vbat + 200 mv 10 - vbat + 250 mv 11 - vbat + 300 mv
  設定VINDPM以跟蹤BAT電壓。
  實際的VINDPM在暫存器值和VBAT+ VDPM 


   unsigned int ret=0;    

    ret=bq25601_config_interface(   (unsigned char)(bq25601_CON7), 
                                    (unsigned char)(val),
                                    (unsigned char)(CON7_VDPM_BAT_TRACK_MASK),
                                    (unsigned char)(CON7_VDPM_BAT_TRACK_SHIFT)
                                    );
}

/* CON8---------------------------------------------------- */

unsigned int bq25601_get_system_status_con8(void)
{
系統狀態位  
  unsigned int ret=0;
    unsigned char val=0;

    ret=bq25601_read_interface(     (unsigned char)(bq25601_CON8), 
                                    (&val),
                                    (unsigned char)(0xFF),
                                    (unsigned char)(0x0)
                                    );
	
    return val;
}

unsigned int bq25601_get_vbus_stat(void)
{
通風裝置狀態暫存器
000:沒有輸入
001:USB主機SDP(500毫安)→PSEL HIGH
010:2.4介面卡→PSEL低
111:OTG
軟體當前限制在IINDPM暫存器中報告   

   unsigned int ret=0;
    unsigned char val=0;

    ret=bq25601_read_interface(     (unsigned char)(bq25601_CON8), 
                                    (&val),
                                    (unsigned char)(CON8_VBUS_STAT_MASK),
                                    (unsigned char)(CON8_VBUS_STAT_SHIFT)
                                    );
	
    return val;
}

unsigned int bq25601_get_chrg_stat(void)
{
    充電狀態:00-Not充電 01-Pre-charge(< VBATLOw) 10-Fast充電 11充電終止
	
	unsigned int ret=0;
    unsigned char val=0;

    ret=bq25601_read_interface(     (unsigned char)(bq25601_CON8), 
                                    (&val),
                                    (unsigned char)(CON8_CHRG_STAT_MASK),
                                    (unsigned char)(CON8_CHRG_STAT_SHIFT)
                                    );
	
    return val;
}

unsigned int bq25601_get_pg_stat(void)
{
功率良好狀態:0-功率不好 1 能力好
unsigned int ret=0;
    unsigned char val=0;

    ret=bq25601_read_interface(     (unsigned char)(bq25601_CON8), 
                                    (&val),
                                    (unsigned char)(CON8_PG_STAT_MASK),
                                    (unsigned char)(CON8_PG_STAT_SHIFT)
                                    );
    
    return val;
}

unsigned int bq25601_get_therm_stat(void)
{
0  不是在其他mai監管中
1-在其他mai監管中   

   unsigned int ret=0;
    unsigned char val=0;

    ret=bq25601_read_interface(     (unsigned char)(bq25601_CON8), 
                                    (&val),
                                    (unsigned char)(CON8_THERM_STAT_MASK),
                                    (unsigned char)(CON8_THERM_STAT_SHIFT)
                                    );
    
    return val;
}


unsigned int bq25601_get_vsys_stat(void)
{
    0-非VSYSMin射頻監管中(BAT > VSYSMin)
	1- VSYSMin射頻監管中(BAT <VSYSMin)
	
	unsigned int ret=0;
    unsigned char val=0;

    ret=bq25601_read_interface(     (unsigned char)(bq25601_CON8), 
                                    (&val),
                                    (unsigned char)(CON8_VSYS_STAT_MASK),
                                    (unsigned char)(CON8_VSYS_STAT_SHIFT)
                                    );
	
    return val;
}

/* CON9---------------------------------------------------- */

unsigned int bq25601_get_system_status_con9(void)
{
得到系統狀態
    unsigned int ret=0;
    unsigned char val=0;

    ret=bq25601_read_interface(     (unsigned char)(bq25601_CON9), 
                                    (&val),
                                    (unsigned char)(0xFF),
                                    (unsigned char)(0x0)
                                    );
    
    return val;
}

/* CON10---------------------------------------------------- */

unsigned int bq25601_get_system_status_con10(void)
{
得到系統狀態 
 unsigned int ret=0;
    unsigned char val=0;

    ret=bq25601_read_interface(     (unsigned char)(bq25601_CON10), 
                                    (&val),
                                    (unsigned char)(0xFF),
                                    (unsigned char)(0x0)
                                    );
    
    return val;
}

void bq25601_set_vindpm_int_mask(unsigned int val)
{
    0-Not VINDPM。1 VINDPM
	unsigned int ret=0;

    ret=bq25601_config_interface(     (unsigned char)(bq25601_CON10), 
                                    (val),
                                    (unsigned char)(CON10_VINDPM_INT_MASK),
                                    (unsigned char)(CON10_VINDPM_INT_SHIFT)
                                    );
    
}

void bq25601_set_iindpm_int_mask(unsigned int val)
{
 0-Not in IINDPM. 1-in IINDPMI   
   unsigned int ret=0;

    ret=bq25601_config_interface(     (unsigned char)(bq25601_CON10), 
                                    (val),
                                    (unsigned char)(CON10_IINDPM_INT_MASK),
                                    (unsigned char)(CON10_IINDPM_INT_SHIFT)
                                    );
    
}

/* CON11---------------------------------------------------- */
unsigned int bq25601_get_system_status_con11(void)
{
    獲取系統狀態
	unsigned int ret=0;
    unsigned char val=0;

    ret=bq25601_read_interface(     (unsigned char)(bq25601_CON11), 
                                    (&val),
                                    (unsigned char)(0xFF),
                                    (unsigned char)(0x0)
                                    );
    
    return val;
}

void bq25601_set_reg_rst(unsigned int val)
{
暫存器復位
0保持當前暫存器設定
1-Reset to default暫存器值和reset safety timer
注意:在暫存器重置完成後,位重置為0
unsigned int ret=0;

    ret=bq25601_config_interface(     (unsigned char)(bq25601_CON11), 
                                    (val),
                                    (unsigned char)(CON11_REG_RST_MASK),
                                    (unsigned char)(CON11_REG_RST_SHIFT)
                                    );
    
}


/**********************************************************
  *
  *   [Read / Write Function]
  *
  *********************************************************/
unsigned int bq25601_read_interface(unsigned char RegNum, unsigned char *val, unsigned char MASK,
				  unsigned char SHIFT)
{
	unsigned char bq25601_reg = 0;
	int ret = 0;

	battery_log(BAT_LOG_FULL, "--------------------------------------------------\n");

	ret = bq25601_read_byte(RegNum, &bq25601_reg);

	battery_log(BAT_LOG_FULL, "[bq25601_read_interface] Reg[%x]=0x%x\n", RegNum, bq25601_reg);

	bq25601_reg &= (MASK << SHIFT);
	*val = (bq25601_reg >> SHIFT);

	battery_log(BAT_LOG_FULL, "[bq25601_read_interface] val=0x%x\n", *val);

	return ret;
}

unsigned int bq25601_config_interface(unsigned char RegNum, unsigned char val, unsigned char MASK,
				    unsigned char SHIFT)
{
	unsigned char bq25601_reg = 0;
	int ret = 0;

	battery_log(BAT_LOG_FULL, "--------------------------------------------------\n");
    printk("11111bq25601_config_interface\r\n");
	ret = bq25601_read_byte(RegNum, &bq25601_reg);
	battery_log(BAT_LOG_FULL, "[bq25601_config_interface] Reg[%x]=0x%x\n", RegNum, bq25601_reg);

	bq25601_reg &= ~(MASK << SHIFT);
	bq25601_reg |= (val << SHIFT);

	ret = bq25601_write_byte(RegNum, bq25601_reg);
	battery_log(BAT_LOG_FULL, "[bq25601_config_interface] write Reg[%x]=0x%x\n", RegNum, bq25601_reg);

	/* Check */
	/* bq25601_read_byte(RegNum, &bq25601_reg); */
	/* battery_log(BAT_LOG_FULL, "[bq25601_config_interface] Check Reg[%x]=0x%x\n", RegNum, bq25601_reg); */

	return ret;
}

/* write one register directly */ //直接寫一個暫存器
unsigned int bq25601_reg_config_interface(unsigned char RegNum, unsigned char val)
{
	unsigned int ret = 0;

	ret = bq25601_write_byte(RegNum, val);

	return ret;
}


/**********************************************************
  *
  *   [I2C Function For Read/Write bq25601]
  *
  *********************************************************/
int bq25601_read_byte(unsigned char cmd, unsigned char *returnData)
{
		char     readData = 0;
	int      ret = 0;
	struct i2c_msg msg[2];
	struct i2c_adapter *adap = new_client->adapter;
    printk("1111bq25601_read_byte\r\n");

	mutex_lock(&bq25601_i2c_access);
	msg[0].addr = new_client->addr;
	msg[0].flags = 0;
	msg[0].len = 1;
	msg[0].buf = &cmd;

	msg[1].addr = new_client->addr;
	msg[1].flags = I2C_M_RD;
	msg[1].len = 1;
	msg[1].buf = &readData;

	ret = i2c_transfer(adap, msg, 2);
	if (ret < 0) {
		mutex_unlock(&bq25601_i2c_access);
		return 0;
	}
	*returnData = readData;

	mutex_unlock(&bq25601_i2c_access);
	return 1;
}

int bq25601_write_byte(unsigned char cmd, unsigned char writeData)
{
	char write_data[2] = { 0 };
	int ret = 0;
	struct i2c_msg msg;
	struct i2c_adapter *adap = new_client->adapter;

	mutex_lock(&bq25601_i2c_access);
	write_data[0] = cmd;
	write_data[1] = writeData;
	msg.addr = new_client->addr;
	msg.flags = 0;
	msg.len = 2;
	msg.buf = (char *)write_data;

	ret = i2c_transfer(adap, &msg, 1);
	if (ret < 0) {
		mutex_unlock(&bq25601_i2c_access);
		return 0;
	}

	mutex_unlock(&bq25601_i2c_access);
	return 1;
}



/**********************************************************
  *
  *   [I2C Slave Setting]
  *
  *********************************************************/
#define bq25601_SLAVE_ADDR_WRITE   0xD6
#define bq25601_SLAVE_ADDR_READ    0xD7

static struct i2c_client *new_client;
static const struct i2c_device_id bq25601_i2c_id[] = { {"bq25601", 0}, {} };

kal_bool chargin_hw_init_done = KAL_FALSE;
static int bq25601_driver_probe(struct i2c_client *client, const struct i2c_device_id *id);

#ifdef CONFIG_OF
static const struct of_device_id bq25601_of_match[] = {
	{.compatible = "bq25601",},
	{},
};

MODULE_DEVICE_TABLE(of, bq25601_of_match);
#endif

static struct i2c_driver bq25601_driver = {
	.driver = {
		   .name = "bq25601",
#ifdef CONFIG_OF
		   .of_match_table = bq25601_of_match,
#endif
		   },
	.probe = bq25601_driver_probe,
	.id_table = bq25601_i2c_id,
};

/**********************************************************
  *
  *   [Global Variable]
  *
  *********************************************************/
unsigned char bq25601_reg[bq25601_REG_NUM] = { 0 };

static DEFINE_MUTEX(bq25601_i2c_access);

int g_bq25601_hw_exist = 0;

/**********************************************************