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

Commit e86dee8e authored by Dhaval Patel's avatar Dhaval Patel
Browse files

drm/msm: update rsc mode_2 entry failure sequence



sde rsc mode_2 entry may fail due to sequence busy in
mode_0 or mode_1. It can be avoided by manually triggering
the f1 qtimer interrupt and execute the mode sequence.
This change tries to run the recovery sequence for 3 times
to avoid mode_2 entry failure.

Change-Id: Ie373c31668e985e7b1c6fd4cb4753cc8a127619f
Signed-off-by: default avatarDhaval Patel <pdhaval@codeaurora.org>
parent 150e5aba
Loading
Loading
Loading
Loading
+66 −14
Original line number Diff line number Diff line
@@ -99,6 +99,10 @@
#define MAX_CHECK_LOOPS			500
#define POWER_CTRL_BIT_12		12

#define SDE_RSC_MODE_0_VAL		0
#define SDE_RSC_MODE_1_VAL		1
#define MAX_MODE2_ENTRY_TRY		3

static void rsc_event_trigger(struct sde_rsc_priv *rsc, uint32_t event_type)
{
	struct sde_rsc_event *event;
@@ -489,23 +493,12 @@ static int sde_rsc_mode2_exit(struct sde_rsc_priv *rsc,
	return rc;
}

static int sde_rsc_mode2_entry(struct sde_rsc_priv *rsc)
static int sde_rsc_mode2_entry_trigger(struct sde_rsc_priv *rsc)
{
	int rc;
	int count, wrapper_status;
	unsigned long reg;

	if (rsc->power_collapse_block)
		return -EINVAL;

	rc = regulator_set_mode(rsc->fs, REGULATOR_MODE_FAST);
	if (rc) {
		pr_err("vdd reg fast mode set failed rc:%d\n", rc);
		return rc;
	}

	rsc_event_trigger(rsc, SDE_RSC_EVENT_PRE_CORE_PC);

	/* update qtimers to high during clk & video mode state */
	if ((rsc->current_state == SDE_RSC_VID_STATE) ||
			(rsc->current_state == SDE_RSC_CLK_STATE)) {
@@ -550,15 +543,74 @@ static int sde_rsc_mode2_entry(struct sde_rsc_priv *rsc)
		usleep_range(10, 100);
	}

	return rc;
}

static void sde_rsc_reset_mode_0_1(struct sde_rsc_priv *rsc)
{
	u32 seq_busy, current_mode, curr_inst_addr;

	seq_busy = dss_reg_r(&rsc->drv_io, SDE_RSCC_SEQ_BUSY_DRV0,
			rsc->debug_mode);
	current_mode = dss_reg_r(&rsc->drv_io, SDE_RSCC_SOLVER_STATUS2_DRV0,
			rsc->debug_mode);
	curr_inst_addr = dss_reg_r(&rsc->drv_io, SDE_RSCC_SEQ_PROGRAM_COUNTER,
			rsc->debug_mode);
	SDE_EVT32(seq_busy, current_mode, curr_inst_addr);

	if (seq_busy && (current_mode == SDE_RSC_MODE_0_VAL ||
			current_mode == SDE_RSC_MODE_1_VAL)) {
		dss_reg_w(&rsc->wrapper_io, SDE_RSCC_F1_QTMR_V1_CNTP_CVAL_LO,
						0xffffffff, rsc->debug_mode);
		dss_reg_w(&rsc->wrapper_io, SDE_RSCC_F1_QTMR_V1_CNTP_CVAL_HI,
						0xffffffff, rsc->debug_mode);
		/* unstick f1 qtimer */
		wmb();

		dss_reg_w(&rsc->wrapper_io, SDE_RSCC_F1_QTMR_V1_CNTP_CVAL_LO,
						0x0, rsc->debug_mode);
		dss_reg_w(&rsc->wrapper_io, SDE_RSCC_F1_QTMR_V1_CNTP_CVAL_HI,
						0x0, rsc->debug_mode);
		/* manually trigger f1 qtimer interrupt */
		wmb();
	}
}

static int sde_rsc_mode2_entry(struct sde_rsc_priv *rsc)
{
	int rc = 0, i;
	u32 reg;

	if (rsc->power_collapse_block)
		return -EINVAL;

	rc = regulator_set_mode(rsc->fs, REGULATOR_MODE_FAST);
	if (rc) {
		pr_err("vdd reg fast mode set failed rc:%d\n", rc);
		return rc;
	}

	rsc_event_trigger(rsc, SDE_RSC_EVENT_PRE_CORE_PC);

	for (i = 0; i <= MAX_MODE2_ENTRY_TRY; i++) {
		rc = sde_rsc_mode2_entry_trigger(rsc);
		if (!rc)
			break;

		reg = dss_reg_r(&rsc->drv_io,
				SDE_RSCC_SEQ_PROGRAM_COUNTER, rsc->debug_mode);
		pr_err("mdss gdsc power down failed, instruction:0x%x, rc:%d\n",
				reg, rc);
		SDE_EVT32(rc, reg, SDE_EVTLOG_ERROR);
		goto end;

		/* avoid touching f1 qtimer for last try */
		if (i != MAX_MODE2_ENTRY_TRY)
			sde_rsc_reset_mode_0_1(rsc);
	}

	if (rc)
		goto end;

	if ((rsc->current_state == SDE_RSC_VID_STATE) ||
			(rsc->current_state == SDE_RSC_CLK_STATE)) {
		dss_reg_w(&rsc->wrapper_io, SDE_RSCC_WRAPPER_OVERRIDE_CTRL,
@@ -632,7 +684,7 @@ static int sde_rsc_state_update(struct sde_rsc_priv *rsc,

		reg = dss_reg_r(&rsc->wrapper_io,
			SDE_RSCC_WRAPPER_OVERRIDE_CTRL, rsc->debug_mode);
		reg &= ~(BIT(8) | BIT(0));
		reg &= ~BIT(0);
		dss_reg_w(&rsc->wrapper_io, SDE_RSCC_WRAPPER_OVERRIDE_CTRL,
							reg, rsc->debug_mode);
		/* make sure that solver mode is disabled */