All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] i2c: imx: check busy bit when START/STOP
@ 2009-10-01  1:13 ` Richard Zhao
  0 siblings, 0 replies; 52+ messages in thread
From: Richard Zhao @ 2009-10-01  1:13 UTC (permalink / raw)
  To: kernel-bIcnvbaLZ9MEGnE8C9+IrQ
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ, w.sang-bIcnvbaLZ9MEGnE8C9+IrQ,
	Richard Zhao

After START/RESTART, wait for busy bit to be set and
after STOP, wait for busy bit to be clear.

Signed-off-by: Richard Zhao <linuxzsc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 4afba3e..156cc95 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -125,14 +125,19 @@ struct imx_i2c_struct {
 /** Functions for IMX I2C adapter driver ***************************************
 *******************************************************************************/
 
-static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx)
+static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy)
 {
 	unsigned long orig_jiffies = jiffies;
+	unsigned int temp;
 
 	dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
 
-	/* wait for bus not busy */
-	while (readb(i2c_imx->base + IMX_I2C_I2SR) & I2SR_IBB) {
+	temp = readb(i2c_imx->base + IMX_I2C_I2SR);
+	while (1) {
+		if (for_busy && (temp & I2SR_IBB))
+			break;
+		if (!for_busy && !(temp & I2SR_IBB))
+			break;
 		if (signal_pending(current)) {
 			dev_dbg(&i2c_imx->adapter.dev,
 				"<%s> I2C Interrupted\n", __func__);
@@ -144,6 +149,7 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx)
 			return -EIO;
 		}
 		schedule();
+		temp = readb(i2c_imx->base + IMX_I2C_I2SR);
 	}
 
 	return 0;
@@ -179,20 +185,32 @@ static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx)
 	return 0;
 }
 
-static void i2c_imx_start(struct imx_i2c_struct *i2c_imx)
+static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
 {
 	unsigned int temp = 0;
+	int result;
 
 	dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
 
 	/* Enable I2C controller */
+	writeb(0, i2c_imx->base + IMX_I2C_I2SR);
 	writeb(I2CR_IEN, i2c_imx->base + IMX_I2C_I2CR);
+
+	result = i2c_imx_bus_busy(i2c_imx, 0);
+	if (result)
+		return result;
+
 	/* Start I2C transaction */
 	temp = readb(i2c_imx->base + IMX_I2C_I2CR);
 	temp |= I2CR_MSTA;
 	writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+	result = i2c_imx_bus_busy(i2c_imx, 1);
+	if (result)
+		return result;
+
 	temp |= I2CR_IIEN | I2CR_MTX | I2CR_TXAK;
 	writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+	return result;
 }
 
 static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
@@ -202,16 +220,16 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
 	/* Stop I2C transaction */
 	dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
 	temp = readb(i2c_imx->base + IMX_I2C_I2CR);
-	temp &= ~I2CR_MSTA;
+	temp &= ~(I2CR_MSTA | I2CR_MTX);
 	writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
-	/* setup chip registers to defaults */
-	writeb(I2CR_IEN, i2c_imx->base + IMX_I2C_I2CR);
-	writeb(0, i2c_imx->base + IMX_I2C_I2SR);
 	/*
 	 * This delay caused by an i.MXL hardware bug.
 	 * If no (or too short) delay, no "STOP" bit will be generated.
 	 */
 	udelay(i2c_imx->disable_delay);
+
+	i2c_imx_bus_busy(i2c_imx, 0);
+
 	/* Disable I2C controller */
 	writeb(0, i2c_imx->base + IMX_I2C_I2CR);
 }
@@ -344,7 +362,7 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
 			dev_dbg(&i2c_imx->adapter.dev,
 				"<%s> clear MSTA\n", __func__);
 			temp = readb(i2c_imx->base + IMX_I2C_I2CR);
-			temp &= ~I2CR_MSTA;
+			temp &= ~(I2CR_MSTA | I2CR_MTX);
 			writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
 		} else if (i == (msgs->len - 2)) {
 			dev_dbg(&i2c_imx->adapter.dev,
@@ -370,14 +388,11 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
 
 	dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
 
-	/* Check if i2c bus is not busy */
-	result = i2c_imx_bus_busy(i2c_imx);
+	/* Start I2C transfer */
+	result = i2c_imx_start(i2c_imx);
 	if (result)
 		goto fail0;
 
-	/* Start I2C transfer */
-	i2c_imx_start(i2c_imx);
-
 	/* read/write data */
 	for (i = 0; i < num; i++) {
 		if (i) {
@@ -386,6 +401,9 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
 			temp = readb(i2c_imx->base + IMX_I2C_I2CR);
 			temp |= I2CR_RSTA;
 			writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+			result =  i2c_imx_bus_busy(i2c_imx, 1);
+			if (result)
+				goto fail0;
 		}
 		dev_dbg(&i2c_imx->adapter.dev,
 			"<%s> transfer message: %d\n", __func__, i);
-- 
1.6.0.4

^ permalink raw reply related	[flat|nested] 52+ messages in thread
* [PATCH 1/4] i2c: imx: check busy bit when START/STOP
@ 2009-09-30  5:55 Richard Zhao
  0 siblings, 0 replies; 52+ messages in thread
From: Richard Zhao @ 2009-09-30  5:55 UTC (permalink / raw)
  To: kernel-bIcnvbaLZ9MEGnE8C9+IrQ
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, Richard Zhao

After START/RESTART, wait for busy bit to be set and
after STOP, wait for busy bit to be clear.

Signed-off-by: Richard Zhao <linuxzsc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 4afba3e..156cc95 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -125,14 +125,19 @@ struct imx_i2c_struct {
 /** Functions for IMX I2C adapter driver ***************************************
 *******************************************************************************/
 
-static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx)
+static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy)
 {
 	unsigned long orig_jiffies = jiffies;
+	unsigned int temp;
 
 	dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
 
-	/* wait for bus not busy */
-	while (readb(i2c_imx->base + IMX_I2C_I2SR) & I2SR_IBB) {
+	temp = readb(i2c_imx->base + IMX_I2C_I2SR);
+	while (1) {
+		if (for_busy && (temp & I2SR_IBB))
+			break;
+		if (!for_busy && !(temp & I2SR_IBB))
+			break;
 		if (signal_pending(current)) {
 			dev_dbg(&i2c_imx->adapter.dev,
 				"<%s> I2C Interrupted\n", __func__);
@@ -144,6 +149,7 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx)
 			return -EIO;
 		}
 		schedule();
+		temp = readb(i2c_imx->base + IMX_I2C_I2SR);
 	}
 
 	return 0;
@@ -179,20 +185,32 @@ static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx)
 	return 0;
 }
 
-static void i2c_imx_start(struct imx_i2c_struct *i2c_imx)
+static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
 {
 	unsigned int temp = 0;
+	int result;
 
 	dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
 
 	/* Enable I2C controller */
+	writeb(0, i2c_imx->base + IMX_I2C_I2SR);
 	writeb(I2CR_IEN, i2c_imx->base + IMX_I2C_I2CR);
+
+	result = i2c_imx_bus_busy(i2c_imx, 0);
+	if (result)
+		return result;
+
 	/* Start I2C transaction */
 	temp = readb(i2c_imx->base + IMX_I2C_I2CR);
 	temp |= I2CR_MSTA;
 	writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+	result = i2c_imx_bus_busy(i2c_imx, 1);
+	if (result)
+		return result;
+
 	temp |= I2CR_IIEN | I2CR_MTX | I2CR_TXAK;
 	writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+	return result;
 }
 
 static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
@@ -202,16 +220,16 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
 	/* Stop I2C transaction */
 	dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
 	temp = readb(i2c_imx->base + IMX_I2C_I2CR);
-	temp &= ~I2CR_MSTA;
+	temp &= ~(I2CR_MSTA | I2CR_MTX);
 	writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
-	/* setup chip registers to defaults */
-	writeb(I2CR_IEN, i2c_imx->base + IMX_I2C_I2CR);
-	writeb(0, i2c_imx->base + IMX_I2C_I2SR);
 	/*
 	 * This delay caused by an i.MXL hardware bug.
 	 * If no (or too short) delay, no "STOP" bit will be generated.
 	 */
 	udelay(i2c_imx->disable_delay);
+
+	i2c_imx_bus_busy(i2c_imx, 0);
+
 	/* Disable I2C controller */
 	writeb(0, i2c_imx->base + IMX_I2C_I2CR);
 }
@@ -344,7 +362,7 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
 			dev_dbg(&i2c_imx->adapter.dev,
 				"<%s> clear MSTA\n", __func__);
 			temp = readb(i2c_imx->base + IMX_I2C_I2CR);
-			temp &= ~I2CR_MSTA;
+			temp &= ~(I2CR_MSTA | I2CR_MTX);
 			writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
 		} else if (i == (msgs->len - 2)) {
 			dev_dbg(&i2c_imx->adapter.dev,
@@ -370,14 +388,11 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
 
 	dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
 
-	/* Check if i2c bus is not busy */
-	result = i2c_imx_bus_busy(i2c_imx);
+	/* Start I2C transfer */
+	result = i2c_imx_start(i2c_imx);
 	if (result)
 		goto fail0;
 
-	/* Start I2C transfer */
-	i2c_imx_start(i2c_imx);
-
 	/* read/write data */
 	for (i = 0; i < num; i++) {
 		if (i) {
@@ -386,6 +401,9 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
 			temp = readb(i2c_imx->base + IMX_I2C_I2CR);
 			temp |= I2CR_RSTA;
 			writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+			result =  i2c_imx_bus_busy(i2c_imx, 1);
+			if (result)
+				goto fail0;
 		}
 		dev_dbg(&i2c_imx->adapter.dev,
 			"<%s> transfer message: %d\n", __func__, i);
-- 
1.6.0.4

^ permalink raw reply related	[flat|nested] 52+ messages in thread

end of thread, other threads:[~2009-10-04 12:30 UTC | newest]

Thread overview: 52+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-10-01  1:13 [PATCH 1/4] i2c: imx: check busy bit when START/STOP Richard Zhao
2009-10-01  1:13 ` Richard Zhao
     [not found] ` <1254359613-21210-1-git-send-email-linuxzsc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2009-10-01  1:13   ` [PATCH 2/4] i2c: imx: only imx1 needs disable delay Richard Zhao
