linux/drivers/gpio/gpiolib.h
Mika Westerberg 77c2d7929d gpiolib: Allow GPIO chips to request their own GPIOs
Sometimes it is useful to allow GPIO chips themselves to request GPIOs they
own through gpiolib API. One use case is ACPI ASL code that should be able
to toggle GPIOs through GPIO operation regions.

We can't use gpio_request() because it will pin the module to the kernel
forever (it calls try_module_get()). To solve this we move module refcount
manipulation to gpiod_request() and let __gpiod_request() handle the actual
request. This changes the sequence a bit as now try_module_get() is called
outside of gpio_lock (I think this is safe, try_module_get() handles
serialization it needs already).

Then we provide gpiolib internal functions gpiochip_request/free_own_desc()
that do the same as gpio_request() but don't manipulate module refrence
count. This allows the GPIO chip driver to request and free descriptors it
owns without being pinned to the kernel forever.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2014-03-13 10:32:18 +01:00

50 lines
1.3 KiB
C

/*
* Internal GPIO functions.
*
* Copyright (C) 2013, Intel Corporation
* Author: Mika Westerberg <mika.westerberg@linux.intel.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef GPIOLIB_H
#define GPIOLIB_H
#include <linux/err.h>
#include <linux/device.h>
/**
* struct acpi_gpio_info - ACPI GPIO specific information
* @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo
* @active_low: in case of @gpioint, the pin is active low
*/
struct acpi_gpio_info {
bool gpioint;
bool active_low;
};
#ifdef CONFIG_ACPI
void acpi_gpiochip_add(struct gpio_chip *chip);
void acpi_gpiochip_remove(struct gpio_chip *chip);
struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
struct acpi_gpio_info *info);
#else
static inline void acpi_gpiochip_add(struct gpio_chip *chip) { }
static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { }
static inline struct gpio_desc *
acpi_get_gpiod_by_index(struct device *dev, int index,
struct acpi_gpio_info *info)
{
return ERR_PTR(-ENOSYS);
}
#endif
int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label);
void gpiochip_free_own_desc(struct gpio_desc *desc);
#endif /* GPIOLIB_H */