Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 64bb44c2 authored by Vatsal Bucha's avatar Vatsal Bucha Committed by Gerrit - the friendly Code Review server
Browse files

soc: swr-mstr: Avoid overflow during swr fifo read/write



Avoid swr fifo overflow by checking no. of outstanding
commands in fifo and comparing with fifo depth before
every read/write. If no. of commands is equal to fifo
depth then give some delay and retry. If no of outstanding
commands are still equal to fifo depth then flush fifo
and try writing/reading from fifo again.

Change-Id: I612203ce6879f5ffcffadc23650f5bba1d45856f
Signed-off-by: default avatarVatsal Bucha <vbucha@codeaurora.org>
parent 2fe71f51
Loading
Loading
Loading
Loading
+68 −0
Original line number Diff line number Diff line
@@ -84,6 +84,11 @@ enum {
	LPASS_AUDIO_CORE,
};

enum {
	SWRM_WR_CHECK_AVAIL,
	SWRM_RD_CHECK_AVAIL,
};

#define TRUE 1
#define FALSE 0

@@ -742,6 +747,52 @@ static u32 swrm_get_packed_reg_val(u8 *cmd_id, u8 cmd_data,
	return val;
}

static void swrm_wait_for_fifo_avail(struct swr_mstr_ctrl *swrm, int swrm_rd_wr)
{
	u32 fifo_outstanding_cmd;
	u8 fifo_retry_count = 10;

	if (swrm_rd_wr) {
		/* Check for fifo underflow during read */
		/* Check no of outstanding commands in fifo before read */
		fifo_outstanding_cmd = ((swr_master_read(swrm,
				SWRM_CMD_FIFO_STATUS) & 0x001F0000) >> 16);
		if (fifo_outstanding_cmd == 0) {
			while (fifo_retry_count) {
				usleep_range(50, 55);
				fifo_outstanding_cmd =
					((swr_master_read (swrm,
					  SWRM_CMD_FIFO_STATUS) & 0x001F0000)
					  >> 16);
				fifo_retry_count--;
				if (fifo_outstanding_cmd > 0)
					break;
			}
		}
		if (fifo_outstanding_cmd == 0)
			pr_err("%s err read underflow\n", __func__);
	} else {
		/* Check for fifo overflow during write */
		/* Check no of outstanding commands in fifo before write */
		fifo_outstanding_cmd = ((swr_master_read(swrm,
					 SWRM_CMD_FIFO_STATUS) & 0x00001F00)
					 >> 8);
		if (fifo_outstanding_cmd == swrm->wr_fifo_depth) {
			while (fifo_retry_count) {
				usleep_range(50, 55);
				fifo_outstanding_cmd =
				((swr_master_read(swrm, SWRM_CMD_FIFO_STATUS)
				  & 0x00001F00) >> 8);
				fifo_retry_count--;
				if (fifo_outstanding_cmd < swrm->wr_fifo_depth)
					break;
			}
		}
		if (fifo_outstanding_cmd == swrm->wr_fifo_depth)
			pr_err("%s err write overflow\n", __func__);
	}
}

static int swrm_cmd_fifo_rd_cmd(struct swr_mstr_ctrl *swrm, int *cmd_data,
				 u8 dev_addr, u8 cmd_id, u16 reg_addr,
				 u32 len)
@@ -755,12 +806,19 @@ static int swrm_cmd_fifo_rd_cmd(struct swr_mstr_ctrl *swrm, int *cmd_data,
		/* skip delay if read is handled in platform driver */
		swr_master_write(swrm, SWRM_CMD_FIFO_RD_CMD, val);
	} else {
		/*
		 * Check for outstanding cmd wrt. write fifo depth to avoid
		 * overflow as read will also increase write fifo cnt.
		 */
		swrm_wait_for_fifo_avail(swrm, SWRM_WR_CHECK_AVAIL);
		/* wait for FIFO RD to complete to avoid overflow */
		usleep_range(100, 105);
		swr_master_write(swrm, SWRM_CMD_FIFO_RD_CMD, val);
		/* wait for FIFO RD CMD complete to avoid overflow */
		usleep_range(250, 255);
	}
	/* Check if slave responds properly after FIFO RD is complete */
	swrm_wait_for_fifo_avail(swrm, SWRM_RD_CHECK_AVAIL);
retry_read:
	*cmd_data = swr_master_read(swrm, SWRM_CMD_FIFO_RD_FIFO_ADDR);
	dev_dbg(swrm->dev, "%s: reg: 0x%x, cmd_id: 0x%x, rcmd_id: 0x%x, \
@@ -807,6 +865,11 @@ static int swrm_cmd_fifo_wr_cmd(struct swr_mstr_ctrl *swrm, u8 cmd_data,
	dev_dbg(swrm->dev, "%s: reg: 0x%x, cmd_id: 0x%x,wcmd_id: 0x%x, \
			dev_num: 0x%x, cmd_data: 0x%x\n", __func__,
			reg_addr, cmd_id, swrm->wcmd_id,dev_addr, cmd_data);
	/*
	 * Check for outstanding cmd wrt. write fifo depth to avoid
	 * overflow.
	 */
	swrm_wait_for_fifo_avail(swrm, SWRM_WR_CHECK_AVAIL);
	swr_master_write(swrm, SWRM_CMD_FIFO_WR_CMD, val);
	/*
	 * wait for FIFO WR command to complete to avoid overflow
@@ -2764,6 +2827,11 @@ static int swrm_probe(struct platform_device *pdev)
	if (pdev->dev.of_node)
		of_register_swr_devices(&swrm->master);

	swrm->rd_fifo_depth = ((swr_master_read(swrm, SWRM_COMP_PARAMS)
				& SWRM_COMP_PARAMS_RD_FIFO_DEPTH) >> 15);
	swrm->wr_fifo_depth = ((swr_master_read(swrm, SWRM_COMP_PARAMS)
				& SWRM_COMP_PARAMS_WR_FIFO_DEPTH) >> 10);

#ifdef CONFIG_DEBUG_FS
	swrm->debugfs_swrm_dent = debugfs_create_dir(dev_name(&pdev->dev), 0);
	if (!IS_ERR(swrm->debugfs_swrm_dent)) {
+2 −0
Original line number Diff line number Diff line
@@ -185,6 +185,8 @@ struct swr_mstr_ctrl {
	int aud_core_clk_en;
	int clk_src;
	u32 disable_div2_clk_switch;
	u32 rd_fifo_depth;
	u32 wr_fifo_depth;
#ifdef CONFIG_DEBUG_FS
	struct dentry *debugfs_swrm_dent;
	struct dentry *debugfs_peek;