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

Commit dc2e0f13 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: Ic894cc585dc8478bc949b45b6870c21efda1bbb3
Signed-off-by: default avatarGilad Avidov <gavidov@codeaurora.org>
parent 360013b1
Loading
Loading
Loading
Loading
+28 −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, 1);

	usleep_range(min_sleep_usec, min_sleep_usec * 10);

	return 0;
}

@@ -2502,6 +2522,8 @@ static int i2c_msm_qup_post_xfer(struct i2c_msm_ctrl *ctrl, int err)
{
	bool need_reset = false;

	i2c_msm_qup_do_bus_clear(ctrl);

	/* poll until bus is released */
	if (i2c_msm_qup_poll_bus_active_unset(ctrl)) {
		if ((ctrl->xfer.err & I2C_MSM_ERR_ARB_LOST) ||