14、GM30线程函数如何终止充电

GM30里面有一个线程函数,默认执行的时间为10s,充满后执行的时间为20s,时间也是可以设置的
charger_routine_thread 函数里面
while函数里面
info->do_algorithm(info); 调用了一个回调函数

这个回调函数是在 mtk_switch_charger.c 里面被设置的
mtk_switch_charging_init 函数

int mtk_switch_charging_init(struct charger_manager *info)
{
	struct switch_charging_alg_data *swch_alg;

	swch_alg = devm_kzalloc(&info->pdev->dev,
				sizeof(*swch_alg), GFP_KERNEL);
	if (!swch_alg)
		return -ENOMEM;

	info->chg1_dev = get_charger_by_name("primary_chg");
	if (info->chg1_dev)
		chr_err("Found primary charger [%s]\n",
			info->chg1_dev->props.alias_name);
	else
		chr_err("*** Error : can't find primary charger ***\n");

	mutex_init(&swch_alg->ichg_aicr_access_mutex);

	info->algorithm_data = swch_alg;
	info->do_algorithm = mtk_switch_charging_run; // 外部充电ic充电,设置了回调函数
	info->plug_in = mtk_switch_charging_plug_in;
	info->plug_out = mtk_switch_charging_plug_out;
	info->do_charging = mtk_switch_charging_do_charging;
	info->do_event = charger_dev_event;
	info->change_current_setting = mtk_switch_charging_current; // 设置充电电流

	return 0;
}

看下设置的回调函数 mtk_switch_charging_run,这个函数里面做了充电模式的切换,我们的主要是CC和BATFUL这两个,
同时会去检查充电时间,然后调用dump_register的回调函数,这里我们重点观察cc模式的这个函数

static int mtk_switch_charging_run(struct charger_manager *info)
{
	struct switch_charging_alg_data *swchgalg = info->algorithm_data;
	int ret = 0;

	chr_err("%s [%d %d], timer=%d\n", __func__, swchgalg->state,
		info->pd_type,
		swchgalg->total_charging_time);

	if (mtk_pdc_check_charger(info) == false &&
	    mtk_is_TA_support_pd_pps(info) == false) {
		mtk_pe20_check_charger(info);
		if (mtk_pe20_get_is_connect(info) == false)
			mtk_pe_check_charger(info);
	}

	do {
		switch (swchgalg->state) {
			chr_err("%s_2 [%d] %d\n", __func__, swchgalg->state,
				info->pd_type);
		case CHR_CC:
			ret = mtk_switch_chr_cc(info); // 恒流模式充电
			break;

		case CHR_PE40_INIT:
			ret = mtk_switch_chr_pe40_init(info); // pe40初始化
			break;

		case CHR_PE40_CC:
			ret = mtk_switch_chr_pe40_cc(info); // pe40恒流
			break;

		case CHR_BATFULL:
			ret = mtk_switch_chr_full(info); // 电池充满
			break;

		case CHR_ERROR:
			ret = mtk_switch_chr_err(info); // 充电错误
			break;
		}
	} while (ret != 0);
	mtk_switch_check_charging_time(info);

	charger_dev_dump_registers(info->chg1_dev);
	return 0;
}

mtk_switch_chr_cc 恒流充电模式函数,这个函数里面会去使能充电,同时会去检查充电是否完成


