From a320f41eac7b250c27db1c8071a984e584109ce1 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 17 Aug 2020 23:29:18 +0800 Subject: soundwire: intel: add CLK_STOP_TEARDOWN for pm_runtime suspend 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 Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20200817152923.3259-8-yung-chuan.liao@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/intel.c | 82 +++++++++++++++++++++++++++++------------------ 1 file changed, 51 insertions(+), 31 deletions(-) (limited to 'drivers/soundwire/intel.c') diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c index 3f9015dcb693..68c1cdfb7999 100644 --- a/drivers/soundwire/intel.c +++ b/drivers/soundwire/intel.c @@ -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; -- cgit v1.2.3