击上方“一口Linux”,选择“置顶/星标公众号”
干货福利,第一时间送达!
一、bq24735简介
bq24735是一款高效率同步电瓶充电器。
当系统供电需求暂时低于适配器最大供电水平的时侯,bq24735使用智能加速技术来准许电瓶向系统中释放能量,这样的话将保护适配器不被毁坏。
bq24735为满足手动系统电源选择的须要,使用2个充电泵来分别驱动n-通道MOSFET(ACFET,RBFET和BATFET)。
SMBus(I2C总线)控制的输入电压,充电电压,和充电电流DAC容许特别高的调节精度,此调节精度可通过系统功率管理微控制器很容易地进行编程。
bq24735使用内部输入电压寄存器或则外部ILIM引脚来缓解PWM调制速率以减少充电电压。
二、Linux内核充电构架
要想理解bq24735驱动,必须首先理解Android供电系统框架,最重要的知识点是powersupply。
1.Android供电系统框架
powersupply(以下简称psy)是Linux中从供电驱动具象下来的子系统,是Linux电源管理的重要组成部份。
psy是一个中间层,在kernel中是属于设备驱动的一部份,psy的作用主要是向用户空间汇总各种供电的状态信息。
具象下来的各种信息称为property,例如供电设备是否联接就对应着POWER_SUPPLY_PROP_ONLINE。
2.powersupply功能
power_supply的软件构架:
powersupplyframework功能包括:
具象PSY设备的共性,向用户空间提供统一的API;
为底层PSY驱动的编撰,提供简单、统一的方法,同时封装并实现公共逻辑。
powersupplyclass坐落drivers/power/目录中,主要由3部份组成(可参考右图的软件构架):
最后,驱动工程师可以基于powersupplyclass,实现具体的PSYdrivers,主要处理平台相关、硬件相关的逻辑。这种drivers都坐落drivers/power/power_supply目录下。
3.驱动层功能
在驱动层,主要是两大模块,与电瓶监控(fuelgauge)和与充放电管理(charger)相关的驱动(对应图中的battery.c和charger.c),这两大模块主要处理硬件相关的逻辑linux内核usb驱动架构,在硬件状态发生变化时,会触发相关的中断,驱动层会调用相应的中断函数,并更新更改相应的psy节点值。
fuelgauge驱动主要是负责向下层android系统提供当前电瓶的电量以及健康状态信息等等,另外不仅这个以外,它也向charger驱动提供电瓶的相关信息;charger驱动主要负责电源线的拔插检查,以及充放电的过程管理。
对于battery管理,硬件上有电量计IC和充放电IC,其实有些厂家为了成本的考虑,也会把电量计和充放电功能集成到一个IC上,更有甚者,可能会把PMU功能也集成在一块硅面上。
4.其他问题
问:android如何晓得当前是哪些供电,充电中与否?
答:uevent机制(实质是net_link形式的socket)(广泛应用于hotplug)linux apache 虚拟主机,充电插入与断掉时,内核通过发送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会直接将电瓶传递给降糖电路,给系统供电当有电源供电的时侯redhat linux 9.0,bq24735会给电瓶充电。
2.引脚说明
在此我们只介绍与驱动相关的引脚
3.寄存器
bq24735用到的寄存器如下:
充电选项寄存器ChargeOptionsRegister[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: 抑制充电
该寄存器为可读写,假如要判定当前是否在充电,则可以读取该寄存器linux内核usb驱动架构,通过判定bit[0]是否为0来确认假如要判定当前是否存在,则可以读取该寄存器,通过判定bit[4]是否为1来确认
充电电压寄存器ChargeCurrentRegister(0x14H)
通过该寄存器可以设置充电电压。
例如我们要设置充电电压为3072mA,
该值为2048+1024,将对应的bite[10]/[11]为1,其他位为0
1100 0000 0000
即设置该寄存器值为:0xC00
充电电流寄存器ChargeVoltageRegister(0x15H)
该寄存器设置方式类似于充电电压寄存器
输入电压InputCurrentRegister(0x3FH)
该寄存器设置方式类似于充电电压寄存器
0xfe,0xff这两个寄存器分别读取MANUFACTURER_ID和DEVICE_ID
这两个值分别为:0x0040、0x000B
驱动初始化时可以通过读取这两个寄存器的值来判定,驱动是否和硬件匹配。
注意:一般寄存器0x14、0x15、0x3F值须要寻问硬件工程师
4.设备树
bq24735@9 {
compatible = "ti,bq24735";
reg = ;
ti,ac-detect-gpios = ;
ti,charge-current =;
ti,charge-voltage=;
ti,input-current =;
}
参数说明
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.驱动讲解
驱动文件内核代码中早已有该驱动
driverspowerbq24735-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流程稍做了更改,只有bq24735present的时侯就会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会触发中断:
之后再断掉电源停止充电
end
一口Linux