static int mtk_switch_chr_cc(struct charger_manager *info)
{
	bool chg_done = false;
	struct switch_charging_alg_data *swchgalg = info->algorithm_data;
	struct timespec time_now, charging_time;

	/* check bif */
	if (IS_ENABLED(CONFIG_MTK_BIF_SUPPORT)) {
		if (pmic_is_bif_exist() != 1) {
			chr_err("CONFIG_MTK_BIF_SUPPORT but no bif , stop charging\n");
			swchgalg->state = CHR_ERROR;
			charger_manager_notifier(info, CHARGER_NOTIFY_ERROR);
		}
	}

	get_monotonic_boottime(&time_now);
	charging_time = timespec_sub(time_now, swchgalg->charging_begin_time);

	swchgalg->total_charging_time = charging_time.tv_sec;

	if (mtk_pe40_is_ready(info)) {
		chr_err("enter PE4.0!\n");
		swchgalg->state = CHR_PE40_INIT;
		info->pe4.is_connect = true;
		return 1;
	}

	swchg_turn_on_charging(info); // 使能开始充电

	charger_dev_is_charging_done(info->chg1_dev, &chg_done); // 检查是否充电完成
	if (chg_done) { // 充电完成
		swchgalg->state = CHR_BATFULL; // 更新状态为充满
		charger_dev_do_event(info->chg1_dev, EVENT_EOC, 0); // 发充满事件
		chr_err("battery full!\n");
	}

	/* If it is not disabled by throttling,
	 * enable PE+/PE+20, if it is disabled
	 */
	if (info->chg1_data.thermal_input_current_limit != -1 &&
		info->chg1_data.thermal_input_current_limit < 300)
		return 0;

	if (!mtk_pe20_get_is_enable(info)) {
		mtk_pe20_set_is_enable(info, true);
		mtk_pe20_set_to_check_chr_type(info, true);
	}

	if (!mtk_pe_get_is_enable(info)) {
		mtk_pe_set_is_enable(info, true);
		mtk_pe_set_to_check_chr_type(info, true);
	}
	return 0;
}

看下使能充电函数 swchg_turn_on_charging,这个函数里面会去选择充电电流,然后调用框架的函数来使能充电

static void swchg_turn_on_charging(struct charger_manager *info)
{
	struct switch_charging_alg_data *swchgalg = info->algorithm_data;
	bool charging_enable = true;

	if (swchgalg->state == CHR_ERROR) {
		charging_enable = false;
		chr_err("[charger]Charger Error, turn OFF charging !\n");
	} else if ((get_boot_mode() == META_BOOT) ||
			((get_boot_mode() == ADVMETA_BOOT))) {
		charging_enable = false;
		info->chg1_data.input_current_limit = 200000; /* 200mA */
		charger_dev_set_input_current(info->chg1_dev,
					info->chg1_data.input_current_limit);
		chr_err("In meta mode, disable charging and set input current limit to 200mA\n");
	} else {
		mtk_pe20_start_algorithm(info);
		if (mtk_pe20_get_is_connect(info) == false)
			mtk_pe_start_algorithm(info);

		swchg_select_charging_current_limit(info); // 设置充电电流函数
		if (info->chg1_data.input_current_limit == 0
		    || info->chg1_data.charging_current_limit == 0) {
			charging_enable = false;
			chr_err("[charger]charging current is set 0mA, turn off charging !\n");
		} else {
			swchg_select_cv(info);
		}
	}

 	charger_dev_enable(info->chg1_dev, charging_enable); // 使能充电的框架函数
}

我们看下框架的函数 charger_dev_enable
charger_dev_xxx开头的函数很多都是框架函数,在charger_class.c文件里面,一般都是调用设置好的回调函数来干活的

int charger_dev_enable(struct charger_device *chg_dev, bool en) // 框架函数 用来使能充电
{
	if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->enable)
		return chg_dev->ops->enable(chg_dev, en); // 调用使能的回调函数

	return -ENOTSUPP;
}
EXPORT_SYMBOL(charger_dev_enable);

一般我们具体的充电IC驱动需要实现框架里面的一些函数,类似下面的这种,对于上面框架里面enable的调用实际上会调用到底层的bq25601_enable_charging函数

static struct charger_ops bq25601_chg_ops = {
#if 0
	.enable_hz = bq25601_enable_hz,
#endif

	/* Normal charging */
	.dump_registers = bq25601_dump_register,
	.enable = bq25601_enable_charging, // 使能函数其实就是调用了这个
	.get_charging_current = bq25601_get_current,
	.set_charging_current = bq25601_set_current,
	.get_input_current = bq25601_get_input_current,
	.set_input_current = bq25601_set_input_current,
	/*.get_constant_voltage = bq25601_get_battery_voreg,*/
	.set_constant_voltage = bq25601_set_cv_voltage,
	.kick_wdt = bq25601_reset_watch_dog_timer,
	.set_mivr = bq25601_set_vindpm_voltage,
	.is_charging_done = bq25601_get_charging_status, // 这个函数是本节的主角,用来终止充电

