gpio: pcf857x: handle only enabled irqs
[firefly-linux-kernel-4.4.55.git] / drivers / gpio / gpio-pcf857x.c
index 83db0e19ec7e6b4974b6c4d7be91f70a0009ef99..404f3c61ef9b19f43243d61eef656e8d81a899c9 100644 (file)
@@ -92,6 +92,7 @@ struct pcf857x {
        unsigned                out;            /* software latch */
        unsigned                status;         /* current status */
        unsigned int            irq_parent;
+       unsigned                irq_enabled;    /* enabled irqs */
 
        int (*write)(struct i2c_client *client, unsigned data);
        int (*read)(struct i2c_client *client);
@@ -195,7 +196,7 @@ static irqreturn_t pcf857x_irq(int irq, void *data)
         * interrupt source, just to avoid bad irqs
         */
 
-       change = (gpio->status ^ status);
+       change = (gpio->status ^ status) & gpio->irq_enabled;
        for_each_set_bit(i, &change, gpio->chip.ngpio)
                handle_nested_irq(irq_find_mapping(gpio->chip.irqdomain, i));
        gpio->status = status;
@@ -210,14 +211,10 @@ static irqreturn_t pcf857x_irq(int irq, void *data)
  */
 static void noop(struct irq_data *data) { }
 
-static unsigned int noop_ret(struct irq_data *data)
-{
-       return 0;
-}
-
 static int pcf857x_irq_set_wake(struct irq_data *data, unsigned int on)
 {
        struct pcf857x *gpio = irq_data_get_irq_chip_data(data);
+
        int error = 0;
 
        if (gpio->irq_parent) {
@@ -229,20 +226,47 @@ static int pcf857x_irq_set_wake(struct irq_data *data, unsigned int on)
                        gpio->irq_parent = 0;
                }
        }
-
        return error;
 }
 
+static void pcf857x_irq_enable(struct irq_data *data)
+{
+       struct pcf857x *gpio = irq_data_get_irq_chip_data(data);
+
+       gpio->irq_enabled |= (1 << data->hwirq);
+}
+
+static void pcf857x_irq_disable(struct irq_data *data)
+{
+       struct pcf857x *gpio = irq_data_get_irq_chip_data(data);
+
+       gpio->irq_enabled &= ~(1 << data->hwirq);
+}
+
+static void pcf857x_irq_bus_lock(struct irq_data *data)
+{
+       struct pcf857x *gpio = irq_data_get_irq_chip_data(data);
+
+       mutex_lock(&gpio->lock);
+}
+
+static void pcf857x_irq_bus_sync_unlock(struct irq_data *data)
+{
+       struct pcf857x *gpio = irq_data_get_irq_chip_data(data);
+
+       mutex_unlock(&gpio->lock);
+}
+
 static struct irq_chip pcf857x_irq_chip = {
        .name           = "pcf857x",
-       .irq_startup    = noop_ret,
-       .irq_shutdown   = noop,
-       .irq_enable     = noop,
-       .irq_disable    = noop,
+       .irq_enable     = pcf857x_irq_enable,
+       .irq_disable    = pcf857x_irq_disable,
        .irq_ack        = noop,
        .irq_mask       = noop,
        .irq_unmask     = noop,
        .irq_set_wake   = pcf857x_irq_set_wake,
+       .irq_bus_lock           = pcf857x_irq_bus_lock,
+       .irq_bus_sync_unlock    = pcf857x_irq_bus_sync_unlock,
 };
 
 /*-------------------------------------------------------------------------*/