/* *di->cin_limit: set usb input limit current(100,150,500,800,900,1500) *di->enable_iterm: Enable charge current termination *ENABLE_STAT_PIN: Enable STAT pin output to show charge status * di->enable_ce=0 : Charger enabled */ static void bq2416x_config_control_reg(struct bq2416x_device_info *di) { u8 Iin_limit; if (di->cin_limit <= 100) Iin_limit = 0; else if (di->cin_limit > 100 && di->cin_limit <= 150) Iin_limit = 1; else if (di->cin_limit > 150 && di->cin_limit <= 500) Iin_limit = 2; else if (di->cin_limit > 500 && di->cin_limit <= 800) Iin_limit = 3; else if (di->cin_limit > 800 && di->cin_limit <= 900) Iin_limit = 4; else if (di->cin_limit > 900 && di->cin_limit <= 1500) Iin_limit = 5; else Iin_limit = 6; di->control_reg = ((Iin_limit << INPUT_CURRENT_LIMIT_SHIFT) | (di->enable_iterm << ENABLE_ITERM_SHIFT) | ENABLE_STAT_PIN |( di->enable_ce << 1) |di->hz_mode); bq2416x_write_byte(di, di->control_reg, REG_CONTROL_REGISTER); return; }
/* *config TMR_RST function to reset the watchdog * */ static void bq2416x_config_usb_supply_sel_reg(struct bq2416x_device_info *di) { //di->usb_supply_sel_reg = (TIMER_RST | ENABLE_USB_SUPPLY_SEL); di->usb_supply_sel_reg = (TIMER_RST); bq2416x_write_byte(di, di->usb_supply_sel_reg, REG_STATUS_CONTROL); return; }
/* * set Battery charger current(550 ~1500mA) and Termination current(50~350mA) * */ static void bq2416x_config_current_reg(struct bq2416x_device_info *di) { unsigned int currentmA = 0; unsigned int term_currentmA = 0; u8 Vichrg = 0; u8 shift = 0; u8 Viterm = 0; currentmA = di->currentmA; term_currentmA = di->term_currentmA; if (currentmA < ICHG_MIN_550) currentmA = ICHG_MIN_550; if ((di->bqchip_version & BQ24161)) { shift = BQ2416x_CURRENT_SHIFT; if (currentmA > ICHG_1500) currentmA = ICHG_1500; } if (term_currentmA < ITERM_MIN_50) term_currentmA = ITERM_MIN_50; if (term_currentmA > ITERM_MAX_400) term_currentmA = ITERM_MAX_400; Vichrg = (currentmA - ICHG_MIN_550)/ICHG_STEP_75; Viterm = (term_currentmA - ITERM_MIN_50)/ITERM_STEP_50; di->current_reg05 = (Vichrg << shift | Viterm); bq2416x_write_byte(di, di->current_reg05, REG_BATTERY_CURRENT_REG05); return; }
/* *di->cin_limit: set usb input limit current(100,150,500,800,900,1500) *di->enable_iterm: Enable charge current termination *ENABLE_STAT_PIN: Enable STAT pin output to show charge status * di->enable_ce=0 : Charger enabled */ static void bq2416x_config_control_reg(struct bq2416x_device_info *di) { u8 Iin_limit; if (di->cin_limit <= IINLIM_100) Iin_limit = 0; else if (di->cin_limit > IINLIM_100 && di->cin_limit <= IINLIM_150) Iin_limit = 1; else if (di->cin_limit > IINLIM_150 && di->cin_limit <= IINLIM_500) Iin_limit = 2; else if (di->cin_limit > IINLIM_500 && di->cin_limit <= IINLIM_800) Iin_limit = 3; else if (di->cin_limit > IINLIM_800 && di->cin_limit <= IINLIM_900) Iin_limit = 4; else if (di->cin_limit > IINLIM_900 && di->cin_limit <= IINLIM_1500) Iin_limit = 5; else Iin_limit = 6; di->control_reg02 = ((Iin_limit << BQ2416x_INPUT_CURRENT_LIMIT_SHIFT) | (di->enable_iterm << BQ2416x_EN_ITERM_SHIFT) | (ENABLE_STAT) |( di->enable_ce << BQ2416x_EN_CE_SHIFT) |di->hz_mode); bq2416x_write_byte(di, di->control_reg02, REG_CONTROL_REGISTER_REG02); return; }
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; }
/* * enable TMR_PIN and set Safety Timer Time Limit = 9h * */ static void bq2416x_config_safety_reg(struct bq2416x_device_info *di) { di->safety_timer_reg07 = TMR_EN | di->safety_timer | di->enable_low_chg; bq2416x_write_byte(di, di->safety_timer_reg07, REG_SAFETY_TIMER_REG07); return; }
/* * enable TMR_PIN and set Safety Timer Time Limit = 6h * */ static void bq2416x_config_safety_reg(struct bq2416x_device_info *di) { di->tmr_ts_reg = (ENABLE_TMR_PIN |TMR_X_6) | di->enable_low_chg; //safety time = 6h and ENABLE_LOW_CHG //di->tmr_ts_reg = (ENABLE_TMR_PIN); //safety time = 27 min bq2416x_write_byte(di, di->tmr_ts_reg, REG_SAFETY_TIMER); return; }
/*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(¬ifier_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(¬ifier_list, events, NULL); }
/* * set USB input dppm voltage between 4.2V and 4.76V * */ static void bq2416x_config_dppm_voltage_reg(struct bq2416x_device_info *di, unsigned int dppm_voltagemV) { u8 Vmreg; if (dppm_voltagemV < VINDPM_MIN_4200) dppm_voltagemV = VINDPM_MIN_4200; else if (dppm_voltagemV > VINDPM_MAX_4760) dppm_voltagemV = VINDPM_MAX_4760; Vmreg = (dppm_voltagemV - VINDPM_MIN_4200)/VINDPM_STEP_80; di->dppm_reg06 =(Vmreg << BQ2416x_USB_INPUT_DPPM_SHIFT); bq2416x_write_byte(di, di->dppm_reg06, REG_DPPM_VOLTAGE_REG06); return; }
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); }
/* * set Battery Regulation Voltage between 3.5V and 4.44V * */ static void bq2416x_config_voltage_reg(struct bq2416x_device_info *di) { unsigned int voltagemV; u8 Voreg; voltagemV = di->voltagemV; if (voltagemV < 3500) voltagemV = 3500; else if (voltagemV > 4440) voltagemV = 4440; Voreg = (voltagemV - 3500)/20; di->voltage_reg = (Voreg << VOLTAGE_SHIFT); bq2416x_write_byte(di, di->voltage_reg, REG_BATTERY_VOLTAGE); return; }
/* * set Battery Regulation Voltage between 3.5V and 4.44V * */ static void bq2416x_config_voltage_reg(struct bq2416x_device_info *di) { unsigned int voltagemV; u8 Voreg; voltagemV = di->voltagemV; if (voltagemV < VCHARGE_MIN_3500) voltagemV = VCHARGE_MIN_3500; else if (voltagemV > VCHARGE_MAX_4440) voltagemV = VCHARGE_MAX_4440; Voreg = (voltagemV - VCHARGE_MIN_3500)/VCHARGE_STEP_20; di->voltage_reg03 = (Voreg << BQ2416x_VCHARGE_SHIFT); bq2416x_write_byte(di, di->voltage_reg03, REG_BATTERY_VOLTAGE_REG03); return; }
/* * set USB input dppm voltage between 4.2V and 4.76V * */ static void bq2416x_config_dppm_voltage_reg(struct bq2416x_device_info *di, unsigned int dppm_voltagemV) { u8 Vmreg; if (dppm_voltagemV < 4200) dppm_voltagemV = 4200; else if (dppm_voltagemV > 4760) dppm_voltagemV = 4760; Vmreg = (dppm_voltagemV - 4200)/80; di->dppm_reg =(Vmreg << USB_INPUT_DPPM_SHIFT); bq2416x_write_byte(di, di->dppm_reg, REG_DPPM_VOLTAGE); return; }
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); }
/* * set Battery charger current(550 ~1500mA) and Termination current(50~350mA) * */ static void bq2416x_config_current_reg(struct bq2416x_device_info *di) { unsigned int currentmA = 0; unsigned int term_currentmA = 0; u8 Vichrg = 0; u8 shift = 0; u8 Viterm = 0; currentmA = di->currentmA; term_currentmA = di->term_currentmA; if (currentmA < 550) currentmA = 550; //r00186667, 20110802 , removed begin #if 0 if ((di->bqchip_version & (BQ24153 | BQ24158))) { shift = BQ24153_CURRENT_SHIFT; if (currentmA > 1250) currentmA = 1250; } #endif //r00186667, 20110802 , removed end if ((di->bqchip_version & BQ24161)) { shift = BQ2416x_CURRENT_SHIFT; if (currentmA > 2500) currentmA = 2500; } if (term_currentmA > 350) term_currentmA = 350; Vichrg = (currentmA - 550)/75; Viterm = (term_currentmA - 50)/50; di->current_reg = (Vichrg << shift | Viterm); bq2416x_write_byte(di, di->current_reg, REG_BATTERY_CURRENT); return; }
/* *config TMR_RST function to reset the watchdog * */ static void bq2416x_config_watchdog_reg(struct bq2416x_device_info *di) { di->status_reg00 = (TMR_RST) | di->supply_sel; bq2416x_write_byte(di, di->status_reg00, REG_STATUS_CONTROL_REG00); return; }
/* *Enable STAT pin output to show charge status * */ static void bq2416x_config_status_reg(struct bq2416x_device_info *di) { bq2416x_config_usb_supply_sel_reg(di); bq2416x_write_byte(di, di->control_reg, REG_CONTROL_REGISTER); 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(¬ifier_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(¬ifier_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; }
/* *Enable STAT pin output to show charge status * */ static void bq2416x_config_status_reg(struct bq2416x_device_info *di) { bq2416x_config_watchdog_reg(di); bq2416x_write_byte(di, di->control_reg02, REG_CONTROL_REGISTER_REG02); return; }