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

Commit 1f221265 authored by Ramprasad Katkam's avatar Ramprasad Katkam Committed by Gerrit - the friendly Code Review server
Browse files

asoc: swr: master controller fixes for tanggu



Add locking for soundwire fifo operation as same
function call can be used at a time by a different thread
like mbhc, and fix register definitions in header.
Add soundwire slave interrupt clear registers as part of
slave interrupt event in master interrupt handler.

Change-Id: I94d9b7ac09192dbf8aa3248d35956b380430ee0b
Signed-off-by: default avatarRamprasad Katkam <katkam@codeaurora.org>
parent a72eb784
Loading
Loading
Loading
Loading
+82 −25
Original line number Original line Diff line number Diff line
@@ -59,8 +59,8 @@ enum {
#define TRUE 1
#define TRUE 1
#define FALSE 0
#define FALSE 0


#define SWRM_MAX_PORT_REG    40
#define SWRM_MAX_PORT_REG    120
#define SWRM_MAX_INIT_REG    8
#define SWRM_MAX_INIT_REG    10


#define SWR_MSTR_MAX_REG_ADDR	0x1740
#define SWR_MSTR_MAX_REG_ADDR	0x1740
#define SWR_MSTR_START_REG_ADDR	0x00
#define SWR_MSTR_START_REG_ADDR	0x00
@@ -304,11 +304,13 @@ static int swr_master_bulk_write(struct swr_mstr_ctrl *swrm, u32 *reg_addr,
	if (swrm->bulk_write)
	if (swrm->bulk_write)
		swrm->bulk_write(swrm->handle, reg_addr, val, length);
		swrm->bulk_write(swrm->handle, reg_addr, val, length);
	else {
	else {
		mutex_lock(&swrm->iolock);
		for (i = 0; i < length; i++) {
		for (i = 0; i < length; i++) {
		/* wait for FIFO WR command to complete to avoid overflow */
		/* wait for FIFO WR command to complete to avoid overflow */
			usleep_range(100, 105);
			usleep_range(100, 105);
			swr_master_write(swrm, reg_addr[i], val[i]);
			swr_master_write(swrm, reg_addr[i], val[i]);
		}
		}
		mutex_unlock(&swrm->iolock);
	}
	}
	return 0;
	return 0;
}
}
@@ -403,6 +405,7 @@ static int swrm_cmd_fifo_rd_cmd(struct swr_mstr_ctrl *swrm, int *cmd_data,
	u32 val;
	u32 val;
	u32 retry_attempt = 0;
	u32 retry_attempt = 0;


	mutex_lock(&swrm->iolock);
	val = swrm_get_packed_reg_val(&swrm->rcmd_id, len, dev_addr, reg_addr);
	val = swrm_get_packed_reg_val(&swrm->rcmd_id, len, dev_addr, reg_addr);
	/* wait for FIFO RD to complete to avoid overflow */
	/* wait for FIFO RD to complete to avoid overflow */
	usleep_range(100, 105);
	usleep_range(100, 105);
@@ -411,9 +414,9 @@ static int swrm_cmd_fifo_rd_cmd(struct swr_mstr_ctrl *swrm, int *cmd_data,
	usleep_range(250, 255);
	usleep_range(250, 255);
retry_read:
retry_read:
	*cmd_data = swr_master_read(swrm, SWRM_CMD_FIFO_RD_FIFO_ADDR);
	*cmd_data = swr_master_read(swrm, SWRM_CMD_FIFO_RD_FIFO_ADDR);
	dev_dbg(swrm->dev,
	dev_dbg(swrm->dev, "%s: reg: 0x%x, cmd_id: 0x%x, rcmd_id: 0x%x, \
		"%s: reg: 0x%x, cmd_id: 0x%x, dev_num: 0x%x, cmd_data: 0x%x\n",
		dev_num: 0x%x, cmd_data: 0x%x\n", __func__, reg_addr,
		__func__, reg_addr, cmd_id, dev_addr, *cmd_data);
		cmd_id, swrm->rcmd_id, dev_addr, *cmd_data);
	if ((((*cmd_data) & 0xF00) >> 8) != swrm->rcmd_id) {
	if ((((*cmd_data) & 0xF00) >> 8) != swrm->rcmd_id) {
		if (retry_attempt < MAX_FIFO_RD_FAIL_RETRY) {
		if (retry_attempt < MAX_FIFO_RD_FAIL_RETRY) {
			/* wait 500 us before retry on fifo read failure */
			/* wait 500 us before retry on fifo read failure */
@@ -421,10 +424,17 @@ static int swrm_cmd_fifo_rd_cmd(struct swr_mstr_ctrl *swrm, int *cmd_data,
			retry_attempt++;
			retry_attempt++;
			goto retry_read;
			goto retry_read;
		} else {
		} else {
			dev_err_ratelimited(swrm->dev, "%s: reg: 0x%x, cmd_id: 0x%x, \
				rcmd_id: 0x%x, dev_num: 0x%x, cmd_data: 0x%x\n",
				__func__, reg_addr, cmd_id, swrm->rcmd_id,
				dev_addr, *cmd_data);

			dev_err_ratelimited(swrm->dev,
			dev_err_ratelimited(swrm->dev,
				"%s: failed to read fifo\n", __func__);
				"%s: failed to read fifo\n", __func__);
		}
		}
	}
	}
	mutex_unlock(&swrm->iolock);

	return 0;
	return 0;
}
}


@@ -434,15 +444,16 @@ static int swrm_cmd_fifo_wr_cmd(struct swr_mstr_ctrl *swrm, u8 cmd_data,
	u32 val;
	u32 val;
	int ret = 0;
	int ret = 0;


	mutex_lock(&swrm->iolock);
	if (!cmd_id)
	if (!cmd_id)
		val = swrm_get_packed_reg_val(&swrm->wcmd_id, cmd_data,
		val = swrm_get_packed_reg_val(&swrm->wcmd_id, cmd_data,
					      dev_addr, reg_addr);
					      dev_addr, reg_addr);
	else
	else
		val = swrm_get_packed_reg_val(&cmd_id, cmd_data,
		val = swrm_get_packed_reg_val(&cmd_id, cmd_data,
					      dev_addr, reg_addr);
					      dev_addr, reg_addr);
	dev_dbg(swrm->dev,
	dev_dbg(swrm->dev, "%s: reg: 0x%x, cmd_id: 0x%x,wcmd_id: 0x%x, \
		"%s: reg: 0x%x, cmd_id: 0x%x, val:0x%x, dev_num: 0x%x, cmd_data: 0x%x\n",
			dev_num: 0x%x, cmd_data: 0x%x\n", __func__,
		__func__, reg_addr, cmd_id, val, dev_addr, cmd_data);
			reg_addr, cmd_id, swrm->wcmd_id,dev_addr, cmd_data);
	/* wait for FIFO WR command to complete to avoid overflow */
	/* wait for FIFO WR command to complete to avoid overflow */
	usleep_range(250, 255);
	usleep_range(250, 255);
	swr_master_write(swrm, SWRM_CMD_FIFO_WR_CMD, val);
	swr_master_write(swrm, SWRM_CMD_FIFO_WR_CMD, val);
@@ -457,6 +468,7 @@ static int swrm_cmd_fifo_wr_cmd(struct swr_mstr_ctrl *swrm, u8 cmd_data,
			wait_for_completion_timeout(&swrm->broadcast,
			wait_for_completion_timeout(&swrm->broadcast,
						    (2 * HZ/10));
						    (2 * HZ/10));
	}
	}
	mutex_unlock(&swrm->iolock);
	return ret;
	return ret;
}
}


