相关概念
懒的排版了,直接上图 
相关文件关系
再来一发 
杂项,电池温度检测原理图
发 
充电流程
图样图森破 
核心函数特写



-
/* 概念: -
ZCV:开路电压 -
OCV: 开路电压 -
VC:闭路电压 -
CAR:库伦计 -
DOD: 放电深度,100-DOD 即电容容量 -
Cmax/Qmax: 电池容量 -
相关文件关系: -
Battery_common.c (s:\i841\mediatek\kernel\drivers\power) // 充电逻辑文件 -
Charging_hw_pmic.c (s:\i841\mediatek\platform\mt6582\kernel\drivers\power) // 具体的充电芯片,相关电池参数检测 -
Linear_charging.c (s:\i841\mediatek\kernel\drivers\power) // 充电状态控制,内部 PMIC -
Switch_charging.c (s:\i841\mediatek\kernel\drivers\power) // 充电状态控制,外部 Charge IC -
硬件原理图: -
NTC 检测温度电路原理如下: -
Vu Ru:上拉电阻值 -
--- Rd: 下拉电阻值 -
| Rntc: NTC 温度电阻 阻值 -
||| Ru Vu: 上拉电压值 -
| Gnd: 地 -
---------- -----Vntc Vntc: NTC 电压 -
| | -
Rntc ||| ||| Rd -
| | -
---------- Rntc = (Ru*Rd*Vntc) / (Vru * Rd - Vntc * Ru) -
| -
----- -
--- -
- -
Gnd -
【充电初始化流程】: -
module_init(battery_init) -
battery_init(void) -
// 注册平台设备 -
platform_device_register(&battery_device) -
// 注册平台驱动 -
platform_driver_register(&battery_driver) -
// 二者匹配调用 probe 函数 -
battery_probe() -
/ -
// 注册字符设备 -
alloc_chrdev_region(&adc_cali_devno, 0, 1, ADC_CALI_DEVNAME) -
cdev_add(adc_cali_cdev, adc_cali_devno, 1) -
/ -
// 创建相关 sys 系统节点 -
class_create(THIS_MODULE, ADC_CALI_DEVNAME) -
device_create(adc_cali_class, NULL, adc_cali_devno, NULL, ADC_CALI_DEVNAME) -
// 与特定硬件的入口操作函数关联 -
get_charging_control() -
// 用来绑定内部 PMIC 或者外部充电芯片的操作函数入口 -
battery_charging_control = chr_control_interface; -
相关充电芯片驱动实现的函数有: -
charging_hw_init -
charging_dump_register -
charging_enable -
charging_set_cv_voltage -
charging_get_current -
charging_set_current -
charging_set_input_current -
charging_get_charging_status -
charging_reset_watch_dog_timer -
charging_set_hv_threshold -
charging_get_hv_status -
charging_get_battery_status -
charging_get_charger_det_status -
charging_get_charger_type -
charging_get_is_pcm_timer_trigger -
charging_set_platform_reset -
charging_get_platfrom_boot_mode -
charging_set_power_off -
// -
// 获得启动模式 -
battery_charging_control(CHARGING_CMD_GET_PLATFORM_BOOT_MODE, &g_platform_boot_mode) -
// 对应 pmic 的 charging_get_platfrom_boot_mode() -
charging_get_platfrom_boot_mode() -
get_boot_mode() -
/ -
// Integrate with Android Battery Service -
// 一般移动设备的供电可来自外部即 AC 与 usb,内部电池供电 battery, -
// 所以需通过 power_supply_register() 函数在 /sys/class/power_supply 下分别 -
// 注册 ac usb battery,注册完成可发现在设备目录 /sys/class/power_supply 下分别 -
// 出现 ac usb battery 三个文件夹 -
power_supply_register(&(dev->dev), &ac_main.psy) -
power_supply_register(&(dev->dev), &usb_main.psy) -
power_supply_register(&(dev->dev), &wireless_main.psy) -
power_supply_register(&(dev->dev), &battery_main.psy) -
/ -
// 初始化电池状态结构体 -
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(); -
/// -
//创建一个定时器,用于定时唤醒下面的内核线程更新电量 -
battery_kthread_hrtimer_init(); -
ktime = ktime_set(1, 0); // 3s, 10* 1000 ms -
// 高分辨率kernel定时器初始化 -
hrtimer_init(&battery_kthread_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); -
battery_kthread_timer.function = battery_kthread_hrtimer_func; -
// 定时器处理函数 -
battery_kthread_hrtimer_func() -
bat_thread_wakeup(); -
// 唤醒下面的 bat_thread_kthread() 线程 -
wake_up(&bat_thread_wq); -
// 重置定时器 -
hrtimer_start(&battery_kthread_timer, ktime, HRTIMER_MODE_REL) -
// -
// 【核心充电线程】 -
kthread_run(bat_thread_kthread, NULL, "bat_thread_kthread"); -
// 设置定时器超时时间 -
ktime_t ktime = ktime_set(3, 0); // 10s, 10* 1000 ms -
while (1) { -
// 这个是核心算法 -
BAT_thread(); -
/// -
// 0. 第一次执行时运行,获得开机显示电量,初始化电池算法 oam 参数 -
// 开机时就会运行,只会运行一次,对电池算法 oam 方案进行初始化, 并获得开机显示电量百分比 -
if(battery_meter_initilized == KAL_FALSE) -
{ -
// 进行的一系列的电池参数与温度对应关系的表格的初始化,并根据电池当前电压,hw ocv 取一个较合适值, -
// 取合适值对应容量,再与 RTC 保存容量比较,选择一个合适量,为开机电池容量,最后初始化 oam 算法参数 -
battery_meter_initial() -
} -
// 1. 判断是插入的是否充电器还是电脑 USB,看能不能进行充电 -
// 如果连接的 USB 线为 USB 充电线,或者电脑 USB 线,则打开 USB, -
// 这里会通过 BC1.1 来判断是电脑 USB 还是 USB 充电器,来决定充电电流 -
// 否则连接的不是充电线或者 USB 作为一个从设备使用,要断开 USB? -
mt_battery_charger_detect_check(); -
/// -
// 2. 通过具体的充电芯片来获得电池信息,充电信息, 获得电池电量百分比 -
// 通过 oam 算法,获得电量百分比 -
mt_battery_GetBatteryData(); -
// 3. 电池温度保护 -
// 电池温度检查,如果温度超过 60 度,关机重启 -
mt_battery_thermal_check(); -
/ -
// 4. 电池状态检查 -
// 对电池状态进行检查,如果有问题,则会调用 printk() 进行打印 -
mt_battery_notify_check(); -
// -
// 5. 调用具本的硬件相关函数进行充电,充电时会进行 CC/CV 之类的状态机切换就是在这里进行的 -
// 如果存在充电线,则调用具体充电芯片相关的函数进行充电 -
if( BMT_status.charger_exist == KAL_TRUE ) -
{ -
// 检查电池状态,设置到 BMT_status.bat_charging_state 中 -
mt_battery_CheckBatteryStatus(); -
// 充电策略,这里有两个文件: switch_charging.c 和 linear_charging.c -
// 他们的关系是,如果定义了任一外部充电 IC,则选择 switch_charging.c 的函数,否则就是 linear_charging.c 的函数 -
// 这里就是调用具体的芯片的充电相关函数进行充电 -
mt_battery_charging_algorithm(); -
void mt_battery_charging_algorithm() -
{ -
switch(BMT_status.bat_charging_state) -
{ -
case CHR_PRE : -
BAT_PreChargeModeAction(); -
break; -
case CHR_CC : -
BAT_ConstantCurrentModeAction(); -
/ -
// MTK 充电是充 9s 停 1s -
// Charging 9s and discharging 1s : start -
battery_charging_control(CHARGING_CMD_ENABLE,&charging_enable); -
break; -
case CHR_TOP_OFF : -
BAT_TopOffModeAction(); -
break; -
case CHR_BATFULL: -
BAT_BatteryFullAction(); -
break; -
case CHR_HOLD: -
BAT_BatteryHoldAction(); -
break; -
case CHR_ERROR: -
BAT_BatteryStatusFailAction(); -
break; -
} -
} -
} -
/// -
// 6. 更新电池显示状态 -
// 更新设置节点的内容: -
// /sys/class/power_supply/下的文件夹 -
// wireless_main -
// battery_main -
// ac_main -
// usb_main -
mt_battery_update_status(); -
// 睡眠等待唤醒 -
wait_event(bat_thread_wq, (bat_thread_timeout == KAL_TRUE)); -
// 每 10s 启动一次 -
hrtimer_start(&battery_kthread_timer, ktime, HRTIMER_MODE_REL); -
ktime = ktime_set(BAT_TASK_PERIOD, 0); // 10s, 10* 1000 ms -
} -
/ -
// 电池过充保护相关检测与初始化,他 2s 检测一次 -
charger_hv_detect_sw_workaround_init(); -
charger_hv_detect_thread = kthread_run(charger_hv_detect_sw_thread_handler, 0, "mtk charger_hv_detect_sw_workaround"); -
// 这个函数是周期来检查电池电压是否超出限制,即过充保护,超出了就不能充电了 -
charger_hv_detect_sw_thread_handler() -
do{ -
ktime = ktime_set(0, BAT_MS_TO_NS(2000)); -
if(chargin_hw_init_done) -
// 高压检测,应该是电池超过这个电压时,就不可以充电了 -
battery_charging_control(CHARGING_CMD_SET_HV_THRESHOLD,&hv_voltage); -
// 对应 PMIC charging_set_hv_threshold() -
wait_event_interruptible(charger_hv_detect_waiter, (charger_hv_detect_flag == KAL_TRUE)); -
// 如果检测到充电器,则检测下电池是否存在 检测电池是否存在,通过读取 PMIC 的 CHR_CON7 -
if ((upmu_is_chr_det() == KAL_TRUE)) -
{ -
// 检测电池是否存在 -
check_battery_exist(); -
} -
hrtimer_start(&charger_hv_detect_timer, ktime, HRTIMER_MODE_REL); -
}while (!kthread_should_stop()); -
// -
// battery notofy UI -
platform_device_register(&MT_batteryNotify_device) -
platform_driver_register(&mt_batteryNotify_driver) -
mt_batteryNotify_probe() -
ret_device_file = device_create_file(&(dev->dev), &dev_attr_BatteryNotify); -
ret_device_file = device_create_file(&(dev->dev), &dev_attr_BN_TestMode); -
battery_dir = proc_mkdir("mtk_battery_cmd", NULL); -
电池测量模块初始化: -
module_init(battery_meter_init); -
battery_meter_init(void) -
platform_device_register(&battery_meter_device); -
platform_driver_register(&battery_meter_driver); -
// 调用对应的 probe 函数 -
battery_meter_probe() -
// 测量模块接口设置【核心在于 bm_ctrl_cmd 函数】 -
battery_meter_ctrl = bm_ctrl_cmd; -
*/ -
module_init(battery_init); -
static int __init battery_init(void) -
{ -
int ret; -
ret = platform_device_register(&battery_device); -
struct platform_device battery_device = { -
.name = "battery", -
.id = -1, -
}; -
if (ret) { -
battery_xlog_printk(BAT_LOG_CRTI, "****[battery_driver] Unable to device register(%d)\n", ret); -
return ret; -
} -
ret = platform_driver_register(&battery_driver); -
static struct platform_driver battery_driver = { -
.probe = battery_probe, -
.remove = battery_remove, -
.shutdown = battery_shutdown, -
.driver = { -
.name = "battery", -
.pm = &battery_pm_ops -
}, -
}; -
if (ret) { -
battery_xlog_printk(BAT_LOG_CRTI, "****[battery_driver] Unable to register driver (%d)\n", ret); -
return ret; -
} -
// battery notofy UI -
ret = platform_device_register(&MT_batteryNotify_device); -
struct platform_device MT_batteryNotify_device = { -
.name = "mt-battery", -
.id = -1, -
}; -
if (ret) { -
battery_xlog_printk(BAT_LOG_CRTI, "****[mt_batteryNotify] Unable to device register(%d)\n", ret); -
return ret; -
} -
ret = platform_driver_register(&mt_batteryNotify_driver); -
static struct platform_driver mt_batteryNotify_driver = { -
.probe = mt_batteryNotify_probe, -
.driver = { -
.name = "mt-battery", -
}, -
}; -
if (ret) { -
battery_xlog_printk(BAT_LOG_CRTI, "****[mt_batteryNotify] Unable to register driver (%d)\n", ret); -
return ret; -
} -
battery_xlog_printk(BAT_LOG_CRTI, "****[battery_driver] Initialization : DONE !!\n"); -
return 0; -
} -
// -
// 第一个调用的 probe,充电相关函数初始化 -
/* 相关文件关系: -
Battery_common.c (s:\i841\mediatek\kernel\drivers\power) // 充电逻辑文件 -
Charging_hw_pmic.c (s:\i841\mediatek\platform\mt6582\kernel\drivers\power) // 具体的充电芯片,相关电池参数检测 -
Linear_charging.c (s:\i841\mediatek\kernel\drivers\power) // 充电状态控制,内部 PMIC -
Switch_charging.c (s:\i841\mediatek\kernel\drivers\power) // 充电状态控制,外部 Charge IC -
*/ -
static int battery_probe//(struct platform_device *dev) -
{ -
struct class_device *class_dev = NULL; -
int ret=0; -
battery_xlog_printk(BAT_LOG_CRTI, "******** battery driver probe!! ********\n" ); -
/* Integrate with NVRAM */ -
ret = alloc_chrdev_region(&adc_cali_devno, 0, 1, ADC_CALI_DEVNAME); // #define ADC_CALI_DEVNAME "MT_pmic_adc_cali" -
if (ret) -
battery_xlog_printk(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; -
static struct file_operations adc_cali_fops = { -
.owner = THIS_MODULE, -
.unlocked_ioctl = adc_cali_ioctl, -
.open = adc_cali_open, -
.release = adc_cali_release, -
}; -
ret = cdev_add(adc_cali_cdev, adc_cali_devno, 1); -
if(ret) -
battery_xlog_printk(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_xlog_printk(BAT_LOG_CRTI, "[BAT_probe] adc_cali prepare : done !!\n "); -
/* 与特定硬件的操作函数关联 */ -
get_charging_control(); -
static void get_charging_control(void) -
{ -
/* 这是一个函数指针,指向了硬件驱动对应的接口函数,这里指向的是 pmic 为例,后面调用 battery_charging_control(xxx) -
即是调用 chr_control_interface(xxx) -
typedef kal_int32 (*CHARGING_CONTROL)(CHARGING_CTRL_CMD cmd, void *data);*/ -
battery_charging_control = chr_control_interface; -
// This function is called to set the charger hw -
kal_int32 chr_control_interface//(CHARGING_CTRL_CMD cmd, void *data) -
{ -
kal_int32 status; -
if(cmd < CHARGING_CMD_NUMBER) -
status = charging_func[cmd](data); -
/* 这是在特定充电芯片中实现的,如 pmic 的 */ -
// static kal_uint32 (*charging_func[CHARGING_CMD_NUMBER])(void *data)= -
// { -
// charging_hw_init -
// ,charging_dump_register -
// ,charging_enable -
// ,charging_set_cv_voltage -
// ,charging_get_current -
// ,charging_set_current -
// ,charging_set_input_current // not support, empty function -
// ,charging_get_charging_status // not support, empty function -
// ,charging_reset_watch_dog_timer -
// ,charging_set_hv_threshold -
// ,charging_get_hv_status -
// ,charging_get_battery_status -
// ,charging_get_charger_det_status -
// ,charging_get_charger_type -
// ,charging_get_is_pcm_timer_trigger -
// ,charging_set_platform_reset -
// ,charging_get_platfrom_boot_mode -
// ,charging_set_power_off -
// }; -
else -
return STATUS_UNSUPPORTED; -
return status; -
} -
} -
/* 获得启动模式 */ -
battery_charging_control(CHARGING_CMD_GET_PLATFORM_BOOT_MODE, &g_platform_boot_mode); -
// 对应 pmic 的 charging_get_platfrom_boot_mode() -
static kal_uint32 charging_get_platfrom_boot_mode(void *data) -
{ -
kal_uint32 status = STATUS_OK; -
*(kal_uint32*)(data) = get_boot_mode(); -
BOOTMODE get_boot_mode(void) -
{ -
return g_boot_mode; -
} -
battery_xlog_printk(BAT_LOG_CRTI, "get_boot_mode=%d\n", get_boot_mode()); -
return status; -
} -
battery_xlog_printk(BAT_LOG_CRTI, "[BAT_probe] g_platform_boot_mode = %d\n ", g_platform_boot_mode); -
wake_lock_init(&battery_suspend_lock, WAKE_LOCK_SUSPEND, "battery suspend wakelock"); -
/* Integrate with Android Battery Service -
一般移动设备的供电可来自外部即 AC 与 usb,内部电池供电 battery,所以需通过 power_supply_register 函数在 -
/sys/class/power_supply 下分别注册 ac usb battery,注册完成可发现在设备目录 /sys/class/power_supply 下分别 -
出现 ac usb battery 三个文件夹 */ -
ret = power_supply_register(&(dev->dev), &ac_main.psy); -
/* 相关的核心结构体 -
struct power_supply { -
struct listnode list; -
char name[256]; -
char type[32]; -
bool online; -
bool valid; -
char cap_path[PATH_MAX]; -
};*/ -
if (ret) -
{ -
battery_xlog_printk(BAT_LOG_CRTI, "[BAT_probe] power_supply_register AC Fail !!\n"); -
return ret; -
} -
battery_xlog_printk(BAT_LOG_CRTI, "[BAT_probe] power_supply_register AC Success !!\n"); -
ret = power_supply_register(&(dev->dev), &usb_main.psy); -
if (ret) -
{ -
battery_xlog_printk(BAT_LOG_CRTI, "[BAT_probe] power_supply_register USB Fail !!\n"); -
return ret; -
} -
battery_xlog_printk(BAT_LOG_CRTI, "[BAT_probe] power_supply_register USB Success !!\n"); -
ret = power_supply_register(&(dev->dev), &wireless_main.psy); -
if (ret) -
{ -
battery_xlog_printk(BAT_LOG_CRTI, "[BAT_probe] power_supply_register WIRELESS Fail !!\n"); -
return ret; -
} -
battery_xlog_printk(BAT_LOG_CRTI, "[BAT_probe] power_supply_register WIRELESS Success !!\n"); -
ret = power_supply_register(&(dev->dev), &battery_main.psy); -
if (ret) -
{ -
battery_xlog_printk(BAT_LOG_CRTI, "[BAT_probe] power_supply_register Battery Fail !!\n"); -
return ret; -
} -
battery_xlog_printk(BAT_LOG_CRTI, "[BAT_probe] power_supply_register Battery Success !!\n"); -
#if !defined(CONFIG_POWER_EXT) -
/* 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); -
} -
//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(); -
//battery kernel thread for 10s check and charger in/out event -
/* Replace GPT timer by hrtime -
创建一个定时器,用于定时唤醒下面的内核线程更新电量 */ -
battery_kthread_hrtimer_init(); -
void battery_kthread_hrtimer_init(void) -
{ -
ktime_t ktime; -
ktime = ktime_set(1, 0); // 3s, 10* 1000 ms -
// 高分辨率kernel定时器初始化 -
hrtimer_init(&battery_kthread_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); -
battery_kthread_timer.function = battery_kthread_hrtimer_func; -
enum hrtimer_restart battery_kthread_hrtimer_func(struct hrtimer *timer) -
{ -
bat_thread_wakeup(); -
void bat_thread_wakeup(void) -
{ -
battery_xlog_printk(BAT_LOG_CRTI, "******** battery : bat_thread_wakeup ********\n" ); -
bat_thread_timeout = KAL_TRUE; -
bat_meter_timeout = KAL_TRUE; -
// 唤醒下面的 bat_thread_kthread() 线程 -
wake_up(&bat_thread_wq); -
} -
return HRTIMER_NORESTART; -
} -
// 重置定时器 -
hrtimer_start(&battery_kthread_timer, ktime, HRTIMER_MODE_REL); -
battery_xlog_printk(BAT_LOG_CRTI, "battery_kthread_hrtimer_init : done\n" ); -
} -
kthread_run(bat_thread_kthread, NULL, "bat_thread_kthread"); -
/// -
Internal API -
int bat_thread_kthread(void *x) -
{ -
// 设置定时器超时时间 -
ktime_t ktime = ktime_set(3, 0); // 10s, 10* 1000 ms -
/* Run on a process content */ -
while (1) { -
mutex_lock(&bat_mutex); -
if((chargin_hw_init_done == KAL_TRUE) && (battery_suspended == KAL_FALSE)) -
/ -
/ -
/* 这个是核心算法 */ -
BAT_thread(); -
void BAT_thread(void) -
{ -
static kal_bool battery_meter_initilized = KAL_FALSE; -
_g_bat_sleep_total_time = 0; -
// 0. 第一次执行时运行,获得开机显示电量,初始化电池算法 oam 参数 -
/* 开机时就会运行,只会运行一次,对电池算法 oam 方案进行初始化, 并获得开机显示电量百分比 */ -
if(battery_meter_initilized == KAL_FALSE) -
{ -
/* 进行的一系列的电池参数与温度对应关系的表格的初始化,并根据电池当前电压,hw ocv 取一个较合适值, -
取合适值对应容量,再与 rtc 容量比较,选择一个合适量,为开机电池容量,最后初始化 oam 算法参数 */ -
battery_meter_initial(); //move from battery_probe() to decrease booting time -
kal_int32 battery_meter_initial(void) -
{ -
#if defined(CONFIG_POWER_EXT) -
return 0; -
#else -
/* 多电池支持 */ -
#ifdef MTK_MULTI_BAT_PROFILE_SUPPORT -
fgauge_get_profile_id(); -
#endif -
/* 针对 AUXADC SW_FG HW_FG 三种不同的电池算法方案,分别初始化,82平台使用的 SW_FG */ -
#if defined(SOC_BY_AUXADC) -
g_auxadc_solution = 1; -
table_init(); -
bm_print(BM_LOG_CRTI, "[battery_meter_initial] SOC_BY_AUXADC done\n"); -
#endif -
#if defined(SOC_BY_HW_FG) -
fgauge_initialization(); -
fgauge_algo_run_init(); -
bm_print(BM_LOG_CRTI, "[battery_meter_initial] SOC_BY_HW_FG done\n"); -
#endif -
#if defined(SOC_BY_SW_FG) -
g_auxadc_solution = 1; -
/* 温度-电池容量,温度-电池内阻,温度-NTC阻值表格等初始化,并获得了当前电池温度及所用掉的容量值 */ -
table_init(); -
void table_init(void) -
{ -
BATTERY_PROFILE_STRUC_P profile_p; -
R_PROFILE_STRUC_P profile_p_r_table; -
/* 获得当前电池温度*/ -
int temperature = force_get_tbat(); -
/* 通过获得当前 NTC 电压,查表并进行线性插值法,得到当前的温度值 */ -
int force_get_tbat(void) -
{ -
#if defined(CONFIG_POWER_EXT) || defined(FIXED_TBAT_25) -
bm_print(BM_LOG_CRTI, "[force_get_tbat] fixed TBAT=25 t\n"); -
return 25; -
#else -
int bat_temperature_volt=0; -
int bat_temperature_val=0; -
int fg_r_value=0; -
kal_int32 fg_current_temp=0; -
kal_bool fg_current_state=KAL_FALSE; -
int bat_temperature_volt_temp=0; -
int ret=0; -
/* Get V_BAT_Temperature */ -
bat_temperature_volt = 2; -
/* 对应 PMIC 的硬件接口函数,这个对应的函数是在下面 battery_meter_init 模块中设置的 -
获得电池 NTC 对应的电压 */ -
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_TEMP, &bat_temperature_volt); -
static kal_int32 read_adc_v_bat_temp(void *data) -
{ -
#if defined(CONFIG_POWER_EXT) -
*(kal_int32*)(data) = 0; -
#else -
#if defined(MTK_PCB_TBAT_FEATURE) -
int ret = 0, data[4], i, ret_value = 0, ret_temp = 0; -
int Channel=1; -
if( IMM_IsAdcInitReady() == 0 ) -
{ -
bm_print(BM_LOG_CRTI, "[get_tbat_volt] AUXADC is not ready"); -
return 0; -
} -
i = times; -
while (i--) -
{ -
ret_value = IMM_GetOneChannelValue(Channel, data, &ret_temp); -
ret += ret_temp; -
bm_print(BM_LOG_FULL, "[get_tbat_volt] ret_temp=%d\n",ret_temp); -
} -
ret = ret*1500/4096 ; -
ret = ret/times; -
bm_print(BM_LOG_CRTI, "[get_tbat_volt] Battery output mV = %d\n",ret); -
*(kal_int32*)(data) = ret; -
#else -
bm_print(BM_LOG_FULL, "[read_adc_v_charger] return PMIC_IMM_GetOneChannelValue(4,times,1);\n"); -
/* 读 PMIC 对应的 ADC 的值,并将其转化为对应的电压值,这里即读取 BATON 引脚电压 */ -
*(kal_int32*)(data) = PMIC_IMM_GetOneChannelValue(VBATTEMP_CHANNEL_NUMBER,*(kal_int32*)(data),1); -
//============================================================================== -
// PMIC-AUXADC -
//============================================================================== -
int PMIC_IMM_GetOneChannelValue(int dwChannel, int deCount, int trimd) -
{ -
kal_int32 ret_data; -
kal_int32 count=0; -
kal_int32 u4Sample_times = 0; -
kal_int32 u4channel=0; -
kal_int32 adc_result_temp=0; -
kal_int32 r_val_temp=0; -
kal_int32 adc_result=0; -
kal_int32 ret=0; -
kal_int32 adc_reg_val=0; -
/* -
0 : BATON2 ** -
1 : CH6 -
2 : THR SENSE2 ** -
3 : THR SENSE1 -
4 : VCDT -
5 : BATON1 // 其实对应的就是硬件 PMIC ADC3 -
6 : ISENSE -
7 : BATSNS -
8 : ACCDET -
9-16 : audio -
*/ -
//do not suppport BATON2 and THR SENSE2 for sw workaround -
if (dwChannel==0 || dwChannel==2) -
return 0; -
wake_lock(&pmicAuxadc_irq_lock); -
/* 采样通道号数,读取对应的 PMIC 寄存器的 ADC 的值 */ -
do -
{ -
mutex_lock(&pmic_adc_mutex); -
/* 硬件上,ADC 通过一个 mux 数据选择器对各路模拟信号进行切换,这里检查哪里通知有数据了 */ -
PMIC_IMM_PollingAuxadcChannel(); -
void PMIC_IMM_PollingAuxadcChannel(void) -
{ -
kal_uint32 ret=0; -
//xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[PMIC_IMM_PollingAuxadcChannel] before:%d ",upmu_get_rg_adc_deci_gdly()); -
if (upmu_get_rg_adc_deci_gdly()==1) -
{ -
while(upmu_get_rg_adc_deci_gdly()==1) -
{ -
unsigned long flags; -
spin_lock_irqsave(&pmic_adc_lock, flags); -
if (pmic_is_auxadc_busy()==0) -
{ -
//upmu_set_rg_adc_deci_gdly(0); -
ret=pmic_config_interface_nolock(AUXADC_CON19,0,PMIC_RG_ADC_DECI_GDLY_MASK,PMIC_RG_ADC_DECI_GDLY_SHIFT); -
} -
spin_unlock_irqrestore(&pmic_adc_lock, flags); -
} -
} -
//xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[PMIC_IMM_PollingAuxadcChannel] after:%d ",upmu_get_rg_adc_deci_gdly()); -
} -
/* adc */ -
if (dwChannel<9) -
{ -
upmu_set_rg_vbuf_en(1); -
//set 0 -
ret=pmic_read_interface(AUXADC_CON22,&adc_reg_val,PMIC_RG_AP_RQST_LIST_MASK,PMIC_RG_AP_RQST_LIST_SHIFT); -
adc_reg_val = adc_reg_val & (~(1<<dwChannel)); -
ret=pmic_config_interface(AUXADC_CON22,adc_reg_val,PMIC_RG_AP_RQST_LIST_MASK,PMIC_RG_AP_RQST_LIST_SHIFT); -
//set 1 -
ret=pmic_read_interface(AUXADC_CON22,&adc_reg_val,PMIC_RG_AP_RQST_LIST_MASK,PMIC_RG_AP_RQST_LIST_SHIFT); -
adc_reg_val = adc_reg_val | (1<<dwChannel); -
ret=pmic_config_interface(AUXADC_CON22,adc_reg_val,PMIC_RG_AP_RQST_LIST_MASK,PMIC_RG_AP_RQST_LIST_SHIFT); -
} -
/* audio 相关 */ -
else if(dwChannel>=9 && dwChannel<=16) -
{ -
ret=pmic_read_interface(AUXADC_CON23,&adc_reg_val,PMIC_RG_AP_RQST_LIST_RSV_MASK,PMIC_RG_AP_RQST_LIST_RSV_SHIFT); -
adc_reg_val = adc_reg_val & (~(1<<(dwChannel-9))); -
ret=pmic_config_interface(AUXADC_CON23,adc_reg_val,PMIC_RG_AP_RQST_LIST_RSV_MASK,PMIC_RG_AP_RQST_LIST_RSV_SHIFT); -
//set 1 -
ret=pmic_read_interface(AUXADC_CON23,&adc_reg_val,PMIC_RG_AP_RQST_LIST_RSV_MASK,PMIC_RG_AP_RQST_LIST_RSV_SHIFT); -
adc_reg_val = adc_reg_val | (1<<(dwChannel-9)); -
ret=pmic_config_interface(AUXADC_CON23,adc_reg_val,PMIC_RG_AP_RQST_LIST_RSV_MASK,PMIC_RG_AP_RQST_LIST_RSV_SHIFT); -
} -
mutex_unlock(&pmic_adc_mutex); -
//Duo to HW limitation -
if(dwChannel!=8) -
msleep(1); -
count=0; -
ret_data=0; -
/* 根据不同通道选择,来读取对应的 PMIC 寄存器的值 */ -
switch(dwChannel){ -
case 0: -
while( upmu_get_rg_adc_rdy_baton2() != 1 ) -
{ -
msleep(1); -
if( (count++) > count_time_out) -
{ -
xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", dwChannel); -
break; -
} -
} -
ret_data = upmu_get_rg_adc_out_baton2(); -
break; -
case 1: -
while( upmu_get_rg_adc_rdy_ch6() != 1 ) -
{ -
msleep(1); -
if( (count++) > count_time_out) -
{ -
xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", dwChannel); -
break; -
} -
} -
ret_data = upmu_get_rg_adc_out_ch6(); -
xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[upmu_get_rg_adc_out_ch6] 0x%x\n", ret_data); -
break; -
case 2: -
while( upmu_get_rg_adc_rdy_thr_sense2() != 1 ) -
{ -
msleep(1); -
if( (count++) > count_time_out) -
{ -
xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", dwChannel); -
break; -
} -
} -
ret_data = upmu_get_rg_adc_out_thr_sense2(); -
break; -
case 3: -
while( upmu_get_rg_adc_rdy_thr_sense1() != 1 ) -
{ -
msleep(1); -
if( (count++) > count_time_out) -
{ -
xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", dwChannel); -
break; -
} -
} -
ret_data = upmu_get_rg_adc_out_thr_sense1(); -
break; -
case 4: -
while( upmu_get_rg_adc_rdy_vcdt() != 1 ) -
{ -
msleep(1); -
if( (count++) > count_time_out) -
{ -
xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", dwChannel); -
break; -
} -
} -
ret_data = upmu_get_rg_adc_out_vcdt(); -
break; -
/* 读取 PMIC 的 VBATON 引用的电压值*/ -
case 5: -
while( upmu_get_rg_adc_rdy_baton1() != 1 ) -
{ -
msleep(1); -
if( (count++) > count_time_out) -
{ -
xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", dwChannel); -
break; -
} -
} -
ret_data = upmu_get_rg_adc_out_baton1(); -
kal_uint32 upmu_get_rg_adc_rdy_baton1(void) -
{ -
kal_uint32 ret=0; -
kal_uint32 val=0; -
pmic_lock(); -
ret=pmic_read_interface( (kal_uint32)(AUXADC_ADC3), -
(&val), -
(kal_uint32)(PMIC_RG_ADC_RDY_BATON1_MASK), -
(kal_uint32)(PMIC_RG_ADC_RDY_BATON1_SHIFT) -
); -
pmic_unlock(); -
return val; -
} -
break; -
case 6: -
while( upmu_get_rg_adc_rdy_isense() != 1 ) -
{ -
msleep(1); -
if( (count++) > count_time_out) -
{ -
xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", dwChannel); -
break; -
} -
} -
ret_data = upmu_get_rg_adc_out_isense(); -
break; -
case 7: -
while( upmu_get_rg_adc_rdy_batsns() != 1 ) -
{ -
msleep(1); -
if( (count++) > count_time_out) -
{ -
xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", dwChannel); -
break; -
} -
} -
ret_data = upmu_get_rg_adc_out_batsns(); -
break; -
case 8: -
while( upmu_get_rg_adc_rdy_ch5() != 1 ); -
ret_data = upmu_get_rg_adc_out_ch5(); -
break; -
case 9: -
case 10: -
case 11: -
case 12: -
case 13: -
case 14: -
case 15: -
case 16: -
while( upmu_get_rg_adc_rdy_int() != 1 ) -
{ -
msleep(1); -
if( (count++) > count_time_out) -
{ -
xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", dwChannel); -
break; -
} -
} -
ret_data = upmu_get_rg_adc_out_int(); -
break; -
default: -
xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[AUXADC] Invalid channel value(%d,%d)\n", dwChannel, trimd); -
wake_unlock(&pmicAuxadc_irq_lock); -
return -1; -
break; -
} -
u4channel += ret_data; -
u4Sample_times++; -
if (Enable_BATDRV_LOG == 2) -
{ -
//debug -
xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[AUXADC] u4channel[%d]=%d.\n", -
dwChannel, ret_data); -
} -
}while (u4Sample_times < deCount); -
/* Value averaging -
adc 采样值取平均值 */ -
adc_result_temp = u4channel / deCount; -
/* ADC 分辨率: 即 ADC 数据每加 1 所对应的电压变化,计算公式为 【测量电压范围/(2^AD位数-1)】*/ -
switch(dwChannel){ -
case 0: -
r_val_temp = 1; -
adc_result = (adc_result_temp*r_val_temp*VOLTAGE_FULL_RANGE)/ADC_PRECISE; -
break; -
case 1: -
r_val_temp = 1; -
adc_result = (adc_result_temp*r_val_temp*VOLTAGE_FULL_RANGE)/ADC_PRECISE; -
break; -
case 2: -
r_val_temp = 1; -
adc_result = (adc_result_temp*r_val_temp*VOLTAGE_FULL_RANGE)/ADC_PRECISE; -
break; -
case 3: -
r_val_temp = 1; -
adc_result = (adc_result_temp*r_val_temp*VOLTAGE_FULL_RANGE)/ADC_PRECISE; -
break; -
case 4: -
r_val_temp = 1; -
adc_result = (adc_result_temp*r_val_temp*VOLTAGE_FULL_RANGE)/ADC_PRECISE; -
break; -
/* ADC 分辨率: 即 ADC 数据每加 1 所对应的电压变化,计算公式为 -
0-正数表示: 【测量电压范围/(2^AD位数)】 -
负数-正数表示: 【测量电压范围/(2^AD位数-1)】 -
获得 BATON 电压值 -
#define VOLTAGE_FULL_RANGE 1800 // 测量的电压范围 -
#define ADC_PRECISE 32768 // 15 bits 2^15 = 32768 -
*/ -
case 5: -
r_val_temp = 1; -
/* 这里得到将数字化数值转换为对应的模拟电压值 */ -
adc_result = (adc_result_temp*r_val_temp*VOLTAGE_FULL_RANGE)/ADC_PRECISE; -
break; -
case 6: -
r_val_temp = 4; // 电阻分压比,因为测量 adc 量程不够,要采用电阻分压 -
adc_result = (adc_result_temp*r_val_temp*VOLTAGE_FULL_RANGE)/ADC_PRECISE; -
break; -
case 7: -
r_val_temp = 4; // 电阻分压比,因为测量 adc 量程不够,要采用电阻分压 -
adc_result = (adc_result_temp*r_val_temp*VOLTAGE_FULL_RANGE)/ADC_PRECISE; -
break; -
case 8: -
r_val_temp = 1; -
adc_result = (adc_result_temp*r_val_temp*VOLTAGE_FULL_RANGE)/ADC_PRECISE; -
break; -
case 9: -
case 10: -
case 11: -
case 12: -
case 13: -
case 14: -
case 15: -
case 16: -
adc_result = adc_result_temp; -
break; -
default: -
xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[AUXADC] Invalid channel value(%d,%d)\n", dwChannel, trimd); -
wake_unlock(&pmicAuxadc_irq_lock); -
return -1; -
break; -
} -
if (Enable_BATDRV_LOG == 2) -
{ -
//debug -
xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[AUXADC] adc_result_temp=%d, adc_result=%d, r_val_temp=%d.\n", -
adc_result_temp, adc_result, r_val_temp); -
} -
wake_unlock(&pmicAuxadc_irq_lock); -
return adc_result; -
} -
#endif -
#endif -
return STATUS_OK; -
} -
/* 如果获得的 PMIC 的 BATON 引脚电压值不为 0 */ -
if(bat_temperature_volt != 0) -
{ -
#if defined(SOC_BY_HW_FG) -
/* 获得配置的放电电阻值的大小 */ -
fg_r_value = get_r_fg_value(); -
int get_r_fg_value(void) -
{ -
return (R_FG_VALUE+CUST_R_FG_OFFSET); -
} -
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CURRENT, &fg_current_temp); -
static kal_int32 fgauge_read_current(void *data) -
{ -
return STATUS_OK; -
} -
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CURRENT_SIGN, &fg_current_state); -
static kal_int32 fgauge_read_current_sign(void *data) -
{ -
return STATUS_OK; -
} -
fg_current_temp = fg_current_temp/10; -
if(fg_current_state==KAL_TRUE) -
{ -
bat_temperature_volt_temp = bat_temperature_volt; -
bat_temperature_volt = bat_temperature_volt - ((fg_current_temp*fg_r_value)/1000); -
} -
else -
{ -
bat_temperature_volt_temp = bat_temperature_volt; -
// 这里对 NTC 电压进行补偿: NTC 实际温度对应电压 = 测量电压 + 负载电压*负载电阻 // 【这里的 1000 是将小数整数化】 -
bat_temperature_volt = bat_temperature_volt + ((fg_current_temp*fg_r_value)/1000); -
} -
#endif -
/// -
/* 将 NTC 的电压通过查表获得对应温度值 */ -
bat_temperature_val = BattVoltToTemp(bat_temperature_volt); -
int BattVoltToTemp(int dwVolt) -
{ -
kal_int64 TRes_temp; -
kal_int64 TRes; -
int sBaTTMP = -100; -
// TRes_temp = ((kal_int64)RBAT_PULL_UP_R*(kal_int64)dwVolt) / (RBAT_PULL_UP_VOLT-dwVolt); -
//TRes = (TRes_temp * (kal_int64)RBAT_PULL_DOWN_R)/((kal_int64)RBAT_PULL_DOWN_R - TRes_temp); -
/* 电路原理如下: -
Vu Ru:上拉电阻值 -
--- Rd: 下拉电阻值 -
| Rntc: NTC 温度电阻 阻值 -
||| Ru Vu: 上拉电压值 -
| Gnd: 地 -
---------- -----Vntc Vntc: NTC 电压 -
| | -
Rntc ||| ||| Rd -
| | -
---------- Rntc = (Ru*Rd*Vntc) / (Vru * Rd - Vntc * Ru) -
| -
----- -
--- -
- -
Gnd -
*/ -
/* TRes_temp = 上拉电阻值 * NTC电压 */ -
TRes_temp = (RBAT_PULL_UP_R*(kal_int64)dwVolt); -
/* 上拉电阻分压 = 上拉电压 - NTC分压 = RBAT_PULL_UP_VOLT-dwVolt -
do_div(): 做除法 -
(上拉电阻值 * NTC电压)/上拉电阻分压 = (上拉电阻值/上拉电压分压)*NTC电压 */ -
do_div(TRes_temp, (RBAT_PULL_UP_VOLT-dwVolt)); -
/* (上拉电阻值/上拉电压分压)*NTC电压*下拉电阻值 */ -
TRes = (TRes_temp * RBAT_PULL_DOWN_R); -
/* (上拉电阻值/上拉电压分压)*NTC电压*下拉电阻值 / (下拉电阻值 - (上拉电阻值/上拉电压分压)*NTC电压)*/ -
do_div(TRes, abs(RBAT_PULL_DOWN_R - TRes_temp)); -
/* convert register to temperature -
将得到的 NTC 阻值通过表格换算成温度 */ -
sBaTTMP = BattThermistorConverTemp((int)TRes); -
int BattThermistorConverTemp//(int Res) -
{ -
int i=0; -
int RES1=0,RES2=0; -
int TBatt_Value=-200,TMP1=0,TMP2=0; -
/* 如果大于最低温度阻值,返回 -20 */ -
if(Res>=Batt_Temperature_Table[0].TemperatureR) /* Cust_battery_meter_table.h (s:\i841\mediatek\custom\mt6582\kernel\battery\battery) */ -
{ -
TBatt_Value = -20; -
} -
/* 如果大于最高温度阻值,返回 60 */ -
else if(Res<=Batt_Temperature_Table[16].TemperatureR) -
{ -
TBatt_Value = 60; -
} -
/* 其他温度 */ -
else -
{ -
RES1=Batt_Temperature_Table[0].TemperatureR; -
TMP1=Batt_Temperature_Table[0].BatteryTemp; -
/* 遍历 NTC 阻值与温度对应表,获得当前阻值所对应的表项 */ -
for(i=0;i<=16;i++) -
{ -
if(Res>=Batt_Temperature_Table[i].TemperatureR) -
{ -
RES2=Batt_Temperature_Table[i].TemperatureR; -
TMP2=Batt_Temperature_Table[i].BatteryTemp; -
break; -
} -
else -
{ -
RES1=Batt_Temperature_Table[i].TemperatureR; -
TMP1=Batt_Temperature_Table[i].BatteryTemp; -
} -
} -
/* Liner Interpolation Method: 线性插值法,方法详见 Battery_Charging Introduction for Customer.pdf -
核心就是一条直接函数,已知两个点的 (X0,Y0) (X1,Y1),并知道第三个点的 X,就对应的 Y -
计算公式为: -
Y = [(X-X0)*Y1 + (X1-X)*Y0] / (X1-X0) -
*/ -
TBatt_Value = (((Res-RES2)*TMP1)+((RES1-Res)*TMP2))/(RES1-RES2); -
} -
return TBatt_Value; -
} -
return sBaTTMP; -
} -
} -
bm_print(BM_LOG_CRTI, "[force_get_tbat] %d,%d,%d,%d,%d,%d\n", -
bat_temperature_volt_temp, bat_temperature_volt, fg_current_state, fg_current_temp, fg_r_value, bat_temperature_val); -
return bat_temperature_val; -
#endif -
} -
// Re-constructure r-table profile according to current temperature -
/* 获得温度-电池内阻表 */ -
profile_p_r_table = fgauge_get_profile_r_table(TEMPERATURE_T); -
R_PROFILE_STRUC_P fgauge_get_profile_r_table(kal_uint32 temperature) -
{ -
switch (temperature) -
{ -
case TEMPERATURE_T0: -
return &r_profile_t0[0]; -
break; -
case TEMPERATURE_T1: -
return &r_profile_t1[0]; -
break; -
case TEMPERATURE_T2: -
return &r_profile_t2[0]; -
break; -
case TEMPERATURE_T3: -
return &r_profile_t3[0]; -
break; -
case TEMPERATURE_T: -
return &r_profile_temperature[0]; -
break; -
default: -
return NULL; -
break; -
} -
} -
if (profile_p_r_table == NULL) -
{ -
bm_print(BM_LOG_CRTI, "[FGADC] fgauge_get_profile_r_table : create table fail !\r\n"); -
} -
/* 获得当前温度使用的 温度-电池内阻 表格*/ -
fgauge_construct_r_table_profile(temperature, profile_p_r_table); -
void fgauge_construct_r_table_profile(kal_int32 temperature, R_PROFILE_STRUC_P temp_profile_p) -
{ -
R_PROFILE_STRUC_P low_profile_p, high_profile_p; -
kal_int32 low_temperature, high_temperature; -
int i, saddles; -
kal_int32 temp_v_1 = 0, temp_v_2 = 0; -
kal_int32 temp_r_1 = 0, temp_r_2 = 0; -
/* 这里跟 NTC 类似,获得在 温度上下限时的电池内阻表 */ -
if (temperature <= TEMPERATURE_T1) -
{ -
low_profile_p = fgauge_get_profile_r_table(TEMPERATURE_T0); -
high_profile_p = fgauge_get_profile_r_table(TEMPERATURE_T1); -
low_temperature = (-10); -
high_temperature = TEMPERATURE_T1; -
if(temperature < low_temperature) -
{ -
temperature = low_temperature; -
} -
} -
else if (temperature <= TEMPERATURE_T2) -
{ -
low_profile_p = fgauge_get_profile_r_table(TEMPERATURE_T1); -
high_profile_p = fgauge_get_profile_r_table(TEMPERATURE_T2); -
low_temperature = TEMPERATURE_T1; -
high_temperature = TEMPERATURE_T2; -
if(temperature < low_temperature) -
{ -
temperature = low_temperature; -
} -
} -
else -
{ -
low_profile_p = fgauge_get_profile_r_table(TEMPERATURE_T2); // 温度下限温度-电池内阻表 -
high_profile_p = fgauge_get_profile_r_table(TEMPERATURE_T3); // 温度上限温度-电池内阻表 -
low_temperature = TEMPERATURE_T2; // 温度下限 -
high_temperature = TEMPERATURE_T3; // 温度上限 -
/* 防溢出温度区间 */ -
if(temperature > high_temperature) -
{ -
temperature = high_temperature; -
} -
} -
/* 获得 温度-电池内阻表 的表格项数 */ -
saddles = fgauge_get_saddles_r_table(); -
int fgauge_get_saddles_r_table(void) -
{ -
return sizeof(r_profile_t2) / sizeof(R_PROFILE_STRUC); -
} -
/* Interpolation for V_BAT -
插值得到当前温度对应的电池电压 V_BAT */ -
for (i = 0; i < saddles; i++) -
{ -
/* 如果表格中温度上限电压 > 温度下限时电压 */ -
if( ((high_profile_p + i)->voltage) > ((low_profile_p + i)->voltage) ) -
{ -
/* 温度上限时电压 */ -
temp_v_1 = (high_profile_p + i)->voltage; -
/* 温度下限时电压 */ -
temp_v_2 = (low_profile_p + i)->voltage; -
/* 插值得到此时温度对应的电压值 */ -
(temp_profile_p + i)->voltage = temp_v_2 + -
( -
( -
(temperature - low_temperature) * -
(temp_v_1 - temp_v_2) -
) / -
(high_temperature - low_temperature) -
); -
} -
/* 如果表格中温度上限电压 <= 温度下限时电压 */ -
else -
{ -
temp_v_1 = (low_profile_p + i)->voltage; -
temp_v_2 = (high_profile_p + i)->voltage; -
(temp_profile_p + i)->voltage = temp_v_2 + -
( -
( -
(high_temperature - temperature) * -
(temp_v_1 - temp_v_2) -
) / -
(high_temperature - low_temperature) -
); -
} -
#if 0 -
//(temp_profile_p + i)->resistance = (high_profile_p + i)->resistance; -
(temp_profile_p + i)->voltage = temp_v_2 + -
( -
( -
(temperature - low_temperature) * -
(temp_v_1 - temp_v_2) -
) / -
(high_temperature - low_temperature) -
); -
#endif -
} -
/* Interpolation for R_BAT -
插值得到当前温度对应的电池内阻 R_BAT */ -
for (i = 0; i < saddles; i++) -
{ -
if( ((high_profile_p + i)->resistance) > ((low_profile_p + i)->resistance) ) -
{ -
/* 温度上限时电池内阻 */ -
temp_r_1 = (high_profile_p + i)->resistance; -
/* 温度下限时电池内阻 */ -
temp_r_2 = (low_profile_p + i)->resistance; -
/* 插值得到此时温度对应的电池内阻值 */ -
(temp_profile_p + i)->resistance = temp_r_2 + -
( -
( -
(temperature - low_temperature) * -
(temp_r_1 - temp_r_2) -
) / -
(high_temperature - low_temperature) -
); -
} -
else -
{ -
temp_r_1 = (low_profile_p + i)->resistance; -
temp_r_2 = (high_profile_p + i)->resistance; -
(temp_profile_p + i)->resistance = temp_r_2 + -
( -
( -
(high_temperature - temperature) * -
(temp_r_1 - temp_r_2) -
) / -
(high_temperature - low_temperature) -
); -
} -
#if 0 -
//(temp_profile_p + i)->voltage = (high_profile_p + i)->voltage; -
(temp_profile_p + i)->resistance = temp_r_2 + -
( -
( -
(temperature - low_temperature) * -
(temp_r_1 - temp_r_2) -
) / -
(high_temperature - low_temperature) -
); -
#endif -
} -
// Dumpt new r-table profile -
for (i = 0; i < saddles ; i++) -
{ -
bm_print(BM_LOG_CRTI, "<Rbat,VBAT> at %d = <%d,%d>\r\n", -
temperature, (temp_profile_p+i)->resistance, (temp_profile_p+i)->voltage); -
} -
} -
// Re-constructure battery profile according to current temperature -
/* 获得当前温度对应的 温度-电池容量表格 */ -
profile_p = fgauge_get_profile(TEMPERATURE_T); -
BATTERY_PROFILE_STRUC_P fgauge_get_profile(kal_uint32 temperature) -
{ -
switch (temperature) -
{ -
case TEMPERATURE_T0: -
return &battery_profile_t0[0]; -
break; -
case TEMPERATURE_T1: -
return &battery_profile_t1[0]; -
break; -
case TEMPERATURE_T2: -
return &battery_profile_t2[0]; -
break; -
case TEMPERATURE_T3: -
return &battery_profile_t3[0]; -
break; -
case TEMPERATURE_T: -
return &battery_profile_temperature[0]; -
break; -
default: -
return NULL; -
break; -
} -
} -
if (profile_p == NULL) -
{ -
bm_print(BM_LOG_CRTI, "[FGADC] fgauge_get_profile : create table fail !\r\n"); -
} -
/* 由当前温度,通过 温度-电池容量表格,获得对应的 温度-电池容量 数据, -
即能得到当前温度所对应的用掉的电池容量 */ -
fgauge_construct_battery_profile(temperature, profile_p); -
void fgauge_construct_battery_profile(kal_int32 temperature, BATTERY_PROFILE_STRUC_P temp_profile_p) -
{ -
BATTERY_PROFILE_STRUC_P low_profile_p, high_profile_p; -
kal_int32 low_temperature, high_temperature; -
int i, saddles; -
kal_int32 temp_v_1 = 0, temp_v_2 = 0; -
/* 获得对就温度所在温度上限/下限所对应的 温度-电池容量表格 */ -
if (temperature <= TEMPERATURE_T1) -
{ -
low_profile_p = fgauge_get_profile(TEMPERATURE_T0); -
high_profile_p = fgauge_get_profile(TEMPERATURE_T1); -
low_temperature = (-10); -
high_temperature = TEMPERATURE_T1; -
if(temperature < low_temperature) -
{ -
temperature = low_temperature; -
} -
} -
else if (temperature <= TEMPERATURE_T2) -
{ -
low_profile_p = fgauge_get_profile(TEMPERATURE_T1); -
high_profile_p = fgauge_get_profile(TEMPERATURE_T2); -
low_temperature = TEMPERATURE_T1; -
high_temperature = TEMPERATURE_T2; -
if(temperature < low_temperature) -
{ -
temperature = low_temperature; -
} -
} -
else -
{ -
low_profile_p = fgauge_get_profile(TEMPERATURE_T2); // 温度下限所对应的 温度-电池容量表格 -
high_profile_p = fgauge_get_profile(TEMPERATURE_T3); // 温度上限所对应的 温度-电池容量表格 -
low_temperature = TEMPERATURE_T2; // 温度下限 -
high_temperature = TEMPERATURE_T3; // 温度上限 -
if(temperature > high_temperature) -
{ -
temperature = high_temperature; -
} -
} -
/* 获得 温度-电池容量 表格项数 */ -
saddles = fgauge_get_saddles(); -
/* 遍历表格,插值获得当前温度对应的容量 */ -
for (i = 0; i < saddles; i++) -
{ -
if( ((high_profile_p + i)->voltage) > ((low_profile_p + i)->voltage) ) -
{ -
temp_v_1 = (high_profile_p + i)->voltage; -
temp_v_2 = (low_profile_p + i)->voltage; -
(temp_profile_p + i)->voltage = temp_v_2 + -
( -
( -
(temperature - low_temperature) * -
(temp_v_1 - temp_v_2) -
) / -
(high_temperature - low_temperature) -
); -
} -
else -
{ -
temp_v_1 = (low_profile_p + i)->voltage; -
temp_v_2 = (high_profile_p + i)->voltage; -
(temp_profile_p + i)->voltage = temp_v_2 + -
( -
( -
(high_temperature - temperature) * -
(temp_v_1 - temp_v_2) -
) / -
(high_temperature - low_temperature) -
); -
} -
(temp_profile_p + i)->percentage = (high_profile_p + i)->percentage; -
#if 0 -
(temp_profile_p + i)->voltage = temp_v_2 + -
( -
( -
(temperature - low_temperature) * -
(temp_v_1 - temp_v_2) -
) / -
(high_temperature - low_temperature) -
); -
#endif -
} -
// Dumpt new battery profile -
for (i = 0; i < saddles ; i++) -
{ -
bm_print(BM_LOG_CRTI, "<DOD,Voltage> at %d = <%d,%d>\r\n", -
temperature, (temp_profile_p+i)->percentage, (temp_profile_p+i)->voltage); -
} -
} -
} -
/* 首先获得电池电压,然后获得 hw ocv 电压,两者差值较小时,即 hw ocv 为准, -
然后以此计算出开机电池容量值,并且与 rtc 中记录的电量值进行比较,如果误差较小(小于 40%) -
则以 rtc 容量值为准,最后初始化 oam 算法的相关参数 */ -
oam_init(); -
void oam_init(void) -
{ -
int ret=0; -
int vol_bat=0; -
kal_int32 vbat_capacity = 0; -
vol_bat = 5; //set avg times -
/* 读 PMIC 引用 BATSNS 的电压,即电池电压 */ -
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_SENSE, &vol_bat); // battery_meter_ctrl() 被初化为 bm_ctrl_cmd() -
static kal_int32 read_adc_v_bat_sense(void *data) -
{ -
#if defined(CONFIG_POWER_EXT) -
*(kal_int32*)(data) = 4201; -
#else -
/* 读 PMIC 对应的 ADC 的值,并将其转化为对应的电压值,这里即读取 BATSNS 引脚电压 */ -
*(kal_int32*)(data) = PMIC_IMM_GetOneChannelValue(VBAT_CHANNEL_NUMBER,*(kal_int32*)(data),1); -
#endif -
return STATUS_OK; -
} -
/* 这里应该是获得 hw ocv 电压 */ -
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_OCV, &gFG_voltage); -
static kal_int32 read_hw_ocv(void *data) -
{ -
/* 外部充电器的话直接固定值 */ -
#if defined(CONFIG_POWER_EXT) -
*(kal_int32*)(data) = 3999; -
#else -
/* 这里应该是读取相应寄存器, 获得一个 hw ocv 电压 */ -
*(kal_int32*)(data) = get_hw_ocv(); -
int get_hw_ocv(void) -
{ -
#if defined(CONFIG_POWER_EXT) -
return 4001; -
#else -
kal_int32 adc_result_reg=0; -
kal_int32 adc_result=0; -
kal_int32 r_val_temp=4; -
#if defined(SWCHR_POWER_PATH) -
adc_result_reg = 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 -
/* 这里应该是读取相应寄存器,获得充电电压值,因为从 PMIC 手册上说,只有在充电电压处于 4.3V <= x <= 7V 时才可以充电*/ -
adc_result_reg = upmu_get_rg_adc_out_wakeup_pchr(); -
kal_uint32 upmu_get_rg_adc_out_wakeup_pchr(void) -
{ -
kal_uint32 ret=0; -
kal_uint32 val=0; -
pmic_lock(); -
ret=pmic_read_interface( (kal_uint32)(AUXADC_ADC8), -
(&val), -
(kal_uint32)(PMIC_RG_ADC_OUT_WAKEUP_PCHR_MASK), -
(kal_uint32)(PMIC_RG_ADC_OUT_WAKEUP_PCHR_SHIFT) -
); -
pmic_unlock(); -
return val; -
} -
/* 将得到的 adc 数值转换为对应的 模拟电压值 */ -
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 -
} -
#endif -
return STATUS_OK; -
} -
/* 获取 hw ocv 电压对应的的电池剩余容量百分比 */ -
gFG_capacity_by_v = fgauge_read_capacity_by_v(gFG_voltage); -
kal_int32 fgauge_read_capacity_by_v(kal_int32 voltage) -
{ -
int i = 0, saddles = 0; -
BATTERY_PROFILE_STRUC_P profile_p; -
kal_int32 ret_percent = 0; -
/* 获得当前温度对应的 温度-电池容量表格 */ -
profile_p = fgauge_get_profile(TEMPERATURE_T); -
if (profile_p == NULL) -
{ -
bm_print(BM_LOG_CRTI, "[FGADC] fgauge get ZCV profile : fail !\r\n"); -
return 100; -
} -
/* 获得 温度-电池容量 表格项数 */ -
saddles = fgauge_get_saddles(); -
if (voltage > (profile_p+0)->voltage) -
{ -
return 100; // battery capacity, not dod -
} -
if (voltage < (profile_p+saddles-1)->voltage) -
{ -
return 0; // battery capacity, not dod -
} -
/* 遍历表格,插值获得当前电压对应的用掉容量百分比 */ -
for (i = 0; i < saddles - 1; i++) -
{ -
if ((voltage <= (profile_p+i)->voltage) && (voltage >= (profile_p+i+1)->voltage)) -
{ -
ret_percent = (profile_p+i)->percentage + -
( -
( -
( ((profile_p+i)->voltage) - voltage ) * -
( ((profile_p+i+1)->percentage) - ((profile_p + i)->percentage) ) -
) / -
( ((profile_p+i)->voltage) - ((profile_p+i+1)->voltage) ) -
); -
break; -
} -
} -
/* 获得当前剩余电量值 */ -
ret_percent = 100 - ret_percent; -
return ret_percent; -
} -
/* 获得当前电池电压对应的剩余容量百分比 */ -
vbat_capacity = fgauge_read_capacity_by_v(vol_bat); -
kal_int32 fgauge_read_capacity_by_v(kal_int32 voltage) -
{ -
int i = 0, saddles = 0; -
BATTERY_PROFILE_STRUC_P profile_p; -
kal_int32 ret_percent = 0; -
/* 获得当前温度对应的 温度-电池容量表格 */ -
profile_p = fgauge_get_profile(TEMPERATURE_T); -
if (profile_p == NULL) -
{ -
bm_print(BM_LOG_CRTI, "[FGADC] fgauge get ZCV profile : fail !\r\n"); -
return 100; -
} -
/* 获得 温度-电池容量 表格项数 */ -
saddles = fgauge_get_saddles(); -
if (voltage > (profile_p+0)->voltage) -
{ -
return 100; // battery capacity, not dod -
} -
if (voltage < (profile_p+saddles-1)->voltage) -
{ -
return 0; // battery capacity, not dod -
} -
/* 遍历表格,插值获得当前电压对应的用掉容量百分比 */ -
for (i = 0; i < saddles - 1; i++) -
{ -
if ((voltage <= (profile_p+i)->voltage) && (voltage >= (profile_p+i+1)->voltage)) -
{ -
ret_percent = (profile_p+i)->percentage + -
( -
( -
( ((profile_p+i)->voltage) - voltage ) * -
( ((profile_p+i+1)->percentage) - ((profile_p + i)->percentage) ) -
) / -
( ((profile_p+i)->voltage) - ((profile_p+i+1)->voltage) ) -
); -
break; -
} -
} -
ret_percent = 100 - ret_percent; -
return ret_percent; -
} -
/* 如果充电器插上了,则比较使用当前电压与 hw ocv 电压计算的两都容量差,如果差值较小,继续使用 hw ocv 电压及 -
对应容量为准 */ -
if(bat_is_charger_exist() == KAL_TRUE) -
/// -
Pulse Charging Algorithm -
// 判断充电是否插上了 -
/// -
kal_bool bat_is_charger_exist(void) -
{ -
return get_charger_detect_status(); -
int get_charger_detect_status(void) -
{ -
kal_bool chr_status; -
/* 对应的充电芯片的硬件函数 */ -
battery_charging_control(CHARGING_CMD_GET_CHARGER_DET_STATUS,&chr_status); -
static kal_uint32 charging_get_charger_det_status(void *data) -
{ -
kal_uint32 status = STATUS_OK; -
#if defined(CHRDET_SW_MODE_EN) -
kal_uint32 vchr_val=0; -
/* 读 PMIC 对应的 ADC 的值,并将其转化为对应的电压值,这里即读取 VCDT 引脚电压 */ -
vchr_val = PMIC_IMM_GetOneChannelValue(4,5,1); -
vchr_val = (((330+39)*100*vchr_val)/39)/100; -
if( vchr_val > 4300 ) -
{ -
battery_xlog_printk(BAT_LOG_FULL, "[CHRDET_SW_WORKAROUND_EN] upmu_is_chr_det=Y (%d)\n", vchr_val); -
*(kal_uint32 *)data = KAL_TRUE; -
} -
else -
{ -
battery_xlog_printk(BAT_LOG_FULL, "[CHRDET_SW_WORKAROUND_EN] upmu_is_chr_det=N (%d)\n", vchr_val); -
*(kal_uint32 *)data = KAL_FALSE; -
} -
#else -
/* 读取 CHR_CON0 寄存器 */ -
*(kal_bool*)(data) = upmu_get_rgs_chrdet(); -
kal_uint32 upmu_get_rgs_chrdet(void) -
{ -
kal_uint32 ret=0; -
kal_uint32 val=0; -
pmic_lock(); -
ret=pmic_read_interface( (kal_uint32)(CHR_CON0), -
(&val), -
(kal_uint32)(PMIC_RGS_CHRDET_MASK), -
(kal_uint32)(PMIC_RGS_CHRDET_SHIFT) -
); -
pmic_unlock(); -
return val; -
} -
#endif -
/* 读取 CHR_CON0 寄存器 */ -
if( upmu_get_rgs_chrdet() == 0 ) -
g_charger_type = CHARGER_UNKNOWN; -
return status; -
} -
return chr_status; -
} -
} -
// 如果插入了充电器,hw_ocv 大部分情况是准的,插着 charger 的情况,采集的时候可能会不准 -
{ -
bm_print(BM_LOG_CRTI, "[oam_init_inf] gFG_capacity_by_v=%d, vbat_capacity=%d, \n",gFG_capacity_by_v,vbat_capacity); -
// to avoid plug in cable without battery, then plug in battery to make hw soc = 100% -
// if the difference bwtween ZCV and vbat is too large, using vbat instead ZCV -
/* 如果两者差值超过 30%,我们认为 hw ocv 存在偏差,会以 Vbat 作为 ocv -
如果两者差值在 30%,继续以 hw ocv 作为 ocv 的数值 */ -
if(((gFG_capacity_by_v == 100) && (vbat_capacity < CUST_POWERON_MAX_VBAT_TOLRANCE)) ||(abs(gFG_capacity_by_v-vbat_capacity)>CUST_POWERON_DELTA_VBAT_TOLRANCE)) -
{ -
bm_print(BM_LOG_CRTI, "[oam_init] fg_vbat=(%d), vbat=(%d), set fg_vat as vat\n", gFG_voltage,vol_bat); -
gFG_voltage = vol_bat; -
gFG_capacity_by_v = vbat_capacity; -
} -
} -
// 获得的比较真实的开机容量 -
gFG_capacity_by_v_init = gFG_capacity_by_v; -
/* 这里与 rtc 中的电量进行比较,确定一个开机显示 UI 电量 */ -
dod_init(); -
void dod_init(void) -
{ -
#if defined(SOC_BY_HW_FG) -
int ret = 0; -
//use get_hw_ocv----------------------------------------------------------------- -
/* 获取 PMIC 硬件上的 hw ocv 电压 */ -
ret=battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_OCV, &gFG_voltage); -
// 对应 PMIC 硬件相关操作函数 -
read_hw_ocv() -
get_hw_ocv() -
/* 根据 hw ocv 电压,查表获取对应的电池剩余电量百分比*/ -
gFG_capacity_by_v = fgauge_read_capacity_by_v(gFG_voltage); -
bm_print(BM_LOG_CRTI, "[FGADC] get_hw_ocv=%d, HW_SOC=%d, SW_SOC = %d\n", -
gFG_voltage, gFG_capacity_by_v, gFG_capacity_by_v_init); -
// compare with hw_ocv & sw_ocv, check if less than or equal to 5% tolerance -
// 将软件 ocv 与硬件 ocv 比较,误差要少于 5%, 才使用之前计算的 sw hov? -
if ((abs(gFG_capacity_by_v_init - gFG_capacity_by_v) > 5) && (bat_is_charger_exist() == KAL_TRUE)) -
{ -
gFG_capacity_by_v = gFG_capacity_by_v_init; -
} -
//------------------------------------------------------------------------------- -
#endif -
#if defined(CONFIG_POWER_EXT) -
g_rtc_fg_soc = gFG_capacity_by_v; -
#else -
/* 获取 DOD0 的数值,电池电量每 10s 写入 RTC 一次,开机会从 RTC 里面读取 DOD0 的值 -
保存在 rtc 数值,即上次关机的 UI 电量数值 */ -
g_rtc_fg_soc = get_rtc_spare_fg_value(); -
int get_rtc_spare_fg_value(void) -
{ -
//RTC_AL_HOU bit8~14 -
u16 temp; -
unsigned long flags; -
spin_lock_irqsave(&rtc_lock, flags); -
temp = hal_rtc_get_register_status("FG"); -
spin_unlock_irqrestore(&rtc_lock, flags); -
return temp; -
} -
#endif -
/* g_rtc_fg_soc: 为上次关机前的 UI 电量 -
gFG_capacity_by_v: 是经过 oam_init() 初始化后的电池真实电压 -
由于存在换电池的风险, 会去判断两者的差值: -
1. 40% 以内,采用 rtc 电量,即继续显示上次 UI 的电量 -
2. 如果在 40% 以外,采用真实电池电压的电量,因为有可能更换了电池 -
设计的初衷: 因为电池特性,在确定 dod 会有误差,从而导致开关机电量跳变, -
因此采用 rtc 是为了防止电量跳变 -
*/ -
if(g_rtc_fg_soc >= gFG_capacity_by_v) -
{ -
if(((g_rtc_fg_soc != 0) && ((g_rtc_fg_soc-gFG_capacity_by_v) < CUST_POWERON_DELTA_CAPACITY_TOLRANCE) &&(( gFG_capacity_by_v > CUST_POWERON_LOW_CAPACITY_TOLRANCE || bat_is_charger_exist() == KAL_TRUE))) -
|| ((g_rtc_fg_soc != 0) &&(g_boot_reason == BR_WDT_BY_PASS_PWK || g_boot_reason == BR_WDT || g_boot_reason == BR_TOOL_BY_PASS_PWK || g_boot_reason == BR_2SEC_REBOOT || g_boot_mode == RECOVERY_BOOT))) -
{ -
gFG_capacity_by_v = g_rtc_fg_soc; -
} -
} -
else -
{ -
if(((g_rtc_fg_soc != 0) && ((gFG_capacity_by_v-g_rtc_fg_soc) < CUST_POWERON_DELTA_CAPACITY_TOLRANCE) &&(( gFG_capacity_by_v > CUST_POWERON_LOW_CAPACITY_TOLRANCE || bat_is_charger_exist() == KAL_TRUE))) -
|| ((g_rtc_fg_soc != 0) &&(g_boot_reason == BR_WDT_BY_PASS_PWK || g_boot_reason == BR_WDT || g_boot_reason == BR_TOOL_BY_PASS_PWK || g_boot_reason == BR_2SEC_REBOOT || g_boot_mode == RECOVERY_BOOT))) -
{ -
gFG_capacity_by_v = g_rtc_fg_soc; -
} -
} -
bm_print(BM_LOG_CRTI, "[FGADC] g_rtc_fg_soc=%d, gFG_capacity_by_v=%d\n", -
g_rtc_fg_soc, gFG_capacity_by_v); -
if (gFG_capacity_by_v == 0 && bat_is_charger_exist() == KAL_TRUE) { -
gFG_capacity_by_v = 1; -
bm_print(BM_LOG_CRTI, "[FGADC] gFG_capacity_by_v=%d\n", -
gFG_capacity_by_v); -
} -
// -
// 在这里最终定义的开机 UI 电量显示 -
gFG_capacity = gFG_capacity_by_v; // 电池剩余容量百分比 -
gFG_capacity_by_c_init = gFG_capacity; -
gFG_capacity_by_c = gFG_capacity; -
gFG_DOD0 = 100 - gFG_capacity; // 电池使用完电量百分比 -
gFG_DOD1=gFG_DOD0; // 电池使用完电量百分比 -
gfg_percent_check_point = gFG_capacity; // 容量检测百分比 -
#if defined(CHANGE_TRACKING_POINT) -
gFG_15_vlot = fgauge_read_v_by_capacity( (100-g_tracking_point) ); -
bm_print(BM_LOG_CRTI, "[FGADC] gFG_15_vlot = %dmV\n", gFG_15_vlot); -
#else -
//gFG_15_vlot = fgauge_read_v_by_capacity(86); //14% -
/* 通过当前使用掉的容量,获取当前电压 */ -
gFG_15_vlot = fgauge_read_v_by_capacity( (100-g_tracking_point) ); -
bm_print(BM_LOG_CRTI, "[FGADC] gFG_15_vlot = %dmV\n", gFG_15_vlot); -
if( (gFG_15_vlot > 3800) || (gFG_15_vlot < 3600) ) -
{ -
bm_print(BM_LOG_CRTI, "[FGADC] gFG_15_vlot(%d) over range, reset to 3700\n", gFG_15_vlot); -
gFG_15_vlot = 3700; -
} -
#endif -
} -
/* 先通过 battery_meter_get_battery_temperature() 获得电池温度,再通过 fgauge_get_Q_max() 计算电量 -
这里获得当前温度的电池的最大容量 */ -
gFG_BATT_CAPACITY_aging = fgauge_get_Q_max(battery_meter_get_battery_temperature()); -
kal_int32 battery_meter_get_battery_temperature(void) -
{ -
/* 通过获得当前 NTC 电压,查表并进行线性插值法,得到当前的温度值 */ -
return force_get_tbat(); -
} -
// 通过当前温度获插值得到当前最大容量 -
kal_int32 fgauge_get_Q_max(kal_int16 temperature) -
{ -
kal_int32 ret_Q_max=0; -
kal_int32 low_temperature = 0, high_temperature = 0; -
kal_int32 low_Q_max = 0, high_Q_max = 0; -
/* 如果温度位于 -20< x <= 0 */ -
if (temperature <= TEMPERATURE_T1) -
{ -
low_temperature = (-10); -
low_Q_max = Q_MAX_NEG_10; -
high_temperature = TEMPERATURE_T1; -
high_Q_max = Q_MAX_POS_0; -
if(temperature < low_temperature) -
{ -
temperature = low_temperature; -
} -
} -
/* 如果温度位于 0< x <= 25 */ -
else if (temperature <= TEMPERATURE_T2) -
{ -
low_temperature = TEMPERATURE_T1; -
low_Q_max = Q_MAX_POS_0; -
high_temperature = TEMPERATURE_T2; -
high_Q_max = Q_MAX_POS_25; -
if(temperature < low_temperature) -
{ -
temperature = low_temperature; -
} -
} -
/* 如果温度位于 -25< x <=50 */ -
else -
{ -
low_temperature = TEMPERATURE_T2; // 低温下限 -
low_Q_max = Q_MAX_POS_25; // 低温最大容量 -
high_temperature = TEMPERATURE_T3; // 高温上限 -
high_Q_max = Q_MAX_POS_50; // 高温对应最大容量 -
// 防止范围溢出 -
if(temperature > high_temperature) -
{ -
temperature = high_temperature; -
} -
} -
/*// -
核心算法: -
当前容量 = 低温下限最大容量 + (当前温度 - 低温下限) * [(高温容量 - 低温容量)/(高温上限-低温下限)] */ -
ret_Q_max = low_Q_max + -
( -
( -
(temperature - low_temperature) * -
(high_Q_max - low_Q_max) -
) / -
(high_temperature - low_temperature) -
); -
bm_print(BM_LOG_FULL, "[fgauge_get_Q_max] Q_max = %d\r\n", ret_Q_max); -
return ret_Q_max; -
} -
//oam_v_ocv_1 = gFG_voltage; -
//oam_v_ocv_2 = gFG_voltage; -
/* 通过当前使用电池容量的百分比,反换算出当前的电压 */ -
oam_v_ocv_init = fgauge_read_v_by_d(gFG_DOD0); -
kal_int32 fgauge_read_v_by_d(int d_val) -
{ -
int i = 0, saddles = 0; -
BATTERY_PROFILE_STRUC_P profile_p; -
kal_int32 ret_volt = 0; -
profile_p = fgauge_get_profile(TEMPERATURE_T); -
if (profile_p == NULL) -
{ -
bm_print(BM_LOG_CRTI, "[fgauge_read_v_by_capacity] fgauge get ZCV profile : fail !\r\n"); -
return 3700; -
} -
saddles = fgauge_get_saddles(); -
if (d_val < (profile_p+0)->percentage) -
{ -
return 3700; -
} -
if (d_val > (profile_p+saddles-1)->percentage) -
{ -
return 3700; -
} -
for (i = 0; i < saddles - 1; i++) -
{ -
if ((d_val >= (profile_p+i)->percentage) && (d_val <= (profile_p+i+1)->percentage)) -
{ -
ret_volt = (profile_p+i)->voltage - -
( -
( -
( d_val - ((profile_p+i)->percentage) ) * -
( ((profile_p+i)->voltage) - ((profile_p+i+1)->voltage) ) -
) / -
( ((profile_p+i+1)->percentage) - ((profile_p+i)->percentage) ) -
); -
break; -
} -
} -
return ret_volt; -
} -
oam_v_ocv_2 = oam_v_ocv_1 = oam_v_ocv_init; // 通过当前使用电池容量的百分比,反换算出当前的电压 -
g_vol_bat_hw_ocv = gFG_voltage; // hw ocv 电压 -
//vbat = 5; //set avg times -
//ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_SENSE, &vbat); -
//oam_r_1 = fgauge_read_r_bat_by_v(vbat); -
/* 通过当前 hw ocv 电压,获得的当前电池内阻 */ -
oam_r_1 = fgauge_read_r_bat_by_v(gFG_voltage); -
oam_r_2 = oam_r_1; -
oam_d0 = gFG_DOD0; -
oam_d_5 = oam_d0; -
oam_i_ori = gFG_current; -
g_d_hw_ocv = oam_d0; -
if(oam_init_i == 0) -
{ -
bm_print(BM_LOG_CRTI, "[oam_init] oam_v_ocv_1,oam_v_ocv_2,oam_r_1,oam_r_2,oam_d0,oam_i_ori\n"); -
oam_init_i=1; -
} -
bm_print(BM_LOG_CRTI, "[oam_init] %d,%d,%d,%d,%d,%d\n", -
oam_v_ocv_1, oam_v_ocv_2, oam_r_1, oam_r_2, oam_d0, oam_i_ori); -
bm_print(BM_LOG_CRTI, "[oam_init_inf] hw_OCV, hw_D0, RTC, D0, oam_OCV_init, tbat\n"); -
bm_print(BM_LOG_CRTI, "[oam_run_inf] oam_OCV1, oam_OCV2, vbat, I1, I2, R1, R2, Car1, Car2,qmax, tbat\n"); -
bm_print(BM_LOG_CRTI, "[oam_result_inf] D1, D2, D3, D4, D5, UI_SOC\n"); -
bm_print(BM_LOG_CRTI, "[oam_init_inf] %d, %d, %d, %d, %d, %d\n", -
gFG_voltage, (100 - fgauge_read_capacity_by_v(gFG_voltage)), g_rtc_fg_soc, gFG_DOD0 ,oam_v_ocv_init, force_get_tbat()); -
} -
bm_print(BM_LOG_CRTI, "[battery_meter_initial] SOC_BY_SW_FG done\n"); -
#endif -
return 0; -
#endif -
} -
/* 获得要监控的电量,(用这个电量反换出电压来校验?)*/ -
BMT_status.nPercent_ZCV = battery_meter_get_battery_nPercent_zcv(); -
kal_int32 battery_meter_get_battery_nPercent_zcv(void) -
{ -
#if defined(CONFIG_POWER_EXT) -
return 3700; -
#else -
return gFG_15_vlot; // 15% zcv, 15% can be customized by 100-g_tracking_point -
#endif -
} -
battery_meter_initilized = KAL_TRUE; -
} -
// 1. 判断是插入的是否充电器还是电脑 USB,看能不能进行充电 -
/* 如果连接的 USB 线为 USB 充电线,或者电脑 USB 线,则打开 USB, -
这里会通过 BC1.1 来判断是电脑 USB 还是 USB 充电器,来决定充电电流 -
否则连接的不是充电线或者 USB 作为一个从设备使用,要断开 USB? -
*/ -
mt_battery_charger_detect_check(); -
static void mt_battery_charger_detect_check(void) -
{ -
/* 根据 USB 是主从状态,以及外部充电电压是否正常来判断是否允许充电, -
这里如果是 USB 作为从设备,允许充电 */ -
if( upmu_is_chr_det() == KAL_TRUE ) -
/// -
PMIC PCHR Related APIs -
/// -
kal_bool upmu_is_chr_det(void) -
{ -
#if defined(CONFIG_POWER_EXT) -
//return KAL_TRUE; -
return get_charger_detect_status(); -
// 如果是外部充电芯片,则直接会调用外部芯片的充电相关函数,如 charging_hw_bq24196.c 中的 -
battery_charging_control(CHARGING_CMD_GET_CHARGER_DET_STATUS,&chr_status); -
#else -
kal_uint32 tmp32; -
/* 这里是 PMIC,调用 PMIC 的充电相关函数 charging_hw_pmic.c, -
这里查询 PMIC 的 CHR_CON0 寄存器,检查充电状态 */ -
tmp32=get_charger_detect_status(); -
int get_charger_detect_status(void) -
{ -
kal_bool chr_status; -
battery_charging_control(CHARGING_CMD_GET_CHARGER_DET_STATUS,&chr_status); -
static kal_uint32 charging_get_charger_det_status(void *data) -
{ -
kal_uint32 status = STATUS_OK; -
#if defined(CHRDET_SW_MODE_EN) -
kal_uint32 vchr_val=0; -
// 获得 PMIC 的 VCDT 充电电压值 -
vchr_val = PMIC_IMM_GetOneChannelValue(4,5,1); -
vchr_val = (((330+39)*100*vchr_val)/39)/100; -
if( vchr_val > 4300 ) -
{ -
battery_xlog_printk(BAT_LOG_FULL, "[CHRDET_SW_WORKAROUND_EN] upmu_is_chr_det=Y (%d)\n", vchr_val); -
*(kal_uint32 *)data = KAL_TRUE; -
} -
else -
{ -
battery_xlog_printk(BAT_LOG_FULL, "[CHRDET_SW_WORKAROUND_EN] upmu_is_chr_det=N (%d)\n", vchr_val); -
*(kal_uint32 *)data = KAL_FALSE; -
} -
#else -
*(kal_bool*)(data) = upmu_get_rgs_chrdet(); -
#endif -
/* 读取 PMIC CHR_CON0 寄存器 */ -
if( upmu_get_rgs_chrdet() == 0 ) -
g_charger_type = CHARGER_UNKNOWN; -
return status; -
} -
return chr_status; -
} -
if(tmp32 == 0) -
{ -
return KAL_FALSE; -
} -
else -
{ -
/* 如果 USB 作为一个不是以从设备运行,是不允许充电的 */ -
if( mt_usb_is_device() ) -
// Usb20.c (s:\i841\mediatek\platform\mt6582\kernel\drivers\usb20) -
/* ================================ */ -
/* connect and disconnect functions */ -
/* ================================ */ -
bool mt_usb_is_device(void) -
{ -
DBG(4,"called\n"); -
/* 如果 mtk_musb 为 0 的话,表明 MTK 的 USB 在作为一个主机使用,不允许充电的 */ -
if(!mtk_musb){ -
DBG(0,"mtk_musb is NULL\n"); -
return false; // don't do charger detection when usb is not ready -
} else { -
DBG(4,"is_host=%d\n",mtk_musb->is_host); -
} -
return !mtk_musb->is_host; -
} -
{ -
battery_xlog_printk(BAT_LOG_FULL, "[upmu_is_chr_det] Charger exist and USB is not host\n"); -
return KAL_TRUE; -
} -
else -
{ -
battery_xlog_printk(BAT_LOG_FULL, "[upmu_is_chr_det] Charger exist but USB is host\n"); -
return KAL_FALSE; -
} -
} -
#endif -
} -
// 如果插入的是 USB 充电线或者 电脑的 USB 线,则打开 USB ,因为充电时 MTK 作为从设备,是允许充电的 -
{ -
wake_lock(&battery_suspend_lock); -
BMT_status.charger_exist = KAL_TRUE; -
// 无线充电支持宏 -
#if defined(MTK_WIRELESS_CHARGER_SUPPORT) -
mt_charger_type_detection(); -
if((BMT_status.charger_type==STANDARD_HOST) || (BMT_status.charger_type==CHARGING_HOST) ) -
{ -
// 这应该是做为从设备连接到电脑上用的 -
mt_usb_connect(); -
} -
#else -
/* 这个结构体是在前面初始化的,所以第一次执行,该值未设置 = 0, -
在这里通过 BC1.1 协议检测外部连接的 USB 线类型,是主是从,还是充电/被充 -
最后根据类型判断要不要启动 USB */ -
if(BMT_status.charger_type == CHARGER_UNKNOWN) -
{ -
/* 调用 PMIC 硬件相关函数,检测充电类型, 这里应用了 BC1.1 协议来检测 */ -
mt_charger_type_detection(); -
CHARGER_TYPE mt_charger_type_detection(void) -
{ -
CHARGER_TYPE CHR_Type_num = CHARGER_UNKNOWN; -
mutex_lock(&charger_type_mutex); -
#if defined(MTK_WIRELESS_CHARGER_SUPPORT) -
battery_charging_control(CHARGING_CMD_GET_CHARGER_TYPE,&CHR_Type_num); -
BMT_status.charger_type = CHR_Type_num; -
#else -
/* 调用 PMIC 硬件相关函数,检测充电类型, 这里应用了 BC1.1 协议来检测 */ -
if(BMT_status.charger_type == CHARGER_UNKNOWN) -
{ -
/* 调用 PMIC 硬件相关函数,检测充电类型, 这里应用了 BC1.1 协议来检测 */ -
battery_charging_control(CHARGING_CMD_GET_CHARGER_TYPE,&CHR_Type_num); -
static kal_uint32 charging_get_charger_type(void *data) -
{ -
kal_uint32 status = STATUS_OK; -
#if defined(CONFIG_POWER_EXT) -
*(CHARGER_TYPE*)(data) = STANDARD_HOST; -
#else -
#if defined(MTK_WIRELESS_CHARGER_SUPPORT) -
int wireless_state = 0; -
/* 无线充电判断引脚,直接拉低就好 */ -
wireless_state = mt_get_gpio_in(wireless_charger_gpio_number); -
if(wireless_state == WIRELESS_CHARGER_EXIST_STATE) -
{ -
*(CHARGER_TYPE*)(data) = WIRELESS_CHARGER; -
battery_xlog_printk(BAT_LOG_CRTI, "WIRELESS_CHARGER!\r\n"); -
return status; -
} -
#endif -
if(g_charger_type!=CHARGER_UNKNOWN && g_charger_type!=WIRELESS_CHARGER) -
{ -
*(CHARGER_TYPE*)(data) = g_charger_type; -
battery_xlog_printk(BAT_LOG_CRTI, "return %d!\r\n", g_charger_type); -
return status; -
} -
charging_type_det_done = KAL_FALSE; -
/*// -
BC1.1 充电协议,主要用来区分是插入的是 USB 还是充电器,如果是 USB 只能提供 500ma 充电, -
如果是充电器,则可以大电流充电 */ -
/********* Step initial ***************/ -
hw_bc11_init(); -
static void hw_bc11_init(void) -
{ -
msleep(300); -
Charger_Detect_Init(); -
//RG_BC11_BIAS_EN=1 -
upmu_set_rg_bc11_bias_en(0x1); -
//RG_BC11_VSRC_EN[1:0]=00 -
upmu_set_rg_bc11_vsrc_en(0x0); -
//RG_BC11_VREF_VTH = [1:0]=00 -
upmu_set_rg_bc11_vref_vth(0x0); -
//RG_BC11_CMP_EN[1.0] = 00 -
upmu_set_rg_bc11_cmp_en(0x0); -
//RG_BC11_IPU_EN[1.0] = 00 -
upmu_set_rg_bc11_ipu_en(0x0); -
//RG_BC11_IPD_EN[1.0] = 00 -
upmu_set_rg_bc11_ipd_en(0x0); -
//BC11_RST=1 -
upmu_set_rg_bc11_rst(0x1); -
//BC11_BB_CTRL=1 -
upmu_set_rg_bc11_bb_ctrl(0x1); -
//msleep(10); -
mdelay(50); -
if(Enable_BATDRV_LOG == BAT_LOG_FULL) -
{ -
battery_xlog_printk(BAT_LOG_FULL, "hw_bc11_init() \r\n"); -
hw_bc11_dump_register(); -
} -
} -
/********* Step DCD ***************/ -
if(1 == hw_bc11_DCD()) -
{ -
/********* Step A1 ***************/ -
if(1 == hw_bc11_stepA1()) -
{ -
*(CHARGER_TYPE*)(data) = APPLE_2_1A_CHARGER; -
battery_xlog_printk(BAT_LOG_CRTI, "step A1 : Apple 2.1A CHARGER!\r\n"); -
} -
else -
{ -
*(CHARGER_TYPE*)(data) = NONSTANDARD_CHARGER; -
battery_xlog_printk(BAT_LOG_CRTI, "step A1 : Non STANDARD CHARGER!\r\n"); -
} -
} -
else -
{ -
/********* Step A2 ***************/ -
if(1 == hw_bc11_stepA2()) -
{ -
/********* Step B2 ***************/ -
if(1 == hw_bc11_stepB2()) -
{ -
*(CHARGER_TYPE*)(data) = STANDARD_CHARGER; -
battery_xlog_printk(BAT_LOG_CRTI, "step B2 : STANDARD CHARGER!\r\n"); -
} -
else -
{ -
*(CHARGER_TYPE*)(data) = CHARGING_HOST; -
battery_xlog_printk(BAT_LOG_CRTI, "step B2 : Charging Host!\r\n"); -
} -
} -
else -
{ -
*(CHARGER_TYPE*)(data) = STANDARD_HOST; -
battery_xlog_printk(BAT_LOG_CRTI, "step A2 : Standard USB Host!\r\n"); -
} -
} -
/********* Finally setting *******************************/ -
hw_bc11_done(); -
static void hw_bc11_done(void) -
{ -
//RG_BC11_VSRC_EN[1:0]=00 -
upmu_set_rg_bc11_vsrc_en(0x0); -
//RG_BC11_VREF_VTH = [1:0]=0 -
upmu_set_rg_bc11_vref_vth(0x0); -
//RG_BC11_CMP_EN[1.0] = 00 -
upmu_set_rg_bc11_cmp_en(0x0); -
//RG_BC11_IPU_EN[1.0] = 00 -
upmu_set_rg_bc11_ipu_en(0x0); -
//RG_BC11_IPD_EN[1.0] = 00 -
upmu_set_rg_bc11_ipd_en(0x0); -
//RG_BC11_BIAS_EN=0 -
upmu_set_rg_bc11_bias_en(0x0); -
Charger_Detect_Release(); -
void Charger_Detect_Release(void) -
{ -
/* RG_USB20_BC11_SW_EN = 1'b0 */ -
USBPHY_CLR8(0x1a, 0x80); -
udelay(1); -
//4 14. turn off internal 48Mhz PLL. -
usb_enable_clock(false); -
printk("Charger_Detect_Release\n"); -
} -
if(Enable_BATDRV_LOG == BAT_LOG_FULL) -
{ -
battery_xlog_printk(BAT_LOG_FULL, "hw_bc11_done() \r\n"); -
hw_bc11_dump_register(); -
} -
} -
charging_type_det_done = KAL_TRUE; -
g_charger_type = *(CHARGER_TYPE*)(data); -
#endif -
return status; -
} -
BMT_status.charger_type = CHR_Type_num; -
} -
#endif -
mutex_unlock(&charger_type_mutex); -
return BMT_status.charger_type; -
} -
/* 如果充电线是 标准主模式 或者 主充电模式, 连接上 USB */ -
if((BMT_status.charger_type==STANDARD_HOST) || (BMT_status.charger_type==CHARGING_HOST) ) -
{ -
/* 连接 USB,充电时可以连接 USB 的 */ -
mt_usb_connect(); -
void mt_usb_connect(void) -
{ -
printk("[MUSB] USB is ready for connect\n"); -
DBG(3, "is ready %d is_host %d power %d\n",mtk_musb->is_ready,mtk_musb->is_host , mtk_musb->power); -
if (!mtk_musb || !mtk_musb->is_ready || mtk_musb->is_host || mtk_musb->power) -
return; -
DBG(0,"cable_mode=%d\n",cable_mode); -
/* CABLE_MODE_CHRG_ONLY = 0, CABLE_MODE_NORMAL, CABLE_MODE_HOST_ONLY, CABLE_MODE_MAX -
上面这些模式,应该是通过 BC1.1 来判断出来的 */ -
if(cable_mode != CABLE_MODE_NORMAL) -
{ -
DBG(0,"musb_sync_with_bat, USB_CONFIGURED\n"); -
musb_sync_with_bat(mtk_musb,USB_CONFIGURED); -
void musb_sync_with_bat(struct musb *musb,int usb_state) -
{ -
#ifndef FPGA_PLATFORM -
DBG(0,"BATTERY_SetUSBState, state=%d\n",usb_state); -
// linear_charging.c,线性充电 -
BATTERY_SetUSBState(usb_state); -
void BATTERY_SetUSBState(int usb_state_value) -
{ -
#if defined(CONFIG_POWER_EXT) -
battery_xlog_printk(BAT_LOG_CRTI, "[BATTERY_SetUSBState] in FPGA/EVB, no service\r\n"); -
#else -
if ( (usb_state_value < USB_SUSPEND) || ((usb_state_value > USB_CONFIGURED))){ -
battery_xlog_printk(BAT_LOG_CRTI, "[BATTERY] BAT_SetUSBState Fail! Restore to default value\r\n"); -
usb_state_value = USB_UNCONFIGURED; -
} else { -
battery_xlog_printk(BAT_LOG_CRTI, "[BATTERY] BAT_SetUSBState Success! Set %d\r\n", usb_state_value); -
g_usb_state = usb_state_value; -
} -
#endif -
} -
wake_up_bat(); -
void wake_up_bat (void) -
{ -
battery_xlog_printk(BAT_LOG_CRTI, "[BATTERY] wake_up_bat. \r\n"); -
chr_wake_up_bat = KAL_TRUE; -
bat_thread_timeout = KAL_TRUE; -
wake_up(&bat_thread_wq); -
} -
#endif -
} -
mtk_musb->power = true; -
return; -
} -
if (!wake_lock_active(&mtk_musb->usb_lock)) -
wake_lock(&mtk_musb->usb_lock); -
// Program the HDRC to start (enable interrupts, dma, etc.). -
// 启动 USB -
musb_start(mtk_musb); -
/*-------------------------------------------------------------------------*/ -
/* -
* Program the HDRC to start (enable interrupts, dma, etc.). -
*/ -
void musb_start(struct musb *musb) -
{ -
void __iomem *regs = musb->mregs; -
int vbusdet_retry = 5; -
u8 intrusbe; -
DBG(0, "start, is_host=%d is_active=%d\n", musb->is_host, musb->is_active); -
if(musb->is_active) { -
if(musb->is_host) { -
DBG(0, "we are host now, add more interrupt devctl=%x\n", musb_readb(mtk_musb->mregs,MUSB_DEVCTL)); -
musb->intrtxe = 0xffff; -
musb_writew(regs, MUSB_INTRTXE, musb->intrtxe); -
musb->intrrxe = 0xfffe; -
musb_writew(regs, MUSB_INTRRXE, musb->intrrxe); -
musb_writeb(regs,MUSB_INTRUSBE,0xf7); -
return; -
} -
} -
musb_platform_enable(musb); -
musb_generic_disable(musb); -
intrusbe= musb_readb(regs, MUSB_INTRUSBE); -
if (musb->is_host){ -
musb->intrtxe = 0xffff; -
musb_writew(regs, MUSB_INTRTXE, musb->intrtxe); -
musb->intrrxe = 0xfffe; -
musb_writew(regs, MUSB_INTRRXE, musb->intrrxe); -
intrusbe = 0xf7; -
while(!musb_platform_get_vbus_status(musb)) { -
mdelay(100); -
if(vbusdet_retry--<=1) { -
DBG(0, "VBUS detection fail!\n"); -
break; -
} -
} -
} else if(!musb->is_host){ -
intrusbe |= MUSB_INTR_RESET; //device mode enable reset interrupt -
} -
musb_writeb(regs,MUSB_INTRUSBE,intrusbe); -
if (musb_speed) { -
/* put into basic highspeed mode and start session */ -
musb_writeb(regs, MUSB_POWER, MUSB_POWER_SOFTCONN -
| MUSB_POWER_HSENAB -
/* ENSUSPEND wedges tusb */ -
| MUSB_POWER_ENSUSPEND); -
} else { -
/* put into basic fullspeed mode and start session */ -
musb_writeb(regs, MUSB_POWER, MUSB_POWER_SOFTCONN -
/* ENSUSPEND wedges tusb */ -
| MUSB_POWER_ENSUSPEND); -
} -
musb->is_active = 1; -
} -
printk("[MUSB] USB connect\n"); -
} -
} -
} -
#endif -
battery_xlog_printk(BAT_LOG_CRTI, "[BAT_thread]Cable in, CHR_Type_num=%d\r\n", BMT_status.charger_type); -
} -
// 如果连接入的不是正常的充电线,或者此时 USB 接口以主机状态运行 ,则设置电池状态参数,断开 USB 连接? -
else -
{ -
wake_unlock(&battery_suspend_lock); -
BMT_status.charger_exist = KAL_FALSE; -
BMT_status.charger_type = CHARGER_UNKNOWN; -
BMT_status.bat_full = KAL_FALSE; -
BMT_status.bat_in_recharging_state = KAL_FALSE; -
BMT_status.bat_charging_state = CHR_PRE; -
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; -
battery_xlog_printk(BAT_LOG_CRTI, "[BAT_thread]Cable out \r\n"); -
// 断开 USB 与电脑的连接 -
mt_usb_disconnect(); -
void mt_usb_disconnect(void) -
{ -
printk("[MUSB] USB is ready for disconnect\n"); -
if (!mtk_musb || !mtk_musb->is_ready || mtk_musb->is_host || !mtk_musb->power) -
return; -
musb_stop(mtk_musb); -
if (wake_lock_active(&mtk_musb->usb_lock)) -
wake_unlock(&mtk_musb->usb_lock); -
DBG(0,"cable_mode=%d\n",cable_mode); -
if (cable_mode != CABLE_MODE_NORMAL) { -
DBG(0,"musb_sync_with_bat, USB_SUSPEND\n"); -
musb_sync_with_bat(mtk_musb,USB_SUSPEND); -
mtk_musb->power = false; -
} -
printk("[MUSB] USB disconnect\n"); -
} -
} -
} -
/// -
// 2. 通过具体的充电芯片来获得电池信息,充电信息, 获得电池电量百分比 -
/* 通过 oam 算法,获得电量百分比 */ -
mt_battery_GetBatteryData(); -
void mt_battery_GetBatteryData(void) -
{ -
kal_uint32 bat_vol, charger_vol, Vsense, ZCV; -
kal_int32 ICharging, temperature, temperatureR, temperatureV, SOC; -
static kal_int32 bat_sum, icharging_sum, temperature_sum; -
static kal_int32 batteryVoltageBuffer[BATTERY_AVERAGE_SIZE]; -
static kal_int32 batteryCurrentBuffer[BATTERY_AVERAGE_SIZE]; -
static kal_int32 batteryTempBuffer[BATTERY_AVERAGE_SIZE]; -
static kal_uint8 batteryIndex = 0; -
static kal_int32 previous_SOC = -1; -
// 获得 BATSNS 引脚电压 -
bat_vol = battery_meter_get_battery_voltage(); -
kal_int32 battery_meter_get_battery_voltage(void) -
{ -
int ret=0; -
int val=5; -
val = 5; //set avg times -
// 获得 PMIC 的 BATSNS 引脚电压 -
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_SENSE, &val); -
static kal_int32 read_adc_v_bat_sense(void *data) -
{ -
#if defined(CONFIG_POWER_EXT) -
*(kal_int32*)(data) = 4201; -
#else -
*(kal_int32*)(data) = PMIC_IMM_GetOneChannelValue(VBAT_CHANNEL_NUMBER,*(kal_int32*)(data),1); -
#endif -
return STATUS_OK; -
} -
g_sw_vbat_temp = val; -
return val; -
} -
/* 获得 PMIC 的 ISENSE 引脚电压*/ -
Vsense = battery_meter_get_VSense(); -
kal_int32 battery_meter_get_VSense(void) -
{ -
#if defined(CONFIG_POWER_EXT) -
return 0; -
#else -
int ret=0; -
int val=0; -
val = 1; //set avg times -
/* 获得 PMIC 的 ISENSE 引脚电压*/ -
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_I_SENSE, &val); -
read_adc_v_i_sense(void *data) -
*(kal_int32*)(data) = PMIC_IMM_GetOneChannelValue(ISENSE_CHANNEL_NUMBER,*(kal_int32*)(data),1); -
return val; -
#endif -
} -
/* 获得充电电流 */ -
ICharging = battery_meter_get_charging_current(); -
kal_int32 battery_meter_get_charging_current(void) -
{ -
kal_int32 ADC_BAT_SENSE_tmp[20]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; -
kal_int32 ADC_BAT_SENSE_sum=0; -
kal_int32 ADC_BAT_SENSE=0; -
kal_int32 ADC_I_SENSE_tmp[20]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; -
kal_int32 ADC_I_SENSE_sum=0; -
kal_int32 ADC_I_SENSE=0; -
int repeat=20; -
int i=0; -
int j=0; -
kal_int32 temp=0; -
int ICharging=0; -
int ret=0; -
int val=1; -
for(i=0 ; i<repeat ; i++) -
{ -
val = 1; //set avg times -
/* 获得 PMIC 的 BATSNS 引脚电压 */ -
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_SENSE, &val); -
read_adc_v_bat_sense(void *data) -
*(kal_int32*)(data) = PMIC_IMM_GetOneChannelValue(VBAT_CHANNEL_NUMBER,*(kal_int32*)(data),1); -
ADC_BAT_SENSE_tmp[i] = val; -
val = 1; //set avg times -
/* 获得 PMIC 的 ISENSE 引脚电压 */ -
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_I_SENSE, &val); -
read_adc_v_i_sense(void *data) -
*(kal_int32*)(data) = PMIC_IMM_GetOneChannelValue(ISENSE_CHANNEL_NUMBER,*(kal_int32*)(data),1); -
ADC_I_SENSE_tmp[i] = val; -
ADC_BAT_SENSE_sum += ADC_BAT_SENSE_tmp[i]; -
ADC_I_SENSE_sum += ADC_I_SENSE_tmp[i]; -
} -
//sorting BAT_SENSE -
for(i=0 ; i<repeat ; i++) -
{ -
for(j=i; j<repeat ; j++) -
{ -
if( ADC_BAT_SENSE_tmp[j] < ADC_BAT_SENSE_tmp[i] ) -
{ -
temp = ADC_BAT_SENSE_tmp[j]; -
ADC_BAT_SENSE_tmp[j] = ADC_BAT_SENSE_tmp[i]; -
ADC_BAT_SENSE_tmp[i] = temp; -
} -
} -
} -
bm_print(BM_LOG_FULL, "[g_Get_I_Charging:BAT_SENSE]\r\n"); -
for(i=0 ; i<repeat ; i++ ) -
{ -
bm_print(BM_LOG_FULL, "%d,", ADC_BAT_SENSE_tmp[i]); -
} -
bm_print(BM_LOG_FULL, "\r\n"); -
//sorting I_SENSE -
for(i=0 ; i<repeat ; i++) -
{ -
for(j=i ; j<repeat ; j++) -
{ -
if( ADC_I_SENSE_tmp[j] < ADC_I_SENSE_tmp[i] ) -
{ -
temp = ADC_I_SENSE_tmp[j]; -
ADC_I_SENSE_tmp[j] = ADC_I_SENSE_tmp[i]; -
ADC_I_SENSE_tmp[i] = temp; -
} -
} -
} -
bm_print(BM_LOG_FULL, "[g_Get_I_Charging:I_SENSE]\r\n"); -
for(i=0 ; i<repeat ; i++ ) -
{ -
bm_print(BM_LOG_FULL, "%d,", ADC_I_SENSE_tmp[i]); -
} -
bm_print(BM_LOG_FULL, "\r\n"); -
ADC_BAT_SENSE_sum -= ADC_BAT_SENSE_tmp[0]; -
ADC_BAT_SENSE_sum -= ADC_BAT_SENSE_tmp[1]; -
ADC_BAT_SENSE_sum -= ADC_BAT_SENSE_tmp[18]; -
ADC_BAT_SENSE_sum -= ADC_BAT_SENSE_tmp[19]; -
ADC_BAT_SENSE = ADC_BAT_SENSE_sum / (repeat-4); -
bm_print(BM_LOG_FULL, "[g_Get_I_Charging] ADC_BAT_SENSE=%d\r\n", ADC_BAT_SENSE); -
ADC_I_SENSE_sum -= ADC_I_SENSE_tmp[0]; -
ADC_I_SENSE_sum -= ADC_I_SENSE_tmp[1]; -
ADC_I_SENSE_sum -= ADC_I_SENSE_tmp[18]; -
ADC_I_SENSE_sum -= ADC_I_SENSE_tmp[19]; -
ADC_I_SENSE = ADC_I_SENSE_sum / (repeat-4); -
bm_print(BM_LOG_FULL, "[g_Get_I_Charging] ADC_I_SENSE(Before)=%d\r\n", ADC_I_SENSE); -
bm_print(BM_LOG_FULL, "[g_Get_I_Charging] ADC_I_SENSE(After)=%d\r\n", ADC_I_SENSE); -
if(ADC_I_SENSE > ADC_BAT_SENSE) -
{ -
ICharging = (ADC_I_SENSE - ADC_BAT_SENSE + g_I_SENSE_offset)*1000/CUST_R_SENSE; -
} -
else -
{ -
ICharging = 0; -
} -
return ICharging; -
} -
/* 获得充电器电压 */ -
charger_vol = battery_meter_get_charger_voltage(); -
kal_int32 battery_meter_get_charger_voltage(void) -
{ -
int ret=0; -
int val=0; -
val = 5; // set avg times -
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_CHARGER, &val); -
static kal_int32 read_adc_v_charger(void *data) -
{ -
#if defined(CONFIG_POWER_EXT) -
*(kal_int32*)(data) = 5001; -
#else -
kal_int32 val; -
/* 获取 PMIC 的 VCDT 引脚电压 */ -
val = PMIC_IMM_GetOneChannelValue(VCHARGER_CHANNEL_NUMBER,*(kal_int32*)(data),1); -
val = (((R_CHARGER_1+R_CHARGER_2)*100*val)/R_CHARGER_2)/100; -
*(kal_int32*)(data) = val; -
#endif -
return STATUS_OK; -
} -
//val = (((R_CHARGER_1+R_CHARGER_2)*100*val)/R_CHARGER_2)/100; -
return val; -
} -
/* 通过获得当前 NTC 电压,查表并进行线性插值法,得到当前的温度值 */ -
temperature = battery_meter_get_battery_temperature(); -
return force_get_tbat(); -
/* 这里用来获取电池 NTC 的电压 */ -
temperatureV = battery_meter_get_tempV(); -
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_TEMP, &val); -
static kal_int32 read_adc_v_bat_temp(void *data) -
{ -
#if defined(CONFIG_POWER_EXT) -
*(kal_int32*)(data) = 0; -
#else -
#if defined(MTK_PCB_TBAT_FEATURE) -
int ret = 0, data[4], i, ret_value = 0, ret_temp = 0; -
int Channel=1; -
if( IMM_IsAdcInitReady() == 0 ) -
return g_adc_init_flag; -
{ -
bm_print(BM_LOG_CRTI, "[get_tbat_volt] AUXADC is not ready"); -
return 0; -
} -
i = times; -
while (i--) -
{ -
ret_value = IMM_GetOneChannelValue(Channel, data, &ret_temp); -
ret += ret_temp; -
bm_print(BM_LOG_FULL, "[get_tbat_volt] ret_temp=%d\n",ret_temp); -
} -
ret = ret*1500/4096 ; -
ret = ret/times; -
bm_print(BM_LOG_CRTI, "[get_tbat_volt] Battery output mV = %d\n",ret); -
*(kal_int32*)(data) = ret; -
#else -
bm_print(BM_LOG_FULL, "[read_adc_v_charger] return PMIC_IMM_GetOneChannelValue(4,times,1);\n"); -
/* 读取 PMIC 的 BATON1 引脚电压 */ -
*(kal_int32*)(data) = PMIC_IMM_GetOneChannelValue(VBATTEMP_CHANNEL_NUMBER,*(kal_int32*)(data),1); -
#endif -
#endif -
return STATUS_OK; -
} -
/* 获得 下拉电阻与 NTC 并并联的电压 */ -
temperatureR = battery_meter_get_tempR(temperatureV); -
/* 上拉电压/下拉电压 = 上拉电阻/ 下拉电阻 */ -
TRes = (RBAT_PULL_UP_R*dwVolt) / (RBAT_PULL_UP_VOLT-dwVolt); -
/* bat_thread_wakeup() 每 10s 唤醒一次,唤醒时设置 bat_meter_timeout = KAL_TRUE -
这时候更新电池电量百分比 */ -
if(bat_meter_timeout == KAL_TRUE || bat_spm_timeout == TRUE) -
{ -
/* oam 算法通过两种方式更新电压,去逼近真实的开路电压,最终查表获取近似真实的电量值百分比,方法 1,查表获得电池百分比,方法 2,库伦积分 -
以方法2获得的参数补偿方法 1 的值,具体方法见 oam_run()*/ -
SOC = battery_meter_get_battery_percentage(); -
kal_int32 battery_meter_get_battery_percentage(void) -
{ -
#if defined(CONFIG_POWER_EXT) -
return 50; -
#else -
if(bat_is_charger_exist() == KAL_FALSE) -
// 这里查询 PMIC 的 CHR_CON0 寄存器,检查充电状态 -
return get_charger_detect_status(); -
battery_charging_control(CHARGING_CMD_GET_CHARGER_DET_STATUS,&chr_status); -
static kal_uint32 charging_get_charger_det_status(void *data) -
{ -
kal_uint32 status = STATUS_OK; -
#if defined(CHRDET_SW_MODE_EN) -
kal_uint32 vchr_val=0; -
vchr_val = PMIC_IMM_GetOneChannelValue(4,5,1); -
vchr_val = (((330+39)*100*vchr_val)/39)/100; -
if( vchr_val > 4300 ) -
{ -
battery_xlog_printk(BAT_LOG_FULL, "[CHRDET_SW_WORKAROUND_EN] upmu_is_chr_det=Y (%d)\n", vchr_val); -
*(kal_uint32 *)data = KAL_TRUE; -
} -
else -
{ -
battery_xlog_printk(BAT_LOG_FULL, "[CHRDET_SW_WORKAROUND_EN] upmu_is_chr_det=N (%d)\n", vchr_val); -
*(kal_uint32 *)data = KAL_FALSE; -
} -
#else -
*(kal_bool*)(data) = upmu_get_rgs_chrdet(); -
#endif -
if( upmu_get_rgs_chrdet() == 0 ) -
g_charger_type = CHARGER_UNKNOWN; -
return status; -
} -
fg_qmax_update_for_aging_flag = 1; -
// AUX ADC算法指只依赖ADC读值,然后查表读取电量的算法 -
#if defined(SOC_BY_AUXADC) -
return auxadc_algo_run(); -
#endif -
//通过开路电压查表得到初始电量D0,后续电量通过电流积分累积,通用性强,依赖初始电量的精确度。 -
#if defined(SOC_BY_HW_FG) -
if(g_auxadc_solution == 1) -
{ -
return auxadc_algo_run(); -
} -
else -
{ -
fgauge_algo_run(); -
return gFG_capacity_by_c; // hw fg, //return gfg_percent_check_point; // voltage mode -
} -
#endif -
/*// -
6582 平台用的计量方法【在 Battery_Charging_Introduction_for_customer_V1.0.pdf】 -
SW FG算法和HW FG算法。事实上MTK平台项目通常采用的是混合型算法。 */ -
#if defined(SOC_BY_SW_FG) -
oam_run(); -
void oam_run(void) -
{ -
/* SW FG的核心 在于 通过两种方式更新电压,去逼近真实开路电压 最终查表获取近似真实的电量值。 -
ocv1 被假定为开路电压 -
ocv2则是闭路电压, -
D0 D1 D2 D3 D4 D5 代表不同的放电深度*/ -
int vol_bat=0; -
//int vol_bat_hw_ocv=0; -
//int d_hw_ocv=0; -
int charging_current=0; -
int ret=0; -
//kal_uint32 now_time; -
struct timespec now_time; -
kal_int32 delta_time = 0; -
//now_time = rtc_read_hw_time(); -
getrawmonotonic(&now_time); -
//delta_time = now_time - last_oam_run_time; -
delta_time = now_time.tv_sec - last_oam_run_time.tv_sec; -
bm_print(BM_LOG_FULL, "[oam_run_time] last time=%d, now time=%d, delta time=%d\n", -
last_oam_run_time.tv_sec, now_time.tv_sec, delta_time); -
last_oam_run_time = now_time; -
// Reconstruct table if temp changed; -
fgauge_construct_table_by_temp(); -
void fgauge_construct_table_by_temp(void) -
{ -
#if defined(CONFIG_POWER_EXT) -
#else -
kal_uint32 i; -
static kal_int32 init_temp = KAL_TRUE; -
static kal_int32 curr_temp, last_temp, avg_temp; -
static kal_int32 battTempBuffer[TEMP_AVERAGE_SIZE]; -
static kal_int32 temperature_sum; -
static kal_uint8 tempIndex = 0; -
/* 通过获得当前 NTC 电压,查表并进行线性插值法,得到当前的温度值 */ -
curr_temp = battery_meter_get_battery_temperature(); -
// Temperature window init -
if (init_temp == KAL_TRUE) -
{ -
for (i=0; i<TEMP_AVERAGE_SIZE; i++) -
{ -
battTempBuffer[i] = curr_temp; -
} -
last_temp = curr_temp; -
temperature_sum = curr_temp * TEMP_AVERAGE_SIZE; -
init_temp = KAL_FALSE; -
} -
// Temperature sliding window -
temperature_sum -= battTempBuffer[tempIndex]; -
temperature_sum += curr_temp; -
battTempBuffer[tempIndex] = curr_temp; -
avg_temp = (temperature_sum)/TEMP_AVERAGE_SIZE; -
if (avg_temp != last_temp) -
{ -
bm_print(BM_LOG_FULL, "[fgauge_construct_table_by_temp] reconstruct table by temperature change from (%d) to (%d)\r\n", last_temp, avg_temp); -
/* 获得 温度-电池内阻 表格*/ -
fgauge_construct_r_table_profile(curr_temp, fgauge_get_profile_r_table(TEMPERATURE_T)); -
/* 由当前温度,通过 温度-电池容量表格,获得对应的 温度-电池容量 数据, -
即能得到当前温度所对应的用掉的电池容量 */ -
fgauge_construct_battery_profile(curr_temp, fgauge_get_profile(TEMPERATURE_T)); -
last_temp = avg_temp; -
} -
tempIndex = (tempIndex+1)%TEMP_AVERAGE_SIZE; -
#endif -
} -
vol_bat = 15; //set avg times -
/* 获得 PMIC 的 BATSNS 寄存器值 -
这里获得 v_bat 当前电池电压值,这是有负载时的电压值 */ -
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_SENSE, &vol_bat); -
read_adc_v_bat_sense(void *data) -
*(kal_int32*)(data) = PMIC_IMM_GetOneChannelValue(VBAT_CHANNEL_NUMBER,*(kal_int32*)(data),1); -
//ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_OCV, &vol_bat_hw_ocv); -
//d_hw_ocv = fgauge_read_d_by_v(vol_bat_hw_ocv); -
/* 通过当前开路电压 - 负载时电压 = 当前电流 * 电池内阻 -
获得当前电流值 */ -
oam_i_1 = (((oam_v_ocv_1-vol_bat)*1000)*10) / oam_r_1; //0.1mA -
oam_i_2 = (((oam_v_ocv_2-vol_bat)*1000)*10) / oam_r_2; //0.1mA -
/* 当前的变化电量值 = 当前电流 * 上次运行此函数到现在的时间 + 上次的电量值 */ -
oam_car_1 = (oam_i_1*delta_time/3600) + oam_car_1; //0.1mAh -
oam_car_2 = (oam_i_2*delta_time/3600) + oam_car_2; //0.1mAh -
/* 这里使用的就是库伦积分法: -
D1 = D0 + (-CAR)/Cmax -
获得当前的电池容量百分比 */ -
oam_d_1 = oam_d0 + (oam_car_1*100/10)/gFG_BATT_CAPACITY_aging; // gFG_BATT_CAPACITY_aging: 当前温度对应的最大电池容量 -
if(oam_d_1 < 0) oam_d_1 = 0; -
if(oam_d_1 > 100) oam_d_1 = 100; -
oam_d_2 = oam_d0 + (oam_car_2*100/10)/gFG_BATT_CAPACITY_aging; -
if(oam_d_2 < 0) oam_d_2 = 0; -
if(oam_d_2 > 100) oam_d_2 = 100; -
/*// -
// 整个程序的核心在这里, 他使用了两种方法更新电量: -
1. 使用补偿过的闭路电压,查表获得电量 【返回给用户的】 -
2. 使用软件库伦积分,得到电量值 【用来校正的】 -
两个方法相对独立,但是在此处,方法 1 使用了 方法 2 的电流来进行较正!!!!!!!!!! -
// -
mtk_imp_tracking() 对闭合电压补偿后,当作开路电压使用 -
通过对当前有负载的电池电压进行补偿,获得当前开路电压 */ -
oam_v_ocv_1 = vol_bat + mtk_imp_tracking(vol_bat, oam_i_2, 5); -
// ============================================================ // SW FG -
// 这个里面返回的是 I*R 的值,即 当前电流 * 当前负载 -
kal_int32 mtk_imp_tracking(kal_int32 ori_voltage, kal_int32 ori_current, kal_int32 recursion_time) -
{ -
kal_int32 ret_compensate_value = 0; -
kal_int32 temp_voltage_1 = ori_voltage; // 闭路电压 -
kal_int32 temp_voltage_2 = temp_voltage_1; // 开路电压,第一次 = 闭路电压,后来都是补偿过 IR 的 -
int i = 0; -
/* 迭代 5 次,反复执行 闭合补偿得开路电压,开路电压查表得内阻,内阻补偿闭路电压 */ -
for(i=0 ; i < recursion_time ; i++) -
{ -
/* 将闭路电压当做开路电压查内阻 */ -
gFG_resistance_bat = fgauge_read_r_bat_by_v(temp_voltage_2); -
/* 算出 IR drop */ -
ret_compensate_value = ( (ori_current) * (gFG_resistance_bat + R_FG_VALUE)) / 1000; -
// ret_compensate是int型变量 做除法时取整处理 会引入较大误差, 加上这个值使结果四舍五入 -
ret_compensate_value = (ret_compensate_value+(10/2)) / 10; -
/* 开路电压 = 当前电压 + IR drop */ -
temp_voltage_2 = temp_voltage_1 + ret_compensate_value; -
bm_print(BM_LOG_FULL, "[mtk_imp_tracking] temp_voltage_2=%d,temp_voltage_1=%d,ret_compensate_value=%d,gFG_resistance_bat=%d\n", -
temp_voltage_2,temp_voltage_1,ret_compensate_value,gFG_resistance_bat); -
} -
/* 通过上面获得的开路电压查找最终内阻 */ -
gFG_resistance_bat = fgauge_read_r_bat_by_v(temp_voltage_2); -
/* 算出 IR drop */ -
ret_compensate_value = ( (ori_current) * (gFG_resistance_bat + R_FG_VALUE + FG_METER_RESISTANCE)) / 1000; -
/* 四舍五入 */ -
ret_compensate_value = (ret_compensate_value+(10/2)) / 10; -
gFG_compensate_value = ret_compensate_value; // I*R 补偿负载 -
bm_print(BM_LOG_FULL, "[mtk_imp_tracking] temp_voltage_2=%d,temp_voltage_1=%d,ret_compensate_value=%d,gFG_resistance_bat=%d\n", -
temp_voltage_2,temp_voltage_1,ret_compensate_value,gFG_resistance_bat); -
/* 该内阻 R* 电流 I 算出最终的电压补偿值 V -
Vbat 是闭路电压 -
SW ocv 是开路电压 -
Sw ocv = V + Vbat -
*/ -
return ret_compensate_value; -
} -
/* 通过补偿的开路电压,获得电池电量百分比 */ -
oam_d_3 = fgauge_read_d_by_v(oam_v_ocv_1); -
if(oam_d_3 < 0) oam_d_3 = 0; -
if(oam_d_3 > 100) oam_d_3 = 100; -
/* 通过开路电压,获得电池内阻 */ -
oam_r_1 = fgauge_read_r_bat_by_v(oam_v_ocv_1); -
/* 通过库伦积分获得的电池容量百分比,来获得电池开路电压*/ -
oam_v_ocv_2 = fgauge_read_v_by_d(oam_d_2); -
/* 通过开路电压,获得电池内阻 */ -
oam_r_2 = fgauge_read_r_bat_by_v(oam_v_ocv_2); -
#if 0 -
oam_d_4 = (oam_d_2+oam_d_3)/2; -
#else -
oam_d_4 = oam_d_3; -
#endif -
// 从上一次运行本函数到现在当前电量变化的值 -
gFG_columb = oam_car_2/10; //mAh -
/* 判断充电状态 */ -
if( (oam_i_1 < 0) || (oam_i_2 < 0) ) -
gFG_Is_Charging = KAL_TRUE; -
else -
gFG_Is_Charging = KAL_FALSE; -
#if 0 -
if(gFG_Is_Charging == KAL_FALSE) -
{ -
d5_count_time = 60; -
} -
else -
{ -
charging_current = get_charging_setting_current(); -
charging_current = charging_current / 100; -
d5_count_time_rate = (((gFG_BATT_CAPACITY_aging*60*60/100/(charging_current-50))*10)+5)/10; -
if(d5_count_time_rate < 1) -
d5_count_time_rate = 1; -
d5_count_time = d5_count_time_rate; -
} -
#else -
d5_count_time = 60; -
#endif -
/ -
// D5 与 D3 对比 -
/* 对获得的 D3 进行优化,有 1min 的限制,不会跳变,电量变化更平滑 -
1分钟内电量值不会改变,且每分钟电量的变化不会大于1%,这样用户体验会比较好。 -
防止因为低电压时陡峭的电量曲线,以及比较耗电的应用,或突然的大电流引起的电量跳变。 -
当然特殊应用下应该取消这个功能,否则会带来电量变化延时等问题*/ -
if(d5_count >= d5_count_time) -
// 60s 执行一次 -
{ -
/* 限制电量变化,每 1 分钟,只能变化 1% */ -
/* 放电状态 */ -
if(gFG_Is_Charging == KAL_FALSE) -
{ -
if( oam_d_3 > oam_d_5 ) -
{ -
oam_d_5 = oam_d_5 + 1; -
} -
else -
{ -
if(oam_d_4 > oam_d_5) -
{ -
oam_d_5 = oam_d_5 + 1; -
} -
} -
} -
/* 充电状态 */ -
else -
{ -
if( oam_d_5 > oam_d_3 ) -
{ -
oam_d_5 = oam_d_5 - 1; -
} -
else -
{ -
if(oam_d_4 < oam_d_5) -
{ -
oam_d_5 = oam_d_5 - 1; -
} -
} -
} -
d5_count = 0; -
oam_d_3_pre = oam_d_3; -
oam_d_4_pre = oam_d_4; -
} -
else -
// 10s 执行一次本函数 -
{ -
d5_count = d5_count + 10; -
} -
bm_print(BM_LOG_CRTI, "[oam_run] %d,%d,%d,%d,%d,%d,%d,%d\n", -
d5_count, d5_count_time, oam_d_3_pre, oam_d_3, oam_d_4_pre, oam_d_4, oam_d_5, charging_current); -
if(oam_run_i == 0) -
{ -
bm_print(BM_LOG_FULL, "[oam_run] oam_i_1,oam_i_2,oam_car_1,oam_car_2,oam_d_1,oam_d_2,oam_v_ocv_1,oam_d_3,oam_r_1,oam_v_ocv_2,oam_r_2,vol_bat,g_vol_bat_hw_ocv,g_d_hw_ocv\n"); -
oam_run_i=1; -
} -
bm_print(BM_LOG_FULL, "[oam_run] %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", -
oam_i_1,oam_i_2,oam_car_1,oam_car_2,oam_d_1,oam_d_2,oam_v_ocv_1,oam_d_3,oam_r_1,oam_v_ocv_2,oam_r_2,vol_bat,g_vol_bat_hw_ocv,g_d_hw_ocv); -
bm_print(BM_LOG_FULL, "[oam_total] %d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", -
gFG_capacity_by_c, gFG_capacity_by_v, gfg_percent_check_point, -
oam_d_1, oam_d_2, oam_d_3, oam_d_4, oam_d_5, gFG_capacity_by_c_init, g_d_hw_ocv); -
bm_print(BM_LOG_CRTI, "[oam_total_s] %d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", -
gFG_capacity_by_c, // 1 -
gFG_capacity_by_v, // 2 -
gfg_percent_check_point, // 3 -
(100-oam_d_1), // 4 -
(100-oam_d_2), // 5 -
(100-oam_d_3), // 6 -
(100-oam_d_4), // 9 -
(100-oam_d_5), // 10 -
gFG_capacity_by_c_init, // 7 -
(100-g_d_hw_ocv) // 8 -
); -
bm_print(BM_LOG_FULL, "[oam_total_s_err] %d,%d,%d,%d,%d,%d,%d\n", -
(gFG_capacity_by_c - gFG_capacity_by_v), -
(gFG_capacity_by_c - gfg_percent_check_point), -
(gFG_capacity_by_c - (100-oam_d_1)), -
(gFG_capacity_by_c - (100-oam_d_2)), -
(gFG_capacity_by_c - (100-oam_d_3)), -
(gFG_capacity_by_c - (100-oam_d_4)), -
(gFG_capacity_by_c - (100-oam_d_5)) -
); -
bm_print(BM_LOG_CRTI, "[oam_init_inf] %d, %d, %d, %d, %d, %d\n", -
gFG_voltage, (100 - fgauge_read_capacity_by_v(gFG_voltage)), g_rtc_fg_soc, gFG_DOD0 ,oam_v_ocv_init, force_get_tbat()); -
bm_print(BM_LOG_CRTI, "[oam_run_inf] %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n", -
oam_v_ocv_1,oam_v_ocv_2,vol_bat,oam_i_1,oam_i_2,oam_r_1,oam_r_2,oam_car_1,oam_car_2,gFG_BATT_CAPACITY_aging,force_get_tbat(), oam_d0); -
bm_print(BM_LOG_CRTI, "[oam_result_inf] %d, %d, %d, %d, %d, %d\n", -
oam_d_1, oam_d_2, oam_d_3, oam_d_4, oam_d_5, BMT_status.UI_SOC); -
} -
// 这边的返回值将填充BMT_status.SOC ,这个参数再经过优化得到BMT_status.UI_SOC就是菜单栏看到的电池电量了。 -
// -
/* D5 是做过平滑,每 1min 电量变化只能是 1% 的,可能会有延时 */ -
#if (OAM_D5 == 1) -
return (100-oam_d_5); -
#else -
/* D2 则是原版的,没有做平滑处理,电量变化可能会跳变,但是变化及时 */ -
return (100-oam_d_2); -
#endif -
#endif -
#endif -
} -
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(); -
return gFG_voltage; // 返回 hw ocv 电压 -
/* 更新电池状态 */ -
BMT_status.ICharging = mt_battery_average_method(&batteryCurrentBuffer[0],ICharging, &icharging_sum, batteryIndex); -
BMT_status.bat_vol = mt_battery_average_method(&batteryVoltageBuffer[0],bat_vol, &bat_sum, batteryIndex); -
BMT_status.temperature = mt_battery_average_method(&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; -
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; -
battery_xlog_printk(BAT_LOG_CRTI, "AvgVbat=(%d),bat_vol=(%d),AvgI=(%d),I=(%d),VChr=(%d),AvgT=(%d),T=(%d),pre_SOC=(%d),SOC=(%d),ZCV=(%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.ZCV); -
} -
// 3. 电池温度保护 -
/* 电池温度检查,如果温度超过 60 度,关机重启 */ -
mt_battery_thermal_check(); -
static void mt_battery_thermal_check(void) -
{ -
if( (g_battery_thermal_throttling_flag==1) || (g_battery_thermal_throttling_flag==3) ) -
{ -
if(battery_cmd_thermal_test_mode == 1){ -
BMT_status.temperature = battery_cmd_thermal_test_mode_value; -
battery_xlog_printk(BAT_LOG_FULL, "[Battery] In thermal_test_mode , Tbat=%d\n", BMT_status.temperature); -
} -
#if defined(MTK_JEITA_STANDARD_SUPPORT) -
//ignore default rule -
#else -
if(BMT_status.temperature >= 60) -
{ -
#if defined(CONFIG_POWER_EXT) -
battery_xlog_printk(BAT_LOG_CRTI, "[BATTERY] CONFIG_POWER_EXT, no update battery update power down.\n"); -
#else -
{ -
if( (g_platform_boot_mode==META_BOOT) || (g_platform_boot_mode==ADVMETA_BOOT) || (g_platform_boot_mode==ATE_FACTORY_BOOT) ) -
{ -
battery_xlog_printk(BAT_LOG_FULL, "[BATTERY] boot mode = %d, bypass temperature check\n", g_platform_boot_mode); -
} -
else -
// 正常启动的话,超过温度,系统重启 -
{ -
struct battery_data *bat_data = &battery_main; -
struct power_supply *bat_psy = &bat_data->psy; -
battery_xlog_printk(BAT_LOG_CRTI, "[Battery] Tbat(%d)>=60, system need power down.\n", BMT_status.temperature); -
bat_data->BAT_CAPACITY = 0; -
power_supply_changed(bat_psy); -
if( BMT_status.charger_exist == KAL_TRUE ) -
{ -
// can not power down due to charger exist, so need reset system -
//battery_charging_control(CHARGING_CMD_SET_PLATFORM_RESET,NULL); -
} -
//avoid SW no feedback -
battery_charging_control(CHARGING_CMD_SET_POWER_OFF,NULL); -
static kal_uint32 charging_set_power_off(void *data) -
{ -
kal_uint32 status = STATUS_OK; -
battery_xlog_printk(BAT_LOG_CRTI, "charging_set_power_off=%d\n"); -
/* */ -
mt_power_off(); -
void mt_power_off(void) -
{ -
printk("mt_power_off\n"); -
/* pull PWRBB low */ -
rtc_bbpu_power_down(); -
void rtc_bbpu_power_down(void) -
{ -
unsigned long flags; -
spin_lock_irqsave(&rtc_lock, flags); -
hal_rtc_bbpu_pwdn(); -
spin_unlock_irqrestore(&rtc_lock, flags); -
} -
while (1) { -
#if defined(CONFIG_POWER_EXT) -
//EVB -
printk("EVB without charger\n"); -
#else -
//Phone -
printk("Phone with charger\n"); -
if (pmic_chrdet_status() == KAL_TRUE) -
arch_reset(0, "power_off_with_charger"); -
#endif -
} -
} -
return status; -
} -
//mt_power_off(); -
} -
} -
#endif -
} -
#endif -
} -
} -
/ -
// 4. 电池状态检查 -
/* 对电池状态进行检查,如果有问题,则会调用 printk() 进行打印 */ -
mt_battery_notify_check(); -
void mt_battery_notify_check(void) -
{ -
g_BatteryNotifyCode = 0x0000; -
if(g_BN_TestMode == 0x0000) /* for normal case */ -
{ -
battery_xlog_printk(BAT_LOG_FULL, "[BATTERY] mt_battery_notify_check\n"); -
mt_battery_notify_VCharger_check(); -
mt_battery_notify_VBatTemp_check(); -
mt_battery_notify_ICharging_check(); -
mt_battery_notify_VBat_check(); -
mt_battery_notify_TatalChargingTime_check(); -
} -
else /* for UI test */ -
{ -
mt_battery_notify_UI_test(); -
} -
} -
// -
// 5. 调用具本的硬件相关函数进行充电,充电时会进行 CC/CV 之类的状态机切换就是在这里进行的 -
/* 如果存在充电线,则调用具体充电芯片相关的函数进行充电 */ -
if( BMT_status.charger_exist == KAL_TRUE ) -
{ -
/* 检查电池状态,设置到 BMT_status.bat_charging_state 中 */ -
mt_battery_CheckBatteryStatus(); -
/* 充电策略,这里有两个文件: switch_charging.c 和 linear_charging.c -
他们的关系是,如果定义了任一外部充电 IC,则选择 switch_charging.c 的函数,否则就是 linear_charging.c 的函数 -
这里就是调用具体的芯片的充电相关函数进行充电 */ -
mt_battery_charging_algorithm(); -
void mt_battery_charging_algorithm() -
{ -
switch(BMT_status.bat_charging_state) -
{ -
case CHR_PRE : -
BAT_PreChargeModeAction(); -
break; -
case CHR_CC : -
BAT_ConstantCurrentModeAction(); -
break; -
case CHR_TOP_OFF : -
BAT_TopOffModeAction(); -
break; -
case CHR_BATFULL: -
BAT_BatteryFullAction(); -
break; -
case CHR_HOLD: -
BAT_BatteryHoldAction(); -
break; -
case CHR_ERROR: -
BAT_BatteryStatusFailAction(); -
break; -
} -
} -
} -
/// -
// 6. 更新电池显示状态 -
/* 更新设置节点的内容: -
/sys/class/power_supply/下的文件夹 -
wireless_main -
battery_main -
ac_main -
usb_main -
*/ -
mt_battery_update_status(); -
static void mt_battery_update_status(void) -
{ -
#if defined(CONFIG_POWER_EXT) -
battery_xlog_printk(BAT_LOG_CRTI, "[BATTERY] CONFIG_POWER_EXT, no update Android.\n"); -
#else -
{ -
wireless_update(&wireless_main); -
battery_update(&battery_main); -
ac_update(&ac_main); -
usb_update(&usb_main); -
} -
#endif -
} -
} -
mutex_unlock(&bat_mutex); -
battery_xlog_printk(BAT_LOG_FULL, "wait event \n" ); -
/* 睡眠等待唤醒 */ -
wait_event(bat_thread_wq, (bat_thread_timeout == KAL_TRUE)); -
bat_thread_timeout = KAL_FALSE; -
/* 每 10s 启动一次 */ -
hrtimer_start(&battery_kthread_timer, ktime, HRTIMER_MODE_REL); -
ktime = ktime_set(BAT_TASK_PERIOD, 0); // 10s, 10* 1000 ms -
/* 如果有充电线插入且 xxx */ -
if( chr_wake_up_bat == KAL_TRUE && g_smartbook_update != 1) // for charger plug in/ out -
{ -
g_smartbook_update = 0; -
/* 重新计算当前电池电量,复位 oam 算法相关参数 */ -
battery_meter_reset(); -
kal_int32 battery_meter_reset(void) -
{ -
#if defined(CONFIG_POWER_EXT) -
return 0; -
#else -
/* 获得 ui 显示的百分比 */ -
kal_uint32 ui_percentage = bat_get_ui_percentage(); -
kal_uint32 bat_get_ui_percentage(void) -
{ -
// for plugging out charger in recharge phase, using SOC as UI_SOC -
if(chr_wake_up_bat == KAL_TRUE) -
return BMT_status.SOC; -
else -
return BMT_status.UI_SOC; -
// typedef struct -
// { -
// kal_bool bat_exist; -
// kal_bool bat_full; // 电池是否充满标志 -
// INT32 bat_charging_state; -
// UINT32 bat_vol; -
// kal_bool bat_in_recharging_state; -
// kal_uint32 Vsense; -
// kal_bool charger_exist; -
// UINT32 charger_vol; -
// INT32 charger_protect_status; -
// INT32 ICharging; -
// INT32 IBattery; -
// INT32 temperature; -
// INT32 temperatureR; -
// INT32 temperatureV; -
// UINT32 total_charging_time; -
// UINT32 PRE_charging_time; -
// UINT32 CC_charging_time; -
// UINT32 TOPOFF_charging_time; -
// UINT32 POSTFULL_charging_time; -
// UINT32 charger_type; -
// INT32 SOC; -
// INT32 UI_SOC; // ui 显示电量百分比 -
// UINT32 nPercent_ZCV; -
// UINT32 nPrecent_UI_SOC_check_point; -
// UINT32 ZCV; -
// } PMU_ChargerStruct; -
} -
/* -
// 如果电池充满了,则更新电池最大容量 */ -
if(bat_is_charging_full() == KAL_TRUE) // charge full -
// 判断电池是否充满 -
kal_bool bat_is_charging_full(void) -
{ -
if((BMT_status.bat_full == KAL_TRUE) && (BMT_status.bat_in_recharging_state == KAL_FALSE)) -
return KAL_TRUE; -
else -
return KAL_FALSE; -
} -
{ -
/* 如果 fg_qmax_update_for_aging_flag == 1 -
则更新电池电容量,并将 fg_qmax_update_for_aging_flag 置为 0 */ -
if(fg_qmax_update_for_aging_flag == 1) -
{ -
fg_qmax_update_for_aging(); -
void fg_qmax_update_for_aging(void) -
{ -
#if defined(CONFIG_POWER_EXT) -
#else -
kal_bool hw_charging_done = bat_is_charging_full(); -
/* 如果电池充满了,更新电池最大容量 */ -
if(hw_charging_done == KAL_TRUE) // charging full, g_HW_Charging_Done == 1 -
{ -
/* gFG_DOD0 应该是 100%-ui 显示百分比 -
即当前使用完的容量百分比 */ -
if(gFG_DOD0 > 85) -
{ -
// 表示在放电 -
if(gFG_columb < 0) // gFG_columb: 从上一次运行本函数到现在当前电量变化的值 -
gFG_columb = gFG_columb - gFG_columb*2; // absolute value -
gFG_BATT_CAPACITY_aging = ( ( (gFG_columb*1000)+(5*gFG_DOD0) ) / gFG_DOD0 ) / 10; // gFG_BATT_CAPACITY_aging: 当前温度电池最大容量 -
// tuning -
gFG_BATT_CAPACITY_aging = (gFG_BATT_CAPACITY_aging * 100) / AGING_TUNING_VALUE; -
/* 如果当前电池容量值为 0 */ -
if(gFG_BATT_CAPACITY_aging == 0) -
{ -
/* 先通过 battery_meter_get_battery_temperature() 获得电池温度,再通过 fgauge_get_Q_max() 计算电量 -
这里获得当前电池的容量 */ -
gFG_BATT_CAPACITY_aging = fgauge_get_Q_max(battery_meter_get_battery_temperature()); -
bm_print(BM_LOG_CRTI, "[fg_qmax_update_for_aging] error, restore gFG_BATT_CAPACITY_aging (%d)\n", gFG_BATT_CAPACITY_aging); -
} -
bm_print(BM_LOG_CRTI, "[fg_qmax_update_for_aging] need update : gFG_columb=%d, gFG_DOD0=%d, new_qmax=%d\r\n", -
gFG_columb, gFG_DOD0, gFG_BATT_CAPACITY_aging); -
} -
else -
{ -
bm_print(BM_LOG_CRTI, "[fg_qmax_update_for_aging] no update : gFG_columb=%d, gFG_DOD0=%d, new_qmax=%d\r\n", -
gFG_columb, gFG_DOD0, gFG_BATT_CAPACITY_aging); -
} -
} -
/* 如果电池未充满 */ -
else -
{ -
bm_print(BM_LOG_CRTI, "[fg_qmax_update_for_aging] hw_charging_done=%d\r\n", hw_charging_done); -
} -
#endif -
} -
fg_qmax_update_for_aging_flag=0; -
} -
} -
/* car: 库伦计的缩写 -
这里是复位库伦计 */ -
reset_parameter_car(); -
void reset_parameter_car(void) -
{ -
#if defined(SOC_BY_HW_FG) -
int ret = 0; -
/* 调用对应充电芯片的操作函数,复位硬件,这里对应 PMIC 的函数为 */ -
ret = battery_meter_ctrl(BATTERY_METER_CMD_HW_RESET, NULL); -
static kal_int32 fgauge_hw_reset//(void *data) -
{ -
return STATUS_OK; -
} -
gFG_columb = 0; -
#endif -
#if defined(SOC_BY_SW_FG) -
oam_car_1 = 0; -
oam_car_2 = 0; -
gFG_columb = 0; -
#endif -
} -
/* DOD: DOD: 放电深度,100-DOD 即电容容量 */ -
reset_parameter_dod_full(ui_percentage); -
void reset_parameter_dod_full(kal_uint32 ui_percentage) -
{ -
#if defined(SOC_BY_HW_FG) -
bm_print(BM_LOG_CRTI, "[battery_meter_reset]1 DOD0=%d,DOD1=%d,ui=%d\n", gFG_DOD0, gFG_DOD1, ui_percentage); -
gFG_DOD0 = 100 - ui_percentage; -
gFG_DOD1 = gFG_DOD0; -
bm_print(BM_LOG_CRTI, "[battery_meter_reset]2 DOD0=%d,DOD1=%d,ui=%d\n", gFG_DOD0, gFG_DOD1, ui_percentage); -
#endif -
// 我们用的是这种,软件库伦积分 -
#if defined(SOC_BY_SW_FG) -
bm_print(BM_LOG_CRTI, "[battery_meter_reset]1 oam_d0=%d,oam_d_5=%d,ui=%d\n", oam_d0, oam_d_5, ui_percentage); -
oam_d0 = 100 - ui_percentage; -
gFG_DOD0 = oam_d0; -
gFG_DOD1 = oam_d0; -
oam_d_1 = oam_d0; -
oam_d_2 = oam_d0; -
oam_d_3 = oam_d0; -
oam_d_4 = oam_d0; -
oam_d_5 = oam_d0; // 相当于平滑处理过的 D3 -
bm_print(BM_LOG_CRTI, "[battery_meter_reset]2 oam_d0=%d,oam_d_5=%d,ui=%d\n", oam_d0, oam_d_5, ui_percentage); -
#endif -
} -
return 0; -
#endif -
} -
chr_wake_up_bat = KAL_FALSE; -
battery_xlog_printk(BAT_LOG_CRTI, "[BATTERY] Charger plug in/out, Call battery_meter_reset. (%d)\n", BMT_status.UI_SOC); -
} -
} -
return 0; -
} -
battery_xlog_printk(BAT_LOG_CRTI, "[battery_probe] bat_thread_kthread Done\n"); -
// 电池过充保护相关检测与初始化,他 2s 检测一次 -
charger_hv_detect_sw_workaround_init(); -
void charger_hv_detect_sw_workaround_init(void) -
{ -
ktime_t ktime; -
ktime = ktime_set(0, BAT_MS_TO_NS(2000)); -
hrtimer_init(&charger_hv_detect_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); -
charger_hv_detect_timer.function = charger_hv_detect_sw_workaround; -
hrtimer_start(&charger_hv_detect_timer, ktime, HRTIMER_MODE_REL); -
// 这个函数是周期来检查电池电压是否超出限制,即过充保护,超出了就不能充电了 -
charger_hv_detect_thread = kthread_run(charger_hv_detect_sw_thread_handler, 0, "mtk charger_hv_detect_sw_workaround"); -
// 这个函数是周期来检查电池电压是否超出限制,即过充保护,超出了就不能充电了 -
int charger_hv_detect_sw_thread_handler(void *unused) -
{ -
ktime_t ktime; -
kal_uint32 charging_enable; -
kal_uint32 hv_voltage = BATTERY_VOLT_07_000000_V; -
kal_bool hv_status; -
do -
{ -
ktime = ktime_set(0, BAT_MS_TO_NS(2000)); -
if(chargin_hw_init_done) -
/* 高压检测,应该是电池超过这个电压时,就不可以充电了 */ -
battery_charging_control(CHARGING_CMD_SET_HV_THRESHOLD,&hv_voltage); -
static kal_uint32 charging_set_hv_threshold(void *data) -
{ -
kal_uint32 status = STATUS_OK; -
kal_uint32 set_hv_voltage; -
kal_uint32 array_size; -
kal_uint16 register_value; -
kal_uint32 voltage = *(kal_uint32*)(data); -
array_size = GETARRAYNUM(VCDT_HV_VTH); -
set_hv_voltage = bmt_find_closest_level(VCDT_HV_VTH, array_size, voltage); -
register_value = charging_parameter_to_value(VCDT_HV_VTH, array_size ,set_hv_voltage); -
/* 设置 PMIC 的 CHR_CON1 */ -
upmu_set_rg_vcdt_hv_vth(register_value); -
return status; -
} -
wait_event_interruptible(charger_hv_detect_waiter, (charger_hv_detect_flag == KAL_TRUE)); -
/* 如果检测到充电器,则检测下电池是否存在 */ -
if ((upmu_is_chr_det() == KAL_TRUE)) -
{ -
/* 检测电池是否存在 */ -
check_battery_exist(); -
void check_battery_exist(void) -
{ -
#if defined(CONFIG_DIS_CHECK_BATTERY) -
battery_xlog_printk(BAT_LOG_CRTI, "[BATTERY] Disable check battery exist.\n"); -
#else -
kal_uint32 baton_count = 0; -
kal_uint32 charging_enable = KAL_FALSE; -
kal_uint32 battery_status; -
kal_uint32 i; -
for(i=0;i<3;i++) -
{ -
/* 检测电池是否存在,通过读取 PMIC 的 CHR_CON7 */ -
battery_charging_control(CHARGING_CMD_GET_BATTERY_STATUS,&battery_status); -
static kal_uint32 charging_get_battery_status(void *data) -
{ -
kal_uint32 status = STATUS_OK; -
upmu_set_baton_tdet_en(1); -
upmu_set_rg_baton_en(1); -
*(kal_bool*)(data) = upmu_get_rgs_baton_undet(); -
return status; -
} -
baton_count += battery_status; -
} -
if( baton_count >= 3) -
{ -
if( (g_platform_boot_mode==META_BOOT) || (g_platform_boot_mode==ADVMETA_BOOT) || (g_platform_boot_mode==ATE_FACTORY_BOOT) ) -
{ -
battery_xlog_printk(BAT_LOG_FULL, "[BATTERY] boot mode = %d, bypass battery check\n", g_platform_boot_mode); -
} -
else -
{ -
battery_xlog_printk(BAT_LOG_FULL, "[BATTERY] Battery is not exist, power off FAN5405 and system (%d)\n", baton_count); -
//battery_charging_control(CHARGING_CMD_ENABLE,&charging_enable); -
//battery_charging_control(CHARGING_CMD_SET_PLATFORM_RESET,NULL); -
} -
} -
#endif -
} -
} -
charger_hv_detect_flag = KAL_FALSE; -
if(chargin_hw_init_done) -
/* 查看 PMIC 是否开启了高压保护? */ -
battery_charging_control(CHARGING_CMD_GET_HV_STATUS,&hv_status); -
static kal_uint32 charging_get_hv_status(void *data) -
{ -
kal_uint32 status = STATUS_OK; -
*(kal_bool*)(data) = upmu_get_rgs_vcdt_hv_det(); -
return status; -
} -
if(hv_status == KAL_TRUE) -
{ -
battery_xlog_printk(BAT_LOG_CRTI, "[charger_hv_detect_sw_thread_handler] charger hv\n"); -
charging_enable = KAL_FALSE; -
if(chargin_hw_init_done) -
battery_charging_control(CHARGING_CMD_ENABLE,&charging_enable); -
} -
else -
{ -
battery_xlog_printk(BAT_LOG_FULL, "[charger_hv_detect_sw_thread_handler] upmu_chr_get_vcdt_hv_det() != 1\n"); -
} -
if(chargin_hw_init_done) -
battery_charging_control(CHARGING_CMD_RESET_WATCH_DOG_TIMER,NULL); -
hrtimer_start(&charger_hv_detect_timer, ktime, HRTIMER_MODE_REL); -
} while (!kthread_should_stop()); -
return 0; -
} -
if (IS_ERR(charger_hv_detect_thread)) -
{ -
battery_xlog_printk(BAT_LOG_FULL, "[%s]: failed to create charger_hv_detect_sw_workaround thread\n", __FUNCTION__); -
} -
battery_xlog_printk(BAT_LOG_CRTI, "charger_hv_detect_sw_workaround_init : done\n" ); -
} -
/*LOG System Set*/ -
init_proc_log(); -
#endif -
g_bat_init_flag = KAL_TRUE; -
return 0; -
} -
// 第二个调用的 probe -
static int mt_batteryNotify_probe(struct platform_device *dev) -
{ -
int ret_device_file = 0; -
//struct proc_dir_entry *entry = NULL; -
struct proc_dir_entry *battery_dir = NULL; -
battery_xlog_printk(BAT_LOG_CRTI, "******** mt_batteryNotify_probe!! ********\n" ); -
ret_device_file = device_create_file(&(dev->dev), &dev_attr_BatteryNotify); -
ret_device_file = device_create_file(&(dev->dev), &dev_attr_BN_TestMode); -
battery_dir = proc_mkdir("mtk_battery_cmd", NULL); -
if (!battery_dir) -
{ -
pr_err("[%s]: mkdir /proc/mtk_battery_cmd failed\n", __FUNCTION__); -
} -
else -
{ -
#if 1 -
proc_create("battery_cmd", S_IRUGO | S_IWUSR, battery_dir, &battery_cmd_proc_fops); -
battery_xlog_printk(BAT_LOG_CRTI, "proc_create battery_cmd_proc_fops\n"); -
#else -
entry = create_proc_entry("battery_cmd", S_IRUGO | S_IWUSR, battery_dir); -
if (entry) -
{ -
entry->read_proc = battery_cmd_read; -
entry->write_proc = battery_cmd_write; -
} -
#endif -
} -
battery_xlog_printk(BAT_LOG_CRTI, "******** mtk_battery_cmd!! ********\n" ); -
return 0; -
} -
// 电池测量模块初始化 -
module_init(battery_meter_init); -
static int __init battery_meter_init(void) -
{ -
int ret; -
ret = platform_device_register(&battery_meter_device); -
struct platform_device battery_meter_device = { -
.name = "battery_meter", -
.id = -1, -
}; -
if (ret) { -
bm_print(BM_LOG_CRTI, "[battery_meter_driver] Unable to device register(%d)\n", ret); -
return ret; -
} -
ret = platform_driver_register(&battery_meter_driver); -
static struct platform_driver battery_meter_driver = { -
.probe = battery_meter_probe, -
.remove = battery_meter_remove, -
.shutdown = battery_meter_shutdown, -
.suspend = battery_meter_suspend, -
.resume = battery_meter_resume, -
.driver = { -
.name = "battery_meter", -
}, -
}; -
if (ret) { -
bm_print(BM_LOG_CRTI, "[battery_meter_driver] Unable to register driver (%d)\n", ret); -
return ret; -
} -
bm_print(BM_LOG_CRTI, "[battery_meter_driver] Initialization : DONE \n"); -
return 0; -
} -
/ -
// 调用的 probe -
// ============================================================ // -
static int battery_meter_probe(struct platform_device *dev) -
{ -
int ret_device_file = 0; -
battery_meter_ctrl = bm_ctrl_cmd; -
bm_print(BM_LOG_CRTI, "[battery_meter_probe] probe\n"); -
//select battery meter control method -
battery_meter_ctrl = bm_ctrl_cmd; -
//LOG System Set -
init_proc_log_fg(); -
//last_oam_run_time = rtc_read_hw_time(); -
getrawmonotonic(&last_oam_run_time); -
//Create File For FG UI DEBUG -
ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_Current); -
ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_bat_volt); -
ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_bat_current); -
ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_bat_zcv); -
ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_bat_temp); -
ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_bat_r); -
ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_bat_car); -
ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_bat_qmax); -
ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_d0); -
ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_d1); -
ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_percentage); -
ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_percentage_fg); -
ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_percentage_voltmode); -
return 0; -
}
什么!还要了解?请看源码
地址:链接: 百度网盘 请输入提取码 密码: uiyb
2556

被折叠的 条评论
为什么被折叠?



