Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 36 additions & 59 deletions drivers/soundwire/intel_bus_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,87 +77,64 @@ int intel_start_bus_after_reset(struct sdw_intel *sdw)
struct device *dev = sdw->cdns.dev;
struct sdw_cdns *cdns = &sdw->cdns;
struct sdw_bus *bus = &cdns->bus;
bool clock_stop0;
int status;
int ret;

/*
* An exception condition occurs for the CLK_STOP_BUS_RESET
* case if one or more masters remain active. In this condition,
* 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.
* make sure all Slaves are tagged as UNATTACHED and
* provide reason for reinitialization
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if it is the right direction. The clock may remain active, and the peripherals may remain attached when bus stops. It seems not be necessary to reset in that case.

*/
clock_stop0 = sdw_cdns_is_clock_stop(&sdw->cdns);

if (!clock_stop0) {

/*
* make sure all Slaves are tagged as UNATTACHED and
* provide reason for reinitialization
*/

status = SDW_UNATTACH_REQUEST_MASTER_RESET;
sdw_clear_slave_status(bus, status);

/*
* follow recommended programming flows to avoid
* timeouts when gsync is enabled
*/
if (bus->multi_link)
sdw_intel_sync_arm(sdw);
status = SDW_UNATTACH_REQUEST_MASTER_RESET;
sdw_clear_slave_status(bus, status);

/*
* Re-initialize the IP since it was powered-off
*/
sdw_cdns_init(&sdw->cdns);
/*
* follow recommended programming flows to avoid
* timeouts when gsync is enabled
*/
if (bus->multi_link)
sdw_intel_sync_arm(sdw);

} else {
ret = sdw_cdns_enable_interrupt(cdns, true);
if (ret < 0) {
dev_err(dev, "cannot enable interrupts during resume\n");
return ret;
}
}
/*
* Re-initialize the IP since it was powered-off
*/
sdw_cdns_init(&sdw->cdns);

ret = sdw_cdns_clock_restart(cdns, !clock_stop0);
ret = sdw_cdns_clock_restart(cdns, true);
if (ret < 0) {
dev_err(dev, "unable to restart clock during resume\n");
if (!clock_stop0)
sdw_cdns_enable_interrupt(cdns, false);
sdw_cdns_enable_interrupt(cdns, false);
return ret;
}

if (!clock_stop0) {
sdw_cdns_config_update(cdns);

if (bus->multi_link) {
ret = sdw_intel_sync_go(sdw);
if (ret < 0) {
dev_err(sdw->cdns.dev, "sync go failed during resume\n");
return ret;
}
}
sdw_cdns_config_update(cdns);

ret = sdw_cdns_config_update_set_wait(cdns);
if (bus->multi_link) {
ret = sdw_intel_sync_go(sdw);
if (ret < 0) {
dev_err(dev, "%s: CONFIG_UPDATE BIT still set\n", __func__);
dev_err(sdw->cdns.dev, "sync go failed 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_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");
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;
}

sdw_cdns_check_self_clearing_bits(cdns, __func__, true, INTEL_MASTER_RESET_ITERATIONS);

schedule_delayed_work(&cdns->attach_dwork,
Expand Down
Loading