浏览代码

msm: camera: sensor: Notify completion in error case

There is no need to wait till timeout in case of NACK or
underflow error irq is raised, so notify thread for rd_done
completion. Also, correct the error mask to catch the NACK
error for Master 1.

CRs-Fixed: 2598605
Change-Id: Ib8a16ee119dd81f1384283ac7e9f82d3ac2588bb
Signed-off-by: Jigarkumar Zala <[email protected]>
Signed-off-by: Depeng Shao <[email protected]>
Jigarkumar Zala 5 年之前
父节点
当前提交
fdb9ade9a8

+ 68 - 7
drivers/cam_sensor_module/cam_cci/cam_cci_core.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/module.h>
@@ -42,6 +42,9 @@ static void cam_cci_flush_queue(struct cci_device *cci_dev,
 	void __iomem *base = soc_info->reg_map[0].mem_base;
 
 	cam_io_w_mb(1 << master, base + CCI_HALT_REQ_ADDR);
+	if (!cci_dev->cci_master_info[master].status)
+		reinit_completion(&cci_dev->cci_master_info[master]
+			.reset_complete);
 	rc = wait_for_completion_timeout(
 		&cci_dev->cci_master_info[master].reset_complete, CCI_TIMEOUT);
 	if (rc < 0) {
@@ -51,6 +54,7 @@ static void cam_cci_flush_queue(struct cci_device *cci_dev,
 
 		/* Set reset pending flag to true */
 		cci_dev->cci_master_info[master].reset_pending = true;
+		cci_dev->cci_master_info[master].status = 0;
 
 		/* Set proper mask to RESET CMD address based on MASTER */
 		if (master == MASTER_0)
@@ -66,6 +70,7 @@ static void cam_cci_flush_queue(struct cci_device *cci_dev,
 			CCI_TIMEOUT);
 		if (rc <= 0)
 			CAM_ERR(CAM_CCI, "wait failed %d", rc);
+		cci_dev->cci_master_info[master].status = 0;
 	}
 }
 
@@ -127,8 +132,10 @@ static int32_t cam_cci_validate_queue(struct cci_device *cci_dev,
 			return rc;
 		}
 		rc = cci_dev->cci_master_info[master].status;
-		if (rc < 0)
+		if (rc < 0) {
 			CAM_ERR(CAM_CCI, "Failed rc %d", rc);
+			cci_dev->cci_master_info[master].status = 0;
+		}
 	}
 
 	return rc;
@@ -246,14 +253,16 @@ static uint32_t cam_cci_wait(struct cci_device *cci_dev,
 		cam_cci_dump_registers(cci_dev, master, queue);
 #endif
 		CAM_ERR(CAM_CCI, "wait for queue: %d", queue);
-		if (rc == 0)
+		if (rc == 0) {
 			rc = -ETIMEDOUT;
-		cam_cci_flush_queue(cci_dev, master);
-		return rc;
+			cam_cci_flush_queue(cci_dev, master);
+			return rc;
+		}
 	}
 	rc = cci_dev->cci_master_info[master].status;
 	if (rc < 0) {
 		CAM_ERR(CAM_CCI, "failed rc %d", rc);
+		cci_dev->cci_master_info[master].status = 0;
 		return rc;
 	}
 
@@ -851,7 +860,8 @@ static int32_t cam_cci_data_queue(struct cci_device *cci_dev,
 
 	rc = cam_cci_transfer_end(cci_dev, master, queue);
 	if (rc < 0) {
-		CAM_ERR(CAM_CCI, "failed rc %d", rc);
+		CAM_ERR(CAM_CCI, "Slave: 0x%x failed rc %d",
+			(c_ctrl->cci_info->sid << 1), rc);
 		return rc;
 	}
 
@@ -918,6 +928,7 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
 	mutex_unlock(&cci_dev->cci_master_info[master].mutex);
 
 	mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);
