Merge branch 'master' of git://git.denx.de/u-boot-i2c

This pull request contains bugfixes for rcar_i2c, rcar_ii2c and
i2c_cdns driver.

Also the commit "i2c: rcar_i2c: Add Gen3 SoC support" from Marek
is a bugfix for arm64 builds, as discussed with Marek on list.
diff --git a/drivers/i2c/i2c-cdns.c b/drivers/i2c/i2c-cdns.c
index 4330d28..1af94d1 100644
--- a/drivers/i2c/i2c-cdns.c
+++ b/drivers/i2c/i2c-cdns.c
@@ -64,12 +64,24 @@
 #define CDNS_I2C_INTERRUPT_RXUNF	0x00000080
 #define CDNS_I2C_INTERRUPT_ARBLOST	0x00000200
 
+#define CDNS_I2C_INTERRUPTS_MASK	(CDNS_I2C_INTERRUPT_COMP | \
+					CDNS_I2C_INTERRUPT_DATA | \
+					CDNS_I2C_INTERRUPT_NACK | \
+					CDNS_I2C_INTERRUPT_TO | \
+					CDNS_I2C_INTERRUPT_SLVRDY | \
+					CDNS_I2C_INTERRUPT_RXOVF | \
+					CDNS_I2C_INTERRUPT_TXOVF | \
+					CDNS_I2C_INTERRUPT_RXUNF | \
+					CDNS_I2C_INTERRUPT_ARBLOST)
+
 #define CDNS_I2C_FIFO_DEPTH		16
 #define CDNS_I2C_TRANSFER_SIZE_MAX	255 /* Controller transfer limit */
 #define CDNS_I2C_TRANSFER_SIZE		(CDNS_I2C_TRANSFER_SIZE_MAX - 3)
 
 #define CDNS_I2C_BROKEN_HOLD_BIT	BIT(0)
 
+#define CDNS_I2C_ARB_LOST_MAX_RETRIES	10
+
 #ifdef DEBUG
 static void cdns_i2c_debug_status(struct cdns_i2c_regs *cdns_i2c)
 {
@@ -224,11 +236,17 @@
 	return 0;
 }
 
+static inline u32 is_arbitration_lost(struct cdns_i2c_regs *regs)
+{
+	return (readl(&regs->interrupt_status) & CDNS_I2C_INTERRUPT_ARBLOST);
+}
+
 static int cdns_i2c_write_data(struct i2c_cdns_bus *i2c_bus, u32 addr, u8 *data,
 			       u32 len)
 {
 	u8 *cur_data = data;
 	struct cdns_i2c_regs *regs = i2c_bus->regs;
+	u32 ret;
 
 	/* Set the controller in Master transmit mode and clear FIFO */
 	setbits_le32(&regs->control, CDNS_I2C_CONTROL_CLR_FIFO);
@@ -241,29 +259,42 @@
 		setbits_le32(&regs->control, CDNS_I2C_CONTROL_HOLD);
 
 	/* Clear the interrupts in status register */
-	writel(0xFF, &regs->interrupt_status);
+	writel(CDNS_I2C_INTERRUPTS_MASK, &regs->interrupt_status);
 
 	writel(addr, &regs->address);
 
-	while (len--) {
+	while (len-- && !is_arbitration_lost(regs)) {
 		writel(*(cur_data++), &regs->data);
 		if (readl(&regs->transfer_size) == CDNS_I2C_FIFO_DEPTH) {
-			if (!cdns_i2c_wait(regs, CDNS_I2C_INTERRUPT_COMP)) {
-				/* Release the bus */
-				clrbits_le32(&regs->control,
-					     CDNS_I2C_CONTROL_HOLD);
-				return -ETIMEDOUT;
-			}
+			ret = cdns_i2c_wait(regs, CDNS_I2C_INTERRUPT_COMP |
+					    CDNS_I2C_INTERRUPT_ARBLOST);
+			if (ret & CDNS_I2C_INTERRUPT_ARBLOST)
+				return -EAGAIN;
+			if (ret & CDNS_I2C_INTERRUPT_COMP)
+				continue;
+			/* Release the bus */
+			clrbits_le32(&regs->control,
+				     CDNS_I2C_CONTROL_HOLD);
+			return -ETIMEDOUT;
 		}
 	}
 
+	if (len && is_arbitration_lost(regs))
+		return -EAGAIN;
+
 	/* All done... release the bus */
 	if (!i2c_bus->hold_flag)
 		clrbits_le32(&regs->control, CDNS_I2C_CONTROL_HOLD);
 
 	/* Wait for the address and data to be sent */
-	if (!cdns_i2c_wait(regs, CDNS_I2C_INTERRUPT_COMP))
+	ret = cdns_i2c_wait(regs, CDNS_I2C_INTERRUPT_COMP |
+			    CDNS_I2C_INTERRUPT_ARBLOST);
+	if (!(ret & (CDNS_I2C_INTERRUPT_ARBLOST |
+		     CDNS_I2C_INTERRUPT_COMP)))
 		return -ETIMEDOUT;
+	if (ret & CDNS_I2C_INTERRUPT_ARBLOST)
+		return -EAGAIN;
+
 	return 0;
 }
 
@@ -279,6 +310,7 @@
 	struct cdns_i2c_regs *regs = i2c_bus->regs;
 	int curr_recv_count;
 	int updatetx, hold_quirk;
+	u32 ret;
 
 	/* Check the hardware can handle the requested bytes */
 	if ((recv_count < 0))
@@ -307,7 +339,7 @@
 
 	hold_quirk = (i2c_bus->quirks & CDNS_I2C_BROKEN_HOLD_BIT) && updatetx;
 
-	while (recv_count) {
+	while (recv_count && !is_arbitration_lost(regs)) {
 		while (readl(&regs->status) & CDNS_I2C_STATUS_RXDV) {
 			if (recv_count < CDNS_I2C_FIFO_DEPTH &&
 			    !i2c_bus->hold_flag) {
@@ -356,8 +388,13 @@
 	}
 
 	/* Wait for the address and data to be sent */
-	if (!cdns_i2c_wait(regs, CDNS_I2C_INTERRUPT_COMP))
+	ret = cdns_i2c_wait(regs, CDNS_I2C_INTERRUPT_COMP |
+			    CDNS_I2C_INTERRUPT_ARBLOST);
+	if (!(ret & (CDNS_I2C_INTERRUPT_ARBLOST |
+		     CDNS_I2C_INTERRUPT_COMP)))
 		return -ETIMEDOUT;
+	if (ret & CDNS_I2C_INTERRUPT_ARBLOST)
+		return -EAGAIN;
 
 	return 0;
 }
@@ -366,8 +403,11 @@
 			 int nmsgs)
 {
 	struct i2c_cdns_bus *i2c_bus = dev_get_priv(dev);
-	int ret, count;
+	int ret = 0;
+	int count;
 	bool hold_quirk;
+	struct i2c_msg *message = msg;
+	int num_msgs = nmsgs;
 
 	hold_quirk = !!(i2c_bus->quirks & CDNS_I2C_BROKEN_HOLD_BIT);
 
@@ -393,7 +433,8 @@
 	}
 
 	debug("i2c_xfer: %d messages\n", nmsgs);
-	for (; nmsgs > 0; nmsgs--, msg++) {
+	for (u8 retry = 0; retry < CDNS_I2C_ARB_LOST_MAX_RETRIES &&
+	     nmsgs > 0; nmsgs--, msg++) {
 		debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len);
 		if (msg->flags & I2C_M_RD) {
 			ret = cdns_i2c_read_data(i2c_bus, msg->addr, msg->buf,
@@ -402,13 +443,22 @@
 			ret = cdns_i2c_write_data(i2c_bus, msg->addr, msg->buf,
 						  msg->len);
 		}
+		if (ret == -EAGAIN) {
+			msg = message;
+			nmsgs = num_msgs;
+			retry++;
+			printf("%s,arbitration lost, retrying:%d\n", __func__,
+			       retry);
+			continue;
+		}
+
 		if (ret) {
 			debug("i2c_write: error sending\n");
 			return -EREMOTEIO;
 		}
 	}
 
-	return 0;
+	return ret;
 }
 
 static int cdns_i2c_ofdata_to_platdata(struct udevice *dev)
diff --git a/drivers/i2c/rcar_i2c.c b/drivers/i2c/rcar_i2c.c
index 8d87c73..2ebae34 100644
--- a/drivers/i2c/rcar_i2c.c
+++ b/drivers/i2c/rcar_i2c.c
@@ -18,39 +18,52 @@
 #include <asm/io.h>
 #include <wait_bit.h>
 
-#define RCAR_I2C_ICSCR			0x00
-#define RCAR_I2C_ICMCR			0x04
-#define RCAR_I2C_ICMCR_MDBS		BIT(7)
-#define RCAR_I2C_ICMCR_FSCL		BIT(6)
-#define RCAR_I2C_ICMCR_FSDA		BIT(5)
-#define RCAR_I2C_ICMCR_OBPC		BIT(4)
-#define RCAR_I2C_ICMCR_MIE		BIT(3)
+#define RCAR_I2C_ICSCR			0x00 /* slave ctrl */
+#define RCAR_I2C_ICMCR			0x04 /* master ctrl */
+#define RCAR_I2C_ICMCR_MDBS		BIT(7) /* non-fifo mode switch */
+#define RCAR_I2C_ICMCR_FSCL		BIT(6) /* override SCL pin */
+#define RCAR_I2C_ICMCR_FSDA		BIT(5) /* override SDA pin */
+#define RCAR_I2C_ICMCR_OBPC		BIT(4) /* override pins */
+#define RCAR_I2C_ICMCR_MIE		BIT(3) /* master if enable */
 #define RCAR_I2C_ICMCR_TSBE		BIT(2)
-#define RCAR_I2C_ICMCR_FSB		BIT(1)
-#define RCAR_I2C_ICMCR_ESG		BIT(0)
-#define RCAR_I2C_ICSSR			0x08
-#define RCAR_I2C_ICMSR			0x0c
+#define RCAR_I2C_ICMCR_FSB		BIT(1) /* force stop bit */
+#define RCAR_I2C_ICMCR_ESG		BIT(0) /* enable start bit gen */
+#define RCAR_I2C_ICSSR			0x08 /* slave status */
+#define RCAR_I2C_ICMSR			0x0c /* master status */
 #define RCAR_I2C_ICMSR_MASK		0x7f
-#define RCAR_I2C_ICMSR_MNR		BIT(6)
-#define RCAR_I2C_ICMSR_MAL		BIT(5)
-#define RCAR_I2C_ICMSR_MST		BIT(4)
+#define RCAR_I2C_ICMSR_MNR		BIT(6) /* Nack */
+#define RCAR_I2C_ICMSR_MAL		BIT(5) /* Arbitration lost */
+#define RCAR_I2C_ICMSR_MST		BIT(4) /* Stop */
 #define RCAR_I2C_ICMSR_MDE		BIT(3)
 #define RCAR_I2C_ICMSR_MDT		BIT(2)
 #define RCAR_I2C_ICMSR_MDR		BIT(1)
 #define RCAR_I2C_ICMSR_MAT		BIT(0)
-#define RCAR_I2C_ICSIER			0x10
-#define RCAR_I2C_ICMIER			0x14
-#define RCAR_I2C_ICCCR			0x18
+#define RCAR_I2C_ICSIER			0x10 /* slave irq enable */
+#define RCAR_I2C_ICMIER			0x14 /* master irq enable */
+#define RCAR_I2C_ICCCR			0x18 /* clock dividers */
 #define RCAR_I2C_ICCCR_SCGD_OFF		3
-#define RCAR_I2C_ICSAR			0x1c
-#define RCAR_I2C_ICMAR			0x20
-#define RCAR_I2C_ICRXD_ICTXD		0x24
+#define RCAR_I2C_ICSAR			0x1c /* slave address */
+#define RCAR_I2C_ICMAR			0x20 /* master address */
+#define RCAR_I2C_ICRXD_ICTXD		0x24 /* data port */
+/*
+ * First Bit Setup Cycle (Gen3).
+ * Defines 1st bit delay between SDA and SCL.
+ */
+#define RCAR_I2C_ICFBSCR		0x38
+#define RCAR_I2C_ICFBSCR_TCYC17		0x0f /* 17*Tcyc */
+
+
+enum rcar_i2c_type {
+	RCAR_I2C_TYPE_GEN2,
+	RCAR_I2C_TYPE_GEN3,
+};
 
 struct rcar_i2c_priv {
 	void __iomem		*base;
 	struct clk		clk;
 	u32			intdelay;
 	u32			icccr;
+	enum rcar_i2c_type	type;
 };
 
 static int rcar_i2c_finish(struct udevice *dev)
@@ -68,12 +81,13 @@
 	return ret;
 }
 
-static void rcar_i2c_recover(struct udevice *dev)
+static int rcar_i2c_recover(struct udevice *dev)
 {
 	struct rcar_i2c_priv *priv = dev_get_priv(dev);
 	u32 mcr = RCAR_I2C_ICMCR_MDBS | RCAR_I2C_ICMCR_OBPC;
 	u32 mcra = mcr | RCAR_I2C_ICMCR_FSDA;
 	int i;
+	u32 mstat;
 
 	/* Send 9 SCL pulses */
 	for (i = 0; i < 9; i++) {
@@ -93,6 +107,9 @@
 	udelay(5);
 	writel(mcra | RCAR_I2C_ICMCR_FSCL, priv->base + RCAR_I2C_ICMCR);
 	udelay(5);
+
+	mstat = readl(priv->base + RCAR_I2C_ICMSR);
+	return mstat & RCAR_I2C_ICMCR_FSDA ? -EBUSY : 0;
 }
 
 static int rcar_i2c_set_addr(struct udevice *dev, u8 chip, u8 read)
@@ -100,7 +117,6 @@
 	struct rcar_i2c_priv *priv = dev_get_priv(dev);
 	u32 mask = RCAR_I2C_ICMSR_MAT |
 		   (read ? RCAR_I2C_ICMSR_MDR : RCAR_I2C_ICMSR_MDE);
-	u32 val;
 	int ret;
 
 	writel(0, priv->base + RCAR_I2C_ICMIER);
@@ -108,21 +124,22 @@
 	writel(0, priv->base + RCAR_I2C_ICMSR);
 	writel(priv->icccr, priv->base + RCAR_I2C_ICCCR);
 
+	/* Wait for the bus */
 	ret = wait_for_bit_le32(priv->base + RCAR_I2C_ICMCR,
 				RCAR_I2C_ICMCR_FSDA, false, 2, true);
 	if (ret) {
-		rcar_i2c_recover(dev);
-		val = readl(priv->base + RCAR_I2C_ICMSR);
-		if (val & RCAR_I2C_ICMCR_FSDA) {
+		if (rcar_i2c_recover(dev)) {
 			dev_err(dev, "Bus busy, aborting\n");
 			return ret;
 		}
 	}
 
 	writel((chip << 1) | read, priv->base + RCAR_I2C_ICMAR);
-	writel(0, priv->base + RCAR_I2C_ICMSR);
+	/* Reset */
 	writel(RCAR_I2C_ICMCR_MDBS | RCAR_I2C_ICMCR_MIE | RCAR_I2C_ICMCR_ESG,
 	       priv->base + RCAR_I2C_ICMCR);
+	/* Clear Status */
+	writel(0, priv->base + RCAR_I2C_ICMSR);
 
 	ret = wait_for_bit_le32(priv->base + RCAR_I2C_ICMSR, mask,
 				true, 100, true);
@@ -142,16 +159,12 @@
 	u32 icmcr = RCAR_I2C_ICMCR_MDBS | RCAR_I2C_ICMCR_MIE;
 	int i, ret = -EREMOTEIO;
 
-	ret = rcar_i2c_set_addr(dev, msg->addr, 1);
-	if (ret)
-		return ret;
-
 	for (i = 0; i < msg->len; i++) {
 		if (msg->len - 1 == i)
 			icmcr |= RCAR_I2C_ICMCR_FSB;
 
 		writel(icmcr, priv->base + RCAR_I2C_ICMCR);
-		writel(~RCAR_I2C_ICMSR_MDR, priv->base + RCAR_I2C_ICMSR);
+		writel((u32)~RCAR_I2C_ICMSR_MDR, priv->base + RCAR_I2C_ICMSR);
 
 		ret = wait_for_bit_le32(priv->base + RCAR_I2C_ICMSR,
 					RCAR_I2C_ICMSR_MDR, true, 100, true);
@@ -161,7 +174,7 @@
 		msg->buf[i] = readl(priv->base + RCAR_I2C_ICRXD_ICTXD) & 0xff;
 	}
 
-	writel(~RCAR_I2C_ICMSR_MDR, priv->base + RCAR_I2C_ICMSR);
+	writel((u32)~RCAR_I2C_ICMSR_MDR, priv->base + RCAR_I2C_ICMSR);
 
 	return rcar_i2c_finish(dev);
 }
@@ -172,14 +185,10 @@
 	u32 icmcr = RCAR_I2C_ICMCR_MDBS | RCAR_I2C_ICMCR_MIE;
 	int i, ret = -EREMOTEIO;
 
-	ret = rcar_i2c_set_addr(dev, msg->addr, 0);
-	if (ret)
-		return ret;
-
 	for (i = 0; i < msg->len; i++) {
 		writel(msg->buf[i], priv->base + RCAR_I2C_ICRXD_ICTXD);
 		writel(icmcr, priv->base + RCAR_I2C_ICMCR);
-		writel(~RCAR_I2C_ICMSR_MDE, priv->base + RCAR_I2C_ICMSR);
+		writel((u32)~RCAR_I2C_ICMSR_MDE, priv->base + RCAR_I2C_ICMSR);
 
 		ret = wait_for_bit_le32(priv->base + RCAR_I2C_ICMSR,
 					RCAR_I2C_ICMSR_MDE, true, 100, true);
@@ -187,7 +196,7 @@
 			return ret;
 	}
 
-	writel(~RCAR_I2C_ICMSR_MDE, priv->base + RCAR_I2C_ICMSR);
+	writel((u32)~RCAR_I2C_ICMSR_MDE, priv->base + RCAR_I2C_ICMSR);
 	icmcr |= RCAR_I2C_ICMCR_FSB;
 	writel(icmcr, priv->base + RCAR_I2C_ICMCR);
 
@@ -199,16 +208,20 @@
 	int ret;
 
 	for (; nmsgs > 0; nmsgs--, msg++) {
+		ret = rcar_i2c_set_addr(dev, msg->addr, 1);
+		if (ret)
+			return ret;
+
 		if (msg->flags & I2C_M_RD)
 			ret = rcar_i2c_read_common(dev, msg);
 		else
 			ret = rcar_i2c_write_common(dev, msg);
 
 		if (ret)
-			return -EREMOTEIO;
+			return ret;
 	}
 
-	return ret;
+	return 0;
 }
 
 static int rcar_i2c_probe_chip(struct udevice *dev, uint addr, uint flags)
@@ -293,6 +306,11 @@
 	priv->icccr = (scgd << RCAR_I2C_ICCCR_SCGD_OFF) | cdf;
 	writel(priv->icccr, priv->base + RCAR_I2C_ICCCR);
 
+	if (priv->type == RCAR_I2C_TYPE_GEN3) {
+		/* Set SCL/SDA delay */
+		writel(RCAR_I2C_ICFBSCR_TCYC17, priv->base + RCAR_I2C_ICFBSCR);
+	}
+
 	return 0;
 }
 
