linux gpio接口

一.相關結構體 
1.gpio_chip代表一個芯片的一個gpio bank
  1. struct gpio_chip {  //gpio bank  
  2.     const char  *label;     //bank名  
  3.     struct device   *dev;   //設備文件  
  4.     struct module   *owner; //模塊所有者  
  5.     int     (*request)(struct gpio_chip *chip,unsigned offset);  
  6.     void    (*free)(struct gpio_chip *chip,unsigned offset);  
  7.     int     (*direction_input)(struct gpio_chip *chip,unsigned offset); //配置gpio爲輸入  
  8.     int     (*get)(struct gpio_chip *chip,unsigned offset); //獲取值  
  9.     int     (*direction_output)(struct gpio_chip *chip,unsigned offset, int value); //配置gpio爲輸出  
  10.     int     (*direction_output_array)(struct gpio_chip*chip, unsigned value, unsigned mask);  
  11.     int     (*set_debounce)(struct gpio_chip *chip,unsigned offset, unsigned debounce); //去抖動時間  
  12.     void    (*set)(struct gpio_chip *chip,unsigned offset, int value);  //設置gpio值  
  13.     int     (*to_irq)(struct gpio_chip *chip,unsigned offset);  //中斷  
  14.     void    (*dbg_show)(struct seq_file *s,struct gpio_chip *chip);  
  15.     int base;   //gpio基數  
  16.     u16 ngpio;  //gpio個數  
  17.     const char  *const *names;  
  18.     unsigned    can_sleep:1;    //能否睡眠  
  19.     unsigned    exported:1;  
  20. #if defined(CONFIG_OF_GPIO)  
  21.     struct device_node *of_node;  
  22.     int of_gpio_n_cells;  
  23.     int (*of_xlate)(struct gpio_chip *gc, struct device_node *np,const void *gpio_spec, u32 *flags);  
  24. #endif  
  25. };  

2.gpio_desc 代表一個gpio口
  1. struct gpio_desc {  //GPIO描述符   
  2.     struct gpio_chip    *chip;  //所屬gpio_chip  
  3.     unsigned long   flags;      //gpio標誌  
  4. #ifdef CONFIG_DEBUG_FS  
  5.     const char  *label;  
  6. #endif  
  7. };  

2.1 gpio_desc flags標誌
  1. #define FLAG_REQUESTED  0   //已請求資源  
  2. #define FLAG_IS_OUT 1   //輸出io  
  3. #define FLAG_RESERVED   2   //保留  
  4. #define FLAG_EXPORT 3   /* protected by sysfs_lock */  
  5. #define FLAG_SYSFS      4   /* exported via /sys/class/gpio/control */  
  6. #define FLAG_TRIG_FALL  5   /* trigger on falling edge */  
  7. #define FLAG_TRIG_RISE  6   /* trigger on rising edge */  
  8. #define FLAG_ACTIVE_LOW 7   /* sysfs value has active low */  

2.2 全局gpio_desc數組
  1. static struct gpio_desc gpio_desc[ARCH_NR_GPIOS];  

3.gpio類
  1. static struct class gpio_class = {  
  2.     .name =     "gpio",  
  3.     .owner =    THIS_MODULE,  
  4.     .class_attrs =  gpio_class_attrs,  
  5. };  

二.api接口
  1. int gpiochip_add(struct gpio_chip *chip)                //添加初始化gpio_chip管理的gpio_desc  
  2. int gpiochip_remove(struct gpio_chip *chip)             //清空gpio_chip管理的全局gpio_desc數組項  
  3. struct gpio_chip *gpiochip_find(void *data,int (*match)(struct gpio_chip *chip, void *data))    //查找獲取gpio_chip  
  4.   
  5. int gpio_request(unsigned gpio, const char *label)      //請求gpio資源  
  6. void gpio_free(unsigned gpio)                           //釋放gpio資源  
  7.   
  8. int gpio_set_debounce(unsigned gpio, unsigned debounce) //設置去抖動時間  
  9. int gpio_direction_input(unsigned gpio)                 //設置gpio爲輸入io  
  10. int gpio_direction_output(unsigned gpio, int value)     //設置gpio爲輸出io  
  11.   
  12. int gpio_cansleep(unsigned gpio)                        //判斷gpio可否睡眠  
  13. int gpio_get_value_cansleep(unsigned gpio)              //獲取gpio值(gpio可睡眠)  
  14. void gpio_set_value_cansleep(unsigned gpio, int value)  //設置gpio值(gpio可睡眠)  
  15. int gpio_get_value(unsigned gpio)                       //獲取gpio值(gpio不可睡眠)  
  16.   
  17. int gpio_request_one(unsigned gpio, unsigned long flags, const char *label) //請求一個gpio資源  
  18. int gpio_request_array(struct gpio *array, size_t num)  //請求一組gpio資源  
  19. void gpio_free_array(struct gpio *array, size_t num)    //釋放一組gpio資源  
  20.   
  21. int gpio_to_irq(unsigned gpio)                          //根據gpio號獲取對應的中斷號  
  22.   
  23. int gpio_export(unsigned gpio, bool direction_may_change)   //gpio創建用戶接口  
  24. void gpio_unexport(unsigned gpio)                       //gpio移除用戶接口  

