6、插充电器识别过程

1、对于6739平台来说,识别用户插入充电器的过程是通过中断来实现的,下面我们来分析一下识别过程
2、识别的原理:通过PMIC上的VCDT引脚来进行识别,当我们插入充电器时VCDT上会检测到电压,从而会触发中断,我们使用的pmic型号:MT6357
3、在 pmic_chr_type_det_v2.c 文件里面
pmic_chrdet_init函数

static int __init pmic_chrdet_init(void)
{
	mutex_init(&chrdet_lock);
	chrdet_psy = power_supply_get_by_name("charger");
	if (!chrdet_psy) {
		pr_notice("%s: get power supply failed\n", __func__);
		return -EINVAL;
	}

#ifdef __SW_CHRDET_IN_PROBE_PHASE__
	/* do charger detect here to prevent HW miss interrupt*/
	INIT_WORK(&chr_work, do_charger_detection_work); 初始化了一个延时工作队列
	schedule_work(&chr_work); 调度延时工作队列
#endif

#ifndef CONFIG_TCPC_CLASS
	pmic_register_interrupt_callback(INT_CHRDET_EDGE, chrdet_int_handler); 使用pmic接口注册了一个中断,并且触发方式是边沿触发,插入充电器和拔出,首先会执行这个中断函数
	pmic_enable_interrupt(INT_CHRDET_EDGE, 1, "PMIC"); 使能这个中断
#endif

	return 0;
}

当我们有充电器插入时会触发 chrdet_int_handler 这个中断函数

/* PMIC Int Handler */
void chrdet_int_handler(void)
{
	/*
	 * pr_notice("[chrdet_int_handler]CHRDET status = %d....\n",
	 *	pmic_get_register_value(PMIC_RGS_CHRDET));
	 */
	if (!pmic_get_register_value(PMIC_RGS_CHRDET)) { 
		int boot_mode = 0;

		hw_bc11_done();
		boot_mode = get_boot_mode(); 获取启动模式

		if (boot_mode == KERNEL_POWER_OFF_CHARGING_BOOT
		    || boot_mode == LOW_POWER_OFF_CHARGING_BOOT) { 判断是否是关机充电或低电
			pr_info("[%s] Unplug Charger/USB\n", __func__);
#ifndef CONFIG_TCPC_CLASS
			pr_info("%s: system_state=%d\n", __func__,
				system_state);
			if (system_state != SYSTEM_POWER_OFF)
				kernel_power_off(); 关闭系统
#else
			return;
#endif
		}
	}
	pmic_set_register_value(PMIC_RG_USBDL_RST, 1); 

	do_charger_detect(); 执行检测充电器干活函数
}

看下 do_charger_detect 这个函数做了什么事

/* Charger Detection */
void do_charger_detect(void)
{
	if (pmic_get_register_value(PMIC_RGS_CHRDET)) 如果真的有充电器
		mtk_pmic_enable_chr_type_det(true); 有充电器在
	else
		mtk_pmic_enable_chr_type_det(false);
}

继续看下 mtk_pmic_enable_chr_type_det 函数

void mtk_pmic_enable_chr_type_det(bool en)
{
#ifndef CONFIG_TCPC_CLASS
	if (!mt_usb_is_device()) {
		g_chr_type = CHARGER_UNKNOWN;
		pr_info("charger type: UNKNOWN, Now is usb host mode. Skip detection\n");
		return;
	}
#endif

	mutex_lock(&chrdet_lock);

	if (en) { 如果有插充电器时en=true
		if (is_meta_mode()) { 判断是否是meta模式,我们的显然不是
			/* Skip charger type detection to speed up meta boot */
			pr_notice("charger type: force Standard USB Host in meta\n");
			g_chr_type = STANDARD_HOST;
			chrdet_inform_psy_changed(g_chr_type, 1);
		} else { 应该是这个才对
			pr_info("charger type: charger IN\n"); 插入标志性打印
			g_chr_type = hw_charging_get_charger_type(); 获取充电器类型
			chrdet_inform_psy_changed(g_chr_type, 1); 上报充电器插入事件
			if (!IS_ERR(pinctrl_cdis_low)) {		 
				pinctrl_select_state(cdis_pinctrl, pinctrl_cdis_low);
				printk("charger IN enable charger\n");
			}
		}
	} else {
		pr_info("charger type: charger OUT\n");
		g_chr_type = CHARGER_UNKNOWN;
		chrdet_inform_psy_changed(g_chr_type, 0);
		if (!IS_ERR(pinctrl_cdis_high)) {		 
			pinctrl_select_state(cdis_pinctrl, pinctrl_cdis_high);
			printk("===charger OUT disable charger===\n");
		}
	}

	mutex_unlock(&chrdet_lock);
}

