|
@@ -1458,26 +1458,14 @@ EXPORT_SYMBOL_GPL(gpiochip_remove_pin_ranges);
|
|
* on each other, and help provide better diagnostics in debugfs.
|
|
* on each other, and help provide better diagnostics in debugfs.
|
|
* They're called even less than the "set direction" calls.
|
|
* 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;
|
|
unsigned long flags;
|
|
|
|
|
|
- if (!desc) {
|
|
|
|
- pr_warn("%s: invalid GPIO\n", __func__);
|
|
|
|
- return -EINVAL;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
spin_lock_irqsave(&gpio_lock, flags);
|
|
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,
|
|
/* NOTE: gpio_request() can be called in early boot,
|
|
* before IRQs are enabled, for non-sleeping (SOC) GPIOs.
|
|
* before IRQs are enabled, for non-sleeping (SOC) GPIOs.
|
|
*/
|
|
*/
|
|
@@ -1487,7 +1475,6 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)
|
|
status = 0;
|
|
status = 0;
|
|
} else {
|
|
} else {
|
|
status = -EBUSY;
|
|
status = -EBUSY;
|
|
- module_put(chip->owner);
|
|
|
|
goto done;
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1499,7 +1486,6 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)
|
|
|
|
|
|
if (status < 0) {
|
|
if (status < 0) {
|
|
desc_set_label(desc, NULL);
|
|
desc_set_label(desc, NULL);
|
|
- module_put(chip->owner);
|
|
|
|
clear_bit(FLAG_REQUESTED, &desc->flags);
|
|
clear_bit(FLAG_REQUESTED, &desc->flags);
|
|
goto done;
|
|
goto done;
|
|
}
|
|
}
|
|
@@ -1510,10 +1496,35 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)
|
|
gpiod_get_direction(desc);
|
|
gpiod_get_direction(desc);
|
|
spin_lock_irqsave(&gpio_lock, flags);
|
|
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:
|
|
done:
|
|
if (status)
|
|
if (status)
|
|
gpiod_dbg(desc, "%s: status %d\n", __func__, status);
|
|
gpiod_dbg(desc, "%s: status %d\n", __func__, status);
|
|
- spin_unlock_irqrestore(&gpio_lock, flags);
|
|
|
|
|
|
+
|
|
return status;
|
|
return status;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1523,18 +1534,14 @@ int gpio_request(unsigned gpio, const char *label)
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(gpio_request);
|
|
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;
|
|
unsigned long flags;
|
|
struct gpio_chip *chip;
|
|
struct gpio_chip *chip;
|
|
|
|
|
|
might_sleep();
|
|
might_sleep();
|
|
|
|
|
|
- if (!desc) {
|
|
|
|
- WARN_ON(extra_checks);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
gpiod_unexport(desc);
|
|
gpiod_unexport(desc);
|
|
|
|
|
|
spin_lock_irqsave(&gpio_lock, flags);
|
|
spin_lock_irqsave(&gpio_lock, flags);
|
|
@@ -1548,15 +1555,23 @@ static void gpiod_free(struct gpio_desc *desc)
|
|
spin_lock_irqsave(&gpio_lock, flags);
|
|
spin_lock_irqsave(&gpio_lock, flags);
|
|
}
|
|
}
|
|
desc_set_label(desc, NULL);
|
|
desc_set_label(desc, NULL);
|
|
- module_put(desc->chip->owner);
|
|
|
|
clear_bit(FLAG_ACTIVE_LOW, &desc->flags);
|
|
clear_bit(FLAG_ACTIVE_LOW, &desc->flags);
|
|
clear_bit(FLAG_REQUESTED, &desc->flags);
|
|
clear_bit(FLAG_REQUESTED, &desc->flags);
|
|
clear_bit(FLAG_OPEN_DRAIN, &desc->flags);
|
|
clear_bit(FLAG_OPEN_DRAIN, &desc->flags);
|
|
clear_bit(FLAG_OPEN_SOURCE, &desc->flags);
|
|
clear_bit(FLAG_OPEN_SOURCE, &desc->flags);
|
|
- } else
|
|
|
|
- WARN_ON(extra_checks);
|
|
|
|
|
|
+ ret = true;
|
|
|
|
+ }
|
|
|
|
|
|
spin_unlock_irqrestore(&gpio_lock, flags);
|
|
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)
|
|
void gpio_free(unsigned gpio)
|
|
@@ -1678,6 +1693,37 @@ const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset)
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(gpiochip_is_requested);
|
|
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
|
|
/* Drivers MUST set GPIO direction before making get/set calls. In
|
|
* some cases this is done in early boot, before IRQs are enabled.
|
|
* some cases this is done in early boot, before IRQs are enabled.
|