On 25/03/13 20:46, Akshay Saraswat wrote:
> From: Gabe Black <gabebl...@google.com>
> 
> The exynos s3c24x0 i2c driver wouldn't do the right thing when a NACK was
> received on a read because it didn't attempt a read before waiting for the
> read to finish. Putting a call to ReadWriteByte in the NACK path fixed a
> problem where getting a NACK reading from a device would jam up the bus and
> prevent future accesses like probing from working.
> 
> Because other than the ReadWriteByte call the NACK and normal paths were
> almost the same thing, and to avoid future instances of the NACK path not
> working because it's not exercised normally, this change also consolidates
> those two paths.
> 
> Signed-off-by: Gabe Black <gabebl...@google.com>
> Signed-off-by: Akshay Saraswat <aksha...@samsung.com>
> ---
>  drivers/i2c/s3c24x0_i2c.c | 53 
> ++++++++++++++++-------------------------------
>  1 file changed, 18 insertions(+), 35 deletions(-)
> 
> diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c
> index d2b4eb0..91298a7 100644
> --- a/drivers/i2c/s3c24x0_i2c.c
> +++ b/drivers/i2c/s3c24x0_i2c.c
> @@ -366,21 +366,25 @@ static int i2c_transfer(struct s3c24x0_i2c *i2c,
>               break;
>  
>       case I2C_READ:
> -             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);
> -                     ReadWriteByte(i2c);
> -                     result = WaitForXfer(i2c);
> +     {
> +             int was_ok = (result == I2C_OK);

do you really need the was_ok?
If not, please remove it.

> +
> +             writel(chip, &i2c->iicds);
> +             /* resend START */
> +             writel(I2C_MODE_MR | I2C_TXRX_ENA |
> +                                     I2C_START_STOP, &i2c->iicstat);
> +             ReadWriteByte(i2c);
> +             result = WaitForXfer(i2c);
> +
> +             if (was_ok || IsACK(i2c)) {
>                       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);
> +                             if (i == data_len - 1) {
> +                                     writel(readl(&i2c->iiccon) &
> +                                           ~I2CCON_ACKGEN,
> +                                           &i2c->iiccon);
> +                             }
>                               ReadWriteByte(i2c);
>                               result = WaitForXfer(i2c);
>                               data[i] = readl(&i2c->iicds);
> @@ -388,35 +392,14 @@ static int i2c_transfer(struct s3c24x0_i2c *i2c,
>                       }
>  
>               } else {
> -                     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 < 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;
> -                     }
> +                     result = I2C_NACK;
>               }
>  
>               /* send STOP */
>               writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat);
>               ReadWriteByte(i2c);
>               break;
> +     }
>  
>       default:
>               debug("i2c_transfer: bad call\n");
> 

Thanks,
Minkyu Kang.
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to