@@ -472,7 +484,7 @@ static int swrm_read(struct swr_master *master, u8 dev_num, u16 reg_addr,
		dev_err(&master->dev, "%s: swrm is NULL\n", __func__);
		dev_err(&master->dev, "%s: swrm is NULL\n", __func__);
		return -EINVAL;
		return -EINVAL;
	}
	}

	pm_runtime_get_sync(swrm->dev);
	if (dev_num)
	if (dev_num)
		ret = swrm_cmd_fifo_rd_cmd(swrm, &val, dev_num, 0, reg_addr,
		ret = swrm_cmd_fifo_rd_cmd(swrm, &val, dev_num, 0, reg_addr,
					   len);
					   len);
@@ -482,8 +494,8 @@ static int swrm_read(struct swr_master *master, u8 dev_num, u16 reg_addr,
	if (!ret)
	if (!ret)
		*reg_val = (u8)val;
		*reg_val = (u8)val;


	pm_runtime_put_autosuspend(swrm->dev);
	pm_runtime_mark_last_busy(swrm->dev);
	pm_runtime_mark_last_busy(swrm->dev);

	return ret;
	return ret;
}
}


@@ -499,12 +511,14 @@ static int swrm_write(struct swr_master *master, u8 dev_num, u16 reg_addr,
		return -EINVAL;
		return -EINVAL;
	}
	}


	pm_runtime_get_sync(swrm->dev);
	if (dev_num)
	if (dev_num)
		ret = swrm_cmd_fifo_wr_cmd(swrm, reg_val, dev_num, 0, reg_addr);
		ret = swrm_cmd_fifo_wr_cmd(swrm, reg_val, dev_num, 0, reg_addr);
	else
	else
		swr_master_write(swrm, reg_addr, reg_val);
		swr_master_write(swrm, reg_addr, reg_val);
	pm_runtime_mark_last_busy(swrm->dev);


	pm_runtime_put_autosuspend(swrm->dev);
	pm_runtime_mark_last_busy(swrm->dev);
	return ret;
	return ret;
}
}