三.api及調用到的相關函數解析 
1.設置gpio_chip管理的全局gpio_desc數組項
  1. int gpiochip_add(struct gpio_chip *chip)  
  2. {  
  3.     unsigned long   flags;  
  4.     int status = 0;  
  5.     unsigned    id;  
  6.     int base = chip->base;   //獲取gpio_chip基數  
  7.     //驗證gpio的基數,gpio的最後一個io的編號正確性  
  8.     if ((!gpio_is_valid(base) || !gpio_is_valid(base + chip->ngpio - 1))&& base >= 0) {     
  9.         status = -EINVAL;  
  10.         goto fail;  
  11.     }  
  12.     spin_lock_irqsave(&gpio_lock, flags);   //上自旋鎖  
  13.     if (base < 0) {  //若gpio的基數小於0  
  14.         base = gpiochip_find_base(chip->ngpio);  //根據gpio個數分配新的基數  
  15.         if (base < 0) {  
  16.             status = base;  
  17.             goto unlock;  
  18.         }  
  19.         chip->base = base;   //設置新的基數  
  20.     }  
  21.     for (id = base; id < base + chip->ngpio; id++) {  
  22.         if (gpio_desc[id].chip != NULL) {   //判斷gpio_desc是否給其他gpio_chip管理  
  23.             status = -EBUSY;  
  24.             break;  
  25.         }  
  26.     }  
  27.     if (status == 0) {  
  28.         for (id = base; id < base + chip->ngpio; id++) {  //填充對應的全局gpio_desc數組項  
  29.             gpio_desc[id].chip = chip;  //gpio_chip  
  30.             gpio_desc[id].flags = !chip->direction_input?(1 << FLAG_IS_OUT):0; //設置輸入輸出標誌位  
  31.         }  
  32.     }  
  33.     of_gpiochip_add(chip);  
  34. unlock:  
  35.     spin_unlock_irqrestore(&gpio_lock, flags);  //解自旋鎖  
  36.     if (status)  
  37.         goto fail;  
  38.     status = gpiochip_export(chip); //gpio_chip創建用戶接口  
  39.     if (status)  
  40.         goto fail;  
  41.     return 0;  
  42. fail:  
  43.     pr_err("gpiochip_add: gpios %d..%d (%s) failed to register\n",chip->base,chip->base+chip->ngpio-1,chip->label?:"generic");  
  44.     return status;  
  45. }  
  46. EXPORT_SYMBOL_GPL(gpiochip_add);  

2.清空gpio_chip管理的全局gpio_desc數組項
  1. int gpiochip_remove(struct gpio_chip *chip)  
  2. {  
  3.     unsigned long   flags;  
  4.     int status = 0;  
  5.     unsigned    id;  
  6.   
  7.     spin_lock_irqsave(&gpio_lock, flags);   //上自旋鎖  
  8.     of_gpiochip_remove(chip);  
  9.     for (id = chip->base; id < chip->base + chip->ngpio; id++) {    //查找對應全局gpio_desc數組項  
  10.         if (test_bit(FLAG_REQUESTED, &gpio_desc[id].flags)) {   //判斷是否存在標誌含FLAG_REQUESTED的gpio口  
  11.             status = -EBUSY;  
  12.             break;  
  13.         }  
  14.     }  
  15.     if (status == 0) {  
  16.         for (id = chip->base; id < chip->base + chip->ngpio; id++)  //清空對應全局gpio_desc數組項  
  17.             gpio_desc[id].chip = NULL;  
  18.     }  
  19.     spin_unlock_irqrestore(&gpio_lock, flags);  //解自旋鎖  
  20.     if (status == 0)  
  21.         gpiochip_unexport(chip);    //gpio_chip移除用戶接口  
  22.     return status;  
  23. }  
  24. EXPORT_SYMBOL_GPL(gpiochip_remove);  

