/*
* set 1 --- enable_charger; 0 --- disable charger
*
*/
static ssize_t bq2416x_set_enable_charger(struct device *dev,	
				  struct device_attribute *attr,
				  const char *buf, size_t count)
{
	long val;
	int status = count;
    long int events = BQ2416x_START_CHARGING;
	struct bq2416x_device_info *di = dev_get_drvdata(dev);

	if ((strict_strtol(buf, 10, &val) < 0) || (val < 0) || (val > 1))
		return -EINVAL;

	di->enable_ce = val ^ 0x1;

	di->factory_flag = val ^ 0x1;
    bq2416x_config_control_reg(di);

    if(!di->factory_flag){
        events = BQ2416x_START_CHARGING;
    } else {
        events = BQ2416x_NOT_CHARGING;
    }

    blocking_notifier_call_chain(&notifier_list, events, NULL);
	return status;
}
static ssize_t bq2416x_set_calling_limit(struct device *dev,
				  struct device_attribute *attr,
				  const char *buf, size_t count)
{
	long val;
	int status = count;
	struct bq2416x_device_info *di = dev_get_drvdata(dev);
	if ((strict_strtol(buf, 10, &val) < 0) || (val < 0) || (val > 1))
		return -EINVAL;

	di->calling_limit = val;
	if (di->charger_source == POWER_SUPPLY_TYPE_MAINS){
		if(di->calling_limit){
			di->cin_limit = IINLIM_800;
			dev_info(di->dev,"calling_limit_current = %d\n", di->cin_limit);
		}else{
            di->battery_temp_status = -1;
            di->cin_limit = di->max_cin_currentmA;
        }
        bq2416x_config_control_reg(di);
	}
	else{
		di->calling_limit = 0;
	}

	return status;
}
예제 #3
0
static void
bq2416x_charger_update_status(struct bq2416x_device_info *di)
{
	u8 read_reg[8] = {0};

	timer_fault = 0;
	bq2416x_read_block(di, &read_reg[0], 0, 8); 

	if ((read_reg[0] & 0x70) == 0x50)   
		dev_dbg(di->dev, "CHARGE DONE\n");

	if ((read_reg[0] & 0x7) == 0x4) 
		timer_fault = 1;
     
	if (read_reg[0] & 0x7) {
		di->cfg_params = 1;
		dev_err(di->dev, "CHARGER STATUS = %x\n", read_reg[0]);
	}

    if ((read_reg[1] & 0x6) == 0x2) {
        di->hz_mode = 1;
        bq2416x_config_control_reg(di);
        bq2416x_write_byte(di, di->voltage_reg, REG_BATTERY_VOLTAGE);
        dev_err(di->dev, "battery ovp = %x,%x\n", read_reg[1],read_reg[3]);
        msleep(700);
        di->hz_mode = 0;
        bq2416x_config_control_reg(di);
    }

	if (is_bq27510_battery_exist(g_battery_measure_by_bq27510_device)){
		bq2416x__charge_status(di);
	}

	if ((timer_fault == 1) || (di->cfg_params == 1)) {
		bq2416x_write_byte(di, di->control_reg, REG_CONTROL_REGISTER);
		bq2416x_write_byte(di, di->voltage_reg, REG_BATTERY_VOLTAGE);
		bq2416x_write_byte(di, di->current_reg, REG_BATTERY_CURRENT);
		bq2416x_write_byte(di, di->dppm_reg, REG_DPPM_VOLTAGE);
		bq2416x_config_safety_reg(di); 
		di->cfg_params = 0;
	}

	/* reset 32 second timer */
	bq2416x_config_status_reg(di);

	return;
}
static void bq2416x_start_ac_charger(struct bq2416x_device_info *di)
{
   long int  events = BQ2416x_START_AC_CHARGING;
	   
   /*set gpio_174 low level for CD pin to enable bq24161 IC*/
	gpio_set_value(ENABLE_BQ2416x_CHARGER, 0);

	blocking_notifier_call_chain(&notifier_list, events, NULL);

	di->charger_source = POWER_SUPPLY_TYPE_MAINS;
	di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
	di->calling_limit = 0;
    di->factory_flag = 0;

    di->battery_temp_status = -1;

	di->dppm_voltagemV = VINDPM_MIN_4200;
	di->cin_limit = di->max_cin_currentmA;
	di->currentmA = di->max_currentmA ;
    di->voltagemV = di->max_voltagemV;
    di->term_currentmA = ITERM_MIN_50;
	di->enable_ce = ENABLE_CHARGER;     /*enable charger*/
	di->enable_iterm = ENABLE_ITERM;    /*enable charge current termination*/
    di->hz_mode = DIS_HIZ;
    di->safety_timer = TMR_X_9;
    di->enable_low_chg = DISABLE_LOW_CHG;

	bq2416x_config_control_reg(di);
	bq2416x_config_voltage_reg(di);
	bq2416x_config_current_reg(di);
    bq2416x_config_dppm_voltage_reg(di,di->dppm_voltagemV);
    bq2416x_config_safety_reg(di);
    bq2416x_config_watchdog_reg(di);

	schedule_delayed_work(&di->bq2416x_charger_work,
						msecs_to_jiffies(0));

	dev_info(di->dev,"%s, ---->START AC CHARGING, \n"
	                  "battery current = %d mA\n"
	                  "battery voltage = %d mV\n"
	                  , __func__, di->currentmA, di->voltagemV);
    di->battery_present = is_bq27510_battery_exist(g_battery_measure_by_bq27510_device);
	if (!di->battery_present){
		dev_info(di->dev, "BATTERY NOT DETECTED!\n");
		events = BQ2416x_NOT_CHARGING;
		blocking_notifier_call_chain(&notifier_list, events, NULL);
		di->charge_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
	}
    di->wakelock_enabled = 1;
    if (di->wakelock_enabled)
        wake_lock(&di->charger_wake_lock);
	return;
}
static ssize_t bq2416x_set_enable_itermination(struct device *dev,
				  struct device_attribute *attr,
				  const char *buf, size_t count)
{
	long val;
	int status = count;
	struct bq2416x_device_info *di = dev_get_drvdata(dev);

	if ((strict_strtol(buf, 10, &val) < 0) || (val < 0) || (val > 1))
		return -EINVAL;
	di->enable_iterm = val;
	bq2416x_config_control_reg(di);

	return status;
}
/*
* set 1 --- enable_charger; 0 --- disable charger
*
*/
static ssize_t bq2416x_set_enable_charger(struct device *dev,	
				  struct device_attribute *attr,
				  const char *buf, size_t count)
{
	long val;
	int status = count;
	struct bq2416x_device_info *di = dev_get_drvdata(dev);
	if ((strict_strtol(buf, 10, &val) < 0) || (val < 0) || (val > 1))
		return -EINVAL;
	di->enable_ce = val ^ 0x1;
	bq2416x_config_control_reg(di);
	di->factory_flag = di->enable_ce;
	bq2416x__charge_status(di);
	return status;
}
예제 #7
0
/*di->enable_ce = 0,charger enable and display charging status
  di->enable_ce = 1 or USB supply fault,charger disable and display not charging status*/
