GM30之充电线程唤醒时间设置

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里面的等待满足条件,从而继续执行充电线程里面的代码,执行完毕后继续等待被唤醒,如此往复。

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值