【Linux驱动】充电芯片bq24735调试详解
一、bq24735简介
bq24735 是一款高效率同步电池充电器。
当系统供电需求暂时高于适配器最大供电水平的时候, bq24735 使用智能加速技术来允许电池向系统中释放能量,这样的话将保护适配器不被损坏。
bq24735 为满足自动系统电源选择的需要,使用 2 个充电泵来分别驱动 n-通道 MOSFET (ACFET, RBFET 和 BATFET) 。
SMBus(I2C总线) 控制的输入电流, 充电电流, 和充电电压DAC允许非常高的调节精度,此调节精度可通过系统功率管理微控制器很容易地进行编程。
bq24735 使用内部输入电流寄存器或者外部ILIM引脚来减缓PWM调制速度以减小充电电流。
二、Linux内核充电架构
要想理解bq24735驱动,必须首先理解Android供电系统框架,最重要的知识点是power supply。
1. Android供电系统框架
power supply(以下简称psy)是Linux中从供电驱动抽象出来的子系统,是Linux电源管理的重要组成部分。
psy是一个中间层,在kernel中是属于设备驱动的一部分,psy的作用主要是向用户空间汇总各类供电的状态信息。
抽象出来的各类信息称为property,比如供电设备是否连接就对应着POWER_SUPPLY_PROP_ONLINE。
2. power supply功能
power_supply的软件架构:
power supply framework功能包括:
- 抽象PSY设备的共性,向用户空间提供统一的API;
- 为底层PSY驱动的编写,提供简单、统一的方式,同时封装并实现公共逻辑。
power supply class位于drivers/power/目录中,主要由3部分组成(可参考下图的软件架构):
- 1)power_supply_core,用于抽象核心数据结构、实现公共逻辑。位于drivers/power/power_supply_core.c中。
- 2)power_supply_sysfs,实现sysfs以及uevent功能。位于drivers/power/power_supply_sysfs.c中。
- 3)power_supply_leds,基于Linux led class,提供PSY设备状态指示的通用实现。位于drivers/power/power_suppply_leds.c中。
最后,驱动工程师可以基于power supply class,实现具体的PSY drivers,主要处理平台相关、硬件相关的逻辑。这些drivers都位于drivers/power/power_supply目录下。
3. 驱动层功能
在驱动层,主要是两大模块,与电池监控(fuelgauge)和与充放电管理(charger)相关的驱动(对应图中的battery.c和charger.c),这两大模块主要处理硬件相关的逻辑,在硬件状态发生变化时,会触发相关的中断,驱动层会调用相应的中断函数,并更新修改相应的psy节点值。
fuelgauge驱动主要是负责向上层android系统提供当前电池的电量以及健康状态信息等等,另外除了这个以外,它也向charger驱动提供电池的相关信息;charger驱动主要负责电源线的插拔检测,以及充放电的过程管理。
对于battery管理,硬件上有电量计IC和充放电IC,当然有些厂家为了成本的考虑,也会把电量计和充放电功能集成到一个IC上,更有甚者,可能会把PMU功能也集成在一块硅面上。
4. 其他问题
问:android怎么知道当前是什么供电,充电中与否?
答:uevent机制(实质是net_link方式的socket)(广泛应用于hotplug),充电插入与断开时,内核通过发送uevent信息,告诉android。
问:android如何知道各种参数并更新的?
答:通过kobject_uevent发送通知给上层,上层读取sys相关文件属性
以下是某平台sysfs文件目录
root@********_arm64:/sys/class # pwd
sys/class/power_supply
root@********_arm64:/sys/class/power_supply # ls
ac
battery
bq24735@5-0009
usb
root@********_arm64:/sys/class/power_supply # cd bq24735@5-0009
cd bq24735@5-0009
root@*********_arm64:/sys/class/power_supply/bq24735@5-0009 # ls
device
online
power
status
subsystem
type
uevent
【文章福利】小编自己整理了一些个人觉得比较好的学习书籍资料有需要的可以私信回复【内核】自行免费领取哦!!
三、bq24735驱动实现
下面基于某款soc来讲解如何让我们的产品支持bq24735。
1. 硬件连接图图
下面是一个典型的bq24735电路连接图:
当没有电源供电的时候,bq24735会直接将电池传递给降压电路,给系统供电
当有电源供电的时候,bq24735会给电池充电。
2. 引脚说明
在此我们只介绍与驱动相关的引脚
3. 寄存器
bq24735用到的寄存器如下:
- 充电选项寄存器Charge Options Register [reset = 0x12H]
其中最重要的两个位bit[4]/bit[0]
bit:[4]
0: AC adapter不在 (ACDET < 2.4 V)
1: AC adapter存在(ACDET > 2.4 V)
bit:[0]
0: 使能充电
1: 抑制充电
该寄存器为可读写,
如果要判断当前是否在充电,则可以读取该寄存器,通过判断bit[0]是否为0来确认
如果要判断当前是否存在,则可以读取该寄存器,通过判断bit[4]是否为1来确认
- 充电电流寄存器Charge Current Register (0x14H)
通过该寄存器可以设置充电电流。
比如我们要设置充电电流为3072mA,
该值为2048+1024,将对应的bite[10]/[11]为1,其他位为0
1100 0000 0000
即设置该寄存器值为:0xC00
充电电压寄存器Charge Voltage Register (0x15H)
该寄存器设置方法类似于充电电流寄存器
输入电流Input Current Register (0x3FH)
该寄存器设置方法类似于充电电流寄存器
0xfe,0xff
这两个寄存器分别读取MANUFACTURER_ID和DEVICE_ID
这两个值分别为:0x0040、0x000B
驱动初始化时可以通过读取这两个寄存器的值来判断,驱动是否和硬件匹配。
注意:
通常寄存器0x14、0x15、0x3F值需要询问硬件工程师
4. 设备树
bq24735@9 {
compatible = "ti,bq24735";
reg = <0x9>;
ti,ac-detect-gpios = <&gpio 72 0x1>;
ti,charge-current =<0x600>;
ti,charge-voltage=<0x41a0>;
ti,input-current =<0x800>;
}
参数说明
compatible :用于和驱动的结构体i2c_driver的driver.of_match_table->compatible属性进行匹配
reg:bq24735从设备地址(I2C)
ti,ac-detect-gpios:中断使用的gpio,第三个参数是该pin默认电平
ti,charge-current :充电电流
ti,charge-voltage :充电电压
ti,input-current :输入电流
5. 驱动讲解
- 驱动文件
内核代码中已经有该驱动
drivers\power\bq24735-charger.c
但是该驱动往往需要修改以适配实际的方案。
该驱动是基于I2C总线,对应结构体变量定义如下:
static struct i2c_driver bq24735_charger_driver = {
.driver = {
.name = "bq24735-charger",
.owner = THIS_MODULE,
.of_match_table = bq24735_match_ids,
},
.probe = bq24735_charger_probe,
.remove = bq24735_charger_remove,
.id_table = bq24735_charger_id,
};
- 主要函数
static bool bq24735_charger_is_present(struct bq24735 *charger)
判断bq24735 是否存在
其实就是读取寄存器0x12的值,判断bit[4]值是否为1
static int bq24735_charger_is_charging(struct bq24735 *charger)
判断bq24735 是否在充电
其实就是读取寄存器0x12的值,判断bit[0]值是否为0
static inline int bq24735_enable_charging(struct bq24735 *charger)
使能充电
将寄存器寄存器0x12的bit[0]置0
static inline int bq24735_disable_charging(struct bq24735 *charger)
禁止充电
将寄存器寄存器0x12的bit[0]置1
static int bq24735_config_charger(struct bq24735 *charger)
配置充电电压(寄存器0x15)、充电电流(寄存器0x14)、输入电流(寄存器0x3f)
static irqreturn_t bq24735_charger_isr(int irq, void *devid)
中断处理函数,
当bq24735充电状态发生变化的时候,会发送中断给cpu
此时可以通过I2C来读取寄存器0x12的内容来获取bq24735当前状态
static int bq24735_charger_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
提供给power supply子系统的回调函数
该函数用于获取bq24735当前状态
状态包括
enum {
POWER_SUPPLY_STATUS_UNKNOWN = 0,
POWER_SUPPLY_STATUS_CHARGING, //正在充电
POWER_SUPPLY_STATUS_DISCHARGING,
POWER_SUPPLY_STATUS_NOT_CHARGING,//没有充电
POWER_SUPPLY_STATUS_FULL,//充满
};
- probe流程
此处检测MANUFACTURER_ID和DEVICE_ID流程稍做了修改,只有bq24735 present的时候才会check并配置
此外还有个最重要的机构体
supply_desc->name = name;
supply_desc->type = POWER_SUPPLY_TYPE_MAINS;
supply_desc->properties = bq24735_charger_properties;
supply_desc->num_properties = ARRAY_SIZE(bq24735_charger_properties);
supply_desc->get_property = bq24735_charger_get_property;
supply_desc->properties
提供给power supply架构可以访问的命令的集合,
这些命令需要在函数supply_desc->get_property增加对应的命令代码
supply_desc->get_property
power supply会定时通过该回调函数获取充电芯片是否在线、是否在充电等状态
- 代码架构
这个架构是一口君根据项目中平台所画的架构,其他平台架构可能会有所不同,
需要具体问题具体分析。
四、 log
下面log是开机启动流程log,
第一步
用电池供电启动
启动后再插入电源充电,
插入电源后,bq24735会触发中断:
然后再断开电源停止充电
【Linux驱动】充电芯片bq24735调试详解的更多相关文章
- Linux驱动开发必看详解神秘内核(完全转载)
Linux驱动开发必看详解神秘内核 完全转载-链接:http://blog.chinaunix.net/uid-21356596-id-1827434.html IT168 技术文档]在开始步入L ...
- Linux Bash命令关于程序调试详解
转载:http://os.51cto.com/art/201006/207230.htm 参考:<Linux shell 脚本攻略>Page22-23 Linux bash程序在程序员的使 ...
- linux PHP 编译安装参数详解
linux PHP 编译安装参数详解 ./configure --prefix=/usr/local/php --with-config-file-path=/usr/local/php/etc -- ...
- Linux文件系统的目录结构详解
Linux文件系统的目录结构详解 一.前 言 文章对Linux下所有目录一一说明,对比较重要的目录加以重点解说,以帮助初学者熟练掌握Linux的目录结构. 二.目 录 1.什么是文件系统 2.文件 ...
- Linux内存管理之mmap详解
转发之:http://blog.chinaunix.net/uid-26669729-id-3077015.html Linux内存管理之mmap详解 一. mmap系统调用 1. mmap系统调用 ...
- (转)Linux命令之Ethtool用法详解
Linux命令之Ethtool用法详解 原文:http://www.linuxidc.com/Linux/2012-01/52669.htm Linux/Unix命令之Ethtool描述:Ethtoo ...
- ALSA声卡驱动中的DAPM详解之四:在驱动程序中初始化并注册widget和route
前几篇文章我们从dapm的数据结构入手,了解了代表音频控件的widget,代表连接路径的route以及用于连接两个widget的path.之前都是一些概念的讲解以及对数据结构中各个字段的说明,从本章开 ...
- ALSA声卡驱动中的DAPM详解之三:如何定义各种widget
上一节中,介绍了DAPM框架中几个重要的数据结构:snd_soc_dapm_widget,snd_soc_dapm_path,snd_soc_dapm_route.其中snd_soc_dapm_pat ...
- Linux 命令之 scp 命令详解
Linux 命令之 scp 命令详解 一.scp 简介 scp 命令用于不同主机之间复制文件和目录. scp 是 secure copy 的缩写,是 基于 ssh 协议进行安全的远程文件拷贝命令. s ...
- Intellij IDEA中使用Debug调试详解
转载:https://www.linuxidc.com/Linux/2017-09/146772.htm Intellij IDEA中使用Debug调试详解 Debug用来追踪代码的运行流程,通常 ...
随机推荐
- Java面试知识点(一)多态
多态概述 1. 定义 多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的 ...
- QuartzNet暂停恢复会执行多次的问题解决
' var config = new System.Collections.Specialized.NameValueCollection { { "quartz.jobStore.misf ...
- WPF网格类型像素着色器
由于WPF只能写像素着色器,没法写顶点着色器,所以只能在这上面做文章了 刚好有个纹理坐标TEXCOORD输入可用,而且值的范围是已知的0-1,左上角是原点,这就好办了 例子 索引 二分网格 使用cei ...
- Mac 完整卸载mysql
依次执行 cd ~ sudo rm /usr/local/mysql sudo rm -rf /usr/local/mysql* sudo rm -rf /Library/StartupItems/M ...
- PHP 使用非对称加密算法
加密的类型: 在日常设计及开发中,为确保数据传输和数据存储的安全,可通过特定的算法,将数据明文加密成复杂的密文.目前主流加密手段大致可分为单向加密和双向加密. 单向加密:通过对数据进行摘要计算生成密文 ...
- oeasy教您玩转python - 9 - # 换行字符
换行字符 回忆上次内容 数制可以转化 bin(n)可以把数字转化为 2进制 hex(n)可以把数字转化为 16进制 int(n)可以把数字转化为 10进制 编码和解码可以转化 encode 编码 ...
- oeasy教您玩转vim - 63 - # window分屏
窗口window 回忆上次 我们这次了解了缓冲区buffer ls可以查看buffer 如下是buffer缓冲的一些flag + 有修改未保存内容 - 可修改标签关闭 = 只读缓冲区 a 活跃缓冲 ...
- WPF/C#:实现导航功能
前言 在WPF中使用导航功能可以使用Frame控件,这是比较基础的一种方法.前几天分享了wpfui中NavigationView的基本用法,但是如果真正在项目中使用起来,基础的用法是无法满足的.今天通 ...
- 毕设项目:springboot+vue实现的在线求职平台
一.前言 随着信息技术的飞速发展和互联网的普及,线上求职已成为众多求职者和企业招聘的重要渠道.为满足市场需求,我们利用Spring Boot和Vue技术栈,开发了一款功能全面.用户友好的在线求职平台. ...
- OI-Wiki 学习笔记
算法基础 \(\text{Update: 2024 - 07 - 22}\) 复杂度 定义 衡量一个算法的快慢,一定要考虑数据规模的大小. 一般来说,数据规模越大,算法的用时就越长. 而在算法竞赛中, ...