*参照元 [#fadad285] #backlinks *説明 [#id47efc4] -パス: [[linux-4.4.1/drivers/gpio/gpiolib.c]] -FIXME: これは何? --説明 **引数 [#xcf20135] -struct gpio_chip *chip -- --[[linux-4.4.1/gpio_chip]] **返り値 [#m9aae114] -int -- **参考 [#f8befcd7] *実装 [#v8610395] /** * 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; - --[[linux-4.4.1/gpio_desc]] descs = kcalloc(chip->ngpio, sizeof(descs[0]), GFP_KERNEL); if (!descs) return -ENOMEM; - --[[linux-4.4.1/kcalloc()]] spin_lock_irqsave(&gpio_lock, flags); - --[[linux-4.4.1/spin_lock_irqsave()]] 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; } - --[[linux-4.4.1/gpiochip_find_base()]] --[[linux-4.4.1/spin_unlock_irqrestore()]] status = gpiochip_add_to_list(chip); if (status) { spin_unlock_irqrestore(&gpio_lock, flags); goto err_free_descs; } - --[[linux-4.4.1/gpiochip_add_to_list()]] 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); - --[[linux-4.4.1/CONFIG_PINCTRL]] --[[linux-4.4.1/INIT_LIST_HEAD()]] #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; - --[[linux-4.4.1/gpiochip_set_desc_names()]] status = of_gpiochip_add(chip); if (status) goto err_remove_chip; - --[[linux-4.4.1/of_gpiochip_add()]] acpi_gpiochip_add(chip); - --[[linux-4.4.1/acpi_gpiochip_add()]] status = gpiochip_sysfs_register(chip); if (status) goto err_remove_chip; - --[[linux-4.4.1/gpiochip_sysfs_register()]] pr_debug("%s: registered GPIOs %d to %d on device: %s\n", __func__, chip->base, chip->base + chip->ngpio - 1, chip->label ? : "generic"); - --[[linux-4.4.1/pr_debug()]] return 0; err_remove_chip: acpi_gpiochip_remove(chip); gpiochip_free_hogs(chip); of_gpiochip_remove(chip); - --[[linux-4.4.1/acpi_gpiochip_remove()]] --[[linux-4.4.1/gpiochip_free_hogs()]] --[[linux-4.4.1/of_gpiochip_remove()]] err_remove_from_list: spin_lock_irqsave(&gpio_lock, flags); list_del(&chip->list); spin_unlock_irqrestore(&gpio_lock, flags); chip->desc = NULL; - --[[linux-4.4.1/spin_lock_irqsave()]] --[[linux-4.4.1/gpio_lock(global)]] --[[linux-4.4.1/list_del()]] --[[linux-4.4.1/spin_unlock_irqrestore()]] err_free_descs: kfree(descs); - --[[linux-4.4.1/kfree()]] /* 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"); - --[[linux-4.4.1/pr_err()]] return status; } EXPORT_SYMBOL_GPL(gpiochip_add); - --[[linux-4.4.1/EXPORT_SYMBOL_GPL()]] *コメント [#k0a70a9c]