aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDaniel Kurtz <djkurtz@chromium.org>2012-11-15 07:13:31 -0500
committerWolfram Sang <w.sang@pengutronix.de>2012-11-16 07:08:55 -0500
commit0da2e7768b4c2b4dbbb148ebe1606b6b4698fca2 (patch)
tree7041036334f71612cc64c4e8b322db396989084c /drivers
parent9bcd04bfbbd5599de011176b846ed00ac15a234c (diff)
i2c: s3c2410: do not generate STOP for QUIRK_HDMIPHY
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> Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c47
1 files changed, 45 insertions, 2 deletions
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 86e60f598c51..a44e2130d3e0 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -235,8 +235,47 @@ static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret)
235 235
236 dev_dbg(i2c->dev, "STOP\n"); 236 dev_dbg(i2c->dev, "STOP\n");
237 237
238 /* stop the transfer */ 238 /*
239 iicstat &= ~S3C2410_IICSTAT_START; 239 * The datasheet says that the STOP sequence should be:
240 * 1) I2CSTAT.5 = 0 - Clear BUSY (or 'generate STOP')
241 * 2) I2CCON.4 = 0 - Clear IRQPEND
242 * 3) Wait until the stop condition takes effect.
243 * 4*) I2CSTAT.4 = 0 - Clear TXRXEN
244 *
245 * Where, step "4*" is only for buses with the "HDMIPHY" quirk.
246 *
247 * However, after much experimentation, it appears that:
248 * a) normal buses automatically clear BUSY and transition from
249 * Master->Slave when they complete generating a STOP condition.
250 * Therefore, step (3) can be done in doxfer() by polling I2CCON.4
251 * after starting the STOP generation here.
252 * b) HDMIPHY bus does neither, so there is no way to do step 3.
253 * There is no indication when this bus has finished generating
254 * STOP.
255 *
256 * In fact, we have found that as soon as the IRQPEND bit is cleared in
257 * step 2, the HDMIPHY bus generates the STOP condition, and then
258 * immediately starts transferring another data byte, even though the
259 * bus is supposedly stopped. This is presumably because the bus is
260 * still in "Master" mode, and its BUSY bit is still set.
261 *
262 * To avoid these extra post-STOP transactions on HDMI phy devices, we
263 * just disable Serial Output on the bus (I2CSTAT.4 = 0) directly,
264 * instead of first generating a proper STOP condition. This should
265 * float SDA & SCK terminating the transfer. Subsequent transfers
266 * start with a proper START condition, and proceed normally.
267 *
268 * The HDMIPHY bus is an internal bus that always has exactly two
269 * devices, the host as Master and the HDMIPHY device as the slave.
270 * Skipping the STOP condition has been tested on this bus and works.
271 */
272 if (i2c->quirks & QUIRK_HDMIPHY) {
273 /* Stop driving the I2C pins */
274 iicstat &= ~S3C2410_IICSTAT_TXRXEN;
275 } else {
276 /* stop the transfer */
277 iicstat &= ~S3C2410_IICSTAT_START;
278 }
240 writel(iicstat, i2c->regs + S3C2410_IICSTAT); 279 writel(iicstat, i2c->regs + S3C2410_IICSTAT);
241 280
242 i2c->state = STATE_STOP; 281 i2c->state = STATE_STOP;
@@ -561,6 +600,10 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
561 else if (ret != num) 600 else if (ret != num)
562 dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret); 601 dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret);
563 602
603 /* For QUIRK_HDMIPHY, bus is already disabled */
604 if (i2c->quirks & QUIRK_HDMIPHY)
605 goto out;
606
564 /* ensure the stop has been through the bus */ 607 /* ensure the stop has been through the bus */
565 608
566 dev_dbg(i2c->dev, "waiting for bus idle\n"); 609 dev_dbg(i2c->dev, "waiting for bus idle\n");