一.相关结构体
1.gpio_chip代表一个芯片的一个gpio bank
2.gpio_desc 代表一个gpio口
2.1 gpio_desc flags标志
2.2 全局gpio_desc数组
3.gpio类
二.api接口
三.api及调用到的相关函数解析
1.设置gpio_chip管理的全局gpio_desc数组项
2.清空gpio_chip管理的全局gpio_desc数组项
3.查找获取gpio_chip
4.验证gpio号是否正确
5.请求gpio资源
6.释放gpio资源
7.设置去抖动时间
8.设置gpio为输入io
9.设备gpio为输出io
10.判断gpio可否睡眠
11.获取gpio值(gpio可睡眠)
12.设置gpio值(gpio可睡眠)
13.获取gpio值(gpio不可睡眠)
14.设置gpio值(gpio不可睡眠)
15.请求一个gpio资源
16.请求一组gpio资源
17.释放一组gpio资源
18.根据gpio号获取对应的中断号
19.gpio_chip创建用户接口
20.gpio_chip移除用户接口
21.gpio创建用户接口
22.gpio移除用户接口
23.中断gpio处理
四.sysfs的初始化
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);