当前位置:   article > 正文

gpio编号到描述符的转换_gpio_to_desc

gpio_to_desc

前言

最近在调试一个新板子的LED驱动,LED灯用到了特定的GPIO引脚,而驱动中有一项工作就是需要占用某个GPIO资源并设置为输出引脚,调用的接口类似如下:

  1. #define GPIOAO_3 (3)  /* GPIOAO_3这个引脚的id为3 */
  2. gpio_request(GPIOAO_3, OWNER_NAME);  /* 占用GPIOAO_3这个GPIO的资源 */
  3. gpio_direction_output(GPIOAO_3, 0); /* 将GPIOAO_3这个GPIO设置为输出引脚并拉低 */

上面的代码比较常见,应该很多同学都看过类似的,现在问题就来了,为什么GPIOAO_3这个GPIO定义为3呢?这个就是我今天要讨论的问题。

正文

前面提出的问题,下面我们会跟着代码来一步步找出答案。每个平台都有自己的GPIO驱动,下面我用到的芯片平台是amlogic s805。虽然代码有差异,但是基本架构是不变的,一般都从probe函数开始,并调用gpiochip_add()函数将自己的驱动注册进系统,在这个过程就决定了GPIO的编号到描述符的映射关系。

1、

代码路径:

amlogic_gpio_probe:arch\arm\mach-meson8b\gpio.c

函数调用:

  1. struct amlogic_gpio_desc amlogic_pins[]=
  2. {
  3.     PIN_AOMAP(GPIOAO_0,6,0,6,16,6,0),
  4.     PIN_AOMAP(GPIOAO_1,6,1,6,17,6,1),
  5.     PIN_AOMAP(GPIOAO_2,6,2,6,18,6,2),
  6.     PIN_AOMAP(GPIOAO_3,6,3,6,19,6,3),
  7.     PIN_AOMAP(GPIOAO_4,6,4,6,20,6,4),
  8.     ...
  9. };
  10. static int amlogic_gpio_probe(struct platform_device *pdev)
  11. {
  12.     ...
  13.     amlogic_gpio_chip.base=0; /* base这个变量值很重要,奠定了后续gpio编号的起始值 */
  14.     amlogic_gpio_chip.ngpio=ARRAY_SIZE(amlogic_pins); /* amlogic_pins是一个数组,里面按顺序列出了平台所有的GPIO引脚 */
  15.     gpiochip_add(&amlogic_gpio_chip); /* 注册进系统 */
  16.     ...
  17.     return 0;
  18. }

2、

代码路径:

gpiochip_add:drivers\gpio\gpiolib.c

函数调用:

  1. int gpiochip_add(struct gpio_chip *chip)
  2. {
  3.     ...
  4.     int        base = chip->base;
  5.     if ((!gpio_is_valid(base) || !gpio_is_valid(base + chip->ngpio - 1)) /* 判断编号和GPIO数是否超过了规定的范围,我这里是0~256 */
  6.             && base >= 0) {
  7.         status = -EINVAL;
  8.         goto fail;
  9.     }
  10.     spin_lock_irqsave(&gpio_lock, flags);
  11.     if (base < 0) { /* 我这个平台的base值是0,不会走到下面的分支 */
  12.         base = gpiochip_find_base(chip->ngpio);   -------------------- 2.1小节
  13.         if (base < 0) {
  14.             status = base;
  15.             goto unlock;
  16.         }
  17.         chip->base = base;
  18.     }
  19.     status = gpiochip_add_to_list(chip); /* 将自己平台的GPIO注册进系统的链表 */
  20.     if (status == 0) {
  21.         chip->desc = &gpio_desc[chip->base]; /* GPIO编号和描述符是一个线性映射的关系,而gpio_desc这个数组就保存这个映射关系,并从base这个偏移位置开始保存每个GPIO的描述符信息 */
  22.         for (id = 0; id < chip->ngpio; id++) { /* 这个for循环里就为每一个GPIO描述符赋值 */
  23.             struct gpio_desc *desc = &chip->desc[id]; /* 描述符的首地址指向gpio_desc数组偏移base的位置 */
  24.             desc->chip = chip;
  25.             
  26.             desc->flags = !chip->direction_input
  27.                 ? (1 << FLAG_IS_OUT)
  28.                 : 0;
  29.         }
  30.     }
  31.     ...
  32.     return status;
  33. }

2.1、

如果你的平台的base小于0,会走到下面的函数去为这组GPIO引脚自动分配一个base值

代码路径:

gpiochip_add:drivers\gpio\gpiolib.c

函数调用:

  1. static int gpiochip_find_base(int ngpio)
  2. {
  3.     struct gpio_chip *chip;
  4.     int base = ARCH_NR_GPIOS - ngpio; /* ARCH_NR_GPIOS一般是平台中GPIO数量的最大值 */
  5.     list_for_each_entry_reverse(chip, &gpio_chips, list) { /* 倒序遍历链表(因为GPIO引脚可能分为了好几个bank),目的是找出gpio_desc数组中已经被占用的位置 */
  6.         /* found a free space? */
  7.         if (chip->base + chip->ngpio <= base) /* 如果已经被占用的数组位置和准备分配的位置不重合,自然就直接跳出循环了 */
  8.             break;
  9.         else
  10.             /* nope, check the space right before the chip */
  11.             base = chip->base - ngpio;
  12.     }
  13.     if (gpio_is_valid(base)) { /* 检查是否在规定的范围内 */
  14.         pr_debug("%s: found new base at %d\n", __func__, base);
  15.         return base;
  16.     } else {
  17.         pr_err("%s: cannot find free range\n", __func__);
  18.         return -ENOSPC;
  19.     }
  20. }

3、

从上面两步可以看出来,GPIO编号和描述符之间的关系是由gpio_desc这个数组决定的。所以我们想通过GPIO编号找到对应的描述符,就必须知道这个描述符在数组中的偏移位置,而偏移多少可以根据GPIO在amlogic_pins这个数组的位置加上base值得到。

代码路径:

drivers\gpio\gpiolib.c

函数调用关系:

  1. gpio_request
  2.     gpiod_request
  3.         gpio_to_desc
  4. static struct gpio_desc *gpio_to_desc(unsigned gpio)
  5. {
  6.     if (WARN(!gpio_is_valid(gpio), "invalid GPIO %d\n", gpio))
  7.         return NULL;
  8.     else
  9.         return &gpio_desc[gpio]; /* 就是根据传递过来的GPIO编号在数组中找到描述符 */
  10. }


 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/397770
推荐阅读
相关标签
  

闽ICP备14008679号