3.查找獲取gpio_chip
  1. struct gpio_chip *gpiochip_find(void *data,int (*match)(struct gpio_chip *chip, void *data))  
  2. {  
  3.     struct gpio_chip *chip = NULL;  
  4.     unsigned long flags;  
  5.     int i;  
  6.   
  7.     spin_lock_irqsave(&gpio_lock, flags);   //上自旋鎖  
  8.     for (i = 0; i < ARCH_NR_GPIOS; i++) {    //遍歷整個全局gpio_desc數組  
  9.         if (!gpio_desc[i].chip) //若沒被某個gpio_chip管理,則跳過繼續  
  10.             continue;  
  11.         if (match(gpio_desc[i].chip, data)) {   //調用傳遞進來的匹配函數  
  12.             chip = gpio_desc[i].chip;   //匹配則獲取其gpio_chip  
  13.             break;  
  14.         }  
  15.     }  
  16.     spin_unlock_irqrestore(&gpio_lock, flags);  //解自旋鎖  
  17.     return chip;    //返回查找到的gpio_chip指針  
  18. }  

4.驗證gpio號是否正確
  1. static inline int gpio_is_valid(int number)  
  2. {  
  3.     return ((unsigned)number) < ARCH_NR_GPIOS;  
  4. }  

5.請求gpio資源
  1. int gpio_request(unsigned gpio, const char *label)  
  2. {  
  3.     struct gpio_desc    *desc;  
  4.     struct gpio_chip    *chip;  
  5.     int status = -EINVAL;  
  6.     unsigned long   flags;  
  7.   
  8.     spin_lock_irqsave(&gpio_lock, flags);   //上自旋鎖  
  9.     if (!gpio_is_valid(gpio))   //驗證gpio號是否正確  
  10.         goto done;  
  11.     desc = &gpio_desc[gpio];    //獲取gpio描述符  
  12.     chip = desc->chip;   //獲取gpio_chip  
  13.     if (chip == NULL)   //獲取gpio_chip失敗  
  14.         goto done;  
  15.     if (!try_module_get(chip->owner))    //增加模塊引用計數  
  16.         goto done;  
  17.     if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {   //測試並設置gpio_desc的FLAG_REQUESTED標誌  
  18.         desc_set_label(desc, label ? : "?");    //設置gpio_desc的label  
  19.         status = 0;  
  20.     }   
  21.     else {  
  22.         status = -EBUSY;  
  23.         module_put(chip->owner); //減少模塊引用計數  
  24.         goto done;  
  25.     }  
  26.     if (chip->request) { //gpio_chip存在request方法  
  27.         spin_unlock_irqrestore(&gpio_lock, flags);  //解自旋鎖  
  28.         status = chip->request(chip, gpio - chip->base);  //調用gpio_chip的request方法  
  29.         spin_lock_irqsave(&gpio_lock, flags);   //上自旋鎖  
  30.         if (status < 0) {  
  31.             desc_set_label(desc, NULL); //清除gpio_desc的label  
  32.             module_put(chip->owner); //減少模塊引用計數  
  33.             clear_bit(FLAG_REQUESTED, &desc->flags); //清除gpio_chip的FLAG_REQUESTED標誌  
  34.         }  
  35.     }  
  36. done:  
  37.     if (status)  
  38.         pr_debug("gpio_request: gpio-%d (%s) status %d\n",gpio, label ? : "?", status);  
  39.     spin_unlock_irqrestore(&gpio_lock, flags);  //解自旋鎖  
  40.     return status;  
  41. }  
  42. EXPORT_SYMBOL_GPL(gpio_request);  

6.釋放gpio資源
  1. void gpio_free(unsigned gpio)     
  2. {  
  3.     unsigned long       flags;  
  4.     struct gpio_desc    *desc;  
  5.     struct gpio_chip    *chip;  
  6.   
  7.     might_sleep();  
  8.     if (!gpio_is_valid(gpio)) { //驗證gpio號  
  9.         WARN_ON(extra_checks);  
  10.         return;  
  11.     }  
  12.     gpio_unexport(gpio);    //gpio移除用戶接口  
  13.     spin_lock_irqsave(&gpio_lock, flags);   //上自旋鎖  
  14.     desc = &gpio_desc[gpio];    //獲取gpio_desc  
  15.     chip = desc->chip;           //獲取gpio_chip  
  16.     if (chip && test_bit(FLAG_REQUESTED, &desc->flags)) {    //測試gpio_desc的FLAG_REQUESTED標誌  
  17.         if (chip->free) {    //gpio_chip存在free方法  
  18.             spin_unlock_irqrestore(&gpio_lock, flags);  //上自旋鎖  
  19.             might_sleep_if(chip->can_sleep);  
  20.             chip->free(chip, gpio - chip->base);  //調用gpio_chip的free方法  
  21.             spin_lock_irqsave(&gpio_lock, flags);   //解自旋鎖  
  22.         }  
  23.         desc_set_label(desc, NULL); //清除gpio_desc的label信息  
  24.         module_put(desc->chip->owner);    //減少模塊引用計數  
  25.         clear_bit(FLAG_ACTIVE_LOW, &desc->flags);    //清除FLAG_ACTIVE_LOW的標誌  
  26.         clear_bit(FLAG_REQUESTED, &desc->flags); //清除FLAG_REQUESTED的標誌  
  27.     }   
  28.     else  
  29.         WARN_ON(extra_checks);  
  30.     spin_unlock_irqrestore(&gpio_lock, flags);  //解自旋鎖  
  31. }  
  32. EXPORT_SYMBOL_GPL(gpio_free);  

