首页 > 学院 > 开发设计 > 正文

Linux驱动regulator

2019-11-06 10:03:23
字体:
来源:转载
供稿:网友

Regulator驱动

        regulator是linux系统中电源管理的基础设施之一,用于稳压电源的管理,是各种驱动子系统中设置电压的标准接口。regulator可以管理系统中的供电单元,即稳压器(Low Dropout Regulator, LDO,即低压差线性稳压器),并提供获取和设置这些供电单元电压的接口。一般在ARM电路板上,各个稳压器会形成一个Regulator树型结构。

regulator_desc结构体是对这个稳压器属性和操作的封装:

/** * struct regulator_desc - Static regulator descriptor * * Each regulator registered with the core is described with a * structure of this type and a struct regulator_config.  This * structure contains the non-varying parts of the regulator * description. * * @name: Identifying name for the regulator. * @supply_name: Identifying the regulator supply * @id: Numerical identifier for the regulator. * @ops: Regulator Operations table. * @irq: Interrupt number for the regulator. * @type: Indicates if the regulator is a voltage or current regulator. * @owner: Module PRoviding the regulator, used for refcounting. * * @continuous_voltage_range: Indicates if the regulator can set any *                            voltage within constrains range. * @n_voltages: Number of selectors available for ops.list_voltage(). * * @min_uV: Voltage given by the lowest selector (if linear mapping) * @uV_step: Voltage increase with each selector (if linear mapping) * @linear_min_sel: Minimal selector for starting linear mapping * @ramp_delay: Time to settle down after voltage change (unit: uV/us) * @volt_table: Voltage mapping table (if table based mapping) * * @vsel_reg: Register for selector when using regulator_regmap_X_voltage_ * @vsel_mask: Mask for register bitfield used for selector * @apply_reg: Register for initiate voltage change on the output when *                using regulator_set_voltage_sel_regmap * @apply_bit: Register bitfield used for initiate voltage change on the *                output when using regulator_set_voltage_sel_regmap * @enable_reg: Register for control when using regmap enable/disable ops * @enable_mask: Mask for control when using regmap enable/disable ops * @enable_is_inverted: A flag to indicate set enable_mask bits to disable *                      when using regulator_enable_regmap and friends APIs. * @bypass_reg: Register for control when using regmap set_bypass * @bypass_mask: Mask for control when using regmap set_bypass * * @enable_time: Time taken for initial enable of regulator (in uS). */struct regulator_desc {	const char *name;                    /* regulator的名字 */	const char *supply_name;             /* regulator supply的名字 */	int id;	bool continuous_voltage_range;	unsigned n_voltages;	struct regulator_ops *ops;	int irq;	enum regulator_type type;            /* regulator的类型,电压还是电流regulator */	struct module *owner;	unsigned int min_uV;                 /* 在线性映射情况下最低的Selector的电压 */	unsigned int uV_step;                /* 在线性映射情况下每步增加/减小的电压 */	unsigned int linear_min_sel;	unsigned int ramp_delay;             /* 电压改变后稳定下来所需要的时间 */	const unsigned int *volt_table;      /* 基于表映射情况下的电压映射表 */	unsigned int vsel_reg;	unsigned int vsel_mask;	unsigned int apply_reg;	unsigned int apply_bit;	unsigned int enable_reg;	unsigned int enable_mask;	bool enable_is_inverted;	unsigned int bypass_reg;	unsigned int bypass_mask;	unsigned int enable_time;};

regulator_ops是对这个稳压器硬件操作的封装,其中包含获取、设置电压等的成员函数:

