gpiolib: Allow GPIO chips to request their own GPIOs
[firefly-linux-kernel-4.4.55.git] / drivers / gpio / gpiolib.c
index 50c4922fe53abf8f51cf1d613d59a9d5207bc002..8fbc67a8846581a472fa95fc55124c2c7623adc5 100644 (file)
@@ -164,16 +164,17 @@ struct gpio_desc *gpio_to_desc(unsigned gpio)
 EXPORT_SYMBOL_GPL(gpio_to_desc);
 
 /**
- * Convert an offset on a certain chip to a corresponding descriptor
+ * Get the GPIO descriptor corresponding to the given hw number for this chip.
  */
-static struct gpio_desc *gpiochip_offset_to_desc(struct gpio_chip *chip,
-                                                unsigned int offset)
+struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip,
+                                   u16 hwnum)
 {
-       if (offset >= chip->ngpio)
+       if (hwnum >= chip->ngpio)
                return ERR_PTR(-EINVAL);
 
-       return &chip->desc[offset];
+       return &chip->desc[hwnum];
 }
+EXPORT_SYMBOL_GPL(gpiochip_get_desc);
 
 /**
  * Convert a GPIO descriptor to the integer namespace.
@@ -350,9 +351,9 @@ static ssize_t gpio_direction_store(struct device *dev,
        if (!test_bit(FLAG_EXPORT, &desc->flags))
                status = -EIO;
        else if (sysfs_streq(buf, "high"))
-               status = gpiod_direction_output(desc, 1);
+               status = gpiod_direction_output_raw(desc, 1);
        else if (sysfs_streq(buf, "out") || sysfs_streq(buf, "low"))
-               status = gpiod_direction_output(desc, 0);
+               status = gpiod_direction_output_raw(desc, 0);
        else if (sysfs_streq(buf, "in"))
                status = gpiod_direction_input(desc);
        else
@@ -1457,26 +1458,14 @@ EXPORT_SYMBOL_GPL(gpiochip_remove_pin_ranges);
  * on each other, and help provide better diagnostics in debugfs.
  * They're called even less than the "set direction" calls.
  */
-static int gpiod_request(struct gpio_desc *desc, const char *label)
+static int __gpiod_request(struct gpio_desc *desc, const char *label)
 {
-       struct gpio_chip        *chip;
-       int                     status = -EPROBE_DEFER;
+       struct gpio_chip        *chip = desc->chip;
+       int                     status;
        unsigned long           flags;
 
-       if (!desc) {
-               pr_warn("%s: invalid GPIO\n", __func__);
-               return -EINVAL;
-       }
-
        spin_lock_irqsave(&gpio_lock, flags);
 
-       chip = desc->chip;
-       if (chip == NULL)
-               goto done;
-
-       if (!try_module_get(chip->owner))
-               goto done;
-
        /* NOTE:  gpio_request() can be called in early boot,
         * before IRQs are enabled, for non-sleeping (SOC) GPIOs.
         */
@@ -1486,7 +1475,6 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)
                status = 0;
        } else {
                status = -EBUSY;
-               module_put(chip->owner);
                goto done;
        }
 
@@ -1498,7 +1486,6 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)
 
                if (status < 0) {
                        desc_set_label(desc, NULL);
-                       module_put(chip->owner);
                        clear_bit(FLAG_REQUESTED, &desc->flags);
                        goto done;
                }
@@ -1509,10 +1496,35 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)
                gpiod_get_direction(desc);
                spin_lock_irqsave(&gpio_lock, flags);
        }
+done:
+       spin_unlock_irqrestore(&gpio_lock, flags);
+       return status;
+}
+
+static int gpiod_request(struct gpio_desc *desc, const char *label)
+{
+       int status = -EPROBE_DEFER;
+       struct gpio_chip *chip;
+
+       if (!desc) {
+               pr_warn("%s: invalid GPIO\n", __func__);
+               return -EINVAL;
+       }
+
+       chip = desc->chip;
+       if (!chip)
+               goto done;
+
+       if (try_module_get(chip->owner)) {
+               status = __gpiod_request(desc, label);
+               if (status < 0)
+                       module_put(chip->owner);
+       }
+
 done:
        if (status)
                gpiod_dbg(desc, "%s: status %d\n", __func__, status);
-       spin_unlock_irqrestore(&gpio_lock, flags);
+
        return status;
 }
 