7.設置去抖動時間
  1. int gpio_set_debounce(unsigned gpio, unsigned debounce)   
  2. {  
  3.     unsigned long       flags;  
  4.     struct gpio_chip    *chip;  
  5.     struct gpio_desc    *desc = &gpio_desc[gpio];   //獲取gpio_desc項  
  6.     int status = -EINVAL;  
  7.   
  8.     spin_lock_irqsave(&gpio_lock, flags);   //上自旋鎖  
  9.     if (!gpio_is_valid(gpio))   //驗證gpio號  
  10.         goto fail;  
  11.     chip = desc->chip;   //獲取gpio_chip  
  12.     if (!chip || !chip->set || !chip->set_debounce)   //判斷gpio_chip是否存在且是否存在set和set_debounce方法  
  13.         goto fail;  
  14.     gpio -= chip->base;  //計算gpio在該gpio_chip的偏移量  
  15.     if (gpio >= chip->ngpio)  //超過該gpio_chip的gpio數範圍  
  16.         goto fail;  
  17.     status = gpio_ensure_requested(desc, gpio); //確保gpio是request請求過了的  
  18.     if (status < 0)  
  19.         goto fail;  
  20.     /* now we know the gpio is valid and chip won't vanish */  
  21.     spin_unlock_irqrestore(&gpio_lock, flags);  //解自旋鎖  
  22.     might_sleep_if(chip->can_sleep);  
  23.     return chip->set_debounce(chip, gpio, debounce); //調用gpio_chip的set_debounce方法  
  24. fail:  
  25.     spin_unlock_irqrestore(&gpio_lock, flags);  //解自旋鎖  
  26.     if (status)  
  27.         pr_debug("%s: gpio-%d status %d\n",__func__, gpio, status);  
  28.     return status;  
  29. }  
  30. EXPORT_SYMBOL_GPL(gpio_set_debounce);  

8.設置gpio爲輸入io
  1. int gpio_direction_input(unsigned gpio)  
  2. {  
  3.     unsigned long   flags;  
  4.     struct gpio_chip    *chip;  
  5.     struct gpio_desc    *desc = &gpio_desc[gpio];   //獲取gpio_desc項  
  6.     int status = -EINVAL;  
  7.   
  8.     spin_lock_irqsave(&gpio_lock, flags);   //上自旋鎖  
  9.     if (!gpio_is_valid(gpio))  
  10.         goto fail;  
  11.     chip = desc->chip;   //獲取gpio_chip  
  12.     if (!chip || !chip->get || !chip->direction_input)    //判斷gpio_chip是否存在且存在get和directon_input方法  
  13.         goto fail;  
  14.     gpio -= chip->base;  //計算gpio在該gpio_chip的偏移量  
  15.     if (gpio >= chip->ngpio)  //超過該gpio_chip的gpio數範圍  
  16.         goto fail;  
  17.     status = gpio_ensure_requested(desc, gpio); //確保gpio是request請求過了的  
  18.     if (status < 0)  
  19.         goto fail;  
  20.     /* now we know the gpio is valid and chip won't vanish */  
  21.     spin_unlock_irqrestore(&gpio_lock, flags);  //解自旋鎖  
  22.     might_sleep_if(chip->can_sleep);  
  23.     if (status) {  
  24.         status = chip->request(chip, gpio);  //調用chip_gpio的request方法  
  25.         if (status < 0) {  
  26.             pr_debug("GPIO-%d: chip request fail, %d\n",chip->base + gpio, status);  
  27.             goto lose;  
  28.         }  
  29.     }  
  30.     status = chip->direction_input(chip, gpio);  //調用chip_gpio的direction_input方法  
  31.     if (status == 0)  
  32.         clear_bit(FLAG_IS_OUT, &desc->flags);  
  33. lose:  
  34.     return status;  
  35. fail:  
  36.     spin_unlock_irqrestore(&gpio_lock, flags);  //解自旋鎖  
  37.     if (status)  
  38.         pr_debug("%s: gpio-%d status %d\n",__func__, gpio, status);  
  39.     return status;  
  40. }  
  41. EXPORT_SYMBOL_GPL(gpio_direction_input);  

