Linux驱动开发---gpio和gpiod

一、旧的gpio_api

在GTX5驱动中兼容了两种获取GPIO、IRQ资源的方法,在老的内核版本中是通过of_get_named_gpio(node,"goodix,reset-gpio", 0)方法去获取GPIO资源的资源号(一个int型的数值),然后再使用如下方法(代码段1)对GPIO资源进行操作。

代码段1

r =devm_gpio_request_one(&core_data->pdev->dev,

                            ts_bdata->reset_gpio,

                            GPIOF_OUT_INIT_LOW,

                            "ts_reset_gpio"); 

二、新的gpiod_api

但在内核3.13之后,引入了新的gpiod_api,该api使用“devm_gpiod_get”去获取GPIO资源,获取到的是一个类型为“struct gpio_desc”的结构体指针,在操作GPIO时使用的是“gpiod_direction_output”方法。这两个方法的调用示例如代码段2和代码段3中所示:

代码段2

devm_gpiod_get(&core_data->pdev->dev,

                            "goodix,reset-gpio",GPIOD_OUT_LOW) 的goodix_ts_core.c中

 

代码段3

gpiod_direction_output(dev->board_data->reset_gpiod, 0);

“devm_gpiod_get”方法在获取GPIO资源时,仍然是通过of_node去获取的,其具体实现,如代码段4中所示。

代码段4

Kernel\drivers\gpio\gpiolib.c

/**

 * gpiod_get_index - obtain aGPIO from a multi-index GPIO function

 * @dev: GPIO consumer, can be NULL for system-global GPIOs

 * @con_id:    function within the GPIO consumer

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

 * @flags:        optional GPIO initialization flags

 *

 * This variant of gpiod_get()allows to access GPIOs other than the first

 * defined one for functions thatdefine several GPIOs.

 *

 * Return a valid GPIOdescriptor, -ENOENT if no GPIO has been assigned to the

 * requested function and/orindex, or another IS_ERR() code if an error

 * occured while trying toacquire the GPIO.

 */

struct gpio_desc *__must_check __gpiod_get_index(struct device *dev,

                                                      const char *con_id,

                                                      unsigned int idx,

                                                      enum gpiod_flags flags)

{

         struct gpio_desc *desc =NULL;

         int status;

         enum gpio_lookup_flagslookupflags = 0;

 

         dev_dbg(dev, "GPIOlookup for consumer %s\n", con_id);

 

         /* Using device tree? */

         if (IS_ENABLED(CONFIG_OF)&& dev && dev->of_node) {

                   dev_dbg(dev,"using device tree for GPIO lookup\n");

                   desc =of_find_gpio(dev, con_id, idx, &lookupflags);

         } else if(IS_ENABLED(CONFIG_ACPI) && dev && ACPI_HANDLE(dev)) {

                   dev_dbg(dev,"using ACPI for GPIO lookup\n");

                   desc =acpi_find_gpio(dev, con_id, idx, &lookupflags);

         }

 

         /*

          * Either we are not using DT or ACPI, or theirlookup did not return

          * a result. In that case, use platform lookupas a fallback.

          */

         if (!desc || desc ==ERR_PTR(-ENOENT)) {

                   dev_dbg(dev,"using lookup tables for GPIO lookup\n");

                   desc =gpiod_find(dev, con_id, idx, &lookupflags);

         }

 

         if (IS_ERR(desc)) {

                   dev_dbg(dev,"lookup for GPIO %s failed\n", con_id);

                   return desc;

         }

 

         status =gpiod_request(desc, con_id);

 

         if (status < 0)

                   returnERR_PTR(status);

 

         if (lookupflags &GPIO_ACTIVE_LOW)

                   set_bit(FLAG_ACTIVE_LOW,&desc->flags);

         if (lookupflags &GPIO_OPEN_DRAIN)

                   set_bit(FLAG_OPEN_DRAIN,&desc->flags);

         if (lookupflags &GPIO_OPEN_SOURCE)