@@ -1522,18 +1534,14 @@ int gpio_request(unsigned gpio, const char *label)
 }
 EXPORT_SYMBOL_GPL(gpio_request);
 
-static void gpiod_free(struct gpio_desc *desc)
+static bool __gpiod_free(struct gpio_desc *desc)
 {
+       bool                    ret = false;
        unsigned long           flags;
        struct gpio_chip        *chip;
 
        might_sleep();
 
-       if (!desc) {
-               WARN_ON(extra_checks);
-               return;
-       }
-
        gpiod_unexport(desc);
 
        spin_lock_irqsave(&gpio_lock, flags);
@@ -1547,15 +1555,23 @@ static void gpiod_free(struct gpio_desc *desc)
                        spin_lock_irqsave(&gpio_lock, flags);
                }
                desc_set_label(desc, NULL);
-               module_put(desc->chip->owner);
                clear_bit(FLAG_ACTIVE_LOW, &desc->flags);
                clear_bit(FLAG_REQUESTED, &desc->flags);
                clear_bit(FLAG_OPEN_DRAIN, &desc->flags);
                clear_bit(FLAG_OPEN_SOURCE, &desc->flags);
-       } else
-               WARN_ON(extra_checks);
+               ret = true;
+       }
 
        spin_unlock_irqrestore(&gpio_lock, flags);
+       return ret;
+}
+
+static void gpiod_free(struct gpio_desc *desc)
+{
+       if (desc && __gpiod_free(desc))
+               module_put(desc->chip->owner);
+       else
+               WARN_ON(extra_checks);
 }
 
 void gpio_free(unsigned gpio)
@@ -1590,7 +1606,7 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
        if (flags & GPIOF_DIR_IN)
                err = gpiod_direction_input(desc);
        else
-               err = gpiod_direction_output(desc,
+               err = gpiod_direction_output_raw(desc,
                                (flags & GPIOF_INIT_HIGH) ? 1 : 0);
 
        if (err)
@@ -1677,6 +1693,37 @@ const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset)
 }
 EXPORT_SYMBOL_GPL(gpiochip_is_requested);
 
