一.相关结构体
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);