};
static struct gpio_desc gpio_desc[ARCH_NR_GPIOS];
+#define GPIO_OFFSET_VALID(chip, offset) (offset >= 0 && offset < chip->ngpio)
+
static LIST_HEAD(gpio_chips);
#ifdef CONFIG_GPIO_SYSFS
*/
static int gpio_chip_hwgpio(const struct gpio_desc *desc)
{
- return (desc - &gpio_desc[0]) - desc->chip->base;
+ return desc - &desc->chip->desc[0];
}
/**
*/
static int desc_to_gpio(const struct gpio_desc *desc)
{
- return desc - &gpio_desc[0];
+ return desc->chip->base + gpio_chip_hwgpio(desc);
}
unsigned gpio;
spin_lock_irqsave(&gpio_lock, flags);
- gpio = chip->base;
- while (gpio_desc[gpio].chip == chip)
- gpio_desc[gpio++].chip = NULL;
+ gpio = 0;
+ while (gpio < chip->ngpio)
+ chip->desc[gpio++].chip = NULL;
spin_unlock_irqrestore(&gpio_lock, flags);
pr_debug("%s: chip %s status %d\n", __func__,
status = gpiochip_add_to_list(chip);
if (status == 0) {
- for (id = base; id < base + chip->ngpio; id++) {
- gpio_desc[id].chip = chip;
+ chip->desc = &gpio_desc[chip->base];
+
+ for (id = 0; id < chip->ngpio; id++) {
+ struct gpio_desc *desc = &chip->desc[id];
+ desc->chip = chip;
/* REVISIT: most hardware initializes GPIOs as
* inputs (often with pullups enabled) so power
* and in case chip->get_direction is not set,
* we may expose the wrong direction in sysfs.
*/
- gpio_desc[id].flags = !chip->direction_input
+ desc->flags = !chip->direction_input
? (1 << FLAG_IS_OUT)
: 0;
}
gpiochip_remove_pin_ranges(chip);
of_gpiochip_remove(chip);
- for (id = chip->base; id < chip->base + chip->ngpio; id++) {
- if (test_bit(FLAG_REQUESTED, &gpio_desc[id].flags)) {
+ for (id = 0; id < chip->ngpio; id++) {
+ if (test_bit(FLAG_REQUESTED, &chip->desc[id].flags)) {
status = -EBUSY;
break;
}
}
if (status == 0) {
- for (id = chip->base; id < chip->base + chip->ngpio; id++)
- gpio_desc[id].chip = NULL;
+ for (id = 0; id < chip->ngpio; id++)
+ chip->desc[id].chip = NULL;
list_del(&chip->list);
}
*/
const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset)
{
- unsigned gpio = chip->base + offset;
- struct gpio_desc *desc = &gpio_desc[gpio];
+ struct gpio_desc *desc;
- if (!gpio_is_valid(gpio) || desc->chip != chip)
+ if (!GPIO_OFFSET_VALID(chip, offset))
return NULL;
+
+ desc = &chip->desc[offset];
+
if (test_bit(FLAG_REQUESTED, &desc->flags) == 0)
return NULL;
#ifdef CONFIG_DEBUG_FS
{
unsigned i;
unsigned gpio = chip->base;
- struct gpio_desc *gdesc = &gpio_desc[gpio];
+ struct gpio_desc *gdesc = &chip->desc[0];
int is_out;
for (i = 0; i < chip->ngpio; i++, gpio++, gdesc++) {
struct seq_file;
struct module;
struct device_node;
+struct gpio_desc;
/**
* struct gpio_chip - abstract a GPIO controller
* negative during registration, requests dynamic ID allocation.
* @ngpio: the number of GPIOs handled by this controller; the last GPIO
* handled is (base + ngpio - 1).
+ * @desc: array of ngpio descriptors. Private.
* @can_sleep: flag must be set iff get()/set() methods sleep, as they
* must while accessing GPIO expander chips over I2C or SPI
* @names: if set, must be an array of strings to use as alternative
struct gpio_chip *chip);
int base;
u16 ngpio;
+ struct gpio_desc *desc;
const char *const *names;
unsigned can_sleep:1;
unsigned exported:1;