@@ -524,6 +538,7 @@ static int swrm_bulk_write(struct swr_master *master, u8 dev_num, void *reg,
	if (len <= 0)
	if (len <= 0)
		return -EINVAL;
		return -EINVAL;


	pm_runtime_get_sync(swrm->dev);
	if (dev_num) {
	if (dev_num) {
		swr_fifo_reg = kcalloc(len, sizeof(u32), GFP_KERNEL);
		swr_fifo_reg = kcalloc(len, sizeof(u32), GFP_KERNEL);
		if (!swr_fifo_reg) {
		if (!swr_fifo_reg) {
@@ -560,6 +575,7 @@ static int swrm_bulk_write(struct swr_master *master, u8 dev_num, void *reg,
mem_fail:
mem_fail:
	kfree(swr_fifo_reg);
	kfree(swr_fifo_reg);
err:
err:
	pm_runtime_put_autosuspend(swrm->dev);
	pm_runtime_mark_last_busy(swrm->dev);
	pm_runtime_mark_last_busy(swrm->dev);
	return ret;
	return ret;
}
}
@@ -1022,6 +1038,26 @@ static int swrm_disconnect_port(struct swr_master *master,
	return 0;
	return 0;
}
}


static int swrm_find_alert_slave(struct swr_mstr_ctrl *swrm,
					int status, u8 *devnum)
{
	int i;
	bool found = false;

	for (i = 0; i < (swrm->master.num_dev + 1); i++) {
		if ((status & SWRM_MCP_SLV_STATUS_MASK) == SWR_ALERT) {
			*devnum = i;
			found = true;
			break;
		}
		status >>= 2;
	}
	if (found)
		return 0;
	else
		return -EINVAL;
}

static int swrm_check_slave_change_status(struct swr_mstr_ctrl *swrm,
static int swrm_check_slave_change_status(struct swr_mstr_ctrl *swrm,
					int status, u8 *devnum)
					int status, u8 *devnum)
{
{
@@ -1049,7 +1085,8 @@ static irqreturn_t swr_mstr_interrupt(int irq, void *dev)
{
{
	struct swr_mstr_ctrl *swrm = dev;
	struct swr_mstr_ctrl *swrm = dev;
	u32 value, intr_sts;
	u32 value, intr_sts;
	int status, chg_sts, i;
	u32 temp = 0;
	u32 status, chg_sts, i;
	u8 devnum = 0;
	u8 devnum = 0;
	int ret = IRQ_HANDLED;
	int ret = IRQ_HANDLED;
	struct swr_device *swr_dev;
	struct swr_device *swr_dev;
@@ -1067,13 +1104,16 @@ static irqreturn_t swr_mstr_interrupt(int irq, void *dev)
		if (!value)
		if (!value)
			continue;
			continue;


		swr_master_write(swrm, SWRM_INTERRUPT_CLEAR, value);
		switch (value) {
		switch (value) {
		case SWRM_INTERRUPT_STATUS_SLAVE_PEND_IRQ:
		case SWRM_INTERRUPT_STATUS_SLAVE_PEND_IRQ:
			dev_dbg(swrm->dev, "Trigger irq to slave device\n");
			dev_dbg(swrm->dev, "Trigger irq to slave device\n");
			status = swr_master_read(swrm, SWRM_MCP_SLV_STATUS);
			status = swr_master_read(swrm, SWRM_MCP_SLV_STATUS);
			swrm_check_slave_change_status(swrm, status,
			ret = swrm_find_alert_slave(swrm, status, &devnum);
								&devnum);
			if (ret) {
				dev_err(swrm->dev, "no slave alert found.\
						spurious interrupt\n");
				return ret;
			}
			list_for_each_entry(swr_dev, &mstr->devices, dev_list) {
			list_for_each_entry(swr_dev, &mstr->devices, dev_list) {
				if (swr_dev->dev_num != devnum)
				if (swr_dev->dev_num != devnum)
					continue;
					continue;
@@ -1082,6 +1122,12 @@ static irqreturn_t swr_mstr_interrupt(int irq, void *dev)
						irq_find_mapping(
						irq_find_mapping(
						swr_dev->slave_irq, 0));
						swr_dev->slave_irq, 0));
			}
			}
			swrm_cmd_fifo_rd_cmd(swrm, &temp, devnum, 0x0,
						SWRS_SCP_INT_STATUS_CLEAR_1, 1);
			swrm_cmd_fifo_wr_cmd(swrm, 0x4, devnum, 0x0,
						SWRS_SCP_INT_STATUS_CLEAR_1);
			swrm_cmd_fifo_wr_cmd(swrm, 0x0, devnum, 0x0,
						SWRS_SCP_INT_STATUS_CLEAR_1);
			break;
			break;
		case SWRM_INTERRUPT_STATUS_NEW_SLAVE_ATTACHED:
		case SWRM_INTERRUPT_STATUS_NEW_SLAVE_ATTACHED:
			dev_dbg(swrm->dev, "SWR new slave attached\n");
			dev_dbg(swrm->dev, "SWR new slave attached\n");
@@ -1160,7 +1206,8 @@ static irqreturn_t swr_mstr_interrupt(int irq, void *dev)
			break;
			break;
		}
		}
	}
	}

	swr_master_write(swrm, SWRM_INTERRUPT_CLEAR, intr_sts);
	swr_master_write(swrm, SWRM_INTERRUPT_CLEAR, 0x0);
	mutex_lock(&swrm->reslock);
	mutex_lock(&swrm->reslock);
	swrm_clk_request(swrm, false);
	swrm_clk_request(swrm, false);
	mutex_unlock(&swrm->reslock);
	mutex_unlock(&swrm->reslock);
@@ -1196,13 +1243,13 @@ static int swrm_get_logical_dev_num(struct swr_master *mstr, u64 dev_id,
		num_dev = swrm->num_dev;
		num_dev = swrm->num_dev;
	else
	else
		num_dev = mstr->num_dev;
		num_dev = mstr->num_dev;

	pm_runtime_get_sync(swrm->dev);
	pm_runtime_get_sync(swrm->dev);
	for (i = 1; i < (num_dev + 1); i++) {
	for (i = 1; i < (num_dev + 1); i++) {
		id = ((u64)(swr_master_read(swrm,
		id = ((u64)(swr_master_read(swrm,
			    SWRM_ENUMERATOR_SLAVE_DEV_ID_2(i))) << 32);
			    SWRM_ENUMERATOR_SLAVE_DEV_ID_2(i))) << 32);
		id |= swr_master_read(swrm,
		id |= swr_master_read(swrm,
					SWRM_ENUMERATOR_SLAVE_DEV_ID_1(i));
					SWRM_ENUMERATOR_SLAVE_DEV_ID_1(i));

		/*
		/*
		 * As pm_runtime_get_sync() brings all slaves out of reset
		 * As pm_runtime_get_sync() brings all slaves out of reset
		 * update logical device number for all slaves.
		 * update logical device number for all slaves.
@@ -1220,6 +1267,11 @@ static int swrm_get_logical_dev_num(struct swr_master *mstr, u64 dev_id,
					dev_dbg(swrm->dev,
					dev_dbg(swrm->dev,
						"%s: devnum %d is assigned for dev addr %lx\n",
						"%s: devnum %d is assigned for dev addr %lx\n",
						__func__, i, swr_dev->addr);
						__func__, i, swr_dev->addr);
					swrm_cmd_fifo_wr_cmd(swrm, 0xFF, i, 0xF,
						SWRS_SCP_INT_STATUS_CLEAR_1);
					swrm_cmd_fifo_wr_cmd(swrm, 0x4, i, 0xF,
						SWRS_SCP_INT_STATUS_MASK_1);

				}
				}
			}
			}
		}
		}
@@ -1256,10 +1308,6 @@ static int swrm_master_init(struct swr_mstr_ctrl *swrm)
	reg[len] = SWRM_ENUMERATOR_CFG_ADDR;
	reg[len] = SWRM_ENUMERATOR_CFG_ADDR;
	value[len++] = 1;
	value[len++] = 1;


	/* Mask soundwire interrupts */
	reg[len] = SWRM_INTERRUPT_MASK_ADDR;
	value[len++] = 0x1FFFD;

	/* Configure No pings */
	/* Configure No pings */
	val = swr_master_read(swrm, SWRM_MCP_CFG_ADDR);
	val = swr_master_read(swrm, SWRM_MCP_CFG_ADDR);
	val &= ~SWRM_MCP_CFG_MAX_NUM_OF_CMD_NO_PINGS_BMSK;
	val &= ~SWRM_MCP_CFG_MAX_NUM_OF_CMD_NO_PINGS_BMSK;
@@ -1272,15 +1320,22 @@ static int swrm_master_init(struct swr_mstr_ctrl *swrm)
	reg[len] = SWRM_CMD_FIFO_CFG_ADDR;
	reg[len] = SWRM_CMD_FIFO_CFG_ADDR;
	value[len++] = val;
	value[len++] = val;


	/* Set IRQ to PULSE */
	reg[len] = SWRM_MCP_BUS_CTRL_ADDR;
	reg[len] = SWRM_COMP_CFG_ADDR;
	value[len++] = 0x2;
	value[len++] = 0x02;


	/* Set IRQ to PULSE */
	reg[len] = SWRM_COMP_CFG_ADDR;
	reg[len] = SWRM_COMP_CFG_ADDR;
	value[len++] = 0x03;
	value[len++] = 0x03;


	reg[len] = SWRM_INTERRUPT_CLEAR;
	reg[len] = SWRM_INTERRUPT_CLEAR;
	value[len++] = 0x08;
	value[len++] = 0xFFFFFFFF;

	/* Mask soundwire interrupts */
	reg[len] = SWRM_INTERRUPT_MASK_ADDR;
	value[len++] = 0x1FFFD;

	reg[len] = SWR_MSTR_RX_SWRM_CPU_INTERRUPT_EN;
	value[len++] = 0x1;


	swr_master_bulk_write(swrm, reg, value, len);
	swr_master_bulk_write(swrm, reg, value, len);


@@ -1430,6 +1485,7 @@ static int swrm_probe(struct platform_device *pdev)
	mutex_init(&swrm->mlock);
	mutex_init(&swrm->mlock);
	mutex_init(&swrm->reslock);
	mutex_init(&swrm->reslock);
	mutex_init(&swrm->force_down_lock);
	mutex_init(&swrm->force_down_lock);
	mutex_init(&swrm->iolock);


	for (i = 0 ; i < SWR_MSTR_PORT_LEN; i++)
	for (i = 0 ; i < SWR_MSTR_PORT_LEN; i++)
		INIT_LIST_HEAD(&swrm->mport_cfg[i].port_req_list);
		INIT_LIST_HEAD(&swrm->mport_cfg[i].port_req_list);
@@ -1535,6 +1591,7 @@ static int swrm_probe(struct platform_device *pdev)
	mutex_destroy(&swrm->mlock);
	mutex_destroy(&swrm->mlock);
	mutex_destroy(&swrm->reslock);
	mutex_destroy(&swrm->reslock);
	mutex_destroy(&swrm->force_down_lock);
	mutex_destroy(&swrm->force_down_lock);
	mutex_destroy(&swrm->iolock);
err_pdata_fail:
err_pdata_fail:
err_memory_fail:
err_memory_fail:
	return ret;
	return ret;
+1 −0
Original line number Original line Diff line number Diff line
@@ -102,6 +102,7 @@ struct swr_mstr_ctrl {
	int clk_ref_count;
	int clk_ref_count;
	struct completion reset;
	struct completion reset;
	struct completion broadcast;
	struct completion broadcast;
	struct mutex iolock;
	struct mutex mlock;
	struct mutex mlock;
	struct mutex reslock;
	struct mutex reslock;
	u32 swrm_base_reg;
	u32 swrm_base_reg;
+9 −3
Original line number Original line Diff line number Diff line
@@ -114,6 +114,8 @@


#define SWRM_INTERRUPT_CLEAR		(SWRM_BASE_ADDRESS+0x00000208)
#define SWRM_INTERRUPT_CLEAR		(SWRM_BASE_ADDRESS+0x00000208)


#define SWR_MSTR_RX_SWRM_CPU_INTERRUPT_EN	(SWRM_BASE_ADDRESS+0x00000210)

#define SWRM_CMD_FIFO_WR_CMD		(SWRM_BASE_ADDRESS + 0x00000300)
#define SWRM_CMD_FIFO_WR_CMD		(SWRM_BASE_ADDRESS + 0x00000300)
#define SWRM_CMD_FIFO_WR_CMD_MASK	0xFFFFFFFF
#define SWRM_CMD_FIFO_WR_CMD_MASK	0xFFFFFFFF
#define SWRM_CMD_FIFO_RD_CMD		(SWRM_BASE_ADDRESS + 0x00000304)
#define SWRM_CMD_FIFO_RD_CMD		(SWRM_BASE_ADDRESS + 0x00000304)
@@ -185,7 +187,8 @@
							0x40*m)
							0x40*m)


#define SWRM_DP_BLOCK_CTRL_1(n)		(SWRM_BASE_ADDRESS + \
#define SWRM_DP_BLOCK_CTRL_1(n)		(SWRM_BASE_ADDRESS + \
							0x0000112C + 0x100*n)
							0x0000112C + \
							0x100*(n-1))


#define SWRM_DP_BLOCK_CTRL2_BANK(n, m)	(SWRM_BASE_ADDRESS + \
#define SWRM_DP_BLOCK_CTRL2_BANK(n, m)	(SWRM_BASE_ADDRESS + \
							0x00001130 + \
							0x00001130 + \
@@ -204,7 +207,7 @@




#define SWRM_DIN_DPn_PCM_PORT_CTRL(n) (SWRM_BASE_ADDRESS + \
#define SWRM_DIN_DPn_PCM_PORT_CTRL(n) (SWRM_BASE_ADDRESS + \
						0x00001054 + 0x100*n)
						0x00001054 + 0x100*(n-1))


#define SWRM_MAX_REGISTER SWRM_DIN_DPn_PCM_PORT_CTRL(7)
#define SWRM_MAX_REGISTER SWRM_DIN_DPn_PCM_PORT_CTRL(7)


@@ -214,8 +217,11 @@


#define SWRS_DP_REG_OFFSET(port, bank)		((0x100*port)+(0x10*bank))
#define SWRS_DP_REG_OFFSET(port, bank)		((0x100*port)+(0x10*bank))


#define SWRS_SCP_INT_STATUS_CLEAR_1             0x40
#define SWRS_SCP_INT_STATUS_MASK_1		0x41

#define SWRS_SCP_CONTROL				0x44
#define SWRS_SCP_CONTROL				0x44
#define SWRS_DP_BLOCK_CONTROL_1(n)		(SWRS_BASE_ADDRESS + 0x120 + \
#define SWRS_DP_BLOCK_CONTROL_1(n)		(SWRS_BASE_ADDRESS + 0x103 + \
						0x100 * n)
						0x100 * n)


#define SWRS_DP_CHANNEL_ENABLE_BANK(n, m)	(SWRS_BASE_ADDRESS + 0x120 + \
#define SWRS_DP_CHANNEL_ENABLE_BANK(n, m)	(SWRS_BASE_ADDRESS + 0x120 + \