lkml.org 
[lkml]   [2023]   [May]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH v2 3/4] soundwire: qcom: add software workaround for bus clash interrupt assertion
Date
Sometimes Hard reset does not clear some of the registers,
this sometimes results in firing a bus clash interrupt.
Add workaround for this during power up sequence, as
suggested by hardware manual.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
drivers/soundwire/qcom.c | 56 ++++++++++++++++++++++++----------------
1 file changed, 34 insertions(+), 22 deletions(-)

diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c
index adf025194a31..1d2a105cb77f 100644
--- a/drivers/soundwire/qcom.c
+++ b/drivers/soundwire/qcom.c
@@ -793,6 +793,26 @@ static irqreturn_t qcom_swrm_irq_handler(int irq, void *dev_id)
return ret;
}

+static bool swrm_wait_for_frame_gen_enabled(struct qcom_swrm_ctrl *ctrl)
+{
+ int retry = SWRM_LINK_STATUS_RETRY_CNT;
+ int comp_sts;
+
+ do {
+ ctrl->reg_read(ctrl, SWRM_COMP_STATUS, &comp_sts);
+
+ if (comp_sts & SWRM_FRM_GEN_ENABLED)
+ return true;
+
+ usleep_range(500, 510);
+ } while (retry--);
+
+ dev_err(ctrl->dev, "%s: link status not %s\n", __func__,
+ comp_sts & SWRM_FRM_GEN_ENABLED ? "connected" : "disconnected");
+
+ return false;
+}
+
static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl)
{
u32 val;
@@ -841,16 +861,28 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl)
SWRM_RD_WR_CMD_RETRIES);
}

+ /* COMP Enable */
+ ctrl->reg_write(ctrl, SWRM_COMP_CFG_ADDR, SWRM_COMP_CFG_ENABLE_MSK);
+
/* Set IRQ to PULSE */
ctrl->reg_write(ctrl, SWRM_COMP_CFG_ADDR,
- SWRM_COMP_CFG_IRQ_LEVEL_OR_PULSE_MSK |
- SWRM_COMP_CFG_ENABLE_MSK);
+ SWRM_COMP_CFG_IRQ_LEVEL_OR_PULSE_MSK);
+
+ ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CLEAR],
+ 0xFFFFFFFF);

/* enable CPU IRQs */
if (ctrl->mmio) {
ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CPU_EN],
SWRM_INTERRUPT_STATUS_RMSK);
}
+
+ /* Set IRQ to PULSE */
+ ctrl->reg_write(ctrl, SWRM_COMP_CFG_ADDR,
+ SWRM_COMP_CFG_IRQ_LEVEL_OR_PULSE_MSK |
+ SWRM_COMP_CFG_ENABLE_MSK);
+
+ swrm_wait_for_frame_gen_enabled(ctrl);
ctrl->slave_status = 0;
ctrl->reg_read(ctrl, SWRM_COMP_PARAMS, &val);
ctrl->rd_fifo_depth = FIELD_GET(SWRM_COMP_PARAMS_RD_FIFO_DEPTH, val);
@@ -1626,26 +1658,6 @@ static int qcom_swrm_remove(struct platform_device *pdev)
return 0;
}

-static bool swrm_wait_for_frame_gen_enabled(struct qcom_swrm_ctrl *ctrl)
-{
- int retry = SWRM_LINK_STATUS_RETRY_CNT;
- int comp_sts;
-
- do {
- ctrl->reg_read(ctrl, SWRM_COMP_STATUS, &comp_sts);
-
- if (comp_sts & SWRM_FRM_GEN_ENABLED)
- return true;
-
- usleep_range(500, 510);
- } while (retry--);
-
- dev_err(ctrl->dev, "%s: link status not %s\n", __func__,
- comp_sts & SWRM_FRM_GEN_ENABLED ? "connected" : "disconnected");
-
- return false;
-}
-
static int __maybe_unused swrm_runtime_resume(struct device *dev)
{
struct qcom_swrm_ctrl *ctrl = dev_get_drvdata(dev);
--
2.21.0
\
 
 \ /
  Last update: 2023-05-25 15:39    [W:0.112 / U:0.660 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site