From 8acf2189b6e2fc83790ecf8dd9c05341f78f19b3 Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Wed, 11 Dec 2019 16:58:20 +0800 Subject: [PATCH] soundwire: intel: refine runtime pm for SDW_INTEL_CLK_STOP_BUS_RESET When all the links are suspended, the HDaudio controller may suspend and the power rails to the SoundWire IP may be disabled, requiring a complete re-initialization/enumeration on resume. However, if one or more Masters remained active, the HDaudio controller will remain active and the power rails will remain enabled. As a result, during the link resume step we can check if the context was preserved by verifying if the clock was stopped, and avoid doing a complete bus reset and re-enumeration. Signed-off-by: Rander Wang --- drivers/soundwire/intel.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c index 32ff4395928039..7eb46eafdf8cd8 100644 --- a/drivers/soundwire/intel.c +++ b/drivers/soundwire/intel.c @@ -1696,6 +1696,8 @@ static int intel_resume_runtime(struct device *dev) struct sdw_cdns *cdns = dev_get_drvdata(dev); struct sdw_intel *sdw = cdns_to_intel(cdns); u32 clock_stop_quirks; + bool clock_stop0; + int status; int ret; if (cdns->bus.prop.hw_disabled) { @@ -1740,12 +1742,23 @@ static int intel_resume_runtime(struct device *dev) return ret; } + /* + * There is a exception condition for CLK_STOP_BUS_RESET + * case. If there is another master is working, all the masters + * are powered on for they are in the same power domain. + * Master can preserve its context for clock stop0, so there is + * no need to clear slave status and reset bus. + */ + clock_stop0 = sdw_cdns_is_clock_stop(&sdw->cdns); + /* * make sure all Slaves are tagged as UNATTACHED and * provide reason for reinitialization */ - sdw_clear_slave_status(&sdw->cdns.bus, - SDW_UNATTACH_REQUEST_MASTER_RESET); + if (!clock_stop0) { + status = SDW_UNATTACH_REQUEST_MASTER_RESET; + sdw_clear_slave_status(&sdw->cdns.bus, status); + } ret = sdw_cdns_enable_interrupt(cdns, true); if (ret < 0) { @@ -1753,7 +1766,7 @@ static int intel_resume_runtime(struct device *dev) return ret; } - ret = sdw_cdns_clock_restart(cdns, true); + ret = sdw_cdns_clock_restart(cdns, !clock_stop0); if (ret < 0) { dev_err(dev, "unable to restart clock during resume\n"); return ret;