一、 概述
電源管理整體上可以分為兩個部分,一個是電池監控(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/”中)