一般插入充电器的打印日志:

charger type: charger IN
charger type: 4, Standard Charger
charger type: chrdet_inform_psy_changed: online = 1, type = 4
mt_charger_set_property
dump_charger_name: charger type: 4, Standard Charger
charger IN enable charger
mtk_charger_int_handler

看下充电器类型是怎么识别的,通过bc11硬件来识别的得到了充电器的类型

int hw_charging_get_charger_type(void)
{
	enum charger_type CHR_Type_num = CHARGER_UNKNOWN;

#ifdef CONFIG_MTK_USB2JTAG_SUPPORT
	if (usb2jtag_mode()) {
		pr_info("[USB2JTAG] in usb2jtag mode, skip charger detection\n");
		return STANDARD_HOST;
	}
#endif

	hw_bc11_init();

	if (hw_bc11_DCD()) {
		if (hw_bc11_stepA1())
			CHR_Type_num = APPLE_2_1A_CHARGER;
		else
			CHR_Type_num = NONSTANDARD_CHARGER;
	} else {
		if (hw_bc11_stepA2()) {
			if (hw_bc11_stepB2())
				CHR_Type_num = STANDARD_CHARGER;
			else
				CHR_Type_num = CHARGING_HOST;
		} else
			CHR_Type_num = STANDARD_HOST;
	}

	if (CHR_Type_num != STANDARD_CHARGER)
		hw_bc11_done();
	else
		pr_info("charger type: skip bc11 release for BC12 DCP SPEC\n");

	dump_charger_name(CHR_Type_num);

#ifdef __FORCE_USB_TYPE__
	CHR_Type_num = STANDARD_HOST;
	pr_info("charger type: Froce to STANDARD_HOST\n");
#endif

	return CHR_Type_num;
}

于此同时会去更新节点信息的,从而上层就知道了具体的充电器类型了

static int chrdet_inform_psy_changed(enum charger_type chg_type,
				bool chg_online)
{
	int ret = 0;
	union power_supply_propval propval;

	pr_info("charger type: %s: online = %d, type = %d\n", __func__,
		chg_online, chg_type);

	/* Inform chg det power supply */
	if (chg_online) {
		propval.intval = chg_online;
		ret = power_supply_set_property(chrdet_psy,
				POWER_SUPPLY_PROP_ONLINE, &propval);
		if (ret < 0)
			pr_notice("%s: psy online failed, ret = %d\n",
				__func__, ret);

		propval.intval = chg_type;
		ret = power_supply_set_property(chrdet_psy,
				POWER_SUPPLY_PROP_CHARGE_TYPE, &propval);
		if (ret < 0)
			pr_notice("%s: psy type failed, ret = %d\n",
				__func__, ret);

		return ret;
	}

	propval.intval = chg_type;
	ret = power_supply_set_property(chrdet_psy,
				POWER_SUPPLY_PROP_CHARGE_TYPE, &propval);
	if (ret < 0)
		pr_notice("%s: psy type failed, ret(%d)\n", __func__, ret);

	propval.intval = chg_online;
	ret = power_supply_set_property(chrdet_psy, POWER_SUPPLY_PROP_ONLINE,
				&propval);
	if (ret < 0)
		pr_notice("%s: psy online failed, ret(%d)\n", __func__, ret);
	return ret;
}

4、拔掉充电器执行的流程也是类似,可以自行分析,这里我们对整个识别过程做一个总结:
首先是注册了pmic VCDT引脚的中断,当有充电器插入时会触发这个中断函数,在这个中断函数里面会去获取系统的开机模式,检测充电器的类型,最后更新节点信息,告诉上层当前充电器的类型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值