/********************************************************** * Function: charge_core_sbatt_by_vbat_ichg_handler * Discription: update the charge parameters in different segment charging * Parameters: vbat:battery voltage * segment_data[]:the table for describe the segment property * data:charge parameters * return value: NULL **********************************************************/ static void charge_core_sbatt_by_vbat_ichg_handler(int vbat, struct charge_segment_data segment_data[], struct charge_core_data *data) { int i,ichg; static int last_i = 0; static int last_vterm = 0; static int last_ichg = 0; static int last_vbat = 0; static int flag_running_first = 1; ichg = -hisi_battery_current(); /* choose index of segment_data */ for (i = 0; i < data->segment_level; i++) { if ((vbat >= segment_data[i].vbat_min) && (vbat < segment_data[i].vbat_max) && ichg < segment_data[i].ichg_segment) { if ((last_i - i <= 0) || (segment_data[i].vbat_max - vbat > segment_data[i].volt_back) || (abs(last_i - i) > 1) || (flag_running_first == 1)) { /*do nothing,just get index "i" */ } else { i = i+1; } break; } } /* if cannot choose right index ,keep last index */ if(i == data->segment_level) { i=last_i; } /* set ichg and vterm according to index only when two consecutive index is the same ,or keep last ichg and vterm */ if(last_i == i || flag_running_first == 1) { data->ichg = data->ichg < segment_data[i].ichg_segment ? data->ichg : segment_data[i].ichg_segment; data->vterm = data->vterm < segment_data[i].vterm_segment ? data->vterm : segment_data[i].vterm_segment; } else { data->ichg = data->ichg < last_ichg ? data->ichg :last_ichg; data->vterm = data->vterm < last_vterm ? data->vterm : last_vterm; } hwlog_info("%s :ichg = %d,vbat =%d , last_i =%d, i =%d,segment_data[i].ichg_segment =%d ,data->ichg =%d ,last_ichg = %d \n", __func__,ichg,vbat,last_i,i,segment_data[i].ichg_segment,data->ichg,last_ichg); last_i = i; flag_running_first = 0; last_vbat = vbat; last_ichg = data->ichg; last_vterm = data->vterm; }
static void get_current_work_func(struct work_struct *work) { int value = 0; #if 0 value = hisi_battery_current(); #endif /*send current to iom3*/ if (send_func) { (*send_func)(value); } if(atomic_read(&enabled)) schedule_delayed_work(&read_current_work, msecs_to_jiffies(READ_CURRENT_INTERVAL)); }
static int calc_capacity_from_voltage(void) { int data = 50; int battery_voltage = 0; int battery_current = 0; battery_current = -hisi_battery_current(); battery_voltage = hisi_battery_voltage();//bq27510_battery_voltage(&dev27510); if (battery_voltage <= BAT_VOL_3200){ data = 0; return data; } battery_voltage = hisi_battery_voltage()-120*battery_current/1000; if (battery_voltage < BAT_VOL_3500) data = 2; else if (battery_voltage < BAT_VOL_3550) data = 10; else if (battery_voltage < BAT_VOL_3600) data = 20; else if (battery_voltage < BAT_VOL_3700) data = 30; else if (battery_voltage < BAT_VOL_3800) data = 40; else if (battery_voltage < BAT_VOL_3850) data = 50; else if (battery_voltage < BAT_VOL_3900) data = 60; else if (battery_voltage < BAT_VOL_3950) data = 65; else if (battery_voltage < BAT_VOL_4000) data = 70; else if (battery_voltage < BAT_VOL_4250) data = 85; else if (battery_voltage >= BAT_VOL_4250) data = 100; return data; }
static int bq_bci_battery_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { struct bq_bci_device_info *di; di = to_bq_bci_device_info(psy); switch (psp) { case POWER_SUPPLY_PROP_STATUS: val->intval = di->charge_status; break; case POWER_SUPPLY_PROP_VOLTAGE_NOW: di->bat_voltage = hisi_battery_voltage(); if (COUL_HISI_HI6421V300 == hisi_coulometer_type()){ val->intval = hisi_battery_voltage_uv(); } else{ val->intval = di->bat_voltage * 1000; } break; case POWER_SUPPLY_PROP_CURRENT_NOW: di->bat_current = hisi_battery_current(); if(COUL_HISI_HI6421V300 == hisi_coulometer_type()){ di->bat_current = -(di->bat_current); } val->intval = di->bat_current; break; case POWER_SUPPLY_PROP_TEMP: val->intval = di->bat_temperature * 10; break; case POWER_SUPPLY_PROP_PRESENT: case POWER_SUPPLY_PROP_ONLINE: val->intval = di->bat_exist; break; case POWER_SUPPLY_PROP_HEALTH: val->intval = di->bat_health; break; case POWER_SUPPLY_PROP_CAPACITY: if (modem_off) { val->intval = 0; }else{ val->intval = di->capacity; } break; case POWER_SUPPLY_PROP_CAPACITY_LEVEL: val->intval = di->bat_capacity_level; break; case POWER_SUPPLY_PROP_TECHNOLOGY: val->intval = di->bat_technolog; break; case POWER_SUPPLY_PROP_CAPACITY_RM: val->intval = di->bat_rm; break; case POWER_SUPPLY_PROP_CAPACITY_FCC: val->intval = di->bat_fcc; break; case POWER_SUPPLY_PROP_VOLTAGE_MAX: val->intval = di->bat_max_volt; break; case POWER_SUPPLY_PROP_ID_VOLTAGE: val->intval = hisi_battery_id_voltage(); break; case POWER_SUPPLY_PROP_BRAND: val->strval = hisi_battery_brand(); break; default: return -EINVAL; } return 0; }
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; }