[Letux-kernel] jz4730-i2c

Paul Boddie paul at boddie.org.uk
Sat Feb 13 16:22:05 CET 2021

On Saturday, 13 February 2021 15:11:14 CET H. Nikolaus Schaller wrote:
> Now, there is a a problem. It appears that the next interrupt occurs before
> the data byte has been sent. Well, FIFO behaviour...
> This als means that the ACKF is not yet valid. And even worse, my test
> command
> i2cdetect -y 0 0x27 0x29 >/dev/null
> sends out data packets with 0 bytes. So it should just send STA + address +
> ACK + STO.

This is indeed one of the annoying problems. What my code does is this...

1. Send start (STA)
2. Set address
3. Indicate data valid (DRF)
4. Wait for interrupt condition...
5. If transferring (STX), keep waiting (return to #4)
6. Otherwise, if neither DRF or NACK are set, keep waiting (return to #4)

As I noted before, waiting for an interrupt condition is just "handle an 
interrupt request" in the given context. Technically, I have a timeout, but 
this is hardly ever needed, and I don't do anything other than report it and 
keep testing for the flags if it does occur.

> What I have not found is the IRQ mechanism to reset the IRQ if there is no
> more data. The IRQ stays pending and is processed by the kernel right again
> and my state engine immediately runs through to the end.
> The flow charts in the data sheet unfortunately do not tell in any way how
> to stop another IRQ after sending the last byte and how to properly switch
> to read mode.

I think that the mysterious STX flag might be the key here. Since DRF gets set 
in order to send the address, testing for it risks just sampling the condition 
that has just been set, making it seem that data has arrived when it is still 
being sent.

When STX is also set, however, it appears to mean that the sending is still in 
progress. Here, the manual uses some incoherent language that doesn't 
communicate the purpose of the STX bit, so I am guessing to an extent.

Once the above process is finished, the usual reading process occurs:

7. If NACK then send stop (STO) and exit
8. While data is expected...
9. Wait for interrupt condition...
10. If timeout then send stop and exit
11. If neither DRF or NACK are set, keep waiting (return to #9)

This should have established that something has responded on the bus, and this 
is handled as follows:

12. If NACK then send stop (STO) and exit
13. Set NACK for the last byte if this will be next, or only one byte is read
14. Store the data
15. Clear DRF
16. Return to 8, sending stop and exiting if no more data is expected

> What I know is that sending STO does end this, but that is brute force and
> not the general case...
> Do you have an idea what condition clears the data IRQ if there is no data
> to send? We only can write AC to CR or DRF to SR. Both are 0.

It is entirely possible that the IRQ occurs over and over in my routine above, 
and thus steps 4-6 are evaluated many times before the right exit conditions 
occur. I don't know how I would prevent this, however. All I can reasonably do 
is to prevent the IRQ from causing an advance through my code (and your state 
machine) by being misinterpreted.

I think I may have sent a patch earlier that incorporated some of the above 
logic into the driver. It might be worth looking at parts of that, 
particularly the STX-related test, to see if it helps.


More information about the Letux-kernel mailing list