static void
bq2416x__charge_status(struct bq2416x_device_info *di)
{
	long int events=BQ2416x_START_CHARGING;
	u8 read_reg[8] = {0};
    int battery_capacity = 0;

	bq2416x_read_block(di, &read_reg[0], 0, 2);

	if((read_reg[1] & BQ2416x_FAULT_VBUS_VUVLO) == BQ2416x_FAULT_VBUS_OVP){
		dev_err(di->dev, " POWER_SUPPLY_OVERVOLTAGE = %x\n",read_reg[1]);
		events = POWER_SUPPLY_OVERVOLTAGE;
		blocking_notifier_call_chain(&notifier_list, events, NULL);
		return;
	}

	if ((read_reg[0] & BQ2416x_VUSB_FAULT) == BQ2416x_CHARGING_FROM_USB){
				events = BQ2416x_START_CHARGING;
	}
	else if((di->enable_ce == DISABLE_CE)
		|| ((read_reg[0] & POWER_SUPPLY_STATE_FAULT) == POWER_SUPPLY_STATE_FAULT)){
		dev_err(di->dev, " BQ2416x_NOT_CHARGING \n");
		events = BQ2416x_NOT_CHARGING;
	}

	else if((read_reg[0] & BQ2416x_VUSB_FAULT) == BQ2416x_CHARGE_DONE){
        battery_capacity = bq27510_battery_capacity(g_battery_measure_by_bq27510_device);
        if((!is_bq27510_battery_full(g_battery_measure_by_bq27510_device))||(battery_capacity !=100)){
            dev_info(di->dev, "charge_done_battery_capacity=%d\n",battery_capacity);
            di->hz_mode = 1; /*enable bq2416x charger high impedance mode*/
            bq2416x_write_byte(di, di->control_reg | di->hz_mode, REG_CONTROL_REGISTER);
            di->hz_mode = 0; /*disable bq2416x charger high impedance mode*/
            msleep(700);
            bq2416x_config_control_reg(di);
            events = BQ2416x_START_CHARGING;
        } else{
            events = BQ2416x_CHARGE_DONE;
       }
     }
	else{
	     events=BQ2416x_START_CHARGING;
		dev_dbg(di->dev, "BQ2416x_START_CHARGING !\n");
	}
	if(di->charger_source == POWER_SUPPLY_TYPE_BATTERY){
		return;
	}
	blocking_notifier_call_chain(&notifier_list, events, NULL);
}
void bq2416x_open_inner_fet(struct bq2416x_device_info *di)
{
    	u8 en_nobatop = 0;
		
		bq2416x_read_byte(di, &en_nobatop, REG_BATTERY_AND_SUPPLY_STATUS);
       if(g_battery_measure_by_bq27510_device &&
          is_bq27510_battery_exist(g_battery_measure_by_bq27510_device) ){
        	di->enable_iterm = ENABLE_ITERM;
        	en_nobatop = en_nobatop & (~EN_NOBATOP);
        }else {
        	di->enable_iterm = DISABLE_ITERM;
        	en_nobatop = en_nobatop | EN_NOBATOP;
        }
	bq2416x_config_control_reg(di);
	bq2416x_write_byte(di, en_nobatop, REG_BATTERY_AND_SUPPLY_STATUS);
}
static ssize_t bq2416x_set_cin_limit(struct device *dev,
				  struct device_attribute *attr,
				  const char *buf, size_t count)
{
	long val;
	int status = count;
	struct bq2416x_device_info *di = dev_get_drvdata(dev);

	if ((strict_strtol(buf, 10, &val) < 0) || (val < 100)
					|| (val > di->max_currentmA))
		return -EINVAL;
	di->cin_limit = val;
	bq2416x_config_control_reg(di);

	return status;
}
static void bq2416x_open_inner_fet(struct bq2416x_device_info *di)
{
    u8 en_nobatop = 0;
		
    bq2416x_read_byte(di, &en_nobatop, REG_BATTERY_AND_SUPPLY_STATUS_REG01);

    if(di->battery_present){
        di->enable_iterm = ENABLE_ITERM;
        en_nobatop = en_nobatop & (~EN_NOBATOP);
    }else {
        di->enable_iterm = DISABLE_ITERM;
        en_nobatop = en_nobatop | EN_NOBATOP;
    }

    bq2416x_config_control_reg(di);
    bq2416x_write_byte(di, en_nobatop, REG_BATTERY_AND_SUPPLY_STATUS_REG01);
}
static void bq2416x_start_ac_charger(struct bq2416x_device_info *di)
{
       long int  events;
	   
      /*set gpio_174 low level for CD pin to enable bq24161 IC*/
	gpio_set_value(BQ2416X_GPIO_174, 0);
	events = BQ2416x_START_AC_CHARGING;
	blocking_notifier_call_chain(&notifier_list, events, NULL);
	di->enable_ce = ENABLE_CE;    /*enable charger*/
	di->enable_iterm = ENABLE_ITERM; /*enable charge current termination*/
	
	if(! g_battery_measure_by_bq27510_device)
        	return ;
	di->charger_source = POWER_SUPPLY_TYPE_MAINS;
	di->charge_status = POWER_SUPPLY_STATUS_CHARGING;

	di->calling_limit = set_zero;
	di->dppm_voltagemV = VOLT_DPPM_ADJUST_AC;
	di->cin_limit = CURRENT_AC_LIMIT_IN;
	di->currentmA = di->max_currentmA ;
	bq2416x_config_control_reg(di);
	bq2416x_config_voltage_reg(di);
	bq2416x_config_current_reg(di);
    bq2416x_config_dppm_voltage_reg(di,di->dppm_voltagemV);
#if BQ2416X_USE_WAKE_LOCK
	wake_lock(&di->charger_wake_lock);
#endif
	schedule_delayed_work(&di->bq2416x_charger_work,
						msecs_to_jiffies(0));

	dev_info(di->dev,"%s, ---->START AC CHARGING, \n"
	                  "battery current = %d mA\n"
	                  "battery voltage = %d mV\n"
	                  , __func__, di->currentmA, di->voltagemV);

	if (!is_bq27510_battery_exist(g_battery_measure_by_bq27510_device)){
		dev_dbg(di->dev, "BATTERY NOT DETECTED!\n");
		events = BQ2416x_NOT_CHARGING;
		blocking_notifier_call_chain(&notifier_list, events, NULL);
		di->charge_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
		di->enable_low_chg = DISABLE_LOW_CHG;
		bq2416x_config_safety_reg(di);
	}
}
static void bq2416x_stop_charger(struct bq2416x_device_info *di)
{
       long int  events;

	dev_info(di->dev,"%s,---->STOP CHARGING\n", __func__);

	di->calling_limit = set_zero;
		di->enable_hotcold_temp_charge = set_one;
	di->factory_flag = set_zero; 
	di->enable_ce = DISABLE_CE;
	di->hz_mode = set_zero; /*not high impedance mode*/
	bq2416x_config_control_reg(di);
#if BQ2416X_USE_WAKE_LOCK
       if (POWER_SUPPLY_TYPE_MAINS == di->charger_source)
	    wake_unlock(&di->charger_wake_lock);
#endif
	di->charger_source = POWER_SUPPLY_TYPE_BATTERY;
	di->charge_status = POWER_SUPPLY_STATUS_DISCHARGING;
	cancel_delayed_work_sync(&di->bq2416x_charger_work);
	events = BQ2416x_STOP_CHARGING;
	blocking_notifier_call_chain(&notifier_list, events, NULL);
	/*set gpio_174 high level for CD pin to disable bq24161 IC */
	gpio_set_value(BQ2416X_GPIO_174, 1);
}
static int bq2416x_charger_event(struct notifier_block *nb, unsigned long event,
				void *_data)
{

	printk("%s,---->enter bq2416x_charger_event\n", __func__);

	struct bq2416x_device_info *di;
	struct charge_params *data;
	u8 read_reg[8] = {0};
	int ret = 0;

	di = container_of(nb, struct bq2416x_device_info, nb);
	data = &di->params;
	di->cfg_params = 1;

	if (event & BQ2416x_CHARGER_FAULT) {
		bq2416x_read_block(di, &read_reg[0], 0, 8);
		ret = read_reg[0] & 0x7F;
		return ret;
	}

	if (data->enable == 0) {
		di->currentmA = data->currentmA;
		di->voltagemV = data->voltagemV;
		di->enable_iterm = data->enable_iterm;
	}
       if ((event & BQ2416x_DEFAULT_USB_CHARGING ) && (di->active == 0)) {
		 di->cin_limit = 500;
	       bq2416x_config_control_reg(di);
	       bq2416x_config_voltage_reg(di);
	       bq2416x_config_current_reg(di);
		bq2416x_config_dppm_voltage_reg(di,di->dppm_voltagemV);	   	
		schedule_delayed_work(&di->bq2416x_charger_work,
						msecs_to_jiffies(0));
		di->active = 1;	   	
       }
	if ((event & BQ2416x_START_AC_CHARGING) && (di->active == 0)) {
		di->cin_limit = 1000;
	       bq2416x_config_control_reg(di);
	       bq2416x_config_voltage_reg(di);
	       bq2416x_config_current_reg(di);
		bq2416x_config_dppm_voltage_reg(di,di->dppm_voltagemV);	
		printk("%s, charging with VAC\n", __func__);	
		schedule_delayed_work(&di->bq2416x_charger_work,
						msecs_to_jiffies(0));
		di->active = 1;
	}
	
	if ((event & BQ2416x_START_USB_CHARGING) && (di->active == 0)) { 
		di->cin_limit = 500;
	       bq2416x_config_control_reg(di);
	       bq2416x_config_voltage_reg(di);
	       bq2416x_config_current_reg(di);
		bq2416x_config_dppm_voltage_reg(di,di->dppm_voltagemV);		
		printk("%s, charging with USB\n", __func__);		
		schedule_delayed_work(&di->bq2416x_charger_work,
						msecs_to_jiffies(0));
		di->active = 1;
	}

	if (event & BQ2416x_STOP_CHARGING) {
		cancel_delayed_work(&di->bq2416x_charger_work);
		di->active = 0;
	}

	if (event & BQ2416x_RESET_TIMER) {
		/* reset 32 second timer */
		bq2416x_config_status_reg(di);
	}

	return ret;
}
/*small current charging(100mA) when low battery voltage or low battery temprature*/
static void
bq2416x_low_current_charge(struct bq2416x_device_info *di)
{
	int battery_voltage = 0;
	int battery_temperature = 0;
	if (!is_bq27510_battery_exist(g_battery_measure_by_bq27510_device))
		return;

		battery_voltage = bq27510_battery_voltage(g_battery_measure_by_bq27510_device);
		battery_temperature = bq27510_battery_temperature(g_battery_measure_by_bq27510_device);

		if (battery_temperature < BQ2416x_COLD_BATTERY_THRESHOLD){
			dev_dbg(di->dev, "battery temp less than -10 degree,disable charging\n");
			di->enable_ce = DISABLE_CE;
			if (di->charger_source == POWER_SUPPLY_TYPE_MAINS){
			   if(di->calling_limit){
					di->cin_limit = CURRENT_AC_LIMIT_IN_800;
			   }
			   else{
					di->cin_limit = CURRENT_AC_LIMIT_IN;
			   }
			}

			else
				di->cin_limit = CURRENT_USB_LIMIT_IN;
		}
		else if ((battery_temperature >= BQ2416x_COLD_BATTERY_THRESHOLD)
			&& (battery_temperature < BQ2416x_COOL_BATTERY_THRESHOLD)){
			/*battery temp is between -10 and 0 degree,or battery voltage is less than 3.0V*/
			di->enable_low_chg = ENABLE_LOW_CHG;/*enable low charge,100mA charging*/
			bq2416x_config_safety_reg(di);
			if (di->charger_source == POWER_SUPPLY_TYPE_MAINS){
			   if(di->calling_limit){
					di->cin_limit = CURRENT_AC_LIMIT_IN_800;
			   }
			   else{
					di->cin_limit = CURRENT_AC_LIMIT_IN;
			   }
			}
			else
				di->cin_limit = CURRENT_USB_LIMIT_IN;
			if(battery_voltage < BQ2416x_LOW_TEMP_TERM_VOLTAGE){
				di->enable_ce = ENABLE_CE;
			}
			else{
				di->enable_ce = DISABLE_CE;
			}
		}
		else if ((battery_temperature >= BQ2416x_COOL_BATTERY_THRESHOLD)
		    && (battery_temperature < (BQ2416x_WARM_BATTERY_THRESHOLD - TEMPERATURE_OFFSET))){
			/*battery temp is between 00 and 50 degree,normal charge*/
			di->enable_low_chg = DISABLE_LOW_CHG;/*normal charge*/
			bq2416x_config_safety_reg(di);
			di->enable_ce = ENABLE_CE;
			if (di->charger_source == POWER_SUPPLY_TYPE_MAINS){
			   if(di->calling_limit){
					di->cin_limit = CURRENT_AC_LIMIT_IN_800;
			   }
			   else{
					di->cin_limit = CURRENT_AC_LIMIT_IN;
				}
			}
			else
				di->cin_limit = CURRENT_USB_LIMIT_IN;
		}
		else if ((battery_temperature >= BQ2416x_WARM_BATTERY_THRESHOLD)
		    && (battery_temperature < BQ2416x_HOT_BATTERY_THRESHOLD )){
			/*battery temp is between 00 and 50 degree,normal charge*/
			di->enable_low_chg = DISABLE_LOW_CHG;/*normal charge*/
			bq2416x_config_safety_reg(di);
			di->enable_ce = ENABLE_CE;
			if (di->charger_source == POWER_SUPPLY_TYPE_MAINS)
				di->cin_limit = CURRENT_AC_LIMIT_IN_800;
			else
				di->cin_limit = CURRENT_USB_LIMIT_IN;
		}
		else if (battery_temperature >= BQ2416x_HOT_BATTERY_THRESHOLD)
		{
			dev_dbg(di->dev, "battery temp more than 50 degree,disable charging\n");
			di->enable_ce = DISABLE_CE;
			if (di->charger_source == POWER_SUPPLY_TYPE_MAINS)
				di->cin_limit = CURRENT_AC_LIMIT_IN_800;
			else
				di->cin_limit = CURRENT_USB_LIMIT_IN;
		}
		else{
			di->cin_limit = di->cin_limit;

		}
		di->enable_ce = (di->enable_ce | di->factory_flag);
		bq2416x_config_control_reg(di);
	return;
}
static void
bq2416x_charger_update_status(struct bq2416x_device_info *di)
{
	u8 read_reg[8] = {0};
    long int events=BQ2416x_START_CHARGING;
    static int battery_capacity = 0;

	di->timer_fault = 0;
	bq2416x_read_block(di, &read_reg[0], 0, 8); 

	if((read_reg[1] & BQ2416x_FAULT_VBUS_VUVLO) == BQ2416x_FAULT_VBUS_OVP){
		dev_err(di->dev, "bq2416x charger over voltage = %x\n",read_reg[1]);
		events = POWER_SUPPLY_OVERVOLTAGE;
		blocking_notifier_call_chain(&notifier_list, events, NULL);
	}
   
	if ((read_reg[0] & BQ2416x_CHARGE_FAULT) == BQ2416x_STATUS_CHARGE_DONE){   
		dev_dbg(di->dev, "CHARGE DONE\n");
        battery_capacity = bq27510_battery_capacity(g_battery_measure_by_bq27510_device);
        if (((!is_bq27510_battery_full(g_battery_measure_by_bq27510_device))||(battery_capacity!=100))&& (di->battery_present)){
            dev_info(di->dev, "charge_done_battery_capacity=%d\n",battery_capacity);
            di->hz_mode = EN_HIZ;
			bq2416x_write_byte(di, di->control_reg02 | di->hz_mode, REG_CONTROL_REGISTER_REG02);
            msleep(500);
			di->hz_mode = DIS_HIZ;
            bq2416x_config_control_reg(di);
			events = BQ2416x_START_CHARGING;           
        }else{
            events = BQ2416x_CHARGE_DONE;
        }
        blocking_notifier_call_chain(&notifier_list, events, NULL);
    }

	if ((read_reg[0] & BQ2416x_FAULT_BATTERY) == BQ2416x_FAULT_WATCHDOG_TIMER){ 
		di->timer_fault = 1;
     }

	if ((read_reg[0] & BQ2416x_FAULT_BATTERY) == BQ2416x_FAULT_SAFETY_TIMER) 
		di->timer_fault = 1;
     
	if (read_reg[0] & BQ2416x_FAULT_BATTERY) {
		di->cfg_params = 1;
		dev_err(di->dev, "CHARGER STATUS %x\n", read_reg[0]);
	}

	if ((read_reg[1] & 0x6) == BQ2416x_FAULT_BAT_OVP) {
        gpio_set_value(ENABLE_BQ2416x_CHARGER, 1);
		dev_err(di->dev, "battery ovp = %x,%x\n", read_reg[1],read_reg[3]);
        msleep(1000);
        gpio_set_value(ENABLE_BQ2416x_CHARGER, 0);
	}

	if ((di->timer_fault == 1) || (di->cfg_params == 1)) {
		bq2416x_write_byte(di, di->control_reg02, REG_CONTROL_REGISTER_REG02);
		bq2416x_write_byte(di, di->voltage_reg03, REG_BATTERY_VOLTAGE_REG03);
		bq2416x_write_byte(di, di->current_reg05, REG_BATTERY_CURRENT_REG05);
		bq2416x_write_byte(di, di->dppm_reg06, REG_DPPM_VOLTAGE_REG06);
		bq2416x_config_safety_reg(di); 
		di->cfg_params = 0;
	}

	/* reset 32 second timer */
	bq2416x_config_status_reg(di);

	return;
}
static void bq2416x_monitor_battery_ntc_charging(struct bq2416x_device_info *di)
{
    int battery_voltage = 0;
    int battery_status = 0;
    long int events = BQ2416x_START_CHARGING;
    if(!di->battery_present){
        blocking_notifier_call_chain(&notifier_list, BQ2416x_NOT_CHARGING, NULL);
        return;
    }
    battery_voltage = bq27510_battery_voltage(g_battery_measure_by_bq27510_device);
    //battery_voltage = battery_voltage/VOLTAGE_MULTIPLE;
    battery_status = bq2416x_check_battery_temperature_threshold();

    switch (battery_status) {
    case BATTERY_HEALTH_TEMPERATURE_OVERLOW:
         di->enable_ce = DISABLE_CHARGER;
        break;
    case BATTERY_HEALTH_TEMPERATURE_LOW:
         if(battery_voltage > BQ2416x_LOW_TEMP_TERM_VOLTAGE){
              di->enable_ce = DISABLE_CHARGER;
         }else{
             di->enable_ce = ENABLE_CHARGER;
         }
         di->enable_low_chg = ENABLE_LOW_CHG;
         
        break;
    case BATTERY_HEALTH_TEMPERATURE_NORMAL:
        di->enable_ce = ENABLE_CHARGER;
        di->enable_low_chg = DISABLE_LOW_CHG;
        if (di->charger_source == POWER_SUPPLY_TYPE_MAINS){
            bq2416x_calling_limit_ac_input_current(di,0);
        }
        break;
    case BATTERY_HEALTH_TEMPERATURE_NORMAL_HIGH:
        di->enable_ce = ENABLE_CHARGER;
        di->enable_low_chg = DISABLE_LOW_CHG;
        if (di->charger_source == POWER_SUPPLY_TYPE_MAINS){
            if(di->battery_temp_status == BATTERY_HEALTH_TEMPERATURE_NORMAL){
                bq2416x_calling_limit_ac_input_current(di,0);
            }else{    
                di->cin_limit = di->cin_limit;
            }
        }
        break;
    case BATTERY_HEALTH_TEMPERATURE_HIGH:
        di->enable_ce = ENABLE_CHARGER;
        di->enable_low_chg = DISABLE_LOW_CHG;
        if (di->charger_source == POWER_SUPPLY_TYPE_MAINS){
            di->cin_limit = IINLIM_800;
        }
        break;
    case BATTERY_HEALTH_TEMPERATURE_OVERHIGH:
        di->enable_ce = DISABLE_CHARGER;
        di->enable_low_chg = DISABLE_LOW_CHG;
        if (di->charger_source == POWER_SUPPLY_TYPE_MAINS){
            di->cin_limit = IINLIM_800;
        }
        break;
    default:
        break;
    }
    di->enable_ce = di->enable_ce | di->factory_flag;
    if(!di->enable_ce){
        events = BQ2416x_START_CHARGING;
    }else{
        events = BQ2416x_NOT_CHARGING;
    }
    bq2416x_config_control_reg(di);
    bq2416x_config_safety_reg(di); 
    di->battery_temp_status = battery_status;
    blocking_notifier_call_chain(&notifier_list, events, NULL);
    return;
}
static int __devinit bq2416x_charger_probe(struct i2c_client *client,
				 const struct i2c_device_id *id)
{
	struct bq2416x_device_info *di;
	struct bq2416x_platform_data *pdata = client->dev.platform_data;
	int ret;
	u8 read_reg = 0;
	enum plugin_status plugin_stat;

	di = kzalloc(sizeof(*di), GFP_KERNEL);
	if (!di)
		return -ENOMEM;

	di->dev = &client->dev;
	di->client = client;

	i2c_set_clientdata(client, di);

	ret = bq2416x_read_byte(di, &read_reg, REG_PART_REVISION);

	if (ret < 0) {
		dev_err(&client->dev, "chip not present at address %x\n",
								client->addr);
		ret = -EINVAL;
		goto err_kfree;
	}
#if 0
	if ((read_reg & 0x18) == 0x00 && (client->addr == 0x6a))
		di->bqchip_version = BQ24156;
#endif 
	
	if ((read_reg & 0x18) == 0x00 && (client->addr == 0x6b))
		di->bqchip_version = BQ24161;

	if (di->bqchip_version == 0) {
		dev_dbg(&client->dev, "unknown bq chip\n");
		dev_dbg(&client->dev, "Chip address %x", client->addr);
		dev_dbg(&client->dev, "bq chip version reg value %x", read_reg);
		ret = -EINVAL;
		goto err_kfree;
	}


	//	di->nb.notifier_call = bq2416x_charger_event;
	
#if 0
	 bq2415x_config_safety_reg(di, pdata->max_charger_currentmA,
						pdata->max_charger_voltagemV);
	 di->cin_limit = 900;
	 di->term_currentmA = pdata->termination_currentmA;
	 bq2415x_config_control_reg(di);
	 bq2415x_config_voltage_reg(di);
	 bq2415x_config_current_reg(di);
#endif 
       /*set gpio_174 to control CD pin to disable/enable bq24161 IC*/
	 gpio_request(BQ2416X_GPIO_174, "gpio_174_cd");
	 /* set charger CD pin to low level and enable it to supply power normally*/
	 gpio_direction_output(BQ2416X_GPIO_174, 0);
     ret = bq2416x_get_max_charge_voltage(di);
	 if(!ret){
		di->max_voltagemV = pdata->max_charger_voltagemV;
	 }

	 di->voltagemV = di->max_voltagemV;

	 ret = bq2416x_get_max_charge_current(di);
	 if(!ret){
		di->max_currentmA = pdata->max_charger_currentmA;
	 }

	 di->currentmA = CURRENT_USB_CHARGE_IN ;
        di->term_currentmA = CURRENT_TERM_CHARGE_IN;
	 di->dppm_voltagemV = VOLT_DPPM_ADJUST;
	 di->cin_limit = CURRENT_USB_LIMIT_IN; 


		di->enable_hotcold_temp_charge = set_one;
	di->enable_low_chg = DISABLE_LOW_CHG;/*set normally charge mode*/
	di->enable_iterm = ENABLE_ITERM; /*enable charge current termination*/
	di->factory_flag = 0;
	 di->enable_ce = ENABLE_CE;
	 di->hz_mode = 0;
	 di->cd_active = 0;
	 
	INIT_DELAYED_WORK_DEFERRABLE(&di->bq2416x_charger_work,
				bq2416x_charger_work);

#if BQ2416X_USE_WAKE_LOCK
	wake_lock_init(&di->charger_wake_lock, WAKE_LOCK_SUSPEND, "charger_wake_lock");
#endif

	//BLOCKING_INIT_NOTIFIER_HEAD(&notifier_list);

	di->active = 0;
	di->params.enable = 1;
	di->cfg_params = 1;
	
	 bq2416x_config_control_reg(di);
	 bq2416x_config_voltage_reg(di);
	 bq2416x_config_current_reg(di);
	 bq2416x_config_dppm_voltage_reg(di,di->dppm_voltagemV);	
	 bq2416x_config_safety_reg(di);
	
#if 0
	ret = bq2416x_read_byte(di, &read_reg, REG_SPECIAL_CHARGER_VOLTAGE);
	if (!(read_reg & 0x08)) {
		di->active = 1;
		schedule_delayed_work(&di->bq2415x_charger_work, 0);
	}
#endif

	ret = sysfs_create_group(&client->dev.kobj, &bq2416x_attr_group);
	if (ret)
		dev_dbg(&client->dev, "could not create sysfs files\n");


	//twl6030_register_notifier(&di->nb, 1);
	INIT_WORK(&di->usb_work, bq2416x_usb_charger_work);

//r00186667, 2011/08/02, otg register for receive USB/AC plugin event.begin   
	di->nb_otg.notifier_call = bq2416x_usb_notifier_call;
	di->otg = otg_get_transceiver();
	ret = otg_register_notifier(di->otg, &di->nb_otg);
	if (ret)
		dev_err(&client->dev, "otg register notifier failed %d\n", ret);
//r00186667, 2011/08/02, otg register for receive USB/AC plugin event.end  

//r00186667, 2011/08/02, get the boot event type.begin  
    plugin_stat = get_plugin_device_status();
    if( PLUGIN_USB_CHARGER == plugin_stat){
		di->event = USB_EVENT_VBUS;
    }else if (PLUGIN_AC_CHARGER == plugin_stat){
         di->event = USB_EVENT_CHARGER;
    }else{
		di->event = USB_EVENT_NONE;
	}
	schedule_work(&di->usb_work);
//r00186667, 2011/08/02, get the boot event type.end  
	return 0;

err_kfree:
	kfree(di);	
	
	return ret;
}
static int __devinit bq2416x_charger_probe(struct i2c_client *client,
				 const struct i2c_device_id *id)
{
	struct bq2416x_device_info *di;
	struct bq2416x_platform_data *pdata = client->dev.platform_data;
	int ret;
	u8 read_reg = 0;
	enum plugin_status plugin_stat;

	di = kzalloc(sizeof(*di), GFP_KERNEL);
	if (!di)
		return -ENOMEM;

	di->dev = &client->dev;
	di->client = client;

	i2c_set_clientdata(client, di);

	ret = bq2416x_read_byte(di, &read_reg, REG_PART_REVISION_REG04);

	if (ret < 0) {
		dev_err(&client->dev, "chip not present at address %x\n",
								client->addr);
		ret = -EINVAL;
		goto err_kfree;
	} 
	
	if ((read_reg & 0x18) == 0x00 && (client->addr == 0x6b))
		di->bqchip_version = BQ24161;

	if (di->bqchip_version == 0) {
		dev_dbg(&client->dev, "unknown bq chip\n");
		dev_dbg(&client->dev, "Chip address %x", client->addr);
		dev_dbg(&client->dev, "bq chip version reg value %x", read_reg);
		ret = -EINVAL;
		goto err_kfree;
	}
	//	di->nb.notifier_call = bq2416x_charger_event;

    /*set gpio_174 to control CD pin to disable/enable bq24161 IC*/
	 gpio_request(ENABLE_BQ2416x_CHARGER, "gpio_174_cd");
	 /* set charger CD pin to low level and enable it to supply power normally*/
	 gpio_direction_output(ENABLE_BQ2416x_CHARGER, 0);

     ret = bq2416x_get_max_charge_voltage(di);
	 if(!ret){
		di->max_voltagemV = pdata->max_charger_voltagemV;
	 }

	 ret = bq2416x_get_max_charge_current(di);
	 if(!ret){
		di->max_currentmA = pdata->max_charger_currentmA;
	 }

     di->max_cin_currentmA = IINLIM_1000;
	 di->voltagemV = di->max_voltagemV;
	 di->currentmA = ICHG_MIN_550 ;
     di->term_currentmA = ITERM_MIN_50;
	 di->dppm_voltagemV = VINDPM_MIN_4200;
	 di->cin_limit = IINLIM_500; 
    di->safety_timer = TMR_X_9;
	di->enable_low_chg = DISABLE_LOW_CHG;/*set normally charge mode*/
	di->enable_iterm = ENABLE_ITERM; /*enable charge current termination*/
    di->supply_sel = SUPPLY_SEL_IN;
	di->factory_flag = 0;
	di->enable_ce = ENABLE_CHARGER;
	di->hz_mode = DIS_HIZ;
	di->cd_active = 0;
	 
	INIT_DELAYED_WORK_DEFERRABLE(&di->bq2416x_charger_work,
				bq2416x_charger_work);


	wake_lock_init(&di->charger_wake_lock, WAKE_LOCK_SUSPEND, "charger_wake_lock");


	//BLOCKING_INIT_NOTIFIER_HEAD(&notifier_list);

	di->params.enable = 1;
	di->cfg_params = 1;
	
	 bq2416x_config_control_reg(di);
	 bq2416x_config_voltage_reg(di);
	 bq2416x_config_current_reg(di);
	 bq2416x_config_dppm_voltage_reg(di,di->dppm_voltagemV);	
	 bq2416x_config_safety_reg(di);

	ret = sysfs_create_group(&client->dev.kobj, &bq2416x_attr_group);
	if (ret)
		dev_dbg(&client->dev, "could not create sysfs files\n");

	//twl6030_register_notifier(&di->nb, 1);

	INIT_WORK(&di->usb_work, bq2416x_usb_charger_work);

	di->nb_otg.notifier_call = bq2416x_usb_notifier_call;
	di->otg = otg_get_transceiver();
	ret = otg_register_notifier(di->otg, &di->nb_otg);
	if (ret)
		dev_err(&client->dev, "otg register notifier failed %d\n", ret);
 
    plugin_stat = get_plugin_device_status();
    if( PLUGIN_USB_CHARGER == plugin_stat){
		di->event = USB_EVENT_VBUS;
    }else if (PLUGIN_AC_CHARGER == plugin_stat){
         di->event = USB_EVENT_CHARGER;
    }else{
		di->event = USB_EVENT_NONE;
	}
	schedule_work(&di->usb_work);
	return 0;

err_kfree:
	kfree(di);	
	
	return ret;
}