Commit 671ca2ef authored by Srinivas Kandagatla's avatar Srinivas Kandagatla Committed by Vinod Koul
Browse files

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: default avatarSrinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20230525133812.30841-4-srinivas.kandagatla@linaro.org


Signed-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent 9ac4a444
Loading
Loading
Loading
Loading
+34 −22
Original line number Diff line number Diff line
@@ -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);