+	reinit_completion(&cci_dev->cci_master_info[master].report_q[queue]);
 	/*
 	 * Call validate queue to make sure queue is empty before starting.
 	 * If this call fails, don't proceed with i2c_read call. This is to
@@ -1024,6 +1035,14 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
 			goto rel_mutex_q;
 		}
 
+		if (cci_dev->cci_master_info[master].status) {
+			CAM_ERR(CAM_CCI, "Error with Salve: 0x%x",
+				(c_ctrl->cci_info->sid << 1));
+			rc = -EINVAL;
+			cci_dev->cci_master_info[master].status = 0;
+			goto rel_mutex_q;
+		}
+
 		read_words = cam_io_r_mb(base +
 			CCI_I2C_M0_READ_BUF_LEVEL_ADDR + master * 0x100);
 		if (read_words <= 0) {
@@ -1104,6 +1123,14 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
 					cam_cci_flush_queue(cci_dev, master);
 				goto rel_mutex_q;
 			}
+
+			if (cci_dev->cci_master_info[master].status) {
+				CAM_ERR(CAM_CCI, "Error with Slave 0x%x",
+					(c_ctrl->cci_info->sid << 1));
+				rc = -EINVAL;
+				cci_dev->cci_master_info[master].status = 0;
+				goto rel_mutex_q;
+			}
 			break;
 		}
 	}
@@ -1183,6 +1210,7 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
 	mutex_unlock(&cci_dev->cci_master_info[master].mutex);
 
 	mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);
+	reinit_completion(&cci_dev->cci_master_info[master].report_q[queue]);
 	/*
 	 * Call validate queue to make sure queue is empty before starting.
 	 * If this call fails, don't proceed with i2c_read call. This is to
@@ -1290,6 +1318,14 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
 		rc = 0;
 	}
 
+	if (cci_dev->cci_master_info[master].status) {
+		CAM_ERR(CAM_CCI, "ERROR with Slave 0x%x:",
+			(c_ctrl->cci_info->sid << 1));
+		rc = -EINVAL;
+		cci_dev->cci_master_info[master].status = 0;
+		goto rel_mutex_q;
+	}
+
 	read_words = cam_io_r_mb(base +
 		CCI_I2C_M0_READ_BUF_LEVEL_ADDR + master * 0x100);
 	exp_words = ((read_cfg->num_byte / 4) + 1);
@@ -1384,6 +1420,8 @@ static int32_t cam_cci_i2c_write(struct v4l2_subdev *sd,
 		goto ERROR;
 	}
 	mutex_unlock(&cci_dev->cci_master_info[master].mutex);
+
+	reinit_completion(&cci_dev->cci_master_info[master].report_q[queue]);
 	/*
 	 * Call validate queue to make sure queue is empty before starting.
 	 * If this call fails, don't proceed with i2c_write call. This is to
@@ -1546,6 +1584,7 @@ static int32_t cam_cci_read_bytes(struct v4l2_subdev *sd,
 	 * THRESHOLD irq's, we reinit the threshold wait before
 	 * we load the burst read cmd.
 	 */
+	reinit_completion(&cci_dev->cci_master_info[master].rd_done);
 	reinit_completion(&cci_dev->cci_master_info[master].th_complete);
 
 	CAM_DBG(CAM_CCI, "Bytes to read %u", read_bytes);
