这里分析下mt6735平台下的电池驱动,使用的bq24296芯片(开关模式的充电方式)。
kernel-3.18/drivers/power/mediatek/battery_common.c
static int battery_probe(struct platform_device *dev)
{
struct class_device *class_dev = NULL;
int ret = 0;
battery_log(BAT_LOG_CRTI, "******** battery driver probe!! ********\n");
/* Integrate with NVRAM */
ret = alloc_chrdev_region(&adc_cali_devno, 0, 1, ADC_CALI_DEVNAME);
if (ret)
battery_log(BAT_LOG_CRTI, "Error: Can't Get Major number for adc_cali\n");
adc_cali_cdev = cdev_alloc();
adc_cali_cdev->owner = THIS_MODULE;
adc_cali_cdev->ops = &adc_cali_fops;
ret = cdev_add(adc_cali_cdev, adc_cali_devno, 1);
if (ret)
battery_log(BAT_LOG_CRTI, "adc_cali Error: cdev_add\n");
adc_cali_major = MAJOR(adc_cali_devno);
adc_cali_class = class_create(THIS_MODULE, ADC_CALI_DEVNAME);
class_dev = (struct class_device *)device_create(adc_cali_class,
NULL,
adc_cali_devno, NULL, ADC_CALI_DEVNAME);
battery_log(BAT_LOG_CRTI, "[BAT_probe] adc_cali prepare : done !!\n ");
get_charging_control();
batt_init_cust_data();
battery_charging_control(CHARGING_CMD_GET_PLATFORM_BOOT_MODE, &g_platform_boot_mode);
battery_log(BAT_LOG_CRTI, "[BAT_probe] g_platform_boot_mode = %d\n ", g_platform_boot_mode);
wake_lock_init(&battery_fg_lock, WAKE_LOCK_SUSPEND, "battery fg wakelock");
wake_lock_init(&battery_suspend_lock, WAKE_LOCK_SUSPEND, "battery suspend wakelock");
#if defined(CONFIG_MTK_PUMP_EXPRESS_SUPPORT)
wake_lock_init(&TA_charger_suspend_lock, WAKE_LOCK_SUSPEND, "TA charger suspend wakelock");
#endif
mtk_pep_init();
mtk_pep20_init();
/* Integrate with Android Battery Service */
ret = power_supply_register(&(dev->dev), &ac_main.psy);
if (ret) {
battery_log(BAT_LOG_CRTI, "[BAT_probe] power_supply_register AC Fail !!\n");
return ret;
}
battery_log(BAT_LOG_CRTI, "[BAT_probe] power_supply_register AC Success !!\n");
ret = power_supply_register(&(dev->dev), &usb_main.psy);
if (ret) {
battery_log(BAT_LOG_CRTI, "[BAT_probe] power_supply_register USB Fail !!\n");
return ret;
}
battery_log(BAT_LOG_CRTI, "[BAT_probe] power_supply_register USB Success !!\n");
ret = power_supply_register(&(dev->dev), &wireless_main.psy);
if (ret) {
battery_log(BAT_LOG_CRTI, "[BAT_probe] power_supply_register WIRELESS Fail !!\n");
return ret;
}
battery_log(BAT_LOG_CRTI, "[BAT_probe] power_supply_register WIRELESS Success !!\n");
ret = power_supply_register(&(dev->dev), &battery_main.psy);
if (ret) {
battery_log(BAT_LOG_CRTI, "[BAT_probe] power_supply_register Battery Fail !!\n");
return ret;
}
battery_log(BAT_LOG_CRTI, "[BAT_probe] power_supply_register Battery Success !!\n");
#if !defined(CONFIG_POWER_EXT)
#ifdef CONFIG_MTK_POWER_EXT_DETECT
if (KAL_TRUE == bat_is_ext_power()) {
battery_main.BAT_STATUS = POWER_SUPPLY_STATUS_FULL;
battery_main.BAT_HEALTH = POWER_SUPPLY_HEALTH_GOOD;
battery_main.BAT_PRESENT = 1;
battery_main.BAT_TECHNOLOGY = POWER_SUPPLY_TECHNOLOGY_LION;
battery_main.BAT_CAPACITY = 100;
battery_main.BAT_batt_vol = 4200;
battery_main.BAT_batt_temp = 220;
g_bat_init_flag = KAL_TRUE;
return 0;
}
#endif
/* For EM */
{
int ret_device_file = 0;
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Charger_Voltage);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_0_Slope);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_1_Slope);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_2_Slope);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_3_Slope);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_4_Slope);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_5_Slope);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_6_Slope);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_7_Slope);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_8_Slope);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_9_Slope);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_10_Slope);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_11_Slope);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_12_Slope);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_13_Slope);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_0_Offset);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_1_Offset);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_2_Offset);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_3_Offset);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_4_Offset);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_5_Offset);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_6_Offset);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_7_Offset);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_8_Offset);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_9_Offset);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_10_Offset);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_11_Offset);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_12_Offset);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_13_Offset);
ret_device_file =device_create_file(&(dev->dev), &dev_attr_ADC_Channel_Is_Calibration);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_Power_On_Voltage);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_Power_Off_Voltage);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_Charger_TopOff_Value);
ret_device_file =device_create_file(&(dev->dev), &dev_attr_FG_Battery_CurrentConsumption);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_SW_CoulombCounter);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_Charging_CallState);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_V_0Percent_Tracking);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_Charger_Type);
ret_device_file = device_create_file(&(dev->dev), &dev_attr_Pump_Express);
}
/* battery_meter_initial(); //move to mt_battery_GetBatteryData() to decrease booting time */
/* Initialization BMT Struct */
BMT_status.bat_exist = KAL_TRUE; /* phone must have battery */
BMT_status.charger_exist = KAL_FALSE; /* for default, no charger */
BMT_status.bat_vol = 0;
BMT_status.ICharging = 0;
BMT_status.temperature = 0;
BMT_status.charger_vol = 0;
BMT_status.total_charging_time = 0;
BMT_status.PRE_charging_time = 0;
BMT_status.CC_charging_time = 0;
BMT_status.TOPOFF_charging_time = 0;
BMT_status.POSTFULL_charging_time = 0;
BMT_status.SOC = 0;
BMT_status.UI_SOC = 0;
BMT_status.bat_charging_state = CHR_PRE;
BMT_status.bat_in_recharging_state = KAL_FALSE;
BMT_status.bat_full = KAL_FALSE;
BMT_status.nPercent_ZCV = 0;
BMT_status.nPrecent_UI_SOC_check_point = battery_meter_get_battery_nPercent_UI_SOC();
#if defined(CONFIG_MTK_DUAL_INPUT_CHARGER_SUPPORT)
dual_input_init();
#endif
/* battery kernel thread for 10s check and charger in/out event */
/* Replace GPT timer by hrtime */
battery_kthread_hrtimer_init();
kthread_run(bat_thread_kthread, NULL, "bat_thread_kthread");
battery_log(BAT_LOG_CRTI, "[battery_probe] bat_thread_kthread Done\n");
charger_hv_detect_sw_workaround_init();
/*LOG System Set */
init_proc_log();
#else
/* keep HW alive */
/* charger_hv_detect_sw_workaround_init(); */
#endif
g_bat_init_flag = KAL_TRUE;
#if defined(CONFIG_MTK_DUAL_INPUT_CHARGER_SUPPORT)
if ((g_vcdt_irq_delay_flag == KAL_TRUE) || (upmu_is_chr_det() == KAL_TRUE))
do_chrdet_int_task();
#endif
return 0;
}
get_charging_control();//获取bq24296的接口
batt_init_cust_data();//获取dts中配置的电池数据
battery_kthread_hrtimer_init();//初始化高精度定时器,每10s唤醒bat_thread_kthread
kthread_run(bat_thread_kthread, NULL, "bat_thread_kthread");//创建内核线程
ret = power_supply_register(&(dev->dev), &battery_main.psy);//注册电池电源
get_charging_control();指针数组初始化
typedef signed int(*CHARGING_CONTROL) (CHARGING_CTRL_CMD cmd, void *data);
CHARGING_CONTROL battery_charging_control;
static void get_charging_control(void)
{
battery_charging_control = chr_control_interface;
}
signed int chr_control_interface(CHARGING_CTRL_CMD cmd, void *data)
{
static signed int init = -1;
if (init == -1) {
init = 0;
charging_func[CHARGING_CMD_INIT] = charging_hw_init;
charging_func[CHARGING_CMD_DUMP_REGISTER] = charging_dump_register;
charging_func[CHARGING_CMD_ENABLE] = charging_enable;
charging_func[CHARGING_CMD_SET_CV_VOLTAGE] = charging_set_cv_voltage;
charging_func[CHARGING_CMD_GET_CURRENT] = charging_get_current;
charging_func[CHARGING_CMD_SET_CURRENT] = charging_set_current;
charging_func[CHARGING_CMD_SET_INPUT_CURRENT] = charging_set_input_current;
charging_func[CHARGING_CMD_GET_CHARGING_STATUS] = charging_get_charging_status;
charging_func[CHARGING_CMD_RESET_WATCH_DOG_TIMER] = charging_reset_watch_dog_timer;
charging_func[CHARGING_CMD_SET_HV_THRESHOLD] = charging_set_hv_threshold;
charging_func[CHARGING_CMD_GET_HV_STATUS] = charging_get_hv_status;
charging_func[CHARGING_CMD_GET_BATTERY_STATUS] = charging_get_battery_status;
charging_func[CHARGING_CMD_GET_CHARGER_DET_STATUS] = charging_get_charger_det_status;
charging_func[CHARGING_CMD_GET_CHARGER_TYPE] = charging_get_charger_type;
charging_func[CHARGING_CMD_SET_PLATFORM_RESET] = charging_set_platform_reset;
charging_func[CHARGING_CMD_GET_PLATFORM_BOOT_MODE] = charging_get_platform_boot_mode;
charging_func[CHARGING_CMD_SET_POWER_OFF] = charging_set_power_off;
charging_func[CHARGING_CMD_SET_TA_CURRENT_PATTERN] = charging_set_ta_current_pattern;
charging_func[CHARGING_CMD_SET_ERROR_STATE] = charging_set_error_state;
charging_func[CHARGING_CMD_DISO_INIT] = charging_diso_init;
charging_func[CHARGING_CMD_GET_DISO_STATE] = charging_get_diso_state;
charging_func[CHARGING_CMD_SET_VBUS_OVP_EN] = charging_set_vbus_ovp_en;
charging_func[CHARGING_CMD_SET_VINDPM] = charging_set_vindpm;
}
if (cmd < CHARGING_CMD_NUMBER) {
if (charging_func[cmd] != NULL)
return charging_func[cmd](data);
}
pr_debug("[%s]UNSUPPORT Function: %d\n", __func__, cmd);
return STATUS_UNSUPPORTED;
}
power_supply_register(&(dev->dev), &battery_main.psy);
上层要获取电池属性,相当于直接获取全局结构体battery_data的值。
struct battery_data {
struct power_supply psy;
int BAT_STATUS;
int BAT_HEALTH;
int BAT_PRESENT;
int BAT_TECHNOLOGY;
int BAT_CAPACITY;
/* Add for Battery Service */
int BAT_batt_vol;
int BAT_batt_temp;
/* Add for EM */
int BAT_TemperatureR;
int BAT_TempBattVoltage;
int BAT_InstatVolt;
int BAT_BatteryAverageCurrent;
int BAT_BatterySenseVoltage;
int BAT_ISenseVoltage;
int BAT_ChargerVoltage;
/* Dual battery */
int status_smb;
int capacity_smb;
int present_smb;
int adjust_power;
};
static enum power_supply_property battery_props[] = {
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_TECHNOLOGY,
POWER_SUPPLY_PROP_CAPACITY,
/* Add for Battery Service */
POWER_SUPPLY_PROP_batt_vol,
POWER_SUPPLY_PROP_batt_temp,
/* Add for EM */
POWER_SUPPLY_PROP_TemperatureR,
POWER_SUPPLY_PROP_TempBattVoltage,
POWER_SUPPLY_PROP_InstatVolt,
POWER_SUPPLY_PROP_BatteryAverageCurrent,
POWER_SUPPLY_PROP_BatterySenseVoltage,
POWER_SUPPLY_PROP_ISenseVoltage,
POWER_SUPPLY_PROP_ChargerVoltage,
/* Dual battery */
POWER_SUPPLY_PROP_status_smb,
POWER_SUPPLY_PROP_capacity_smb,
POWER_SUPPLY_PROP_present_smb,
/* ADB CMD Discharging */
POWER_SUPPLY_PROP_adjust_power,
};
static int battery_get_property(struct power_supply *psy,
enum power_supply_property psp, union power_supply_propval *val)
{
int ret = 0;
struct battery_data *data = container_of(psy, struct battery_data, psy);
switch (psp) {
case POWER_SUPPLY_PROP_STATUS:
val->intval = data->BAT_STATUS;
break;
case POWER_SUPPLY_PROP_HEALTH:
val->intval = data->BAT_HEALTH;
break;
case POWER_SUPPLY_PROP_PRESENT:
val->intval = data->BAT_PRESENT;
break;
case POWER_SUPPLY_PROP_TECHNOLOGY:
val->intval = data->BAT_TECHNOLOGY;
break;
case POWER_SUPPLY_PROP_CAPACITY:
val->intval = data->BAT_CAPACITY;
break;
case POWER_SUPPLY_PROP_batt_vol:
val->intval = data->BAT_batt_vol;
break;
case POWER_SUPPLY_PROP_batt_temp:
val->intval = data->BAT_batt_temp;
break;
case POWER_SUPPLY_PROP_TemperatureR:
val->intval = data->BAT_TemperatureR;
break;
case POWER_SUPPLY_PROP_TempBattVoltage:
val->intval = data->BAT_TempBattVoltage;
break;
case POWER_SUPPLY_PROP_InstatVolt:
val->intval = data->BAT_InstatVolt;
break;
case POWER_SUPPLY_PROP_BatteryAverageCurrent:
val->intval = data->BAT_BatteryAverageCurrent;
break;
case POWER_SUPPLY_PROP_BatterySenseVoltage:
val->intval = data->BAT_BatterySenseVoltage;
break;
case POWER_SUPPLY_PROP_ISenseVoltage:
val->intval = data->BAT_ISenseVoltage;
break;
case POWER_SUPPLY_PROP_ChargerVoltage:
val->intval = data->BAT_ChargerVoltage;
break;
/* Dual battery */
case POWER_SUPPLY_PROP_status_smb:
val->intval = data->status_smb;
break;
case POWER_SUPPLY_PROP_capacity_smb:
val->intval = data->capacity_smb;
break;
case POWER_SUPPLY_PROP_present_smb:
val->intval = data->present_smb;
break;
case POWER_SUPPLY_PROP_adjust_power:
val->intval = data->adjust_power;
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
/* battery_data initialization */
static struct battery_data battery_main = {
.psy = {
.name = "battery",
.type = POWER_SUPPLY_TYPE_BATTERY,
.properties = battery_props,
.num_properties = ARRAY_SIZE(battery_props),
.get_property = battery_get_property,
},
/* CC: modify to have a full power supply status */
#if defined(CONFIG_POWER_EXT)
.BAT_STATUS = POWER_SUPPLY_STATUS_FULL,
.BAT_HEALTH = POWER_SUPPLY_HEALTH_GOOD,
.BAT_PRESENT = 1,
.BAT_TECHNOLOGY = POWER_SUPPLY_TECHNOLOGY_LION,
.BAT_CAPACITY = 100,
.BAT_batt_vol = 4200,
.BAT_batt_temp = 22,
/* Dual battery */
.status_smb = POWER_SUPPLY_STATUS_NOT_CHARGING,
.capacity_smb = 50,
.present_smb = 0,
/* ADB CMD discharging */
.adjust_power = -1,
#else
.BAT_STATUS = POWER_SUPPLY_STATUS_NOT_CHARGING,
.BAT_HEALTH = POWER_SUPPLY_HEALTH_GOOD,
.BAT_PRESENT = 1,
.BAT_TECHNOLOGY = POWER_SUPPLY_TECHNOLOGY_LION,
#if defined(PUMP_EXPRESS_SERIES)
.BAT_CAPACITY = -1,
#else
.BAT_CAPACITY = 50,
#endif
.BAT_batt_vol = 0,
.BAT_batt_temp = 0,
/* Dual battery */
.status_smb = POWER_SUPPLY_STATUS_NOT_CHARGING,
.capacity_smb = 50,
.present_smb = 0,
/* ADB CMD discharging */
.adjust_power = -1,
#endif
};
下面看下电池线程函数
void BAT_thread(void)
{
static kal_bool battery_meter_initilized = KAL_FALSE;
static int first_time_update;
if (battery_meter_initilized == KAL_FALSE) {
battery_meter_initial(); /* move from battery_probe() to decrease booting time */
BMT_status.nPercent_ZCV = battery_meter_get_battery_nPercent_zcv();
battery_meter_initilized = KAL_TRUE;
}
mt_battery_charger_detect_check();
if (fg_battery_shutdown)
return;
mt_battery_GetBatteryData();
if (fg_battery_shutdown)
return;
if (BMT_status.charger_exist == KAL_TRUE)
check_battery_exist();
mt_battery_thermal_check();
mt_battery_notify_check();
if (first_time_update == 0) {
mt_battery_update_status();
if (BMT_status.charger_exist == KAL_TRUE) {
mt_battery_CheckBatteryStatus();
mt_battery_charging_algorithm();
}
first_time_update = 1;
} else {
if (BMT_status.charger_exist == KAL_TRUE && !fg_battery_shutdown) {
mt_battery_CheckBatteryStatus();
mt_battery_charging_algorithm();
}
mt_battery_update_status();
}
mt_kpoc_power_off_check();
}
int bat_thread_kthread(void *x)
{
ktime_t ktime = ktime_set(3, 0); /* 10s, 10* 1000 ms */
/* Run on a process content */
while (!fg_battery_shutdown) {
mutex_lock(&bat_mutex);
if (((chargin_hw_init_done == KAL_TRUE) && (battery_suspended == KAL_FALSE))
|| ((chargin_hw_init_done == KAL_TRUE) && (fg_wake_up_bat == KAL_TRUE)))
BAT_thread();
mutex_unlock(&bat_mutex);
#ifdef FG_BAT_INT
if (fg_wake_up_bat == KAL_TRUE) {
wake_unlock(&battery_fg_lock);
fg_wake_up_bat = KAL_FALSE;
battery_log(BAT_LOG_CRTI, "unlock battery_fg_lock\n");
}
#endif /* #ifdef FG_BAT_INT */
battery_log(BAT_LOG_FULL, "wait event\n");
wait_event(bat_thread_wq, (bat_thread_timeout == KAL_TRUE));
bat_thread_timeout = KAL_FALSE;
hrtimer_start(&battery_kthread_timer, ktime, HRTIMER_MODE_REL);
/* 10s, 10* 1000 ms */
if (!fg_battery_shutdown)
ktime = ktime_set(BAT_TASK_PERIOD, 0);
if (chr_wake_up_bat == KAL_TRUE && g_smartbook_update != 1) { /* for charger plug in/ out */
#if defined(CONFIG_MTK_DUAL_INPUT_CHARGER_SUPPORT)
if (DISO_data.chr_get_diso_state) {
DISO_data.chr_get_diso_state = KAL_FALSE;
battery_charging_control(CHARGING_CMD_GET_DISO_STATE, &DISO_data);
}
#endif
g_smartbook_update = 0;
battery_meter_reset();
chr_wake_up_bat = KAL_FALSE;
battery_log(BAT_LOG_CRTI,
"[BATTERY] Charger plug in/out, Call battery_meter_reset. (%d)\n",
BMT_status.UI_SOC);
}
}
mutex_lock(&bat_mutex);
fg_bat_thread = KAL_TRUE;
mutex_unlock(&bat_mutex);
return 0;
}
mt_battery_charger_detect_check//检测充电器的类型
mt_battery_GetBatteryData()//获取电池数据
mt_battery_thermal_check()/电池温度检查
mt_battery_notify_check();//电池其他参数检查
mt_battery_charging_algorithm();充电算法(充电硬件初始化,选择充电电流)
mt_battery_update_status()//更新电池数据
mt_battery_GetBatteryData
void mt_battery_GetBatteryData(void)
{
unsigned int bat_vol, charger_vol, Vsense, ZCV;
signed int ICharging, temperature, temperatureR, temperatureV, SOC;
static signed int bat_sum, icharging_sum, temperature_sum;
static signed int batteryVoltageBuffer[BATTERY_AVERAGE_SIZE];
static signed int batteryCurrentBuffer[BATTERY_AVERAGE_SIZE];
static signed int batteryTempBuffer[BATTERY_AVERAGE_SIZE];
static unsigned char batteryIndex;
static signed int previous_SOC = -1;
kal_bool current_sign;
bat_vol = battery_meter_get_battery_voltage(KAL_TRUE);
Vsense = battery_meter_get_VSense();
if (upmu_is_chr_det() == KAL_TRUE)
ICharging = battery_meter_get_charging_current();
else
ICharging = 0;
charger_vol = battery_meter_get_charger_voltage();
temperature = battery_meter_get_battery_temperature();
temperatureV = battery_meter_get_tempV();
temperatureR = battery_meter_get_tempR(temperatureV);
if (bat_meter_timeout == KAL_TRUE || bat_spm_timeout == TRUE || fg_wake_up_bat == KAL_TRUE) {
SOC = battery_meter_get_battery_percentage();
/* if (bat_spm_timeout == true) */
/* BMT_status.UI_SOC = battery_meter_get_battery_percentage(); */
bat_meter_timeout = KAL_FALSE;
bat_spm_timeout = FALSE;
} else {
if (previous_SOC == -1)
SOC = battery_meter_get_battery_percentage();
else
SOC = previous_SOC;
}
ZCV = battery_meter_get_battery_zcv();
BMT_status.ICharging =
mt_battery_average_method(BATTERY_AVG_CURRENT, &batteryCurrentBuffer[0], ICharging,
&icharging_sum, batteryIndex);
if (previous_SOC == -1 && bat_vol <= batt_cust_data.v_0percent_tracking) {
battery_log(BAT_LOG_CRTI,
"battery voltage too low, use ZCV to init average data.\n");
BMT_status.bat_vol =
mt_battery_average_method(BATTERY_AVG_VOLT, &batteryVoltageBuffer[0], ZCV,
&bat_sum, batteryIndex);
} else {
BMT_status.bat_vol =
mt_battery_average_method(BATTERY_AVG_VOLT, &batteryVoltageBuffer[0], bat_vol,
&bat_sum, batteryIndex);
}
if (battery_cmd_thermal_test_mode == 1) {
battery_log(BAT_LOG_CRTI, "test mode , battery temperature is fixed.\n");
} else {
BMT_status.temperature =
mt_battery_average_method(BATTERY_AVG_TEMP, &batteryTempBuffer[0], temperature,
&temperature_sum, batteryIndex);
}
BMT_status.Vsense = Vsense;
BMT_status.charger_vol = charger_vol;
BMT_status.temperatureV = temperatureV;
BMT_status.temperatureR = temperatureR;
BMT_status.SOC = SOC;
BMT_status.ZCV = ZCV;
BMT_status.IBattery = battery_meter_get_battery_current();
current_sign = battery_meter_get_battery_current_sign();
BMT_status.IBattery *= (current_sign ? 1 : (-1));
if (BMT_status.charger_exist == KAL_FALSE) {
if (BMT_status.SOC > previous_SOC && previous_SOC >= 0)
BMT_status.SOC = previous_SOC;
}
previous_SOC = BMT_status.SOC;
batteryIndex++;
if (batteryIndex >= BATTERY_AVERAGE_SIZE)
batteryIndex = 0;
if (g_battery_soc_ready == KAL_FALSE)
g_battery_soc_ready = KAL_TRUE;
battery_log(BAT_LOG_CRTI,
"AvgVbat=(%d,%d),AvgI=(%d,%d),VChr=%d,AvgT=(%d,%d),SOC=(%d,%d),UI_SOC=%d,ZCV=%d,CHR_Type=%d bcct:%d:%d I:%d Ibat:%d\n",
BMT_status.bat_vol, bat_vol, BMT_status.ICharging, ICharging,
BMT_status.charger_vol, BMT_status.temperature, temperature,
previous_SOC, BMT_status.SOC, BMT_status.UI_SOC, BMT_status.ZCV,
BMT_status.charger_type, g_bcct_flag, get_usb_current_unlimited(),
get_bat_charging_current_level(), BMT_status.IBattery / 10);
battery_log(BAT_LOG_CRTI, "v=%d,i=%d,t=%d,soc=%d,bcct:%d:%d I:%d Ibat:%d\n",
bat_vol, ICharging, temperature, BMT_status.UI_SOC, g_bcct_flag,
get_usb_current_unlimited(), get_bat_charging_current_level(),
BMT_status.IBattery / 10);
}
battery_meter_get_battery_percentage //获取电池电量(方式1通过开路电压与容量的关系 方式2根据开路电压算出初始电量,然后通过库伦积分算出消耗的电量)
BMT_status.bat_vol, bat_vol, //该段时间的平均电池电压 //电池电压(直接读寄存器)
BMT_status.ICharging //电流(平台硬件差异这里是0,这里通过的是库仑计获取电流)
BMT_status.charger_vol //充电器电压 根据pmic6328vcdt脚获取到的电压,根据分压原理算出vbus的电压 其中vcdt还有一个功能,
作为充电器的中断检测,来判断充电器的插拔
BMT_status.temperature, temperature, //电池温度
BMT_status.SOC, BMT_status.UI_SOC //电池容量 电池ui容量
BMT_status.ZCV//电路开路电压
BMT_status.charger_type//充电器类型
g_bcct_flag//充电是否被限流(高温或者其他情况)
get_bat_charging_current_level(), //获取充电电流等级(bq24296对应的值)
mt_battery_update_status//更新全局结构体battery_data的值,上层便能及时获取到电池的数据
static void mt_battery_update_status(void)
{
#if defined(CONFIG_POWER_EXT)
battery_log(BAT_LOG_CRTI, "[BATTERY] CONFIG_POWER_EXT, no update Android.\n");
#else
{
if (skip_battery_update == KAL_FALSE) {
battery_log(BAT_LOG_FULL, "mt_battery_update_status.\n");
usb_update(&usb_main);
ac_update(&ac_main);
wireless_update(&wireless_main);
battery_update(&battery_main);
} else {
battery_log(BAT_LOG_CRTI, "skip mt_battery_update_status.\n");
skip_battery_update = KAL_FALSE;
}
}
#endif
}
static void battery_update(struct battery_data *bat_data)
{
struct power_supply *bat_psy = &bat_data->psy;
kal_bool resetBatteryMeter = KAL_FALSE;
static unsigned int update_cnt = 3;
static unsigned int pre_uisoc;
static unsigned int pre_chr_state;
bat_data->BAT_TECHNOLOGY = POWER_SUPPLY_TECHNOLOGY_LION;
bat_data->BAT_HEALTH = POWER_SUPPLY_HEALTH_GOOD;
bat_data->BAT_batt_vol = BMT_status.bat_vol;
bat_data->BAT_batt_temp = BMT_status.temperature * 10;
bat_data->BAT_PRESENT = BMT_status.bat_exist;
if ((BMT_status.charger_exist == KAL_TRUE) && (BMT_status.bat_charging_state != CHR_ERROR)) {
if (BMT_status.bat_exist) { /* charging */
if (BMT_status.bat_vol <= batt_cust_data.v_0percent_tracking)
resetBatteryMeter = mt_battery_0Percent_tracking_check();
else
resetBatteryMeter = mt_battery_100Percent_tracking_check();
bat_data->BAT_STATUS = POWER_SUPPLY_STATUS_CHARGING;
} else { /* No Battery, Only Charger */
bat_data->BAT_STATUS = POWER_SUPPLY_STATUS_UNKNOWN;
BMT_status.UI_SOC = 0;
}
} else { /* Only Battery */
bat_data->BAT_STATUS = POWER_SUPPLY_STATUS_NOT_CHARGING;
if (BMT_status.bat_vol <= batt_cust_data.v_0percent_tracking)
resetBatteryMeter = mt_battery_0Percent_tracking_check();
else
resetBatteryMeter = mt_battery_nPercent_tracking_check();
}
if (resetBatteryMeter == KAL_TRUE) {
battery_meter_reset();
} else {
if (BMT_status.bat_full == KAL_TRUE && is_uisoc_ever_100 == KAL_TRUE) {
BMT_status.UI_SOC = 100;
battery_log(BAT_LOG_CRTI, "[recharging] UI_SOC=%d, SOC=%d\n",
BMT_status.UI_SOC, BMT_status.SOC);
} else {
mt_battery_Sync_UI_Percentage_to_Real();
}
}
battery_log(BAT_LOG_CRTI, "UI_SOC=(%d), resetBatteryMeter=(%d)\n",
BMT_status.UI_SOC, resetBatteryMeter);
/* set RTC SOC to 1 to avoid SOC jump in charger boot.*/
if (BMT_status.UI_SOC <= 1)
set_rtc_spare_fg_value(1);
else
set_rtc_spare_fg_value(BMT_status.UI_SOC);
mt_battery_update_EM(bat_data);
if (cmd_discharging == 1)
bat_data->BAT_STATUS = POWER_SUPPLY_STATUS_CMD_DISCHARGING;
if (adjust_power != -1) {
bat_data->adjust_power = adjust_power;
battery_log(BAT_LOG_CRTI, "adjust_power=(%d)\n", adjust_power);
}
#ifdef DLPT_POWER_OFF_EN
/*extern int dlpt_check_power_off(void);*/
if (bat_data->BAT_CAPACITY <= DLPT_POWER_OFF_THD) {
static signed char cnt;
battery_log(BAT_LOG_CRTI, "[DLPT_POWER_OFF_EN] run\n");
if (dlpt_check_power_off() == 1) {
bat_data->BAT_CAPACITY = 0;
cnt++;
battery_log(BAT_LOG_CRTI, "[DLPT_POWER_OFF_EN] SOC=%d to power off\n",
bat_data->BAT_CAPACITY);
if (cnt >= 2)
kernel_restart("DLPT reboot system");
} else
cnt = 0;
} else {
battery_log(BAT_LOG_CRTI, "[DLPT_POWER_OFF_EN] disable(%d)\n",
bat_data->BAT_CAPACITY);
}
#endif
if (update_cnt >= 3) {
/* Update per 60 seconds */
power_supply_changed(bat_psy);
pre_uisoc = BMT_status.UI_SOC;
update_cnt = 0;
pre_chr_state = BMT_status.bat_charging_state;
if (cable_in_uevent == 1)
cable_in_uevent = 0;
} else if ((pre_uisoc != BMT_status.UI_SOC) || (BMT_status.UI_SOC == 0)) {
/* Update when soc change */
power_supply_changed(bat_psy);
pre_uisoc = BMT_status.UI_SOC;
update_cnt = 0;
} else if ((BMT_status.charger_exist == KAL_TRUE) &&
((pre_chr_state != BMT_status.bat_charging_state) ||
(BMT_status.bat_charging_state == CHR_ERROR))) {
/* Update when changer status change */
power_supply_changed(bat_psy);
pre_chr_state = BMT_status.bat_charging_state;
update_cnt = 0;
} else if (cable_in_uevent == 1) {
/*To prevent interrupt-trigger update from being filtered*/
power_supply_changed(bat_psy);
cable_in_uevent = 0;
} else {
/* No update */
update_cnt++;
}
}
mt_battery_0Percent_tracking_check//低于关机电压监测,让ui电池容量减少到0,这时framework层会让系统关机
mt_battery_nPercent_tracking_check//n可自行定制,库仑积分计算的电量跟ocv(开路电压)计算的电量进行同步,保证电量计算的可靠性。
mt_battery_Sync_UI_Percentage_to_Real();//同步ui显示的电量百分比