一.相关结构体
1.gpio_chip代表一个芯片的一个gpio bank
struct gpio_chip { //gpio bank
const char *label; //bank名
struct device *dev; //设备文件
struct module *owner; //模块所有者
int (*request)(struct gpio_chip *chip,unsigned offset);
void (*free)(struct gpio_chip *chip,unsigned offset);
int (*direction_input)(struct gpio_chip *chip,unsigned offset); //配置gpio为输入
int (*get)(struct gpio_chip *chip,unsigned offset); //获取值
int (*direction_output)(struct gpio_chip *chip,unsigned offset, int value); //配置gpio为输出
int (*direction_output_array)(struct gpio_chip*chip, unsigned value, unsigned mask);
int (*set_debounce)(struct gpio_chip *chip,unsigned offset, unsigned debounce); //去抖动时间
void (*set)(struct gpio_chip *chip,unsigned offset, int value); //设置gpio值
int (*to_irq)(struct gpio_chip *chip,unsigned offset); //中断
void (*dbg_show)(struct seq_file *s,struct gpio_chip *chip);
int base; //gpio基数
u16 ngpio; //gpio个数
const char *const *names;
unsigned can_sleep:1; //能否睡眠
unsigned exported:1;
#if defined(CONFIG_OF_GPIO)
struct device_node *of_node;
int of_gpio_n_cells;
int (*of_xlate)(struct gpio_chip *gc, struct device_node *np,const void *gpio_spec, u32 *flags);
#endif
};
2.gpio_desc 代表一个gpio口
struct gpio_desc { //GPIO描述符
struct gpio_chip *chip; //所属gpio_chip
unsigned long flags; //gpio标志
#ifdef CONFIG_DEBUG_FS
const char *label;
#endif
};
2.1 gpio_desc flags标志
#define FLAG_REQUESTED 0 //已请求资源
#define FLAG_IS_OUT 1 //输出io
#define FLAG_RESERVED 2 //保留
#define FLAG_EXPORT 3 /* protected by sysfs_lock */
#define FLAG_SYSFS 4 /* exported via /sys/class/gpio/control */
#define FLAG_TRIG_FALL 5 /* trigger on falling edge */
#define FLAG_TRIG_RISE 6 /* trigger on rising edge */
#define FLAG_ACTIVE_LOW 7 /* sysfs value has active low */
2.2 全局gpio_desc数组
static struct gpio_desc gpio_desc[ARCH_NR_GPIOS];
3.gpio类
static struct class gpio_class = {
.name = "gpio",
.owner = THIS_MODULE,
.class_attrs = gpio_class_attrs,
};
二.api接口
int gpiochip_add(struct gpio_chip *chip) //添加初始化gpio_chip管理的gpio_desc
int gpiochip_remove(struct gpio_chip *chip) //清空gpio_chip管理的全局gpio_desc数组项
struct gpio_chip *gpiochip_find(void *data,int (*match)(struct gpio_chip *chip, void *data)) //查找获取gpio_chip
int gpio_request(unsigned gpio, const char *label) //请求gpio资源
void gpio_free(unsigned gpio) //释放gpio资源
int gpio_set_debounce(unsigned gpio, unsigned debounce) //设置去抖动时间
int gpio_direction_input(unsigned gpio) //设置gpio为输入io
int gpio_direction_output(unsigned gpio, int value) //设置gpio为输出io
int gpio_cansleep(unsigned gpio) //判断gpio可否睡眠
int gpio_get_value_cansleep(unsigned gpio) //获取gpio值(gpio可睡眠)
void gpio_set_value_cansleep(unsigned gpio, int value) //设置gpio值(gpio可睡眠)
int gpio_get_value(unsigned gpio) //获取gpio值(gpio不可睡眠)
int gpio_request_one(unsigned gpio, unsigned long flags, const char *label) //请求一个gpio资源
int gpio_request_array(struct gpio *array, size_t num) //请求一组gpio资源
void gpio_free_array(struct gpio *array, size_t num) //释放一组gpio资源
int gpio_to_irq(unsigned gpio) //根据gpio号获取对应的中断号
int gpio_export(unsigned gpio, bool direction_may_change) //gpio创建用户接口
void gpio_unexport(unsigned gpio) //gpio移除用户接口
三.api及调用到的相关函数解析
1.设置gpio_chip管理的全局gpio_desc数组项
int gpiochip_add(struct gpio_chip *chip)
{
unsigned long flags;
int status = 0;
unsigned id;
int base = chip->base; //获取gpio_chip基数
//验证gpio的基数,gpio的最后一个io的编号正确性
if ((!gpio_is_valid(base) || !gpio_is_valid(base + chip->ngpio - 1))&& base >= 0) {
status = -EINVAL;
goto fail;
}
spin_lock_irqsave(&gpio_lock, flags); //上自旋锁
if (base < 0) { //若gpio的基数小于0
base = gpiochip_find_base(chip->ngpio); //根据gpio个数分配新的基数
if (base < 0) {
status = base;
goto unlock;
}
chip->base = base; //设置新的基数
}
for (id = base; id < base + chip->ngpio; id++) {
if (gpio_desc[id].chip != NULL) { //判断gpio_desc是否给其他gpio_chip管理
status = -EBUSY;
break;
}
}
if (status == 0) {
for (id = base; id < base + chip->ngpio; id++) { //填充对应的全局gpio_desc数组项
gpio_desc[id].chip = chip; //gpio_chip
gpio_desc[id].flags = !chip->direction_input?(1 << FLAG_IS_OUT):0; //设置输入输出标志位
}
}
of_gpiochip_add(chip);
unlock:
spin_unlock_irqrestore(&gpio_lock, flags); //解自旋锁
if (status)
goto fail;
status = gpiochip_export(chip); //gpio_chip创建用户接口
if (status)
goto fail;
return 0;
fail:
pr_err("gpiochip_add: gpios %d..%d (%s) failed to register\n",chip->base,chip->base+chip->ngpio-1,chip->label?:"generic");
return status;
}
EXPORT_SYMBOL_GPL(gpiochip_add);
2.清空gpio_chip管理的全局gpio_desc数组项
int gpiochip_remove(struct gpio_chip *chip)
{
unsigned long flags;
int status = 0;
unsigned id;
spin_lock_irqsave(&gpio_lock, flags); //上自旋锁
of_gpiochip_remove(chip);
for (id = chip->base; id < chip->base + chip->ngpio; id++) { //查找对应全局gpio_desc数组项
if (test_bit(FLAG_REQUESTED, &gpio_desc[id].flags)) { //判断是否存在标志含FLAG_REQUESTED的gpio口
status = -EBUSY;
break;
}
}
if (status == 0) {
for (id = chip->base; id < chip->base + chip->ngpio; id++) //清空对应全局gpio_desc数组项
gpio_desc[id].chip = NULL;
}
spin_unlock_irqrestore(&gpio_lock, flags); //解自旋锁
if (status == 0)
gpiochip_unexport(chip); //gpio_chip移除用户接口
return status;
}
EXPORT_SYMBOL_GPL(gpiochip_remove);
3.查找获取gpio_chip
struct gpio_chip *gpiochip_find(void *data,int (*match)(struct gpio_chip *chip, void *data))
{
struct gpio_chip *chip = NULL;
unsigned long flags;
int i;
spin_lock_irqsave(&gpio_lock, flags); //上自旋锁
for (i = 0; i < ARCH_NR_GPIOS; i++) { //遍历整个全局gpio_desc数组
if (!gpio_desc[i].chip) //若没被某个gpio_chip管理,则跳过继续
continue;
if (match(gpio_desc[i].chip, data)) { //调用传递进来的匹配函数
chip = gpio_desc[i].chip; //匹配则获取其gpio_chip
break;
}
}
spin_unlock_irqrestore(&gpio_lock, flags); //解自旋锁
return chip; //返回查找到的gpio_chip指针
}
4.验证gpio号是否正确
static inline int gpio_is_valid(int number)
{
return ((unsigned)number) < ARCH_NR_GPIOS;
}
5.请求gpio资源
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)) //验证gpio号是否正确
goto done;
desc = &gpio_desc[gpio]; //获取gpio描述符
chip = desc->chip; //获取gpio_chip
if (chip == NULL) //获取gpio_chip失败
goto done;
if (!try_module_get(chip->owner)) //增加模块引用计数
goto done;
if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) { //测试并设置gpio_desc的FLAG_REQUESTED标志
desc_set_label(desc, label ? : "?"); //设置gpio_desc的label
status = 0;
}
else {
status = -EBUSY;
module_put(chip->owner); //减少模块引用计数
goto done;
}
if (chip->request) { //gpio_chip存在request方法
spin_unlock_irqrestore(&gpio_lock, flags); //解自旋锁
status = chip->request(chip, gpio - chip->base); //调用gpio_chip的request方法
spin_lock_irqsave(&gpio_lock, flags); //上自旋锁
if (status < 0) {
desc_set_label(desc, NULL); //清除gpio_desc的label
module_put(chip->owner); //减少模块引用计数
clear_bit(FLAG_REQUESTED, &desc->flags); //清除gpio_chip的FLAG_REQUESTED标志
}
}
done:
if (status)
pr_debug("gpio_request: gpio-%d (%s) status %d\n",gpio, label ? : "?", status);
spin_unlock_irqrestore(&gpio_lock, flags); //解自旋锁
return status;
}
EXPORT_SYMBOL_GPL(gpio_request);
6.释放gpio资源
void gpio_free(unsigned gpio)
{
unsigned long flags;
struct gpio_desc *desc;
struct gpio_chip *chip;
might_sleep();
if (!gpio_is_valid(gpio)) { //验证gpio号
WARN_ON(extra_checks);
return;
}
gpio_unexport(gpio); //gpio移除用户接口
spin_lock_irqsave(&gpio_lock, flags); //上自旋锁
desc = &gpio_desc[gpio]; //获取gpio_desc
chip = desc->chip; //获取gpio_chip
if (chip && test_bit(FLAG_REQUESTED, &desc->flags)) { //测试gpio_desc的FLAG_REQUESTED标志
if (chip->free) { //gpio_chip存在free方法
spin_unlock_irqrestore(&gpio_lock, flags); //上自旋锁
might_sleep_if(chip->can_sleep);
chip->free(chip, gpio - chip->base); //调用gpio_chip的free方法
spin_lock_irqsave(&gpio_lock, flags); //解自旋锁
}
desc_set_label(desc, NULL); //清除gpio_desc的label信息
module_put(desc->chip->owner); //减少模块引用计数
clear_bit(FLAG_ACTIVE_LOW, &desc->flags); //清除FLAG_ACTIVE_LOW的标志
clear_bit(FLAG_REQUESTED, &desc->flags); //清除FLAG_REQUESTED的标志
}
else
WARN_ON(extra_checks);
spin_unlock_irqrestore(&gpio_lock, flags); //解自旋锁
}
EXPORT_SYMBOL_GPL(gpio_free);
7.设置去抖动时间
int gpio_set_debounce(unsigned gpio, unsigned debounce)
{
unsigned long flags;
struct gpio_chip *chip;
struct gpio_desc *desc = &gpio_desc[gpio]; //获取gpio_desc项
int status = -EINVAL;
spin_lock_irqsave(&gpio_lock, flags); //上自旋锁
if (!gpio_is_valid(gpio)) //验证gpio号
goto fail;
chip = desc->chip; //获取gpio_chip
if (!chip || !chip->set || !chip->set_debounce) //判断gpio_chip是否存在且是否存在set和set_debounce方法
goto fail;
gpio -= chip->base; //计算gpio在该gpio_chip的偏移量
if (gpio >= chip->ngpio) //超过该gpio_chip的gpio数范围
goto fail;
status = gpio_ensure_requested(desc, gpio); //确保gpio是request请求过了的
if (status < 0)
goto fail;
/* now we know the gpio is valid and chip won't vanish */
spin_unlock_irqrestore(&gpio_lock, flags); //解自旋锁
might_sleep_if(chip->can_sleep);
return chip->set_debounce(chip, gpio, debounce); //调用gpio_chip的set_debounce方法
fail:
spin_unlock_irqrestore(&gpio_lock, flags); //解自旋锁
if (status)
pr_debug("%s: gpio-%d status %d\n",__func__, gpio, status);
return status;
}
EXPORT_SYMBOL_GPL(gpio_set_debounce);
8.设置gpio为输入io
int gpio_direction_input(unsigned gpio)
{
unsigned long flags;
struct gpio_chip *chip;
struct gpio_desc *desc = &gpio_desc[gpio]; //获取gpio_desc项
int status = -EINVAL;
spin_lock_irqsave(&gpio_lock, flags); //上自旋锁
if (!gpio_is_valid(gpio))
goto fail;
chip = desc->chip; //获取gpio_chip
if (!chip || !chip->get || !chip->direction_input) //判断gpio_chip是否存在且存在get和directon_input方法
goto fail;
gpio -= chip->base; //计算gpio在该gpio_chip的偏移量
if (gpio >= chip->ngpio) //超过该gpio_chip的gpio数范围
goto fail;
status = gpio_ensure_requested(desc, gpio); //确保gpio是request请求过了的
if (status < 0)
goto fail;
/* now we know the gpio is valid and chip won't vanish */
spin_unlock_irqrestore(&gpio_lock, flags); //解自旋锁
might_sleep_if(chip->can_sleep);
if (status) {
status = chip->request(chip, gpio); //调用chip_gpio的request方法
if (status < 0) {
pr_debug("GPIO-%d: chip request fail, %d\n",chip->base + gpio, status);
goto lose;
}
}
status = chip->direction_input(chip, gpio); //调用chip_gpio的direction_input方法
if (status == 0)
clear_bit(FLAG_IS_OUT, &desc->flags);
lose:
return status;
fail:
spin_unlock_irqrestore(&gpio_lock, flags); //解自旋锁
if (status)
pr_debug("%s: gpio-%d status %d\n",__func__, gpio, status);
return status;
}
EXPORT_SYMBOL_GPL(gpio_direction_input);
9.设备gpio为输出io
int gpio_direction_output(unsigned gpio, int value)
{
unsigned long flags;
struct gpio_chip *chip;
struct gpio_desc *desc = &gpio_desc[gpio]; //获取gpio_desc项
int status = -EINVAL;
spin_lock_irqsave(&gpio_lock, flags); //上自旋锁
if (!gpio_is_valid(gpio))
goto fail;
chip = desc->chip; //获取gpio_chip
if (!chip || !chip->set || !chip->direction_output) //判断gpio_chip是否存在且存在set和direction_output方法
goto fail;
gpio -= chip->base; //计算gpio在该gpio_chip的偏移量
if (gpio >= chip->ngpio) //超过该gpio_chip的gpio数范围
goto fail;
status = gpio_ensure_requested(desc, gpio); //确保gpio是request请求过了的
if (status < 0)
goto fail;
spin_unlock_irqrestore(&gpio_lock, flags); //解自旋锁
might_sleep_if(chip->can_sleep);
if (status) {
status = chip->request(chip, gpio); //调用gpio_chip的request方法
if (status < 0) {
pr_debug("GPIO-%d: chip request fail, %d\n",chip->base + gpio, status);
goto lose;
}
}
status = chip->direction_output(chip, gpio, value); //调用gpio_chip的direction_output方法
if (status == 0)
set_bit(FLAG_IS_OUT, &desc->flags);
lose:
return status;
fail:
spin_unlock_irqrestore(&gpio_lock, flags); //解自旋锁
if (status)
pr_debug("%s: gpio-%d status %d\n",__func__, gpio, status);
return status;
}
EXPORT_SYMBOL_GPL(gpio_direction_output);
10.判断gpio可否睡眠
#define gpio_cansleep __gpio_cansleep
int __gpio_cansleep(unsigned gpio)
{
struct gpio_chip *chip;
chip = gpio_to_chip(gpio); //获取gpio_chip
return chip->can_sleep; //调用gpio_chip的can_sleep方法
}
EXPORT_SYMBOL_GPL(__gpio_cansleep);
11.获取gpio值(gpio可睡眠)
int gpio_get_value_cansleep(unsigned gpio)
{
struct gpio_chip *chip;
might_sleep_if(extra_checks);
chip = gpio_to_chip(gpio); //获取gpio_chip
return chip->get ? chip->get(chip, gpio - chip->base) : 0; //若存在gpio_chip的get方法则调用该方法
}
EXPORT_SYMBOL_GPL(gpio_get_value_cansleep);
12.设置gpio值(gpio可睡眠)
void gpio_set_value_cansleep(unsigned gpio, int value)
{
struct gpio_chip *chip;
might_sleep_if(extra_checks);
chip = gpio_to_chip(gpio); //获取gpio_chip
chip->set(chip, gpio - chip->base, value); //调用gpio_chip的set方法
}
EXPORT_SYMBOL_GPL(gpio_set_value_cansleep);
13.获取gpio值(gpio不可睡眠)
#define gpio_get_value __gpio_get_value
int __gpio_get_value(unsigned gpio)
{
struct gpio_chip *chip;
chip = gpio_to_chip(gpio); //获取gpio_chip
WARN_ON(chip->can_sleep);
return chip->get ? chip->get(chip, gpio - chip->base) : 0; //若存在gpio_chip的get方法则调用该方法
}
EXPORT_SYMBOL_GPL(__gpio_get_value);
14.设置gpio值(gpio不可睡眠)
#define gpio_set_value __gpio_set_value
void __gpio_set_value(unsigned gpio, int value)
{
struct gpio_chip *chip;
chip = gpio_to_chip(gpio); //获取gpio_chip
WARN_ON(chip->can_sleep);
chip->set(chip, gpio - chip->base, value); //调用gpio_chip的set方法
}
EXPORT_SYMBOL_GPL(__gpio_set_value);
15.请求一个gpio资源
int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
{
int err;
err = gpio_request(gpio, label); //请求gpio资源
if (err)
return err;
if (flags & GPIOF_DIR_IN) //输入gpio
err = gpio_direction_input(gpio); //设置gpio为输入
else //输出gpio
err = gpio_direction_output(gpio,(flags & GPIOF_INIT_HIGH) ? 1 : 0); //设置gpio为输出
if (err) //出错
gpio_free(gpio); //释放gpio资源
return err;
}
EXPORT_SYMBOL_GPL(gpio_request_one);
16.请求一组gpio资源
int gpio_request_array(struct gpio *array, size_t num)
{
int i, err;
for (i = 0; i < num; i++, array++) { //批量请求gpio资源
err = gpio_request_one(array->gpio, array->flags, array->label);
if (err)
goto err_free;
}
return 0;
err_free:
while (i--)
gpio_free((--array)->gpio); //释放gpio资源
return err;
}
EXPORT_SYMBOL_GPL(gpio_request_array);
17.释放一组gpio资源
void gpio_free_array(struct gpio *array, size_t num)
{
while (num--)
gpio_free((array++)->gpio); //批量是否gpio资源
}
EXPORT_SYMBOL_GPL(gpio_free_array);
18.根据gpio号获取对应的中断号
int __gpio_to_irq(unsigned gpio)
{
struct gpio_chip *chip;
chip = gpio_to_chip(gpio); //获取gpio_chip
return chip->to_irq?chip->to_irq(chip,gpio-chip->base):-ENXIO; //若gpio_chip的to_irq方法存在则调用其方法
}
EXPORT_SYMBOL_GPL(__gpio_to_irq);
19.gpio_chip创建用户接口
static int gpiochip_export(struct gpio_chip *chip)
{
int status;
struct device *dev;
if (!gpio_class.p)
return 0;
mutex_lock(&sysfs_lock); //上互斥锁
dev = device_create(&gpio_class, chip->dev, MKDEV(0, 0), chip,"gpiochip%d", chip->base); //创建设备
if (!IS_ERR(dev)) {
status = sysfs_create_group(&dev->kobj,&gpiochip_attr_group);
}
else
status = PTR_ERR(dev);
chip->exported = (status == 0); //设置gpio_chip的exported标志
mutex_unlock(&sysfs_lock); //解互斥锁
if (status) {
unsigned long flags;
unsigned gpio;
spin_lock_irqsave(&gpio_lock, flags); //上自旋锁
gpio = chip->base; //获取gpio_chip的基数
while (gpio_desc[gpio].chip == chip) //遍历该gpio_chip管理的所有gpio_desc
gpio_desc[gpio++].chip = NULL; //清除该gpio_desc的chip成员
spin_unlock_irqrestore(&gpio_lock, flags); //解自旋锁
pr_debug("%s: chip %s status %d\n", __func__,chip->label, status);
}
return status;
}
20.gpio_chip移除用户接口
static void gpiochip_unexport(struct gpio_chip *chip)
{
int status;
struct device *dev;
mutex_lock(&sysfs_lock); //上互斥锁
dev = class_find_device(&gpio_class, NULL, chip, match_export); //找到export的gpio_chip的设备文件
if (dev) {
put_device(dev); //减少引用计数
device_unregister(dev); //注销设备文件
chip->exported = 0; //清除export标志
status = 0; //设置status
}
else
status = -ENODEV;
mutex_unlock(&sysfs_lock); //解互斥锁
if (status)
pr_debug("%s: chip %s status %d\n", __func__,chip->label, status);
}
21.gpio创建用户接口
int gpio_export(unsigned gpio, bool direction_may_change)
{
unsigned long flags;
struct gpio_desc *desc;
int status = -EINVAL;
const char *ioname = NULL;
if (!gpio_class.p) {
pr_debug("%s: called too early!\n", __func__);
return -ENOENT;
}
if (!gpio_is_valid(gpio)) //验证gpio号的正确性
goto done;
mutex_lock(&sysfs_lock); //上互斥锁
spin_lock_irqsave(&gpio_lock, flags); //上自旋锁
desc = &gpio_desc[gpio]; //获取gpio_desc数组项
if (test_bit(FLAG_REQUESTED, &desc->flags)&& !test_bit(FLAG_EXPORT, &desc->flags)) { //已请求但没export
status = 0;
if (!desc->chip->direction_input|| !desc->chip->direction_output) //gpio_chip不存在direction_input和direction_output方法
direction_may_change = false; //那么gpio的方向不可能会改变
}
spin_unlock_irqrestore(&gpio_lock, flags); //解自旋锁
if (desc->chip->names && desc->chip->names[gpio - desc->chip->base]) //gpio_chip存在名字数组且存在对应数组项的名字
ioname = desc->chip->names[gpio - desc->chip->base]; //设置gpio名
if (status == 0) {
struct device *dev;
dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),desc, ioname ? ioname : "gpio%u", gpio); //创建设备文件
if (!IS_ERR(dev)) {
status = sysfs_create_group(&dev->kobj,&gpio_attr_group); //创建属性
if (!status && direction_may_change) //gpio方向可能会改变
status = device_create_file(dev,&dev_attr_direction); //则创建跟方向相关的属性
if (!status && gpio_to_irq(gpio) >= 0&& (direction_may_change|| !test_bit(FLAG_IS_OUT,&desc->flags))) //可设置中断的引荐
status = device_create_file(dev,&dev_attr_edge); //则创建跟中断触发相关的属性
if (status != 0)
device_unregister(dev); //注销设备
}
else
status = PTR_ERR(dev);
if (status == 0)
set_bit(FLAG_EXPORT, &desc->flags); //设置export标志
}
mutex_unlock(&sysfs_lock); //解互斥锁
done:
if (status)
pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
return status;
}
EXPORT_SYMBOL_GPL(gpio_export);
22.gpio移除用户接口
void gpio_unexport(unsigned gpio)
{
struct gpio_desc *desc;
int status = 0;
if (!gpio_is_valid(gpio)) { //验证gpio号的正确性
status = -EINVAL;
goto done;
}
mutex_lock(&sysfs_lock); //上锁互斥锁
desc = &gpio_desc[gpio]; //获取gpio_desc
if (test_bit(FLAG_EXPORT, &desc->flags)) { //判断是否export
struct device *dev = NULL;
dev = class_find_device(&gpio_class, NULL, desc, match_export); //获取设备文件
if (dev) {
gpio_setup_irq(desc, dev, 0); //中断gpio的处理
clear_bit(FLAG_EXPORT, &desc->flags); //清除export标志
put_device(dev); //增加dev引用计数
device_unregister(dev); //注销设备
}
else
status = -ENODEV;
}
mutex_unlock(&sysfs_lock); //解锁互斥锁
done:
if (status)
pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
}
EXPORT_SYMBOL_GPL(gpio_unexport);
23.中断gpio处理
static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,unsigned long gpio_flags)
{
struct sysfs_dirent *value_sd;
unsigned long irq_flags;
int ret, irq, id;
if ((desc->flags & GPIO_TRIGGER_MASK) == gpio_flags) //有FLAG_TRIG_FALL或FLAG_TRIG_RISE标志
return 0;
irq = gpio_to_irq(desc - gpio_desc); //根据gpio获取对应的中断号
if (irq < 0)
return -EIO;
id = desc->flags >> ID_SHIFT; //#define ID_SHIFT 16
value_sd = idr_find(&dirent_idr, id); //获取设备id
if (value_sd) //获取设备id成功,说明是申请过gpio中断的了
free_irq(irq, value_sd); //释放中断
desc->flags &= ~GPIO_TRIGGER_MASK; //屏蔽gpio_desc标志位FLAG_TRIG_FALL或FLAG_TRIG_RISE
if (!gpio_flags) { //gpio_unexport中的gpio_setup_irq跑到这里返回
ret = 0;
goto free_id;
}
irq_flags = IRQF_SHARED; //设置为共享中断类型
if (test_bit(FLAG_TRIG_FALL, &gpio_flags)) //FLAG_TRIG_FALL 下降沿触发
irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
if (test_bit(FLAG_TRIG_RISE, &gpio_flags)) //FLAG_TRIG_RISE 上升沿触发
irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
if (!value_sd) { //获取设备id不成功
value_sd = sysfs_get_dirent(dev->kobj.sd, NULL, "value"); //获取设备id
if (!value_sd) {
ret = -ENODEV;
goto err_out;
}
do {
ret = -ENOMEM;
if (idr_pre_get(&dirent_idr, GFP_KERNEL))
ret = idr_get_new_above(&dirent_idr, value_sd,1, &id);
} while (ret == -EAGAIN);//id机制中获取新的id该id指向value_sd
if (ret)
goto free_sd;
desc->flags &= GPIO_FLAGS_MASK; //设置gpio_desc标志
desc->flags |= (unsigned long)id << ID_SHIFT; //或上idr机制获取的id
if (desc->flags >> ID_SHIFT != id) { //验证下是否id存放正确
ret = -ERANGE;
goto free_id;
}
}
ret = request_any_context_irq(irq, gpio_sysfs_irq, irq_flags,"gpiolib", value_sd); //申请中断
if (ret < 0)
goto free_id;
desc->flags |= gpio_flags; //gpio_desc设置传递进来的标志
return 0;
free_id:
idr_remove(&dirent_idr, id);
desc->flags &= GPIO_FLAGS_MASK;
free_sd:
if (value_sd)
sysfs_put(value_sd);
err_out:
return ret;
}
四.sysfs的初始化
static int __init gpiolib_sysfs_init(void)
{
int status;
unsigned long flags;
unsigned gpio;
status = class_register(&gpio_class); //注册gpio_class
if (status < 0)
return status;
spin_lock_irqsave(&gpio_lock, flags);
for (gpio = 0; gpio < ARCH_NR_GPIOS; gpio++) { //遍历全局gpio_desc数组
struct gpio_chip *chip;
chip = gpio_desc[gpio].chip; //获取数组项的gpio_chip
if (!chip || chip->exported) //gpio_chip为空或已经exported了
continue;
spin_unlock_irqrestore(&gpio_lock, flags); //上自旋锁
status = gpiochip_export(chip); //exported该项
spin_lock_irqsave(&gpio_lock, flags); //解自旋锁
}
spin_unlock_irqrestore(&gpio_lock, flags);
return status;
}
postcore_initcall(gpiolib_sysfs_init);