Merge tag 'gpio-v3.19-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw...
[cascardo/linux.git] / drivers / gpio / gpiolib.c
index 58659db..487afe6 100644 (file)
@@ -47,8 +47,6 @@
  */
 DEFINE_SPINLOCK(gpio_lock);
 
-static struct gpio_desc gpio_desc[ARCH_NR_GPIOS];
-
 #define GPIO_OFFSET_VALID(chip, offset) (offset >= 0 && offset < chip->ngpio)
 
 static DEFINE_MUTEX(gpio_lookup_lock);
@@ -65,10 +63,24 @@ static inline void desc_set_label(struct gpio_desc *d, const char *label)
  */
 struct gpio_desc *gpio_to_desc(unsigned gpio)
 {
-       if (WARN(!gpio_is_valid(gpio), "invalid GPIO %d\n", gpio))
-               return NULL;
-       else
-               return &gpio_desc[gpio];
+       struct gpio_chip *chip;
+       unsigned long flags;
+
+       spin_lock_irqsave(&gpio_lock, flags);
+
+       list_for_each_entry(chip, &gpio_chips, list) {
+               if (chip->base <= gpio && chip->base + chip->ngpio > gpio) {
+                       spin_unlock_irqrestore(&gpio_lock, flags);
+                       return &chip->desc[gpio - chip->base];
+               }
+       }
+
+       spin_unlock_irqrestore(&gpio_lock, flags);
+
+       if (!gpio_is_valid(gpio))
+               WARN(1, "invalid GPIO %d\n", gpio);
+
+       return NULL;
 }
 EXPORT_SYMBOL_GPL(gpio_to_desc);
 
@@ -91,7 +103,7 @@ struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip,
  */
 int desc_to_gpio(const struct gpio_desc *desc)
 {
-       return desc - &gpio_desc[0];
+       return desc->chip->base + (desc - &desc->chip->desc[0]);
 }
 EXPORT_SYMBOL_GPL(desc_to_gpio);
 
@@ -138,7 +150,7 @@ static int gpiochip_find_base(int ngpio)
  *
  * This function may sleep if gpiod_cansleep() is true.
  */
-int gpiod_get_direction(const struct gpio_desc *desc)
+int gpiod_get_direction(struct gpio_desc *desc)
 {
        struct gpio_chip        *chip;
        unsigned                offset;
@@ -154,13 +166,11 @@ int gpiod_get_direction(const struct gpio_desc *desc)
        if (status > 0) {
                /* GPIOF_DIR_IN, or other positive */
                status = 1;
-               /* FLAG_IS_OUT is just a cache of the result of get_direction(),
-                * so it does not affect constness per se */
-               clear_bit(FLAG_IS_OUT, &((struct gpio_desc *)desc)->flags);
+               clear_bit(FLAG_IS_OUT, &desc->flags);
        }
        if (status == 0) {
                /* GPIOF_DIR_OUT */
-               set_bit(FLAG_IS_OUT, &((struct gpio_desc *)desc)->flags);
+               set_bit(FLAG_IS_OUT, &desc->flags);
        }
        return status;
 }