@@ -304,6 +322,7 @@
 	priv->base = dev_read_addr_ptr(dev);
 	priv->intdelay = dev_read_u32_default(dev,
 					      "i2c-scl-internal-delay-ns", 5);
+	priv->type = dev_get_driver_data(dev);
 
 	ret = clk_get_by_index(dev, 0, &priv->clk);
 	if (ret)
@@ -339,7 +358,8 @@
 };
 
 static const struct udevice_id rcar_i2c_ids[] = {
-	{ .compatible = "renesas,rcar-gen2-i2c" },
+	{ .compatible = "renesas,rcar-gen2-i2c", .data = RCAR_I2C_TYPE_GEN2 },
+	{ .compatible = "renesas,rcar-gen3-i2c", .data = RCAR_I2C_TYPE_GEN3 },
 	{ }
 };
 
diff --git a/drivers/i2c/rcar_iic.c b/drivers/i2c/rcar_iic.c
index e91fc86..9d45f54 100644
--- a/drivers/i2c/rcar_iic.c
+++ b/drivers/i2c/rcar_iic.c
@@ -58,12 +58,14 @@
 static int sh_irq_dte_with_tack(struct udevice *dev)
 {
 	struct rcar_iic_priv *priv = dev_get_priv(dev);
+	u8 icsr;
 	int i;
 
 	for (i = 0; i < IRQ_WAIT; i++) {
-		if (RCAR_IC_DTE & readb(priv->base + RCAR_IIC_ICSR))
+		icsr = readb(priv->base + RCAR_IIC_ICSR);
+		if (RCAR_IC_DTE & icsr)
 			break;
-		if (RCAR_IC_TACK & readb(priv->base + RCAR_IIC_ICSR))
+		if (RCAR_IC_TACK & icsr)
 			return -ETIMEDOUT;
 		udelay(10);
 	}