bus: ti-sysc: Tag some modules resource providers for noirq suspend
authorTony Lindgren <tony@atomide.com>
Mon, 16 Apr 2018 17:26:46 +0000 (10:26 -0700)
committerTony Lindgren <tony@atomide.com>
Tue, 1 May 2018 13:54:17 +0000 (06:54 -0700)
Modules that provide resources for other modules need to be suspended
and resumed in the noirq calls. Tag the resource providing modules.

Signed-off-by: Tony Lindgren <tony@atomide.com>
drivers/bus/ti-sysc.c
include/linux/platform_data/ti-sysc.h

index f27b182384cd53fe4b55d87990b677564f63000c..1f90b91dbfae6e6890559cb831f4e126ab639ac4 100644 (file)
@@ -665,6 +665,10 @@ static int sysc_suspend(struct device *dev)
 
        ddata = dev_get_drvdata(dev);
 
+       if (ddata->cfg.quirks & (SYSC_QUIRK_RESOURCE_PROVIDER |
+                                SYSC_QUIRK_LEGACY_IDLE))
+               return 0;
+
        if (!ddata->enabled)
                return 0;
 
@@ -678,6 +682,58 @@ static int sysc_resume(struct device *dev)
        struct sysc *ddata;
 
        ddata = dev_get_drvdata(dev);
+
+       if (ddata->cfg.quirks & (SYSC_QUIRK_RESOURCE_PROVIDER |
+                                SYSC_QUIRK_LEGACY_IDLE))
+               return 0;
+
+       if (ddata->needs_resume) {
+               dev_dbg(ddata->dev, "%s %s\n", __func__,
+                       ddata->name ? ddata->name : "");
+
+               ddata->needs_resume = false;
+
+               return sysc_runtime_resume(dev);
+       }
+
+       return 0;
+}
+
+static int sysc_noirq_suspend(struct device *dev)
+{
+       struct sysc *ddata;
+
+       ddata = dev_get_drvdata(dev);
+
+       if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE)
+               return 0;
+
+       if (!(ddata->cfg.quirks & SYSC_QUIRK_RESOURCE_PROVIDER))
+               return 0;
+
+       if (!ddata->enabled)
+               return 0;
+
+       dev_dbg(ddata->dev, "%s %s\n", __func__,
+               ddata->name ? ddata->name : "");
+
+       ddata->needs_resume = true;
+
+       return sysc_runtime_suspend(dev);
+}
+
+static int sysc_noirq_resume(struct device *dev)
+{
+       struct sysc *ddata;
+
+       ddata = dev_get_drvdata(dev);
+
+       if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE)
+               return 0;
+
+       if (!(ddata->cfg.quirks & SYSC_QUIRK_RESOURCE_PROVIDER))
+               return 0;
+
        if (ddata->needs_resume) {
                ddata->needs_resume = false;
 
@@ -690,6 +746,7 @@ static int sysc_resume(struct device *dev)
 
 static const struct dev_pm_ops sysc_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(sysc_suspend, sysc_resume)
+       SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(sysc_noirq_suspend, sysc_noirq_resume)
        SET_RUNTIME_PM_OPS(sysc_runtime_suspend,
                           sysc_runtime_resume,
                           NULL)
@@ -721,6 +778,26 @@ struct sysc_revision_quirk {
        }
 
 static const struct sysc_revision_quirk sysc_revision_quirks[] = {
+       /* These need to use noirq_suspend */
+       SYSC_QUIRK("control", 0, 0, 0x10, -1, 0x40000900, 0xffffffff,
+                  SYSC_QUIRK_RESOURCE_PROVIDER),
+       SYSC_QUIRK("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xffffffff,
+                  SYSC_QUIRK_RESOURCE_PROVIDER),
+       SYSC_QUIRK("mcspi", 0, 0, 0x10, -1, 0x40300a0b, 0xffffffff,
+                  SYSC_QUIRK_RESOURCE_PROVIDER),
+       SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x40000100, 0xffffffff,
+                  SYSC_QUIRK_RESOURCE_PROVIDER),
+       SYSC_QUIRK("ocp2scp", 0, 0, 0x10, 0x14, 0x50060005, 0xffffffff,
+                  SYSC_QUIRK_RESOURCE_PROVIDER),
+       SYSC_QUIRK("padconf", 0, 0, 0x10, -1, 0x4fff0800, 0xffffffff,
+                  SYSC_QUIRK_RESOURCE_PROVIDER),
+       SYSC_QUIRK("scm", 0, 0, 0x10, -1, 0x40000900, 0xffffffff,
+                  SYSC_QUIRK_RESOURCE_PROVIDER),
+       SYSC_QUIRK("scrm", 0, 0, -1, -1, 0x00000010, 0xffffffff,
+                  SYSC_QUIRK_RESOURCE_PROVIDER),
+       SYSC_QUIRK("sdma", 0, 0, 0x2c, 0x28, 0x00010900, 0xffffffff,
+                  SYSC_QUIRK_RESOURCE_PROVIDER),
+
        /* These drivers need to be fixed to not use pm_runtime_irq_safe() */
        SYSC_QUIRK("gpio", 0, 0, 0x10, 0x114, 0x50600801, 0xffffffff,
                   SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_OPT_CLKS_IN_RESET),
index 80ce28d4083247f145b63c940da5927ced1a5ae3..990aad477458113abf887af2f12e68bf56eec66d 100644 (file)
@@ -45,6 +45,7 @@ struct sysc_regbits {
        s8 emufree_shift;
 };
 
+#define SYSC_QUIRK_RESOURCE_PROVIDER   BIT(9)
 #define SYSC_QUIRK_LEGACY_IDLE         BIT(8)
 #define SYSC_QUIRK_RESET_STATUS                BIT(7)
 #define SYSC_QUIRK_NO_IDLE_ON_INIT     BIT(6)