Linux Regulator驱动框架与应用

目录

Linux Regulator框架的基本介绍

linux regulator 的文档Documentation/power/regulator下
这里有几个概念要清楚:
regulator 谷歌翻译意思为“调节器”,理解为控制电压,电流的一种装置。
PMIC 电源管理芯片。
Consumer : 由regulator 控制供电的设备。
Constraints: 约束和限制电源参数。
Power Domain:电源域,输出提供给输入的。字面意思比较难理解,可以参考一下面的

  o Power Domain - Electronic circuit that is supplied its input power by the
                   output power of a regulator, switch or by another power
                   domain.

                   The supply regulator may be behind a switch(s). i.e.

                   Regulator -+-> Switch-1 -+-> Switch-2 --> [Consumer A]
                              |             |
                              |             +-> [Consumer B], [Consumer C]
                              |
                              +-> [Consumer D], [Consumer E]

                   That is one regulator and three power domains:

                   Domain 1: Switch-1, Consumers D & E.
                   Domain 2: Switch-2, Consumers B & C.
                   Domain 3: Consumer A.

                   and this represents a "supplies" relationship:

                   Domain-1 --> Domain-2 --> Domain-3.

                   A power domain may have regulators that are supplied power
                   by other regulators. i.e.

                   Regulator-1 -+-> Regulator-2 -+-> [Consumer A]
                                |
                                +-> [Consumer B]

                   This gives us two regulators and two power domains:

                   Domain 1: Regulator-2, Consumer B.
                   Domain 2: Consumer A.

                   and a "supplies" relationship:

                   Domain-1 --> Domain-2

machine

machine 驱动接口 linux/regulator/machine.h, 描述regulator在板级的物理现状,包括regulator的级连(supply_regulator)
regulator的物理限制(struct regulation_constraints)

/**
 * struct regulator_init_data - regulator platform initialisation data.
 *
 * Initialisation constraints, our supply and consumers supplies.
 *
 * @supply_regulator: Parent regulator.  Specified using the regulator name
 *                    as it appears in the name field in sysfs, which can
 *                    be explicitly set using the constraints field 'name'.
 *
 * @constraints: Constraints.  These must be specified for the regulator to
 *               be usable.
 * @num_consumer_supplies: Number of consumer device supplies.
 * @consumer_supplies: Consumer device supply configuration.
 *
 * @regulator_init: Callback invoked when the regulator has been registered.
 * @driver_data: Data passed to regulator_init.
 */
struct regulator_init_data {
	const char *supply_regulator;        /* or NULL for system supply */

	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 regulation_constraints - regulator operating constraints.
 *
 * This struct describes regulator and board/machine specific constraints.
 *
 * @name: Descriptive name for the constraints, used for display purposes.
 *
 * @min_uV: Smallest voltage consumers may set.
 * @max_uV: Largest voltage consumers may set.
 * @uV_offset: Offset applied to voltages from consumer to compensate for
 *             voltage drops.
 *
 * @min_uA: Smallest current consumers may set.
 * @max_uA: Largest current consumers may set.
 * @ilim_uA: Maximum input current.
 * @system_load: Load that isn't captured by any consumer requests.
 *
 * @max_spread: Max possible spread between coupled regulators
 * @valid_modes_mask: Mask of modes which may be configured by consumers.
 * @valid_ops_mask: Operations which may be performed by consumers.
 *
 * @always_on: Set if the regulator should never be disabled.
 * @boot_on: Set if the regulator is enabled when the system is initially
 *           started.  If the regulator is not enabled by the hardware or
 *           bootloader then it will be enabled when the constraints are
 *           applied.
 * @apply_uV: Apply the voltage constraint when initialising.
 * @ramp_disable: Disable ramp delay when initialising or when setting voltage.
 * @soft_start: Enable soft start so that voltage ramps slowly.
 * @pull_down: Enable pull down when regulator is disabled.
 * @over_current_protection: Auto disable on over current event.
 *
 * @input_uV: Input voltage for regulator when supplied by another regulator.
 *
 * @state_disk: State for regulator when system is suspended in disk mode.
 * @state_mem: State for regulator when system is suspended in mem mode.
 * @state_standby: State for regulator when system is suspended in standby
 *                 mode.
 * @initial_state: Suspend state to set by default.
 * @initial_mode: Mode to set at startup.
 * @ramp_delay: Time to settle down after voltage change (unit: uV/us)
 * @settling_time: Time to settle down after voltage change when voltage
 *		   change is non-linear (unit: microseconds).
 * @settling_time_up: Time to settle down after voltage increase when voltage
 *		      change is non-linear (unit: microseconds).
 * @settling_time_down : Time to settle down after voltage decrease when
 *			 voltage change is non-linear (unit: microseconds).
 * @active_discharge: Enable/disable active discharge. The enum
 *		      regulator_active_discharge values are used for
 *		      initialisation.
 * @enable_time: Turn-on time of the rails (unit: microseconds)
 */
struct regulation_constraints {

