CHROMIUM: i2c-s3c2410: do not generate STOP for QUIRK_HDMIPHY buses
authorDaniel Kurtz <djkurtz@chromium.org>
Tue, 14 Aug 2012 12:52:54 +0000 (20:52 +0800)
committerGerrit <chrome-bot@google.com>
Thu, 16 Aug 2012 12:36:01 +0000 (05:36 -0700)
commitedc19760a277ca1c812f5fd1ebf303f8fd7967fd
treeed8aa57aed7b031ca6b7424a2030d468281fcb8a
parentc20f13bdf5b32856c922b5d8a9daf263c54638e7
CHROMIUM: i2c-s3c2410: do not generate STOP for QUIRK_HDMIPHY buses

The datasheet says that the STOP sequence should be:
 1) I2CSTAT.5 = 0 - Clear BUSY (or 'generate STOP')
 2) I2CCON.4 = 0 - Clear IRQPEND
 3) Wait until the stop condition takes effect.
 4*) I2CSTAT.4 = 0  - Clear TXRXEN

Where, step "4*" is only for buses with the "HDMIPHY" quirk.

However, after much experimentation, it appears that:
 a) normal buses automatically clear BUSY and transition from
    Master->Slave when they complete generating a STOP condition.
    Therefore, step (3) can be done in doxfer() by polling I2CCON.4
    after starting the STOP generation here.
 b) HDMIPHY bus does neither, so there is no way to do step 3.
    There is no indication when this bus has finished generating STOP.

In fact, we have found that as soon as the IRQPEND bit is cleared in
step 2, the HDMIPHY bus generates the STOP condition, and then immediately
starts transferring another data byte, even though the bus is supposedly
stopped.  This is presumably because the bus is still in "Master" mode,
and its BUSY bit is still set.

To avoid these extra post-STOP transactions on HDMI phy devices, we just
disable Serial Output on the bus (I2CSTAT.4 = 0) directly, instead of
first generating a proper STOP condition.  This should float SDA & SCK
terminating the transfer.  Subsequent transfers start with a proper START
condition, and proceed normally.

The HDMIPHY bus is an internal bus that always has exactly two devices,
the host as Master and the HDMIPHY device as the slave. Skipping the STOP
condition has been tested on this bus and works.

Also, since we disable the bus directly from the isr, we can skip the bus
idle polling loop at the end of doxfer().

Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
BUG=chrome-os-partner:10089
TEST=No "s3c-i2c 12ce0000.i2c: timeout waiting for bus idle" in dmesg
TEST=HDMI output works after hot plug
 1) EDID displayed in /var/log/Xorg.0.log
 2) Video shown on external monitor

Change-Id: Ic6518aceba46a058b65e6adff1bc7a5a295eb5b0
Reviewed-on: https://gerrit.chromium.org/gerrit/29876
Reviewed-by: Doug Anderson <dianders@chromium.org>
Commit-Ready: Daniel Kurtz <djkurtz@chromium.org>
Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
Tested-by: Daniel Kurtz <djkurtz@chromium.org>
drivers/i2c/busses/i2c-s3c2410.c