RE: [PATCH 0/6] i2c-davinci gpio pulsed SCL recovery with ICPFUNC

2011-04-19 Thread Jon Povey
Ben Gardiner wrote:
> In "i2c-davinci: Fix race when setting up for TX" and "i2c-davinci:
> Fix TX setup for more SoCs" you mention testing on DM355 -- is there
> any you have hardware on which the recovery procedure is executed on
> occasion and that you would be available to test modifications to the
> current implementation?

Nope, sorry. I've never seen the bus lock up.

--
Jon Povey
jon.po...@racelogic.co.uk

Racelogic is a limited company registered in England. Registered number 2743719 
.
Registered Office Unit 10, Swan Business Centre, Osier Way, Buckingham, Bucks, 
MK18 1TB .

The information contained in this electronic mail transmission is intended by 
Racelogic Ltd for the use of the named individual or entity to which it is 
directed and may contain information that is confidential or privileged. If you 
have received this electronic mail transmission in error, please delete it from 
your system without copying or forwarding it, and notify the sender of the 
error by reply email so that the sender's address records can be corrected. The 
views expressed by the sender of this communication do not necessarily 
represent those of Racelogic Ltd. Please note that Racelogic reserves the right 
to monitor e-mail communications passing through its network


--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: [PATCH 0/6] i2c-davinci gpio pulsed SCL recovery with ICPFUNC

2011-04-18 Thread Jon Povey
Ben Gardiner wrote:

>>> When creating this series I noticed that there are obvious
>>> similarities between the existing recovery routine implemented by
>>> Philby John and John Povey

> I'm not sure how the 20us in the existing method was derived -- I
> wonder if Philby John or John Povey could comment?

I've been a little bemused about why I am getting credited for I2C
bus recovery work. I don't remember doing any work on that.

I did a couple of patches to fix a race when setting up a TX, but
those are, afaik, unrelated.

All I know about the bus recovery stuff is looking at it a while back
and thinking hmm, that seems to wiggle gpio without changing the
pinmuxing, so it can't possibly work.

--
Jon Povey
jon.po...@racelogic.co.uk

Racelogic is a limited company registered in England. Registered number 2743719 
.
Registered Office Unit 10, Swan Business Centre, Osier Way, Buckingham, Bucks, 
MK18 1TB .

The information contained in this electronic mail transmission is intended by 
Racelogic Ltd for the use of the named individual or entity to which it is 
directed and may contain information that is confidential or privileged. If you 
have received this electronic mail transmission in error, please delete it from 
your system without copying or forwarding it, and notify the sender of the 
error by reply email so that the sender's address records can be corrected. The 
views expressed by the sender of this communication do not necessarily 
represent those of Racelogic Ltd. Please note that Racelogic reserves the right 
to monitor e-mail communications passing through its network


--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: [PATCH v4] i2c: davinci: Fix race when setting up for TX

2010-10-11 Thread Jon Povey
Kevin Hilman wrote:
> I just noticed that it has already been pulled and is part of -rc7.
>
> Jon, care to submit a new patch with v4 diff and including
> the acks and
> tested-bys?

Done and sent:
Message-Id: <1286858825-21540-1-git-send-email-jon.po...@racelogic.co.uk>

--
Jon Povey
jon.po...@racelogic.co.uk

Racelogic is a limited company registered in England. Registered number 2743719 
.
Registered Office Unit 10, Swan Business Centre, Osier Way, Buckingham, Bucks, 
MK18 1TB .

The information contained in this electronic mail transmission is intended by 
Racelogic Ltd for the use of the named individual or entity to which it is 
directed and may contain information that is confidential or privileged. If you 
have received this electronic mail transmission in error, please delete it from 
your system without copying or forwarding it, and notify the sender of the 
error by reply email so that the sender's address records can be corrected. The 
views expressed by the sender of this communication do not necessarily 
represent those of Racelogic Ltd. Please note that Racelogic reserves the right 
to monitor e-mail communications passing through its network


