概述
一、regulator子系统常用数据结构
struct regulator_desc {
const char *name;
const char *supply_name;
const char *of_match;
const char *regulators_node;
int (*of_parse_cb)(struct device_node *,
const struct regulator_desc *,
struct regulator_config *);
int id;
bool continuous_voltage_range;
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 linear_min_sel;
int fixed_uV;
unsigned int ramp_delay;
const struct regulator_linear_range *linear_ranges;
int n_linear_ranges;
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;
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 enable_time;
unsigned int off_on_delay;
unsigned int (*of_map_mode)(unsigned int mode);
};
struct regulator_config {
struct device *dev;
const struct regulator_init_data *init_data;
void *driver_data;
struct device_node *of_node;
struct regmap *regmap;
bool ena_gpio_initialized;
int ena_gpio;
unsigned int ena_gpio_invert:1;
unsigned int ena_gpio_flags;
};
- regulator_register注册时需要的两个结构体参数
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 */
const char *supply_name;
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;
/* time when this regulator was disabled last time */
unsigned long last_off_jiffy;
};
- regulator_register注册时根据regulator_desc和regulator_config最终生成的结构体
二、regulator的注册
struct regulator_dev *
regulator_register(const struct regulator_desc *regulator_desc,
const struct regulator_config *cfg)
{
......
init_data = regulator_of_get_init_data(dev, regulator_desc, config,
&rdev->dev.of_node);
if (!init_data) {
init_data = config->init_data;
rdev->dev.of_node = of_node_get(config->of_node);
}
......
/* preform any regulator specific init */
if (init_data && init_data->regulator_init) {
ret = init_data->regulator_init(rdev->reg_data);
if (ret < 0)
goto clean;
}
......
if ((config->ena_gpio || config->ena_gpio_initialized) &&
gpio_is_valid(config->ena_gpio)) {
ret = regulator_ena_gpio_request(rdev, config);
if (ret != 0) {
rdev_err(rdev, "Failed to request enable GPIO%d: %dn",
config->ena_gpio, ret);
goto wash;
}
}
/* set regulator constraints */
if (init_data)
constraints = &init_data->constraints;
ret = set_machine_constraints(rdev, constraints);
if (ret < 0)
goto scrub;
if (init_data && init_data->supply_regulator)
rdev->supply_name = init_data->supply_regulator;
else if (regulator_desc->supply_name)
rdev->supply_name = regulator_desc->supply_name;
/* add consumers devices */
if (init_data) {
for (i = 0; i < init_data->num_consumer_supplies; i++) {
ret = set_consumer_device_supply(rdev,
init_data->consumer_supplies[i].dev_name,
init_data->consumer_supplies[i].supply);
if (ret < 0) {
dev_err(dev, "Failed to set supply %sn",
init_data->consumer_supplies[i].supply);
goto unset_supplies;
}
}
}
list_add(&rdev->list, ®ulator_list);
rdev_init_debugfs(rdev);
......
}
- 分配和创建regulator_dev设备并注册到链表regulator_list
- 调用set_consumer_device_supply注册consumer_supplies
- 调用rdev_init_debugfs创建debugfs接口
三、获取regulator
struct regulator *regulator_get(struct device *dev, const char *id)
{
return _regulator_get(dev, id, false, true);
}
EXPORT_SYMBOL_GPL(regulator_get);
/* Internal regulator request function */
static struct regulator *_regulator_get(struct device *dev, const char *id,
bool exclusive, bool allow_dummy)
{
......
rdev = regulator_dev_lookup(dev, id, &ret);
if (rdev)
goto found;
......
/*
* Assume that a regulator is physically present and enabled
* even if it isn't hooked up and just provide a dummy.
*/
if (have_full_constraints() && allow_dummy) {
pr_warn("%s supply %s not found, using dummy regulatorn",
devname, id);
rdev = dummy_regulator_rdev;
goto found;
/* Don't log an error when called from regulator_get_optional() */
} else if (!have_full_constraints() || exclusive) {
dev_warn(dev, "dummy supplies not allowedn");
}
mutex_unlock(®ulator_list_mutex);
return regulator;
found:
if (rdev->exclusive) {
regulator = ERR_PTR(-EPERM);
goto out;
}
if (exclusive && rdev->open_count) {
regulator = ERR_PTR(-EBUSY);
goto out;
}
ret = regulator_resolve_supply(rdev);
if (ret < 0) {
regulator = ERR_PTR(ret);
goto out;
}
if (!try_module_get(rdev->owner))
goto out;
regulator = create_regulator(rdev, dev, id);
if (regulator == NULL) {
regulator = ERR_PTR(-ENOMEM);
module_put(rdev->owner);
goto out;
}
rdev->open_count++;
if (exclusive) {
rdev->exclusive = 1;
ret = _regulator_is_enabled(rdev);
if (ret > 0)
rdev->use_count = 1;
else
rdev->use_count = 0;
}
out:
mutex_unlock(®ulator_list_mutex);
return regulator;
}
- regulator_get调用_regulator_get间接去获取regulator
- _regulator_get调用regulator_dev_lookup去查找rdev,如果没有找到返回dummy_regulator_rdev,如果找到则调用create_regulator创建regulator
static struct regulator_dev *regulator_dev_lookup(struct device *dev,
const char *supply,
int *ret)
{
struct regulator_dev *r;
struct device_node *node;
struct regulator_map *map;
const char *devname = NULL;
regulator_supply_alias(&dev, &supply);
/* first do a dt based lookup */
if (dev && dev->of_node) {
node = of_get_regulator(dev, supply);
if (node) {
list_for_each_entry(r, ®ulator_list, list)
if (r->dev.parent &&
node == r->dev.of_node)
return r;
*ret = -EPROBE_DEFER;
return NULL;
} else {
/*
* If we couldn't even get the node then it's
* not just that the device didn't register
* yet, there's no node and we'll never
* succeed.
*/
*ret = -ENODEV;
}
}
/* if not found, try doing it non-dt way */
if (dev)
devname = dev_name(dev);
list_for_each_entry(r, ®ulator_list, list)
if (strcmp(rdev_get_name(r), supply) == 0)
return r;
list_for_each_entry(map, ®ulator_map_list, list) {
/* If the mapping has a device set up it must match */
if (map->dev_name &&
(!devname || strcmp(map->dev_name, devname)))
continue;
if (strcmp(map->supply, supply) == 0)
return map->regulator;
}
return NULL;
}
- 首先通过设备树的方式去查找rdev
- 如果没有找到,在通过regulator_map_list查找rdev.regulator_map_list在regulator_rdev注册的时候初始化的
static struct regulator *create_regulator(struct regulator_dev *rdev,
struct device *dev,
const char *supply_name)
{
struct regulator *regulator;
char buf[REG_STR_SIZE];
int err, size;
regulator = kzalloc(sizeof(*regulator), GFP_KERNEL);
if (regulator == NULL)
return NULL;
mutex_lock(&rdev->mutex);
regulator->rdev = rdev;
list_add(®ulator->list, &rdev->consumer_list);
......
regulator->debugfs = debugfs_create_dir(regulator->supply_name,
rdev->debugfs);
if (!regulator->debugfs) {
rdev_warn(rdev, "Failed to create debugfs directoryn");
} else {
debugfs_create_u32("uA_load", 0444, regulator->debugfs,
®ulator->uA_load);
debugfs_create_u32("min_uV", 0444, regulator->debugfs,
®ulator->min_uV);
debugfs_create_u32("max_uV", 0444, regulator->debugfs,
®ulator->max_uV);
}
......
}
- 创建regulator并注册到rdev的consumer_list
- 创建regulator对应的debugfs调试接口
转载于:https://www.cnblogs.com/qzhang1535/p/10995943.html
最后
以上就是热情睫毛膏为你收集整理的kernel - regulator的全部内容,希望文章能够帮你解决kernel - regulator所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复