From: Naveen Krishna Chatradhi <ch.nav...@samsung.com> Adding NACK logic for i2c write. Verified by reading and writing to device with address 9 on i2c-0.
Signed-off-by: Naveen Krishna Chatradhi <ch.nav...@samsung.com> Signed-off-by: Akshay Saraswat <aksha...@samsung.com> --- drivers/i2c/s3c24x0_i2c.c | 111 +++++++++++++++++++++++----------------------- 1 file changed, 56 insertions(+), 55 deletions(-) diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c index 769a2ba..d2b4eb0 100644 --- a/drivers/i2c/s3c24x0_i2c.c +++ b/drivers/i2c/s3c24x0_i2c.c @@ -201,6 +201,35 @@ unsigned int i2c_get_bus_num(void) } #endif +/* + * Verify the whether I2C ACK was received or not + * + * @param i2c pointer to I2C register base + * @param buf array of data + * @param len length of data + * return I2C_OK when transmission done + * I2C_NACK otherwise + */ +static int i2c_send_verify(struct s3c24x0_i2c *i2c, unsigned char buf[], + unsigned char len) +{ + int i, result = I2C_OK; + + if (IsACK(i2c)) { + for (i = 0; (i < len) && (result == I2C_OK); i++) { + writel(buf[i], &i2c->iicds); + ReadWriteByte(i2c); + result = WaitForXfer(i2c); + if (!IsACK(i2c)) + result = I2C_NACK; + } + } else { + result = I2C_NACK; + } + + return result; +} + void i2c_init(int speed, int slaveadd) { struct s3c24x0_i2c *i2c; @@ -302,41 +331,30 @@ static int i2c_transfer(struct s3c24x0_i2c *i2c, return I2C_NOK_TOUT; writel(readl(&i2c->iiccon) | I2CCON_ACKGEN, &i2c->iiccon); - result = I2C_OK; + + if (addr && addr_len) { + writel(chip, &i2c->iicds); + /* send START */ + writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP, + &i2c->iicstat); + if (WaitForXfer(i2c) == I2C_OK) + result = i2c_send_verify(i2c, addr, addr_len); + else + result = I2C_NACK; + } else + result = I2C_NACK; switch (cmd_type) { case I2C_WRITE: - if (addr && addr_len) { - writel(chip, &i2c->iicds); - /* send START */ - writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP, - &i2c->iicstat); - i = 0; - while ((i < addr_len) && (result == I2C_OK)) { - result = WaitForXfer(i2c); - writel(addr[i], &i2c->iicds); - ReadWriteByte(i2c); - i++; - } - i = 0; - while ((i < data_len) && (result == I2C_OK)) { - result = WaitForXfer(i2c); - writel(data[i], &i2c->iicds); - ReadWriteByte(i2c); - i++; - } - } else { + if (result == I2C_OK) + result = i2c_send_verify(i2c, data, data_len); + else { writel(chip, &i2c->iicds); /* send START */ writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP, - &i2c->iicstat); - i = 0; - while ((i < data_len) && (result = I2C_OK)) { - result = WaitForXfer(i2c); - writel(data[i], &i2c->iicds); - ReadWriteByte(i2c); - i++; - } + &i2c->iicstat); + if (WaitForXfer(i2c) == I2C_OK) + result = i2c_send_verify(i2c, data, data_len); } if (result == I2C_OK) @@ -348,42 +366,25 @@ static int i2c_transfer(struct s3c24x0_i2c *i2c, break; case I2C_READ: - if (addr && addr_len) { - writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat); + if (result == I2C_OK) { + writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat); writel(chip, &i2c->iicds); /* send START */ writel(readl(&i2c->iicstat) | I2C_START_STOP, &i2c->iicstat); - result = WaitForXfer(i2c); - if (IsACK(i2c)) { - i = 0; - while ((i < addr_len) && (result == I2C_OK)) { - writel(addr[i], &i2c->iicds); - ReadWriteByte(i2c); - result = WaitForXfer(i2c); - i++; - } - - writel(chip, &i2c->iicds); - /* resend START */ - writel(I2C_MODE_MR | I2C_TXRX_ENA | - I2C_START_STOP, &i2c->iicstat); ReadWriteByte(i2c); result = WaitForXfer(i2c); - i = 0; - while ((i < data_len) && (result == I2C_OK)) { - /* disable ACK for final READ */ - if (i == data_len - 1) - writel(readl(&i2c->iiccon) + i = 0; + while ((i < data_len) && (result == I2C_OK)) { + /* disable ACK for final READ */ + if (i == data_len - 1) + writel(readl(&i2c->iiccon) & ~I2CCON_ACKGEN, &i2c->iiccon); ReadWriteByte(i2c); result = WaitForXfer(i2c); - data[i] = readl(&i2c->iicds); - i++; - } - } else { - result = I2C_NACK; + data[i] = readl(&i2c->iicds); + i++; } } else { -- 1.8.0 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot