gpio被其他模块占用 gpio_request

gpio_request()简单分析

2015年01月28日 10:38:00

阅读数:3950

一、软件环境

Andorid Version:5.0

Cpu & Arch:Intel X86_64

 

二、File Path

include/linux/gpio.h

include/asm-generic/gpio.h

drivers/gpio/gpiolib.c

 

三、代码分析

 

 
  1. int gpio_request(unsigned gpio, const char *label)

  2. {

  3. <span style="white-space:pre"> </span>return gpiod_request(gpio_to_desc(gpio), label);

  4. }

  5. EXPORT_SYMBOL_GPL(gpio_request);

 

(1)根据gpio序号获取相应的描述gpio的结构体desc

 
  1. static struct gpio_desc *gpio_to_desc(unsigned gpio)

  2. { //<span style="font-family: Arial, Helvetica, sans-serif;">条件为真时(</span><span style="font-family: Arial, Helvetica, sans-serif;">0 <= gpio < ARCH_NR_GPIOS)输出Debug信息,且返回NULL</span>

  3. if (WARN(!gpio_is_valid(gpio), "invalid GPIO %d\n", gpio))

  4. return NULL;

  5. else

  6. return &gpio_desc[gpio];

  7. }

(2)根据desc与label,调用gpiod_request注册gpio口

 

 
  1. static int gpiod_request(struct gpio_desc *desc, const char *label)

  2. {

  3. struct gpio_chip *chip;

  4. int status = -EPROBE_DEFER;

  5. unsigned long flags;

  6.  
  7. if (!desc) {

  8. pr_warn("%s: invalid GPIO\n", __func__);

  9. return -EINVAL;

  10. }

  11.  
  12. spin_lock_irqsave(&gpio_lock, flags);

  13.  
  14. chip = desc->chip;

  15. if (chip == NULL)

  16. goto done;

  17.  
  18. if (!try_module_get(chip->owner))

  19. goto done;

  20.  
  21. /* NOTE: gpio_request() can be called in early boot,

  22. * before IRQs are enabled, for non-sleeping (SOC) GPIOs.

  23. */

  24.  
  25. if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {//设置flags的第0位为1,并返回原来的值

  26. desc_set_label(desc, label ? : "?");

  27. status = 0;

  28. } else {

  29. status = -EBUSY;

  30. module_put(chip->owner);

  31. goto done;

  32. }

  33.  
  34. if (chip->request) {

  35. /* chip->request may sleep */

  36. spin_unlock_irqrestore(&gpio_lock, flags);

  37. status = chip->request(chip, gpio_chip_hwgpio(desc));

  38. spin_lock_irqsave(&gpio_lock, flags);

  39.  
  40. if (status < 0) {

  41. desc_set_label(desc, NULL);

  42. module_put(chip->owner);

  43. clear_bit(FLAG_REQUESTED, &desc->flags);

  44. goto done;

  45. }

  46. }

  47. if (chip->get_direction) {

  48. /* chip->get_direction may sleep */

  49. spin_unlock_irqrestore(&gpio_lock, flags);

  50. gpiod_get_direction(desc);

  51. spin_lock_irqsave(&gpio_lock, flags);

  52. }

  53. done:

  54. if (status)

  55. pr_debug("_gpio_request: gpio-%d (%s) status %d\n",

  56. desc_to_gpio(desc), label ? : "?", status);

  57. spin_unlock_irqrestore(&gpio_lock, flags);

  58. return status;

  59. }


Q&A

==================================================================================================

一、驱动中是如何调到gpiolib.c中的gpio_reuqset函数的?

(1)头文件包含
#inlcude <linux/gpio.h>


#ifdef CONFIG_GPIOLIB

#ifdef CONFIG_ARCH_HAVE_CUSTOM_GPIO_H
#include <asm/gpio.h>
#else
#include <asm-generic/gpio.h>
#endif /* ! CONFIG_ARCH_HAVE_CUSTOM_GPIO_H */

#else /* ! CONFIG_GPIOLIB */

......

#endif /* ! CONFIG_GPIOLIB */


(2)函数声明
include/asm-generic/gpio.h
extern int gpio_request(unsigned gpio, const char *label);

(3)符号导出
drivers/gpio/gpiolib.c
EXPORT_SYMBOL_GPL(gpio_request);




二、gpio_requset的返回值

根据官方文档Documentation/gpio.txt可知返回值有如下关系

0 :成功
负值 :失败

具体分析gpiod_request函数
(1)
if (!desc) {
pr_warn("%s: invalid GPIO\n", __func__);
return -EINVAL;
}
(2)
if (chip == NULL)
return -EPROBE_DEFER;

(3)
if (!try_module_get(chip->owner))
return -EPROBE_DEFER;
(4)
if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0)
return -EBUSY;

因此,在写驱动代码时如下判错是错误的!

 

 
  1. ret = gpio_request(RST_PORT, "GSL_RST");

  2. if (ret) { //错误的写法,判错条件应为ret < 0

  3. printk( "ret = %d : could not req gpio reset\n", ret);

  4. }



三、当gpio被其他模块占用时怎么快速定位

根据gpio序号,在注册的函数中加入log可以打印申请该gpio序号的label
 

 
  1. int gpio_request(unsigned gpio, const char *label)

  2. {

  3. <span style="color:#ff0000;"> if (gpio == 128) {

  4. printk("gpio[%d] label = %s\n",label);

  5. } </span>

  6. return gpiod_request(gpio_to_desc(gpio), label);

  7. }

 

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值