static void low_comp_work_handler(struct work_struct *work) { struct battery_data *battery = container_of(work, struct battery_data, low_comp_work.work); int fg_soc; int fg_vcell; int fg_current; int i, comp_result; fg_soc = battery->info.level; for (i = 0 ; i<10 ; i++) { fg_vcell = get_fuelgauge_value(FG_VOLTAGE); fg_current = get_fuelgauge_value(FG_CURRENT); pr_info("%s : running", __func__); comp_result = p3_low_batt_compensation(fg_soc, fg_vcell, fg_current); if (comp_result == 2) { pr_info("%s : soc(%d), vcell(%d), current(%d), count(%d), pre_count(%d), pre_condition(%d)\n", __func__, fg_soc, fg_vcell, fg_current, i, max17042_chip_data->pre_cond_ok, max17042_chip_data->low_comp_pre_cond); break; } else if (comp_result == 1) { pr_info("%s : low compensation occurred!, vcell(%d), current(%d)\n", __func__, fg_vcell, fg_current); wake_lock(&battery->work_wake_lock); schedule_work(&battery->battery_work); break; } msleep(2000); } wake_unlock(&battery->low_comp_wake_lock); }
static int p3_get_bat_level(struct power_supply *bat_ps) { struct battery_data *battery = container_of(bat_ps, struct battery_data, psy_battery); int fg_soc; int fg_vfsoc; int fg_vcell; int fg_current; int avg_current; int recover_flag = 0; recover_flag = fg_check_cap_corruption(); /* check VFcapacity every five minutes */ if (!(battery->fg_chk_cnt++ % 10)) { fg_check_vf_fullcap_range(); battery->fg_chk_cnt = 1; } fg_soc = get_fuelgauge_value(FG_LEVEL); if (fg_soc < 0) { pr_info("Can't read soc!!!"); fg_soc = battery->info.level; } if (!check_jig_on() && !max17042_chip_data->info.low_batt_comp_flag) { if (((fg_soc+5) < max17042_chip_data->info.previous_repsoc) || (fg_soc > (max17042_chip_data->info.previous_repsoc+5))) battery->fg_skip = 1; } /* skip one time (maximum 30 seconds) because of corruption. */ if (battery->fg_skip) { pr_info("%s: skip update until corruption check " "is done (fg_skip_cnt:%d)\n", __func__, ++battery->fg_skip_cnt); fg_soc = battery->info.level; if (recover_flag || battery->fg_skip_cnt > 10) { battery->fg_skip = 0; battery->fg_skip_cnt = 0; } } if (battery->low_batt_boot_flag) { fg_soc = 0; if (check_ta_conn(battery) && !check_UV_charging_case()) { fg_adjust_capacity(); battery->low_batt_boot_flag = 0; } if (!check_ta_conn(battery)) battery->low_batt_boot_flag = 0; } fg_vcell = get_fuelgauge_value(FG_VOLTAGE); if (fg_vcell < 0) { pr_info("Can't read vcell!!!"); fg_vcell = battery->info.batt_vol; } else battery->info.batt_vol = fg_vcell; fg_current = get_fuelgauge_value(FG_CURRENT); avg_current = get_fuelgauge_value(FG_CURRENT_AVG); fg_vfsoc = get_fuelgauge_value(FG_VF_SOC); // Algorithm for reducing time to fully charged (from MAXIM) if(battery->info.charging_enabled && // Charging is enabled !battery->info.batt_is_recharging && // Not Recharging battery->info.charging_source == CHARGER_AC && // Only AC (Not USB cable) !battery->is_first_check && // Skip when first check after boot up (fg_vfsoc>70 && (fg_current>20 && fg_current<250) && (avg_current>20 && avg_current<260))) { if(battery->full_check_flag == 2) { pr_info("%s: force fully charged SOC !! (%d)", __func__, battery->full_check_flag); fg_set_full_charged(); fg_soc = get_fuelgauge_value(FG_LEVEL); } else if(battery->full_check_flag < 2) pr_info("%s: full_check_flag (%d)", __func__, battery->full_check_flag); if(battery->full_check_flag++ > 10000) // prevent overflow battery->full_check_flag = 3; } else battery->full_check_flag = 0; if (battery->info.charging_source == CHARGER_AC && battery->info.batt_improper_ta == 0) { if (is_over_abs_time(battery)) { fg_soc = 100; battery->info.batt_is_full = 1; pr_info("%s: charging time is over", __func__); pr_info("%s: fg_vcell = %d, fg_soc = %d," " is_full = %d\n", __func__, fg_vcell, fg_soc, battery->info.batt_is_full); p3_set_chg_en(battery, 0); goto __end__; } } if (fg_vcell <= battery->pdata->recharge_voltage) { if (battery->info.batt_is_full && !battery->info.charging_enabled) { if (++battery->recharging_cnt > 1) { pr_info("recharging(under full)"); battery->info.batt_is_recharging = 1; p3_set_chg_en(battery, 1); battery->recharging_cnt = 0; pr_info("%s: fg_vcell = %d, fg_soc = %d," " is_recharging = %d\n", __func__, fg_vcell, fg_soc, battery->info.batt_is_recharging); } } else battery->recharging_cnt = 0; } else battery->recharging_cnt = 0; if (fg_soc > 100) fg_soc = 100; /* Checks vcell level and tries to compensate SOC if needed.*/ /* If jig cable is connected, then skip low batt compensation check. */ if (!check_jig_on() && !battery->info.charging_enabled) fg_soc = p3_low_batt_compensation(fg_soc, fg_vcell, fg_current); __end__: pr_debug("fg_vcell = %d, fg_soc = %d, is_full = %d", fg_vcell, fg_soc, battery->info.batt_is_full); if(battery->is_first_check) battery->is_first_check = false; if (battery->info.batt_is_full && (battery->info.charging_source != CHARGER_USB)) fg_soc = 100; #if 0 // not used else { if (fg_soc >= 100) fg_soc = 99; } #endif return fg_soc; }