	const char *name;

	/* voltage output range (inclusive) - for voltage control */
	int min_uV;
	int max_uV;

	int uV_offset;

	/* current output range (inclusive) - for current control */
	int min_uA;
	int max_uA;
	int ilim_uA;

	int system_load;

	/* used for coupled regulators */
	int max_spread;

	/* valid regulator operating modes for this machine */
	unsigned int valid_modes_mask;

	/* valid operations for regulator on this machine */
	unsigned int valid_ops_mask;

	/* regulator input voltage - only if supply is another regulator */
	int input_uV;

	/* regulator suspend states for global PMIC STANDBY/HIBERNATE */
	struct regulator_state state_disk;
	struct regulator_state state_mem;
	struct regulator_state state_standby;
	suspend_state_t initial_state; /* suspend state to set at init */

	/* mode to set on startup */
	unsigned int initial_mode;

	unsigned int ramp_delay;
	unsigned int settling_time;
	unsigned int settling_time_up;
	unsigned int settling_time_down;
	unsigned int enable_time;

	unsigned int active_discharge;

	/* constraint flags */
	unsigned always_on:1;	/* regulator never off when system is on */
	unsigned boot_on:1;	/* bootloader/firmware enabled regulator */
	unsigned apply_uV:1;	/* apply uV constraint if min == max */
	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 */
};

输出电压的最大值和最小值(voltage regulator);
输出电流的最大值和最小值(current regulator);
允许的操作(修改电压值、修改电流限制、enable、disable等等);
输入电压是多少(当输入是另一个regulator时);
是否不允许关闭(always_on);
是否启动时就要打开(always_on);
等等。

driver

linux/regulator/drier.h
从regulator driver的角度,抽象regulator设备.
一些数据类型和一些API,没有driver.c,API的实现大多在linux/regulator/core.c 中
1.使用struct regulator_desc描述regulator的静态信息,包括:名字、supply regulator的名字、中断号、操作函数集(struct regulator_ops)、使用regmap时相应的寄存器即bitmap等等.

2.使用struct regulator_config,描述regulator的动态信息(所谓的动态信息,体现在struct regulator_config变量都是局部变量,因此不会永久保存),包括struct regulator_init_data指针、设备指针、enable gpio等等

3.提供regulator的注册接口

struct regulator_dev *
regulator_register(const struct regulator_desc *regulator_desc,
		   const struct regulator_config *config);
struct regulator_dev *
devm_regulator_register(struct device *dev,
			const struct regulator_desc *regulator_desc,
			const struct regulator_config *config);
void regulator_unregister(struct regulator_dev *rdev);
void devm_regulator_unregister(struct device *dev, struct regulator_dev *rdev);

consumer

linux/regulator/consumer.h 提供regulator的相关接口,与driver 类似,实现大多在linux/regulator/core.c

常用API接口

/* regulator get and put */
//正常的get,非独占、可以重复
struct regulator *__must_check regulator_get(struct device *dev,
					     const char *id);
struct regulator *__must_check devm_regulator_get(struct device *dev,
					     const char *id);

//独占性质的get,独占、不可重复
struct regulator *__must_check regulator_get_exclusive(struct device *dev,
						       const char *id);
struct regulator *__must_check devm_regulator_get_exclusive(struct device *dev,
							const char *id);

//optional的get,非独占、不可重复
struct regulator *__must_check regulator_get_optional(struct device *dev,
						      const char *id);
struct regulator *__must_check devm_regulator_get_optional(struct device *dev,
							   const char *id);
void regulator_put(struct regulator *regulator);
void devm_regulator_put(struct regulator *regulator);

RV1109电源

在这里插入图片描述在这里插入图片描述供电由rk809 ,PMIC芯片管理,对应的配置参考下方的设备树

RV1109电源设备树

rv1126-evb-v10.dtsi

rk809: pmic@20 {
		compatible = "rockchip,rk809";
		reg = <0x20>;
		interrupt-parent = <&gpio0>;
		interrupts = <9 IRQ_TYPE_LEVEL_LOW>;
		pinctrl-names = "default", "pmic-sleep",
			"pmic-power-off", "pmic-reset";
		pinctrl-0 = <&pmic_int>;
		pinctrl-1 = <&soc_slppin_gpio>, <&rk817_slppin_slp>;
		pinctrl-2 = <&soc_slppin_gpio>, <&rk817_slppin_pwrdn>;
		pinctrl-3 = <&soc_slppin_slp>, <&rk817_slppin_rst>;
		rockchip,system-power-controller;
		wakeup-source;
		#clock-cells = <1>;
		clock-output-names = "rk808-clkout1", "rk808-clkout2";
		/* 0: rst the pmic, 1: rst regs (default in codes) */
		pmic-reset-func = <0>;

		vcc1-supply = <&vcc5v0_sys>;
		vcc2-supply = <&vcc5v0_sys>;
		vcc3-supply = <&vcc5v0_sys>;
		vcc4-supply = <&vcc5v0_sys>;
		vcc5-supply = <&vcc_buck5>;
		vcc6-supply = <&vcc_buck5>;
		vcc7-supply = <&vcc5v0_sys>;
		vcc8-supply = <&vcc3v3_sys>;
		vcc9-supply = <&vcc5v0_sys>;

		pwrkey {
			status = "okay";
		};

		pinctrl_rk8xx: pinctrl_rk8xx {
			gpio-controller;
			#gpio-cells = <2>;

			/omit-if-no-ref/
			rk817_slppin_null: rk817_slppin_null {
				pins = "gpio_slp";
				function = "pin_fun0";
			};

			/omit-if-no-ref/
			rk817_slppin_slp: rk817_slppin_slp {
				pins = "gpio_slp";
				function = "pin_fun1";
			};

			/omit-if-no-ref/
			rk817_slppin_pwrdn: rk817_slppin_pwrdn {
				pins = "gpio_slp";
				function = "pin_fun2";
			};

			/omit-if-no-ref/
			rk817_slppin_rst: rk817_slppin_rst {
				pins = "gpio_slp";
				function = "pin_fun3";
			};
		};

		regulators {
			vdd_logic: DCDC_REG1 {
				regulator-always-on;
				regulator-boot-on;
				regulator-min-microvolt = <725000>;
				regulator-max-microvolt = <1350000>;
				regulator-ramp-delay = <6001>;
				regulator-initial-mode = <0x2>;
				regulator-name = "vdd_logic";
				regulator-state-mem {
					regulator-on-in-suspend;
					regulator-suspend-microvolt = <800000>;
				};
			};

			vdd_arm: DCDC_REG2 {
				regulator-always-on;
				regulator-boot-on;
				regulator-min-microvolt = <725000>;
				regulator-max-microvolt = <1350000>;
				regulator-ramp-delay = <6001>;
				regulator-initial-mode = <0x2>;
				regulator-name = "vdd_arm";
				regulator-state-mem {
					regulator-off-in-suspend;
				};
			};

			vcc_ddr: DCDC_REG3 {
				regulator-always-on;
				regulator-boot-on;
				regulator-initial-mode = <0x2>;
				regulator-name = "vcc_ddr";
				regulator-state-mem {
					regulator-on-in-suspend;
				};
			};

			vcc3v3_sys: DCDC_REG4 {
				regulator-always-on;
				regulator-boot-on;
				regulator-min-microvolt = <3300000>;
				regulator-max-microvolt = <3300000>;
				regulator-initial-mode = <0x2>;
				regulator-name = "vcc3v3_sys";
				regulator-state-mem {
					regulator-on-in-suspend;
					regulator-suspend-microvolt = <3300000>;
				};
			};

			vcc_buck5: DCDC_REG5 {
				regulator-always-on;
				regulator-boot-on;
				regulator-min-microvolt = <2200000>;
				regulator-max-microvolt = <2200000>;
				regulator-name = "vcc_buck5";
				regulator-state-mem {
					regulator-on-in-suspend;
					regulator-suspend-microvolt = <2200000>;
				};
			};

			vcc_0v8: LDO_REG1 {
				regulator-always-on;
				regulator-boot-on;
				regulator-min-microvolt = <800000>;
				regulator-max-microvolt = <800000>;
				regulator-name = "vcc_0v8";
				regulator-state-mem {
					regulator-off-in-suspend;
				};
			};

			vcc1v8_pmu: LDO_REG2 {
				regulator-always-on;
				regulator-boot-on;
				regulator-min-microvolt = <1800000>;
				regulator-max-microvolt = <1800000>;
				regulator-name = "vcc1v8_pmu";
				regulator-state-mem {
					regulator-on-in-suspend;
					regulator-suspend-microvolt = <1800000>;
				};
			};

			vdd0v8_pmu: LDO_REG3 {
				regulator-always-on;
				regulator-boot-on;
				regulator-min-microvolt = <800000>;
				regulator-max-microvolt = <800000>;
				regulator-name = "vcc0v8_pmu";
				regulator-state-mem {
					regulator-on-in-suspend;
					regulator-suspend-microvolt = <800000>;
				};
			};

			vcc_1v8: LDO_REG4 {
				regulator-always-on;
				regulator-boot-on;
				regulator-min-microvolt = <1800000>;
				regulator-max-microvolt = <1800000>;
				regulator-name = "vcc_1v8";
				regulator-state-mem {
					regulator-on-in-suspend;
					regulator-suspend-microvolt = <1800000>;
				};
			};

			vcc_dovdd: LDO_REG5 {
				//regulator-always-on; /* 否则摄像头不工作,影响显示*/
				regulator-boot-on;
				regulator-min-microvolt = <1800000>;
				regulator-max-microvolt = <1800000>;
				regulator-name = "vcc_dovdd";
				regulator-state-mem {
					regulator-off-in-suspend;
				};
			};

			vcc_dvdd: LDO_REG6 {
				regulator-min-microvolt = <1200000>;
				regulator-max-microvolt = <1200000>;
				regulator-name = "vcc_dvdd";
				regulator-state-mem {
					regulator-off-in-suspend;
				};
			};

			vcc_avdd: LDO_REG7 {
				regulator-min-microvolt = <2800000>;
				regulator-max-microvolt = <2800000>;
				regulator-name = "vcc_avdd";
				regulator-state-mem {
					regulator-off-in-suspend;
				};
			};

			vccio_sd: LDO_REG8 {
				regulator-always-on;
				regulator-boot-on;
				regulator-min-microvolt = <1800000>;
				regulator-max-microvolt = <3300000>;
				regulator-name = "vccio_sd";
				regulator-state-mem {
					regulator-off-in-suspend;
				};
			};

			vcc3v3_sd: LDO_REG9 {
				regulator-always-on;
				regulator-boot-on;
				regulator-min-microvolt = <3300000>;
				regulator-max-microvolt = <3300000>;
				regulator-name = "vcc3v3_sd";
				regulator-state-mem {
					regulator-off-in-suspend;
				};
			};

			vcc5v0_host: SWITCH_REG1 {
				regulator-name = "vcc5v0_host";
			};

			vcc_3v3: SWITCH_REG2 {
				regulator-always-on;
				regulator-boot-on;
				regulator-name = "vcc_3v3";
			};
		};

		rk809_codec: codec {
			#sound-dai-cells = <0>;
			compatible = "rockchip,rk809-codec", "rockchip,rk817-codec";
			clocks = <&cru MCLK_I2S0_TX_OUT2IO>;
			clock-names = "mclk";
			pinctrl-names = "default";
			assigned-clocks = <&cru MCLK_I2S0_TX_OUT2IO>;
			assigned-clock-parents = <&cru MCLK_I2S0_TX>;
			pinctrl-0 = <&i2s0m0_mclk>;
			hp-volume = <20>;
			spk-volume = <3>;
		};
	};

注意这里设备树的label与上面的原理图对应,从官方评估板原理图与对应的SDK可以很清楚的理清供电逻辑

rv1126-evb-v12.dtsi中

	vdd_logic: vdd-logic {
		compatible = "regulator-fixed"; 
		regulator-name = "vdd_logic";
		regulator-always-on;
		regulator-boot-on;
		regulator-min-microvolt = <810000>;
		regulator-max-microvolt = <810000>;
	};

可以搜索vdd_logic ,这里指定使用的regulator对应的驱动。rv1126-evb-v12.dtsi 引用 rv1126-evb-v10.dtsi
dts中的regulator的配置,会通过dts解析到前面提到的struct regulator_config

实际应用场景

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值