mtk 电池管理hw_ocv的更新和获取方法
[DESCRIPTION]
电量计算过程中,旧gauge算法和GM2.0都会经常用到hw_ocv的值,那到底hw_ocv如何获取?hw_ocv又是何时更新?
[SOLUTION]
1.hw_ocv何时更新:
hw_ocv表示电池的开路电压,我们的做法是让硬件在合适的时间点通过ADC获取电池电压的值保存到对应的寄存器,
在需要用到hw_ocv的值时才会通过软件读寄存器的值,并不会像去读电池CV电压一样通过一个ADC通道实时读取和更新,
hw_ocv对应寄存器的值在如下两个时间点会得到更新:
(1)手机第一次上电时会更新一次,即 AV(LDO)信号起来后2~3mS内会更新一次;
(2)手机休眠唤醒过程会更新一次,即SRCLKEN(26MHz时钟)信号从0->1时更新一次。
2.旧gauge算法获取hw_ocv的方法:
直接通过下面这个回调函数接口,调到battery_meter_hal.c里面对应接口读取寄存器的值
1388 ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_OCV, &gFG_voltage);
3.GM2.0获取hw_ocv的方法:
从battery_meter_hal.c对应接口读取到寄存器的值后,通过netlink将hw_ocv的值传到GM2.0上层daemon。
/kernel-3.10/drivers/power/mediatek/battery_meter_fg_20.c
void bmd_ctrl_cmd_from_user(void *nl_data, struct fgd_nl_msg_t *ret_msg)
{
switch (msg->fgd_cmd) {
case FG_DAEMON_CMD_GET_HW_OCV:
{
kal_int32 voltage = 0;
battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_OCV, &voltage);
ret_msg->fgd_data_len += sizeof(voltage);
memcpy(ret_msg->fgd_data, &voltage, sizeof(voltage));
//bm_print(BM_LOG_CRTI, " ret_msg->fgd_data_len %d\n",ret_msg->fgd_data_len);
bm_print(BM_LOG_CRTI, "[fg_res] voltage = %d\n",voltage);
gFG_hwocv = voltage;
}
break;
4.battery_meter_hal.c里面对应的接口函数如下:
定义宏值SWCHR_POWER_PATH选择不同的通道,分别对应硬件BATSENS & ISENSE两个PIN的电压。
/kernel-3.10/drivers/misc/mediatek/power/mt6735/battery_meter_hal.c
int get_hw_ocv(void)
{
#if defined(CONFIG_POWER_EXT)
return 4001;
bm_print(BM_LOG_CRTI, "[get_hw_ocv] TBD\n");
#else
kal_int32 adc_result_reg=0;
kal_int32 adc_result=0;
kal_int32 r_val_temp=3; //MT6325 use 2, old chip use 4
#if defined(SWCHR_POWER_PATH)
adc_result_reg = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_WAKEUP_SWCHR);//mt6325_upmu_get_rg_adc_out_wakeup_swchr();
adc_result = (adc_result_reg*r_val_temp*VOLTAGE_FULL_RANGE)/ADC_PRECISE;
bm_print(BM_LOG_CRTI, "[oam] get_hw_ocv (swchr) : adc_result_reg=%d, adc_result=%d\n",
adc_result_reg, adc_result);
#else
adc_result_reg = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_WAKEUP_PCHR);//mt6325_upmu_get_rg_adc_out_wakeup_pchr();
adc_result = (adc_result_reg*r_val_temp*VOLTAGE_FULL_RANGE)/ADC_PRECISE;
bm_print(BM_LOG_CRTI, "[oam] get_hw_ocv (pchr) : adc_result_reg=%d, adc_result=%d\n",
adc_result_reg, adc_result);
#endif
adc_result += g_hw_ocv_tune_value;
return adc_result;
#endif
}