@@ -206,7 +216,7 @@ static int gpiochip_add_to_list(struct gpio_chip *chip)
 /**
  * gpiochip_add() - register a gpio_chip
  * @chip: the chip to register, with chip->base initialized
- * Context: potentially before irqs or kmalloc will work
+ * 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
@@ -226,12 +236,11 @@ int gpiochip_add(struct gpio_chip *chip)
        int             status = 0;
        unsigned        id;
        int             base = chip->base;
+       struct gpio_desc *descs;
 
-       if ((!gpio_is_valid(base) || !gpio_is_valid(base + chip->ngpio - 1))
-                       && base >= 0) {
-               status = -EINVAL;
-               goto fail;
-       }
+       descs = kcalloc(chip->ngpio, sizeof(descs[0]), GFP_KERNEL);
+       if (!descs)
+               return -ENOMEM;
 
        spin_lock_irqsave(&gpio_lock, flags);
 
@@ -247,10 +256,8 @@ int gpiochip_add(struct gpio_chip *chip)
        status = gpiochip_add_to_list(chip);
 
        if (status == 0) {
-               chip->desc = &gpio_desc[chip->base];
-
                for (id = 0; id < chip->ngpio; id++) {
-                       struct gpio_desc *desc = &chip->desc[id];
+                       struct gpio_desc *desc = &descs[id];
                        desc->chip = chip;
 
                        /* REVISIT:  most hardware initializes GPIOs as
@@ -266,6 +273,8 @@ int gpiochip_add(struct gpio_chip *chip)
                }
        }
 
+       chip->desc = descs;
+
        spin_unlock_irqrestore(&gpio_lock, flags);
 
 #ifdef CONFIG_PINCTRL
@@ -291,6 +300,9 @@ int gpiochip_add(struct gpio_chip *chip)
 unlock:
        spin_unlock_irqrestore(&gpio_lock, flags);
 fail:
+       kfree(descs);
+       chip->desc = NULL;
+
        /* 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,
@@ -331,6 +343,9 @@ void gpiochip_remove(struct gpio_chip *chip)
        list_del(&chip->list);
        spin_unlock_irqrestore(&gpio_lock, flags);
        gpiochip_unexport(chip);
+
+       kfree(chip->desc);
+       chip->desc = NULL;
 }
 EXPORT_SYMBOL_GPL(gpiochip_remove);
 
@@ -495,7 +510,7 @@ static int gpiochip_irq_reqres(struct irq_data *d)
 {
        struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
 
-       if (gpio_lock_as_irq(chip, d->hwirq)) {
+       if (gpiochip_lock_as_irq(chip, d->hwirq)) {
                chip_err(chip,
                        "unable to lock HW IRQ %lu for IRQ\n",
                        d->hwirq);
@@ -508,7 +523,7 @@ static void gpiochip_irq_relres(struct irq_data *d)
 {
        struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
 
-       gpio_unlock_as_irq(chip, d->hwirq);
+       gpiochip_unlock_as_irq(chip, d->hwirq);
 }
 
 static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset)
@@ -1254,6 +1269,88 @@ static void _gpiod_set_raw_value(struct gpio_desc *desc, bool value)
                chip->set(chip, gpio_chip_hwgpio(desc), value);
 }
 
+/*
+ * set multiple outputs on the same chip;
+ * use the chip's set_multiple function if available;
+ * otherwise set the outputs sequentially;
+ * @mask: bit mask array; one bit per output; BITS_PER_LONG bits per word
+ *        defines which outputs are to be changed
+ * @bits: bit value array; one bit per output; BITS_PER_LONG bits per word
+ *        defines the values the outputs specified by mask are to be set to
+ */
+static void gpio_chip_set_multiple(struct gpio_chip *chip,
+                                  unsigned long *mask, unsigned long *bits)
+{
+       if (chip->set_multiple) {
+               chip->set_multiple(chip, mask, bits);
+       } else {
+               int i;
+               for (i = 0; i < chip->ngpio; i++) {
+                       if (mask[BIT_WORD(i)] == 0) {
+                               /* no more set bits in this mask word;
+                                * skip ahead to the next word */
+                               i = (BIT_WORD(i) + 1) * BITS_PER_LONG - 1;
+                               continue;
+                       }
+                       /* set outputs if the corresponding mask bit is set */
+                       if (__test_and_clear_bit(i, mask)) {
+                               chip->set(chip, i, test_bit(i, bits));
+                       }
+               }
+       }
+}
+
+static void gpiod_set_array_priv(bool raw, bool can_sleep,
+                                unsigned int array_size,
+                                struct gpio_desc **desc_array,
+                                int *value_array)
+{
+       int i = 0;
+
+       while (i < array_size) {
+               struct gpio_chip *chip = desc_array[i]->chip;
+               unsigned long mask[BITS_TO_LONGS(chip->ngpio)];
+               unsigned long bits[BITS_TO_LONGS(chip->ngpio)];
+               int count = 0;
+
+               if (!can_sleep) {
+                       WARN_ON(chip->can_sleep);
+               }
+               memset(mask, 0, sizeof(mask));
+               do {
+                       struct gpio_desc *desc = desc_array[i];
+                       int hwgpio = gpio_chip_hwgpio(desc);
+                       int value = value_array[i];
+
+                       if (!raw && test_bit(FLAG_ACTIVE_LOW, &desc->flags))
+                               value = !value;
+                       trace_gpio_value(desc_to_gpio(desc), 0, value);
+                       /*
+                        * collect all normal outputs belonging to the same chip
+                        * open drain and open source outputs are set individually
+                        */
+                       if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) {
+                               _gpio_set_open_drain_value(desc,value);
+                       } else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) {
+                               _gpio_set_open_source_value(desc, value);
+                       } else {
+                               __set_bit(hwgpio, mask);
+                               if (value) {
+                                       __set_bit(hwgpio, bits);
+                               } else {
+                                       __clear_bit(hwgpio, bits);
+                               }
+                               count++;
+                       }
+                       i++;
+               } while ((i < array_size) && (desc_array[i]->chip == chip));
+               /* push collected bits to outputs */
+               if (count != 0) {
+                       gpio_chip_set_multiple(chip, mask, bits);
+               }
+       }
+}
+
 /**
  * gpiod_set_raw_value() - assign a gpio's raw value
  * @desc: gpio whose value will be assigned
@@ -1298,6 +1395,48 @@ void gpiod_set_value(struct gpio_desc *desc, int value)
 }
 EXPORT_SYMBOL_GPL(gpiod_set_value);
 
+/**
+ * gpiod_set_raw_array() - assign values to an array of GPIOs
+ * @array_size: number of elements in the descriptor / value arrays
+ * @desc_array: array of GPIO descriptors whose values will be assigned
+ * @value_array: array of values to assign
+ *
+ * Set the raw values of the GPIOs, i.e. the values of the physical lines
+ * without regard for their ACTIVE_LOW status.
+ *
+ * This function should be called from contexts where we cannot sleep, and will
+ * complain if the GPIO chip functions potentially sleep.
+ */
+void gpiod_set_raw_array(unsigned int array_size,
+                        struct gpio_desc **desc_array, int *value_array)
+{
+       if (!desc_array)
+               return;
+       gpiod_set_array_priv(true, false, array_size, desc_array, value_array);
+}
+EXPORT_SYMBOL_GPL(gpiod_set_raw_array);
+
+/**
+ * gpiod_set_array() - assign values to an array of GPIOs
+ * @array_size: number of elements in the descriptor / value arrays
+ * @desc_array: array of GPIO descriptors whose values will be assigned
+ * @value_array: array of values to assign
+ *
+ * Set the logical values of the GPIOs, i.e. taking their ACTIVE_LOW status
+ * into account.
+ *
+ * This function should be called from contexts where we cannot sleep, and will
+ * complain if the GPIO chip functions potentially sleep.
+ */
+void gpiod_set_array(unsigned int array_size,
+                    struct gpio_desc **desc_array, int *value_array)
+{
+       if (!desc_array)
+               return;
+       gpiod_set_array_priv(false, false, array_size, desc_array, value_array);
+}
+EXPORT_SYMBOL_GPL(gpiod_set_array);
+
 /**
  * gpiod_cansleep() - report whether gpio value access may sleep
  * @desc: gpio to check
@@ -1332,14 +1471,14 @@ int gpiod_to_irq(const struct gpio_desc *desc)
 EXPORT_SYMBOL_GPL(gpiod_to_irq);
 
 /**
- * gpio_lock_as_irq() - lock a GPIO to be used as IRQ
+ * gpiochip_lock_as_irq() - lock a GPIO to be used as IRQ
  * @chip: the chip the GPIO to lock belongs to
  * @offset: the offset of the GPIO to lock as IRQ
  *
  * This is used directly by GPIO drivers that want to lock down
  * a certain GPIO line to be used for IRQs.
  */
