Linux 中power supply软件架构和相关API

一、 概述

电源管理整体上可以分为两个部分,一个是电池监控(fuel gauge),另外一个是充放电管理。这两部分在内核中也是分为两个驱动来管理。fuelgauge驱动的功能主要是负责向上层Android系统提供当前电池的电量和健康信息等等。同时也向charger驱动提供电池的相关信息。charger驱动主要是负责电源线的插拔检测、充电器类型识别和充放电的过程管理等实务。
Power supply class 是为编写供电设备(power supply ,简称PSY)的驱动提供的统一框架
主要功能包括如下部分:
1. 抽象PSY设备共性,向用户空间提供统一的API
2. 为底层PSY驱动的编写提供简单统一的方式,同时封装并且实现公共逻辑,驱动工程师只要专注与硬件细节部分。

设计思路:
PSY driver的主要功能就是向用户空间程序汇总各类状态信息。因此power supply class的思路如下:
PSY driver负责:该PSY设备具有哪些属性,这些属性的值是什么,当属性值发生改变时要通知power supply class
Power supply class负责:将某个PSY设备支持的属性及其value以sysfs的形式提供给用户空间,当属性值改变时以uevent的形式广播给用户空间程序。,另外也会协助处理PSY级联的情况。

软件架构及API接口
Power supply class 位于driver/power目录中,主要由三部分组成:
1. power_supply_core.c 抽象核心数据结构实现公共逻辑
2. power_supply_sysfs.c 实现sysfs和uevent功能
3. power_supply_leds.c 提供PSY设备状态指示的通用实现
核心数据结构:

struct power_supply {
    const struct power_supply_desc *desc;
    char **supplied_to;          //当此电源变化时需要通知的电源模块 name
    size_t num_supplicants;      // supplied_to 数组的大小

    char **supplied_from;        //接收其他电源模块发生变化时的通知 name
    size_t num_supplies;         // supplied_from 数组的大小
    struct device_node *of_node;

    /* Driver private data */
    void *drv_data;

    /* private */
    struct device dev;
//工作队列,相当与一个内核线程,主要思路是该PSY设备状态改变了就启用一个workqueue,查询并通知所有由他发起supplicants 
struct work_struct changed_work;
    struct delayed_work deferred_register_work;
    spinlock_t changed_lock;
    bool changed;
    bool initialized;
    atomic_t use_cnt;
#ifdef CONFIG_THERMAL
    struct thermal_zone_device *tzd;
    struct thermal_cooling_device *tcd;
#endif
#ifdef CONFIG_LEDS_TRIGGERS   //LED相关的操作省略显示。。
#endif
};

其中 power_supply_desc 定义如下:

struct power_supply_desc {
    const char *name;                //电源名称
    enum power_supply_type type;     //电源类型 为电池 USB或者。。
    enum power_supply_property *properties; //该电源的属性
    size_t num_properties;                //该电源属性的数目
    //读取属性值
    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);
    bool no_thermal;                     //设置本电源会不会产生热源
    int use_for_apm;            //For APM emulation, think legacy userspace.
};

向具体的PSY driver提供的API接口
1. PSY的register/unregister API

power_supply_register(struct device *parent,const struct power_supply_desc *desc,
                       const struct power_supply_config *cfg)
power_supply_register_no_ws(struct device *parent,const struct power_supply_desc *desc,const struct power_supply_config *cfg)
power_supply_unregister(struct power_supply *psy)

power_supply_register 和 power_supply_register_no_ws的区别:
power_supply_register_no_ws 没有weakup系统的能力
2. PSY状态发生改变时的API
power_supply_changed(struct power_supply *psy)
当PSY driver 检测到设备某些属性值发生改变时需要调用这个接口,通知我们的
Power supply core ,Power supply core 会有如下动作:
1) 如果该PSY是其他PSY的供电源,调用这些PSY的external_power_changed回调函数,通知他们。
2) 如果配置了CONFIG_LEDS_TRIGGERS,调用power_supply_update_leds更新该PSY有关的LED状态。
3) 发送notifier ,通知那些关心PSY设备状态的drivers.
4) 以统一的格式向用户空间发送uevent
3.其他杂项接口

extern struct power_supply *power_supply_get_by_name(const char *name); 
extern struct power_supply *power_supply_get_by_phandle(struct device_node *np, 
                                                           const char *property); 
