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

Commit 6ae3e698 authored by Ankit Gupta's avatar Ankit Gupta
Browse files

i2c-qup: improve the bus recovery procedure in qup i2c driver



Bus recovery procedure is required when bus goes in a bad state.
Recovery procedure may not get success in single iteration. This
patch increases iteration number to let the bus recover based on
the QUP_I2C_STATUS and QUP_I2C_MASTER_BUS_CLR register values.

Change-Id: I2ab397645b852cf6f7e7b8071596bf64455af831
Signed-off-by: default avatarAnkit Gupta <ankgupta@codeaurora.org>
parent 5593593b
Loading
Loading
Loading
Loading
+21 −4
Original line number Diff line number Diff line
@@ -142,6 +142,7 @@ enum msm_i2c_state {
#define I2C_STATUS_CLK_STATE		13
#define QUP_OUT_FIFO_NOT_EMPTY		0x10
#define I2C_GPIOS_DT_CNT		(2)		/* sda and scl */
#define I2C_QUP_MAX_BUS_RECOVERY_RETRY	10

/* Register:QUP_I2C_MASTER_CLK_CTL field setters */
#define QUP_I2C_SCL_NOISE_REJECTION(reg_val, noise_rej_val) \
@@ -937,14 +938,13 @@ static int qup_i2c_reset(struct qup_i2c_dev *dev)
	return ret;
}

static int qup_i2c_recover_bus_busy(struct qup_i2c_dev *dev)
static int qup_i2c_try_recover_bus_busy(struct qup_i2c_dev *dev)
{
	int ret;
	u32 status;
	ulong min_sleep_usec;

	disable_irq(dev->err_irq);
	dev_info(dev->dev, "Executing bus recovery procedure (9 clk pulse)\n");

	qup_i2c_reset(dev);

@@ -972,14 +972,31 @@ static int qup_i2c_recover_bus_busy(struct qup_i2c_dev *dev)
	usleep_range(min_sleep_usec, min_sleep_usec * 10);

	status = readl_relaxed(dev->base + QUP_I2C_STATUS);
	dev_info(dev->dev, "Bus recovery %s\n",
		(status & I2C_STATUS_BUS_ACTIVE) ? "fail" : "success");

recovery_end:
	enable_irq(dev->err_irq);
	return ret;
}

static void qup_i2c_recover_bus_busy(struct qup_i2c_dev *dev)
{
	u32 bus_clr, bus_active, status;
	int retry = 0;
	dev_info(dev->dev, "Executing bus recovery procedure (9 clk pulse)\n");

	do {
		qup_i2c_try_recover_bus_busy(dev);
		bus_clr    = readl_relaxed(dev->base + QUP_I2C_MASTER_BUS_CLR);
		status     = readl_relaxed(dev->base + QUP_I2C_STATUS);
		bus_active = status & I2C_STATUS_BUS_ACTIVE;
		if (++retry >= I2C_QUP_MAX_BUS_RECOVERY_RETRY)
			break;
	} while (bus_clr || bus_active);

	dev_info(dev->dev, "Bus recovery %s after %d retries\n",
		(bus_clr || bus_active) ? "fail" : "success", retry);
}

static int
qup_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
{