轉載請注明轉自:http://www.cnblogs.com/connectfuture/
參考自linux-2.6.32.61\Documentation\power\regulator
一、簡介
電源框架能夠動態調節電源輸出,以達到省電效果。
二、基本術語
-
Regulator
供其他設備電源的電子設備,一些電源具有開關及控制輸出的電壓電流。
-
PMIC(Power Management IC)
電源管理芯片,內涵多個電源甚至其他子系統。
-
Consumer
由regulator供電的設備統稱為consumer,其可分為靜態和動態兩類。
靜態:不需要改變電壓電流,只需要開關電源,通常在bootloader、firmware、kernel board階段被設置。
動態:根據操作需求改變電壓電流。
-
Power Domain
由電源或者其他電源域的輸出作為輸入的電路。
電源在開關之后,如下圖所示:
Regulator -+-> Switch-1 -+-> Switch-2 --> [Consumer A]
| |
| +-> [Consumer B], [Consumer C]
|
+-> [Consumer D], [Consumer E]
其為一個電源和三個電源域:
Domain 1: Switch-1, Consumers D & E.
Domain 2: Switch-2, Consumers B & C.
Domain 3: Consumer A.
其三者有輸出關系(1的輸出作為2的輸入,2的輸出作為3的輸入):
Domain-1 --> Domain-2 --> Domain-3.
一個電源域的電源還可以由其他電源提供,如:
Regulator-1 -+-> Regulator-2 -+-> [Consumer A]
|
+-> [Consumer B]
這里有兩個電源域:
Domain 1: Regulator-2, Consumer B.
Domain 2: Consumer A.
其輸出關系:
Domain-1 --> Domain-2
-
Constraints
約束,用於定義電源特性和保護硬件,可划分為以下三方面:
Regulator Level:
定義了電源硬件的參數規格,如:
- voltage output is in the range 800mV -> 3500mV.
- regulator current output limit is 20mA @ 5V but is 10mA @ 10V.
Power Domain Level:
由kernel board初始化代碼定義,其約束電源域的電源范圍,如:
- Domain-1 voltage is 3300mV
- Domain-2 voltage is 1400mV -> 1600mV
- Domain-3 current limit is 0mA -> 20mA.
Consumer Level:
由驅動設置,動態調整電流電壓。
約束示例:
e.g. a consumer backlight driver asks for a current increase from 5mA to 10mA to increase LCD illumination. This passes to through the levels as follows :-
Consumer: need to increase LCD brightness. Lookup and request next current mA value in brightness table (the consumer driver could be used on several different personalities based upon the same reference device).
Power Domain: is the new current limit within the domain operating limits for this domain and system state (e.g.battery power, USB power)
Regulator Domains: is the new current limit within the regulator operating parameters for input/output voltage.
If the regulator request passes all the constraint tests then the new regulator value is applied.
三、Regulator Consumer Driver Interface
-
Consumer Regulator Access (static & dynamic drivers)
regulator = regulator_get(dev, "Vcc");
通過此接口獲取該驅動對應的regulator。dev為驅動對應的設備指針,“Vcc"為電源ID。內核會查表找到電源ID對應的regulator。
regulator_put(regulator);
通過此接口釋放regulator。
regulator_get和regulator_put通常在driver的probe和remove中調用。
-
Regulator Output Enable & Disable (static & dynamic drivers)
int regulator_enable(regulator);
通過此接口使能電源輸出。
注:在調此函數前,電源輸出可能已經被使能了。
NOTE: The supply may already be enabled before regulator_enabled() is called.
This may happen if the consumer shares the regulator or the regulator has been
previously enabled by bootloader or kernel board initialization code.
int regulator_is_enabled(regulator);
通過此接口判斷電源輸出是否已被使能。返回值大於0時已使能。
int regulator_disable(regulator);
通過此接口關閉電源輸出。
注:在調此函數后,電源未必立刻關閉,存在共享電源場景。
NOTE: This may not disable the supply if it's shared with other consumers. The
regulator will only be disabled when the enabled reference count is zero.
int regulator_force_disable(regulator);
通過此接口立刻關閉電源。
-
Regulator Voltage Control & Status (dynamic drivers)
int regulator_set_voltage(regulator, min_uV, max_uV);
通過此接口能調節電壓的最小和最大輸出。
注:調用時機
NOTE: this can be called when the regulator is enabled or disabled. If called
when enabled, then the voltage changes instantly, otherwise the voltage
configuration changes and the voltage is physically set when the regulator is
next enabled.
int regulator_get_voltage(regulator);
通過此接口獲取配置的輸出電壓。
NOTE: get_voltage() will return the configured output voltage whether the
regulator is enabled or disabled and should NOT be used to determine regulator
output state. However this can be used in conjunction with is_enabled() to
determine the regulator physical output voltage.
四、Regulator Machine Driver Interface
之前提到的電源域具有拓撲結構,當子節點的電源被打開時,對應的一系列父節點也會打開,在如下regulator machine中會提及:

