* [PATCH 1/4] i2c: imx: check busy bit when START/STOP
@ 2009-09-30 5:55 Richard Zhao
[not found] ` <1254290106-29272-1-git-send-email-linuxzsc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
0 siblings, 1 reply; 8+ 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] 8+ messages in thread[parent not found: <1254290106-29272-1-git-send-email-linuxzsc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>]
* [PATCH 2/4] i2c: imx: only imx1 needs disable delay [not found] ` <1254290106-29272-1-git-send-email-linuxzsc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> @ 2009-09-30 5:55 ` Richard Zhao [not found] ` <1254290106-29272-2-git-send-email-linuxzsc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> 0 siblings, 1 reply; 8+ messages in thread From: Richard Zhao @ 2009-09-30 5:55 UTC (permalink / raw) To: kernel-bIcnvbaLZ9MEGnE8C9+IrQ Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, Richard Zhao check cpu_is_mx1() when set disable_delay. 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 156cc95..c1e541c 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -254,14 +254,16 @@ static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, /* Write divider value to register */ writeb(i2c_clk_div[i][1], i2c_imx->base + IMX_I2C_IFDR); - /* - * There dummy delay is calculated. - * It should be about one I2C clock period long. - * This delay is used in I2C bus disable function - * to fix chip hardware bug. - */ - i2c_imx->disable_delay = (500000U * i2c_clk_div[i][0] - + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2); + if (cpu_is_mx1()) { + /* + * There dummy delay is calculated. + * It should be about one I2C clock period long. + * This delay is used in I2C bus disable function + * to fix chip hardware bug. + */ + i2c_imx->disable_delay = (500000U * i2c_clk_div[i][0] + + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2); + } /* dev_dbg() can't be used, because adapter is not yet registered */ #ifdef CONFIG_I2C_DEBUG_BUS -- 1.6.0.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
[parent not found: <1254290106-29272-2-git-send-email-linuxzsc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>]
* [PATCH 3/4] i2c: imx: add macros and printk to make debug easy [not found] ` <1254290106-29272-2-git-send-email-linuxzsc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> @ 2009-09-30 5:55 ` Richard Zhao [not found] ` <1254290106-29272-3-git-send-email-linuxzsc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> 0 siblings, 1 reply; 8+ messages in thread From: Richard Zhao @ 2009-09-30 5:55 UTC (permalink / raw) To: kernel-bIcnvbaLZ9MEGnE8C9+IrQ Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, Richard Zhao When CONFIG_I2C_DEBUG_BUS is enabled, it helps dump registers at operation fail condition, and print i2c_msg to xfer. 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 c1e541c..87faea4 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -125,6 +125,20 @@ struct imx_i2c_struct { /** Functions for IMX I2C adapter driver *************************************** *******************************************************************************/ +#ifdef CONFIG_I2C_DEBUG_BUS +#define reg_dump(i2c_imx) \ +{ \ + printk(KERN_DEBUG "fun %s:%d ", __func__, __LINE__); \ + printk(KERN_DEBUG "IADR %02x IFDR %02x I2CR %02x I2SR %02x\n", \ + readb(i2c_imx->base + IMX_I2C_IADR), \ + readb(i2c_imx->base + IMX_I2C_IFDR), \ + readb(i2c_imx->base + IMX_I2C_I2CR), \ + readb(i2c_imx->base + IMX_I2C_I2SR)); \ +} +#else +#define reg_dump(i2c_imx) +#endif + static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy) { unsigned long orig_jiffies = jiffies; @@ -146,6 +160,7 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy) if (time_after(jiffies, orig_jiffies + HZ / 1000)) { dev_dbg(&i2c_imx->adapter.dev, "<%s> I2C bus is busy\n", __func__); + reg_dump(i2c_imx); return -EIO; } schedule(); @@ -164,9 +179,11 @@ static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx) if (unlikely(result < 0)) { dev_dbg(&i2c_imx->adapter.dev, "<%s> result < 0\n", __func__); + reg_dump(i2c_imx); return result; } else if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) { dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__); + reg_dump(i2c_imx); return -ETIMEDOUT; } dev_dbg(&i2c_imx->adapter.dev, "<%s> TRX complete\n", __func__); @@ -178,6 +195,7 @@ static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx) { if (readb(i2c_imx->base + IMX_I2C_I2SR) & I2SR_RXAK) { dev_dbg(&i2c_imx->adapter.dev, "<%s> No ACK\n", __func__); + reg_dump(i2c_imx); return -EIO; /* No ACK */ } @@ -197,17 +215,20 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx) writeb(I2CR_IEN, i2c_imx->base + IMX_I2C_I2CR); result = i2c_imx_bus_busy(i2c_imx, 0); - if (result) + if (result) { + reg_dump(i2c_imx); 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) + if (result) { + reg_dump(i2c_imx); return result; - + } temp |= I2CR_IIEN | I2CR_MTX | I2CR_TXAK; writeb(temp, i2c_imx->base + IMX_I2C_I2CR); return result; @@ -228,7 +249,8 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx) */ udelay(i2c_imx->disable_delay); - i2c_imx_bus_busy(i2c_imx, 0); + if (i2c_imx_bus_busy(i2c_imx, 0)) + reg_dump(i2c_imx); /* Disable I2C controller */ writeb(0, i2c_imx->base + IMX_I2C_I2CR); @@ -389,7 +411,18 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter, struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(adapter); dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); - +#ifdef CONFIG_I2C_DEBUG_BUS + for (i = 0; i < num; i++) { + printk(KERN_DEBUG "msg%d addr %02x RD %d cnt %d d:", i, + msgs[i].addr, msgs[i].flags & I2C_M_RD, msgs[i].len); + if (!(msgs[i].flags & I2C_M_RD)) { + int j; + for (j = 0; j < msgs[i].len; j++) + printk("%02x ", msgs[i].buf[j]); + } + printk("\n"); + } +#endif /* Start I2C transfer */ result = i2c_imx_start(i2c_imx); if (result) @@ -404,8 +437,10 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter, temp |= I2CR_RSTA; writeb(temp, i2c_imx->base + IMX_I2C_I2CR); result = i2c_imx_bus_busy(i2c_imx, 1); - if (result) + if (result) { + reg_dump(i2c_imx); goto fail0; + } } dev_dbg(&i2c_imx->adapter.dev, "<%s> transfer message: %d\n", __func__, i); @@ -562,7 +597,7 @@ static int __init i2c_imx_probe(struct platform_device *pdev) res_size, i2c_imx->res->start); dev_dbg(&i2c_imx->adapter.dev, "adapter name: \"%s\"\n", i2c_imx->adapter.name); - dev_dbg(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n"); + dev_info(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n"); return 0; /* Return OK */ -- 1.6.0.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
[parent not found: <1254290106-29272-3-git-send-email-linuxzsc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>]
* [PATCH 4/4] i2c: imx: disable clock when it's possible to save power. [not found] ` <1254290106-29272-3-git-send-email-linuxzsc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> @ 2009-09-30 5:55 ` Richard Zhao 0 siblings, 0 replies; 8+ messages in thread From: Richard Zhao @ 2009-09-30 5:55 UTC (permalink / raw) To: kernel-bIcnvbaLZ9MEGnE8C9+IrQ Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, Richard Zhao Enable clock before START, disable it after STOP. 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 87faea4..72ddea3 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -120,6 +120,7 @@ struct imx_i2c_struct { wait_queue_head_t queue; unsigned long i2csr; unsigned int disable_delay; + unsigned int ifdr; /* IMX_I2C_IFDR */ }; /** Functions for IMX I2C adapter driver *************************************** @@ -210,6 +211,8 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx) dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); + clk_enable(i2c_imx->clk); + writeb(i2c_imx->ifdr, i2c_imx->base + IMX_I2C_IFDR); /* Enable I2C controller */ writeb(0, i2c_imx->base + IMX_I2C_I2SR); writeb(I2CR_IEN, i2c_imx->base + IMX_I2C_I2CR); @@ -254,6 +257,7 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx) /* Disable I2C controller */ writeb(0, i2c_imx->base + IMX_I2C_I2CR); + clk_disable(i2c_imx->clk); } static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, @@ -273,8 +277,8 @@ static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, else for (i = 0; i2c_clk_div[i][0] < div; i++); - /* Write divider value to register */ - writeb(i2c_clk_div[i][1], i2c_imx->base + IMX_I2C_IFDR); + /* Store divider value */ + i2c_imx->ifdr = i2c_clk_div[i][1]; if (cpu_is_mx1()) { /* @@ -555,7 +559,6 @@ static int __init i2c_imx_probe(struct platform_device *pdev) dev_err(&pdev->dev, "can't get I2C clock\n"); goto fail3; } - clk_enable(i2c_imx->clk); /* Request IRQ */ ret = request_irq(i2c_imx->irq, i2c_imx_isr, 0, pdev->name, i2c_imx); @@ -604,7 +607,6 @@ static int __init i2c_imx_probe(struct platform_device *pdev) fail5: free_irq(i2c_imx->irq, i2c_imx); fail4: - clk_disable(i2c_imx->clk); clk_put(i2c_imx->clk); fail3: release_mem_region(i2c_imx->res->start, resource_size(res)); @@ -641,8 +643,6 @@ static int __exit i2c_imx_remove(struct platform_device *pdev) if (pdata && pdata->exit) pdata->exit(&pdev->dev); - /* Disable I2C clock */ - clk_disable(i2c_imx->clk); clk_put(i2c_imx->clk); release_mem_region(i2c_imx->res->start, resource_size(i2c_imx->res)); -- 1.6.0.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 1/4] i2c: imx: check busy bit when START/STOP
@ 2009-10-01 1:13 Richard Zhao
[not found] ` <1254359613-21210-1-git-send-email-linuxzsc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
0 siblings, 1 reply; 8+ 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] 8+ messages in thread[parent not found: <1254359613-21210-1-git-send-email-linuxzsc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>]
* [PATCH 2/4] i2c: imx: only imx1 needs disable delay [not found] ` <1254359613-21210-1-git-send-email-linuxzsc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> @ 2009-10-01 1:13 ` Richard Zhao [not found] ` <1254359613-21210-2-git-send-email-linuxzsc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> 0 siblings, 1 reply; 8+ 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 check cpu_is_mx1() when set disable_delay. 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 156cc95..c1e541c 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -254,14 +254,16 @@ static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, /* Write divider value to register */ writeb(i2c_clk_div[i][1], i2c_imx->base + IMX_I2C_IFDR); - /* - * There dummy delay is calculated. - * It should be about one I2C clock period long. - * This delay is used in I2C bus disable function - * to fix chip hardware bug. - */ - i2c_imx->disable_delay = (500000U * i2c_clk_div[i][0] - + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2); + if (cpu_is_mx1()) { + /* + * There dummy delay is calculated. + * It should be about one I2C clock period long. + * This delay is used in I2C bus disable function + * to fix chip hardware bug. + */ + i2c_imx->disable_delay = (500000U * i2c_clk_div[i][0] + + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2); + } /* dev_dbg() can't be used, because adapter is not yet registered */ #ifdef CONFIG_I2C_DEBUG_BUS -- 1.6.0.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
[parent not found: <1254359613-21210-2-git-send-email-linuxzsc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>]
* Re: [PATCH 2/4] i2c: imx: only imx1 needs disable delay [not found] ` <1254359613-21210-2-git-send-email-linuxzsc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> @ 2009-10-01 7:26 ` Sascha Hauer 2009-10-01 7:52 ` Richard Zhao 0 siblings, 1 reply; 8+ messages in thread From: Sascha Hauer @ 2009-10-01 7:26 UTC (permalink / raw) To: Richard Zhao Cc: kernel-bIcnvbaLZ9MEGnE8C9+IrQ, linux-i2c-u79uwXL29TY76Z2rM5mHXA, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, w.sang-bIcnvbaLZ9MEGnE8C9+IrQ On Thu, Oct 01, 2009 at 09:13:31AM +0800, Richard Zhao wrote: > check cpu_is_mx1() when set disable_delay. > > 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 156cc95..c1e541c 100644 > --- a/drivers/i2c/busses/i2c-imx.c > +++ b/drivers/i2c/busses/i2c-imx.c > @@ -254,14 +254,16 @@ static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, > /* Write divider value to register */ > writeb(i2c_clk_div[i][1], i2c_imx->base + IMX_I2C_IFDR); > > - /* > - * There dummy delay is calculated. > - * It should be about one I2C clock period long. > - * This delay is used in I2C bus disable function > - * to fix chip hardware bug. > - */ > - i2c_imx->disable_delay = (500000U * i2c_clk_div[i][0] > - + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2); > + if (cpu_is_mx1()) { > + /* > + * There dummy delay is calculated. > + * It should be about one I2C clock period long. > + * This delay is used in I2C bus disable function > + * to fix chip hardware bug. > + */ > + i2c_imx->disable_delay = (500000U * i2c_clk_div[i][0] > + + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2); > + } I think you should put the udelay(i2c_imx->disable_delay) in cpu_is_mx1() rather than the calculation. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/4] i2c: imx: only imx1 needs disable delay 2009-10-01 7:26 ` Sascha Hauer @ 2009-10-01 7:52 ` Richard Zhao [not found] ` <4e090d470910010052k37a0a4eep6d436e45e6524234-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 0 siblings, 1 reply; 8+ messages in thread From: Richard Zhao @ 2009-10-01 7:52 UTC (permalink / raw) To: Sascha Hauer; +Cc: linux-arm-kernel, linux-i2c, kernel, w.sang On Thu, Oct 1, 2009 at 3:26 PM, Sascha Hauer <s.hauer@pengutronix.de> wrote: > On Thu, Oct 01, 2009 at 09:13:31AM +0800, Richard Zhao wrote: >> check cpu_is_mx1() when set disable_delay. >> >> Signed-off-by: Richard Zhao <linuxzsc@gmail.com> >> >> diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c >> index 156cc95..c1e541c 100644 >> --- a/drivers/i2c/busses/i2c-imx.c >> +++ b/drivers/i2c/busses/i2c-imx.c >> @@ -254,14 +254,16 @@ static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, >> /* Write divider value to register */ >> writeb(i2c_clk_div[i][1], i2c_imx->base + IMX_I2C_IFDR); >> >> - /* >> - * There dummy delay is calculated. >> - * It should be about one I2C clock period long. >> - * This delay is used in I2C bus disable function >> - * to fix chip hardware bug. >> - */ >> - i2c_imx->disable_delay = (500000U * i2c_clk_div[i][0] >> - + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2); >> + if (cpu_is_mx1()) { >> + /* >> + * There dummy delay is calculated. >> + * It should be about one I2C clock period long. >> + * This delay is used in I2C bus disable function >> + * to fix chip hardware bug. >> + */ >> + i2c_imx->disable_delay = (500000U * i2c_clk_div[i][0] >> + + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2); >> + } > > I think you should put the udelay(i2c_imx->disable_delay) in > cpu_is_mx1() rather than the calculation. > > Sascha > > > -- > Pengutronix e.K. | | > Industrial Linux Solutions | http://www.pengutronix.de/ | > Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | > Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | > Do you think udelay(0) wast any more time than if()? And Could I get all you comments in a single patch loop? Thanks Richard ^ permalink raw reply [flat|nested] 8+ messages in thread
[parent not found: <4e090d470910010052k37a0a4eep6d436e45e6524234-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: [PATCH 2/4] i2c: imx: only imx1 needs disable delay [not found] ` <4e090d470910010052k37a0a4eep6d436e45e6524234-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2009-10-01 7:57 ` Sascha Hauer 0 siblings, 0 replies; 8+ messages in thread From: Sascha Hauer @ 2009-10-01 7:57 UTC (permalink / raw) To: Richard Zhao Cc: kernel-bIcnvbaLZ9MEGnE8C9+IrQ, linux-i2c-u79uwXL29TY76Z2rM5mHXA, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, w.sang-bIcnvbaLZ9MEGnE8C9+IrQ On Thu, Oct 01, 2009 at 03:52:15PM +0800, Richard Zhao wrote: > On Thu, Oct 1, 2009 at 3:26 PM, Sascha Hauer <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org> wrote: > > On Thu, Oct 01, 2009 at 09:13:31AM +0800, Richard Zhao wrote: > >> check cpu_is_mx1() when set disable_delay. > >> > >> 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 156cc95..c1e541c 100644 > >> --- a/drivers/i2c/busses/i2c-imx.c > >> +++ b/drivers/i2c/busses/i2c-imx.c > >> @@ -254,14 +254,16 @@ static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, > >> /* Write divider value to register */ > >> writeb(i2c_clk_div[i][1], i2c_imx->base + IMX_I2C_IFDR); > >> > >> - /* > >> - * There dummy delay is calculated. > >> - * It should be about one I2C clock period long. > >> - * This delay is used in I2C bus disable function > >> - * to fix chip hardware bug. > >> - */ > >> - i2c_imx->disable_delay = (500000U * i2c_clk_div[i][0] > >> - + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2); > >> + if (cpu_is_mx1()) { > >> + /* > >> + * There dummy delay is calculated. > >> + * It should be about one I2C clock period long. > >> + * This delay is used in I2C bus disable function > >> + * to fix chip hardware bug. > >> + */ > >> + i2c_imx->disable_delay = (500000U * i2c_clk_div[i][0] > >> + + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2); > >> + } > > > > I think you should put the udelay(i2c_imx->disable_delay) in > > cpu_is_mx1() rather than the calculation. > > > > Sascha > > > > > > -- > > Pengutronix e.K. | | > > Industrial Linux Solutions | http://www.pengutronix.de/ | > > Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | > > Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | > > > Do you think udelay(0) wast any more time than if()? if (cpu_is_mx1()) is optimized out by the compiler. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2009-10-01 7:57 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-09-30 5:55 [PATCH 1/4] i2c: imx: check busy bit when START/STOP Richard Zhao
[not found] ` <1254290106-29272-1-git-send-email-linuxzsc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2009-09-30 5:55 ` [PATCH 2/4] i2c: imx: only imx1 needs disable delay Richard Zhao
[not found] ` <1254290106-29272-2-git-send-email-linuxzsc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2009-09-30 5:55 ` [PATCH 3/4] i2c: imx: add macros and printk to make debug easy Richard Zhao
[not found] ` <1254290106-29272-3-git-send-email-linuxzsc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2009-09-30 5:55 ` [PATCH 4/4] i2c: imx: disable clock when it's possible to save power Richard Zhao
-- strict thread matches above, loose matches on Subject: below --
2009-10-01 1:13 [PATCH 1/4] i2c: imx: check busy bit when START/STOP 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
[not found] ` <1254359613-21210-2-git-send-email-linuxzsc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2009-10-01 7:26 ` Sascha Hauer
2009-10-01 7:52 ` Richard Zhao
[not found] ` <4e090d470910010052k37a0a4eep6d436e45e6524234-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2009-10-01 7:57 ` Sascha Hauer
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox