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
三、代码分析
-
int gpio_request(unsigned gpio, const char *label)
-
{
-
<span style="white-space:pre"> </span>return gpiod_request(gpio_to_desc(gpio), label);
-
}
-
EXPORT_SYMBOL_GPL(gpio_request);
(1)根据gpio序号获取相应的描述gpio的结构体desc
-
static struct gpio_desc *gpio_to_desc(unsigned gpio)
-
{ //<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>
-
if (WARN(!gpio_is_valid(gpio), "invalid GPIO %d\n", gpio))
-
return NULL;
-
else
-
return &gpio_desc[gpio];
-
}
(2)根据desc与label,调用gpiod_request注册gpio口
-
static int gpiod_request(struct gpio_desc *desc, const char *label)
-
{
-
struct gpio_chip *chip;
-
int status = -EPROBE_DEFER;
-
unsigned long flags;
-
if (!desc) {
-
pr_warn("%s: invalid GPIO\n", __func__);
-
return -EINVAL;
-
}
-
spin_lock_irqsave(&gpio_lock, flags);
-
chip = desc->chip;
-
if (chip == NULL)
-
goto done;
-
if (!try_module_get(chip->owner))
-
goto done;
-
/* NOTE: gpio_request() can be called in early boot,
-
* before IRQs are enabled, for non-sleeping (SOC) GPIOs.
-
*/
-
if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {//设置flags的第0位为1,并返回原来的值
-
desc_set_label(desc, label ? : "?");
-
status = 0;
-
} else {
-
status = -EBUSY;
-
module_put(chip->owner);
-
goto done;
-
}
-
if (chip->request) {
-
/* chip->request may sleep */
-
spin_unlock_irqrestore(&gpio_lock, flags);
-
status = chip->request(chip, gpio_chip_hwgpio(desc));
-
spin_lock_irqsave(&gpio_lock, flags);
-
if (status < 0) {
-
desc_set_label(desc, NULL);
-
module_put(chip->owner);
-
clear_bit(FLAG_REQUESTED, &desc->flags);
-
goto done;
-
}
-
}
-
if (chip->get_direction) {
-
/* chip->get_direction may sleep */
-
spin_unlock_irqrestore(&gpio_lock, flags);
-
gpiod_get_direction(desc);
-
spin_lock_irqsave(&gpio_lock, flags);
-
}
-
done:
-
if (status)
-
pr_debug("_gpio_request: gpio-%d (%s) status %d\n",
-
desc_to_gpio(desc), label ? : "?", status);
-
spin_unlock_irqrestore(&gpio_lock, flags);
-
return status;
-
}
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;
因此,在写驱动代码时如下判错是错误的!
-
ret = gpio_request(RST_PORT, "GSL_RST");
-
if (ret) { //错误的写法,判错条件应为ret < 0
-
printk( "ret = %d : could not req gpio reset\n", ret);
-
}
三、当gpio被其他模块占用时怎么快速定位
根据gpio序号,在注册的函数中加入log可以打印申请该gpio序号的label
-
int gpio_request(unsigned gpio, const char *label)
-
{
-
<span style="color:#ff0000;"> if (gpio == 128) {
-
printk("gpio[%d] label = %s\n",label);
-
} </span>
-
return gpiod_request(gpio_to_desc(gpio), label);
-
}