aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorBen Dooks <ben-linux@fluff.org>2007-05-01 17:26:35 -0400
committerJean Delvare <khali@hyperion.delvare>2007-05-01 17:26:35 -0400
commite00a8cdf325346c531c841ee85c803792db60157 (patch)
treecd77aa2a2f94e8577f73ec3e2e4073ad94c184b9 /drivers/i2c
parente8c76eed2ecdb8e9ca5339761d2c076d32b7cbca (diff)
i2c-s3c2410: Fix I2C SDA to SCL setup time
Fix the setup time for SDA to SCL due to the way the S3C24XX I2C controller works. Signed-off-by: Ben Dooks <ben-linux@fluff.org> Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c26
1 files changed, 20 insertions, 6 deletions
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 3eb5958f347d..e8395be0d92c 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -61,6 +61,8 @@ struct s3c24xx_i2c {
61 unsigned int msg_idx; 61 unsigned int msg_idx;
62 unsigned int msg_ptr; 62 unsigned int msg_ptr;
63 63
64 unsigned int tx_setup;
65
64 enum s3c24xx_i2c_state state; 66 enum s3c24xx_i2c_state state;
65 67
66 void __iomem *regs; 68 void __iomem *regs;
@@ -199,8 +201,11 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
199 dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr); 201 dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr);
200 writeb(addr, i2c->regs + S3C2410_IICDS); 202 writeb(addr, i2c->regs + S3C2410_IICDS);
201 203
202 // delay a bit and reset iiccon before setting start (per samsung) 204 /* delay here to ensure the data byte has gotten onto the bus
203 udelay(1); 205 * before the transaction is started */
206
207 ndelay(i2c->tx_setup);
208
204 dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon); 209 dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon);
205 writel(iiccon, i2c->regs + S3C2410_IICCON); 210 writel(iiccon, i2c->regs + S3C2410_IICCON);
206 211
@@ -322,7 +327,15 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
322 if (!is_msgend(i2c)) { 327 if (!is_msgend(i2c)) {
323 byte = i2c->msg->buf[i2c->msg_ptr++]; 328 byte = i2c->msg->buf[i2c->msg_ptr++];
324 writeb(byte, i2c->regs + S3C2410_IICDS); 329 writeb(byte, i2c->regs + S3C2410_IICDS);
325 330
331 /* delay after writing the byte to allow the
332 * data setup time on the bus, as writing the
333 * data to the register causes the first bit
334 * to appear on SDA, and SCL will change as
335 * soon as the interrupt is acknowledged */
336
337 ndelay(i2c->tx_setup);
338
326 } else if (!is_lastmsg(i2c)) { 339 } else if (!is_lastmsg(i2c)) {
327 /* we need to go to the next i2c message */ 340 /* we need to go to the next i2c message */
328 341
@@ -570,9 +583,10 @@ static const struct i2c_algorithm s3c24xx_i2c_algorithm = {
570}; 583};
571 584
572static struct s3c24xx_i2c s3c24xx_i2c = { 585static struct s3c24xx_i2c s3c24xx_i2c = {
573 .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_i2c.lock), 586 .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_i2c.lock),
574 .wait = __WAIT_QUEUE_HEAD_INITIALIZER(s3c24xx_i2c.wait), 587 .wait = __WAIT_QUEUE_HEAD_INITIALIZER(s3c24xx_i2c.wait),
575 .adap = { 588 .tx_setup = 50,
589 .adap = {
576 .name = "s3c2410-i2c", 590 .name = "s3c2410-i2c",
577 .owner = THIS_MODULE, 591 .owner = THIS_MODULE,
578 .algo = &s3c24xx_i2c_algorithm, 592 .algo = &s3c24xx_i2c_algorithm,