了解linux-5.4.31/drivers/gpio/gpiolib-devres.c中的devm_gpiod_get_optional()函数

ops/2025/2/6 16:58:42/

1、打开“drivers/gpio/gpiolib-devres.c

/**

获取GPIO线的索引,查找“设备资源”,分配设备资源数据”,注册“设备资源”;

 * devm_gpiod_get_optional - Resource-managed gpiod_get_optional()

 * @dev: GPIO consumer

 * @con_id: function within the GPIO consumer

 * @flags: optional GPIO initialization flags

 *

 * Managed gpiod_get_optional(). GPIO descriptors returned from this function

 * are automatically disposed on driver detach. See gpiod_get_optional() for

 * detailed information about behavior and return values.

 */

//sii902x->reset_gpio = devm_gpiod_get_optional(dev, "reset",GPIOD_OUT_LOW);

struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev,

       const char *con_id,

       enum gpiod_flags flags)

{

return devm_gpiod_get_index_optional(dev, con_id, 0, flags);

}

/**

获取GPIO线的索引,查找“设备资源”,分配设备资源数据”,注册“设备资源”;

 * devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional()

 * @dev: GPIO consumer

 * @con_id: function within the GPIO consumer

 * @index: index of the GPIO to obtain in the consumer

 * @flags: optional GPIO initialization flags

 *

 * Managed gpiod_get_index_optional(). GPIO descriptors returned from this

 * function are automatically disposed on driver detach. See

 * gpiod_get_index_optional() for detailed information about behavior and

 * return values.

 */

struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev,

     const char *con_id,

     unsigned int index,

     enum gpiod_flags flags)

{

struct gpio_desc *desc;

desc = devm_gpiod_get_index(dev, con_id, index, flags);

//获取GPIO线的索引,查找“设备资源”,分配设备资源数据”,注册“设备资源”;

if (IS_ERR(desc)) {

if (PTR_ERR(desc) == -ENOENT)

return NULL;

}

return desc;

}

/**

获取GPIO线的索引,查找“设备资源”,分配设备资源数据”,注册“设备资源”;

 * devm_gpiod_get_index - Resource-managed gpiod_get_index()

 * @dev: GPIO consumer

 * @con_id: function within the GPIO consumer

 * @idx: index of the GPIO to obtain in the consumer

 * @flags: optional GPIO initialization flags

 *

 * Managed gpiod_get_index(). GPIO descriptors returned from this function are

 * automatically disposed on driver detach. See gpiod_get_index() for detailed

 * information about behavior and return values.

 */

struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,

    const char *con_id,

    unsigned int idx,

    enum gpiod_flags flags)

{

struct gpio_desc **dr;

struct gpio_desc *desc;

desc = gpiod_get_index(dev, con_id, idx, flags);//用于获取GPIO线的索引

if (IS_ERR(desc))

return desc;

/*

 * For non-exclusive GPIO descriptors, check if this descriptor is

 * already under resource management by this device.

 */

if (flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE) {

struct devres *dres;

dres = devres_find(dev, devm_gpiod_release,devm_gpiod_match, &desc);

//查找设备资源

if (dres) return desc;

}

dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),GFP_KERNEL);

//分配设备资源数据

if (!dr) {

gpiod_put(desc);

//释放一个已经申请的GPIO资源,释放后该GPIO可以被其他设备或应用程序使用;

return ERR_PTR(-ENOMEM);

}

*dr = desc;

devres_add(dev, dr);//注册设备资源

return desc;

}

/**

 * devres_find - 查找设备资源Find device resource

 * @dev: Device to lookup resource from

 * @release: Look for resources associated with this release function

 * @match: Match function (optional)

 * @match_data: Data for the match function

 *

 * Find the latest devres of @dev which is associated with @release

 * and for which @match returns 1.  If @match is NULL, it's considered

 * to match all.

 *

 * RETURNS:

 * Pointer to found devres, NULL if not found.

 */

void * devres_find(struct device *dev, dr_release_t release,

   dr_match_t match, void *match_data)

{

struct devres *dr;

unsigned long flags;

spin_lock_irqsave(&dev->devres_lock, flags);

dr = find_dr(dev, release, match, match_data);

spin_unlock_irqrestore(&dev->devres_lock, flags);

if (dr)

return dr->data;

return NULL;

}

2、打开“drivers/gpio/gpiolib.c”

/**

 * gpiod_put - 处理一个GPIO描述符,dispose of a GPIO descriptor

 * @desc: GPIO descriptor to dispose of

 *

 * No descriptor can be used after gpiod_put() has been called on it.

 */

void gpiod_put(struct gpio_desc *desc)

{

if (desc)

gpiod_free(desc);

//用于释放一个已经申请的GPIO资源,释放后该GPIO可以被其他设备或应用程序使用;

}

3、打开“include/linux/device.h”

#define devres_alloc(release, size, gfp) \