2009-10-01  1:13     ` Richard Zhao
     [not found]     ` <1254359613-21210-2-git-send-email-linuxzsc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2009-10-01  1:13       ` [PATCH 3/4] i2c: imx: add macros and printk to make debug easy Richard Zhao
2009-10-01  1:13         ` Richard Zhao
     [not found]         ` <1254359613-21210-3-git-send-email-linuxzsc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2009-10-01  1:13           ` [PATCH 4/4] i2c: imx: disable clock when it's possible to save power Richard Zhao
2009-10-01  1:13             ` Richard Zhao
     [not found]             ` <1254359613-21210-4-git-send-email-linuxzsc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2009-10-01  7:34               ` Sascha Hauer
2009-10-01  7:34                 ` Sascha Hauer
     [not found]                 ` <20091001073434.GY27039-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2009-10-01  7:56                   ` Richard Zhao
2009-10-01  7:56                     ` Richard Zhao
     [not found]                     ` <4e090d470910010056n56bff9f4l1fec703c2dde9edf-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2009-10-01  8:00                       ` Sascha Hauer
2009-10-01  8:00                         ` Sascha Hauer
2009-10-04 12:30                         ` Richard Zhao
2009-10-01  7:29           ` [PATCH 3/4] i2c: imx: add macros and printk to make debug easy Sascha Hauer
2009-10-01  7:29             ` Sascha Hauer
     [not found]             ` <20091001072934.GX27039-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2009-10-01  8:01               ` Richard Zhao
2009-10-01  8:01                 ` Richard Zhao
     [not found]                 ` <4e090d470910010101r6839cc9ax4fe84f04a1afbb00-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2009-10-01  8:26                   ` Sascha Hauer
