diff options
author | Ben Dooks <ben-linux@fluff.org> | 2007-05-01 17:26:35 -0400 |
---|---|---|
committer | Jean Delvare <khali@hyperion.delvare> | 2007-05-01 17:26:35 -0400 |
commit | e00a8cdf325346c531c841ee85c803792db60157 (patch) | |
tree | cd77aa2a2f94e8577f73ec3e2e4073ad94c184b9 /drivers/i2c/busses/i2c-s3c2410.c | |
parent | e8c76eed2ecdb8e9ca5339761d2c076d32b7cbca (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/busses/i2c-s3c2410.c')
-rw-r--r-- | drivers/i2c/busses/i2c-s3c2410.c | 26 |
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 | ||
572 | static struct s3c24xx_i2c s3c24xx_i2c = { | 585 | static 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, |