--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] i2c: davinci: Fix TX setup for more SoCs

2010-10-11 Thread Jon Povey
This patch is an improvement to 4bba0fd8d1c6d405df666e2573e1a1f917098be0
which got to mainline a little early.

Sudhakar Rajashekhara explains that at least OMAP-L138 requires MDR mode
settings before DXR for correct behaviour, so load MDR first with
STT cleared and later load again with STT set.

Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985

Signed-off-by: Jon Povey 
Acked-by: Troy Kisky 
Tested-by: Sudhakar Rajashekhara 
Acked-by: Kevin Hilman 
---
This patches to what was v4 of the original patch.

The original patch which made it to 2.6.36-rc7 will as I understand it have
introduced a regression for OMAP-L138 so this patch is a regression fix and
wants to get into 2.6.36.

 drivers/i2c/busses/i2c-davinci.c |   24 +++-
 1 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index b8feac5..5795c83 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -331,21 +331,16 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct 
i2c_msg *msg, int stop)
INIT_COMPLETION(dev->cmd_complete);
dev->cmd_err = 0;
 
-   /* Take I2C out of reset, configure it as master and set the
-* start bit */
-   flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST | DAVINCI_I2C_MDR_STT;
+   /* Take I2C out of reset and configure it as master */
+   flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST;
 
/* if the slave address is ten bit address, enable XA bit */
if (msg->flags & I2C_M_TEN)
flag |= DAVINCI_I2C_MDR_XA;
if (!(msg->flags & I2C_M_RD))
flag |= DAVINCI_I2C_MDR_TRX;
-   if (stop)
-   flag |= DAVINCI_I2C_MDR_STP;
-   if (msg->len == 0) {
+   if (msg->len == 0)
flag |= DAVINCI_I2C_MDR_RM;
-   flag &= ~DAVINCI_I2C_MDR_STP;
-   }
 
/* Enable receive or transmit interrupts */
w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG);
@@ -358,17 +353,28 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct 
i2c_msg *msg, int stop)
dev->terminate = 0;
 
/*
+* Write mode register first as needed for correct behaviour
+* on OMAP-L138, but don't set STT yet to avoid a race with XRDY
+* occuring before we have loaded DXR
+*/
+   davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
+
+   /*
 * First byte should be set here, not after interrupt,
 * because transmit-data-ready interrupt can come before
 * NACK-interrupt during sending of previous message and
 * ICDXR may have wrong data
+* It also saves us one interrupt, slightly faster
 */
if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) {
davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++);
dev->buf_len--;
}
 
-   /* write the data into mode register; start transmitting */
+   /* Set STT to begin transmit now DXR is loaded */
+   flag |= DAVINCI_I2C_MDR_STT;
+   if (stop && msg->len != 0)
+   flag |= DAVINCI_I2C_MDR_STP;
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
 
r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
-- 
1.6.3.3

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: [PATCH v4] i2c: davinci: Fix race when setting up for TX

2010-10-07 Thread Jon Povey
Hi Ben,

I am not on the i2c list but noticed this pull request:
http://www.spinics.net/linux/lists/linux-i2c/msg04022.html

I think you have the wrong (old) version of this patch in that branch,
http://git.fluff.org/gitweb?p=bjdooks/linux.git;a=commitdiff;h=4bba0fd8d1c6d405df666e2573e1a1f917098be0

The correct v4 one from the start of this thread has more lines
of patch and this commit message:

>>>>> When setting up to transmit, a race exists between the ISR and
>>>>> i2c_davinci_xfer_msg() trying to load the first byte and adjust
>>>>> counters. This is mostly visible for transmits > 1 byte long.
>>>>>
>>>>> The hardware starts sending immediately that MDR.STT is set. IMR
>>>>> trickery doesn't work because if we start sending, finish the
>>>>> first byte and an XRDY event occurs before we load IMR to unmask
>>>>> it, we never get an interrupt, and we timeout.
>>>>>
>>>>> Sudhakar Rajashekhara explains that at least OMAP-L138 requires
>>>>> MDR mode settings before DXR for correct behaviour, so load MDR
>>>>> first with STT cleared and later load again with STT set.
>>>>>
>>>>> Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985
>>>>>
>>>>> Signed-off-by: Jon Povey 
>>>>> CC: Sudhakar Rajashekhara 
>>>>> CC: Troy Kisky 

