[linux-yocto] [PATCH 02/12] i2c: i2c-octeon: broken irqs, high-level controller, retry lost arbitration

Chandrakala Chavva cchavva.cavm at gmail.com
Thu Jan 29 07:32:01 PST 2015


From: Abhishek Paliwal <abhishek.paliwal at aricent.com>

From: David Daney <david.daney at cavium.com>

Combined several changes:
Add workaround for chips with broken irqs.
Use High Level Controller when possible.
Retry more situations where arbitration is lost.
Clean up resource allocation code.

Signed-off-by: David Daney <david.daney at cavium.com>
Signed-off-by: Abhishek Paliwal <abhishek.paliwal at aricent.com>
---
 drivers/i2c/busses/i2c-octeon.c | 446 +++++++++++++++++++++++++++++++++++++---
 1 file changed, 420 insertions(+), 26 deletions(-)

diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
index 81042b0..96d88d0 100644
--- a/drivers/i2c/busses/i2c-octeon.c
+++ b/drivers/i2c/busses/i2c-octeon.c
@@ -2,7 +2,7 @@
  * (C) Copyright 2009-2010
  * Nokia Siemens Networks, michael.lawnick.ext at nsn.com
  *
- * Portions Copyright (C) 2010, 2011 Cavium Networks, Inc.
+ * Portions Copyright (C) 2010 - 2013 Cavium, Inc.
  *
  * This is a driver for the i2c adapter in Cavium Networks' OCTEON processors.
  *
@@ -27,21 +27,31 @@
 #define DRV_NAME "i2c-octeon"
 
 /* The previous out-of-tree version was implicitly version 1.0. */
-#define DRV_VERSION	"2.0"
+#define DRV_VERSION	"2.5"
 
 /* register offsets */
-#define SW_TWSI	 0x00
-#define TWSI_INT 0x10
+#define SW_TWSI		0x00
+#define TWSI_INT	0x10
+#define SW_TWSI_EXT	0x18
 
 /* Controller command patterns */
 #define SW_TWSI_V               0x8000000000000000ull
+#define SW_TWSI_EIA		(1ull << 61)
+#define SW_TWSI_R		(1ull << 56)
+#define SW_TWSI_SOVR		(1ull << 55)
+#define SW_TWSI_OP_7		(0ull << 57)
+#define SW_TWSI_OP_7_IA		(1ull << 57)
+#define SW_TWSI_OP_10		(2ull << 57)
+#define SW_TWSI_OP_10_IA	(3ull << 57)
+#define SW_TWSI_SIZE_SHIFT	52
+#define SW_TWSI_A_SHIFT		40
+#define SW_TWSI_IA_SHIFT	32
 #define SW_TWSI_EOP_TWSI_DATA   0x0C00000100000000ull
 #define SW_TWSI_EOP_TWSI_CTL    0x0C00000200000000ull
 #define SW_TWSI_EOP_TWSI_CLKCTL 0x0C00000300000000ull
 #define SW_TWSI_EOP_TWSI_STAT   0x0C00000300000000ull
 #define SW_TWSI_EOP_TWSI_RST    0x0C00000700000000ull
 #define SW_TWSI_OP_TWSI_CLK     0x0800000000000000ull
-#define SW_TWSI_R               0x0100000000000000ull
 
 /* Controller command and status bits */
 #define TWSI_CTL_CE   0x80