1 Regulator Machine Driver Interface 2 =================================== 3 4 The regulator machine driver interface is intended for board/machine specific 5 initialisation code to configure the regulator subsystem. 6 7 Consider the following machine :- 8 9 Regulator-1 -+-> Regulator-2 --> [Consumer A @ 1.8 - 2.0V] 10 | 11 +-> [Consumer B @ 3.3V] 12 13 The drivers for consumers A & B must be mapped to the correct regulator in 14 order to control their power supply. This mapping can be achieved in machine 15 initialisation code by creating a struct regulator_consumer_supply for 16 each regulator. 17 18 struct regulator_consumer_supply { 19 struct device *dev; /* consumer */ 20 const char *supply; /* consumer supply - e.g. "vcc" */ 21 }; 22 23 e.g. for the machine above 24 25 static struct regulator_consumer_supply regulator1_consumers[] = { 26 { 27 .dev = &platform_consumerB_device.dev, 28 .supply = "Vcc", 29 },}; 30 31 static struct regulator_consumer_supply regulator2_consumers[] = { 32 { 33 .dev = &platform_consumerA_device.dev, 34 .supply = "Vcc", 35 },}; 36 37 This maps Regulator-1 to the 'Vcc' supply for Consumer B and maps Regulator-2 38 to the 'Vcc' supply for Consumer A. 39 40 Constraints can now be registered by defining a struct regulator_init_data 41 for each regulator power domain. This structure also maps the consumers 42 to their supply regulator :- 43 44 static struct regulator_init_data regulator1_data = { 45 .constraints = { 46 .min_uV = 3300000, 47 .max_uV = 3300000, 48 .valid_modes_mask = REGULATOR_MODE_NORMAL, 49 }, 50 .num_consumer_supplies = ARRAY_SIZE(regulator1_consumers), 51 .consumer_supplies = regulator1_consumers, 52 }; 53 54 Regulator-1 supplies power to Regulator-2. This relationship must be registered 55 with the core so that Regulator-1 is also enabled when Consumer A enables it's 56 supply (Regulator-2). The supply regulator is set by the supply_regulator_dev 57 field below:- 58 59 static struct regulator_init_data regulator2_data = { 60 .supply_regulator_dev = &platform_regulator1_device.dev, 61 .constraints = { 62 .min_uV = 1800000, 63 .max_uV = 2000000, 64 .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, 65 .valid_modes_mask = REGULATOR_MODE_NORMAL, 66 }, 67 .num_consumer_supplies = ARRAY_SIZE(regulator2_consumers), 68 .consumer_supplies = regulator2_consumers, 69 }; 70 71 Finally the regulator devices must be registered in the usual manner. 72 73 static struct platform_device regulator_devices[] = { 74 { 75 .name = "regulator", 76 .id = DCDC_1, 77 .dev = { 78 .platform_data = ®ulator1_data, 79 }, 80 }, 81 { 82 .name = "regulator", 83 .id = DCDC_2, 84 .dev = { 85 .platform_data = ®ulator2_data, 86 }, 87 }, 88 }; 89 /* register regulator 1 device */ 90 platform_device_register(®ulator_devices[0]); 91 92 /* register regulator 2 device */ 93 platform_device_register(®ulator_devices[1]);