1. 前言Regulator,中文名翻譯為“穩(wěn)定器”,在電子工程中,是voltage regulator(穩(wěn)壓器)或者current regulator(穩(wěn)流器)的簡稱,指可以自動維持恒定電壓(或電流)的裝置。 voltage regulator最早應用于功放電路中,主要用于濾除電源紋波(100或者120Hz)和噪聲,以及避免“輸出電壓隨負載的變化而變化”的情況。后來,隨著IC級別的regulator的出現(xiàn)(便宜了),voltage regulator幾乎存在于任何的電子設備中。例如我們常見的嵌入式設備中,基本上每一種電壓,都是經(jīng)過regulator輸出的。 相比較voltage regulator的廣泛使用,很少見到current regulator的應用場景(相信大多數(shù)的嵌入式工程師都沒有接觸過)。它一般存在于電流源中,除此之外,它廣泛存在于近年來新興的LED照明設備中。current regulator在LED設備中的作用主要有兩個:避免驅(qū)動電流超出最大額定值,影響其可靠性;獲得預期的亮度要求,并保證各個LED亮度、色度的一致性。 雖然原理比較復雜,但從設備驅(qū)動的角度看,regulator的控制應該很簡單,就是輸出的enable/disable、輸出電壓或電流的大小的控制。那么,linux kernel的regulator framework到底要做什么呢?這就是本文的目的:弄清楚regulator framework背后思考,并總結(jié)出其軟件架構(gòu)(和common clock framework類似,consumer/provider/core)。 注1:有關regulator的描述,參考自“http://sound./articles/vi-regulators.html”。 注2:kernel中有關regulator framework的介紹寫的相當好(Documentation\power\regulator\*),因此本文大部分內(nèi)容會參考這些文件。 2. 背后的思考Linux regulator framework的目的很直接:提供標準的內(nèi)核接口,控制系統(tǒng)的voltage/current regulators,并提供相應的機制,在系統(tǒng)運行的過程中,動態(tài)改變regulators的輸出,以達到省電的目的。 看似簡單的背后,有些因素不得不考慮。 1)最重要的,就是安全性:
2)系統(tǒng)中大部分的設備,都沒有動態(tài)更改regulator配置的需求,甚至連enable/disable都懶得關心的,framework需要考慮這種情況,盡量簡化接口。 3)會存在同一個regulator向多個設備提供power的情況,如果這些設備的需求不同怎么辦? 4)regulator之間是否可以級聯(lián)?如果可以,怎么處理? 這些思考最終都會反映到軟件設計上,具體可參考如下的軟件架構(gòu)。 3. 軟件架構(gòu)基于上面的思考,regulator framework的軟件架構(gòu)如下: 除了machine之外,基本上和common clock framework的consumer/provider框架類似。 3.1 machine machine的主要功能,是使用軟件語言(struct regulator_init_data),靜態(tài)的描述regulator在板級的物理現(xiàn)狀,包括: 1)前級regulator(即該regulator的輸入是另一個regulator的輸出,簡稱supply regulator)和后級regulator(即該regulator的輸出是其它regulator的輸入,簡稱consumer regulator)。
2)該regulator的物理限制(struct regulation_constraints),包括:
這些限制關系到系統(tǒng)安全,因此必須小心配置。配置完成后,在系統(tǒng)運行的整個過程中,它們都不會再改變了。 3.2 driver driver模塊的功能,是從regulator driver的角度,抽象regulator設備。 1)使用struct regulator_desc描述regulator的靜態(tài)信息,包括:名字、supply regulator的名字、中斷號、操作函數(shù)集(struct regulator_ops)、使用regmap時相應的寄存器即bitmap等等。 2)使用struct regulator_config,描述regulator的動態(tài)信息(所謂的動態(tài)信息,體現(xiàn)在struct regulator_config變量都是局部變量,因此不會永久保存),包括struct regulator_init_data指針、設備指針、enable gpio等等。 3)提供regulator的注冊接口(regulator_register/devm_regulator_register),該接口接受描述該regulator的兩個變量的指針:struct regulator_desc和struct regulator_config,并分配一個新的數(shù)據(jù)結(jié)構(gòu)(struct regulator_dev,從設備的角度描述regulator),并把靜態(tài)指針(struct regulator_desc)和動態(tài)指針(struct regulator_config)提供的信息保存在其中。 4)最后,regulator driver將以為struct regulator_dev指針為對象,對regulator進行后續(xù)的操作。 3.3 consumer consumer的功能,是從regulator consumer的角度,抽象regulator設備(struct regulator),并提供regulator操作相關的接口。包括: 3.4 core core負責上述邏輯的具體實現(xiàn),并以sysfs的形式,向用戶空間提供接口。 4. 接口匯整本節(jié)對regulator framework向各個層次提供的API做一個匯整,具體細節(jié)會在后續(xù)的文章中詳細描述。 4.1 consumer模塊向內(nèi)核空間consumer提供的接口 regulator framework向內(nèi)核空間consumer提供的接口位于“include/linux/regulator/consumer.h”中,包括regulator的獲取、使能、修改等接口,如下。 1)struct regulator struct regulator結(jié)構(gòu)用于從consumer的角度抽象一個regulator,consumer不需要關心該結(jié)構(gòu)的細節(jié),當作一個句柄使用即可(類似struct clk)。 2)regulator的get/put接口 1: struct regulator *__must_check regulator_get(struct device *dev, 2: const char *id); 3: struct regulator *__must_check devm_regulator_get(struct device *dev, 4: const char *id); 5: struct regulator *__must_check regulator_get_exclusive(struct device *dev, 6: const char *id); 7: struct regulator *__must_check devm_regulator_get_exclusive(struct device *dev, 8: const char *id); 9: struct regulator *__must_check regulator_get_optional(struct device *dev, 10: const char *id); 11: struct regulator *__must_check devm_regulator_get_optional(struct device *dev, 12: const char *id); 13: void regulator_put(struct regulator *regulator); 14: void devm_regulator_put(struct regulator *regulator);
3)supply alias相關的接口 1: int regulator_register_supply_alias(struct device *dev, const char *id, 2: struct device *alias_dev, 3: const char *alias_id); 4: void regulator_unregister_supply_alias(struct device *dev, const char *id); 5:
6: int devm_regulator_register_supply_alias(struct device *dev, const char *id, 7: struct device *alias_dev, 8: const char *alias_id); 9: void devm_regulator_unregister_supply_alias(struct device *dev, 10: const char *id); 11:
12: int devm_regulator_bulk_register_supply_alias(struct device *dev, 13: const char *const *id, 14: struct device *alias_dev, 15: const char *const *alias_id, 16: int num_id); 17: void devm_regulator_bulk_unregister_supply_alias(struct device *dev, 18: const char *const *id, 19: int num_id);
4)regulator的控制、狀態(tài)獲取接口 1: int __must_check regulator_enable(struct regulator *regulator); 2: int regulator_disable(struct regulator *regulator); 3: int regulator_force_disable(struct regulator *regulator); 4: int regulator_is_enabled(struct regulator *regulator); 5: int regulator_disable_deferred(struct regulator *regulator, int ms); 6:
7: int regulator_can_change_voltage(struct regulator *regulator); 8: int regulator_count_voltages(struct regulator *regulator); 9: int regulator_list_voltage(struct regulator *regulator, unsigned selector); 10: int regulator_is_supported_voltage(struct regulator *regulator, 11: int min_uV, int max_uV); 12: unsigned int regulator_get_linear_step(struct regulator *regulator); 13: int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV); 14: int regulator_set_voltage_time(struct regulator *regulator, 15: int old_uV, int new_uV); 16: int regulator_get_voltage(struct regulator *regulator); 17: int regulator_sync_voltage(struct regulator *regulator); 18: int regulator_set_current_limit(struct regulator *regulator, 19: int min_uA, int max_uA); 20: int regulator_get_current_limit(struct regulator *regulator); 21:
22: int regulator_set_mode(struct regulator *regulator, unsigned int mode); 23: unsigned int regulator_get_mode(struct regulator *regulator); 24: int regulator_set_optimum_mode(struct regulator *regulator, int load_uA); 25:
26: int regulator_allow_bypass(struct regulator *regulator, bool allow); 27:
28: struct regmap *regulator_get_regmap(struct regulator *regulator); 29: int regulator_get_hardware_vsel_register(struct regulator *regulator, 30: unsigned *vsel_reg, 31: unsigned *vsel_mask); 32: int regulator_list_hardware_vsel(struct regulator *regulator, 33: unsigned selector); 34:
5)bulk型的操作(一次操作多個regulator) 1: int regulator_bulk_register_supply_alias(struct device *dev, 2: const char *const *id, 3: struct device *alias_dev, 4: const char *const *alias_id, 5: int num_id); 6: void regulator_bulk_unregister_supply_alias(struct device *dev, 7: const char * const *id, int num_id); 8: int __must_check regulator_bulk_get(struct device *dev, int num_consumers, 9: struct regulator_bulk_data *consumers); 10: int __must_check devm_regulator_bulk_get(struct device *dev, int num_consumers, 11: struct regulator_bulk_data *consumers); 12: int __must_check regulator_bulk_enable(int num_consumers, 13: struct regulator_bulk_data *consumers); 14: int regulator_bulk_disable(int num_consumers, 15: struct regulator_bulk_data *consumers); 16: int regulator_bulk_force_disable(int num_consumers, 17: struct regulator_bulk_data *consumers); 18: void regulator_bulk_free(int num_consumers, 19: struct regulator_bulk_data *consumers); 6)notifier相關的接口 1: int regulator_register_notifier(struct regulator *regulator, 2: struct notifier_block *nb); 3: int regulator_unregister_notifier(struct regulator *regulator, 4: struct notifier_block *nb);
7)其它接口 1: /* driver data - core doesn't touch */ 2: void *regulator_get_drvdata(struct regulator *regulator); 3: void regulator_set_drvdata(struct regulator *regulator, void *data);
4.2 consumer模塊向用戶空間consumer提供的接口 用戶空間程序可以通過sysfs接口,使用regulator,就像內(nèi)核空間consumer一樣。這些接口由“drivers/regulator/userspace-consumer.c”實現(xiàn),主要包括:
4.3 machine模塊向regulator driver提供的接口 machine模塊主要提供struct regulator_init_data、struct regulation_constraints constraints等數(shù)據(jù)結(jié)構(gòu),用于描述板級的regulator配置,具體可參考3.1中介紹。 4.4 driver模塊向regulator driver提供的接口 regulator framework向regulator driver提供的接口位于“include/linux/regulator/driver.h”中,包括數(shù)據(jù)結(jié)構(gòu)抽象、regulator注冊等。 1)struct regulator_desc、struct regulator_config和struct regulator_dev 見3.2中的介紹。 2)regulator設備的注冊接口 1: struct regulator_dev * 2: regulator_register(const struct regulator_desc *regulator_desc, 3: const struct regulator_config *config); 4: struct regulator_dev * 5: devm_regulator_register(struct device *dev, 6: const struct regulator_desc *regulator_desc, 7: const struct regulator_config *config); 8: void regulator_unregister(struct regulator_dev *rdev); 9: void devm_regulator_unregister(struct device *dev, struct regulator_dev *rdev); 見3.2中的介紹。 3)其它接口,請參考后續(xù)的文章。 4.5 core模塊向用戶空間提供的sysfs接口 regulator設備在內(nèi)核中是以regulator class的形式存在的,regulator core通過class->dev_groups的方式,提供了一些默認的attribute,包括:
另外,如果regulator driver需要提供更多的attribute(如狀態(tài)、最大/最小電壓等等),可以調(diào)用add_regulator_attributes接口,主動添加。 原創(chuàng)文章,轉(zhuǎn)發(fā)請注明出處。蝸窩科技,www.。 標簽: Linux framework regulator 軟件架構(gòu) 評論:
tigger
2015-03-24 11:26 hi wowo
我有個問題想請教,我的理解,arm的電,都是靠PMIC給供的。那PMIC的電,跟regulator是怎么對應上的呢??物理上肯定是有連線的。 或者說,比如一個regulator是vdd1v8,那這個肯定是PMIC那邊的1V8供過來的?還是隨便一個regulator,只是軟件寫成1v8,然后PMIC就會出這個電?
wowo
2015-03-24 14:38 @tigger:tigger,我不是很明白您的意思。PMIC是一個硬件設備,regulator也是硬件設備。只不過,大多數(shù)時候,regulator集成在PMIC的內(nèi)部了,因此會出現(xiàn);類似下面的設備拓撲結(jié)構(gòu)(以DTS的形式):
PMICx { avdd0 { }; vcc1_8 { }; ... }; driver的編寫形式為: pmic_probe { ... regulator_register(1...); regulator_register(2...); ... }; 因此regulator的控制(包括enable、disable、modify value等),還是需要依賴parent driver(PMIC)的實現(xiàn)的。 |
|
來自: 老匹夫 > 《Regulator》