当前位置:首页>Linux>深入理解Linux Power Supply Framework

深入理解Linux Power Supply Framework

  • 2026-10-23 14:37:22
深入理解Linux Power Supply Framework

在 Linux 内核中,Power Supply Framework是用于描述和管理电池、充电器、外部电源的一套标准子系统。

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

一、Power Supply Framework 在内核中负责什么?

Power Supply Framework 的核心目标只有两个:

  • • 抽象 power supply(PSY)设备的共性,并向用户空间提供统一接口
  • • 为电池/充电相关驱动提供一致、低成本的接入框架,并封装公共逻辑

它并不关心具体芯片型号,也不直接实现充电策略,而是提供一个标准化的“电源状态模型”。

二、Power Supply Framework 在内核中的位置

源码目录:drivers/power/

典型的 PSY 设备包括:

  • • Battery(电池 / Fuel Gauge)
  • • USB / AC / DC(外部供电)
  • • Charger(充电 IC)
  • • Charger Manager(策略层)

最终,这些设备都会统一出现在:/sys/class/power_supply/

三、Power Supply Class 的整体架构

Power Supply 子系统主要由三部分组成:

               1)Power Supply Core            

路径:drivers/power/power_supply_core.c

职责:

  • • 定义核心数据结构
  • • 管理 PSY 设备生命周期
  • • 处理属性变化
  • • 触发 notifier 与 uevent
struct power_supply {     const char *name;     enum power_supply_type type;     enum power_supply_property *properties;     size_t num_properties;     char **supplied_to;     size_t num_supplicants;      char **supplied_from;     size_t num_supplies;#ifdef CONFIG_OF     struct device_node *of_node;#endif     int (*get_property)(struct power_supply *psy,                 enum power_supply_property psp,                 union power_supply_propval *val);     int (*set_property)(struct power_supply *psy,                enum power_supply_property psp,                 const union power_supply_propval *val);     int (*property_is_writeable)(struct power_supply *psy,                      enum power_supply_property psp);     void (*external_power_changed)(struct power_supply *psy);     void (*set_charged)(struct power_supply *psy);     /* For APM emulation, think legacy userspace. */     int use_for_apm;     /* private */     struct device *dev;     struct work_struct changed_work;     spinlock_t changed_lock;     bool changed;     struct wake_lock work_wake_lock;#ifdef CONFIG_THERMAL     struct thermal_zone_device *tzd;     struct thermal_cooling_device *tcd;#endif#ifdef CONFIG_LEDS_TRIGGERS     struct led_trigger *charging_full_trig;     char *charging_full_trig_name;     struct led_trigger *charging_trig;     char *charging_trig_name;     struct led_trigger *full_trig;     char *full_trig_name;     struct led_trigger *online_trig;     char *online_trig_name;     struct led_trigger *charging_blink_full_solid_trig;     char *charging_blink_full_solid_trig_name;#endif};
power_supply向外提供了接口以供具体驱动来使用,主要接口如下:
struct power_supply *power_supply_get_by_name(const char *name);voidpower_supply_changed(struct power_supply *psy);intpower_supply_am_i_supplied(struct power_supply *psy);intpower_supply_set_battery_charged(struct power_supply *psy);intpower_supply_set_current_limit(struct power_supply *psy, int limit);intpower_supply_set_online(struct power_supply *psy, bool enable);intpower_supply_set_present(struct power_supply *psy, bool enable);intpower_supply_set_scope(struct power_supply *psy, int scope);intpower_supply_set_charge_type(struct power_supply *psy, int type);intpower_supply_set_supply_type(struct power_supply *psy,enum power_supply_type supply_type);intpower_supply_is_system_supplied(void);intpower_supply_register(struct device *parent,struct power_supply *psy);voidpower_supply_unregister(struct power_supply *psy);intpower_supply_powers(struct power_supply *psy, struct device *dev);

上面的 register 和 unregister 接口是用来注册和反注册 power supply 设备的接口,当该 power supply 设备中有监测信息变化时,使用 power_supply_changed 接口用来通知上层,这种通知机制采用的是 netlink socket 接口来实现的,具体实现参见该函数体。最终函数会通过netlink socket发送出来一系列的字符串,比如 POWER_SUPPLY_NAME=battery,当上层daemon服务程序收到该提醒后,就会去读取相应驱动提供的 sysfs 接口文件来获取相应的信息。

               2)Power Supply Sysfs            

路径:drivers/power/power_supply_sysfs.c

职责:

  • • 创建 /sys/class/power_supply/*
  • • 实现属性读写
  • • 生成 uevent(change 事件)
enum power_supply_property *properties;size_t num_properties;
               3)Power Supply LEDs            

路径:drivers/power/power_supply_leds.c

职责:

  • • 基于 Linux LED class
  • • 提供充电、满电、在线状态的通用指示机制
voidpower_supply_update_leds(struct power_supply *psy);intpower_supply_create_triggers(struct power_supply *psy);voidpower_supply_remove_triggers(struct power_supply *psy);

这几个 API 分别就是创建和删除 led_trigger,以及触发 LED。

四、核心数据结构解析

               1. struct power_supply            

struct power_supply 用于抽象一个 PSY 设备实例:

  • • 内嵌 struct device
  • • 维护状态变化的 workqueue
  • • 管理 notifier、thermal、led 等资源

它代表的是运行时实体,通常由框架维护,驱动不直接操作其内部成员。

               2. struct power_supply_desc(驱动最核心部分)            

power_supply_desc 用于描述一个 PSY 设备“对外提供什么能力”。

关键字段包括:

  • • PSY 名称
  • • PSY 类型(battery / usb / mains 等)
  • • 支持的属性列表
  • • 属性的 get / set 回调
               3. power_supply_battery_info            

用于描述静态电池参数(容量、内阻、设计电压等),推荐用于 battery/fuel gauge 驱动,避免将固定参数散落在代码中。

写至此处,也该画上句号了。常言道,程序员的世界由0和1构成,但我逐渐意识到——更多的时候,我们面对的是“咦?这怎么又出错了?”
感谢您的阅读,希望我的些许探索,能够助您避开一些陷阱,更接近事实的真相。
敬请关注「码上求真」,期待下次与您相逢。

最新文章

随机文章