以mt6357 pmic为例,充电器插拔检测和类型检测在mt6357-charger-type.c下完成:

一、首先从pmic的probe开始分析:

static int mt6357_charger_type_probe(struct platform_device *pdev)
{struct mtk_charger_type *info;struct iio_channel *chan_vbus;struct device *dev = &pdev->dev;struct device_node *np = dev->of_node;int ret = 0;pr_notice("%s: starts\n", __func__);chan_vbus = devm_iio_channel_get(&pdev->dev, "pmic_vbus");                //dts中pmic_vbus设备节点读取,通过adc读取vcdt引脚上的分压电压(充电器电压)来识别并触发中断,if (IS_ERR(chan_vbus)) {pr_notice("mt6357 charger type requests probe deferral ret:%d\n",chan_vbus);return -EPROBE_DEFER;}info = devm_kzalloc(&pdev->dev, sizeof(*info),GFP_KERNEL);if (!info)return -ENOMEM;info->chip = (struct mt6397_chip *)dev_get_drvdata(                //pmic私有数据获取pdev->dev.parent);info->regmap = info->chip->regmap;dev_set_drvdata(&pdev->dev, info);info->pdev = pdev;mutex_init(&info->ops_lock);check_boot_mode(info, &pdev->dev);info->psy_desc.name = "mtk_charger_type";                //一些私有数据赋值info->psy_desc.type = POWER_SUPPLY_TYPE_UNKNOWN;info->psy_desc.properties = chr_type_properties;info->psy_desc.num_properties = ARRAY_SIZE(chr_type_properties);info->psy_desc.get_property = psy_chr_type_get_property;info->psy_desc.set_property = psy_chr_type_set_property;info->psy_desc.property_is_writeable =psy_charger_type_property_is_writeable;info->psy_desc.usb_types = mt6357_charger_usb_types,info->psy_desc.num_usb_types = ARRAY_SIZE(mt6357_charger_usb_types),info->psy_cfg.drv_data = info;info->psy_cfg.of_node = np;info->psy_cfg.supplied_to = mt6357_charger_supplied_to;info->psy_cfg.num_supplicants = ARRAY_SIZE(mt6357_charger_supplied_to);info->ac_desc.name = "ac";info->ac_desc.type = POWER_SUPPLY_TYPE_MAINS;info->ac_desc.properties = mt_ac_properties;info->ac_desc.num_properties = ARRAY_SIZE(mt_ac_properties);info->ac_desc.get_property = mt_ac_get_property;info->ac_cfg.drv_data = info;info->usb_desc.name = "usb";info->usb_desc.type = POWER_SUPPLY_TYPE_USB;info->usb_desc.properties = mt_usb_properties;info->usb_desc.num_properties = ARRAY_SIZE(mt_usb_properties);info->usb_desc.get_property = mt_usb_get_property;info->usb_cfg.drv_data = info;info->psy = power_supply_register(&pdev->dev, &info->psy_desc,        //注册此pmic设备为psy设备&info->psy_cfg);if (IS_ERR(info->psy)) {pr_notice("%s Failed to register power supply: %ld\n",__func__, PTR_ERR(info->psy));return PTR_ERR(info->psy);}pr_notice("%s register psy success\n", __func__);info->chan_vbus = devm_iio_channel_get(                //再次读取该psy设备信息&pdev->dev, "pmic_vbus");if (IS_ERR_OR_NULL(info->chan_vbus)) {pr_notice("chan_vbus auxadc get fail, ret=%d\n",PTR_ERR(info->chan_vbus));}if (of_property_read_u32(np, "bc12_active", &info->bc12_active) < 0)        //bc1.2使能,bc检测使能pr_notice("%s: no bc12_active\n", __func__);pr_notice("%s: bc12_active:%d\n", __func__, info->bc12_active);if (info->bc12_active) {info->ac_psy = power_supply_register(&pdev->dev,        //注册ac psy设备&info->ac_desc, &info->ac_cfg);if (IS_ERR(info->ac_psy)) {pr_notice("%s Failed to register power supply: %ld\n",__func__, PTR_ERR(info->ac_psy));return PTR_ERR(info->ac_psy);}info->usb_psy = power_supply_register(&pdev->dev,            //注册usb psy设备&info->usb_desc, &info->usb_cfg);if (IS_ERR(info->usb_psy)) {pr_notice("%s Failed to register power supply: %ld\n",__func__, PTR_ERR(info->usb_psy));return PTR_ERR(info->usb_psy);}INIT_WORK(&info->chr_work, do_charger_detection_work);            //这里初始化了一个do_charger_detection_work任务,做插拔检测schedule_work(&info->chr_work);ret = devm_request_threaded_irq(&pdev->dev,                //这里注册了一个chrdet_int_handler中断,触发方式是边沿触发,插入充电器和拔出,首先会执行这个中断函数platform_get_irq_byname(pdev, "chrdet"), NULL,chrdet_int_handler, IRQF_TRIGGER_HIGH, "chrdet", info);if (ret < 0)pr_notice("%s request chrdet irq fail\n", __func__);}info->first_connect = true;pr_notice("%s: done\n", __func__);return 0;
}

