Commit e00a8cdf authored by Ben Dooks's avatar Ben Dooks Committed by Jean Delvare

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: default avatarBen Dooks <ben-linux@fluff.org>
Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
parent e8c76eed
...@@ -61,6 +61,8 @@ struct s3c24xx_i2c { ...@@ -61,6 +61,8 @@ struct s3c24xx_i2c {
unsigned int msg_idx; unsigned int msg_idx;
unsigned int msg_ptr; unsigned int msg_ptr;
unsigned int tx_setup;
enum s3c24xx_i2c_state state; enum s3c24xx_i2c_state state;
void __iomem *regs; void __iomem *regs;
...@@ -199,8 +201,11 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c, ...@@ -199,8 +201,11 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr); dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr);
writeb(addr, i2c->regs + S3C2410_IICDS); writeb(addr, i2c->regs + S3C2410_IICDS);
// delay a bit and reset iiccon before setting start (per samsung) /* delay here to ensure the data byte has gotten onto the bus
udelay(1); * before the transaction is started */
ndelay(i2c->tx_setup);
dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon); dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon);
writel(iiccon, i2c->regs + S3C2410_IICCON); writel(iiccon, i2c->regs + S3C2410_IICCON);
...@@ -323,6 +328,14 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) ...@@ -323,6 +328,14 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
byte = i2c->msg->buf[i2c->msg_ptr++]; byte = i2c->msg->buf[i2c->msg_ptr++];
writeb(byte, i2c->regs + S3C2410_IICDS); writeb(byte, i2c->regs + S3C2410_IICDS);
/* delay after writing the byte to allow the
* data setup time on the bus, as writing the
* data to the register causes the first bit
* to appear on SDA, and SCL will change as
* soon as the interrupt is acknowledged */
ndelay(i2c->tx_setup);
} else if (!is_lastmsg(i2c)) { } else if (!is_lastmsg(i2c)) {
/* we need to go to the next i2c message */ /* we need to go to the next i2c message */
...@@ -572,6 +585,7 @@ static const struct i2c_algorithm s3c24xx_i2c_algorithm = { ...@@ -572,6 +585,7 @@ static const struct i2c_algorithm s3c24xx_i2c_algorithm = {
static struct s3c24xx_i2c s3c24xx_i2c = { static struct s3c24xx_i2c s3c24xx_i2c = {
.lock = __SPIN_LOCK_UNLOCKED(s3c24xx_i2c.lock), .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_i2c.lock),
.wait = __WAIT_QUEUE_HEAD_INITIALIZER(s3c24xx_i2c.wait), .wait = __WAIT_QUEUE_HEAD_INITIALIZER(s3c24xx_i2c.wait),
.tx_setup = 50,
.adap = { .adap = {
.name = "s3c2410-i2c", .name = "s3c2410-i2c",
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment