mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Felipe Balbi <balbi@ti.com>
To: Grygorii Strashko <grygorii.strashko@ti.com>
Cc: <balbi@ti.com>, Hein Tibosch <hein_tibosch@yahoo.es>,
	Tony Lindgren <tony@atomide.com>,
	linux-i2c <linux-i2c@vger.kernel.org>,
	linux-omap <linux-omap@vger.kernel.org>,
	linux-kernel <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH] i2c-omap: always send stop after nack
Date: Tue, 16 Jul 2013 14:27:46 +0300	[thread overview]
Message-ID: <20130716112746.GN8880@arwen.pp.htv.fi> (raw)
In-Reply-To: <51E527F7.4080007@ti.com>

[-- Attachment #1: Type: text/plain, Size: 5375 bytes --]

Hi,

On Tue, Jul 16, 2013 at 02:01:11PM +0300, Grygorii Strashko wrote:
> >>>>On a OMAP4460, i2c-bus-3:
> >>>>
> >>>>A driver (lm75) is causing many 'timeout waiting for bus ready' errors.
> >>>>SDA remains high (as it should), but SCL remains low after a NACK.
> >>>>The bus becomes _unusable for other clients_.
> >>>>
> >>>>While probing, "lm75" writes a command, followed by a read + stop,
> >>>>but the write command is NACK'd. The chip does accept other writes/reads,
> >>>>it just refuses to ack invalid commands.
> >>>>
> >>>>Can you tell me if the patch below would make any sense? Or is it the
> >>>>responsibility of the client to reset the i2c_smbus?
> >>>patch below breaks repeated start.
> Felipe, I'd very appreciate if you'd be able to provide the use case
> which will fail with such solution?

can't you see how this would fail ?

assume omap_i2c_xfer() is called with its last argument (num) being
greater than one and you get the NAK before the last transfer.

Will you not be breaking a possible repeated start for the following
transfer ?

> >>No, after the NACK, no more commands are being processed,
> >>including a repeated start. omap_i2c_xfer() returns -EREMOTEIO
> >>without ever freeing the bus.
> >>
> >>The bus is left in an impossible state with SCL constantly low
> >>and all next commands (to different chips) will therefore get
> >>a -ETIMEDOUT
> >>
> >>With this patch, the bus will become idle again and new commands
> >>can be processed normally
> I think, this is valid fix, but it was done here already:)
> http://patchwork.ozlabs.org/patch/249790/
> "i2c: omap: query STP always when NACK is received"
> 
> And nacked in the same way :(
> But! I've back-ported my patch on TI Android product kernel 3.4, did
> sanity test and I didn't see any issues with my patch :))

that's because you don't care about repeated start, but that's a valid
bus signal which needs to be supported.

> >but you mentioned that if you have IGNORE_NAK set, everything is fine,
> >since lm75 will get a return value of 0 and things will work just fine,
> >right ?
> >
> >Also, you also said that the chip 'refuses to ack invalid commands', why
> >are you sending invalid commands to start with ? This could be a bug in
> >i2c-omap.c, sure, but let's try to figure out why IGNORE_NAK helps and
> >why is lm75 driver sending invalid commands.
> >
> 
> The problem is, that lm75 device is SmBus compatible and its driver has
> .detect() function implemented. During detection it tries to scan some
> registers which might be not present in current device - in my case
> it's tmp105.
> 
> For example to read regA in tmp105 following is done:
> 1) do write in "Index" register (val RegA index) (I2C 1st message)
> 2) do read (I2C 2d message)
> the message 1 is Nacked by device in case if register index is wrong,
> but i2c-omap don't send NACK (or STP). As result, bus stack in Bus
> Busy state.

wait a minute, it's not i2c-omap which needs to send NAK, it's LM75,
and it does the NAK. The handling for NAK in the i2c framework is to
return -EREMOTEIO as we do. If our last message got a NAK, we send STOP
because there will be no other transfers following this one, namely, the
for loop in omap_i2c_xfer() will be finished.

> For SMBus devices the specification states (http://smbus.org/specs/)
> "4.2.Acknowledge (ACK) and not acknowledge (NACK)":
> - "The slave device detects an invalid command or invalid data. In this
> case the slave device must not acknowledge the received byte. The
> master upon detection of this condition must generate a STOP condition
> and retry the transaction"

hmm, but that's something that the OMAP I2C controller doesn't support
and is emulated by the i2c framework, right ?

If you look into the I2C specification, the one the OMAP controller is
compliant to, you'll see e.g. in Figure 13 that a repeated start is a
valid condition after a NAK.

Also it states that:

"This is indicated by the slave generating the not-acknowledge on the
first byte to follow. The slave leaves the data line HIGH and the master
generates a STOP or a repeated START condition."

Because the OMAP I2C controller is compliant to the I2C specification,
not the SMBus specification, we must follow through with the loop and
let the next message try to send a repeated start.

What you need here is a way to discriminate between SMBus message and
normal I2C message, that way you could have something like:

diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 142b694d..571b160 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -618,7 +618,7 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
        if (dev->cmd_err & OMAP_I2C_STAT_NACK) {
                if (msg->flags & I2C_M_IGNORE_NAK)
                        return 0;
-               if (stop) {
+               if (stop || is_smbus) {
                        w = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
                        w |= OMAP_I2C_CON_STP;
                        omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);

and, btw, this also means that I2C_M_IGNORE_NAK is invalid during SMBus
transfers, so you might want to patch the framework to prevent that case
altogether.

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

  reply	other threads:[~2013-07-16 11:28 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-16  8:19 Hein Tibosch
2013-07-16  9:03 ` Felipe Balbi
2013-07-16  9:33   ` Hein Tibosch
2013-07-16  9:42     ` Felipe Balbi
2013-07-16 11:01       ` Grygorii Strashko
2013-07-16 11:27         ` Felipe Balbi [this message]
2013-07-16 12:08           ` Grygorii Strashko
2013-07-16 13:00             ` Felipe Balbi
2013-07-16 16:17               ` Hein Tibosch
2013-08-19 12:11                 ` Wolfram Sang
2013-08-19 13:57                   ` Felipe Balbi
2013-08-19 14:05                     ` Wolfram Sang
2013-08-20 16:39                   ` Grygorii Strashko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20130716112746.GN8880@arwen.pp.htv.fi \
    --to=balbi@ti.com \
    --cc=grygorii.strashko@ti.com \
    --cc=hein_tibosch@yahoo.es \
    --cc=linux-i2c@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-omap@vger.kernel.org \
    --cc=tony@atomide.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®