soundwire: intel: add CLK_STOP_TEARDOWN for pm_runtime suspend
authorPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Mon, 17 Aug 2020 15:29:18 +0000 (23:29 +0800)
committerVinod Koul <vkoul@kernel.org>
Tue, 18 Aug 2020 06:31:05 +0000 (12:01 +0530)
Now that we have options, add support for TEARDOWN mode (same
functionality as existing code)

All other modes will be added in follow-up patches.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Link: https://lore.kernel.org/r/20200817152923.3259-8-yung-chuan.liao@linux.intel.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
drivers/soundwire/intel.c
drivers/soundwire/intel.h
drivers/soundwire/intel_init.c

index 3f9015d..68c1cdf 100644 (file)
@@ -1548,6 +1548,7 @@ static int intel_suspend_runtime(struct device *dev)
        struct sdw_cdns *cdns = dev_get_drvdata(dev);
        struct sdw_intel *sdw = cdns_to_intel(cdns);
        struct sdw_bus *bus = &cdns->bus;
+       u32 clock_stop_quirks;
        int ret;
 
        if (bus->prop.hw_disabled) {
@@ -1556,21 +1557,31 @@ static int intel_suspend_runtime(struct device *dev)
                return 0;
        }
 
-       ret = sdw_cdns_enable_interrupt(cdns, false);
-       if (ret < 0) {
-               dev_err(dev, "cannot disable interrupts on suspend\n");
-               return ret;
-       }
+       clock_stop_quirks = sdw->link_res->clock_stop_quirks;
 
-       ret = intel_link_power_down(sdw);
-       if (ret) {
-               dev_err(dev, "Link power down failed: %d", ret);
-               return ret;
-       }
+       if (clock_stop_quirks & SDW_INTEL_CLK_STOP_TEARDOWN) {
 
-       intel_shim_wake(sdw, false);
+               ret = sdw_cdns_enable_interrupt(cdns, false);
+               if (ret < 0) {
+                       dev_err(dev, "cannot disable interrupts on suspend\n");
+                       return ret;
+               }
 
-       return 0;
+               ret = intel_link_power_down(sdw);
+               if (ret) {
+                       dev_err(dev, "Link power down failed: %d", ret);
+                       return ret;
+               }
+
+               intel_shim_wake(sdw, false);
+
+       } else {
+               dev_err(dev, "%s clock_stop_quirks %x unsupported\n",
+                       __func__, clock_stop_quirks);
+               ret = -EINVAL;
+       }
+
+       return ret;
 }
 
 static int intel_resume(struct device *dev)
@@ -1645,6 +1656,7 @@ static int intel_resume_runtime(struct device *dev)
        struct sdw_cdns *cdns = dev_get_drvdata(dev);
        struct sdw_intel *sdw = cdns_to_intel(cdns);
        struct sdw_bus *bus = &cdns->bus;
+       u32 clock_stop_quirks;
        int ret;
 
        if (bus->prop.hw_disabled) {
@@ -1653,28 +1665,36 @@ static int intel_resume_runtime(struct device *dev)
                return 0;
        }
 
-       ret = intel_init(sdw);
-       if (ret) {
-               dev_err(dev, "%s failed: %d", __func__, ret);
-               return ret;
-       }
+       clock_stop_quirks = sdw->link_res->clock_stop_quirks;
 
-       /*
-        * make sure all Slaves are tagged as UNATTACHED and provide
-        * reason for reinitialization
-        */
-       sdw_clear_slave_status(bus, SDW_UNATTACH_REQUEST_MASTER_RESET);
+       if (clock_stop_quirks & SDW_INTEL_CLK_STOP_TEARDOWN) {
+               ret = intel_init(sdw);
+               if (ret) {
+                       dev_err(dev, "%s failed: %d", __func__, ret);
+                       return ret;
+               }
 
-       ret = sdw_cdns_enable_interrupt(cdns, true);
-       if (ret < 0) {
-               dev_err(dev, "cannot enable interrupts during resume\n");
-               return ret;
-       }
+               /*
+                * make sure all Slaves are tagged as UNATTACHED and provide
+                * reason for reinitialization
+                */
+               sdw_clear_slave_status(bus, SDW_UNATTACH_REQUEST_MASTER_RESET);
 
-       ret = sdw_cdns_exit_reset(cdns);
-       if (ret < 0) {
-               dev_err(dev, "unable to exit bus reset sequence during resume\n");
-               return ret;
+               ret = sdw_cdns_enable_interrupt(cdns, true);
+               if (ret < 0) {
+                       dev_err(dev, "cannot enable interrupts during resume\n");
+                       return ret;
+               }
+
+               ret = sdw_cdns_exit_reset(cdns);
+               if (ret < 0) {
+                       dev_err(dev, "unable to exit bus reset sequence during resume\n");
+                       return ret;
+               }
+       } else {
+               dev_err(dev, "%s clock_stop_quirks %x unsupported\n",
+                       __func__, clock_stop_quirks);
+               ret = -EINVAL;
        }
 
        return ret;
index 4ea3d26..23daab9 100644 (file)
@@ -17,6 +17,7 @@
  * @dev: device implementing hw_params and free callbacks
  * @shim_lock: mutex to handle access to shared SHIM registers
  * @shim_mask: global pointer to check SHIM register initialization
+ * @clock_stop_quirks: mask defining requested behavior on pm_suspend
  * @cdns: Cadence master descriptor
  * @list: used to walk-through all masters exposed by the same controller
  */
@@ -31,6 +32,7 @@ struct sdw_intel_link_res {
        struct device *dev;
        struct mutex *shim_lock; /* protect shared registers */
        u32 *shim_mask;
+       u32 clock_stop_quirks;
        struct sdw_cdns *cdns;
        struct list_head list;
 };
index a1f2108..dd10507 100644 (file)
@@ -249,6 +249,7 @@ static struct sdw_intel_ctx
                link->ops = res->ops;
                link->dev = res->dev;
 
+               link->clock_stop_quirks = res->clock_stop_quirks;
                link->shim_lock = &ctx->shim_lock;
                link->shim_mask = &ctx->shim_mask;