Merge tag 'for-linus-4.8-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git...
[cascardo/linux.git] / drivers / extcon / extcon-usb-gpio.c
index 2b2fecf..2512660 100644 (file)
 #include <linux/module.h>
 #include <linux/of_gpio.h>
 #include <linux/platform_device.h>
+#include <linux/pm_wakeirq.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
+#include <linux/acpi.h>
 
 #define USB_GPIO_DEBOUNCE_MS   20      /* ms */
 
@@ -91,7 +93,7 @@ static int usb_extcon_probe(struct platform_device *pdev)
        struct usb_extcon_info *info;
        int ret;
 
-       if (!np)
+       if (!np && !ACPI_HANDLE(dev))
                return -EINVAL;
 
        info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
@@ -141,7 +143,8 @@ static int usb_extcon_probe(struct platform_device *pdev)
        }
 
        platform_set_drvdata(pdev, info);
-       device_init_wakeup(dev, 1);
+       device_init_wakeup(dev, true);
+       dev_pm_set_wake_irq(dev, info->id_irq);
 
        /* Perform initial detection */
        usb_extcon_detect_cable(&info->wq_detcable.work);
@@ -155,6 +158,9 @@ static int usb_extcon_remove(struct platform_device *pdev)
 
        cancel_delayed_work_sync(&info->wq_detcable);
 
+       dev_pm_clear_wake_irq(&pdev->dev);
+       device_init_wakeup(&pdev->dev, false);
+
        return 0;
 }
 
@@ -164,12 +170,6 @@ static int usb_extcon_suspend(struct device *dev)
        struct usb_extcon_info *info = dev_get_drvdata(dev);
        int ret = 0;
 
-       if (device_may_wakeup(dev)) {
-               ret = enable_irq_wake(info->id_irq);
-               if (ret)
-                       return ret;
-       }
-
        /*
         * We don't want to process any IRQs after this point
         * as GPIOs used behind I2C subsystem might not be
@@ -185,13 +185,10 @@ static int usb_extcon_resume(struct device *dev)
        struct usb_extcon_info *info = dev_get_drvdata(dev);
        int ret = 0;
 
-       if (device_may_wakeup(dev)) {
-               ret = disable_irq_wake(info->id_irq);
-               if (ret)
-                       return ret;
-       }
-
        enable_irq(info->id_irq);
+       if (!device_may_wakeup(dev))
+               queue_delayed_work(system_power_efficient_wq,
+                                  &info->wq_detcable, 0);
 
        return ret;
 }
@@ -206,6 +203,12 @@ static const struct of_device_id usb_extcon_dt_match[] = {
 };
 MODULE_DEVICE_TABLE(of, usb_extcon_dt_match);
 
+static const struct platform_device_id usb_extcon_platform_ids[] = {
+       { .name = "extcon-usb-gpio", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, usb_extcon_platform_ids);
+
 static struct platform_driver usb_extcon_driver = {
        .probe          = usb_extcon_probe,
        .remove         = usb_extcon_remove,
@@ -214,6 +217,7 @@ static struct platform_driver usb_extcon_driver = {
                .pm     = &usb_extcon_pm_ops,
                .of_match_table = usb_extcon_dt_match,
        },
+       .id_table = usb_extcon_platform_ids,
 };
 
 module_platform_driver(usb_extcon_driver);