kernel - regulator
一、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: %d\n",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 %s\n",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 regulator\n",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 allowed\n");}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;elserdev->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 directory\n");} 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相关推荐
- rsyslogd 重启_RE: 服务器定时重启
服务器定时重启,系统版本:CentOS release 6.2 (Final),内核:2.6.32-279.el6.x86_64 系统产生的日志如下: Jun 14 10:40:20 localhos ...
- android uboot log,RK3288 Android 8.1系统uboot logo过渡到kernel logo会花一下
在调试RK3288 Android 8.1系统遇到一个问题:开机启动uboot logo过渡到kernel log的过程中会花掉直到没有显示,再出现kernel logo. 分析:打印串口log时发现 ...
- 【Linux开发】如何查看Linux kernel的内置模块驱动列表和进程ID
[Linux开发]如何查看Linux kernel的内置模块驱动列表和进程ID 标签:[Linux开发] 命令: cat /lib/modules/$(uname -r)/modules.builti ...
- [IMX6Q][Android5.1]移植笔记 --- Kernel启动无法挂载文件系统
platform: imx6q os: Android5.1 branch: l5.1.1_2.1.0-ga 错误log如下,主要是最后几句: ...... sdhci: Secure Digital ...
- 嵌入式Linux应用与开发——内核配置选项含Linux最新版本kernel下载后续操作
下载官网的最新Linux内核版本,Linux虚拟机中Ubuntu 下载速度慢,更换镜像源后使下载速度正常.这是一个.tar.xz文件,我们要先来解压它.下面是下载内核解压文件编译内核配置内核的全过程. ...
- Rockchip RK3588 kernel dts解析之MMC
Rockchip RK3588 kernel dts解析之MMC RK3588的MMC分为3中模式: SDMMC SDIO SDHCI 下面针对每种模式的DTS配置进行说明 SDMMC SDMMC用于 ...
- I.MX6Q(TQIMX6Q/TQE9)学习笔记——新版BSP之kernel移植
前篇文章已经在tqimx6q上成功跑起了新版BSP的uboot,本文来配置下新版BSP的kernel,使kernel能在tqimx6q上正常启动. 准备工作 每次移植kernel的时候都会做的工作就是 ...
- i.MX arm 3.12.28 Kernel Configuration
#make menucofig画面 General setup ---> 通用选项设置 │ │ ...
- 【嵌入式开发】 Linux Kernel 下载 配置 编译 安装 及 驱动简介
作者 : 韩曙亮 转载请出名出处 : http://blog.csdn.net/shulianghan/article/details/38636827 一. Linux 内核简介 1. 内核功能简介 ...
- 【迅为iMX6Q】开发板:迅为官方提供好的kernel的编译
操作系统:win10 64位 虚拟机:VMware® Workstation 14 Pro 虚拟机操作系统:ubuntu 18.04 64位 ubuntu-18.04.2-desktop-amd64 ...
最新文章
- python 正则表达式方法_Python正则表达式一: 基本使用方法
- Ajax---根据id从数据库查找对应的省份名称
- UOJ#370. 【UR #17】滑稽树上滑稽果 动态规划
- python xlsxwriter 在 flask 中的使用
- php文件写入生成文件,PHP 文件操作类(创建文件并写入) 生成日志
- 【网摘阅读】舒迅:产品经理必读的九步法
- 现代软件工程讲义 4 团队和流程
- unity android 原生,unity创建Android原生插件
- linux scp 隐藏文件,scp 客户端发现了隐藏 35 年的漏洞
- 加密狗破解教程-数据抓取工具
- ubuntu使用cmake编译coffe
- HttpClient 调用耗时长服务问题记录和处理方案
- eclipse java web乱码,eclipse中文乱码解决
- Android两种时间轴实现
- Unity ECS初学
- 《点燃我,温暖你》李峋 代码 爱心❤ - 源代码
- Flink——运行的组件有哪些?分别有什么作用?
- [PM2] Spawning PM2 daemon with pm2_home=/root/.pm2 错误
- XX集团工厂集成改造MES+SCADA数字化项目实施方案原创
- Google OR-Tools(一) Get Start