It also has some more acks and a tested, via Kevin:

> Acked-by: Troy Kisky 
> Tested-by: Sudhakar Rajashekhara 
> Acked-by: Kevin Hilman 


--
Jon Povey
jon.po...@racelogic.co.uk

Racelogic is a limited company registered in England. Registered number 2743719 
.
Registered Office Unit 10, Swan Business Centre, Osier Way, Buckingham, Bucks, 
MK18 1TB .

The information contained in this electronic mail transmission is intended by 
Racelogic Ltd for the use of the named individual or entity to which it is 
directed and may contain information that is confidential or privileged. If you 
have received this electronic mail transmission in error, please delete it from 
your system without copying or forwarding it, and notify the sender of the 
error by reply email so that the sender's address records can be corrected. The 
views expressed by the sender of this communication do not necessarily 
represent those of Racelogic Ltd. Please note that Racelogic reserves the right 
to monitor e-mail communications passing through its network


--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4] i2c: davinci: Fix race when setting up for TX

2010-09-20 Thread Jon Povey
When setting up to transmit, a race exists between the ISR and
i2c_davinci_xfer_msg() trying to load the first byte and adjust counters.
This is mostly visible for transmits > 1 byte long.

The hardware starts sending immediately that MDR.STT is set. IMR trickery
doesn't work because if we start sending, finish the first byte and an
XRDY event occurs before we load IMR to unmask it, we never get an
interrupt, and we timeout.

Sudhakar Rajashekhara explains that at least OMAP-L138 requires MDR mode
settings before DXR for correct behaviour, so load MDR first with
STT cleared and later load again with STT set.

Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985

Signed-off-by: Jon Povey 
CC: Sudhakar Rajashekhara 
CC: Troy Kisky 
---
Reworked after comments by Troy and Sudhakar.

Looking at the datasheet it seemed like setting STP without STT early
might cause a stray STOP to be generated, so I moved it into the second
MDR load.

This passes a quick smoke test but I can't do much more testing right at
the moment. Sudhakar, your comments would be welcomed.

 drivers/i2c/busses/i2c-davinci.c |   24 +++-
 1 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index c87..5795c83 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -331,21 +331,16 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct 
i2c_msg *msg, int stop)
INIT_COMPLETION(dev->cmd_complete);
dev->cmd_err = 0;
 
-   /* Take I2C out of reset, configure it as master and set the
-* start bit */
-   flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST | DAVINCI_I2C_MDR_STT;
+   /* Take I2C out of reset and configure it as master */
+   flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST;
 
/* if the slave address is ten bit address, enable XA bit */
if (msg->flags & I2C_M_TEN)
flag |= DAVINCI_I2C_MDR_XA;
if (!(msg->flags & I2C_M_RD))
flag |= DAVINCI_I2C_MDR_TRX;
-   if (stop)
-   flag |= DAVINCI_I2C_MDR_STP;
-   if (msg->len == 0) {
+   if (msg->len == 0)
flag |= DAVINCI_I2C_MDR_RM;
-   flag &= ~DAVINCI_I2C_MDR_STP;
-   }
 
/* Enable receive or transmit interrupts */
w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG);
@@ -357,7 +352,11 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct 
i2c_msg *msg, int stop)
 
dev->terminate = 0;
 
-   /* write the data into mode register */
+   /*
+* Write mode register first as needed for correct behaviour
+* on OMAP-L138, but don't set STT yet to avoid a race with XRDY
+* occuring before we have loaded DXR
+*/
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
 
/*
@@ -365,12 +364,19 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct 
i2c_msg *msg, int stop)
 * because transmit-data-ready interrupt can come before
 * NACK-interrupt during sending of previous message and
 * ICDXR may have wrong data
+* It also saves us one interrupt, slightly faster
 */