	/* Safety timer */
	.enable_safety_timer = bq25601_enable_safetytimer,
	.is_safety_timer_enabled = bq25601_get_is_safetytimer_enable,


	/* Power path */
	/*.enable_powerpath = bq25601_enable_power_path, */
	/*.is_powerpath_enabled = bq25601_get_is_power_path_enable, */


	/* OTG */
	.enable_otg = bq25601_enable_otg,
	.set_boost_current_limit = bq25601_set_boost_current_limit,
	.event = bq25601_do_event,
};

顺便看下使能函数里面做了什么操作,其实就是控制寄存器咯

static int bq25601_enable_charging(struct charger_device *chg_dev,
				   bool en)
{
	int status = 0;

	pr_info("enable state : %d\n", en);
	if (en) {
		/* bq25601_config_interface(bq25601_CON3, 0x1, 0x1, 4); */
		/* enable charging */
		bq25601_set_en_hiz(0x0);
		bq25601_set_chg_config(en);
	} else {
		/* bq25601_config_interface(bq25601_CON3, 0x0, 0x1, 4); */
		/* enable charging */
		bq25601_set_chg_config(en);
		pr_info("[charging_enable] under test mode: disable charging\n");

		/*bq25601_set_en_hiz(0x1);*/
	}

	return status;
}

我们继续回到 mtk_switch_chr_cc 恒流充电函数来,还有一个很重要的事就是检查充电状态是否完成
charger_dev_is_charging_done 函数,如果充电完成需要更新状态为BATFUL

	charger_dev_is_charging_done(info->chg1_dev, &chg_done); // 检查是否充电完成
	if (chg_done) { // 充电完成
		swchgalg->state = CHR_BATFULL; // 更新状态为充满更新充电状态,更新这个状态
		charger_dev_do_event(info->chg1_dev, EVENT_EOC, 0); // 发充满事件
		chr_err("battery full!\n");
	}


int charger_dev_is_charging_done(struct charger_device *chg_dev, bool *done)
{
	if (chg_dev != NULL && chg_dev->ops != NULL &&
	    chg_dev->ops->is_charging_done)
		return chg_dev->ops->is_charging_done(chg_dev, done); // 调用回调函数

	return -ENOTSUPP;
}
EXPORT_SYMBOL(charger_dev_is_charging_done);

is_charging_done的回调函数为,这个函数里面根据寄存器的状态来判断当前是否充满,我们可以看到当寄存器的值返回是0x3的时候表示真正充满了,从而上报充满

static int bq25601_get_charging_status(struct charger_device *chg_dev,
				       bool *is_done)
{
	unsigned int status = true;
	unsigned int ret_val;

	ret_val = bq25601_get_chrg_stat();

	if (ret_val == 0x3)
		*is_done = true;
	else
		*is_done = false;

	return status;
}

我们继续看下这个0x3表示什么含义,需要分析bq25601_get_chrg_stat函数,调用了一个接口函数读取了CON8寄存器的bit3-bit4位的值

#define bq25601_CON8      0x08
#define CON8_CHRG_STAT_MASK           0x03
#define CON8_CHRG_STAT_SHIFT          3

unsigned int bq25601_get_chrg_stat(void)
{
	unsigned int ret = 0;
	unsigned char val = 0;

	ret = bq25601_read_interface((unsigned char) (bq25601_CON8),
				     (&val),
				     (unsigned char) (CON8_CHRG_STAT_MASK),
				     (unsigned char) (CON8_CHRG_STAT_SHIFT)
				    );
	return val;
}

我们看下这个值在手册里面的含义,从手册里面来看当值为11时表示的就是充电截至,因此就可以判断当前充电完成了
在这里插入图片描述
最后我们总结一下整个过程:
1、需要掌握充电函数的框架层charger_class.c文件里面的调用回调函数
2、charger_class.c文件负责将实例化的charger ic驱动和mtk_charger.c文件连接到了一起,mtk_charger.c不直接调用具体的charger ic驱动,而是通过框架charger_class.c来进行调用
3、充电的终止条件是根据charger ic的寄存器状态来判断的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值