disp: msm: dsi: implement ESD recovery cleanup

After an ESD failure, the PHY lanes and controller can be stuck in
an unknown state. This can result in interrupt storms and watchdog
failures, if these error states are not handled correctly. The following
change implements the below mechanism to avoid failures.

1) Disable error interrupts during an ESD reg read, which are re-enabled once
ESD check is successful.
2) On ESD failure, before turning off LP clocks, reset the PHY lanes and DSI
controller.
3) After the HS clocks are turned off, issue a PHY hard reset.
4) Before enabling/disabling error interrupts, clear the error status registers
as they are not cleared as part of controller reset.

Change-Id: If10e4edf095a334a9416d109ec4b1401d1a84505
Signed-off-by: Satya Rama Aditya Pinapala <psraditya30@codeaurora.org>
This commit is contained in:
Satya Rama Aditya Pinapala
2021-10-11 12:01:03 -07:00
förälder a6400b2c81
incheckning 1317b11bc2
4 ändrade filer med 95 tillägg och 20 borttagningar

Visa fil

@@ -448,10 +448,8 @@ static void dsi_ctrl_post_cmd_transfer(struct dsi_ctrl *dsi_ctrl)
if (rc)
DSI_CTRL_ERR(dsi_ctrl, "failed to disable command engine\n");
if (dsi_ctrl->pending_cmd_flags & DSI_CTRL_CMD_READ)
mask |= BIT(DSI_FIFO_UNDERFLOW);
dsi_ctrl_mask_error_status_interrupts(dsi_ctrl, mask, false);
if (!(dsi_ctrl->pending_cmd_flags & DSI_CTRL_CMD_READ))
dsi_ctrl_mask_error_status_interrupts(dsi_ctrl, mask, false);
mutex_unlock(&dsi_ctrl->ctrl_lock);
@@ -1909,16 +1907,18 @@ static int dsi_disable_ulps(struct dsi_ctrl *dsi_ctrl)
return rc;
}
static void dsi_ctrl_enable_error_interrupts(struct dsi_ctrl *dsi_ctrl)
void dsi_ctrl_toggle_error_interrupt_status(struct dsi_ctrl *dsi_ctrl, bool enable)
{
if (dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE &&
!dsi_ctrl->host_config.u.video_engine.bllp_lp11_en &&
!dsi_ctrl->host_config.u.video_engine.eof_bllp_lp11_en)
dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw,
0xFF00A0);
else
dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw,
0xFF00E0);
if (!enable) {
dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, 0);
} else {
if (dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE &&
!dsi_ctrl->host_config.u.video_engine.bllp_lp11_en &&
!dsi_ctrl->host_config.u.video_engine.eof_bllp_lp11_en)
dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, 0xFF00A0);
else
dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, 0xFF00E0);
}
}
static int dsi_ctrl_drv_state_init(struct dsi_ctrl *dsi_ctrl)
@@ -2597,7 +2597,7 @@ int dsi_ctrl_setup(struct dsi_ctrl *dsi_ctrl)
&dsi_ctrl->host_config.common_config);
dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw, 0x0);
dsi_ctrl_enable_error_interrupts(dsi_ctrl);
dsi_ctrl_toggle_error_interrupt_status(dsi_ctrl, true);
dsi_ctrl->hw.ops.ctrl_en(&dsi_ctrl->hw, true);
@@ -3131,7 +3131,7 @@ int dsi_ctrl_host_init(struct dsi_ctrl *dsi_ctrl, bool skip_op)
}
dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw, 0x0);
dsi_ctrl_enable_error_interrupts(dsi_ctrl);
dsi_ctrl_toggle_error_interrupt_status(dsi_ctrl, true);
DSI_CTRL_DEBUG(dsi_ctrl, "Host initialization complete, skip op: %d\n",
skip_op);
@@ -3417,10 +3417,8 @@ int dsi_ctrl_transfer_prepare(struct dsi_ctrl *dsi_ctrl, u32 flags)
mutex_lock(&dsi_ctrl->ctrl_lock);
if (flags & DSI_CTRL_CMD_READ)
mask |= BIT(DSI_FIFO_UNDERFLOW);
dsi_ctrl_mask_error_status_interrupts(dsi_ctrl, mask, true);
if (!(flags & DSI_CTRL_CMD_READ))
dsi_ctrl_mask_error_status_interrupts(dsi_ctrl, mask, true);
rc = dsi_ctrl_set_cmd_engine_state(dsi_ctrl, DSI_CTRL_ENGINE_ON, false);
if (rc) {