ソースを参照

Merge branch 'i2c-fixes' of git://git.fluff.org/bjdooks/linux

* 'i2c-fixes' of git://git.fluff.org/bjdooks/linux:
  i2c-omap: OMAP3: Fix I2C lockup during timeout/error cases
  i2c-omap: Don't write IE state in unidle if 0
  i2c-bfin-twi: fix CLKDIV calculation
Linus Torvalds 15 年 前
コミット
4310471668
2 ファイル変更15 行追加4 行削除
  1. 3 3
      drivers/i2c/busses/i2c-bfin-twi.c
  2. 12 1
      drivers/i2c/busses/i2c-omap.c

+ 3 - 3
drivers/i2c/busses/i2c-bfin-twi.c

@@ -693,13 +693,13 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
 	}
 
 	/* Set TWI internal clock as 10MHz */
-	write_CONTROL(iface, ((get_sclk() / 1024 / 1024 + 5) / 10) & 0x7F);
+	write_CONTROL(iface, ((get_sclk() / 1000 / 1000 + 5) / 10) & 0x7F);
 
 	/*
 	 * We will not end up with a CLKDIV=0 because no one will specify
-	 * 20kHz SCL or less in Kconfig now. (5 * 1024 / 20 = 0x100)
+	 * 20kHz SCL or less in Kconfig now. (5 * 1000 / 20 = 250)
 	 */
-	clkhilow = 5 * 1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ;
+	clkhilow = ((10 * 1000 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ) + 1) / 2;
 
 	/* Set Twi interface clock as specified */
 	write_CLKDIV(iface, (clkhilow << 8) | clkhilow);

+ 12 - 1
drivers/i2c/busses/i2c-omap.c

@@ -247,7 +247,13 @@ static void omap_i2c_unidle(struct omap_i2c_dev *dev)
 		omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
 	}
 	dev->idle = 0;
-	omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
+
+	/*
+	 * Don't write to this register if the IE state is 0 as it can
+	 * cause deadlock.
+	 */
+	if (dev->iestate)
+		omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
 }
 
 static void omap_i2c_idle(struct omap_i2c_dev *dev)
@@ -280,6 +286,11 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
 	unsigned long internal_clk = 0;
 
 	if (dev->rev >= OMAP_I2C_REV_2) {
+		/* Disable I2C controller before soft reset */
+		omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
+			omap_i2c_read_reg(dev, OMAP_I2C_CON_REG) &
+				~(OMAP_I2C_CON_EN));
+
 		omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, SYSC_SOFTRESET_MASK);
 		/* For some reason we need to set the EN bit before the
 		 * reset done bit gets set. */