9.設備gpio爲輸出io
  1. int gpio_direction_output(unsigned gpio, int value)  
  2. {  
  3.     unsigned long   flags;  
  4.     struct gpio_chip    *chip;  
  5.     struct gpio_desc    *desc = &gpio_desc[gpio];   //獲取gpio_desc項  
  6.     int status = -EINVAL;  
  7.   
  8.     spin_lock_irqsave(&gpio_lock, flags);   //上自旋鎖  
  9.     if (!gpio_is_valid(gpio))  
  10.         goto fail;  
  11.     chip = desc->chip;   //獲取gpio_chip  
  12.     if (!chip || !chip->set || !chip->direction_output)   //判斷gpio_chip是否存在且存在set和direction_output方法  
  13.         goto fail;  
  14.     gpio -= chip->base;  //計算gpio在該gpio_chip的偏移量  
  15.     if (gpio >= chip->ngpio)  //超過該gpio_chip的gpio數範圍  
  16.         goto fail;  
  17.     status = gpio_ensure_requested(desc, gpio); //確保gpio是request請求過了的  
  18.     if (status < 0)  
  19.         goto fail;  
  20.     spin_unlock_irqrestore(&gpio_lock, flags);  //解自旋鎖  
  21.     might_sleep_if(chip->can_sleep);  
  22.     if (status) {  
  23.         status = chip->request(chip, gpio);  //調用gpio_chip的request方法  
  24.         if (status < 0) {  
  25.             pr_debug("GPIO-%d: chip request fail, %d\n",chip->base + gpio, status);  
  26.             goto lose;  
  27.         }  
  28.     }  
  29.     status = chip->direction_output(chip, gpio, value);  //調用gpio_chip的direction_output方法  
  30.     if (status == 0)  
  31.         set_bit(FLAG_IS_OUT, &desc->flags);  
  32. lose:  
  33.     return status;  
  34. fail:  
  35.     spin_unlock_irqrestore(&gpio_lock, flags);  //解自旋鎖  
  36.     if (status)  
  37.         pr_debug("%s: gpio-%d status %d\n",__func__, gpio, status);  
  38.     return status;  
  39. }  
  40. EXPORT_SYMBOL_GPL(gpio_direction_output);  

10.判斷gpio可否睡眠
  1. #define gpio_cansleep     __gpio_cansleep  
  2. int __gpio_cansleep(unsigned gpio)  
  3. {  
  4.     struct gpio_chip    *chip;  
  5.     chip = gpio_to_chip(gpio);  //獲取gpio_chip  
  6.     return chip->can_sleep;      //調用gpio_chip的can_sleep方法  
  7. }  
  8. EXPORT_SYMBOL_GPL(__gpio_cansleep);  

11.獲取gpio值(gpio可睡眠)
  1. int gpio_get_value_cansleep(unsigned gpio)  
  2. {  
  3.     struct gpio_chip    *chip;  
  4.     might_sleep_if(extra_checks);  
  5.     chip = gpio_to_chip(gpio);  //獲取gpio_chip  
  6.     return chip->get ? chip->get(chip, gpio - chip->base) : 0; //若存在gpio_chip的get方法則調用該方法  
  7. }  
  8. EXPORT_SYMBOL_GPL(gpio_get_value_cansleep);  

12.設置gpio值(gpio可睡眠)
  1. void gpio_set_value_cansleep(unsigned gpio, int value)  
  2. {  
  3.     struct gpio_chip    *chip;  
  4.     might_sleep_if(extra_checks);  
  5.     chip = gpio_to_chip(gpio);  //獲取gpio_chip  
  6.     chip->set(chip, gpio - chip->base, value);    //調用gpio_chip的set方法  
  7. }  
  8. EXPORT_SYMBOL_GPL(gpio_set_value_cansleep);  

13.獲取gpio值(gpio不可睡眠)
  1. #define gpio_get_value    __gpio_get_value    
  2. int __gpio_get_value(unsigned gpio)  
  3. {  
  4.     struct gpio_chip    *chip;  
  5.     chip = gpio_to_chip(gpio);  //獲取gpio_chip  
  6.     WARN_ON(chip->can_sleep);  
  7.     return chip->get ? chip->get(chip, gpio - chip->base) : 0; //若存在gpio_chip的get方法則調用該方法  
  8. }  
  9. EXPORT_SYMBOL_GPL(__gpio_get_value);  

14.設置gpio值(gpio不可睡眠)
  1. #define gpio_set_value    __gpio_set_value    
  2. void __gpio_set_value(unsigned gpio, int value)  
  3. {  
  4.     struct gpio_chip    *chip;  
  5.     chip = gpio_to_chip(gpio);  //獲取gpio_chip  
  6.     WARN_ON(chip->can_sleep);  
  7.     chip->set(chip, gpio - chip->base, value);    //調用gpio_chip的set方法  
  8. }  
  9. EXPORT_SYMBOL_GPL(__gpio_set_value);  

