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:
@@ -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) {
|
||||
|
Referens i nytt ärende
Block a user