2017年9月22日 星期五

Linux driver GPIO ownership

gpio_request() : Use test and set to verify GPIO and get ownership
gpio_free() : Release ownership
-----------------------------------------------------------------------------------
int gpio_request(unsigned gpio, const char *label)
{
    struct gpio_desc    *desc;
    struct gpio_chip    *chip;
    int         status = -EPROBE_DEFER;
    unsigned long       flags;
    spin_lock_irqsave(&gpio_lock, flags);
    if (!gpio_is_valid(gpio)) {
        status = -EINVAL;
        goto done;
    }
    desc = &gpio_desc[gpio];
    chip = desc->chip;
    if (chip == NULL)
        goto done;
    if (!try_module_get(chip->owner))
        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) {
        desc_set_label(desc, label ? : "?");
        status = 0;
    } else {
        status = -EBUSY;
        module_put(chip->owner);
        goto done;
    }
    if (chip->request) {
        /* chip->request may sleep */
        spin_unlock_irqrestore(&gpio_lock, flags);
        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);
            goto done;
        }
    }
    if (chip->get_direction) {
        /* chip->get_direction may sleep */
        spin_unlock_irqrestore(&gpio_lock, flags);
        gpio_get_direction(gpio);
        spin_lock_irqsave(&gpio_lock, 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);
-----------------------------------------------------------------------------------
Refer to:


沒有留言:

張貼留言