15.請求一個gpio資源
  1. int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)  
  2. {  
  3.     int err;  
  4.     err = gpio_request(gpio, label);    //請求gpio資源  
  5.     if (err)  
  6.         return err;  
  7.     if (flags & GPIOF_DIR_IN)   //輸入gpio  
  8.         err = gpio_direction_input(gpio);   //設置gpio爲輸入  
  9.     else                        //輸出gpio  
  10.         err = gpio_direction_output(gpio,(flags & GPIOF_INIT_HIGH) ? 1 : 0);    //設置gpio爲輸出  
  11.     if (err)    //出錯  
  12.         gpio_free(gpio);    //釋放gpio資源  
  13.     return err;  
  14. }  
  15. EXPORT_SYMBOL_GPL(gpio_request_one);  

16.請求一組gpio資源
  1. int gpio_request_array(struct gpio *array, size_t num)  
  2. {  
  3.     int i, err;  
  4.     for (i = 0; i < num; i++, array++) { //批量請求gpio資源  
  5.         err = gpio_request_one(array->gpio, array->flags, array->label);  
  6.         if (err)  
  7.             goto err_free;  
  8.     }  
  9.     return 0;  
  10. err_free:  
  11.     while (i--)  
  12.         gpio_free((--array)->gpio);  //釋放gpio資源  
  13.     return err;  
  14. }  
  15. EXPORT_SYMBOL_GPL(gpio_request_array);  

17.釋放一組gpio資源
  1. void gpio_free_array(struct gpio *array, size_t num)  
  2. {  
  3.     while (num--)  
  4.         gpio_free((array++)->gpio);  //批量是否gpio資源  
  5. }  
  6. EXPORT_SYMBOL_GPL(gpio_free_array);  

18.根據gpio號獲取對應的中斷號
  1. int __gpio_to_irq(unsigned gpio)  
  2. {  
  3.     struct gpio_chip    *chip;  
  4.     chip = gpio_to_chip(gpio);  //獲取gpio_chip  
  5.     return chip->to_irq?chip->to_irq(chip,gpio-chip->base):-ENXIO; //若gpio_chip的to_irq方法存在則調用其方法  
  6. }  
  7. EXPORT_SYMBOL_GPL(__gpio_to_irq);  

19.gpio_chip創建用戶接口
  1. static int gpiochip_export(struct gpio_chip *chip)  
  2. {  
  3.     int     status;  
  4.     struct device   *dev;  
  5.   
  6.     if (!gpio_class.p)  
  7.         return 0;  
  8.     mutex_lock(&sysfs_lock);    //上互斥鎖  
  9.     dev = device_create(&gpio_class, chip->dev, MKDEV(0, 0), chip,"gpiochip%d", chip->base);  //創建設備  
  10.     if (!IS_ERR(dev)) {  
  11.         status = sysfs_create_group(&dev->kobj,&gpiochip_attr_group);  
  12.     }   
  13.     else  
  14.         status = PTR_ERR(dev);  
  15.     chip->exported = (status == 0);  //設置gpio_chip的exported標誌  
  16.     mutex_unlock(&sysfs_lock);  //解互斥鎖  
  17.   
  18.     if (status) {  
  19.         unsigned long   flags;  
  20.         unsigned    gpio;  
  21.         spin_lock_irqsave(&gpio_lock, flags);   //上自旋鎖  
  22.         gpio = chip->base;   //獲取gpio_chip的基數  
  23.         while (gpio_desc[gpio].chip == chip)    //遍歷該gpio_chip管理的所有gpio_desc  
  24.             gpio_desc[gpio++].chip = NULL;      //清除該gpio_desc的chip成員  
  25.         spin_unlock_irqrestore(&gpio_lock, flags);  //解自旋鎖  
  26.         pr_debug("%s: chip %s status %d\n", __func__,chip->label, status);  
  27.     }  
  28.   
  29.     return status;  
  30. }  

20.gpio_chip移除用戶接口
  1. static void gpiochip_unexport(struct gpio_chip *chip)  
  2. {  
  3.     int status;  
  4.     struct device   *dev;  
  5.   
  6.     mutex_lock(&sysfs_lock);    //上互斥鎖  
  7.     dev = class_find_device(&gpio_class, NULL, chip, match_export); //找到export的gpio_chip的設備文件  
  8.     if (dev) {  
  9.         put_device(dev);    //減少引用計數  
  10.         device_unregister(dev); //註銷設備文件  
  11.         chip->exported = 0;  //清除export標誌  
  12.         status = 0; //設置status  
  13.     }   
  14.     else  
  15.         status = -ENODEV;  
  16.     mutex_unlock(&sysfs_lock);  //解互斥鎖  
  17.     if (status)  
  18.         pr_debug("%s: chip %s status %d\n", __func__,chip->label, status);  
  19. }  

