Linux regulator子系统分析2(基于Linux6.6)---数据结构介绍
一、数据结构间的关联说明
针对regulator子系统,包括regulator device(电源提供者)、电源管理芯片(pmic)、电源使用者(consumer)、电源域等几个概念。而在regulator子系统的实现中,则抽象了数据结构regulator_device(表示一个regulator device)、regulator(对应一个电源使用者 consumer),然后围绕这两个数据结构,又定义了regulator_map、regulator_enable_gpio、regulator_desc、regulator_ops、regulator_constraints、regulator_config、regulator_init_data、regulator_consumer_supply等数据结构。
如下图所示,表示数据结构struct regulator_map、struct regulator、struct regulator_dev的关联图:
- 系统中所有注册的struct regulator_dev类型的变量,均会添加到链表regulator_list中,而这些操作由接口regulator_register实现。
- 在regulator_register接口中,针对一个regulator device的所有使用者,均为其创建struct regulator_map类型变量,并将其插入regulator_map_list链表上,而struct regulator_map中包含该使用者的名称(使用者对应的设备名称、使用类型、regulator_dev类型的指针指向该电源的提供者);
- 当电源的使用者(对应的device驱动)在驱动接口中调用regulator_get,申请一个电源使用信息时,则根据该设备的名称、supply名称,在regulator_map_list上查找对应struct regulator_map类型的变量,并创建struct regulator类型的变量,并将其加入到struct regulator_dev的consumer_list链表中,从而实现下图struct regulator、struct regulator_dev的关联(它们之间的关联,需要借助注册在regulator_map_list链表的regulator_map类型变量)。
- 若该regulator_dev通过gpio进行enable/disable的控制,则在调用接口regulator_register接口进行regulator_dev的注册时,则创建对应struct regulator_enable_gpio类型变量的创建,并注册到链表regulator_ena_gpio_list中。
下图的数据结构间的关联主要借助接口regulator_register、regulator_get实现。而在regulator_register接口中实现regulator_dev、regulator_map的关联时,还涉及数据结构regulator_enable_gpio、regulator_desc、regulator_ops、regulator_constraints、regulator_config、regulator_init_data、regulator_consumer_supply的关联(这在数据结构regulator_dev中说明)
二、regulator_dev相关数据结构说明
struct regulator_dev包含多个数据结构,因此将这几个数据结构间的关联进行说明。如下图所示即为regulator_dev相关的数据结构的关联图。
2.1、struct regulator_config相关数据结构
include/linux/regulator/driver.h
struct regulator_config {
struct device *dev;
const struct regulator_init_data *init_data;
void *driver_data;
struct device_node *of_node;
struct regmap *regmap;
struct gpio_desc *ena_gpiod;
};
struct regulator_config相关数据结构主要用于描述regulator_dev的所有使用者信息,以及该regulator_dev的输出参数信息,具体说明如下:
- struct regulator_consumer_supply表示一个regulator_dev的使用者描述,包含使用者对应的设备名称(也可为空)、supply名称,通过这些描述信息,在调用接口regulator_register接口进行regulator_dev的注册时,则根据该数据结构描述的信息,完成上面所说的struct regulator_map类型变量的注册,以便调用regulator_get时可实现struct regulator类型变量的创建;
- 若该regulator_dev通过gpio进行enable/disable的控制,则需要对该gpio进行描述(包含gpio号、gpio使能状态、gpio状态是否为invert等),在调用接口regulator_register接口进行regulator_dev的注册时,则创建对应struct regulator_enable_gpio类型变量的创建,并注册到链表regulator_ena_gpio_list中。
- 数据结构struct regulation_constraints描述该regulator dev相关的配置信息,包括最小输出电压、最大输出电压、初始模式、是否支持suspend state(suspend to memory、suspend to disk、suspend standby状态等)
2.2、struct regulator_desc相关数据结构
主要涉及struct regulator_desc、struct regulator_ops,具体说明如下:
- struct regulator_desc描述该regulator device的类型(电压、电流、电流和电压)、中断id、支持的输出电压个数、操作类型(可改变电压等)、输出模式(fast、normal、idle、standby等);若该regulator device在注册的时候支持通过regmap进行配置(如该regulator device可通过spi、iic接口访问,则可以通过spi/iic对应的regmap接口访问该regulator device的寄存器,进行配置操作),则需要定义enable_reg、enable_mask、apply_reg等参数的信息,以便通过regmap进行配置
以上介绍的是数据结构间关联的说明,下面对几个数据结构进行简要说明:
三、struct regulator_desc
该数据结构是一个regulator_dev的描述信息:
- regulator的名称;
- 若该regulator device是由别的的regulator device提供的电源(即该regulator device是另一个regulator device的使用者),则supply_name表示提供电源的regulator device名称;
- 说明该regulator device可提供的输出电压个数、支持的输出电压列表、单步电压调节值等
- 该regulator device的操作接口(struct regulator_ops,包括设置电压、设置电流、输出使能等接口)
include/linux/regulator/driver.h
struct regulator_desc {
const char *name;
const char *supply_name;
const char *of_match;
bool of_match_full_name;
const char *regulators_node;
int (*of_parse_cb)(struct device_node *,
const struct regulator_desc *,
struct regulator_config *);
int id;
unsigned int continuous_voltage_range:1;
unsigned n_voltages;
unsigned int n_current_limits;
const struct regulator_ops *ops;
int irq;
enum regulator_type type;
struct module *owner;
unsigned int min_uV;
unsigned int uV_step;
unsigned int linear_min_sel;
int fixed_uV;
unsigned int ramp_delay;
int min_dropout_uV;
const struct linear_range *linear_ranges;
const unsigned int *linear_range_selectors_bitfield;
int n_linear_ranges;
const unsigned int *volt_table;
const unsigned int *curr_table;
unsigned int vsel_range_reg;
unsigned int vsel_range_mask;
unsigned int vsel_reg;
unsigned int vsel_mask;
unsigned int vsel_step;
unsigned int csel_reg;
unsigned int csel_mask;
unsigned int apply_reg;
unsigned int apply_bit;
unsigned int enable_reg;
unsigned int enable_mask;
unsigned int enable_val;
unsigned int disable_val;
bool enable_is_inverted;
unsigned int bypass_reg;
unsigned int bypass_mask;
unsigned int bypass_val_on;
unsigned int bypass_val_off;
unsigned int active_discharge_on;
unsigned int active_discharge_off;
unsigned int active_discharge_mask;
unsigned int active_discharge_reg;
unsigned int soft_start_reg;
unsigned int soft_start_mask;
unsigned int soft_start_val_on;
unsigned int pull_down_reg;
unsigned int pull_down_mask;
unsigned int pull_down_val_on;
unsigned int ramp_reg;
unsigned int ramp_mask;
const unsigned int *ramp_delay_table;
unsigned int n_ramp_values;
unsigned int enable_time;
unsigned int off_on_delay;
unsigned int poll_enabled_time;
unsigned int (*of_map_mode)(unsigned int mode);
};
四、struct regulation_constraints
该数据结构描述regulator device的约束信息,定义如下:
- 输出电压范围;
- 输出电流范围;
- 该regulator device支持的模式(fast、normal、idle、standby等);
- 该regulator device支持的操作模式,包括change volt、change current、change bypass mode等;
- 该regulator device支持的suspend 状态下的输出控制(如在suspend to disk状态下的输出控制等);
include/linux/regulator/machine.h
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;
/* 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 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 */
};
五、struct regulator_dev
该数据结构表示一个regulator device,定义如下;
- 该regulator device的描述信息,struct regulator_desc类型的变量,描述regulator_dev的电压输出信息、操作信息(使能去使能接口、电压设置与获取接口、电流设置与获取接口);
- 该regulator_dev所有使用者的信息(consumer_list链表上的regulator成员);
- 该regulator_dev是另一个regulator_dev的使用者,则通过supply作为使用者信息;
- 该regulator_dev是否支持通过regmap访问;
- notifier链表,用于regulator_dev状态变化的通知链;
include/linux/regulator/driver.h
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 ww_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;
void *reg_data; /* regulator_dev data */
struct dentry *debugfs;
struct regulator_enable_gpio *ena_pin;
unsigned int ena_gpio_state:1;
unsigned int is_switch:1;
/* time when this regulator was disabled last time */
ktime_t last_off;
int cached_err;
bool use_cached_err;
spinlock_t err_lock;
};
六、struct regulator
该数据结构表示一个regulator device的使用者,包括是否一直使能、是否使用bypass模式(bypass模式指regulator device输入电压直接作为输出,不做限制)、电压范围、电流值、设备属性信息、该regulator对应的supply名称等。
drivers/regulator/internal.h
/*
* 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;
int enabled;
char *supply_name;
struct device_attribute dev_attr;
struct regulator_dev *rdev;
struct dentry *debugfs;
};