现在的位置: 首页 > 综合 > 正文

Linux regulator分析

2017年04月12日 ⁄ 综合 ⁄ 共 5974字 ⁄ 字号 评论关闭
文章目录

Regulator模块用于控制系统中某些设备的电压/电流供应。在嵌入式系统(尤其是手机)中,控制耗电量很重要,直接影响到电池的续航时间。所以,如果系统中某一个模块暂时不需要使用,就可以通过regulator关闭其电源供应;或者降低提供给该模块的电压、电流大小。

Regulator的文档在KERNEL/Documentation/Power/Regulator中。

 

Regulator与模块之间是树状关系。父regulator可以给设备供电,也可以给子regulator供电:

 父Regulator -+->子Regulator --> [Consumer A @ 1.8 - 2.0V] |

             +-> [Consumer B @ 3.3V]

具体细节可参考内核文档machine.txt。

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 */

};

Regulator的注册

Regulator的注册由regulator_register完成。

一般来说,为了添加regulator_dev,需要实现一个设备驱动程序,以及在板子的设备列表中增加一个该驱动对应的设备(比如platform_device)。在这个设备的struct device->platform_data域,需要设置regulator_init结构,填写该regulator的相关信息。另外,还需要定义一个regulator_desc结构。这样,在这个物理设备的驱动程序中,就可以通过regulator_register函数登记生成一个regulator_dev。

struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, struct device *dev, void *driver_data)

           struct regulator_init_data *init_data = dev->platform_data;// 得到init_data

           // 完整性检查

           …

           // 分配regulator_dev结构

           struct regulator_dev *rdev = kzalloc (sizeof(struct regulator_dev), GFP_KERNEL);

           // 初始化regulator_dev结构

           …

           // 执行regulator_init,该函数中实现regulator代表的硬件设备的初始化

           if (init_data->regulator_init)

                       ret = init_data->regulator_init(rdev->reg_data);

           rdev->dev.class = &regulator_class;          // 指定class为regulator_class

           rdev->dev.parent = dev;

           device_register(&rdev->dev);                  // 注册设备

           // 设置constraints,其中可能会包括供电状态的初始化(设置初始电压,enable/disable等等)

           set_machine_constraints(rdev, &init_data->constraints);

           add_regulator_attributes (rdev);

           // 如果此regulator有父regulator,设置父regulator

           if (init_data->supply_regulator_dev) {

                       ret = set_supply(rdev,

                                   dev_get_drvdata(init_data->supply_regulator_dev));

                       if (ret < 0)

                                   goto scrub;

           }

           // 设置此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, &regulator_list);

 

set_consumer_device_supply函数用于登记regulator_dev与comsumer_dev(regulator负责供电的设备)之间的对应关系。对于每一个regulator_dev—comsumer_dev的配对,都会有一个regulator_map结构,这些结构会被加入到全局链表regulator_map_list中。

Regulator的使用

在设备驱动使用regulator对其驱动的设备供电时,需要首先保证设备与对应regulator之间的匹配关系已经被登记到regulator框架中。这可通过填写regulator_init_data结构实现。(具体可参考内核文档machine.txt)

之后,设备驱动通过regulator_get函数得到regulator结构,此函数通过前文所述regulator_map_list找到对应regulator_dev,再生成regulator结构给用户使用。

通过regulator_enable / regulator_disable打开、关闭regulator,这两个函数最终都是调用struct regulator_ops里的对应成员。

除此之外,还有regualtor_set_voltage / regulator_get_voltage等等。

Regulator能够支持的所有功能列表都在struct regulator_ops中定义,具体可参考代码中的注释。

struct regulator_ops {

           /* get/set regulator voltage */

           int (*set_voltage) (struct regulator_dev *, int min_uV, int max_uV);

           int (*get_voltage) (struct regulator_dev *);

           /* get/set regulator current  */

           int (*set_current_limit) (struct regulator_dev *,

                                                int min_uA, int max_uA);

           int (*get_current_limit) (struct regulator_dev *);

           /* enable/disable regulator */

           int (*enable) (struct regulator_dev *);

           int (*disable) (struct regulator_dev *);

           int (*is_enabled) (struct regulator_dev *);

           /* get/set regulator operating mode (defined in regulator.h) */

           int (*set_mode) (struct regulator_dev *, unsigned int mode);

           unsigned int (*get_mode) (struct regulator_dev *);

           /* get most efficient regulator operating mode for load */

           unsigned int (*get_optimum_mode) (struct regulator_dev *, int input_uV,

                                                             int output_uV, int load_uA);

           /* the operations below are for configuration of regulator state when

            * its parent PMIC enters a global STANDBY/HIBERNATE state */

           /* set regulator suspend voltage */

           int (*set_suspend_voltage) (struct regulator_dev *, int uV);

           /* enable/disable regulator in suspend state */

           int (*set_suspend_enable) (struct regulator_dev *);

           int (*set_suspend_disable) (struct regulator_dev *);

           /* set regulator suspend operating mode (defined in regulator.h) */

           int (*set_suspend_mode) (struct regulator_dev *, unsigned int mode);

};

抱歉!评论已关闭.