10-10-2018 03:05 AM
When trying to read more than 252 bytes at once from an I2C-Slave, the transmission is split up into chunks of 252 bytes. The driver from the hardware vendor needs to read 255 or more bytes in one transaction.
The hardware we are using is a Zynq Ultrascale+ ZU3EG-1E and the PS-I2C modules uses the pins MIO 26 and 27. The OS is Petalinux 2018.2 with kernel version 4.14.0-xilinx-v2018.2. The application communicates with the I2C driver via read/write functions from the C stdlib, so the driver for the slave is completely in user space and communicates with the Xilinx/Cadence I2C driver.
We tried with different bus speed like 100 kHz and 340 kHz but the result is the same. The hardware vendor also provides a devkit with an MicroZed on it where the same I2C transmission works as intended without splits but it uses Petalinux 2016.3. So our guess is that either the driver in the kernel or the hardware of the Ultrascale+ is causing this behaviour.
In the attachment is the screenshot of the oscilloscope where it ends the transmission after the 252th byte and starts a read for the remaining 3 bytes. The slave cannot handle the second read and outputs 0xFF.
10-11-2018 03:19 AM
After further research into this problem, we found AR# 61664 and this commit from 2014 to the I2C driver. The AR seems to affect only the older 7-series Zynq. The commit adds code to handle larger transmissions (>252 bytes) and is in most parts still present in today's kernel.
Also in some experiments we tried larger sizes and the transmission is always split up into chunks of 252 bytes.
Does somebody know of a version of Petalinux which is known to have working I2C and does not split up into 252-byte-chunks?
10-11-2018 07:22 AM - edited 10-11-2018 07:24 AM
I don't think it's actually "splitting up" the transaction. I believe it's just maintaining a register at a value greater than 0 so that the transaction can continue.
You may want to looking into the "bus hold quirk" as the behavior in the case of >252 byte transfers changes based on that flag.
10-29-2018 06:03 AM
After doing some other part of the project, I'm back again at this problem. Now I modified the driver to print out the hold_quirk variable in the cdns_i2c_master_isr and cdns_i2c_master_xfer functions and it is always set to 0 meaning false. After some research I found out that the "bus hold quirk" affects only the 7-series Zynq (r1p10 hardware revision) and should be fixed for the UltraScale+ line (r1p14 hardware revision). So the driver does not use the workaround for the quirk on our hardware because we are using an ZynqMP.
The last code change of the driver was made in August 2017 and since then nobody found such a bug and reported it? Very unlikely. Can someone else confirm this behaviour?