Regulator模块用于控制系统中某些设备的电压/电流供应。在嵌入式系统(尤其是手机)中,控制耗电量很重要,直接影响到电池的续航时间。所以,如果系统中某一个模块暂时不需要使用,就可以通过regulator关闭其电源供应;或者降低提供给该模块的电压、电流大小。
Regulator的文档在KERNEL/Documentation/Power/Regulator中。
2、几个重要结构:
regulator_dev
regulator_dev代表一个regulator设备。
struct regulator_dev {
struct regulator_desc *desc; // 描述符,包括regulator的名称、ID、regulator_ops等
int use_count; // 使用计数
/* lists we belong to */
struct list_head list; // regulator通过此结构挂到regulator_list链表中
struct list_head slist; // 如果有父regulator,通过此域挂到父regulator的链表
/* lists we own */
struct list_head consumer_list; // 此regulator负责供电的设备列表
struct list_head supply_list; //此regulator负责供电的子regulator
struct blocking_notifier_head notifier; // notifier,具体的值在consumer.h中,比如REGULATOR_EVENT_FAIL
struct mutex mutex;
struct module *owner;
struct device dev; // device结构,属于class regulator_class
struct regulation_constraints *constraints; // 限制,比如最大电压/电流、最小电压/电流
struct regulator_dev *supply; // 父regulator的指针
void *reg_data; /* regulator_dev data */
};
regulator_init_data
regulator_init_data在初始化时使用,用来建立父子regulator、受电模块之间的树状结构,以及一些regulator的基本参数。
struct regulator_init_data {
struct device *supply_regulator_dev; // 父regulator的指针
struct regulation_constraints constraints;
int num_consumer_supplies;
struct regulator_consumer_supply *consumer_supplies; // 负责供电的设备数组
/* optional regulator machine specific init */
int (*regulator_init)(void *driver_data); // 初始化函数
void *driver_data; /* core does not touch this */
};
其它结构体自己可以看看~如
struct regulator
struct regulation_constraints
struct regulator_init_data,用于初始化
struct regulator_consumer_supply ----->consumer信息
struct regulator_desc
struct regulator_map
regulator_desc
struct regulator_described{
const char* name;
int id;
unsigned n_voltages;
struct regulator_ops *ops;
int irq;
enum regulator_type type;
struct module *owner;
}
3、注册regulator
板级信息和regulator_desc准备好之后就要注册了。
通过regulator_register函数登记生成一个regulator_dev。
struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, struct device *dev, struct regulator_init_data *init_data,void *driver_data)
{
struct regulator_dev *rdev;
....
//fill struct regulator_dev结构;
device_register(&rdev->dev); // 注册设备
// 设置constraints,其中可能会包括供电状态的初始化(设置初始电压,enable/disable等等)
set_machine_constraints(rdev, &init_data->constraints);
add_regulator_attributes (rdev);
// 设置此regulator与其负责供电的设备之间的联系
for (i = 0; i < init_data->num_consumer_supplies; i++)
ret = set_consumer_device_supply(rdev, init_data->consumer_supplies[i].dev,
init_data->consumer_supplies[i].supply);
// 将regulator加入一个链表,该链表包含所有regulator
list_add(&rdev->list, ®ulator_list);
.......
}
set_consumer_device_supply函数用于登记regulator_dev与comsumer_dev(regulator负责供电的设备)之间的对应关系。对于每一个regulator_dev—comsumer_dev的配对,都会有一个regulator_map结构,这些结构会被加入到全局链表regulator_map_list中。
4、regulator应用
在设备驱动使用regulator对其驱动的设备供电时,需要首先保证设备与对应regulator之间的匹配关系已经被登记到regulator框架中。
设备驱动通过regulator_get函数得到regulator结构,此函数通过前文所述regulator_map_list找到对应regulator_dev,再生成regulator结构给用户使用。
通过regulator_enable / regulator_disable打开、关闭regulator,这两个函数最终都是调用struct regulator_ops里的对应成员。
除此之外,还有regualtor_set_voltage / regulator_get_voltage等等。
具体代码查看:/kernel/driver/regulator/core.c
以下文字来自:http://www.ednchina.com/ART_50292_28_0_AN_0573b455_2.HTM
1 校准器的基本概念
所谓校准器实际是在软件控制下把输入的电源调节精心输出。例如电压的控制,输入时5V 输出是1.8V;电流的限制,最大20mA;简单的切换和电源的开关等,如图1所示。
图1 校准器
电源域是一组校准器,设备组成、输入可能是校准器,开关也许是电源域,电源域可以级联,电源约束可以和电源域配合以保护硬件。例如一个Internet Tablet/PMP,它由CPU、NOR Flash、音频编解码器、触摸屏、LCD控制器、USB、WiFi 等其他外设组成,如图2所示。
图2 Internet Tablet/PMP系统结构
为了实现上面的构想,需要在内核里建立一个校准器构架,目的就是设计一个可以控制电压和电流的标准内核接口以节省电能,从而尽可能的延长电池的供应。这个内核的架构分为四个部分:针对设备驱动的消费接口(consumer)、校准器驱动的接口、系统配置的接口和面向应用sysfs的userspace接口。
2 Consumer的API
regulator = regulator_get(dev, “Vcc”);
其中,dev 是设备“Vcc”一个字符串代表,校准器(regulator)然后返回一个指针,也是regulator_put(regulator)使用的。
打开和关闭校准器(regulator)API如下。
int regulator_enable(regulator);
int regulator_disable(regulator);
3 电压的API
消费者可以申请提供给它们的电压,如下所示。
int regulator_set_voltage(regulator, int min_uV, int max_uV);
在改变电压前要检查约束,如下所示。
regulator_set_voltage(regulator,100000,150000)
电压值下面的设置改变如下所示。
int regulator_get_voltage)struct regulator *regulator);
4 电流的API
电流的API也是类似,需要指出的是,校准器的方法并不一定是最高的效率,效率和加载(如加载10mA电流)、操作模式都有关系,通过下面的API可以改变模式设置。
regulator_set_optimum_mode(requlator,10000);//10mA
5 校准器的驱动和系统配置
在实际使用校准器之前,需要按照下面的结构写校准器的驱动程序,然后注册后通知给消费者使用。
完成了校准器驱动程序之后,下一步就是系统设置(machine specific),即匹配如电压、LDO1和NAND等关系。
regulator_set_supply(“LDO1”,dev, “Vcc”)
对于userspace,校准器的使用是通过sysfs,但是目前所有的包括电压、电流、操作模式、限制等信息多只是只读信息,应该是非常适合象powerTop这样工具的使用。
6 应用
校准器的典型的应用包括如下:CPUfreq——CPU频率的调节;CPU idle——CPU空闲模式控制;LCD背光调节——通过电流控制LED灯的亮度达到控制LCD背光的目的;音频单元——如FM收音机在MP3使用的时候应该是关闭的,麦克风使用的时候,扬声器的放大器应该是关闭的;NAND/NOR存储器是耗电大户,根据不同操作方式(读/写、擦除等)优化操作模式(控制电流)达到节省电量的要求。同其他电源管理的方法比较,校准器方法具有一定的硬件独立和抽象性,简单实用,原理上可以适合任何有电源管理芯片支持嵌入式系统电源管理,目前已经移植到Freescale MC13783、Wolfson WM8350/8400等几个集成度很高的电源管理器件上了.
基于构件的面向CPU的电源管理技术
无论是PM_QoS、控制电压和电流的校准器方法,还是许许多多半导体公司支持自己CPU和电源管理芯片的Linux BSP电源管理部分,都还没有一个构建在更高层面的构件级嵌入式系统电源解决方案和商业产品。虽然包括CELF(消费和嵌入式Linux 论坛)和Intel主导的Mobile &Internet Linux项目都设立了专门的电源管理计划(power manager project),但是显然距离人们的要求和实际的应用还太远了。
Montavista在过去和IBM合作开发DPM(动态电源管理)技术的基础上,最近在专门针对手机、互联网移动终端、PMP/PDN等便携消费电子设备的mobilinux5.0上提出嵌入式电源管理技术的构件方法。Montavista的构件方式主要是针对以先进的多媒体应用处理器为核心的新一代嵌入式系统,比如Freescale的MX31、TI OMAP2430/3430为核心的系统级电源管理,它包含下面几个主要的部分。