if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) {
davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++);
dev->buf_len--;
}
 
+   /* Set STT to begin transmit now DXR is loaded */
+   flag |= DAVINCI_I2C_MDR_STT;
+   if (stop && msg->len != 0)
+   flag |= DAVINCI_I2C_MDR_STP;
+   davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
+
r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
  dev->adapter.timeout);
if (r == 0) {
-- 
1.6.3.3

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: [PATCH v3] i2c: davinci: Fix race when setting up for TX

2010-09-19 Thread Jon Povey
Troy Kisky wrote:
> On 9/17/2010 6:09 AM, Sudhakar Rajashekhara wrote:
>> Hi,

Seems I didn't get Sudhakar's email.. I wonder why?

>> On Fri, Sep 17, 2010 at 08:32:11, Jon Povey wrote:
>>> Move the MDR load after DXR,IMR loads to avoid this race without
>>> locking.
>>
>> I remember I had some issues on OMAP-L138 with this fix, that's when
>> I reverted to configuring ICMDR before writing to DXR (Please see
>> here: https://patchwork.kernel.org/patch/75262/). I checked the BIOS
>> I2C driver code for OMAP-L138 and there also we are configuring MDR
>> before accessing DXR.

Ah :/

> How about killing the lines from commit
> c6c7c729a22bfeb8e63eafce48dbaeea20e68703
> ---
> /*
>  * First byte should be set here, not after interrupt,
>  * because transmit-data-ready interrupt can come before
>  * NACK-interrupt during sending of previous message and
>  * ICDXR may have wrong data
>  */
> if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) {
> davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++);
> dev->buf_len--; }
> --
>
> and resetting the i2c upon a NAK interrupt (after the stop)
> to clear the bad fifo data?

I can't really comment on how valid that would be and can't easily test it.

However preloading DXR does save one interrupt on transmit so the whole 
operation is faster and more efficient.

Maybe v1 of my patch, with locking, is the best option?

--
Jon Povey
jon.po...@racelogic.co.uk

Racelogic is a limited company registered in England. Registered number 2743719 
.
Registered Office Unit 10, Swan Business Centre, Osier Way, Buckingham, Bucks, 
MK18 1TB .

The information contained in this electronic mail transmission is intended by 
Racelogic Ltd for the use of the named individual or entity to which it is 
directed and may contain information that is confidential or privileged. If you 
have received this electronic mail transmission in error, please delete it from 
your system without copying or forwarding it, and notify the sender of the 
error by reply email so that the sender's address records can be corrected. The 
views expressed by the sender of this communication do not necessarily 
represent those of Racelogic Ltd. Please note that Racelogic reserves the right 
to monitor e-mail communications passing through its network


--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3] i2c: davinci: Fix race when setting up for TX

2010-09-16 Thread Jon Povey
When setting up to transmit, a race exists between the ISR and
i2c_davinci_xfer_msg() trying to load the first byte and adjust counters.
This is mostly visible for transmits > 1 byte long.

The hardware starts sending immediately that MDR is loaded. IMR trickery
doesn't work because if we start sending, finish the first byte and an
XRDY event occurs before we load IMR to unmask it, we never get an
interrupt, and we timeout.

Move the MDR load after DXR,IMR loads to avoid this race without locking.

Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985

Signed-off-by: Jon Povey 
---
Oops, v2 was based on the wrong version. Rebased so this should apply
against mainline.

Troy, thanks for the input. I tried reordering the IMR load before but got
occasional timeouts. Went back to the logic analyser today and worked out
why, see above comment in the commit message.

Moving the MDR load seems to fix things without locking, much neater and
tiny patch.

As I understand it we can be confident inside i2c_davinci_xfer_msg() that
the peripheral is not busy sending or receiving something else, I had a
look at the other interrupt sources in the datasheet and this seems safe
enough.

