第05课第1节_regulator系统的概念并编写代码

Regulator:矫正器,调整器,实际上就是一个电源芯片。比如jz2440上的LCD背光就是由下图所示的电源芯片供电的,操作EN引脚即可使能该芯片。

 

 

概念:

Regulator   : 电源芯片, 比如电压转换芯片

Consumer    : 消费者,使用电源的部件, Regulator是给Consumer供电的

machine     : 单板,上面焊接有Regulator和Consumer

Constraints : 约束, 比如某个电源管理芯片输出的电压范围

Supply      : 提供电源的部件, Regulator就是一个Supply; Regulator A可以给Regulator B供电, 那么Regulator B的Supply就是A

 

扫描二维码关注公众号,回复: 2430762 查看本文章

 

 

Regulator系统的框架如下图所示,分为图中标号的三部分。

 

 

所以Regulator系统的驱动程序可以分为三个部分:

写驱动程序:

1. regulator:

   注册一个platform_driver: 在它的probe函数里分配、设置、注册一个regulator

   "设置"里要做的事情: 实现regulator的操作, 比如enable, disable, set_voltage

2. machine:

   注册一个platform_device: 在它的私有数据里指定regulator和consume的对应关系(这个电源芯片给哪一个部件供电)

                            指定约束条件(比如电压范围)

3. consumer: 使用即可: regulator_get, regulator_enable, regulator_disable, regulator_set_voltage....

 

 

 

Regulator.c详解:

/* 参考: drivers/regulator/tps6105x-regulator.c */

 

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/init.h>

#include <linux/err.h>

#include <linux/platform_device.h>

#include <linux/regulator/driver.h>

#include <linux/mfd/core.h>

 

static volatile unsigned long *gpbcon;

static volatile unsigned long *gpbdat;

 

static int myregulator_enable(struct regulator_dev *rdev)

{

         *gpbdat |= 1;     /* 输出高电平 */

         return 0;

}

 

static int myregulator_disable(struct regulator_dev *rdev)

{

         *gpbdat &= ~1;     /* 输出低电平 */

         return 0;

}

 

static int myregulator_is_enabled(struct regulator_dev *rdev)

{

         if (*gpbdat & 1)

                   return 1;

         else

                   return 0;

}

 

 

static struct regulator_ops myregulator_ops = {

         .enable              = myregulator_enable,

         .disable    = myregulator_disable,

         .is_enabled      = myregulator_is_enabled,

};

 

 

static struct regulator_desc myregulator_desc = {

         .name                = "myregulator",

         .ops           = &myregulator_ops,

         .type                  = REGULATOR_VOLTAGE,

         .id              = 0,

         .owner               = THIS_MODULE,

         .n_voltages      = 1,

};

 

static struct regulator_dev *myregulator_dev;

static int myregulator_probe(struct platform_device *pdev)

{

         struct regulator_init_data *init_data = dev_get_platdata(&pdev->dev);

 

         gpbcon = ioremap(0x56000010, 8);   //为什么要映射?直接操作这个地址不行吗?

         gpbdat = gpbcon+1;

 

         *gpbcon &= ~(3);  /* GPB0设置为输出引脚 */

         *gpbcon |= 1;

        

         /* 分配/设置/注册 regulator */

         myregulator_dev = regulator_register(&myregulator_desc,

                                                    &pdev->dev,

                                                    init_data, NULL,

                                                    NULL);

 

         if (IS_ERR(myregulator_dev)) {

                   printk("regulator_register error!\n");

                   return -EIO;

         }

 

         return 0;

}

 

static int myregulator_remove(struct platform_device *pdev)

{

         regulator_unregister(myregulator_dev);

         return 0;

}

 

struct platform_driver myregulator_drv = {

         .probe                = myregulator_probe,

         .remove            = myregulator_remove,

         .driver                = {

                   .name       = "myregulator",

         }

};

 

static int myregulator_init(void)

{

         platform_driver_register(&myregulator_drv);

         return 0;

}

 

static void myregulator_exit(void)

{

         platform_driver_unregister(&myregulator_drv);

}

 

module_init(myregulator_init);

module_exit(myregulator_exit);

 

MODULE_LICENSE("GPL v2");

 

 

 

 

 

 

Machine详解:

 

/* 参考: arch\arm\mach-omap2\board-2430sdp.c

*/

 

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/init.h>

#include <linux/err.h>

#include <linux/platform_device.h>

#include <linux/regulator/driver.h>

#include <linux/mfd/core.h>

 

/* 分配/设置/注册regulator_init_data */

 

#if 0

 regulator_consumer_supply:

 const char *dev_name;          /* consumer的名字 */

 const char *supply;     /* consumer的电源引脚名称 ,一个consumer可能有多个电源*/

 

#endif

 

static struct regulator_consumer_supply myregulator_supplies[] = {

         REGULATOR_SUPPLY("VCC", "mylcd"),

};

 

 

static struct regulator_init_data myregulator_init_data = {

         .constraints = {

                   .min_uV                      = 12000000,

                   .max_uV                     = 12000000,

                   .valid_modes_mask          = REGULATOR_MODE_NORMAL,

                   .valid_ops_mask                = REGULATOR_CHANGE_STATUS,

         },

         .num_consumer_supplies        = 1,

         .consumer_supplies         = myregulator_supplies,

};

 

static void myregulator_release(struct device * dev)

{

}

 

 

static struct platform_device myregulator_dev = {

    .name         = "myregulator",

    .id       = -1,

    .dev = {

             .release       = myregulator_release,

                   .platform_data = &myregulator_init_data,

         },

};

 

 

static int myregulator_machine_init(void)

{

         platform_device_register(&myregulator_dev);

         return 0;

}

 

static void myregulator_machine_exit(void)

{

         platform_device_unregister(&myregulator_dev);

}

 

module_init(myregulator_machine_init);

module_exit(myregulator_machine_exit);

 

MODULE_LICENSE("GPL v2");

 

 

 

 

 

regulator_register流程分析:

         // 分配regulator_dev

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

        

         /* set regulator constraints */

         set_machine_constraints

         add_regulator_attributes

        

         /* add consumers devices */

         set_consumer_device_supply

                   在regulator_map_list链表里生成一项regulator_map: 它里面有dev_name(consumer的名字),supply(cosumer的电源引脚名字)

 

         // 把regulator_dev放入regulator_list

         list_add(&rdev->list, &regulator_list);  

 

 

如下图所示:

         Consumer里面如果想使用regulator的话,只需要执行regulator_get函数就好,执行该函数后就会遍历regulator_list链表中的设备,如果能找到对应的regulator_map,说明就找到了这个regulator设备。

 

 

 

Consumer_lcd_4.3.c中添加的核心函数:

 

         myregulator = regulator_get(pdev->dev, "VCC");

regulator_enable(myregulator);   //使能背光电源。但是不明白这个函数最终是否调用到了register_driver下的opsmyregular_enable函数?

         regulator_disable(myregulator);  //禁止背光电源

猜你喜欢

转载自blog.csdn.net/hahaha_2017/article/details/81226961
今日推荐