参照元

説明

引数

返り値

参考

実装

/**
 * gpiochip_add() - register a gpio_chip
 * @chip: the chip to register, with chip->base initialized
 * Context: potentially before irqs will work
 *
 * Returns a negative errno if the chip can't be registered, such as
 * because the chip->base is invalid or already associated with a
 * different chip.  Otherwise it returns zero as a success code.
 *
 * When gpiochip_add() is called very early during boot, so that GPIOs
 * can be freely used, the chip->dev device must be registered before
 * the gpio framework's arch_initcall().  Otherwise sysfs initialization
 * for GPIOs will fail rudely.
 *
 * If chip->base is negative, this requests dynamic assignment of
 * a range of valid GPIOs.
 */
int gpiochip_add(struct gpio_chip *chip)
{
        unsigned long   flags;
        int             status = 0;
        unsigned        id;
        int             base = chip->base;
        struct gpio_desc *descs;
        descs = kcalloc(chip->ngpio, sizeof(descs[0]), GFP_KERNEL);
        if (!descs)
                return -ENOMEM;
        spin_lock_irqsave(&gpio_lock, flags);
        if (base < 0) {
                base = gpiochip_find_base(chip->ngpio);
                if (base < 0) {
                        status = base;
                        spin_unlock_irqrestore(&gpio_lock, flags);
                        goto err_free_descs;
                }
                chip->base = base;
        }
        status = gpiochip_add_to_list(chip);
        if (status) {
                spin_unlock_irqrestore(&gpio_lock, flags);
                goto err_free_descs;
        }
        for (id = 0; id < chip->ngpio; id++) {
                struct gpio_desc *desc = &descs[id];

                desc->chip = chip;

                /* REVISIT: most hardware initializes GPIOs as inputs (often
                 * with pullups enabled) so power usage is minimized. Linux
                 * code should set the gpio direction first thing; but until
                 * it does, and in case chip->get_direction is not set, we may
                 * expose the wrong direction in sysfs.
                 */
                desc->flags = !chip->direction_input ? (1 << FLAG_IS_OUT) : 0;
        }

        chip->desc = descs;

        spin_unlock_irqrestore(&gpio_lock, flags);

#ifdef CONFIG_PINCTRL
        INIT_LIST_HEAD(&chip->pin_ranges);
#endif

        if (!chip->owner && chip->dev && chip->dev->driver)
                chip->owner = chip->dev->driver->owner;

        status = gpiochip_set_desc_names(chip);
        if (status)
                goto err_remove_from_list;
        status = of_gpiochip_add(chip);
        if (status)
                goto err_remove_chip;
        acpi_gpiochip_add(chip);
        status = gpiochip_sysfs_register(chip);
        if (status)
                goto err_remove_chip;
        pr_debug("%s: registered GPIOs %d to %d on device: %s\n", __func__,
                chip->base, chip->base + chip->ngpio - 1,
                chip->label ? : "generic");
        return 0;

err_remove_chip:
        acpi_gpiochip_remove(chip);
        gpiochip_free_hogs(chip);
        of_gpiochip_remove(chip);
err_remove_from_list:
        spin_lock_irqsave(&gpio_lock, flags);
        list_del(&chip->list);
        spin_unlock_irqrestore(&gpio_lock, flags);
        chip->desc = NULL;
err_free_descs:
        kfree(descs);
        /* failures here can mean systems won't boot... */
        pr_err("%s: GPIOs %d..%d (%s) failed to register\n", __func__,
                chip->base, chip->base + chip->ngpio - 1,
                chip->label ? : "generic");
        return status;
}
EXPORT_SYMBOL_GPL(gpiochip_add);

コメント


トップ   編集 凍結 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2016-05-19 (木) 10:42:27