21.gpio創建用戶接口
  1. int gpio_export(unsigned gpio, bool direction_may_change)  
  2. {  
  3.     unsigned long   flags;  
  4.     struct gpio_desc    *desc;  
  5.     int status = -EINVAL;  
  6.     const char  *ioname = NULL;  
  7.   
  8.     if (!gpio_class.p) {  
  9.         pr_debug("%s: called too early!\n", __func__);  
  10.         return -ENOENT;  
  11.     }  
  12.     if (!gpio_is_valid(gpio))   //驗證gpio號的正確性  
  13.         goto done;  
  14.     mutex_lock(&sysfs_lock);    //上互斥鎖  
  15.     spin_lock_irqsave(&gpio_lock, flags);   //上自旋鎖  
  16.     desc = &gpio_desc[gpio];    //獲取gpio_desc數組項  
  17.     if (test_bit(FLAG_REQUESTED, &desc->flags)&& !test_bit(FLAG_EXPORT, &desc->flags)) {  //已請求但沒export  
  18.         status = 0;  
  19.         if (!desc->chip->direction_input|| !desc->chip->direction_output)   //gpio_chip不存在direction_input和direction_output方法  
  20.             direction_may_change = false;   //那麼gpio的方向不可能會改變  
  21.     }  
  22.     spin_unlock_irqrestore(&gpio_lock, flags);  //解自旋鎖  
  23.     if (desc->chip->names && desc->chip->names[gpio - desc->chip->base])  //gpio_chip存在名字數組且存在對應數組項的名字  
  24.         ioname = desc->chip->names[gpio - desc->chip->base];    //設置gpio名  
  25.     if (status == 0) {  
  26.         struct device   *dev;  
  27.         dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),desc, ioname ? ioname : "gpio%u", gpio);    //創建設備文件  
  28.         if (!IS_ERR(dev)) {  
  29.             status = sysfs_create_group(&dev->kobj,&gpio_attr_group);    //創建屬性  
  30.             if (!status && direction_may_change)    //gpio方向可能會改變  
  31.                 status = device_create_file(dev,&dev_attr_direction);   //則創建跟方向相關的屬性  
  32.             if (!status && gpio_to_irq(gpio) >= 0&& (direction_may_change|| !test_bit(FLAG_IS_OUT,&desc->flags))) //可設置中斷的引薦  
  33.                 status = device_create_file(dev,&dev_attr_edge);    //則創建跟中斷觸發相關的屬性  
  34.             if (status != 0)  
  35.                 device_unregister(dev); //註銷設備  
  36.         }   
  37.         else  
  38.             status = PTR_ERR(dev);  
  39.         if (status == 0)  
  40.             set_bit(FLAG_EXPORT, &desc->flags);  //設置export標誌  
  41.     }  
  42.     mutex_unlock(&sysfs_lock);  //解互斥鎖  
  43. done:  
  44.     if (status)  
  45.         pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);  
  46.     return status;  
  47. }  
  48. EXPORT_SYMBOL_GPL(gpio_export);  

22.gpio移除用戶接口
  1. void gpio_unexport(unsigned gpio)  
  2. {  
  3.     struct gpio_desc    *desc;  
  4.     int         status = 0;  
  5.       
  6.     if (!gpio_is_valid(gpio)) { //驗證gpio號的正確性  
  7.         status = -EINVAL;  
  8.         goto done;  
  9.     }  
  10.     mutex_lock(&sysfs_lock);    //上鎖互斥鎖  
  11.     desc = &gpio_desc[gpio];    //獲取gpio_desc  
  12.     if (test_bit(FLAG_EXPORT, &desc->flags)) {   //判斷是否export  
  13.         struct device   *dev = NULL;  
  14.         dev = class_find_device(&gpio_class, NULL, desc, match_export); //獲取設備文件  
  15.         if (dev) {  
  16.             gpio_setup_irq(desc, dev, 0);   //中斷gpio的處理  
  17.             clear_bit(FLAG_EXPORT, &desc->flags);    //清除export標誌  
  18.             put_device(dev);    //增加dev引用計數  
  19.             device_unregister(dev); //註銷設備  
  20.         }   
  21.         else  
  22.             status = -ENODEV;  
  23.     }  
  24.     mutex_unlock(&sysfs_lock);  //解鎖互斥鎖  
  25. done:  
  26.     if (status)  
  27.         pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);  
  28. }  
  29. EXPORT_SYMBOL_GPL(gpio_unexport);  

