101 lines
3.3 KiB
Diff
101 lines
3.3 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Sanyog Kale <sanyog.r.kale@intel.com>
|
|
Date: Wed, 16 Aug 2017 12:26:31 +0530
|
|
Subject: [PATCH] SoundWire: Perform clock exit by setting clock stop clear
|
|
|
|
As per HW sequence, clock stop clear bit in mcp_control
|
|
register should be set and wait for bit to be cleared in
|
|
order to exit Master from clock stop. Hence adding the
|
|
support.
|
|
|
|
Change-Id: I3491c74a9969e4ce112ed6afc5eb366e1cc6737a
|
|
Signed-off-by: Sanyog Kale <sanyog.r.kale@intel.com>
|
|
Signed-off-by: Paul, Subhankar <subhankar.paul@intel.com>
|
|
---
|
|
drivers/sdw/sdw_cnl.c | 55 ++++++++++++++++++++++++++++++++++++++++++-
|
|
1 file changed, 54 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/sdw/sdw_cnl.c b/drivers/sdw/sdw_cnl.c
|
|
index 95eb7a8fab2b..c754edbe6564 100644
|
|
--- a/drivers/sdw/sdw_cnl.c
|
|
+++ b/drivers/sdw/sdw_cnl.c
|
|
@@ -485,7 +485,7 @@ static int sdw_init(struct cnl_sdw *sdw, bool is_first_init)
|
|
int mcp_config, mcp_control, sync_reg, mcp_clockctrl;
|
|
volatile int sync_update = 0;
|
|
int timeout = 10; /* Try 10 times before timing out */
|
|
- int ret = 0;
|
|
+ int ret = 0, mask;
|
|
|
|
/* Power up the link controller */
|
|
ret = sdw_power_up_link(sdw);
|
|
@@ -498,6 +498,56 @@ static int sdw_init(struct cnl_sdw *sdw, bool is_first_init)
|
|
/* Switch the ownership to Master IP from glue logic */
|
|
sdw_switch_to_mip(sdw);
|
|
|
|
+ /* write to MCP Control register to enable block wakeup */
|
|
+ mcp_control = cnl_sdw_reg_readl(data->sdw_regs, SDW_CNL_MCP_CONTROL);
|
|
+ mask = (MCP_CONTROL_BLOCKWAKEUP_MASK <<
|
|
+ MCP_CONTROL_BLOCKWAKEUP_SHIFT);
|
|
+ mcp_control &= ~mask;
|
|
+ cnl_sdw_reg_writel(data->sdw_regs, SDW_CNL_MCP_CONTROL, mcp_control);
|
|
+ do {
|
|
+ mcp_control = cnl_sdw_reg_readl(data->sdw_regs,
|
|
+ SDW_CNL_MCP_CONTROL);
|
|
+ if (!(mcp_control & mask))
|
|
+ break;
|
|
+
|
|
+ timeout--;
|
|
+ /* Wait 20ms before each time */
|
|
+ msleep(20);
|
|
+ } while (timeout != 0);
|
|
+
|
|
+ /* Write the MCP Control register to exit from clock stop */
|
|
+ mcp_control = cnl_sdw_reg_readl(data->sdw_regs, SDW_CNL_MCP_CONTROL);
|
|
+ mask = (MCP_CONTROL_CLOCKSTOPCLEAR_MASK <<
|
|
+ MCP_CONTROL_CLOCKSTOPCLEAR_SHIFT);
|
|
+ mcp_control |= mask;
|
|
+ cnl_sdw_reg_writel(data->sdw_regs, SDW_CNL_MCP_CONTROL, mcp_control);
|
|
+
|
|
+ /* Reset timeout */
|
|
+ timeout = 10;
|
|
+
|
|
+ /* Wait for clock stop exit bit to be self cleared */
|
|
+ do {
|
|
+ mcp_control = cnl_sdw_reg_readl(data->sdw_regs,
|
|
+ SDW_CNL_MCP_CONTROL);
|
|
+ if (!(mcp_control & mask))
|
|
+ break;
|
|
+ timeout--;
|
|
+ /* Wait 20ms before each time */
|
|
+ msleep(20);
|
|
+ } while (timeout != 0);
|
|
+
|
|
+ /* Read once again to confirm */
|
|
+ mcp_control = cnl_sdw_reg_readl(data->sdw_regs, SDW_CNL_MCP_CONTROL);
|
|
+ if (!(mcp_control & mask)) {
|
|
+ dev_dbg(&sdw->mstr->dev, "SDW ctrl %d exit clock stop success\n",
|
|
+ data->inst_id);
|
|
+ } else {
|
|
+ dev_err(&sdw->mstr->dev,
|
|
+ "Failed exit from clock stop SDW ctrl %d\n",
|
|
+ data->inst_id);
|
|
+ return -EIO;
|
|
+ }
|
|
+
|
|
/* Set SyncPRD period */
|
|
sync_reg = cnl_sdw_reg_readl(data->sdw_shim, SDW_CNL_SYNC);
|
|
sync_reg |= (SDW_CNL_DEFAULT_SYNC_PERIOD << CNL_SYNC_SYNCPRD_SHIFT);
|
|
@@ -506,6 +556,9 @@ static int sdw_init(struct cnl_sdw *sdw, bool is_first_init)
|
|
sync_reg |= (0x1 << CNL_SYNC_SYNCCPU_SHIFT);
|
|
cnl_sdw_reg_writel(data->sdw_shim, SDW_CNL_SYNC, sync_reg);
|
|
|
|
+ /* Reset timeout */
|
|
+ timeout = 10;
|
|
+
|
|
do {
|
|
sync_update = cnl_sdw_reg_readl(data->sdw_shim, SDW_CNL_SYNC);
|
|
if ((sync_update & CNL_SYNC_SYNCCPU_MASK) == 0)
|
|
--
|
|
https://clearlinux.org
|
|
|