2009-10-01  8:26                     ` Sascha Hauer
     [not found]                     ` <20091001082610.GB27039-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2009-10-01  9:30                       ` Richard Zhao
2009-10-01  9:30                         ` Richard Zhao
2009-10-04 12:23                         ` Richard Zhao
2009-10-01  7:26       ` [PATCH 2/4] i2c: imx: only imx1 needs disable delay Sascha Hauer
2009-10-01  7:26         ` Sascha Hauer
2009-10-01  7:52         ` Richard Zhao
2009-10-01  7:52           ` Richard Zhao
     [not found]           ` <4e090d470910010052k37a0a4eep6d436e45e6524234-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2009-10-01  7:57             ` Sascha Hauer
2009-10-01  7:57               ` Sascha Hauer
2009-10-01  8:03   ` [PATCH 1/4] i2c: imx: check busy bit when START/STOP Richard Zhao
2009-10-01  8:03     ` Richard Zhao
     [not found]     ` <4e090d470910010103o611d9fb2t3acf93632216fc88-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2009-10-01  8:38       ` Sascha Hauer
2009-10-01  8:38         ` Sascha Hauer
     [not found]         ` <20091001083831.GD27039-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2009-10-01  9:11           ` Richard Zhao
2009-10-01  9:11             ` Richard Zhao
     [not found]             ` <4e090d470910010211k4ce78763i1a5163ec6ea57fe8-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2009-10-01  9:52               ` Sascha Hauer
2009-10-01  9:52                 ` Sascha Hauer
     [not found]                 ` <20091001095239.GE27039-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2009-10-01 14:54                   ` Richard Zhao
2009-10-01 14:54                     ` Richard Zhao
     [not found]                     ` <4e090d470910010754r1ebc4455u6220ccfd803491b0-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2009-10-01 16:37                       ` Wolfram Sang
2009-10-01 16:37                         ` Wolfram Sang
     [not found]                         ` <20091001163753.GA20103-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2009-10-02  0:57                           ` Richard Zhao
2009-10-02  0:57                             ` Richard Zhao
     [not found]                             ` <4e090d470910011757g261c693ehdca40ce43ebee2ec-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2009-10-02  7:26                               ` Sascha Hauer
2009-10-02  7:26                                 ` Sascha Hauer
     [not found]                                 ` <20091002072643.GH27039-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2009-10-02  8:17                                   ` Richard Zhao
2009-10-02  8:17                                     ` Richard Zhao
     [not found]                                     ` <4e090d470910020117w620fda4cta7b26b912d01bc24-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2009-10-02 14:11                                       ` Wolfram Sang
2009-10-02 14:11                                         ` Wolfram Sang
2009-10-04 12:22                                         ` Richard Zhao
  -- strict thread matches above, loose matches on Subject: below --
2009-09-30  5:55 Richard Zhao

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.