[Letux-kernel] jz4730-i2c

Paul Boddie paul at boddie.org.uk
Sat Feb 13 16:58:37 CET 2021

On Saturday, 13 February 2021 16:33:53 CET H. Nikolaus Schaller wrote:
> > Am 13.02.2021 um 16:22 schrieb Paul Boddie <paul at boddie.org.uk>:
> > 
> > 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)
> can you find out if this happens after submitting the first byte (address)
> or only after first data bytes?

This is after the first byte (address). I don't bother testing STX once I 
start reading the data because DRF will be cleared to indicate that more data 
is expected, and so there isn't a risk of testing DRF and finding it set 
because of something I just did.

It is possible that STX is a distraction, but it happens to be a useful one 
for my code. I imagine that I could also use the same logic when reading data, 
though. In other words:

  while (STX || (!DRF && !NACK));

But with DRF and NACK initially unset, and with the peripheral the only thing 
likely to set them, it doesn't seem worthwhile to involve STX as well.


> > 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.
> This is currently my main issue that I get spurious interrupts. Which
> disappear (or are merged) if I add printk at some locations.

Yes, I don't know how these interrupts could be prevented.

> > 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.
> Well, my code has deviated from any published version now to simplify
> further and reduce the issues to small locations.
> At the moment I have two such critical points: one makes the NACK recognized
> correctly. And the other makes the state engine stuck on write (not on
> read).

In terms of address (write) to read transitions, it does seem to involve a 
safe transition that does not get confused by DRF. I haven't looked at 
situations where actual writing and reading are mixed within a single 
transaction, and I don't think the manual is much help with that, either.

> What I have also tried is to guess from the values I see in the I2CSR and
> the ISR what boolean equation could describe an IRQ:
> 	IRQ = !DRF & (STX | !TEND)
> But that may not be correct. I remember from an earlier attempt to do the
> same that I got both (IRQ=1 and IRQ=0) for the same values of the I2CSR.

This is presumably only for read-related interrupts, or does the involvement 
of TEND suggest more general consideration of both read and write interrupts?

It seems to me that read-related interrupts will (or should) occur when DRF or 
NACK are set by the peripheral:

  IRQread = DRF || NACK

It might be no more complicated than that. We would really want some kind of 
condition involved that prevents the IRQ from occurring if we set DRF 
ourselves. This might involve ignoring the address setting operation which 
cannot avoid setting DRF. Here I could imagine a flag being set to indicate 
the transition from driver control of DRF to peripheral control, and I manage 
to use STX for that, regardless of whatever it really means.

> So there may be some internal and invisible state involved.

I could imagine the read/write status of the address byte being used to 
control the IRQ logic internally.

> And the problem with the above assumption is that we can only write the DRF
> bit! So we must write it to 1 to stop any IRQ. Even after writing the
> last byte.
> So I don't know how to switch to read mode...

I hope I have given you some ideas, at least.


More information about the Letux-kernel mailing list