extern int power_supply_am_i_supplied(struct power_supply *psy); 
extern int power_supply_set_battery_charged(struct power_supply *psy); 
extern int power_supply_is_system_supplied(void); 
extern int power_supply_powers(struct power_supply *psy, struct device *dev);

power_supply_get_by_name,通过名字获取PSY指针。
power_supply_get_by_phandle,从DTS中,解析出对应的PSY指针。
power_supply_am_i_supplied,查询自己是否由其它PSY供电。
power_supply_set_battery_charged,调用指定PSY的set_charged回调。
power_supply_is_system_supplied,查询系统是否有有效的或者处于online状态的PSY,如果没有,可能为桌面系统。
power_supply_powers,在指定设备(通常是该PSY设备)的sysfs目录(/sys/devices/xxx/)下,创建指定PSY的符号链接(/sys/devices/xxx/powers)。

4.向其它driver提供的用于接收PSY状态改变notifier的API

extern int power_supply_reg_notifier(struct notifier_block *nb); 
extern void power_supply_unreg_notifier(struct notifier_block *nb);

通过notifier注册接口注册notifier之后,系统任何PSY设备的状态发生改变,并调用了power_supply_changed接口,power supply core就是通知notifier的监听者。
5. 向用户空间程序提供的API
power supply class通过两种形式向用户空间提供接口。
1)uevent 以“名字=value”的形式,上报所有property的值
uevent一般会在PSY设备添加到kernel时,或者PSY属性发生改变时(可参考3.3中的介绍)发送。
2)sysfs 如果某个PSY设备具有某个属性,该属性对应的attribute就会体现在sysfs中(一般位于“/sys/class/power_supply/xxx/”中)

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`power_supply_get_property`、`power_supply_set_property`、`power_supply_property_is_writeable` 是 Linux 内核与电源管理相关的函数,主要用于获取和设置电源供应设备的属性值。下面分别对这三个函数进行详细说明: 1. `power_supply_get_property` 函数 `power_supply_get_property` 函数用于获取电源供应设备的属性值。其函数原型为: ``` int power_supply_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val); ``` 其,`psy` 是指向 `struct power_supply` 结构体的指针,用于指定要获取属性的电源供应设备;`psp` 是一个枚举类型的值,用于指定要获取的属性名称;`val` 是一个 `union` 类型的变量,用于存储获取到的属性值。 使用 `power_supply_get_property` 函数时,需要先定义一个 `struct power_supply` 类型的变量,并将其指针传递给函数。同时需要指定要获取的属性名称,可以通过 `enum power_supply_property` 枚举类型来指定。获取到的属性值会被存储在 `union power_supply_propval` 变量。这个变量包含了多种类型的属性值,可以根据属性的类型来获取相应的值。 2. `power_supply_set_property` 函数 `power_supply_set_property` 函数用于设置电源供应设备的属性值。其函数原型为: ``` int power_supply_set_property(struct power_supply *psy, enum power_supply_property psp, const union power_supply_propval *val); ``` 其,`psy` 是指向 `struct power_supply` 结构体的指针,用于指定要设置属性的电源供应设备;`psp` 是一个枚举类型的值,用于指定要设置的属性名称;`val` 是一个 `const union` 类型的指针,用于指定要设置的属性值。 使用 `power_supply_set_property` 函数时,需要先定义一个 `struct power_supply` 类型的变量,并将其指针传递给函数。同时需要指定要设置的属性名称和属性值,可以通过 `enum power_supply_property` 枚举类型和 `union power_supply_propval` 变量来指定。需要注意的是,某些属性可能是只读的,不能通过这个函数来设置属性值。 3. `power_supply_property_is_writeable` 函数 `power_supply_property_is_writeable` 函数用于判断电源供应设备的某个属性是否可写。其函数原型为: ``` int power_supply_property_is_writeable(struct power_supply *psy, enum power_supply_property psp); ``` 其,`psy` 是指向 `struct power_supply` 结构体的指针,用于指定要查询的电源供应设备;`psp` 是一个枚举类型的值,用于指定要查询的属性名称。 使用 `power_supply_property_is_writeable` 函数时,需要先定义一个 `struct power_supply` 类型的变量,并将其指针传递给函数。同时需要指定要查询的属性名称,可以通过 `enum power_supply_property` 枚举类型来指定。函数会返回一个整型值,表示该属性是否可写。如果可写,则返回 1,否则返回 0。 这三个函数是 Linux 内核电源管理的重要函数,可以用于获取和设置电源供应设备的属性值,帮助开发人员进行电源管理的相关工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值