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);