                   set_bit(FLAG_OPEN_SOURCE,&desc->flags);

 

         /* No particular flagrequest, return here... */

         if (!(flags &GPIOD_FLAGS_BIT_DIR_SET))

                   return desc;

 

         /* Process flags */

         if (flags &GPIOD_FLAGS_BIT_DIR_OUT)

                   status =gpiod_direction_output(desc,

                                                     flags & GPIOD_FLAGS_BIT_DIR_VAL);

         else

                   status =gpiod_direction_input(desc);

 

         if (status < 0) {

                   dev_dbg(dev,"setup of GPIO %s failed\n", con_id);

                   gpiod_put(desc);

                   returnERR_PTR(status);

         }

 

         return desc;

}

EXPORT_SYMBOL_GPL(__gpiod_get_index);

三、调用devm_gpiod_get时的注意点

 

使用该方法时,给方法传递的第二个参数一定要特别注意。追踪该方法在内核中的具体实现可知:devm_gpiod_get最终调用的是gpiolib.c中的“__gpiod_get_index”方法,而该方法最终调用的是“of_find_gpio”方法,查看该方法的实现可知,方法在查找GPIO资源时已经自动为我们加了“-gpio”、“-gpios”后缀,所以我们在调用devm_gpiod_get时,要对匹配字符串进行相应的修改。

比如在DTS中有如下的资源:

snowflate,reset-gpio= <&pio 256 0>;

那么在调用devm_gpiod_get去获取该资源时,第二个参数直接传"snowflate,reset"就可以了,而不是传递“snowflate,reset-gpio”。

代码段5

Kernel\drivers\gpio\gpiolib.c

staticstruct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,

                                           unsigned int idx,

                                           enum gpio_lookup_flags *flags)

{

         static const char *suffixes[] = { "gpios","gpio" };

         char prop_name[32]; /* 32 is max size of property name */

         enum of_gpio_flags of_flags;

         struct gpio_desc *desc;

         unsigned int i;

 

         for (i = 0; i < ARRAY_SIZE(suffixes); i++) {

                   if (con_id)

                            snprintf(prop_name, 32,"%s-%s", con_id, suffixes[i]);

                   else

                            snprintf(prop_name, 32, "%s",suffixes[i]);

 

                   desc = of_get_named_gpiod_flags(dev->of_node,prop_name, idx,

                                                        &of_flags);

                   if (!IS_ERR(desc) || (PTR_ERR(desc) ==-EPROBE_DEFER))

                            break;

         }

 

         if (IS_ERR(desc))

                   return desc;

 

         if (of_flags & OF_GPIO_ACTIVE_LOW)

                   *flags |= GPIO_ACTIVE_LOW;

 

         return desc;

}

 

 

  • 3
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux中,gpiod是一个用于操作GPIO(通用输入输出)的API。它提供了一种简单而统一的方式来获取和控制GPIO资源。在不同的内核版本中,有不同的方法来获取和操作GPIO资源。 在老的内核版本中,可以使用of_get_named_gpio方法来获取GPIO资源的资源号,然后使用相应的方法对GPIO资源进行操作。例如,可以使用代码段1中的方法来操作GPIO资源。\[1\] 然而,在新的内核版本中,引入了新的gpiod_api。使用devm_gpiod_get方法可以获取一个类型为"struct gpio_desc"的结构体指针,然后可以使用gpiod_direction_output等方法来操作GPIO资源。例如,可以使用代码段2和代码段3中的方法来操作GPIO资源。\[3\] 需要注意的是,在使用devm_gpiod_get方法时,要对匹配字符串进行相应的修改,因为该方法会自动为我们加上"-gpio"或"-gpios"后缀。\[2\] 总之,gpiod是一个用于操作GPIO的API,在不同的内核版本中,可以使用不同的方法来获取和操作GPIO资源。 #### 引用[.reference_title] - *1* *2* *3* [Linux驱动开发---gpiogpiod](https://blog.csdn.net/happy987818/article/details/76854306)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值