RK3588 regulator

更多资料下载,冲击月薪过万,一线经验工程师录制, 干货满满的嵌入式视频教程,请点击淘宝店:wanglitao.taobao.com

Regulator,翻译成中文是:调节器、稳定器。

 Input Voltage -> Regulator -> Output Voltage

Regulator一般分为电压稳定器和电流稳定器两种。电压稳定器能够自动调节电压,电流稳定器能够自动调节电流。对Regulator的控制比较简单,主要分为:Enable、Disable、对输出电压电流大小的控制等。

Linux内核中的Regulator

在Linux内核中,对提供电源的LDO、DC-DC芯片、PMIC等,都可以抽象成一个 Regulator。每个Regulator都有对应的驱动。驱动中实现各自的regulator_ops方法,然后向Linux系统注册相关的操作函数。用来设置电压、电流输出大小,电源的Enable和Disable控制等。

在Linux内核中,对于每一个Regulator,使用struct regulator_desc结构体来表示:

struct regulator_desc {
    const char *name;  // Regulator的名字,一般跟设备树节点的名字对应
    const char *supply_name; // 该regulator parent的name,在级联时使用
    const char *of_match;    // 匹配设备树中的regulator名字
    const char *regulators_node;    // 
    ...
    int id;    //regulator的标识
    unsigned n_voltages; // regulator可用的选择器输出数量,固定输出电压,应将n_voltage设置为1
    const struct regulator_ops *ops; // 操作接口的具体实现:设置、读取电压值等
    int irq;
    enum regulator_type type; //类型:LDO、BUCK、DVS、FIXED、GPIO...
    struct module *owner;
    unsigned int min_uV; //Regulator输出的最小电压
    unsigned int uV_step;
    unsigned int ramp_delay; //电压重新设置后稳定下来需要的时间
    ...
};

struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
                                         const struct regulator_config *config);
void regulator_unregister(struct regulator_dev *rdev);

可以通过regulator_register函数向Linux系统注册regulator。
传入regulator_desc和regulator_config两个结构体参数,regulator_desc描述regulator以及相关操作回调函数, regulator_config主要包含一些调节器描述的可变元素和一些约束,一种安全限制等。

struct regulation_constraints {
    const char *name;
    int min_uV; // 电压输出最小值,驱动会解析设备树中的regulator-min-microvolt属性来初始化此值
    int max_uV; // 电压输出最大值
    int uV_offset;
    int min_uA; // 电流输出最小值
    int max_uA; // 电流输出最大值
    ...
    /* regulator input voltage - only if supply is another regulator */
    int input_uV; // 级联时,表示上一级的 Regulator

    /* 约束标志位 */
    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 */
}

regulator_register函数注册成功后,会返回一个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 所有注册的Regulator都放入链表,统一受系统管理*/

    /* lists we own */
    struct list_head consumer_list; /* consumers we supply,该regulator下所有的consumer */

    struct coupling_desc coupling_desc;

    struct blocking_notifier_head notifier; // regulator的通知链,用于给consumer 通知 event
    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 */
};

struct regulator_dev结构体是对注册到系统中的Regulator的一个抽象描述。为了更好地匹配设备驱动模型,Linux内核使用一个struct regulator结构体来对其进行二次封装:

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;
};

Linux设备树中的Regulator节点

在Linux设备树中,对于提供电源的LDO、DC-DC、PMIC,都可以通过创建一个Regulator节点来表示:

pcie20_avdd0v85: pcie20-avdd0v85 {
        compatible = "regulator-fixed"; // 电源的输出电压是固定的
        regulator-name = "pcie20_avdd0v85"; //regulator的名字,会初始化device.name,然后跟driver的name匹配
        regulator-boot-on; // 在bootloader/firmware阶段使能
        regulator-always-on; // 需要一直使能,不能Disable
        regulator-min-microvolt = <850000>; // 电压输出最小值
        regulator-max-microvolt = <850000>; // 电压输出最大值
        vin-supply = <&avdd_0v85_s0>; // 级联的父regulator节点,说明该稳压器需要另外一个regulator供电
    };

如果电路图中使用了某个GPIO管脚来控制电源的Enable/Disable,需要在设备树文件中添加 gpios属性:

    vcc3v3_pcie30: vcc3v3-pcie30 {
        compatible = "regulator-fixed";
        regulator-name = "vcc3v3_pcie30";
        regulator-min-microvolt = <3300000>;
        regulator-max-microvolt = <3300000>;
        enable-active-high; // 使能信号,高电平有效
        gpios = <&gpio3 RK_PC3 GPIO_ACTIVE_HIGH>; // 使用GPIO_C3来控制vcc3v3_pcie30电源的开关
        startup-delay-us = <5000>;
        vin-supply = <&vcc12v_dcin>;
    };

在上面的Regulator中,使用 gpio_c3 管脚来控制电源的Enable/Disable。