ACPI / LPSS: Resume BYT/CHT I2C controllers from resume_noirq
[sfrench/cifs-2.6.git] / drivers / acpi / acpi_lpss.c
index 859b5b3dcdbfa04c392f46e56449a5113eeda3a2..10adb8cb3a3f27c4c563983a827457554686f7d5 100644 (file)
@@ -84,6 +84,7 @@ struct lpss_device_desc {
        size_t prv_size_override;
        struct property_entry *properties;
        void (*setup)(struct lpss_private_data *pdata);
+       bool resume_from_noirq;
 };
 
 static const struct lpss_device_desc lpss_dma_desc = {
@@ -293,12 +294,14 @@ static const struct lpss_device_desc byt_i2c_dev_desc = {
        .flags = LPSS_CLK | LPSS_SAVE_CTX,
        .prv_offset = 0x800,
        .setup = byt_i2c_setup,
+       .resume_from_noirq = true,
 };
 
 static const struct lpss_device_desc bsw_i2c_dev_desc = {
        .flags = LPSS_CLK | LPSS_SAVE_CTX | LPSS_NO_D3_DELAY,
        .prv_offset = 0x800,
        .setup = byt_i2c_setup,
+       .resume_from_noirq = true,
 };
 
 static const struct lpss_device_desc bsw_spi_dev_desc = {
@@ -472,6 +475,8 @@ struct lpss_device_links {
  */
 static const struct lpss_device_links lpss_device_links[] = {
        {"808622C1", "7", "80860F14", "3", DL_FLAG_PM_RUNTIME},
+       {"808622C1", "7", "LNXVIDEO", NULL, DL_FLAG_PM_RUNTIME},
+       {"80860F41", "5", "LNXVIDEO", NULL, DL_FLAG_PM_RUNTIME},
 };
 
 static bool hid_uid_match(struct acpi_device *adev,
@@ -1037,7 +1042,7 @@ static int acpi_lpss_resume(struct device *dev)
 }
 
 #ifdef CONFIG_PM_SLEEP
-static int acpi_lpss_suspend_late(struct device *dev)
+static int acpi_lpss_do_suspend_late(struct device *dev)
 {
        int ret;
 
@@ -1048,12 +1053,62 @@ static int acpi_lpss_suspend_late(struct device *dev)
        return ret ? ret : acpi_lpss_suspend(dev, device_may_wakeup(dev));
 }
 
-static int acpi_lpss_resume_early(struct device *dev)
+static int acpi_lpss_suspend_late(struct device *dev)
+{
+       struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));
+
+       if (pdata->dev_desc->resume_from_noirq)
+               return 0;
+
+       return acpi_lpss_do_suspend_late(dev);
+}
+
+static int acpi_lpss_suspend_noirq(struct device *dev)
+{
+       struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));
+       int ret;
+
+       if (pdata->dev_desc->resume_from_noirq) {
+               ret = acpi_lpss_do_suspend_late(dev);
+               if (ret)
+                       return ret;
+       }
+
+       return acpi_subsys_suspend_noirq(dev);
+}
+
+static int acpi_lpss_do_resume_early(struct device *dev)
 {
        int ret = acpi_lpss_resume(dev);
 
        return ret ? ret : pm_generic_resume_early(dev);
 }
+
+static int acpi_lpss_resume_early(struct device *dev)
+{
+       struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));
+
+       if (pdata->dev_desc->resume_from_noirq)
+               return 0;
+
+       return acpi_lpss_do_resume_early(dev);
+}
+
+static int acpi_lpss_resume_noirq(struct device *dev)
+{
+       struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));
+       int ret;
+
+       ret = acpi_subsys_resume_noirq(dev);
+       if (ret)
+               return ret;
+
+       if (!dev_pm_may_skip_resume(dev) && pdata->dev_desc->resume_from_noirq)
+               ret = acpi_lpss_do_resume_early(dev);
+
+       return ret;
+}
+
 #endif /* CONFIG_PM_SLEEP */
 
 static int acpi_lpss_runtime_suspend(struct device *dev)
@@ -1083,8 +1138,8 @@ static struct dev_pm_domain acpi_lpss_pm_domain = {
                .complete = acpi_subsys_complete,
                .suspend = acpi_subsys_suspend,
                .suspend_late = acpi_lpss_suspend_late,
-               .suspend_noirq = acpi_subsys_suspend_noirq,
-               .resume_noirq = acpi_subsys_resume_noirq,
+               .suspend_noirq = acpi_lpss_suspend_noirq,
+               .resume_noirq = acpi_lpss_resume_noirq,
                .resume_early = acpi_lpss_resume_early,
                .freeze = acpi_subsys_freeze,
                .freeze_late = acpi_subsys_freeze_late,