23.中斷gpio處理
  1. static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,unsigned long gpio_flags)  
  2. {  
  3.     struct sysfs_dirent *value_sd;  
  4.     unsigned long   irq_flags;  
  5.     int ret, irq, id;  
  6.   
  7.     if ((desc->flags & GPIO_TRIGGER_MASK) == gpio_flags) //有FLAG_TRIG_FALL或FLAG_TRIG_RISE標誌  
  8.         return 0;  
  9.     irq = gpio_to_irq(desc - gpio_desc);    //根據gpio獲取對應的中斷號  
  10.     if (irq < 0)  
  11.         return -EIO;  
  12.     id = desc->flags >> ID_SHIFT;  //#define ID_SHIFT  16  
  13.     value_sd = idr_find(&dirent_idr, id);   //獲取設備id  
  14.     if (value_sd)   //獲取設備id成功,說明是申請過gpio中斷的了  
  15.         free_irq(irq, value_sd);    //釋放中斷  
  16.     desc->flags &= ~GPIO_TRIGGER_MASK;   //屏蔽gpio_desc標誌位FLAG_TRIG_FALL或FLAG_TRIG_RISE  
  17.     if (!gpio_flags) {  //gpio_unexport中的gpio_setup_irq跑到這裏返回  
  18.         ret = 0;  
  19.         goto free_id;  
  20.     }  
  21.     irq_flags = IRQF_SHARED;    //設置爲共享中斷類型  
  22.     if (test_bit(FLAG_TRIG_FALL, &gpio_flags))  //FLAG_TRIG_FALL 下降沿觸發  
  23.         irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;  
  24.     if (test_bit(FLAG_TRIG_RISE, &gpio_flags))  //FLAG_TRIG_RISE 上升沿觸發  
  25.         irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;  
  26.     if (!value_sd) {    //獲取設備id不成功  
  27.         value_sd = sysfs_get_dirent(dev->kobj.sd, NULL, "value");    //獲取設備id  
  28.         if (!value_sd) {  
  29.             ret = -ENODEV;  
  30.             goto err_out;  
  31.         }  
  32.         do {  
  33.             ret = -ENOMEM;  
  34.             if (idr_pre_get(&dirent_idr, GFP_KERNEL))  
  35.                 ret = idr_get_new_above(&dirent_idr, value_sd,1, &id);  
  36.         } while (ret == -EAGAIN);//id機制中獲取新的id該id指向value_sd  
  37.         if (ret)  
  38.             goto free_sd;  
  39.         desc->flags &= GPIO_FLAGS_MASK;      //設置gpio_desc標誌  
  40.         desc->flags |= (unsigned long)id << ID_SHIFT;  //或上idr機制獲取的id  
  41.         if (desc->flags >> ID_SHIFT != id) {   //驗證下是否id存放正確  
  42.             ret = -ERANGE;  
  43.             goto free_id;  
  44.         }  
  45.     }  
  46.     ret = request_any_context_irq(irq, gpio_sysfs_irq, irq_flags,"gpiolib", value_sd);  //申請中斷  
  47.     if (ret < 0)  
  48.         goto free_id;  
  49.     desc->flags |= gpio_flags;   //gpio_desc設置傳遞進來的標誌  
  50.     return 0;  
  51. free_id:  
  52.     idr_remove(&dirent_idr, id);  
  53.     desc->flags &= GPIO_FLAGS_MASK;  
  54. free_sd:  
  55.     if (value_sd)  
  56.         sysfs_put(value_sd);  
  57. err_out:  
  58.     return ret;  
  59. }  

四.sysfs的初始化
  1. static int __init gpiolib_sysfs_init(void)  
  2. {  
  3.     int status;  
  4.     unsigned long   flags;  
  5.     unsigned    gpio;  
  6.   
  7.     status = class_register(&gpio_class);   //註冊gpio_class  
  8.     if (status < 0)  
  9.         return status;  
  10.   
  11.     spin_lock_irqsave(&gpio_lock, flags);  
  12.     for (gpio = 0; gpio < ARCH_NR_GPIOS; gpio++) {   //遍歷全局gpio_desc數組  
  13.         struct gpio_chip    *chip;  
  14.   
  15.         chip = gpio_desc[gpio].chip;    //獲取數組項的gpio_chip  
  16.         if (!chip || chip->exported) //gpio_chip爲空或已經exported了  
  17.             continue;  
  18.   
  19.         spin_unlock_irqrestore(&gpio_lock, flags);  //上自旋鎖  
  20.         status = gpiochip_export(chip); //exported該項  
  21.         spin_lock_irqsave(&gpio_lock, flags);   //解自旋鎖  
  22.     }  
  23.     spin_unlock_irqrestore(&gpio_lock, flags);  
  24.   
  25.   
  26.     return status;  
  27. }  
  28. postcore_initcall(gpiolib_sysfs_init); 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章