电量计驱动的简易框架

背景

最近调试了一个电量计的问题,顺便把电量计驱动的框架简单梳理了一下

  • Kernel: 5.15
  • 以cw2015电量计的驱动为例

整体框架

代码主要位于:drivers/power/supply/power supply class的实现,具体的电量计、充电IC等设备驱动都在此目录下

整体框架大致如下:

power supply class

power supply class为编写供电设备(power supply,后面简称PSY)的驱动提供了统一的框架,功能包括:

  • 抽象PSY设备的共性,向用户空间提供统一的API。
  • 为底层PSY驱动的编写,提供简单、统一的方式。同时封装并实现公共逻辑,驱动工程师只需把精力集中在和硬件相关的部分即可。

power supply class主要由4部分组成:

  1. power supply core,用于抽象核心数据结构、实现公共逻辑。对应drivers/power/supply/power_supply_core.c
  2. power supply sysfs,实现sysfs以及uevent功能。对应drivers/power/supply/power_supply_sysfs.c
  3. power supply leds,基于linux led class,提供PSY设备状态指示的通用实现。对应drivers/power/supply/power_suppply_leds.c
  4. power supply hwmon,基于hwmon子系统,提供检测设备相关状态的接口,比如温度、电流等,对应drivers/power/supply/power_supply_hwmon.c

详细相关power supply class的知识点可参见蜗窝相关的博文(见文章最后的参考地址), 这里不再赘述

电量计驱动主要流程:

电量计一般是一个I2C设备,所以整体上看就是一个I2C设备驱动,所以先注册:

module_i2c_driver(xxx_driver);

当设备与驱动匹配后就会调用驱动相应的probe函数,里面会有一系列的设备初始化,向子系统注册,工作队列或处理线程初始化等操作,大致的流程如下:

\-> xxx_probe
	\-> 获取properties并初始化电量计,主要是充电曲线等
	\-> devm_regmap_init_i2c 初始化regmap来读写寄存器
	\-> devm_power_supply_register 注册power-supply,根据实际情况,实现这些properties的get/set接口
	\-> power_supply_get_battery_info 获取电池信息
	\-> queue_delayed_work 初始化并开始一个delay work来定时获取电量计状态

在定时work中,更新电量计状态,状态变化时,通过power_supply_changed,通知power supply core

电量计主要是监测获取电池状态并提供给用户空间,功能相对来说比较单一,所以驱动比较简单

参考

power supply class相关说明见:
http://www.wowotech.net/pm_subsystem/psy_class_overview.html