soundwire: qcom: add software workaround for bus clash interrupt assertion

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>
Link: https://lore.kernel.org/r/20230525133812.30841-4-srinivas.kandagatla@linaro.org
Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
Srinivas Kandagatla 2023-05-25 14:38:11 +01:00 committed by Vinod Koul
parent 9ac4a4441a
commit 671ca2ef12
1 changed files with 34 additions and 22 deletions

View File

@ -790,6 +790,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;
@ -838,16 +858,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);
@ -1623,26 +1655,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);