• RK3399平台开发系列讲解(驱动篇)Regulator Framework


    在这里插入图片描述

    🚀返回专栏总目录

    沉淀、分享、成长,让自己和他人都能有所收获!😄

    📢 要简单介绍下系统的Regulator Framework

    Regulator翻译为”调节器”,分为电压调节器(voltage regulator)和电流调节器(current regulator),是电源管理的底层基础设施之一,在内核中regulator实际是个抽象出来的概念。

    linuxregulator Framework框架设计,控制系统中某些设备的电压/电流供应,并且在系统运行的过程中,动态改变regulators的输出,以达到省电的目的。 该Regulator框架为各种使用电源的设备(consumer)提供统一接口,允许获取电压,限制电压,使能和关闭电源等操作,也提供了Regulator驱动接口, 允许注册电源提供者(provider)并向内核提供操作函数等。

    Linux Regulator Framework整体分为四个部分,分别是machine(regulator硬件制约,映射关系等),regulator(理解为regulator driver), consumer(regulator的使用者,服务对象),sys-class-regulator(用户空间接口)。

    一、Regulator驱动


    Regulator驱动主要是电源提供者(provider)注册和通过相关操作函数,电源提供者(provider)是PMIC等。下面介绍下注册接口函数和数据结构:

    struct regulator_desc结构体用来描述一个独立的PMIC提供的每个调节器,一个静态描述。

    struct regulator_desc {
        const char *name;
        const char *supply_name;
        const char *of_match;
        const char *regulators_node;
        /*..................*/
        int id;
    
        unsigned n_voltages;
        const struct regulator_ops *ops;
        int irq;
        enum regulator_type type;
        struct module *owner;
        unsigned int min_uV;
        unsigned int uV_step;
        unsigned int ramp_delay;
        /*..................*/
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    上面结构体有省略,详细请看内核源码/include/linux/regulator/driver.h,有详细的注释。

    • name: Regulator的名字
    • supply_name :该regulator parent的name,在级联时使用
    • of_match:匹配设备树中的regulator名字
    • regulators_node:自动从DTS中解析init_data
    • id:regulator的标识
    • n_voltages :regulator可用的选择器输出数量,固定输出电压,应将n_voltage设置为1
    • ops:一组操作函数,回调函数,用来操作电源管理,注册regulator资源,会指定
    • type: 表示regulator是电压调节器还是电流调节器。
    • min_uV: 表示regulator输出的最小电压
    • ramp_delay : 电压改变后稳定下来所需时间
    struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
                                         const struct regulator_config *config);
    
    void regulator_unregister(struct regulator_dev *rdev);
    
    • 1
    • 2
    • 3
    • 4

    regulator_register函数是注册regulator的接口,传入regulator_desc和regulator_config两个结构体参数,regulator_desc描述regulator以及相关操作函数, regulator_config主要包含一些调节器描述的可变元素和一些约束,一种安全限制等。返回一个regulator_dev结构体,该结构体是一个抽象的描述对regulator,如下(有省略):

    struct regulator_dev {
        const struct regulator_desc *desc;
        int exclusive;
        u32 use_count;
        u32 open_count;
        u32 bypass_count;
    
        /* lists we belong to */
        struct list_head list; /* list of all regulators */
    
        /* lists we own */
        struct list_head consumer_list; /* consumers we supply */
    
        struct coupling_desc coupling_desc;
    
        struct blocking_notifier_head notifier;
        struct mutex mutex; /* consumer lock */
        struct task_struct *mutex_owner;
        int ref_cnt;
        struct module *owner;
        struct device dev;
        struct regulation_constraints *constraints;
        struct regulator *supply;       /* for tree */
        const char *supply_name;
        struct regmap *regmap;
    
        struct delayed_work disable_work;
        int deferred_disables;
        void *reg_data;         /* regulator_dev data */
        /*..................*/
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • list:regulator链表。
    • consumer_list:该regulator下所有的consumer。
    • notifier: regulator的通知链,用于给consumer通知event。
    • constraints:结构体regulation_constraints结构对regulator施加的一些的限制,是一种安全限制。结构体如下(有省略):
    struct regulation_constraints {
    
        const char *name;
    
        /*电压输出范围 */
        int min_uV;
        int max_uV;
    
        int uV_offset;
    
        /* 电流输出范围 */
        int min_uA;
        int max_uA;
        int ilim_uA;
    
        int system_load;
    
        /* used for coupled regulators */
        int max_spread;
    
        /* 标志对这个regulator有效的操作模式*/
        unsigned int valid_modes_mask;
    
        /* regulator有效的操作 */
        unsigned int valid_ops_mask;
    
        /* regulator input voltage - only if supply is another regulator */
        int input_uV;
    
        /*.......................*/
    
        /* 约束标志位 */
        unsigned always_on:1;   /* 当系统开启时,regulator不会关闭 */
        unsigned boot_on:1;     /* bootloader/firmware enabled regulator */
        unsigned apply_uV:1;    /* 当电压最大值等于最小值,使能约束,是固定的电压*/
        unsigned ramp_disable:1; /* disable ramp delay */
        unsigned soft_start:1;  /* ramp voltage slowly */
        unsigned pull_down:1;   /* pull down resistor when regulator off */
        unsigned over_current_protection:1; /* auto disable on over current */
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    该结构体是一个安全限制,比如是电压调节器,限制了电压的输出范围等,这些一般在设备树描述,比如min_uA对应设备树的“regulator-min-microvolt”属性。

    二、consumer接口函数


    consumer是regulator提供服务的对象,使用者。每个consumer都有个结构体:

    struct regulator {
        struct device *dev;
        struct list_head list;
        unsigned int always_on:1;
        unsigned int bypass:1;
        int uA_load;
        struct regulator_voltage voltage[REGULATOR_STATES_NUM];
        const char *supply_name;
        struct device_attribute dev_attr;
        struct regulator_dev *rdev;      //关联的regulator
        struct dentry *debugfs;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    常见的consumer接口函数:

    /*获取和释放*/
    struct regulator *regulator_get(struct device*dev, const char *id);
    
    void regulator_put(struct regulator *regulator);
    
    /*使能和关闭*/
    int regulator_enable(regulator);
    
    int regulator_disable(regulator);
    
    /*设置regulator的电压,获得regulator的电压状态*/
    int regulator_set_voltage(regulator, min_uVmax_uV)
    int regulator_get_voltage(regulator);
    
    int regulator_set_current_limit(regulator, min_uA, max_uA);
    
    /*操作模式控制和状态*/
    int regulator_set_optimum_mode(struct regulator*regulator,int load_uA);
    
    int regulator_set_mode(struct regulator*regulator, unsigned int mode);
    
    unsigned int regulator_get_mode(struct regulator*regulator);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    三、用户空间sysfs接口


    切换到/sys/class/regulator目录下。

    可以看到该目录有我们注册的regulator,并且都是链接文件,指向平台设备下的具体文件。 我们切换到一个regulator.14(tcs4525)目录下,可以看到一系列文件:

    在这里插入图片描述

    • state 表示该regulator,可以是’enabled’、’disabled’、’unknown’几种状态。
    • type 表示regulator的类型,是电压、电流等,即:’voltage’、’current’、’unknown’
    • microvolts 表示输出的电压,min_microvolts和max_microvolts就表示可以输出的电压范围
    • num_users 表示使用改regulator的consumer数量
    • opmode 操作模式,一般是’normal’
  • 相关阅读:
    unity3d 卡死原因
    计算机毕业设计之java+javaweb的新冠疫情下的校园出入系统
    (64)MIPI DSI LLP介绍(四)
    jQuery网页开发案例:jQuery常用API--jQuery 尺寸、位置操作及 电梯导航案例和节流阀(互斥锁)
    HDFS工作流程和机制
    JavaScript:日期对象
    利用免费的敏捷研发管理工具管理端到端敏捷研发流程
    C#程序随系统启动例子 - 开源研究系列文章
    【OpenCV小练手】-仿造验证码去除干扰因子
    【Spring】——2、使用@ComponentScan自动扫描组件并指定扫描规则
  • 原文地址:https://blog.csdn.net/qq_33487044/article/details/133896893