diff options
author | Srinivas Kandagatla <srinivas.kandagatla@linaro.org> | 2023-01-06 14:07:14 +0000 |
---|---|---|
committer | Srinivas Kandagatla <srinivas.kandagatla@linaro.org> | 2023-02-01 16:38:26 +0000 |
commit | 7a1ddb436a2a9a4fc2ac5c0418dd4d81f1648b43 (patch) | |
tree | bfe2d22184a82315bd7e162df2fdf925ee2cf3f2 | |
parent | f39ce17b03f4a1514483383408f6bfe17306cb52 (diff) |
soundwire: qcom: add software workaround for bus clash interrupt assertion
Sometimes Hardreset does not clear some of the registers,
this sometimes results in firing a bus clash interrupt.
Add workaround for this during power up sequence.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
-rw-r--r-- | drivers/soundwire/qcom.c | 55 |
1 files changed, 33 insertions, 22 deletions
diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c index fcc279bd5a97a..1ebc8dd2adb3e 100644 --- a/drivers/soundwire/qcom.c +++ b/drivers/soundwire/qcom.c @@ -699,6 +699,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 *swrm) +{ + int retry = SWRM_LINK_STATUS_RETRY_CNT; + int comp_sts; + + do { + swrm->reg_read(swrm, SWRM_COMP_STATUS, &comp_sts); + + if (comp_sts & SWRM_FRM_GEN_ENABLED) + return true; + + usleep_range(500, 510); + } while (retry--); + + dev_err(swrm->dev, "%s: link status %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; @@ -743,16 +763,27 @@ 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, SWRM_INTERRUPT_CLEAR, 0xFFFFFFFF); /* enable CPU IRQs */ if (ctrl->mmio) { ctrl->reg_write(ctrl, SWRM_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); @@ -1506,26 +1537,6 @@ static int qcom_swrm_remove(struct platform_device *pdev) return 0; } -static bool swrm_wait_for_frame_gen_enabled(struct qcom_swrm_ctrl *swrm) -{ - int retry = SWRM_LINK_STATUS_RETRY_CNT; - int comp_sts; - - do { - swrm->reg_read(swrm, SWRM_COMP_STATUS, &comp_sts); - - if (comp_sts & SWRM_FRM_GEN_ENABLED) - return true; - - usleep_range(500, 510); - } while (retry--); - - dev_err(swrm->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); |