Skip to content

Commit ffc363d

Browse files
plbossartvinodkoul
authored andcommitted
soundwire: intel/cadence: update hardware reset sequence
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#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>
1 parent 46b56a5 commit ffc363d

3 files changed

Lines changed: 53 additions & 17 deletions

File tree

drivers/soundwire/cadence_master.c

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,29 @@ static int cdns_config_update(struct sdw_cdns *cdns)
283283
return ret;
284284
}
285285

286+
/**
287+
* sdw_cdns_config_update() - Update configurations
288+
* @cdns: Cadence instance
289+
*/
290+
void sdw_cdns_config_update(struct sdw_cdns *cdns)
291+
{
292+
/* commit changes */
293+
cdns_writel(cdns, CDNS_MCP_CONFIG_UPDATE, CDNS_MCP_CONFIG_UPDATE_BIT);
294+
}
295+
EXPORT_SYMBOL(sdw_cdns_config_update);
296+
297+
/**
298+
* sdw_cdns_config_update_set_wait() - wait until configuration update bit is self-cleared
299+
* @cdns: Cadence instance
300+
*/
301+
int sdw_cdns_config_update_set_wait(struct sdw_cdns *cdns)
302+
{
303+
/* the hardware recommendation is to wait at least 300us */
304+
return cdns_set_wait(cdns, CDNS_MCP_CONFIG_UPDATE,
305+
CDNS_MCP_CONFIG_UPDATE_BIT, 0);
306+
}
307+
EXPORT_SYMBOL(sdw_cdns_config_update_set_wait);
308+
286309
/*
287310
* debugfs
288311
*/
@@ -1116,13 +1139,7 @@ int sdw_cdns_exit_reset(struct sdw_cdns *cdns)
11161139
CDNS_MCP_CONTROL_HW_RST);
11171140

11181141
/* commit changes */
1119-
cdns_updatel(cdns, CDNS_MCP_CONFIG_UPDATE,
1120-
CDNS_MCP_CONFIG_UPDATE_BIT,
1121-
CDNS_MCP_CONFIG_UPDATE_BIT);
1122-
1123-
/* don't wait here */
1124-
return 0;
1125-
1142+
return cdns_config_update(cdns);
11261143
}
11271144
EXPORT_SYMBOL(sdw_cdns_exit_reset);
11281145

drivers/soundwire/cadence_master.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,4 +199,7 @@ int cdns_set_sdw_stream(struct snd_soc_dai *dai,
199199
void sdw_cdns_check_self_clearing_bits(struct sdw_cdns *cdns, const char *string,
200200
bool initial_delay, int reset_iterations);
201201

202+
void sdw_cdns_config_update(struct sdw_cdns *cdns);
203+
int sdw_cdns_config_update_set_wait(struct sdw_cdns *cdns);
204+
202205
#endif /* __SDW_CADENCE_H */

drivers/soundwire/intel_bus_common.c

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,7 @@ int intel_start_bus(struct sdw_intel *sdw)
2929
return ret;
3030
}
3131

32-
ret = sdw_cdns_exit_reset(cdns);
33-
if (ret < 0) {
34-
dev_err(dev, "%s: unable to exit bus reset sequence: %d\n", __func__, ret);
35-
return ret;
36-
}
32+
sdw_cdns_config_update(cdns);
3733

3834
if (bus->multi_link) {
3935
ret = sdw_intel_sync_go(sdw);
@@ -43,6 +39,18 @@ int intel_start_bus(struct sdw_intel *sdw)
4339
}
4440
}
4541

42+
ret = sdw_cdns_config_update_set_wait(cdns);
43+
if (ret < 0) {
44+
dev_err(dev, "%s: CONFIG_UPDATE BIT still set\n", __func__);
45+
return ret;
46+
}
47+
48+
ret = sdw_cdns_exit_reset(cdns);
49+
if (ret < 0) {
50+
dev_err(dev, "%s: unable to exit bus reset sequence: %d\n", __func__, ret);
51+
return ret;
52+
}
53+
4654
ret = sdw_cdns_enable_interrupt(cdns, true);
4755
if (ret < 0) {
4856
dev_err(dev, "%s: cannot enable interrupts: %d\n", __func__, ret);
@@ -112,11 +120,7 @@ int intel_start_bus_after_reset(struct sdw_intel *sdw)
112120
}
113121

114122
if (!clock_stop0) {
115-
ret = sdw_cdns_exit_reset(cdns);
116-
if (ret < 0) {
117-
dev_err(dev, "unable to exit bus reset sequence during resume\n");
118-
return ret;
119-
}
123+
sdw_cdns_config_update(cdns);
120124

121125
if (bus->multi_link) {
122126
ret = sdw_intel_sync_go(sdw);
@@ -126,6 +130,18 @@ int intel_start_bus_after_reset(struct sdw_intel *sdw)
126130
}
127131
}
128132

133+
ret = sdw_cdns_config_update_set_wait(cdns);
134+
if (ret < 0) {
135+
dev_err(dev, "%s: CONFIG_UPDATE BIT still set\n", __func__);
136+
return ret;
137+
}
138+
139+
ret = sdw_cdns_exit_reset(cdns);
140+
if (ret < 0) {
141+
dev_err(dev, "unable to exit bus reset sequence during resume\n");
142+
return ret;
143+
}
144+
129145
ret = sdw_cdns_enable_interrupt(cdns, true);
130146
if (ret < 0) {
131147
dev_err(dev, "cannot enable interrupts during resume\n");

0 commit comments

Comments
 (0)