1、6739平台默认使用的是GM3.0的算法,在GM30里面有2个很重要的文件mtk_charger.c和mtk_battery.c文件
mtk_charger.c ------> 和以前battery_common.c 的功能类似,主要是和充电器有关
mtk_battery.c ------> 和以前的battery_meter.c 的功能有点类似,处理和电量显示和上层交互有关
2、充电线程的创建过程
mtk_charger.c 文件
mtk_charger_init
platform_driver_register(&charger_driver);
charger_driver
mtk_charger_probe函数里面
mtk_charger_parse_dt
info->polling_interval = CHARGING_INTERVAL; 这个值默认是10,用来设置线程唤醒的时间
mtk_charger_init_timer(info); 初始化了一个定时器
kthread_run(charger_routine_thread, info, “charger_thread”); 创建了一个线程
注释1:
#define CHARGING_INTERVAL 10
#define CHARGING_FULL_INTERVAL 20
3、mtk_charger_init_timer 初始化了一个定时器
static void mtk_charger_init_timer(struct charger_manager *info)
{
alarm_init(&info->charger_timer, ALARM_BOOTTIME,
mtk_charger_alarm_timer_func);
mtk_charger_start_timer(info);
#ifdef CONFIG_PM
if (register_pm_notifier(&charger_pm_notifier_func))
chr_err("%s: register pm failed\n", __func__);
#endif /* CONFIG_PM */
}
继续看下mtk_charger_start_timer,如何开启这个定时器的
在这个定时器开启之前设置了定时器定时的时间,在现在的基础上+10(CHARGING_INTERVAL )
static void mtk_charger_start_timer(struct charger_manager *info)
{
struct timespec time, time_now;
ktime_t ktime;
int ret = 0;
/* If the timer was already set, cancel it */
ret = alarm_try_to_cancel(&pinfo->charger_timer);
if (ret < 0) {
chr_err("%s: callback was running, skip timer\n", __func__);
return;
}
get_monotonic_boottime(&time_now);
time.tv_sec = info->polling_interval; 这里是不是看起来很熟悉呢,就是上面赋值的CHARGING_INTERVAL
time.tv_nsec = 0;
info->endtime = timespec_add(time_now, time);
ktime = ktime_set(info->endtime.tv_sec, info->endtime.tv_nsec);
chr_err("%s: alarm timer start:%d, %ld %ld\n", __func__, ret,
info->endtime.tv_sec, info->endtime.tv_nsec);
alarm_start(&pinfo->charger_timer, ktime);
}
看下这个定时器时间到了会做什么事?
static enum alarmtimer_restart
mtk_charger_alarm_timer_func(struct alarm *alarm, ktime_t now)
{
struct charger_manager *info =
container_of(alarm, struct charger_manager, charger_timer);
if (info->is_suspend == false) {
chr_err("%s: not suspend, wake up charger\n", __func__);
_wake_up_charger(info);
} else {
chr_err("%s: alarm timer timeout\n", __func__);
__pm_stay_awake(&info->charger_wakelock);
}
return ALARMTIMER_NORESTART;
}
返回来看下另外一个通知:register_pm_notifier(&charger_pm_notifier_func)
会唤醒充电的charger,从而让线程继续执行下去
static struct notifier_block charger_pm_notifier_func = {
.notifier_call = charger_pm_event,
.priority = 0,
};
static int charger_pm_event(struct notifier_block *notifier,
unsigned long pm_event, void *unused)
{
struct timespec now;
switch (pm_event) {
case PM_SUSPEND_PREPARE:
pinfo->is_suspend = true;
chr_debug("%s: enter PM_SUSPEND_PREPARE\n", __func__);
break;
case PM_POST_SUSPEND:
pinfo->is_suspend = false;
chr_debug("%s: enter PM_POST_SUSPEND\n", __func__);
get_monotonic_boottime(&now);
if (timespec_compare(&now, &pinfo->endtime) >= 0 &&
pinfo->endtime.tv_sec != 0 &&
pinfo->endtime.tv_nsec != 0) { 判断当前时间是否大于定时结束时间,如果大于了,就去唤醒charger
chr_err("%s: alarm timeout, wake up charger\n",
__func__);
__pm_relax(&pinfo->charger_wakelock);
pinfo->endtime.tv_sec = 0;
pinfo->endtime.tv_nsec = 0;
_wake_up_charger(pinfo); 这个会唤醒charger,很重要的调用
}
break;
default:
break;
}
return NOTIFY_DONE;
}
static inline int timespec_compare(const struct timespec *lhs, const struct timespec *rhs)
{
if (lhs->tv_sec < rhs->tv_sec)
return -1;
if (lhs->tv_sec > rhs->tv_sec)
return 1;
return lhs->tv_nsec - rhs->tv_nsec;
}
4、然后看下这个电池的线程
kthread_run(charger_routine_thread, info, “charger_thread”);
charger_routine_thread
static int charger_routine_thread(void *arg)
{
struct charger_manager *info = arg;
unsigned long flags;
bool is_charger_on;
int bat_current, chg_current;
while (1) {
wait_event(info->wait_que,
(info->charger_thread_timeout == true)); 在这里等待被唤醒
mutex_lock(&info->charger_lock);
spin_lock_irqsave(&info->slock, flags);
if (!info->charger_wakelock.active)
__pm_stay_awake(&info->charger_wakelock);
spin_unlock_irqrestore(&info->slock, flags);
info->charger_thread_timeout = false;
bat_current = battery_get_bat_current();
chg_current = pmic_get_charging_current();
// 充电关键log
chr_err("Vbat=%d,Ibat=%d,I=%d,VChr=%d,T=%d,Soc=%d:%d,CT:%d:%d hv:%d pd:%d:%d\n",
battery_get_bat_voltage(),
bat_current,
chg_current,
battery_get_vbus(),
battery_get_bat_temperature(),
battery_get_soc(),
battery_get_uisoc(),
mt_get_charger_type(),
info->chr_type,
info->enable_hv_charging,
info->pd_type,
info->pd_reset);
if (info->pd_reset == true) {
mtk_pe40_plugout_reset(info);
info->pd_reset = false;
}
is_charger_on = mtk_is_charger_on(info);
if (info->charger_thread_polling == true) 只要插了充电器就为真
mtk_charger_start_timer(info);
charger_update_data(info);
check_battery_exist(info);
check_dynamic_mivr(info);
charger_check_status(info);
kpoc_power_off_check(info);
if (is_disable_charger() == false) {
if (is_charger_on == true) {
if (info->do_algorithm)
info->do_algorithm(info);
}
} else
chr_debug("disable charging\n");
spin_lock_irqsave(&info->slock, flags);
__pm_relax(&info->charger_wakelock);
spin_unlock_irqrestore(&info->slock, flags);
chr_debug("%s end , %d\n",
__func__, info->charger_thread_timeout);
mutex_unlock(&info->charger_lock);
}
return 0;
}
5、charger_thread_timeout 用来唤醒这个线程继续执行,这个条件赋值为真的地方在_wake_up_charger函数里面
void _wake_up_charger(struct charger_manager *info)
{
unsigned long flags;
if (info == NULL)
return;
spin_lock_irqsave(&info->slock, flags);
if (!info->charger_wakelock.active)
__pm_stay_awake(&info->charger_wakelock);
spin_unlock_irqrestore(&info->slock, flags);
info->charger_thread_timeout = true; 赋值为真了,让线程继续执行下去
wake_up(&info->wait_que);
}
6、最后_wake_up_charger在什么地方被调用呢,调用的地方很多,但是关机充电主要是由上面我们提到的 charger_pm_event 这个函数执行时触发的
static int charger_pm_event(struct notifier_block *notifier,
unsigned long pm_event, void *unused)
{
struct timespec now;
switch (pm_event) {
case PM_SUSPEND_PREPARE:
pinfo->is_suspend = true;
chr_debug("%s: enter PM_SUSPEND_PREPARE\n", __func__);
break;
case PM_POST_SUSPEND:
pinfo->is_suspend = false;
chr_debug("%s: enter PM_POST_SUSPEND\n", __func__);
get_monotonic_boottime(&now);
if (timespec_compare(&now, &pinfo->endtime) >= 0 &&
pinfo->endtime.tv_sec != 0 &&
pinfo->endtime.tv_nsec != 0) {
chr_err("%s: alarm timeout, wake up charger\n",
__func__);
__pm_relax(&pinfo->charger_wakelock);
pinfo->endtime.tv_sec = 0;
pinfo->endtime.tv_nsec = 0;
_wake_up_charger(pinfo);
}
break;
default:
break;
}
return NOTIFY_DONE;
}
7、总结线程的唤醒过程
先是charger_pm_event事件的触发,比较了当前时间和定时的结束时间,如果当前时间大于了定时结束的时间就执行_wake_up_charger函数,执行唤醒charger函数后,charger_thread_timeout = true,这个条件为真会引起charger_routine_thread线程里面的while里面的等待满足条件,从而继续执行充电线程里面的代码,执行完毕后继续等待被唤醒,如此往复。