+/**
+ * gpiochip_request_own_desc - Allow GPIO chip to request its own descriptor
+ * @desc: GPIO descriptor to request
+ * @label: label for the GPIO
+ *
+ * Function allows GPIO chip drivers to request and use their own GPIO
+ * descriptors via gpiolib API. Difference to gpiod_request() is that this
+ * function will not increase reference count of the GPIO chip module. This
+ * allows the GPIO chip module to be unloaded as needed (we assume that the
+ * GPIO chip driver handles freeing the GPIOs it has requested).
+ */
+int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label)
+{
+       if (!desc || !desc->chip)
+               return -EINVAL;
+
+       return __gpiod_request(desc, label);
+}
+
+/**
+ * gpiochip_free_own_desc - Free GPIO requested by the chip driver
+ * @desc: GPIO descriptor to free
+ *
+ * Function frees the given GPIO requested previously with
+ * gpiochip_request_own_desc().
+ */
+void gpiochip_free_own_desc(struct gpio_desc *desc)
+{
+       if (desc)
+               __gpiod_free(desc);
+}
 
 /* Drivers MUST set GPIO direction before making get/set calls.  In
  * some cases this is done in early boot, before IRQs are enabled.
@@ -1756,28 +1803,13 @@ fail:
 }
 EXPORT_SYMBOL_GPL(gpiod_direction_input);
 
-/**
- * gpiod_direction_output - set the GPIO direction to input
- * @desc:      GPIO to set to output
- * @value:     initial output value of the GPIO
- *
- * Set the direction of the passed GPIO to output, such as gpiod_set_value() can
- * be called safely on it. The initial value of the output must be specified.
- *
- * Return 0 in case of success, else an error code.
- */
-int gpiod_direction_output(struct gpio_desc *desc, int value)
+static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value)
 {
        unsigned long           flags;
        struct gpio_chip        *chip;
        int                     status = -EINVAL;
        int offset;
 
-       if (!desc || !desc->chip) {
-               pr_warn("%s: invalid GPIO\n", __func__);
-               return -EINVAL;
-       }
-
        /* GPIOs used for IRQs shall not be set as output */
        if (test_bit(FLAG_USED_AS_IRQ, &desc->flags)) {
                gpiod_err(desc,
@@ -1840,6 +1872,50 @@ fail:
                gpiod_dbg(desc, "%s: gpio status %d\n", __func__, status);
        return status;
 }
+
+/**
+ * gpiod_direction_output_raw - set the GPIO direction to output
+ * @desc:      GPIO to set to output
+ * @value:     initial output value of the GPIO
+ *
+ * Set the direction of the passed GPIO to output, such as gpiod_set_value() can
+ * be called safely on it. The initial value of the output must be specified
+ * as raw value on the physical line without regard for the ACTIVE_LOW status.
+ *
+ * Return 0 in case of success, else an error code.
+ */
+int gpiod_direction_output_raw(struct gpio_desc *desc, int value)
+{
+       if (!desc || !desc->chip) {
+               pr_warn("%s: invalid GPIO\n", __func__);
+               return -EINVAL;
+       }
+       return _gpiod_direction_output_raw(desc, value);
+}
+EXPORT_SYMBOL_GPL(gpiod_direction_output_raw);
+
+/**
+ * gpiod_direction_output - set the GPIO direction to output
+ * @desc:      GPIO to set to output
+ * @value:     initial output value of the GPIO
+ *
+ * Set the direction of the passed GPIO to output, such as gpiod_set_value() can
+ * be called safely on it. The initial value of the output must be specified
+ * as the logical value of the GPIO, i.e. taking its ACTIVE_LOW status into
+ * account.
+ *
+ * Return 0 in case of success, else an error code.
+ */
+int gpiod_direction_output(struct gpio_desc *desc, int value)
+{
+       if (!desc || !desc->chip) {
+               pr_warn("%s: invalid GPIO\n", __func__);
+               return -EINVAL;
+       }
+       if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
+               value = !value;
+       return _gpiod_direction_output_raw(desc, value);
+}
 EXPORT_SYMBOL_GPL(gpiod_direction_output);
 
 /**
@@ -2137,10 +2213,7 @@ EXPORT_SYMBOL_GPL(gpiod_to_irq);
  * @gpio: the GPIO line to lock as used for IRQ
  *
  * This is used directly by GPIO drivers that want to lock down
- * a certain GPIO line to be used as IRQs, for example in the
- * .to_irq() callback of their gpio_chip, or in the .irq_enable()
- * of its irq_chip implementation if the GPIO is known from that
- * code.
+ * a certain GPIO line to be used for IRQs.
  */
 int gpiod_lock_as_irq(struct gpio_desc *desc)
 {
@@ -2161,7 +2234,7 @@ EXPORT_SYMBOL_GPL(gpiod_lock_as_irq);
 
 int gpio_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
 {
-       return gpiod_lock_as_irq(gpiochip_offset_to_desc(chip, offset));
+       return gpiod_lock_as_irq(gpiochip_get_desc(chip, offset));
 }
 EXPORT_SYMBOL_GPL(gpio_lock_as_irq);
 
@@ -2183,7 +2256,7 @@ EXPORT_SYMBOL_GPL(gpiod_unlock_as_irq);
 
 void gpio_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)
 {
-       return gpiod_unlock_as_irq(gpiochip_offset_to_desc(chip, offset));
+       return gpiod_unlock_as_irq(gpiochip_get_desc(chip, offset));
 }
 EXPORT_SYMBOL_GPL(gpio_unlock_as_irq);
 
@@ -2404,7 +2477,7 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
                        return ERR_PTR(-EINVAL);
                }
 
-               desc = gpiochip_offset_to_desc(chip, p->chip_hwnum);
+               desc = gpiochip_get_desc(chip, p->chip_hwnum);
                *flags = p->flags;
 
                return desc;