Linux下GPIO驱动(四) ----gpio_request();gpio_free();

时间:2021-11-19 17:56:39

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