static int bq_bci_battery_suspend(struct platform_device *pdev,pm_message_t state) { struct bq_bci_device_info *di = platform_get_drvdata(pdev); if (di == NULL) { dev_err(&pdev->dev, "di is NULL!\n"); return -ENODEV; } suspend_capacity = hisi_battery_capacity(); cancel_delayed_work(&di->bq_bci_monitor_work); return 0; }
/********************************************************** * Function: charge_core_get_params * Discription: update update the charge parameters * Parameters: NULL * return value: charge parameters **********************************************************/ struct charge_core_data *charge_core_get_params(void) { struct charge_core_info *di = g_core_info; int tbatt = hisi_battery_temperature(); int vbatt = hisi_battery_voltage(); int cbatt = hisi_battery_capacity(); charge_core_tbatt_handler(tbatt,di->temp_para,&di->data); charge_core_vbatt_handler(vbatt,di->volt_para,&di->data); charge_core_cbatt_handler(cbatt,di->vdpm_para,&di->data); charge_core_sbatt_handler(vbatt,di->segment_para,&di->data); charge_core_protect_inductance_handler(cbatt,di->inductance_para,&di->data); return &di->data; }
static int bq_bci_battery_resume(struct platform_device *pdev) { struct bq_bci_device_info *di = platform_get_drvdata(pdev); int i = 0, resume_capacity = 0; if (di == NULL) { dev_err(&pdev->dev, "di is NULL!\n"); return -ENODEV; } resume_capacity = hisi_battery_capacity(); if(di->charge_status == POWER_SUPPLY_STATUS_DISCHARGING || di->charge_status == POWER_SUPPLY_STATUS_NOT_CHARGING) { if ((suspend_capacity - resume_capacity)>=2) { capacity_sum = 0; for(i=0;i<WINDOW_LEN;i++) { capacity_filter[i] = resume_capacity; capacity_sum += capacity_filter[i]; } } } schedule_delayed_work(&di->bq_bci_monitor_work, 0); return 0; }
static int bq_bci_battery_probe(struct platform_device *pdev) { struct bq_bci_device_info *di; struct battery_charge_param_s param; int low_bat_flag = 0; int ret = 0; unsigned int i = 0; di = kzalloc(sizeof(*di), GFP_KERNEL); if (!di) return -ENOMEM; g_bq_bci_dev = di; ret = hisi_battery_charge_param(¶m); if(!ret){ param.max_voltagemV = 4200; } di->bat_max_volt = param.max_voltagemV; di->monitoring_interval = NORMAL_SAMPLE_INTERVAL; di->dev = &pdev->dev; di->bat.name = "Battery"; di->bat.supplied_to = bq_bci_supplied_to; di->bat.num_supplicants = ARRAY_SIZE(bq_bci_supplied_to); di->bat.type = POWER_SUPPLY_TYPE_BATTERY; di->bat.properties = bq_bci_battery_props; di->bat.num_properties = ARRAY_SIZE(bq_bci_battery_props); di->bat.get_property = bq_bci_battery_get_property; di->bat_health = POWER_SUPPLY_HEALTH_GOOD; di->bat_exist = is_hisi_battery_exist(); di->bat_err = 0; di->usb.name = "USB"; di->usb.type = POWER_SUPPLY_TYPE_USB; di->usb.properties = bq_usb_props; di->usb.num_properties = ARRAY_SIZE(bq_usb_props); di->usb.get_property = bq_usb_get_property; di->power_supply_status = POWER_SUPPLY_HEALTH_GOOD; di->ac.name = "Mains"; di->ac.type = POWER_SUPPLY_TYPE_MAINS; di->ac.properties = bq_ac_props; di->ac.num_properties = ARRAY_SIZE(bq_ac_props); di->ac.get_property = bq_ac_get_property; di->charge_status = POWER_SUPPLY_STATUS_DISCHARGING; di->bk_bat.name = "bq_bk_battery"; di->bk_bat.type = POWER_SUPPLY_TYPE_UPS; di->bk_bat.properties = bq_bk_bci_battery_props; di->bk_bat.num_properties = ARRAY_SIZE(bq_bk_bci_battery_props); di->bk_bat.get_property = bq_bk_bci_battery_get_property; di->capacity = -1; di->capacity_filter_count = 0; di->charge_full_count = 0; for(i=0;i<WINDOW_LEN;i++) { capacity_filter[i] = hisi_battery_capacity(); capacity_sum += capacity_filter[i]; } bq_get_battery_info(di); platform_set_drvdata(pdev, di); wake_lock_init(&low_power_lock, WAKE_LOCK_SUSPEND, "low_power_wake_lock"); low_bat_flag = is_hisi_battery_reach_threshold(); if(( low_bat_flag & BQ27510_FLAG_LOCK ) == BQ27510_FLAG_LOCK) { wake_lock(&low_power_lock); is_low_power_locked = 1; } ret = power_supply_register(&pdev->dev, &di->bat); if (ret) { dev_dbg(&pdev->dev, "failed to register main battery\n"); goto batt_failed; } ret = power_supply_register(&pdev->dev, &di->usb); if (ret) { dev_dbg(&pdev->dev, "failed to register usb power supply\n"); goto usb_failed; } ret = power_supply_register(&pdev->dev, &di->ac); if (ret) { dev_dbg(&pdev->dev, "failed to register ac power supply\n"); goto ac_failed; } ret = power_supply_register(&pdev->dev, &di->bk_bat); if (ret) { dev_dbg(&pdev->dev, "failed to register backup battery\n"); goto bk_batt_failed; } INIT_DELAYED_WORK(&di->bq_bci_monitor_work, bq_bci_battery_work); schedule_delayed_work(&di->bq_bci_monitor_work, 0); di->nb.notifier_call = bq_charger_event; bq_register_notifier(&di->nb, 1); dev_err(&pdev->dev, "bq_bci probe ok!\n"); if (!battery_dclient) { battery_dclient = dsm_register_client(&dsm_battery); } return 0; bk_batt_failed: cancel_delayed_work(&di->bq_bci_monitor_work); power_supply_unregister(&di->ac); ac_failed: power_supply_unregister(&di->usb); usb_failed: power_supply_unregister(&di->bat); batt_failed: wake_lock_destroy(&low_power_lock); platform_set_drvdata(pdev, NULL); kfree(di); di = NULL; return ret; }
int bq_get_error_info(struct bq_bci_device_info *di) { static int pre_bat_err =0, archive_state = 1; static unsigned long timeout_jiffies = 0; static int first_in = 1; static int pre_uf_capacity = 0; static int pre_capacity = 0; static int capacity_stay_count = 0; static int online_delay_count = 0; int bat_uf_capacity = 0; int curr_by_coultype = 1; int dsm_bci_battery_err_offset = 0; if (COUL_HISI_HI6421V300 == hisi_coulometer_type()) curr_by_coultype = -1; di->bat_err = 0; if(!is_hisi_battery_exist()) di->bat_err |= ERROR_BATT_NOT_EXIST; if(hisi_battery_temperature()< BQ2419x_COLD_BATTERY_THRESHOLD || hisi_battery_temperature()>= BQ2419x_HOT_BATTERY_THRESHOLD) { if(di->charge_status == POWER_SUPPLY_STATUS_NOT_CHARGING) di->bat_err |= ERROR_BATT_TEMP_STOP; if(di->charge_status == POWER_SUPPLY_STATUS_CHARGING) di->bat_err |= ERROR_BATT_TEMP_CHARGE; di->bat_err |= ERROR_BATT_TEMP_OUT; dev_info(di->dev,"batt temp = %d\n ", hisi_battery_temperature()); } if(di->charge_status == POWER_SUPPLY_STATUS_NOT_CHARGING && !(bq2419x_get_factory_flag())) { if(di->power_supply_status == POWER_SUPPLY_HEALTH_OVERVOLTAGE) di->bat_err |= ERROR_VBUS_OVERVOLTAGE; if(hisi_battery_voltage() > BATT_OVERVOLTAGE_THRES) di->bat_err |= ERROR_BATT_OVERVOLTAGE; di->bat_err |= ERROR_BATT_NOT_CHARGING; } else { if(hisi_battery_voltage() > BATT_OVERVOLTAGE_THRES || hisi_battery_voltage() < BATT_LOWVOLTAGE_THRES) { di->bat_err |= ERROR_BATT_VOLTAGE; dev_info(di->dev,"batt volt = %d\n ", hisi_battery_voltage()); } } if(di->chargedone_stat && hisi_battery_capacity() <= CHG_CANT_FULL_THRESHOLD){ di->bat_err |= ERROR_PRE_CHARGEDONE; dev_info(di->dev,"batt capacity = %d\n ", hisi_battery_capacity()); } if(di->charge_status == POWER_SUPPLY_STATUS_CHARGING && hisi_battery_current_avg() <= 50 && hisi_battery_current_avg() >= 10 && (curr_by_coultype*hisi_battery_current()) <= 50 && (curr_by_coultype*hisi_battery_current()) >= 10 && di->capacity == 100) { di->bat_err |= ERROR_NO_CHARGEDONE; dev_info(di->dev,"batt curr = %d batt curr_avg = %d\n ", (curr_by_coultype*hisi_battery_current()), hisi_battery_current_avg()); } if((!di->usb_online) && (!di->ac_online)){ if((-hisi_battery_current() > 0) && (online_delay_count++ == 1)){ di->bat_err |= ERROR_BAD_CURR_SENSOR; online_delay_count = 0; dev_info(di->dev,"batt curr = %d\n ", (-hisi_battery_current())); } } else { online_delay_count = 0; } bat_uf_capacity = hisi_battery_unfiltered_capacity(); if(first_in){ pre_uf_capacity = bat_uf_capacity; pre_capacity = di->capacity; first_in = 0; } else { if (abs(pre_uf_capacity - bat_uf_capacity) >= 3) { if (100 != bat_uf_capacity) { di->bat_err |= ERROR_UFCAPCITY_DEBOUNCE_OTHER; } else { if (abs(pre_uf_capacity - bat_uf_capacity) > 10) di->bat_err |= ERROR_UFCAPCITY_DEBOUNCE_100; } hisi_hi6421v300_print_cc_reg(2); //debug } pre_uf_capacity = bat_uf_capacity; } if(di->charge_status == POWER_SUPPLY_STATUS_NOT_CHARGING || di->charge_status == POWER_SUPPLY_STATUS_DISCHARGING) { if(pre_capacity > 0 && di->capacity != pre_capacity) { if(di->capacity > REACH_FULL_RESAMPLE_THRESHOLD) { if(capacity_stay_count <= 2) { di->bat_err |= ERROR_CAPACITY_CHANGE_FAST; capacity_stay_count = 0; } } else if (di->capacity < REACH_EMPTY_RESAMPLE_THRESHOLD) { if(capacity_stay_count <= 12) { di->bat_err |= ERROR_CAPACITY_CHANGE_FAST; capacity_stay_count = 0; } } else { if(capacity_stay_count <= 6) { di->bat_err |= ERROR_CAPACITY_CHANGE_FAST; capacity_stay_count = 0; } } capacity_stay_count = 0; } else { capacity_stay_count++; } } pre_capacity = di->capacity; if (is_hisi_hi6421v300_fcc_debounce()) { di->bat_err |= ERROR_FCC_DEBOUNCE; } if(di->bat_err != pre_bat_err && archive_state == 1){ timeout_jiffies = jiffies + msecs_to_jiffies(LOG_ARCH_DELAY_TIME); archive_state = 0; dev_info(di->dev,"(%s) BATT ERR = %x\n", hisi_battery_brand(), di->bat_err); } pre_bat_err = di->bat_err; if(time_is_before_jiffies(timeout_jiffies) && di->bat_err != 0x0 && archive_state == 0){ //bq_log_exception_archive(di->bat_err); if (dsm_client_ocuppy(battery_dclient)) { dsm_client_record(battery_dclient, "battery error = %x.\n", di->bat_err); dsm_bci_battery_err_offset = get_bit(di->bat_err); dsm_client_notify(battery_dclient, DSM_BATTERY_ERROR_NO + dsm_bci_battery_err_offset); } archive_state = 1; } return di->bat_err; }
static int capacity_changed(struct bq_bci_device_info *di) { int curr_capacity = 0; int low_bat_flag = is_hisi_battery_reach_threshold(); di->bat_exist = is_hisi_battery_exist(); /* if battery is not present we assume it is on battery simulator * if we are in factory mode, BAT FW is not updated yet, we use volt2Capacity */ if ((!di->bat_exist) || (is_fake_battery) || (strstr(saved_command_line, "androidboot.swtype=factory") && (COUL_BQ27510 == hisi_coulometer_type())) ){ curr_capacity = calc_capacity_from_voltage(); } else { curr_capacity = hisi_battery_capacity(); } if((low_bat_flag & BQ27510_FLAG_LOCK) != BQ27510_FLAG_LOCK && is_low_power_locked){ wake_unlock(&low_power_lock); is_low_power_locked = 0; } /* Debouncing of power on init. */ if (di->capacity == -1) { di->capacity = curr_capacity; di->prev_capacity = curr_capacity; return 1; } if (modem_off) { dev_info(di->dev," modem off so shut down AP and curr_capacity = %d \n", curr_capacity); di->capacity = 0; return 1; } /*Only availability if the capacity changed*/ if (curr_capacity != di->prev_capacity) { if (abs(di->prev_capacity -curr_capacity) >= CHG_ODD_CAPACITY){ dev_info(di->dev,"prev_capacity = %d \n" "curr_capacity = %d \n" "curr_voltage = %d \n", di->prev_capacity, curr_capacity,hisi_battery_voltage()); } } if (curr_capacity < 2 ) { int battery_volt; battery_volt = hisi_battery_voltage(); if (battery_volt < BAT_VOL_3500) { di->capacity = curr_capacity; return 1; } dev_err(di->dev, "error capacity reported, capacity = %d\n", curr_capacity); return 0; } switch(di->charge_status) { case POWER_SUPPLY_STATUS_CHARGING: curr_capacity = bq_force_full_timer(curr_capacity,di); break; case POWER_SUPPLY_STATUS_FULL: if(hisi_battery_current_avg() >= 0){ if(hisi_battery_voltage() >= (di->bat_max_volt-RECHG_PROTECT_THRESHOLD)){ curr_capacity = 100; dev_info(di->dev,"Force soc=100\n"); } } di->charge_full_count = 0; break; case POWER_SUPPLY_STATUS_DISCHARGING: case POWER_SUPPLY_STATUS_NOT_CHARGING: /*capacity-count will always decrease when discharging || notcharging*/ if(di->prev_capacity < curr_capacity) return 0; di->charge_full_count = 0; break; default: dev_err(di->dev, "%s defualt run.\n", __func__); break; } /*change monitoring interval from 10s to 30s when capacity greater than 90%*/ if(curr_capacity > REACH_FULL_RESAMPLE_THRESHOLD) { di->monitoring_interval = REACH_FULL_SAMPLE_INTERVAL; } else if(curr_capacity < REACH_EMPTY_RESAMPLE_THRESHOLD) { di->monitoring_interval = REACH_EMPTY_SAMPLE_INTERVAL; } else { di->monitoring_interval = NORMAL_SAMPLE_INTERVAL; } /*filter*/ curr_capacity = bq_capacity_pulling_filter(curr_capacity,di); if(di->prev_capacity == curr_capacity) return 0; dev_info(di->dev,"Capacity Updated = %d, charge_full_count = %d, charge_status = %d\n", curr_capacity, di->charge_full_count, di->charge_status); di->capacity = curr_capacity; di->prev_capacity = curr_capacity; return 1; }