u-boot/drivers
Trent Piepho c854933f50 i2c: mxc_i2c: Fix read and read->write xfers in DM mode
This is an old driver that supports both device mapped and non-mapped
mode, and covers a wide range of hardware.  It's hard to change without
risking breaking something.  I have to tried to be exceedingly detailed
in this patch, so please excuse the length of the commit essay that
follows.

In device mapped mode the I2C xfer function does not handle plain read,
and some other, transfers correctly.

What it can't handle are transactions that:
    Start with a read, or,
    Have a write followed by a read, or,
    Have more than one read in a row.

The common I2C/SMBUS read register and write register transactions
always start with a write, followed by a write or a read, and then end.
These work, so the bug is not apparent for most I2C slaves that only use
these common xfer forms.

The existing xfer loop initializes by sending the chip address in write
mode after it deals with bus arbitration and master setup.  When
processing each message, if the next message will be a read, it sends a
repeated start followed by the chip address in read mode after the
current message.

Obviously, this does not work if the first message is a read, as the
chip is always addressed in write mode initially by i2c_init_transfer().

A write following a read does not work because the repeated start is
only sent when the next message is a read.  There is no logic to send it
when the current message is a read and next is write.  It should be sent
every time the bus changes direction.

The ability to use a plain read was added to this driver in
commit 2feec4eafd ("imx: mxc_i2c: tweak the i2c transfer method"),
but this applied only the non-DM code path.

This patch fixes the DM code path.  The xfer function will call
i2c_init_transfer() with an alen of -1 to avoid sending the chip
address.  The same way the non-DM code achieves this.  The xfer
function's message loop will send the address and mode before each
message if the bus changes direction, and on the first message.

When reading data, the master hardware is one byte ahead of what we
receive.  I.e., reading a byte from the data register returns a byte
*already received* by the master, and causes the master to start the RX
of the *next* byte.  Therefor, before we read the final byte of a
message, we must tell the master what to do next.  I add a "last" flag
to i2c_read_data() to tell it if the message is to be followed by a stop
or a repeated start.  When last == true it acts exactly as before.

The non-DM code can only create an xfer where the read, if any, is the
final message of the xfer.  And so the only callsite of i2c_read_data()
in the non-DM code has the "last" parameter as true.  Therefore, this
change has no effect on the non-DM code.  As all other changes are in
the DM xfer function, which is not even compiled in non-DM code, I am
confident that this patch has no effect on boards not using I2C_DM.
This greatly reduces the range of hardware that could be affected.

For DM boards, I have verified every transaction the "i2c" command can
create on a scope and they are all exactly as they are supposed to be.
I also tested write->read->write, which isn't possible with the i2c
command, and it works as well.  I didn't fix multiple reads in a row, as
it's a lot more invasive and obviously no one has every wanted them
since they've never worked.  It didn't seem like the extra complexity
was justified to support something no one uses.

