相关概念
懒的排版了,直接上图
相关文件关系
再来一发
杂项,电池温度检测原理图
发
充电流程
图样图森破
核心函数特写
-
/* 概念:
-
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