__devres_alloc_node(release, size, gfp, NUMA_NO_NODE, #release)

4、打开“drivers/base/devres.c”

/**

 * devres_alloc - 分配设备资源数据Allocate device resource data

 * @release: Release function devres will be associated with

 * @size: Allocation size

 * @gfp: Allocation flags

 * @nid: NUMA node

 *

 * Allocate devres of @size bytes.  The allocated area is zeroed, then

 * associated with @release.  The returned pointer can be passed to

 * other devres_*() functions.

 *

 * RETURNS:

 * Pointer to allocated devres on success, NULL on failure.

 */

void * devres_alloc_node(dr_release_t release, size_t size, gfp_t gfp, int nid)

{

struct devres *dr;

dr = alloc_dr(release, size, gfp | __GFP_ZERO, nid);

if (unlikely(!dr))

return NULL;

return dr->data;

}

static __always_inline struct devres * alloc_dr(dr_release_t release,

size_t size, gfp_t gfp, int nid)

{

size_t tot_size;

struct devres *dr;

/* We must catch any near-SIZE_MAX cases that could overflow. */

if (unlikely(check_add_overflow(sizeof(struct devres), size,

&tot_size)))

return NULL;

dr = kmalloc_node_track_caller(tot_size, gfp, nid);

if (unlikely(!dr))

return NULL;

memset(dr, 0, offsetof(struct devres, data));

INIT_LIST_HEAD(&dr->node.entry);

dr->node.release = release;

return dr;

}

/**

 * devres_add - 注册设备资源,Register device resource

 * @dev: Device to add resource to

 * @res: Resource to register

 *

 * Register devres @res to @dev.  @res should have been allocated

 * using devres_alloc().  On driver detach, the associated release

 * function will be invoked and devres will be freed automatically.

 */

void devres_add(struct device *dev, void *res)

{

struct devres *dr = container_of(res, struct devres, data);

unsigned long flags;

spin_lock_irqsave(&dev->devres_lock, flags);

add_dr(dev, &dr->node);

spin_unlock_irqrestore(&dev->devres_lock, flags);

}


http://www.ppmy.cn/ops/156196.html

相关文章

LabVIEW自定义测量参数怎么设置?

以下通过一个温度采集案例,说明在 LabVIEW 中设置自定义测量参数的具体方法: 案例背景 ​ 假设使用 NI USB-6009 数据采集卡 和 热电偶传感器 监测温度,需自定义以下参数: 采样率:1 kHz 输入量程:0~10 V&a…

【数据结构】_链表经典算法OJ:相交链表

目录 1. 题目链接及描述 2. 解题思路 2.1 思路1:一个链表把另外一个链表的结点逐个轮一遍 2.2 思路2:截断长链表,从距离交点结点前等距处开始同时遍历(本题解法) 3. 程序 关于解题程序的细节: 3.1…

暴力破解与验证码安全

目录 前言 暴力破解:简单粗暴的黑客攻击手段 暴力破解的前提条件 暴力破解的定义与原理 常见的暴力破解工具 暴力破解的常见场景 暴力破解的危害 验证码:抵御暴力破解的第一道防线 验证码的定义与作用 验证码的工作原理 验证码的类型 验证码…

JDK17主要特性

JDK 17,也被称为Java 17或Java Platform, Standard Edition 17,是Java编程语言的第十七个主要版本,由Oracle公司在2021年9月发布。Java 17是一个长期支持(LTS,Long-Term Support)版本,这意味着它…

蓝桥杯之c++入门(一)【C++入门】

目录 前言5. 算术操作符5.1 算术操作符5.2 浮点数的除法5.3 负数取模5.4 数值溢出5.5 练习练习1:计算 ( a b ) ⋆ c (ab)^{\star}c (ab)⋆c练习2:带余除法练习3:整数个位练习4:整数十位练习5:时间转换练习6&#xff…

【论文投稿-第八届智能制造与自动化学术会议(IMA 2025)】HTML, CSS, JavaScript:三者的联系与区别

大会官网:www.icamima.org 目录 前言 一、HTML(超文本标记语言):网页的骨架 HTML 的作用: 例子: 总结: 二、CSS(层叠样式表):网页的外观设计 CSS 的…

Kafka分区策略实现

引言 Kafka 的分区策略决定了生产者发送的消息会被分配到哪个分区中,合理的分区策略有助于实现负载均衡、提高消息处理效率以及满足特定的业务需求。 轮询策略(默认) 轮询策略是 Kafka 默认的分区策略(当消息没有指定键时&…

2021Java面试-基础篇

文章目录 前言一: Java概述 1、何为编程2、JDK1.5之后的三大版本3、JVM,JRE和JDK的关系4、什么是跨平台?原理是什么5、Java语言有哪些特点6、什么是字节码?采用字节码的最大好处是什么7、什么是Java程序的主类?应用程序和小程序的…