在 Linux 内核中,Power Supply Framework 是一套用于描述和管理电池、充电器、外部电源等设备的标准化子系统。它的核心作用可以归纳为两点:
- 抽象 PSY 设备的共性,向用户空间提供统一的 API。
- 为底层 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/ 目录下,这正是它通过 sysfs 向用户空间暴露的统一接口。
三、Power Supply Class 的整体架构
Power Supply 子系统主要由三部分组成:
1)Power Supply Core
路径:drivers/power/power_supply_core.c
职责:
- 定义核心数据结构
- 管理 PSY 设备生命周期
- 处理属性变化
- 触发 notifier 与 uevent
核心数据结构 struct power_supply 用于抽象一个 PSY 设备实例:
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);
void power_supply_changed(struct power_supply *psy);
int power_supply_am_i_supplied(struct power_supply *psy);
int power_supply_set_battery_charged(struct power_supply *psy);
int power_supply_set_current_limit(struct power_supply *psy, int limit);
int power_supply_set_online(struct power_supply *psy, bool enable);
int power_supply_set_present(struct power_supply *psy, bool enable);
int power_supply_set_scope(struct power_supply *psy, int scope);
int power_supply_set_charge_type(struct power_supply *psy, int type);
int power_supply_set_supply_type(struct power_supply *psy, enum power_supply_type supply_type);
int power_supply_is_system_supplied(void);
int power_supply_register(struct device *parent, struct power_supply *psy);
void power_supply_unregister(struct power_supply *psy);
int power_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 事件)
struct power_supply_desc 中的以下两个字段决定了向用户空间暴露哪些属性:
enum power_supply_property *properties;
size_t num_properties;
3)Power Supply LEDs
路径:drivers/power/power_supply_leds.c
职责:
- 基于 Linux LED class
- 提供充电、满电、在线状态的通用指示机制
主要API:
void power_supply_update_leds(struct power_supply *psy);
int power_supply_create_triggers(struct power_supply *psy);
void power_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 驱动,避免将固定参数散落在代码中。
通过本文的介绍,希望能帮助你更清晰地理解 Linux 内核中 Power Supply Framework 的架构与工作原理。掌握这套框架,对于开发与电源、电池相关的嵌入式驱动至关重要。如果你想深入探讨更多内核或系统底层知识,欢迎在 云栈社区 的 网络/系统板块 或 基础 & 综合 板块与其他开发者交流学习。