@@ -1687,7 +1726,29 @@ int32_t cam_cci_core_cfg(struct v4l2_subdev *sd,
 {
 	int32_t rc = 0;
 	struct cci_device *cci_dev = v4l2_get_subdevdata(sd);
-	CAM_DBG(CAM_CCI, "cmd %d", cci_ctrl->cmd);
+	enum cci_i2c_master_t master = MASTER_MAX;
+
+	if (!cci_dev) {
+		CAM_ERR(CAM_CCI, "CCI_DEV IS NULL");
+		return -EINVAL;
+	}
+
+	if (!cci_ctrl) {
+		CAM_ERR(CAM_CCI, "CCI_CTRL IS NULL");
+		return -EINVAL;
+	}
+
+	master = cci_ctrl->cci_info->cci_i2c_master;
+	if (master >= MASTER_MAX) {
+		CAM_ERR(CAM_CCI, "INVALID MASTER: %d", master);
+		return -EINVAL;
+	}
+
+	if (cci_dev->cci_master_info[master].status < 0) {
+		CAM_WARN(CAM_CCI, "CCI hardware is resetting");
+		return -EAGAIN;
+	}
+	CAM_DBG(CAM_CCI, "master = %d, cmd = %d", master, cci_ctrl->cmd);
 
 	switch (cci_ctrl->cmd) {
 	case MSM_CCI_INIT:

+ 37 - 11
drivers/cam_sensor_module/cam_cci/cam_cci_dev.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
  */
 
 #include "cam_cci_dev.h"
@@ -82,7 +82,9 @@ irqreturn_t cam_cci_irq(int irq_num, void *data)
 				false;
 			if (!cci_master_info->status)
 				complete(&cci_master_info->reset_complete);
-			cci_master_info->status = 0;
+
+			complete_all(&cci_master_info->rd_done);
+			complete_all(&cci_master_info->th_complete);
 		}
 		if (cci_dev->cci_master_info[MASTER_1].reset_pending == true) {
 			cci_master_info = &cci_dev->cci_master_info[MASTER_1];
@@ -90,7 +92,9 @@ irqreturn_t cam_cci_irq(int irq_num, void *data)
 				false;
 			if (!cci_master_info->status)
 				complete(&cci_master_info->reset_complete);
-			cci_master_info->status = 0;
+
+			complete_all(&cci_master_info->rd_done);
+			complete_all(&cci_master_info->th_complete);
 		}
 	}
 
@@ -223,9 +227,18 @@ irqreturn_t cam_cci_irq(int irq_num, void *data)
 	}
 	if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_ERROR_BMSK) {
 		cci_dev->cci_master_info[MASTER_0].status = -EINVAL;
-		if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_NACK_ERROR_BMSK)
-			CAM_ERR(CAM_CCI, "Base:%pK, M0 NACK ERROR: 0x%x",
+		if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q0_NACK_ERROR_BMSK) {
+			CAM_ERR(CAM_CCI, "Base:%pK, M0_Q0 NACK ERROR: 0x%x",
+				base, irq_status0);
+			complete_all(&cci_dev->cci_master_info[MASTER_0]
+				.report_q[QUEUE_0]);
+		}
+		if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q1_NACK_ERROR_BMSK) {
+			CAM_ERR(CAM_CCI, "Base:%pK, M0_Q1 NACK ERROR: 0x%x",
 				base, irq_status0);
+			complete_all(&cci_dev->cci_master_info[MASTER_0]
+			.report_q[QUEUE_1]);
+		}
 		if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_ERROR_BMSK)
 			CAM_ERR(CAM_CCI,
 			"Base:%pK, M0 QUEUE_OVER/UNDER_FLOW OR CMD ERR: 0x%x",
@@ -234,22 +247,35 @@ irqreturn_t cam_cci_irq(int irq_num, void *data)
 			CAM_ERR(CAM_CCI,
 				"Base: %pK, M0 RD_OVER/UNDER_FLOW ERROR: 0x%x",
 				base, irq_status0);
-		cam_io_w_mb(CCI_M0_HALT_REQ_RMSK, base + CCI_HALT_REQ_ADDR);
+
+		cci_dev->cci_master_info[MASTER_0].reset_pending = true;
+		cam_io_w_mb(CCI_M0_RESET_RMSK, base + CCI_RESET_CMD_ADDR);
 	}
 	if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_ERROR_BMSK) {
 		cci_dev->cci_master_info[MASTER_1].status = -EINVAL;
-		if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_NACK_ERROR_BMSK)
-			CAM_ERR(CAM_CCI, "Base:%pK, M1 NACK ERROR: 0x%x",
+		if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_Q0_NACK_ERROR_BMSK) {
+			CAM_ERR(CAM_CCI, "Base:%pK, M1_Q0 NACK ERROR: 0x%x",
 				base, irq_status0);
-		if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_ERROR_BMSK)
+			complete_all(&cci_dev->cci_master_info[MASTER_1]
+			.report_q[QUEUE_0]);
+		}
+		if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_Q1_NACK_ERROR_BMSK) {
+			CAM_ERR(CAM_CCI, "Base:%pK, M1_Q1 NACK ERROR: 0x%x",
+				base, irq_status0);
+			complete_all(&cci_dev->cci_master_info[MASTER_1]
+			.report_q[QUEUE_1]);
+		}
+		if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_Q0Q1_ERROR_BMSK)
 			CAM_ERR(CAM_CCI,
 			"Base:%pK, M1 QUEUE_OVER_UNDER_FLOW OR CMD ERROR:0x%x",
 				base, irq_status0);