下面分解看它的中断函数和检测函数:

二、chrdet_int_handler函数:

irqreturn_t chrdet_int_handler(int irq, void *data)
{struct mtk_charger_type *info = data;unsigned int chrdet = 0;chrdet = bc11_get_register_value(info->regmap,            //bc1.2读取pmic CHRDET寄存器值,来判断是否使能检测充电器PMIC_RGS_CHRDET_ADDR,PMIC_RGS_CHRDET_MASK,PMIC_RGS_CHRDET_SHIFT);if (!chrdet) {hw_bc11_done(info);            //pmic寄存器操作/* 8 = KERNEL_POWER_OFF_CHARGING_BOOT *//* 9 = LOW_POWER_OFF_CHARGING_BOOT */if (info->bootmode == 8 || info->bootmode == 9) {        //boot mode判断,关机充电或者低压充电pr_info("%s: Unplug Charger/USB\n", __func__);#ifndef CONFIG_TCPC_CLASSpr_info("%s: system_state=%d\n", __func__,system_state);if (system_state != SYSTEM_POWER_OFF)kernel_power_off();            //系统下点
#endif}}pr_notice("%s: chrdet:%d\n", __func__, chrdet);do_charger_detect(info, chrdet);                //这里会去做充电器是否在位和类型判断return IRQ_HANDLED;
}

三、do_charger_detection_work:

static void do_charger_detection_work(struct work_struct *data)
{//container_of: 通过已知的一个数据结构成员指针data,数据结构类型mtk_charger_type,以及这个成员指针在这个数据结构中的成员名chr_work,来获取指向这个数据结构的指针mtk_charger_type *struct mtk_charger_type *info = (struct mtk_charger_type *)container_of(            data, struct mtk_charger_type, chr_work);unsigned int chrdet = 0;chrdet = bc11_get_register_value(info->regmap,            //bc1.2读取pmic CHRDET寄存器值,来判断是否使能检测充电器PMIC_RGS_CHRDET_ADDR,PMIC_RGS_CHRDET_MASK,PMIC_RGS_CHRDET_SHIFT);pr_notice("%s: chrdet:%d\n", __func__, chrdet);if (chrdet)do_charger_detect(info, chrdet);            //这里会去做充电器是否在位和类型判断else {hw_bc11_done(info);/* 8 = KERNEL_POWER_OFF_CHARGING_BOOT *//* 9 = LOW_POWER_OFF_CHARGING_BOOT */if (info->bootmode == 8 || info->bootmode == 9) {pr_info("%s: Unplug Charger/USB\n", __func__);#ifndef CONFIG_TCPC_CLASSpr_info("%s: system_state=%d\n", __func__,system_state);if (system_state != SYSTEM_POWER_OFF)kernel_power_off();
#endif}}
}

四、do_charger_detect:

这个函数会在do_charger_detection_work和chrdet_int_handler都去调用,主要是做psy设备状态改变之后的通知动作
;

void do_charger_detect(struct mtk_charger_type *info, bool en)
{union power_supply_propval prop, prop2, prop3;int ret = 0;#ifndef CONFIG_TCPC_CLASSif (!mt_usb_is_device()) {                //通过usb phy识别和确认是usb设备pr_info("charger type: UNKNOWN, Now is usb host mode. Skip detection\n");return;}
#endifprop.intval = en;if (en) {ret = power_supply_set_property(info->psy,            //spy设备online属性设置POWER_SUPPLY_PROP_ONLINE, &prop);ret = power_supply_get_property(info->psy,            //psy类型获取POWER_SUPPLY_PROP_TYPE, &prop2);ret = power_supply_get_property(info->psy,            //usb类型获取POWER_SUPPLY_PROP_USB_TYPE, &prop3);} else {prop2.intval = POWER_SUPPLY_TYPE_UNKNOWN;prop3.intval = POWER_SUPPLY_USB_TYPE_UNKNOWN;info->psy_desc.type = POWER_SUPPLY_TYPE_UNKNOWN;info->type = POWER_SUPPLY_USB_TYPE_UNKNOWN;}pr_notice("%s type:%d usb_type:%d\n", __func__, prop2.intval, prop3.intval);if(en &&(prop3.intval ==1 || prop3.intval ==3)) {            //usb类型mt_usb_connect();} else {mt_usb_disconnect();}power_supply_changed(info->psy);            //这里做psy设备状态更新
}

mtk充电器插拔检测相关推荐

  1. 耳机驱动调试(插拔检测与按键检测)

    耳机驱动调试(插拔检测与按键检测) 小白一枚,欢各位大佬指出错误 耳机类型判断 三段和四段.欧标和美标 现在许多设备的耳机接口都采用3.5mm的耳机接口,其中终端就是,终端可以兼容三段和四段耳机:三段 ...

  2. linux U盘插拔检测

    因为最终要在tiny210上实现此功能,最终选择了hotplug. http://hi.baidu.com/hdy5200075/item/7751f48647f3d12a100ef3f6这里是hot ...

  3. MFC使用Windows API实现U盘插拔检测,获取U盘容量,U盘内容移动删除,开启和关闭U盘以及获取盘符

    文章目录 前言 一.利用OS API实现对U盘的管理 二.项目到底长啥样 三.实例代码 1.实时判断U盘插入与拔出 2.能够显示U盘的总容量.使用容量和剩余容量 3.能够将某个目录上的文件或整个目录复 ...

  4. 教程一:windows api(c mfc vs2017)实现U盘插拔检测,获取U盘容量,U盘内容移动,开启和关闭U盘以及获取盘符等

    c++是大二下学期的专业课,大家可能都学过,这里主要介绍U盘这个小项目要用到没学过的知识.(踩坑合集) U盘完整项目源代码下载地址:https://download.csdn.net/download ...

  5. 使用libusb检测USB设备插拔状态

    libusb是一个提供USB设备访问的跨平台用户模式程序库.该项目最新网址:http://www.libusb.info, 支持主流的操作系统:Linux.Mac OS X. Windows.Open ...

  6. 高通平台耳机插拔检测

    https://blog.csdn.net/u012899335/article/details/82312766 高通耳机的插拔检测需要配置NC或NO,并且使用匹配的耳机(欧标,美标). 欧标,美标 ...

  7. sim插拔识别时间_特斯拉+树莓派实现车牌识别检测系统

    转自机器之心 | 作者:Robert Lucian Chiriac | 参与:王子嘉.思.一鸣 怎样在不换车的前提下打造一个智能车系统呢?一段时间以来,本文作者 Robert Lucian Chiri ...

  8. [转]VB:如何检测到U盘的插拔(源代码)

    听说现在网络上流传着一些能实时检测到U盘插拔消息并能在其插入后伺机拷贝其中文档资料的恶意程序,而日前在CSDN论坛也看到有网友询问这类程序的实现原理,为此我想通过一个简单的VB程序演示一下核心操作过程 ...

  9. shell 判断网线插拔_linux检测网线插拔状态

    Shell查看网线插拔状态: 使用ifconfig命令,如果含有"RUNNING",说明网线接入,否则就没有. 例: ifconfig ifconfig eth0 ifconfig ...

最新文章

  1. ArcBruTile 0.2.2
  2. eclipse创建了java web项目后怎么连接mysql
  3. redis反杀面试官之10问
  4. java 物理内存_聊聊Java中的内存
  5. php session缓存,扫盲:php session缓存至memcached中的方法
  6. 关于二维数组取地址加以或减一解引用问题
  7. [蓝桥杯][2018年第九届真题]约瑟夫环
  8. oracle的aud文件,oracle asm实例的aud文件有关问题
  9. [转]Qt 之 QFileSystemWatcher
  10. 使用php-amqplib连接rabbitMQ 学习笔记及总结
  11. iOS底层探索之多线程(十七)——通过 Swift的Foundation源码分析锁(NSLock、NSCondition、NSRecursiveLock)
  12. HDU 3333-Turing Tree(BIT好题)
  13. Atitit 提升稳定性 数据库死锁 目录 1.1. 配置数据库死锁检测超时时间从默认50s到10s 1 1.2. 调整隔离级别到read commit 1 1.3. mysql数据库连接使用完毕
  14. 联想电脑 Windows10 20H2 32位64位 专业版 V2021【OEM原版镜像】
  15. python安装openpyxl库_Python openpyxl 库
  16. Java--集合框架--Map集合、 HashMap和Hashtable的区别、 Collections(集合工具类)
  17. 高级语言程序设计(c语言描述) 陆黎明 朱媛媛 练习答案,高级语言程序设计(c语言描述) 陆黎明 朱媛媛 练习答案...
  18. 实时渲染3D动画创作大赛
  19. 使用R进行VENN_维恩图或韦恩图_的绘制_2020-11-08
  20. 在windows下使用docker做本机linux环境系统测试

热门文章

  1. atom ui html,几个受欢迎的Atom插件
  2. oracle nvl 效率,说说 Oracle 的 NVL 与 NVL2 函数
  3. TYD-python数据分析与机器学习实战(文本挖掘部分笔记)
  4. 班组沟通与管理培训PPT模板
  5. 反弹球c语言小游戏编程,C语言实现反弹球小游戏
  6. 王道考研2021——数据结构学习笔记
  7. Linux高阶—安全认证模块pam(九)
  8. c++语言循环读写文件夹,在C++中逐行读取文件
  9. pdf模板带图片二维码导出(多个)
  10. HIT 软件构造 垃圾回收