[Letux-kernel] jz4730-i2c

H. Nikolaus Schaller hns at goldelico.com
Sat Feb 13 17:11:34 CET 2021


> Am 13.02.2021 um 16:58 schrieb Paul Boddie <paul at boddie.org.uk>:
> 
> 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:
> 
>  do
>  {
>    wait_for_irq();
>  }
>  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.

Well, at least sending the address is the same on both and the original
driver did take care of 10 bit addresses, i.e. two write cycles.

So my assumption is that reading is "just not transmitting and sending STO"...

> 
>> 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

Yes, that would be plausible...

Well, in my observations the ACKF (= !NACK) is not part of requesting an interrupt
at all. I have cases with or without ACKF being set and they have always the
same I2C IRQ state. So it seems to be a 9th bit like in the I2CDR.

What also may confirm my theory is that STA start sending SCK (and sets BUSY=1)
and STO stops sending SCK (BUSY=0). So ACK or NACK is just sampling a bit and
not a state. Especially the sequencer likely doesn't stop on NACK unless we
send a STO. This seems to be missing in the Flow Charts...

> 
> 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.

I also thought about this possibility but 7 vs. 10 bit adresses makes it unlikely.
And it may IMHO be more compelex in VHDL than to spend a read/write bit in some
status register than decoding the address. But since it is not there, there must
be some hidden condition.

> 
>> 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.

Indeed :)

BR and thanks,
Nikolaus



More information about the Letux-kernel mailing list