/** * struct regulator_ops - regulator operations. * * @enable: Configure the regulator as enabled. * @disable: Configure the regulator as disabled. * @is_enabled: Return 1 if the regulator is enabled, 0 if not. *		May also return negative errno. * * @set_voltage: Set the voltage for the regulator within the range specified. *               The driver should select the voltage closest to min_uV. * @set_voltage_sel: Set the voltage for the regulator using the specified *                   selector. * @map_voltage: Convert a voltage into a selector * @get_voltage: Return the currently configured voltage for the regulator. * @get_voltage_sel: Return the currently configured voltage selector for the *                   regulator. * @list_voltage: Return one of the supported voltages, in microvolts; zero *	if the selector indicates a voltage that is unusable on this system; *	or negative errno.  Selectors range from zero to one less than *	regulator_desc.n_voltages.  Voltages may be reported in any order. * * @set_current_limit: Configure a limit for a current-limited regulator. *                     The driver should select the current closest to max_uA. * @get_current_limit: Get the configured limit for a current-limited regulator. * * @set_mode: Set the configured operating mode for the regulator. * @get_mode: Get the configured operating mode for the regulator. * @get_status: Return actual (not as-configured) status of regulator, as a *	REGULATOR_STATUS value (or negative errno) * @get_optimum_mode: Get the most efficient operating mode for the regulator *                    when running with the specified parameters. * * @set_bypass: Set the regulator in bypass mode. * @get_bypass: Get the regulator bypass mode state. * * @enable_time: Time taken for the regulator voltage output voltage to *               stabilise after being enabled, in microseconds. * @set_ramp_delay: Set the ramp delay for the regulator. The driver should *		select ramp delay equal to or less than(closest) ramp_delay. * @set_voltage_time_sel: Time taken for the regulator voltage output voltage *               to stabilise after being set to a new value, in microseconds. *               The function provides the from and to voltage selector, the *               function should return the worst case. * * @set_suspend_voltage: Set the voltage for the regulator when the system *                       is suspended. * @set_suspend_enable: Mark the regulator as enabled when the system is *                      suspended. * @set_suspend_disable: Mark the regulator as disabled when the system is *                       suspended. * @set_suspend_mode: Set the operating mode for the regulator when the *                    system is suspended. * * This struct describes regulator operations which can be implemented by * regulator chip drivers. */struct regulator_ops {	/* enumerate supported voltages */	int (*list_voltage) (struct regulator_dev *, unsigned selector);	/* get/set regulator voltage */	int (*set_voltage) (struct regulator_dev *, int min_uV, int max_uV,			    unsigned *selector);	int (*map_voltage)(struct regulator_dev *, int min_uV, int max_uV);	int (*set_voltage_sel) (struct regulator_dev *, unsigned selector);	int (*get_voltage) (struct regulator_dev *);	int (*get_voltage_sel) (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 consumer.h) */	int (*set_mode) (struct regulator_dev *, unsigned int mode);	unsigned int (*get_mode) (struct regulator_dev *);	/* Time taken to enable or set voltage on the regulator */	int (*enable_time) (struct regulator_dev *);	int (*set_ramp_delay) (struct regulator_dev *, int ramp_delay);	int (*set_voltage_time_sel) (struct regulator_dev *,				     unsigned int old_selector,				     unsigned int new_selector);	/* report regulator status ... most other accessors report	 * control inputs, this reports results of combining inputs	 * from Linux (and other sources) with the actual load.	 * returns REGULATOR_STATUS_* or negative errno.	 */	int (*get_status)(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);	/* control and report on bypass mode */	int (*set_bypass)(struct regulator_dev *dev, bool enable);	int (*get_bypass)(struct regulator_dev *dev, bool *enable);	/* 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 consumer.h) */	int (*set_suspend_mode) (struct regulator_dev *, unsigned int mode);};

regulator_config结构体,包含regulator的pdata的一些描述:

/** * struct regulator_config - Dynamic regulator descriptor * * Each regulator registered with the core is described with a * structure of this type and a struct regulator_desc.  This structure * contains the runtime variable parts of the regulator description. * * @dev: struct device for the regulator * @init_data: platform provided init data, passed through by driver * @driver_data: private regulator data * @of_node: OpenFirmware node to parse for device tree bindings (may be *           NULL). * @regmap: regmap to use for core regmap helpers if dev_get_regulator() is *          insufficient. * @ena_gpio: GPIO controlling regulator enable. * @ena_gpio_invert: Sense for GPIO enable control. * @ena_gpio_flags: Flags to use when calling gpio_request_one() */struct regulator_config {	struct device *dev;	const struct regulator_init_data *init_data;	void *driver_data;	struct device_node *of_node;	struct regmap *regmap;	int ena_gpio;	unsigned int ena_gpio_invert:1;	unsigned int ena_gpio_flags;};regulator_dev结构体,每个电压或电流reulator的设备实例:
/* * struct regulator_dev * * Voltage / Current regulator class device. One for each * regulator. * * This should *not* be used directly by anything except the regulator * core and notification injection (which should take the mutex and do * no other direct access). */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 blocking_notifier_head notifier;	struct mutex mutex; /* consumer lock */	struct module *owner;	struct device dev;	struct regulation_constraints *constraints;	struct regulator *supply;	/* for tree */	struct regmap *regmap;	struct delayed_work disable_work;	int deferred_disables;	void *reg_data;		/* regulator_dev data */	struct dentry *debugfs;	struct regulator_enable_gpio *ena_pin;	unsigned int ena_gpio_state:1;};

regulator_dev注册与注销的方法:

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

regulator结构体,每个Comsumer获取得到的实例:

/* * struct regulator * * One for each consumer device. */struct regulator {	struct device *dev;	struct list_head list;	unsigned int always_on:1;	unsigned int bypass:1;	int uA_load;	int min_uV;	int max_uV;	char *supply_name;	struct device_attribute dev_attr;	struct regulator_dev *rdev;	struct dentry *debugfs;};

Linux的regulator子系统提供消费者(Consumer)API以便让其他的驱动获取、设置、关闭和使能稳压器:

struct regulator *regulator_get(struct device *dev, const char *id);struct regulator *devm_regulator_get(struct device *dev, const char *id);struct regulator *regulator_get_exclusive(struct device *dev, const char *id); /* 获得regulator并独占此id的regulator_dev */void regulator_put(struct regulator *regulator);void devm_regulator_put(struct regulator *regulator);int regulator_enable(struct regulator *regulator);int regulator_disable(struct regulator *regulator);int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV);int regulator_get_voltage(struct regulator *regulator);

这些消费者API的地位大致与GPIO子系统的gpio_request()、时钟子系统的clk_get()、dmaengine子系统的dmaengine_submit()等相当,属于基础设施。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表