原文地址:
http://blog.csdn.net/maopig/article/details/7428561
其原型为
int gpio_request(unsigned gpio, const char *label) 先说说其参数,gpio则为你要申请的哪一个管脚,label则是为其取一个名字。其具体实现如下:
-
int gpio_request(unsigned gpio, const char *label)
-
{
-
struct gpio_desc *desc;//这个自己看源码
-
struct gpio_chip *chip;//这个自己看源码
-
int status = -EINVAL;
-
unsigned long flags;
-
spin_lock_irqsave(&gpio_lock, flags);//屏蔽中断
-
if (!gpio_is_valid(gpio))//判断是否有效,也就是参数的取值范围判断
-
goto done;
-
desc = &gpio_desc[gpio];
-
//这个是关键gpio_desc为定义的一个全局的数组变量,这个函数的实值也就是,
-
//用gpio_desc里面的一个变量来表示数组中的这个元素已经被申请了,而这个变量就是下面会看到的desc->flags。
-
chip = desc->chip;//按理说这个这个全局的gpio_desc如果没有初始化的话,这个chip就为空了,随后就直接返回-EINVAL了。
-
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的第FLAG_REQUESTED位,如果没有被申请就返回该位的原值0,分析到这儿,也差不多满足了我的个人要求。
-
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->base);
-
spin_lock_irqsave(&gpio_lock, flags);
-
if (status < 0) {
-
desc_set_label(desc, NULL);
-
module_put(chip->owner);
-
clear_bit(FLAG_REQUESTED, &desc->flags);
-
}
-
}
-
done:
-
if (status)
-
pr_debug("gpio_request: gpio-%d (%s) status %d\n",
-
gpio, label ? : "?", status);
-
spin_unlock_irqrestore(&gpio_lock, flags);
-
return status;
-
}
-
int gpio_request(unsigned gpio, const char *label)
-
{
-
struct gpio_desc *desc;//这个自己看源码
-
struct gpio_chip *chip;//这个自己看源码
-
int status = -EINVAL;
-
unsigned long flags;
-
spin_lock_irqsave(&gpio_lock, flags);//屏蔽中断
-
if (!gpio_is_valid(gpio))//判断是否有效,也就是参数的取值范围判断
-
goto done;
-
desc = &gpio_desc[gpio];
-
//这个是关键gpio_desc为定义的一个全局的数组变量,这个函数的实值也就是,
-
//用gpio_desc里面的一个变量来表示数组中的这个元素已经被申请了,而这个变量就是下面会看到的desc->flags。
-
chip = desc->chip;//按理说这个这个全局的gpio_desc如果没有初始化的话,这个chip就为空了,随后就直接返回-EINVAL了。
-
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的第FLAG_REQUESTED位,如果没有被申请就返回该位的原值0,分析到这儿,也差不多满足了我的个人要求。
-
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->base);
-
spin_lock_irqsave(&gpio_lock, flags);
-
if (status < 0) {
-
desc_set_label(desc, NULL);
-
module_put(chip->owner);
-
clear_bit(FLAG_REQUESTED, &desc->flags);
-
}
-
}
-
done:
-
if (status)
-
pr_debug("gpio_request: gpio-%d (%s) status %d\n",
-
gpio, label ? : "?", status);
-
spin_unlock_irqrestore(&gpio_lock, flags);
-
return status;
-
}
int gpio_request(unsigned gpio, const char *label) { struct gpio_desc *desc;//这个自己看源码 struct gpio_chip *chip;//这个自己看源码 int status = -EINVAL; unsigned long flags; spin_lock_irqsave(&gpio_lock, flags);//屏蔽中断 if (!gpio_is_valid(gpio))//判断是否有效,也就是参数的取值范围判断 goto done; desc = &gpio_desc[gpio]; //这个是关键gpio_desc为定义的一个全局的数组变量,这个函数的实值也就是, //用gpio_desc里面的一个变量来表示数组中的这个元素已经被申请了,而这个变量就是下面会看到的desc->flags。 chip = desc->chip;//按理说这个这个全局的gpio_desc如果没有初始化的话,这个chip就为空了,随后就直接返回-EINVAL了。 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的第FLAG_REQUESTED位,如果没有被申请就返回该位的原值0,分析到这儿,也差不多满足了我的个人要求。 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->base); spin_lock_irqsave(&gpio_lock, flags); if (status < 0) { desc_set_label(desc, NULL); module_put(chip->owner); clear_bit(FLAG_REQUESTED, &desc->flags); } } done: if (status) pr_debug("gpio_request: gpio-%d (%s) status %d\n", gpio, label ? : "?", status); spin_unlock_irqrestore(&gpio_lock, flags); return status; }
davinci 平台:
-
/*
-
* TI DaVinci GPIO Support
-
*
-
* Copyright (c) 2006 David Brownell
-
* Copyright (c) 2007, MontaVista Software, Inc.
-
*
-
* This program is free software; you can redistribute it and/or modify
-
* it under the terms of the GNU General Public License as published by
-
* the Free Software Foundation; either version 2 of the License, or
-
* (at your option) any later version.
-
*/
-
-
#include
-
#include
-
#include
-
#include
-
#include
-
#include
-
-
#include
-
#include
-
#include
-
-
#include
-
#include
-
#include
-
#include
-
-
#include
-
-
/*
-
该文件实现了gpio的各种应用功能和向内核注册gpio的中断例程等功能。
-
用户的驱动程序可调用gpio_request和gpio_free使用或释放该gpio,
-
可以调用gpio_direction_input和gpio_direction_output函数设置gpio输入输出方向,
-
调用gpio_get_value和gpio_set_value获取设置值。
-
*/
-
-
static DEFINE_SPINLOCK(gpio_lock);
-
-
/* 总共有DAVINCI_N_GPIO(71)个gpio引脚,故使用相应多的bit来记录这些引脚的使用状态 */
-
static DECLARE_BITMAP(gpio_in_use, DAVINCI_N_GPIO);
-
-
/*
-
申请一个gpio,其实就是检查该gpio是否空闲,如果空闲就可以使用并将该gpio相应的bit置位
-
(在gpio_in_use中)。
-
*/
-
int gpio_request(unsigned gpio, const char *tag)
-
{
-
if (gpio >= DAVINCI_N_GPIO)
-
return -EINVAL;
-
if (test_and_set_bit(gpio, gpio_in_use))
-
return -EBUSY;
-
return 0;
-
}
-
EXPORT_SYMBOL(gpio_request);
-
-
/*
-
释放一个gpio,其实就是清除gpio相应的控制bit位(在gpio_in_use中)。
-
*/
-
void gpio_free(unsigned gpio)
-
{
-
if (gpio >= DAVINCI_N_GPIO)
-
return;
-
clear_bit(gpio, gpio_in_use);
-
}
-
EXPORT_SYMBOL(gpio_free);
-
-
/* 获得gpio_controller结构体指针,gpio_controller结构体是gpio的核心控制单元,里面包含
-
gpio的设置和数据寄存器。该结构体和__gpio_to_controller函数在/include/asm-arm/
-
arch-davinci/gpio.h中定义,具体如下:
-
struct gpio_controller {
-
u32 dir;
-
u32 out_data;
-
u32 set_data;
-
u32 clr_data;
-
u32 in_data;
-
u32 set_rising;
-
u32 clr_rising;
-
u32 set_falling;
-
u32 clr_falling;
-
u32 intstat;
-
};
-
-
static inline struct gpio_controller *__iomem
-
__gpio_to_controller(unsigned gpio)
-
{
-
void *__iomem ptr;
-
if (gpio >= DAVINCI_N_GPIO)
-
return NULL;
-
-
if (gpio < 32)
-
ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x10);
-
else if (gpio < 64)
-
ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x38);
-
else if (gpio < 96)
-
ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x60);
-
else
-
ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x88);
-
return ptr;
-
}
-
由上面的定义和ti的SPRUE25.pdf手册可以看出,__gpio_to_controller函数返回的是
-
gpio_controller结构体到第一个成员dir的虚拟地址。获取了这个结构体指针后,
-
便可以控制相应的gpio了。dm644x共有71个gpio,
-
所以使用三个gpio_controller结构体控制,关于这个后面会由更详细的分析,
-
*/
-
/* create a non-inlined version */
-
static struct gpio_controller *__iomem gpio2controller(unsigned gpio)
-
{
-
return __gpio_to_controller(gpio);
-
}
-
-
/*
-
向某个gpio设置值,0或1。如果向gpio写1,则向set_data寄存器相应的位置1,如果写0,
-
则向clr_data寄存器相应的位置1.__gpio_mask函数在gpio.h中定义,定义如下,
-
static inline u32 __gpio_mask(unsigned gpio)
-
{
-
return 1 << (gpio % 32);
-
}
-
因为71个引脚由3个结构体控制,第一个控制前32个gpio,第二个控制次32个gpio,
-
最后一个控制剩余的7个gpio,故__gpio_mask函数的作用是找到在其相应控制结构体里的偏移数,
-
比如gpio34,那么其由第二个结构体控制,在这个机构体里的偏移是3(从0开始算,就是第二位)。
-
使用这个函数之前,必须确认该gpio设置成输出模式。
-
*/
-
/*
-
* Assuming the pin is muxed as a gpio output, set its output value.
-
*/
-
void __gpio_set(unsigned gpio, int value)
-
{
-
struct gpio_controller *__iomem g = gpio2controller(gpio);
-
// 设置gpio的值
-
__raw_writel(__gpio_mask(gpio), value ? &g->set_data : &g->clr_data);
-
}
-
EXPORT_SYMBOL(__gpio_set);
-
-
/*
-
通过读取in_data寄存器相应该gpio的位来读取gpio的值。
-
使用这个函数之前,必须确认该gpio设置成输入模式,否则获得到值不可预料。
-
*/
-
/*
-
* Read the pin's value (works even if it's set up as output);
-
* returns zero/nonzero.
-
阅读(1054) | 评论(0) | 转发(0) |