-int gpio_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
+int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
 {
        if (offset >= chip->ngpio)
                return -EINVAL;
@@ -1354,24 +1493,24 @@ int gpio_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
        set_bit(FLAG_USED_AS_IRQ, &chip->desc[offset].flags);
        return 0;
 }
-EXPORT_SYMBOL_GPL(gpio_lock_as_irq);
+EXPORT_SYMBOL_GPL(gpiochip_lock_as_irq);
 
 /**
- * gpio_unlock_as_irq() - unlock a GPIO used as IRQ
+ * gpiochip_unlock_as_irq() - unlock a GPIO used as IRQ
  * @chip: the chip the GPIO to lock belongs to
  * @offset: the offset of the GPIO to lock as IRQ
  *
  * This is used directly by GPIO drivers that want to indicate
  * that a certain GPIO is no longer used exclusively for IRQ.
  */
-void gpio_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)
+void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)
 {
        if (offset >= chip->ngpio)
                return;
 
        clear_bit(FLAG_USED_AS_IRQ, &chip->desc[offset].flags);
 }
-EXPORT_SYMBOL_GPL(gpio_unlock_as_irq);
+EXPORT_SYMBOL_GPL(gpiochip_unlock_as_irq);
 
 /**
  * gpiod_get_raw_value_cansleep() - return a gpio's raw value
@@ -1457,6 +1596,50 @@ void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)
 }
 EXPORT_SYMBOL_GPL(gpiod_set_value_cansleep);
 
+/**
+ * gpiod_set_raw_array_cansleep() - assign values to an array of GPIOs
+ * @array_size: number of elements in the descriptor / value arrays
+ * @desc_array: array of GPIO descriptors whose values will be assigned
+ * @value_array: array of values to assign
+ *
+ * Set the raw values of the GPIOs, i.e. the values of the physical lines
+ * without regard for their ACTIVE_LOW status.
+ *
+ * This function is to be called from contexts that can sleep.
+ */
+void gpiod_set_raw_array_cansleep(unsigned int array_size,
+                                 struct gpio_desc **desc_array,
+                                 int *value_array)
+{
+       might_sleep_if(extra_checks);
+       if (!desc_array)
+               return;
+       gpiod_set_array_priv(true, true, array_size, desc_array, value_array);
+}
+EXPORT_SYMBOL_GPL(gpiod_set_raw_array_cansleep);
+
+/**
+ * gpiod_set_array_cansleep() - assign values to an array of GPIOs
+ * @array_size: number of elements in the descriptor / value arrays
+ * @desc_array: array of GPIO descriptors whose values will be assigned
+ * @value_array: array of values to assign
+ *
+ * Set the logical values of the GPIOs, i.e. taking their ACTIVE_LOW status
+ * into account.
+ *
+ * This function is to be called from contexts that can sleep.
+ */
+void gpiod_set_array_cansleep(unsigned int array_size,
+                             struct gpio_desc **desc_array,
+                             int *value_array)
+{
+       might_sleep_if(extra_checks);
+       if (!desc_array)
+               return;
+       gpiod_set_array_priv(false, true, array_size, desc_array, value_array);
+}
+EXPORT_SYMBOL_GPL(gpiod_set_array_cansleep);
+
 /**
  * gpiod_add_lookup_table() - register GPIO device consumers
  * @table: table of consumers to register