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

Commit db1e8beb authored by Rishabh Jain's avatar Rishabh Jain
Browse files

msm: camera: ope: Handle reset IRQ delay



If reset irq is not received within allocated time,
check for irq status to confirm if irq is delayed or
reset failed.
In case of irq delay, clear the irq status and mark it
as success.

CRs-Fixed: 2663505
Change-Id: I1b3658e2ada973f531ddba8bc2378b0440c9088a
Signed-off-by: default avatarRishabh Jain <risjai@codeaurora.org>
parent 0a0ebfa0
Loading
Loading
Loading
Loading
+58 −21
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ static int cam_ope_top_reset(struct ope_hw *ope_hw_info,
	struct cam_ope_top_reg *top_reg;
	struct cam_ope_top_reg_val *top_reg_val;
	uint32_t irq_mask, irq_status;
	unsigned long flags;

	if (!ope_hw_info) {
		CAM_ERR(CAM_OPE, "Invalid ope_hw_info");
@@ -72,21 +73,37 @@ static int cam_ope_top_reset(struct ope_hw *ope_hw_info,

	rc = wait_for_completion_timeout(
			&ope_top_info.reset_complete,
			msecs_to_jiffies(30));
			msecs_to_jiffies(60));

	cam_io_w_mb(top_reg_val->debug_cfg_val,
		top_reg->base + top_reg->debug_cfg);

	if (!rc || rc < 0) {
		CAM_ERR(CAM_OPE, "reset error result = %d", rc);
		spin_lock_irqsave(&ope_top_info.hw_lock, flags);
		if (!completion_done(&ope_top_info.reset_complete)) {
			CAM_DBG(CAM_OPE,
				"IRQ delayed, checking the status registers");
			irq_mask = cam_io_r_mb(ope_hw_info->top_reg->base +
				top_reg->irq_mask);
			irq_status = cam_io_r_mb(ope_hw_info->top_reg->base +
				top_reg->irq_status);
		CAM_ERR(CAM_OPE, "irq mask 0x%x irq status 0x%x",
			if (irq_status & top_reg_val->rst_done) {
				CAM_DBG(CAM_OPE, "ope reset done");
				cam_io_w_mb(irq_status,
					top_reg->base + top_reg->irq_clear);
				cam_io_w_mb(top_reg_val->irq_set_clear,
					top_reg->base + top_reg->irq_cmd);
			} else {
				CAM_ERR(CAM_OPE,
					"irq mask 0x%x irq status 0x%x",
					irq_mask, irq_status);
				cam_ope_top_dump_debug_reg(ope_hw_info);
				rc = -ETIMEDOUT;
			}
		} else {
			rc = 0;
		}
		spin_unlock_irqrestore(&ope_top_info.hw_lock, flags);
	} else {
		rc = 0;
	}
@@ -137,6 +154,7 @@ static int cam_ope_top_init(struct ope_hw *ope_hw_info,
	struct cam_ope_top_reg_val *top_reg_val;
	struct cam_ope_dev_init *dev_init = data;
	uint32_t irq_mask, irq_status;
	unsigned long flags;

	if (!ope_hw_info) {
		CAM_ERR(CAM_OPE, "Invalid ope_hw_info");
@@ -160,25 +178,41 @@ static int cam_ope_top_init(struct ope_hw *ope_hw_info,

	rc = wait_for_completion_timeout(
			&ope_top_info.reset_complete,
			msecs_to_jiffies(30));
			msecs_to_jiffies(60));

	cam_io_w_mb(top_reg_val->debug_cfg_val,
		top_reg->base + top_reg->debug_cfg);

	if (!rc || rc < 0) {
		CAM_ERR(CAM_OPE, "reset error result = %d", rc);
		spin_lock_irqsave(&ope_top_info.hw_lock, flags);
		if (!completion_done(&ope_top_info.reset_complete)) {
			CAM_DBG(CAM_OPE,
				"IRQ delayed, checking the status registers");
			irq_mask = cam_io_r_mb(ope_hw_info->top_reg->base +
				top_reg->irq_mask);
			irq_status = cam_io_r_mb(ope_hw_info->top_reg->base +
				top_reg->irq_status);
		CAM_ERR(CAM_OPE, "irq mask 0x%x irq status 0x%x",
			if (irq_status & top_reg_val->rst_done) {
				CAM_DBG(CAM_OPE, "ope reset done");
				cam_io_w_mb(irq_status,
					top_reg->base + top_reg->irq_clear);
				cam_io_w_mb(top_reg_val->irq_set_clear,
					top_reg->base + top_reg->irq_cmd);
			} else {
				CAM_ERR(CAM_OPE,
					"irq mask 0x%x irq status 0x%x",
					irq_mask, irq_status);
				cam_ope_top_dump_debug_reg(ope_hw_info);
				rc = -ETIMEDOUT;
			}
		} else {
			CAM_DBG(CAM_OPE, "reset done");
			rc = 0;
		}
		spin_unlock_irqrestore(&ope_top_info.hw_lock, flags);
	} else {
		rc = 0;
	}

	/* enable interrupt mask */
	cam_io_w_mb(top_reg_val->irq_mask,
		ope_hw_info->top_reg->base + top_reg->irq_mask);
@@ -197,6 +231,7 @@ static int cam_ope_top_probe(struct ope_hw *ope_hw_info,
	}

	ope_top_info.ope_hw_info = ope_hw_info;
	spin_lock_init(&ope_top_info.hw_lock);

	return rc;
}
@@ -219,6 +254,7 @@ static int cam_ope_top_isr(struct ope_hw *ope_hw_info,
	top_reg = ope_hw_info->top_reg;
	top_reg_val = ope_hw_info->top_reg_val;

	spin_lock(&ope_top_info.hw_lock);
	/* Read and Clear Top Interrupt status */
	irq_status = cam_io_r_mb(top_reg->base + top_reg->irq_status);
	cam_io_w_mb(irq_status,
@@ -238,6 +274,7 @@ static int cam_ope_top_isr(struct ope_hw *ope_hw_info,
		irq_data->error = 1;
		CAM_ERR(CAM_OPE, "ope violation: %x", violation_status);
	}
	spin_unlock(&ope_top_info.hw_lock);

	return rc;
}
+2 −0
Original line number Diff line number Diff line
@@ -33,11 +33,13 @@ struct ope_top_ctx {
 * @top_ctx:        OPE top context
 * @reset_complete: Reset complete flag
 * @ope_mutex:      OPE hardware mutex
 * @hw_lock:        OPE hardware spinlock
 */
struct ope_top {
	struct ope_hw *ope_hw_info;
	struct ope_top_ctx top_ctx[OPE_CTX_MAX];
	struct completion reset_complete;
	struct mutex      ope_hw_mutex;
	spinlock_t        hw_lock;
};
#endif /* OPE_TOP_H */