summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/soundwire/cadence_master.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c
index 37e16199933c..613c63359413 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -866,6 +866,24 @@ int sdw_cdns_exit_reset(struct sdw_cdns *cdns)
EXPORT_SYMBOL(sdw_cdns_exit_reset);
/**
+ * sdw_cdns_enable_slave_interrupt() - Enable SDW slave interrupts
+ * @cdns: Cadence instance
+ * @state: boolean for true/false
+ */
+static void cdns_enable_slave_interrupts(struct sdw_cdns *cdns, bool state)
+{
+ u32 mask;
+
+ mask = cdns_readl(cdns, CDNS_MCP_INTMASK);
+ if (state)
+ mask |= CDNS_MCP_INT_SLAVE_MASK;
+ else
+ mask &= ~CDNS_MCP_INT_SLAVE_MASK;
+
+ cdns_writel(cdns, CDNS_MCP_INTMASK, mask);
+}
+
+/**
* sdw_cdns_enable_interrupt() - Enable SDW interrupts
* @cdns: Cadence instance
* @state: True if we are trying to enable interrupt.
@@ -1263,6 +1281,13 @@ int sdw_cdns_clock_stop(struct sdw_cdns *cdns, bool block_wake)
}
/*
+ * Before entering clock stop we mask the Slave
+ * interrupts. This helps avoid having to deal with e.g. a
+ * Slave becoming UNATTACHED while the clock is being stopped
+ */
+ cdns_enable_slave_interrupts(cdns, false);
+
+ /*
* For specific platforms, it is required to be able to put
* master into a state in which it ignores wake-up trials
* in clock stop state
@@ -1339,6 +1364,9 @@ int sdw_cdns_clock_restart(struct sdw_cdns *cdns, bool bus_reset)
{
int ret;
+ /* unmask Slave interrupts that were masked when stopping the clock */
+ cdns_enable_slave_interrupts(cdns, true);
+
ret = cdns_clear_bit(cdns, CDNS_MCP_CONTROL,
CDNS_MCP_CONTROL_CLK_STOP_CLR);
if (ret < 0) {