//gpio_request申請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); // gpio_lock是自旋鎖,上鎖,保存FLAG在flags變量 if (!gpio_is_valid(gpio)) goto done; desc = &gpio_desc[gpio]; chip = desc->chip; if (chip == NULL) goto done; if (!try_module_get(chip->owner)) // 該函數用於增加模塊使用計數;若返回為0,表示調用失敗,希望使用的模塊沒有被加載或正在被卸載中 goto done; /* NOTE: gpio_request() can be called in early boot, * before IRQs are enabled, for non-sleeping (SOC) GPIOs. */ if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) { // 原子操作,將flags的第FLAG_REQUESTED位置1,並返回其原值
desc_set_label(desc, label ? : "?");// 如果原來的值是0, 執行desc_set_label, 對desc->chip.label賦值,如果label有定義,直接用定義,比如上面的“temporary”,否則用“?”
status = 0; } else { status = -EBUSY; module_put(chip->owner); // 該函數用於減少模塊使用計數goto done; } if (chip->request) {// chip->request在linux初始化時是沒有指向的 /* chip->request may sleep */ spin_unlock_irqrestore(&gpio_lock, flags);// 如果chip->request不為0, 解鎖,因為后面調用的chip->request有可能睡眠
status = chip->request(chip, gpio - chip->base); spin_lock_irqsave(&gpio_lock, flags); if (status < 0) { desc_set_label(desc, NULL); module_put(chip->owner); clear_bit(FLAG_REQUESTED, &desc->flags); } } 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); void gpio_free(unsigned gpio) { unsigned long flags; struct gpio_desc *desc; struct gpio_chip *chip; might_sleep(); if (!gpio_is_valid(gpio)) { WARN_ON(extra_checks); return; } gpio_unexport(gpio); spin_lock_irqsave(&gpio_lock, flags); desc = &gpio_desc[gpio]; chip = desc->chip; if (chip && test_bit(FLAG_REQUESTED, &desc->flags)) { if (chip->free) { spin_unlock_irqrestore(&gpio_lock, flags); might_sleep_if(extra_checks && chip->can_sleep); chip->free(chip, gpio - chip->base); spin_lock_irqsave(&gpio_lock, flags); } desc_set_label(desc, NULL); module_put(desc->chip->owner); clear_bit(FLAG_ACTIVE_LOW, &desc->flags); clear_bit(FLAG_REQUESTED, &desc->flags); } else WARN_ON(extra_checks); spin_unlock_irqrestore(&gpio_lock, flags); } EXPORT_SYMBOL_GPL(gpio_free);