Cc: Nandor Han <nandor.han@ge.com>
Cc: Heiko Schocher <hs@denx.de>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Fabio Estevam <festevam@gmail.com>
Cc: Breno Matheus Lima <brenomatheus@gmail.com>
Signed-off-by: Trent Piepho <tpiepho@impinj.com>
2019-05-17 05:35:23 +02:00
..
adc adc: exynos-adc: Fix wrong bit operation used to stop the ADC 2019-03-11 15:53:19 +09:00
ata ata: ahci: fix memory leak 2019-05-09 19:52:55 -04:00
axi drivers: cosmetic: Convert SPDX license tags to Linux Kernel style 2018-10-28 09:26:39 -04:00
bios_emulator bios_emulator: remove assignment without effect 2018-07-23 14:33:21 -04:00
block blk: Increase cache element size 2019-01-15 15:28:53 -05:00
board drivers: cosmetic: Convert SPDX license tags to Linux Kernel style 2018-10-28 09:26:39 -04:00
bootcount bootcount: add a DM RTC backing store for bootcount 2018-12-10 10:04:45 +01:00
cache dm: cache: add the pl310 cache controller driver 2019-05-05 08:48:50 -04:00
clk Merge tag 'rockchip-for-v2019.07-rc1' of git://git.denx.de/u-boot-rockchip 2019-05-09 12:36:17 -04:00
core dm: core: Fix translate condition in ofnode_get_addr_size() 2019-05-08 12:44:07 +08:00
cpu cpu: Bind timer driver for boot hart 2019-02-27 09:12:33 +08:00
crypto SPDX: Convert all of our single license tags to Linux Kernel style 2018-05-07 09:34:12 -04:00
ddr arm: socfpga: Move Stratix 10 SDRAM driver to DM 2019-05-06 12:44:17 +02:00
demo SPDX: Convert all of our single license tags to Linux Kernel style 2018-05-07 09:34:12 -04:00
dfu dfu: mmc: call fs functions instead of run_command 2019-01-30 21:22:53 -05:00
dma dma: ti: k3-udma: Do not touch RT registers before channel configuration 2019-05-03 07:23:17 -04:00
fastboot fastboot: add support for 'getvar platform' 2019-04-21 10:26:52 +02:00
firmware firmware: ti_sci: Always request response from firmware 2019-05-03 07:23:17 -04:00
fpga spl: socfpga: Implement fpga bitstream loading with socfpga loadfs 2019-05-10 22:48:11 +02:00
gpio gpio: dwapb_gpio: convert to livetree 2019-05-10 22:48:11 +02:00
hwspinlock hwspinlock: add stm32 hardware spinlock support 2018-12-06 23:26:33 -05:00
i2c i2c: mxc_i2c: Fix read and read->write xfers in DM mode 2019-05-17 05:35:23 +02:00
input Kconfig: tegra: Migrate TEGRA_KEYBOARD 2019-02-20 09:01:45 -07:00
led led: bcm6858: allow to use this driver on ARCH_963158 2019-04-23 17:57:22 -04:00
mailbox drivers: cosmetic: Convert SPDX license tags to Linux Kernel style 2018-10-28 09:26:39 -04:00
memory SPDX: Convert all of our single license tags to Linux Kernel style 2018-05-07 09:34:12 -04:00
misc cros_ec: Use a hyphen in the uclass name 2019-05-08 12:44:07 +08:00
mmc Merge tag 'mmc-2019-5-3' of https://github.com/MrVan/u-boot 2019-05-04 20:02:16 -04:00
mtd mtd: ubi: Remove select for non existent option 2019-05-10 07:18:13 -04:00
net eth: mtk-eth: fix incorrect read of phy-handle 2019-05-14 14:43:33 -05:00
nvme blk: Call part_init() in the post_probe() method 2018-11-14 09:16:27 -08:00
pch pch: Add ioctl support 2019-02-20 15:27:08 +08:00
pci x86: Support PCI VGA ROM when TPL is used 2019-05-08 13:02:16 +08:00
pcmcia SPDX: Convert all of our single license tags to Linux Kernel style 2018-05-07 09:34:12 -04:00
phy phy: meson: add Amlogic G12A USB2 and USB3+PCIE PHY drivers 2019-05-09 10:38:32 +02:00
pinctrl pinctrl: rockchip: Also move common set_schmitter func into per Soc file 2019-05-08 17:34:12 +08:00
power stm32 patches for v2019.07-rc1 2019-04-12 15:43:19 -04:00
pwm rockchip: use 'arch-rockchip' as header file path 2019-05-01 00:00:05 +02:00
qe drivers: qe: add TFABOOT support 2018-12-06 14:37:51 -08:00
ram rockchip: ram: rk3399: update for TPL 2019-05-08 17:34:12 +08:00
remoteproc remoteproc: k3_system_controller: Increase rx timeout 2019-05-09 20:22:05 -04:00
reset reset: socfpga: convert to livetree 2019-05-10 22:48:11 +02:00
rtc rtc: m41t62: add compatible for m41t82 2019-04-25 00:00:49 +02:00
scsi dm: scsi: report correct device number 2019-02-19 08:55:43 -05:00
serial Merge branch 'master' of git://git.denx.de/u-boot-socfpga 2019-05-13 07:13:03 -04:00
smem drivers: smem: sandbox 2018-07-19 16:31:38 -04:00
soc soc: keystone: Merge into ti specific directory 2019-04-11 20:07:12 -04:00
sound rockchip: use 'arch-rockchip' as header file path 2019-05-01 00:00:05 +02:00
spi STM32 MCUs update: 2019-05-15 07:10:32 -04:00
spmi SPDX: Convert all of our single license tags to Linux Kernel style 2018-05-07 09:34:12 -04:00
sysreset sysreset: select DM_GPIO instead of GPIO 2019-05-10 07:18:13 -04:00
tee test/py: avb: fix test_avb_persistent_values fail 2019-05-09 19:52:55 -04:00
thermal SPDX: Convert all of our single license tags to Linux Kernel style 2018-05-07 09:34:12 -04:00
timer timer: dw-apb: remove unused DECLARE_GLOBAL_DATA_PTR 2019-05-10 22:48:11 +02:00
tpm tpm: Export the open/close functions 2018-11-29 09:30:06 -07:00
usb usb: ohci: ohci-da8xx: Cleanup Error handling and fix flags 2019-05-09 19:52:55 -04:00
video rockchip: use 'arch-rockchip' as header file path 2019-05-01 00:00:05 +02:00
virtio virtio: Add a Sandbox transport driver 2018-11-14 09:16:28 -08:00
w1 w1: Add driver for i.MX bus master controller 2019-01-01 14:12:18 +01:00
w1-eeprom w1-eeprom: Add support for Maxim DS2502 add only memory 2018-11-16 16:51:55 -05:00
watchdog - mscc: small fixes, enhance network support for Serval, Luton amd 2019-05-04 20:02:42 -04:00
Kconfig dm: cache: Create a uclass for cache 2019-05-05 08:48:50 -04:00
Makefile Merge branch 'master' of git://git.denx.de/u-boot-socfpga 2019-05-07 09:37:11 -04:00