summaryrefslogtreecommitdiff
path: root/drivers/gpio/gpio-zynq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio/gpio-zynq.c')
-rw-r--r--drivers/gpio/gpio-zynq.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c
index c0c53fdbf07d..c3145f91fda3 100644
--- a/drivers/gpio/gpio-zynq.c
+++ b/drivers/gpio/gpio-zynq.c
@@ -301,6 +301,48 @@ static void zynq_gpio_irq_unmask(struct irq_data *irq_data)
}
/**
+ * zynq_gpio_irq_ack - Acknowledge the interrupt of a gpio pin
+ * @irq_data: irq data containing irq number of gpio pin for the interrupt
+ * to ack
+ *
+ * This function calculates gpio pin number from irq number and sets the bit
+ * in the Interrupt Status Register of the corresponding bank, to ACK the irq.
+ */
+static void zynq_gpio_irq_ack(struct irq_data *irq_data)
+{
+ unsigned int device_pin_num, bank_num, bank_pin_num;
+ struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data);
+
+ device_pin_num = irq_data->hwirq;
+ zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num);
+ writel_relaxed(BIT(bank_pin_num),
+ gpio->base_addr + ZYNQ_GPIO_INTSTS_OFFSET(bank_num));
+}
+
+/**
+ * zynq_gpio_irq_enable - Enable the interrupts for a gpio pin
+ * @irq_data: irq data containing irq number of gpio pin for the interrupt
+ * to enable
+ *
+ * Clears the INTSTS bit and unmasks the given interrrupt.
+ */
+static void zynq_gpio_irq_enable(struct irq_data *irq_data)
+{
+ /*
+ * The Zynq GPIO controller does not disable interrupt detection when
+ * the interrupt is masked and only disables the propagation of the
+ * interrupt. This means when the controller detects an interrupt
+ * condition while the interrupt is logically disabled it will propagate
+ * that interrupt event once the interrupt is enabled. This will cause
+ * the interrupt consumer to see spurious interrupts to prevent this
+ * first make sure that the interrupt is not asserted and then enable
+ * it.
+ */
+ zynq_gpio_irq_ack(irq_data);
+ zynq_gpio_irq_unmask(irq_data);
+}
+
+/**
* zynq_gpio_set_irq_type - Set the irq type for a gpio pin
* @irq_data: irq data containing irq number of gpio pin
* @type: interrupt type that is to be set for the gpio pin
@@ -384,6 +426,7 @@ static int zynq_gpio_set_wake(struct irq_data *data, unsigned int on)
/* irq chip descriptor */
static struct irq_chip zynq_gpio_irqchip = {
.name = DRIVER_NAME,
+ .irq_enable = zynq_gpio_irq_enable,
.irq_mask = zynq_gpio_irq_mask,
.irq_unmask = zynq_gpio_irq_unmask,
.irq_set_type = zynq_gpio_set_irq_type,