On Mon, Mar 25, 2013 at 4:17 AM, Akshay Saraswat <aksha...@samsung.com> wrote: > > 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 >
Guys, can we please hold on to this. I have a version which was debugged and worked with the Infineon TPM, (which is generates NACKs quite liberally, and not just on writes, but on reads too). I will submit it a bit later. --vb > _______________________________________________ > U-Boot mailing list > U-Boot@lists.denx.de > http://lists.denx.de/mailman/listinfo/u-boot _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot