]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Input: synaptics-rmi4 - add rmi_enable/disable_irq
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>
Wed, 30 Nov 2016 01:42:13 +0000 (17:42 -0800)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Wed, 30 Nov 2016 17:03:13 +0000 (09:03 -0800)
Set the .enabled boolean and trigger an event processing when enabling
for edge-triggered systems.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
drivers/input/rmi4/rmi_driver.c
drivers/input/rmi4/rmi_driver.h
include/linux/rmi.h

index 2b17d8cb3d10a7ea768b1ad1506966b4e86b708d..f04fc4152c1fcdef0b6044ca883f77cbf0dfd209 100644 (file)
@@ -215,6 +215,7 @@ static irqreturn_t rmi_irq_fn(int irq, void *dev_id)
 static int rmi_irq_init(struct rmi_device *rmi_dev)
 {
        struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
+       struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
        int irq_flags = irq_get_trigger_type(pdata->irq);
        int ret;
 
@@ -232,6 +233,8 @@ static int rmi_irq_init(struct rmi_device *rmi_dev)
                return ret;
        }
 
+       data->enabled = true;
+
        return 0;
 }
 
@@ -866,17 +869,54 @@ err_put_fn:
        return error;
 }
 
-int rmi_driver_suspend(struct rmi_device *rmi_dev, bool enable_wake)
+void rmi_enable_irq(struct rmi_device *rmi_dev, bool clear_wake)
 {
        struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
+       struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
        int irq = pdata->irq;
-       int retval = 0;
+       int irq_flags;
+       int retval;
 
-       retval = rmi_suspend_functions(rmi_dev);
-       if (retval)
-               dev_warn(&rmi_dev->dev, "Failed to suspend functions: %d\n",
-                       retval);
+       mutex_lock(&data->enabled_mutex);
+
+       if (data->enabled)
+               goto out;
+
+       enable_irq(irq);
+       data->enabled = true;
+       if (clear_wake && device_may_wakeup(rmi_dev->xport->dev)) {
+               retval = disable_irq_wake(irq);
+               if (!retval)
+                       dev_warn(&rmi_dev->dev,
+                                "Failed to disable irq for wake: %d\n",
+                                retval);
+       }
+
+       /*
+        * Call rmi_process_interrupt_requests() after enabling irq,
+        * otherwise we may lose interrupt on edge-triggered systems.
+        */
+       irq_flags = irq_get_trigger_type(pdata->irq);
+       if (irq_flags & IRQ_TYPE_EDGE_BOTH)
+               rmi_process_interrupt_requests(rmi_dev);
+
+out:
+       mutex_unlock(&data->enabled_mutex);
+}
+
+void rmi_disable_irq(struct rmi_device *rmi_dev, bool enable_wake)
+{
+       struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
+       struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
+       int irq = pdata->irq;
+       int retval;
+
+       mutex_lock(&data->enabled_mutex);
+
+       if (!data->enabled)
+               goto out;
 
+       data->enabled = false;
        disable_irq(irq);
        if (enable_wake && device_may_wakeup(rmi_dev->xport->dev)) {
                retval = enable_irq_wake(irq);
@@ -885,24 +925,30 @@ int rmi_driver_suspend(struct rmi_device *rmi_dev, bool enable_wake)
                                 "Failed to enable irq for wake: %d\n",
                                 retval);
        }
+
+out:
+       mutex_unlock(&data->enabled_mutex);
+}
+
+int rmi_driver_suspend(struct rmi_device *rmi_dev, bool enable_wake)
+{
+       int retval;
+
+       retval = rmi_suspend_functions(rmi_dev);
+       if (retval)
+               dev_warn(&rmi_dev->dev, "Failed to suspend functions: %d\n",
+                       retval);
+
+       rmi_disable_irq(rmi_dev, enable_wake);
        return retval;
 }
 EXPORT_SYMBOL_GPL(rmi_driver_suspend);
 
 int rmi_driver_resume(struct rmi_device *rmi_dev, bool clear_wake)
 {
-       struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
-       int irq = pdata->irq;
        int retval;
 
-       enable_irq(irq);
-       if (clear_wake && device_may_wakeup(rmi_dev->xport->dev)) {
-               retval = disable_irq_wake(irq);
-               if (!retval)
-                       dev_warn(&rmi_dev->dev,
-                                "Failed to disable irq for wake: %d\n",
-                                retval);
-       }
+       rmi_enable_irq(rmi_dev, clear_wake);
 
        retval = rmi_resume_functions(rmi_dev);
        if (retval)
@@ -916,10 +962,8 @@ EXPORT_SYMBOL_GPL(rmi_driver_resume);
 static int rmi_driver_remove(struct device *dev)
 {
        struct rmi_device *rmi_dev = to_rmi_device(dev);
-       struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
-       int irq = pdata->irq;
 
-       disable_irq(irq);
+       rmi_disable_irq(rmi_dev, false);
 
        rmi_f34_remove_sysfs(rmi_dev);
        rmi_free_function_list(rmi_dev);
@@ -1108,6 +1152,7 @@ static int rmi_driver_probe(struct device *dev)
        }
 
        mutex_init(&data->irq_mutex);
+       mutex_init(&data->enabled_mutex);
 
        retval = rmi_probe_interrupts(data);
        if (retval)
index 5b201f369505a941ce29a138ba5eb9f3a0d490fe..c9fe3d3deef3756b0795fa01cee44949c73c3506 100644 (file)
@@ -101,6 +101,8 @@ int rmi_scan_pdt(struct rmi_device *rmi_dev, void *ctx,
                 int (*callback)(struct rmi_device *rmi_dev, void *ctx,
                 const struct pdt_entry *entry));
 int rmi_probe_interrupts(struct rmi_driver_data *data);
+void rmi_enable_irq(struct rmi_device *rmi_dev, bool clear_wake);
+void rmi_disable_irq(struct rmi_device *rmi_dev, bool enable_wake);
 int rmi_init_functions(struct rmi_driver_data *data);
 int rmi_initial_reset(struct rmi_device *rmi_dev, void *ctx,
                      const struct pdt_entry *pdt);
index 0b118ab47b8d3c929ac22fdd00cdc2349b20d1df..621f098f12438233d743a3c2c5ced25b58f0d1df 100644 (file)
@@ -356,6 +356,7 @@ struct rmi_driver_data {
        u8 num_tx_electrodes;
 
        bool enabled;
+       struct mutex enabled_mutex;
 };
 
 int rmi_register_transport_device(struct rmi_transport_dev *xport);