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

Commit dbe6ca08 authored by Gilad Avidov's avatar Gilad Avidov
Browse files

i2c-msm-v2: add wait time to let recovery complete



bus recovery procedure requires time to complete prior to
moving to reset state.

Change-Id: I0773bb3161769b87e4513432b8c65b8c3d24f777
Signed-off-by: default avatarAnkit Gupta <ankgupta@codeaurora.org>
Signed-off-by: default avatarAvidov Gilad <gavidov@codeaurora.org>
parent 8b606f17
Loading
Loading
Loading
Loading
+26 −6
Original line number Diff line number Diff line
@@ -2045,9 +2045,14 @@ static bool i2c_msm_qup_slv_holds_bus(struct i2c_msm_ctrl *ctrl)
{
	u32 status = readl_relaxed(ctrl->rsrcs.base + QUP_I2C_STATUS);

	return  !(status & QUP_I2C_SDA) &&
	bool slv_holds_bus =	!(status & QUP_I2C_SDA) &&
				(status & QUP_BUS_ACTIVE) &&
				!(status & QUP_BUS_MASTER);
	if (slv_holds_bus)
		dev_info(ctrl->dev,
			"bus lines held low by a slave detected\n");

	return slv_holds_bus;
}

/*
@@ -2470,6 +2475,7 @@ static int i2c_msm_qup_init(struct i2c_msm_ctrl *ctrl)
static bool i2c_msm_qup_do_bus_clear(struct i2c_msm_ctrl *ctrl)
{
	int ret;
	ulong min_sleep_usec;
	dev_info(ctrl->dev, "Executing bus recovery procedure (9 clk pulse)\n");

	/* call i2c_msm_qup_init() to set core in idle state */
@@ -2477,15 +2483,29 @@ static bool i2c_msm_qup_do_bus_clear(struct i2c_msm_ctrl *ctrl)
	if (ret)
		return ret;

	/* call i2c_msm_qup_xfer_init_run_state() to set clock dividers */
	i2c_msm_qup_xfer_init_run_state(ctrl);

	/* must be in run state for bus clear */
	ret = i2c_msm_qup_state_set(ctrl, QUP_STATE_RUN);
	if (ret)
		return ret;

	/*
	 * call i2c_msm_qup_xfer_init_run_state() to set clock dividers.
	 * the dividers are necessary for bus clear.
	 */
	i2c_msm_qup_xfer_init_run_state(ctrl);

	writel_relaxed(0x1, ctrl->rsrcs.base + QUP_I2C_MASTER_BUS_CLR);

	/*
	 * wait for recovery (9 clock pulse cycles) to complete.
	 * min_time = 9 clock *10  (1000% margin)
	 * max_time = 10* min_time
	 */
	min_sleep_usec =
	  max_t(ulong, (9 * 10 * USEC_PER_SEC) / ctrl->rsrcs.clk_freq_out, 100);

	usleep_range(min_sleep_usec, min_sleep_usec * 10);

	return 0;
}