diff options
Diffstat (limited to 'drivers/i2c/mxc_i2c.c')
| -rw-r--r-- | drivers/i2c/mxc_i2c.c | 36 | 
1 files changed, 27 insertions, 9 deletions
| diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c index 093a73f1c..cbb0fffb8 100644 --- a/drivers/i2c/mxc_i2c.c +++ b/drivers/i2c/mxc_i2c.c @@ -218,7 +218,7 @@ void i2c_imx_stop(void)   * Send start signal, chip address and   * write register address   */ -static int i2c_init_transfer(struct mxc_i2c_regs *i2c_regs, +static int i2c_init_transfer_(struct mxc_i2c_regs *i2c_regs,  		uchar chip, uint addr, int alen)  {  	unsigned int temp; @@ -235,7 +235,7 @@ static int i2c_init_transfer(struct mxc_i2c_regs *i2c_regs,  	writeb(0, &i2c_regs->i2sr);  	ret = wait_for_sr_state(i2c_regs, ST_BUS_IDLE);  	if (ret < 0) -		goto exit; +		return ret;  	/* Start I2C transaction */  	temp = readb(&i2c_regs->i2cr); @@ -244,7 +244,7 @@ static int i2c_init_transfer(struct mxc_i2c_regs *i2c_regs,  	ret = wait_for_sr_state(i2c_regs, ST_BUS_BUSY);  	if (ret < 0) -		goto exit; +		return ret;  	temp |= I2CR_MTX | I2CR_TX_NO_AK;  	writeb(temp, &i2c_regs->i2cr); @@ -252,18 +252,36 @@ static int i2c_init_transfer(struct mxc_i2c_regs *i2c_regs,  	/* write slave address */  	ret = tx_byte(i2c_regs, chip << 1);  	if (ret < 0) -		goto exit; +		return ret;  	while (alen--) {  		ret = tx_byte(i2c_regs, (addr >> (alen * 8)) & 0xff);  		if (ret < 0) -			goto exit; +			return ret;  	}  	return 0; -exit: -	i2c_imx_stop(); -	/* Disable I2C controller */ -	writeb(0, &i2c_regs->i2cr); +} + +static int i2c_init_transfer(struct mxc_i2c_regs *i2c_regs, +		uchar chip, uint addr, int alen) +{ +	int retry; +	int ret; +	for (retry = 0; retry < 3; retry++) { +		ret = i2c_init_transfer_(i2c_regs, chip, addr, alen); +		if (ret >= 0) +			return 0; +		i2c_imx_stop(); +		if (ret == -ENODEV) +			return ret; + +		printf("%s: failed for chip 0x%x retry=%d\n", __func__, chip, +				retry); +		if (ret != -ERESTART) +			writeb(0, &i2c_regs->i2cr);	/* Disable controller */ +		udelay(100); +	} +	printf("%s: give up i2c_regs=%p\n", __func__, i2c_regs);  	return ret;  } |