@@ -66,10 +76,10 @@ struct octeon_i2c {
 	int irq;
 	u32 twsi_freq;
 	int sys_freq;
-	resource_size_t twsi_phys;
 	void __iomem *twsi_base;
-	resource_size_t regsize;
 	struct device *dev;
+	int broken_irq_mode;
+	bool octeon_i2c_hlc_enabled;
 };
 
 /**
@@ -202,6 +212,20 @@ static int octeon_i2c_wait(struct octeon_i2c *i2c)
 {
 	int result;
 
+	if (i2c->broken_irq_mode) {
+		/*
+		 * Some chip revisions seem to not assert the irq in
+		 * the interrupt controller.  So we must poll for the
+		 * IFLG change.
+		 */
+		u64 end = get_jiffies_64() + i2c->adap.timeout;
+
+		while (!octeon_i2c_test_iflg(i2c) && get_jiffies_64() <= end)
+			udelay(50);
+
+		return octeon_i2c_test_iflg(i2c) ? 0 : -ETIMEDOUT;
+	}
+
 	octeon_i2c_int_enable(i2c);
 
 	result = wait_event_timeout(i2c->queue,
@@ -210,6 +234,13 @@ static int octeon_i2c_wait(struct octeon_i2c *i2c)
 
 	octeon_i2c_int_disable(i2c);
 
+
+	if (result <= 0 && octeon_i2c_test_iflg(i2c)) {
+		dev_err(i2c->dev, "broken irq connection detected, switching to polling mode.\n");
+		i2c->broken_irq_mode = 1;
+		return 0;
+	}
+
 	if (result < 0) {
 		dev_dbg(i2c->dev, "%s: wait interrupted\n", __func__);
 		return result;
@@ -221,6 +252,44 @@ static int octeon_i2c_wait(struct octeon_i2c *i2c)
 	return 0;
 }
 
+static int octeon_i2c_enable_hlc(struct octeon_i2c *i2c)
+{
+	if (i2c->octeon_i2c_hlc_enabled)
+		return 0;
+
+	octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL,
+			    TWSI_CTL_CE | TWSI_CTL_ENAB);
+
+	i2c->octeon_i2c_hlc_enabled = true;
+	return 0;
+}
+
+static bool octeon_i2c_lost_arb(u64 code)
+{
+	switch (code & 0xffull) {
+	/* Arbitration lost in address or data byte */
+	case 0x38:
+	/*
+	 * Arbitration lost in address as master, slave address +
+	 * write bit received, ACK transmitted.
+	 */
+	case 0x68:
+	/*
+	 * Arbitration lost in address as master, general call address
+	 * received, ACK transmitted.
+	 */
+	case 0x78:
+	/*
+	 * Arbitration lost in address as master, slave address + read
+	 * bit received, ACK transmitted.
+	 */
+	case 0xb0:
+		return true;
+	default:
+		return false;
+	}
+}
+
 /**
  * octeon_i2c_start - send START to the bus.
  * @i2c: The struct octeon_i2c.
@@ -232,6 +301,8 @@ static int octeon_i2c_start(struct octeon_i2c *i2c)
 	u8 data;
 	int result;
 
+	i2c->octeon_i2c_hlc_enabled = false;
+
 	octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL,
 				TWSI_CTL_ENAB | TWSI_CTL_STA);
 
@@ -290,17 +361,19 @@ static int octeon_i2c_stop(struct octeon_i2c *i2c)
  * @target: Target address.
  * @data: Pointer to the data to be sent.
  * @length: Length of the data.
+ * @phase: which phase of a combined operation.
  *
  * The address is sent over the bus, then the data.
  *
  * Returns 0 on success, otherwise a negative errno.
  */
 static int octeon_i2c_write(struct octeon_i2c *i2c, int target,
-			    const u8 *data, int length)
+			    const u8 *data, int length, int phase)
 {
 	int i, result;
 	u8 tmp;
 
+restart:
 	result = octeon_i2c_start(i2c);
 	if (result)
 		return result;
@@ -314,6 +387,9 @@ static int octeon_i2c_write(struct octeon_i2c *i2c, int target,
 
 	for (i = 0; i < length; i++) {
 		tmp = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT);
+		if (phase == 0 && octeon_i2c_lost_arb(tmp))
+			goto restart;
+
 		if ((tmp != STAT_TXADDR_ACK) && (tmp != STAT_TXDATA_ACK)) {
 			dev_err(i2c->dev,
 				"%s: bad status before write (0x%x)\n",
@@ -338,13 +414,14 @@ static int octeon_i2c_write(struct octeon_i2c *i2c, int target,
  * @target: Target address.
  * @data: Pointer to the location to store the datae .
  * @length: Length of the data.
+ * @phase: which phase of a combined operation.
  *
  * The address is sent over the bus, then the data is read.
  *
  * Returns 0 on success, otherwise a negative errno.
  */
 static int octeon_i2c_read(struct octeon_i2c *i2c, int target,
-			   u8 *data, int length)
+			   u8 *data, int length, int phase)
 {
 	int i, result;
 	u8 tmp;
@@ -352,6 +429,7 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target,
 	if (length < 1)
 		return -EINVAL;
 
+restart:
 	result = octeon_i2c_start(i2c);
 	if (result)
 		return result;
@@ -365,6 +443,9 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target,
 
 	for (i = 0; i < length; i++) {
 		tmp = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT);
+		if (phase == 0 && octeon_i2c_lost_arb(tmp))
+			goto restart;
+
 		if ((tmp != STAT_RXDATA_ACK) && (tmp != STAT_RXADDR_ACK)) {
 			dev_err(i2c->dev,
 				"%s: bad status before read (0x%x)\n",
@@ -388,6 +469,294 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target,
 	return 0;
 }
 
+static bool octeon_i2c_hlc_test_ready(struct octeon_i2c *i2c)
+{
+	u64 v = __raw_readq(i2c->twsi_base + SW_TWSI);
+	return (v & SW_TWSI_V) == 0;
+}
+
+static void octeon_i2c_hlc_int_enable(struct octeon_i2c *i2c)
+{
+	octeon_i2c_write_int(i2c, 0x10);
+}
+
+static void octeon_i2c_hlc_int_clear(struct octeon_i2c *i2c)
+{
+	octeon_i2c_write_int(i2c, 0x3);
+}
+
+/**
+ * octeon_i2c_hlc_wait - wait for an HLC operation to complete.
+ * @i2c: The struct octeon_i2c.
+ *
+ * Returns 0 on success, otherwise a negative errno.
+ */
+static int octeon_i2c_hlc_wait(struct octeon_i2c *i2c)
+{
+	int result;
+
+	if (i2c->broken_irq_mode) {
+		/*
+		 * Some chip revisions seem to not assert the irq in
+		 * the interrupt controller.  So we must poll for the
+		 * IFLG change.
+		 */
+		u64 end = get_jiffies_64() + i2c->adap.timeout;
+
+		while (!octeon_i2c_hlc_test_ready(i2c) && get_jiffies_64() <= end)
+			udelay(50);
+
+		return octeon_i2c_hlc_test_ready(i2c) ? 0 : -ETIMEDOUT;
+	}
+
+	octeon_i2c_hlc_int_enable(i2c);
+
+	result = wait_event_interruptible_timeout(i2c->queue,
+						  octeon_i2c_hlc_test_ready(i2c),
+						  i2c->adap.timeout);
+
+	octeon_i2c_int_disable(i2c);
+
+
+	if (result <= 0 && octeon_i2c_hlc_test_ready(i2c)) {
+		dev_err(i2c->dev, "broken irq connection detected, switching to polling mode.\n");
+		i2c->broken_irq_mode = 1;
+		return 0;
+	}
+
+	if (result < 0) {
+		dev_dbg(i2c->dev, "%s: wait interrupted\n", __func__);
+		return result;
+	} else if (result == 0) {
+		dev_dbg(i2c->dev, "%s: timeout\n", __func__);
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int octeon_i2c_simple_read(struct octeon_i2c *i2c, struct i2c_msg *msgs)
+{
+	u64 cmd;
+	int i, j;
+	int ret = 0;
+
+	octeon_i2c_enable_hlc(i2c);
+retry:
+	cmd = SW_TWSI_V | SW_TWSI_R | SW_TWSI_SOVR;
+	/* SIZE */
+	cmd |= (u64)(msgs[0].len - 1) << SW_TWSI_SIZE_SHIFT;
+	/* A */
+	cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_A_SHIFT;
+
+	if (msgs[0].flags & I2C_M_TEN)
+		cmd |= SW_TWSI_OP_10;
+	else
+		cmd |= SW_TWSI_OP_7;
+
+	octeon_i2c_hlc_int_clear(i2c);
+	__raw_writeq(cmd, i2c->twsi_base + SW_TWSI);
+
+	ret = octeon_i2c_hlc_wait(i2c);
+
+	if (ret)
+		goto err;
+
+	cmd = __raw_readq(i2c->twsi_base + SW_TWSI);
+
+	if ((cmd & SW_TWSI_R) == 0) {
+		if (octeon_i2c_lost_arb(cmd))
+			goto retry;
+		ret = -EIO;
+		goto err;
+	}
+
+	for (i = 0, j = msgs[0].len - 1; i  < msgs[0].len && i < 4; i++, j--)
+		msgs[0].buf[j] = (cmd >> (8 * i)) & 0xff;
+
+	if (msgs[0].len >= 4) {
+		cmd = __raw_readq(i2c->twsi_base + SW_TWSI_EXT);
+		for (i = 0; i  < msgs[0].len - 4 && i < 4; i++, j--)
+			msgs[0].buf[j] = (cmd >> (8 * i)) & 0xff;
+	}
+
+err:
+	return ret;
+}
+
+static int octeon_i2c_simple_write(struct octeon_i2c *i2c, struct i2c_msg *msgs)
+{
+	u64 cmd;
+	int i, j;
+	int ret = 0;
+
+	octeon_i2c_enable_hlc(i2c);
+
+retry:
+	cmd = SW_TWSI_V | SW_TWSI_SOVR;
+	/* SIZE */
+	cmd |= (u64)(msgs[0].len - 1) << SW_TWSI_SIZE_SHIFT;
+	/* A */
+	cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_A_SHIFT;
+
+	if (msgs[0].flags & I2C_M_TEN)
+		cmd |= SW_TWSI_OP_10;
+	else
+		cmd |= SW_TWSI_OP_7;
+
+	for (i = 0, j = msgs[0].len - 1; i  < msgs[0].len && i < 4; i++, j--)
+		cmd |= (u64)msgs[0].buf[j] << (8 * i);
+
+	if (msgs[0].len >= 4) {
+		u64 ext = 0;
+		for (i = 0; i < msgs[0].len - 4 && i < 4; i++, j--)
+			ext |= (u64)msgs[0].buf[j] << (8 * i);
+		__raw_writeq(ext, i2c->twsi_base + SW_TWSI_EXT);
+	}
+
+	octeon_i2c_hlc_int_clear(i2c);
+	__raw_writeq(cmd, i2c->twsi_base + SW_TWSI);
+
+	ret = octeon_i2c_hlc_wait(i2c);
+
+	if (ret)
+		goto err;
+
+	cmd = __raw_readq(i2c->twsi_base + SW_TWSI);
+
+	if ((cmd & SW_TWSI_R) == 0) {
+		if (octeon_i2c_lost_arb(cmd))
+			goto retry;
+		ret = -EIO;
+		goto err;
+	}
+
+err:
+	return ret;
+}
+
+static int octeon_i2c_ia_read(struct octeon_i2c *i2c, struct i2c_msg *msgs)
+{
+	u64 cmd;
+	int i, j;
+	int ret = 0;
+
+	octeon_i2c_enable_hlc(i2c);
+
+retry:
+	cmd = SW_TWSI_V | SW_TWSI_R | SW_TWSI_SOVR;
+	/* SIZE */
+	cmd |= (u64)(msgs[1].len - 1) << SW_TWSI_SIZE_SHIFT;
+	/* A */
+	cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_A_SHIFT;
+
+	if (msgs[0].flags & I2C_M_TEN)
+		cmd |= SW_TWSI_OP_10_IA;
+	else
+		cmd |= SW_TWSI_OP_7_IA;
+
+	if (msgs[0].len == 2) {
+		u64 ext = 0;
+		cmd |= SW_TWSI_EIA;
+		ext = (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT;
+		cmd |= (u64)msgs[0].buf[1] << SW_TWSI_IA_SHIFT;
+		__raw_writeq(ext, i2c->twsi_base + SW_TWSI_EXT);
+	} else {
+		cmd |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT;
+	}
+
+	octeon_i2c_hlc_int_clear(i2c);
+	__raw_writeq(cmd, i2c->twsi_base + SW_TWSI);
+
+	ret = octeon_i2c_hlc_wait(i2c);
+
+	if (ret)
+		goto err;
+
+	cmd = __raw_readq(i2c->twsi_base + SW_TWSI);
+
+	if ((cmd & SW_TWSI_R) == 0) {
+		if (octeon_i2c_lost_arb(cmd))
+			goto retry;
+		ret = -EIO;
+		goto err;
+	}
+
+	for (i = 0, j = msgs[1].len - 1; i  < msgs[1].len && i < 4; i++, j--)
+		msgs[1].buf[j] = (cmd >> (8 * i)) & 0xff;
+
+	if (msgs[1].len >= 4) {
+		cmd = __raw_readq(i2c->twsi_base + SW_TWSI_EXT);
+		for (i = 0; i  < msgs[1].len - 4 && i < 4; i++, j--)
+			msgs[1].buf[j] = (cmd >> (8 * i)) & 0xff;
+	}
+
+err:
+	return ret;
+}
+
+static int octeon_i2c_ia_write(struct octeon_i2c *i2c, struct i2c_msg *msgs)
+{
+	u64 cmd;
+	int i, j;
+	int ret = 0;
+	u64 ext = 0;
+	bool set_ext = false;
+
+	octeon_i2c_enable_hlc(i2c);
+
+retry:
+	cmd = SW_TWSI_V | SW_TWSI_SOVR;
+	/* SIZE */
+	cmd |= (u64)(msgs[1].len - 1) << SW_TWSI_SIZE_SHIFT;
+	/* A */
+	cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_A_SHIFT;
+
+	if (msgs[0].flags & I2C_M_TEN)
+		cmd |= SW_TWSI_OP_10_IA;
+	else
+		cmd |= SW_TWSI_OP_7_IA;
+
+	if (msgs[0].len == 2) {
+		cmd |= SW_TWSI_EIA;
+		ext |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT;
+		set_ext = true;
+		cmd |= (u64)msgs[0].buf[1] << SW_TWSI_IA_SHIFT;
+	} else {
+		cmd |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT;
+	}
+	for (i = 0, j = msgs[1].len - 1; i  < msgs[1].len && i < 4; i++, j--)
+		cmd |= (u64)msgs[1].buf[j] << (8 * i);
+
+	if (msgs[1].len >= 4) {
+		for (i = 0; i < msgs[1].len - 4 && i < 4; i++, j--)
+			ext |= (u64)msgs[1].buf[j] << (8 * i);
+		set_ext = true;
+	}
+	if (set_ext)
+		__raw_writeq(ext, i2c->twsi_base + SW_TWSI_EXT);
+
+	octeon_i2c_hlc_int_clear(i2c);
+	__raw_writeq(cmd, i2c->twsi_base + SW_TWSI);
+
+	ret = octeon_i2c_hlc_wait(i2c);
+
+	if (ret)
+		goto err;
+
+	cmd = __raw_readq(i2c->twsi_base + SW_TWSI);
+
+	if ((cmd & SW_TWSI_R) == 0) {
+		if (octeon_i2c_lost_arb(cmd))
+			goto retry;
+		ret = -EIO;
+		goto err;
+	}
+
+err:
+	return ret;
+}
+
 /**
  * octeon_i2c_xfer - The driver's master_xfer function.
  * @adap: Pointer to the i2c_adapter structure.
@@ -406,6 +775,27 @@ static int octeon_i2c_xfer(struct i2c_adapter *adap,
 	int ret = 0;
 	struct octeon_i2c *i2c = i2c_get_adapdata(adap);
 
+	if (num == 1) {
+		if (msgs[0].len > 0 && msgs[0].len <= 8) {
+			if (msgs[0].flags & I2C_M_RD)
+				ret = octeon_i2c_simple_read(i2c, msgs);
+			else
+				ret = octeon_i2c_simple_write(i2c, msgs);
+			goto out;
+		}
+	} else if (num == 2) {
+		if ((msgs[0].flags & I2C_M_RD) == 0 &&
+		    msgs[0].len > 0 && msgs[0].len <= 2 &&
+		    msgs[1].len > 0 && msgs[1].len <= 8 &&
+		    msgs[0].addr == msgs[1].addr) {
+			if (msgs[1].flags & I2C_M_RD)
+				ret = octeon_i2c_ia_read(i2c, msgs);
+			else
+				ret = octeon_i2c_ia_write(i2c, msgs);
+			goto out;
+		}
+	}
+
 	for (i = 0; ret == 0 && i < num; i++) {
 		pmsg = &msgs[i];
 		dev_dbg(i2c->dev,
@@ -414,13 +804,13 @@ static int octeon_i2c_xfer(struct i2c_adapter *adap,
 			 pmsg->len, pmsg->addr, i + 1, num);
 		if (pmsg->flags & I2C_M_RD)
 			ret = octeon_i2c_read(i2c, pmsg->addr, pmsg->buf,
-						pmsg->len);
+					      pmsg->len, i);
 		else
 			ret = octeon_i2c_write(i2c, pmsg->addr, pmsg->buf,
-						pmsg->len);
+					       pmsg->len, i);
 	}
 	octeon_i2c_stop(i2c);
-
+out:
 	return (ret != 0) ? ret : num;
 }
 
@@ -438,7 +828,6 @@ static struct i2c_adapter octeon_i2c_ops = {
 	.owner = THIS_MODULE,
 	.name = "OCTEON adapter",
 	.algo = &octeon_i2c_algo,
-	.timeout = HZ / 50,
 };
 
 /**
@@ -492,20 +881,26 @@ static int octeon_i2c_initlowlevel(struct octeon_i2c *i2c)
 	u8 status;
 	int tries;
 
-	/* disable high level controller, enable bus access */
-	octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB);
-
 	/* reset controller */
 	octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_RST, 0);
 
-	for (tries = 10; tries; tries--) {
+	status = 0;
+	for (tries = 10; tries && status != STAT_IDLE; tries--) {
 		udelay(1);
 		status = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT);
-		if (status == STAT_IDLE)
-			return 0;
 	}
-	dev_err(i2c->dev, "%s: TWSI_RST failed! (0x%x)\n", __func__, status);
-	return -EIO;
+
+	if (status != STAT_IDLE) {
+		dev_err(i2c->dev, "%s: TWSI_RST failed! (0x%x)\n",
+			__func__, status);
+		return -EIO;
+	}
+
+
+	/* disable high level controller, enable bus access */
+	octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB);
+
+	return 0;
 }
 
 static int octeon_i2c_probe(struct platform_device *pdev)
@@ -534,8 +929,6 @@ static int octeon_i2c_probe(struct platform_device *pdev)
 		result = -ENXIO;
 		goto out;
 	}
-	i2c->twsi_phys = res_mem->start;
-	i2c->regsize = resource_size(res_mem);
 
 	/*
 	 * "clock-rate" is a legacy binding, the official binding is
@@ -554,12 +947,12 @@ static int octeon_i2c_probe(struct platform_device *pdev)
 
 	i2c->sys_freq = octeon_get_io_clock_rate();
 
-	if (!devm_request_mem_region(&pdev->dev, i2c->twsi_phys, i2c->regsize,
-				      res_mem->name)) {
+	if (!devm_request_mem_region(&pdev->dev, res_mem->start, resource_size(res_mem),
+				     res_mem->name)) {
 		dev_err(i2c->dev, "request_mem_region failed\n");
 		goto out;
 	}
-	i2c->twsi_base = devm_ioremap(&pdev->dev, i2c->twsi_phys, i2c->regsize);
+	i2c->twsi_base = devm_ioremap(&pdev->dev, res_mem->start, resource_size(res_mem));
 
 	init_waitqueue_head(&i2c->queue);
 
@@ -585,6 +978,7 @@ static int octeon_i2c_probe(struct platform_device *pdev)
 	}
 
 	i2c->adap = octeon_i2c_ops;
+	i2c->adap.timeout = msecs_to_jiffies(50);
 	i2c->adap.dev.parent = &pdev->dev;
 	i2c->adap.dev.of_node = pdev->dev.of_node;
 	i2c_set_adapdata(&i2c->adap, i2c);
-- 
1.8.1.4



More information about the linux-yocto mailing list