Skip to content

Commit

Permalink
soundwire: intel/cadence: update hardware reset sequence
Browse files Browse the repository at this point in the history
Combining hardware reset with the multi-link mode leads to a shortened
hardware reset pattern observed on the bus.

The updated hardware programming sequence is to first enable the clock
with the sync_arm/sync_go pattern, and only in a second step to issue
the hardware reset sequence. Since there is no longer a dependency
between sync_arm/sync_go and hw_reset, the behavior of
sdw_cdns_exit_reset() is changed to wait for the self-clearing
CONFIG_UPDATE to go back to zero,

Link: thesofproject/linux#4170
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Rander Wang <rander.wang@intel.com>
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Link: https://lore.kernel.org/r/20230518024119.164160-3-yung-chuan.liao@linux.intel.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
  • Loading branch information
plbossart authored and vinodkoul committed May 29, 2023
1 parent 46b56a5 commit ffc363d
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 17 deletions.
31 changes: 24 additions & 7 deletions drivers/soundwire/cadence_master.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,29 @@ static int cdns_config_update(struct sdw_cdns *cdns)
return ret;
}

/**
* sdw_cdns_config_update() - Update configurations
* @cdns: Cadence instance
*/
void sdw_cdns_config_update(struct sdw_cdns *cdns)
{
/* commit changes */
cdns_writel(cdns, CDNS_MCP_CONFIG_UPDATE, CDNS_MCP_CONFIG_UPDATE_BIT);
}
EXPORT_SYMBOL(sdw_cdns_config_update);

/**
* sdw_cdns_config_update_set_wait() - wait until configuration update bit is self-cleared
* @cdns: Cadence instance
*/
int sdw_cdns_config_update_set_wait(struct sdw_cdns *cdns)
{
/* the hardware recommendation is to wait at least 300us */
return cdns_set_wait(cdns, CDNS_MCP_CONFIG_UPDATE,
CDNS_MCP_CONFIG_UPDATE_BIT, 0);
}
EXPORT_SYMBOL(sdw_cdns_config_update_set_wait);

/*
* debugfs
*/
Expand Down Expand Up @@ -1116,13 +1139,7 @@ int sdw_cdns_exit_reset(struct sdw_cdns *cdns)
CDNS_MCP_CONTROL_HW_RST);

/* commit changes */
cdns_updatel(cdns, CDNS_MCP_CONFIG_UPDATE,
CDNS_MCP_CONFIG_UPDATE_BIT,
CDNS_MCP_CONFIG_UPDATE_BIT);

/* don't wait here */
return 0;

return cdns_config_update(cdns);
}
EXPORT_SYMBOL(sdw_cdns_exit_reset);

Expand Down
3 changes: 3 additions & 0 deletions drivers/soundwire/cadence_master.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,4 +199,7 @@ int cdns_set_sdw_stream(struct snd_soc_dai *dai,
void sdw_cdns_check_self_clearing_bits(struct sdw_cdns *cdns, const char *string,
bool initial_delay, int reset_iterations);

void sdw_cdns_config_update(struct sdw_cdns *cdns);
int sdw_cdns_config_update_set_wait(struct sdw_cdns *cdns);

#endif /* __SDW_CADENCE_H */
36 changes: 26 additions & 10 deletions drivers/soundwire/intel_bus_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,7 @@ int intel_start_bus(struct sdw_intel *sdw)
return ret;
}

ret = sdw_cdns_exit_reset(cdns);
if (ret < 0) {
dev_err(dev, "%s: unable to exit bus reset sequence: %d\n", __func__, ret);
return ret;
}
sdw_cdns_config_update(cdns);

if (bus->multi_link) {
ret = sdw_intel_sync_go(sdw);
Expand All @@ -43,6 +39,18 @@ int intel_start_bus(struct sdw_intel *sdw)
}
}

ret = sdw_cdns_config_update_set_wait(cdns);
if (ret < 0) {
dev_err(dev, "%s: CONFIG_UPDATE BIT still set\n", __func__);
return ret;
}

ret = sdw_cdns_exit_reset(cdns);
if (ret < 0) {
dev_err(dev, "%s: unable to exit bus reset sequence: %d\n", __func__, ret);
return ret;
}

ret = sdw_cdns_enable_interrupt(cdns, true);
if (ret < 0) {
dev_err(dev, "%s: cannot enable interrupts: %d\n", __func__, ret);
Expand Down Expand Up @@ -112,11 +120,7 @@ int intel_start_bus_after_reset(struct sdw_intel *sdw)
}

if (!clock_stop0) {
ret = sdw_cdns_exit_reset(cdns);
if (ret < 0) {
dev_err(dev, "unable to exit bus reset sequence during resume\n");
return ret;
}
sdw_cdns_config_update(cdns);

if (bus->multi_link) {
ret = sdw_intel_sync_go(sdw);
Expand All @@ -126,6 +130,18 @@ int intel_start_bus_after_reset(struct sdw_intel *sdw)
}
}

ret = sdw_cdns_config_update_set_wait(cdns);
if (ret < 0) {
dev_err(dev, "%s: CONFIG_UPDATE BIT still set\n", __func__);
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;
}

ret = sdw_cdns_enable_interrupt(cdns, true);
if (ret < 0) {
dev_err(dev, "cannot enable interrupts during resume\n");
Expand Down

0 comments on commit ffc363d

Please sign in to comment.