[PATCH 4/6] gpiolib: override irq_enable/disable

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Hans Verkuil <hans.verkuil@xxxxxxxxx>

When using the gpiolib irqchip helpers install irq_enable/disable
hooks for the irqchip to ensure that gpiolib knows when the irq
is enabled or disabled, allowing drivers to disable the irq and then
use it as an output pin, and later switch the direction to input and
re-enable the irq.

Signed-off-by: Hans Verkuil <hans.verkuil@xxxxxxxxx>
---
 drivers/gpio/gpiolib.c      | 30 ++++++++++++++++++++++++++++++
 include/linux/gpio/driver.h | 14 ++++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 63db513c237a..c14f8fa6ab57 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1835,6 +1835,28 @@ static void gpiochip_irq_relres(struct irq_data *d)
 	gpiochip_relres_irq(chip, d->hwirq);
 }
 
+static void gpiochip_irq_enable(struct irq_data *d)
+{
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
+
+	gpiochip_enable_irq(chip, d->hwirq);
+	if (chip->irq.irq_enable)
+		chip->irq.irq_enable(d);
+	else
+		chip->irq.chip->irq_unmask(d);
+}
+
+static void gpiochip_irq_disable(struct irq_data *d)
+{
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
+
+	if (chip->irq.irq_disable)
+		chip->irq.irq_disable(d);
+	else
+		chip->irq.chip->irq_mask(d);
+	gpiochip_disable_irq(chip, d->hwirq);
+}
+
 static void gpiochip_set_irq_hooks(struct gpio_chip *gpiochip)
 {
 	struct irq_chip *irqchip = gpiochip->irq.chip;
@@ -1844,9 +1866,13 @@ static void gpiochip_set_irq_hooks(struct gpio_chip *gpiochip)
 
 	gpiochip->irq.irq_reqres = irqchip->irq_request_resources;
 	gpiochip->irq.irq_relres = irqchip->irq_release_resources;
+	gpiochip->irq.irq_enable = irqchip->irq_enable;
+	gpiochip->irq.irq_disable = irqchip->irq_disable;
 
 	irqchip->irq_request_resources = gpiochip_irq_reqres;
 	irqchip->irq_release_resources = gpiochip_irq_relres;
+	irqchip->irq_enable = gpiochip_irq_enable;
+	irqchip->irq_disable = gpiochip_irq_disable;
 }
 
 /**
@@ -1969,9 +1995,13 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
 	if (irqchip && irqchip->irq_request_resources == gpiochip_irq_reqres) {
 		irqchip->irq_request_resources = gpiochip->irq.irq_reqres;
 		irqchip->irq_release_resources = gpiochip->irq.irq_relres;
+		irqchip->irq_enable = gpiochip->irq.irq_enable;
+		irqchip->irq_disable = gpiochip->irq.irq_disable;
 	}
 	gpiochip->irq.irq_reqres = NULL;
 	gpiochip->irq.irq_relres = NULL;
+	gpiochip->irq.irq_enable = NULL;
+	gpiochip->irq.irq_disable = NULL;
 	gpiochip->irq.chip = NULL;
 
 	gpiochip_irqchip_free_valid_mask(gpiochip);
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index 24a1f9bc0ad2..536322b9d30e 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -152,6 +152,20 @@ struct gpio_irq_chip {
 	 * Store old irq_chip irq_release_resources callback
 	 */
 	void		(*irq_relres)(struct irq_data *d);
+
+	/**
+	 * @irq_enable:
+	 *
+	 * Store old irq_chip irq_enable callback
+	 */
+	void		(*irq_enable)(struct irq_data *data);
+
+	/**
+	 * @irq_disable:
+	 *
+	 * Store old irq_chip irq_disable callback
+	 */
+	void		(*irq_disable)(struct irq_data *data);
 };
 
 static inline struct gpio_irq_chip *to_gpio_irq_chip(struct irq_chip *chip)
-- 
2.18.0




[Index of Archives]     [Linux SPI]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux