一、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, &regulator_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(&regulator_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(&regulator_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, &regulator_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, &regulator_list, list)if (strcmp(rdev_get_name(r), supply) == 0)return r;list_for_each_entry(map, &regulator_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(&regulator->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,&regulator->uA_load);debugfs_create_u32("min_uV", 0444, regulator->debugfs,&regulator->min_uV);debugfs_create_u32("max_uV", 0444, regulator->debugfs,&regulator->max_uV);}......
}
  • 创建regulator并注册到rdev的consumer_list
  • 创建regulator对应的debugfs调试接口

转载于:https://www.cnblogs.com/qzhang1535/p/10995943.html

kernel - regulator相关推荐

  1. rsyslogd 重启_RE: 服务器定时重启

    服务器定时重启,系统版本:CentOS release 6.2 (Final),内核:2.6.32-279.el6.x86_64 系统产生的日志如下: Jun 14 10:40:20 localhos ...

  2. android uboot log,RK3288 Android 8.1系统uboot logo过渡到kernel logo会花一下

    在调试RK3288 Android 8.1系统遇到一个问题:开机启动uboot logo过渡到kernel log的过程中会花掉直到没有显示,再出现kernel logo. 分析:打印串口log时发现 ...

  3. 【Linux开发】如何查看Linux kernel的内置模块驱动列表和进程ID

    [Linux开发]如何查看Linux kernel的内置模块驱动列表和进程ID 标签:[Linux开发] 命令: cat /lib/modules/$(uname -r)/modules.builti ...

  4. [IMX6Q][Android5.1]移植笔记 --- Kernel启动无法挂载文件系统

    platform: imx6q os: Android5.1 branch: l5.1.1_2.1.0-ga 错误log如下,主要是最后几句: ...... sdhci: Secure Digital ...

  5. 嵌入式Linux应用与开发——内核配置选项含Linux最新版本kernel下载后续操作

    下载官网的最新Linux内核版本,Linux虚拟机中Ubuntu 下载速度慢,更换镜像源后使下载速度正常.这是一个.tar.xz文件,我们要先来解压它.下面是下载内核解压文件编译内核配置内核的全过程. ...

  6. Rockchip RK3588 kernel dts解析之MMC

    Rockchip RK3588 kernel dts解析之MMC RK3588的MMC分为3中模式: SDMMC SDIO SDHCI 下面针对每种模式的DTS配置进行说明 SDMMC SDMMC用于 ...

  7. I.MX6Q(TQIMX6Q/TQE9)学习笔记——新版BSP之kernel移植

    前篇文章已经在tqimx6q上成功跑起了新版BSP的uboot,本文来配置下新版BSP的kernel,使kernel能在tqimx6q上正常启动. 准备工作 每次移植kernel的时候都会做的工作就是 ...

  8. i.MX arm 3.12.28 Kernel Configuration

    #make menucofig画面 General setup  --->                                                 通用选项设置 │ │ ...

  9. 【嵌入式开发】 Linux Kernel 下载 配置 编译 安装 及 驱动简介

    作者 : 韩曙亮 转载请出名出处 : http://blog.csdn.net/shulianghan/article/details/38636827 一. Linux 内核简介 1. 内核功能简介 ...

  10. 【迅为iMX6Q】开发板:迅为官方提供好的kernel的编译

    操作系统:win10 64位 虚拟机:VMware® Workstation 14 Pro 虚拟机操作系统:ubuntu 18.04 64位  ubuntu-18.04.2-desktop-amd64 ...

最新文章

  1. python 正则表达式方法_Python正则表达式一: 基本使用方法
  2. Ajax---根据id从数据库查找对应的省份名称
  3. UOJ#370. 【UR #17】滑稽树上滑稽果 动态规划
  4. python xlsxwriter 在 flask 中的使用
  5. php文件写入生成文件,PHP 文件操作类(创建文件并写入) 生成日志
  6. 【网摘阅读】舒迅:产品经理必读的九步法
  7. 现代软件工程讲义 4 团队和流程
  8. unity android 原生,unity创建Android原生插件
  9. linux scp 隐藏文件,scp 客户端发现了隐藏 35 年的漏洞
  10. 加密狗破解教程-数据抓取工具
  11. ubuntu使用cmake编译coffe
  12. HttpClient 调用耗时长服务问题记录和处理方案
  13. eclipse java web乱码,eclipse中文乱码解决
  14. Android两种时间轴实现
  15. Unity ECS初学
  16. 《点燃我,温暖你》李峋 代码 爱心❤ - 源代码
  17. Flink——运行的组件有哪些?分别有什么作用?
  18. [PM2] Spawning PM2 daemon with pm2_home=/root/.pm2 错误
  19. XX集团工厂集成改造MES+SCADA数字化项目实施方案原创
  20. Google OR-Tools(一) Get Start

热门文章

  1. 记录六足机器人的各类参数(micropython)
  2. spider pi 智能视觉六足机器人 开箱介绍 0602
  3. Linux文件群发脚本
  4. 我编写的肺炎疫情数据API的实现过程
  5. P1357 花园(状压dp + 矩阵快速幂)
  6. 博士入学考题(ZZ)
  7. 论文解读:预测lncRNA的相互作用生物分子类型:一种集成深度学习方法
  8. codeforces1428F Fruit Sequences
  9. 【liunxptp协议栈详解第一部分】
  10. FOTA升级差分包编译服务器搭建