[PATCH 4/6] i2c: fsl_i2c: fix m68k transferts

Angelo Dureghello angelo at kernel-space.org
Wed Apr 5 00:59:26 CEST 2023


This driver is actually used for powerpc and m68k/ColdFire.

On ColdFire SoC's, interrupt flag get not set if IIEN flag (mbcr bit6,
interrupt enabled) is not set appropriately before each transfert.
As a result, the transfert hangs forever waiting for IIEN.
This patch set IIEN before each transfert, while considering this fix
as not harming powerpc arch.

Signed-off-by: Angelo Dureghello <angelo at kernel-space.org>
---
 arch/m68k/include/asm/fsl_i2c.h | 10 ++++++++++
 drivers/i2c/fsl_i2c.c           | 16 +++++++++-------
 2 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/arch/m68k/include/asm/fsl_i2c.h b/arch/m68k/include/asm/fsl_i2c.h
index 9c54fdea77..dc6b37a575 100644
--- a/arch/m68k/include/asm/fsl_i2c.h
+++ b/arch/m68k/include/asm/fsl_i2c.h
@@ -57,4 +57,14 @@ typedef struct fsl_i2c_base {
 #define I2C_DR_RES	~(I2C_DR)
 } fsl_i2c_t;
 
+#if CONFIG_IS_ENABLED(DM_I2C)
+struct fsl_i2c_dev {
+	struct fsl_i2c_base __iomem *base;      /* register base */
+	u32 i2c_clk;
+	u32 index;
+	u8 slaveadd;
+	uint speed;
+};
+#endif
+
 #endif	/* _ASM_I2C_H_ */
diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c
index d312f35f04..d9d8ee81d2 100644
--- a/drivers/i2c/fsl_i2c.c
+++ b/drivers/i2c/fsl_i2c.c
@@ -278,7 +278,8 @@ static void __i2c_init(const struct fsl_i2c_base *base, int speed, int
 	set_i2c_bus_speed(base, i2c_clk, speed);
 	writeb(slaveadd << 1, &base->adr);/* write slave address */
 	writeb(0x0, &base->sr);		/* clear status register */
-	writeb(I2C_CR_MEN, &base->cr);	/* start I2C controller */
+	/* start I2C controller */
+	writeb(I2C_CR_MEN | I2C_CR_MIEN, &base->cr);
 
 	timeval = get_ticks();
 	while (readb(&base->sr) & I2C_SR_MBB) {
@@ -346,7 +347,7 @@ static int i2c_wait(const struct fsl_i2c_base *base, int write)
 static int i2c_write_addr(const struct fsl_i2c_base *base, u8 dev,
 			  u8 dir, int rsta)
 {
-	writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_MTX
+	writeb(I2C_CR_MEN | I2C_CR_MIEN | I2C_CR_MSTA | I2C_CR_MTX
 	       | (rsta ? I2C_CR_RSTA : 0),
 	       &base->cr);
 
@@ -378,7 +379,8 @@ static int __i2c_read_data(const struct fsl_i2c_base *base, u8 *data,
 {
 	int i;
 
-	writeb(I2C_CR_MEN | I2C_CR_MSTA | ((length == 1) ? I2C_CR_TXAK : 0),
+	writeb(I2C_CR_MEN | I2C_CR_MIEN |
+	       I2C_CR_MSTA | ((length == 1) ? I2C_CR_TXAK : 0),
 	       &base->cr);
 
 	/* dummy read */
@@ -390,13 +392,13 @@ static int __i2c_read_data(const struct fsl_i2c_base *base, u8 *data,
 
 		/* Generate ack on last next to last byte */
 		if (i == length - 2)
-			writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_TXAK,
-			       &base->cr);
+			writeb(I2C_CR_MEN | I2C_CR_MIEN | I2C_CR_MSTA |
+			       I2C_CR_TXAK, &base->cr);
 
 		/* Do not generate stop on last byte */
 		if (i == length - 1)
-			writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_MTX,
-			       &base->cr);
+			writeb(I2C_CR_MEN | I2C_CR_MIEN | I2C_CR_MSTA |
+			       I2C_CR_MTX, &base->cr);
 
 		data[i] = readb(&base->dr);
 	}
-- 
2.40.0



More information about the U-Boot mailing list