gpio_request()简单分析

一、软件环境

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);
}



  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值