-		if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_ERROR_BMSK)
+		if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_ERROR_BMSK)
 			CAM_ERR(CAM_CCI,
 				"Base:%pK, M1 RD_OVER/UNDER_FLOW ERROR: 0x%x",
 				base, irq_status0);
-		cam_io_w_mb(CCI_M1_HALT_REQ_RMSK, base + CCI_HALT_REQ_ADDR);
+
+		cci_dev->cci_master_info[MASTER_1].reset_pending = true;
+		cam_io_w_mb(CCI_M1_RESET_RMSK, base + CCI_RESET_CMD_ADDR);
 	}
 
 	cam_io_w_mb(irq_status0, base + CCI_IRQ_CLEAR_0_ADDR);

+ 5 - 3
drivers/cam_sensor_module/cam_cci/cam_cci_hwreg.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2012-2015, 2017-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2015, 2017-2020, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _CAM_CCI_HWREG_
@@ -54,8 +54,10 @@
 #define CCI_IRQ_STATUS_0_I2C_M0_Q0_REPORT_BMSK                            0x10
 #define CCI_IRQ_STATUS_0_I2C_M0_ERROR_BMSK                          0x18000EE6
 #define CCI_IRQ_STATUS_0_I2C_M1_ERROR_BMSK                          0x60EE6000
-#define CCI_IRQ_STATUS_0_I2C_M0_NACK_ERROR_BMSK                     0x18000000
-#define CCI_IRQ_STATUS_0_I2C_M1_NACK_ERROR_BMSK                     0x60000000
+#define CCI_IRQ_STATUS_0_I2C_M0_Q0_NACK_ERROR_BMSK                   0x8000000
+#define CCI_IRQ_STATUS_0_I2C_M0_Q1_NACK_ERROR_BMSK                  0x10000000
+#define CCI_IRQ_STATUS_0_I2C_M1_Q0_NACK_ERROR_BMSK                  0x20000000
+#define CCI_IRQ_STATUS_0_I2C_M1_Q1_NACK_ERROR_BMSK                  0x40000000
 #define CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_ERROR_BMSK                          0xEE0
 #define CCI_IRQ_STATUS_0_I2C_M1_Q0Q1_ERROR_BMSK                       0xEE0000
 #define CCI_IRQ_STATUS_0_I2C_M0_RD_ERROR_BMSK                              0x6

+ 3 - 0
drivers/cam_sensor_module/cam_cci/cam_cci_soc.c

@@ -55,6 +55,7 @@ int cam_cci_init(struct v4l2_subdev *sd,
 				&cci_dev->cci_master_info[master].report_q[i]);
 			/* Set reset pending flag to true */
 			cci_dev->cci_master_info[master].reset_pending = true;
+			cci_dev->cci_master_info[master].status = 0;
 			/* Set proper mask to RESET CMD address */
 			if (master == MASTER_0)
 				cam_io_w_mb(CCI_M0_RESET_RMSK,
@@ -68,6 +69,7 @@ int cam_cci_init(struct v4l2_subdev *sd,
 				CCI_TIMEOUT);
 			if (rc <= 0)
 				CAM_ERR(CAM_CCI, "wait failed %d", rc);
+			cci_dev->cci_master_info[master].status = 0;
 			mutex_unlock(&cci_dev->cci_master_info[master].mutex);
 		}
 		return 0;
@@ -142,6 +144,7 @@ int cam_cci_init(struct v4l2_subdev *sd,
 	}
 
 	cci_dev->cci_master_info[master].reset_pending = true;
+	cci_dev->cci_master_info[master].status = 0;
 	cam_io_w_mb(CCI_RESET_CMD_RMSK, base +
 			CCI_RESET_CMD_ADDR);
 	cam_io_w_mb(0x1, base + CCI_RESET_CMD_ADDR);