I'm not sure what the correct thing to do for followup message IDs here..
My original email? Troy's? Clues welcome for next time.

 drivers/i2c/busses/i2c-davinci.c |6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index c87..b8feac5 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -357,9 +357,6 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct 
i2c_msg *msg, int stop)
 
dev->terminate = 0;
 
-   /* write the data into mode register */
-   davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
-
/*
 * First byte should be set here, not after interrupt,
 * because transmit-data-ready interrupt can come before
@@ -371,6 +368,9 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct 
i2c_msg *msg, int stop)
dev->buf_len--;
}
 
+   /* write the data into mode register; start transmitting */
+   davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
+
r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
  dev->adapter.timeout);
if (r == 0) {
-- 
1.6.3.3

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2] i2c: davinci: Fix race when setting up for TX

2010-09-16 Thread Jon Povey
When setting up to transmit, a race exists between the ISR and
i2c_davinci_xfer_msg() trying to load the first byte and adjust counters.
This is mostly visible for transmits > 1 byte long.

The hardware starts sending immediately that MDR is loaded. IMR trickery
doesn't work because if we start sending, finish the first byte and an
XRDY event occurs before we load IMR to unmask it, we never get an
interrupt, and we timeout.

Move the MDR load after DXR,IMR loads to avoid this race without locking.

Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985

Signed-off-by: Jon Povey 
---
Troy, thanks for the input. I tried reordering the IMR load before but got
occasional timeouts. Went back to the logic analyser today and worked out
why, see above comment in the commit message.

Moving the MDR load seems to fix things without locking, much neater and
tiny patch.

As I understand it we can be confident inside i2c_davinci_xfer_msg() that
the peripheral is not busy sending or receiving something else, I had a
look at the other interrupt sources in the datasheet and this seems safe
enough.

I'm not sure what the correct thing to do for followup message IDs here..
My original email? Troy's? Clues welcome for next time.

 drivers/i2c/busses/i2c-davinci.c |6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 72df4af..baa5209 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -349,9 +349,6 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct 
i2c_msg *msg, int stop)
 
dev->terminate = 0;
 
-   /* write the data into mode register */
-   davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
-
/*
 * First byte should be set here, not after interrupt,
 * because transmit-data-ready interrupt can come before
@@ -371,6 +368,9 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct 
i2c_msg *msg, int stop)
w |= DAVINCI_I2C_IMR_XRDY;
davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, w);
 
+   /* write the data into mode register; start transmitting */
+   davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
+
r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
  dev->adapter.timeout);
if (r == 0) {
-- 
1.6.3.3

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] i2c: davinci: Fix race when setting up for TX

2010-09-16 Thread Jon Povey
When setting up to transmit, a race exists between the ISR and
i2c_davinci_xfer_msg() trying to load the first byte and adjust counters.
This is mostly visible for transmits > 1 byte long.

The ISR may run at any time after the mode register has been set.
While we are setting up and loading the first byte, protect this critical
section from the ISR with a spinlock.

The RX path or zero-length transmits do not need this locking.

Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985

Signed-off-by: Jon Povey 
---
I suspect this hasn't shown up for others using single-byte transmits as the
interrupt tends to either run entirely before or entirely after this block
in i2c_davinci_xfer_msg():

/*
 * First byte should be set here, not after interrupt,
 * because transmit-data-ready interrupt can come before
 * NACK-interrupt during sending of previous message and
 * ICDXR may have wrong data
 */
if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) {
davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++);
dev->buf_len--;
}

Often the entire message would be sent before that test was executed
(observed with LED wiggling and a logic analyser), so dev->buf_len would
be untrue and things merrily went on their way. That seems to be counter
to the intent in the comment.

I tried some fiddling around reordering the register loads but couldn't
get things reliable so stuck in a spinlock. Better solutions welcome.

P.S.: Having run into the the bus reset code a lot during testing, I
am pretty sure that that generic_i2c_clock_pulse() does NOTHING due to
pinmuxing, at least on DM355, it is misleading and may be better
replaced with a comment saying "It would be great to toggle SCL here".

 drivers/i2c/busses/i2c-davinci.c |   21 -
 1 files changed, 20 insertions(+), 1 deletions(-)

diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index c87..43aa55d 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -107,6 +107,7 @@ struct davinci_i2c_dev {
u8  *buf;
size_t  buf_len;
int irq;
+   spinlock_t  lock;
int stop;
u8  terminate;
struct i2c_adapter  adapter;
@@ -312,6 +313,8 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct 
i2c_msg *msg, int stop)
u32 flag;
u16 w;
int r;
+   unsigned long flags;
+   int preload = 0;
 
if (!pdata)
pdata = &davinci_i2c_platform_data_default;
@@ -347,6 +350,15 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct 
i2c_msg *msg, int stop)
flag &= ~DAVINCI_I2C_MDR_STP;
}
 
+   /*
+* When transmitting, lock ISR out to avoid it racing on the buffer and
+* DXR register before we are done
+*/
+   if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) {
+   preload = 1;
+   spin_lock_irqsave(&dev->lock, flags);
+   }
+
/* Enable receive or transmit interrupts */
w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG);
if (msg->flags & I2C_M_RD)
@@ -366,13 +378,15 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct 
i2c_msg *msg, int stop)
 * NACK-interrupt during sending of previous message and
 * ICDXR may have wrong data
 */
-   if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) {
+   if (preload) {
davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++);
dev->buf_len--;
+   spin_unlock_irqrestore(&dev->lock, flags);
}
 
r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
  dev->adapter.timeout);
+
if (r == 0) {
dev_err(dev->dev, "controller timed out\n");
i2c_recover_bus(dev);
@@ -490,6 +504,8 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void 
*dev_id)
int count = 0;
u16 w;
 
+   spin_lock(&dev->lock);
+
while ((stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG))) {
dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat);
if (count++ == 100) {
@@ -579,6 +595,8 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void 
*dev_id)
}
}
 
+   spin_unlock(&dev->lock);
+
return count ? IRQ_HANDLED : IRQ_NONE;
 }
 
@@ -662,6 +680,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
goto err_release_region;
}
 
+   spin_lock_init(&dev->lock);
init_completion(&dev->

[PATCH] i2c: davinci: Fix race when setting up for TX

2010-06-22 Thread Jon Povey
Move the interrupt enable after the first byte load for TX, as it
was racing with the interrupt handler and corrupting dev->buf_len
for messages > 1 byte.

Tested on DM355.

Signed-off-by: Jon Povey 
---
The race seems to have been introduced by 
869e6692d527983958216f13c3c8e095791909df

This fixes the problem for me, but someone from TI might want to comment
on the validity of starting the transfer before enabling the RDY interrupts.
Any possibility of losing interrupts?

Considered a spinlock but if this reordering is OK then it's neater.

I'm guessing not many people have been sending multi-byte messages..

 drivers/i2c/busses/i2c-davinci.c |   16 
 1 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index c87..72df4af 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -347,14 +347,6 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct 
i2c_msg *msg, int stop)
flag &= ~DAVINCI_I2C_MDR_STP;
}
 
-   /* Enable receive or transmit interrupts */
-   w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG);
-   if (msg->flags & I2C_M_RD)
-   w |= DAVINCI_I2C_IMR_RRDY;
-   else
-   w |= DAVINCI_I2C_IMR_XRDY;
-   davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, w);
-
dev->terminate = 0;
 
/* write the data into mode register */
@@ -371,6 +363,14 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct 
i2c_msg *msg, int stop)
dev->buf_len--;
}
 
+   /* Enable receive or transmit interrupts */
+   w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG);
+   if (msg->flags & I2C_M_RD)
+   w |= DAVINCI_I2C_IMR_RRDY;
+   else
+   w |= DAVINCI_I2C_IMR_XRDY;
+   davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, w);
+
r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
  dev->adapter.timeout);
if (r == 0) {
-- 
1.6.3.3

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html