diff options
| author | Ilya Yanok <ilya.yanok@cogentembedded.com> | 2012-06-08 03:12:09 +0000 | 
|---|---|---|
| committer | Albert ARIBAUD <albert.u.boot@aribaud.net> | 2012-09-01 14:58:08 +0200 | 
| commit | 55faa58976c74ebc7351a87c59568f05394ff7c5 (patch) | |
| tree | a4a6160987ac8110bee39b1b96414c2020557412 /drivers/i2c | |
| parent | 27e301e5b7df6254c768d27130d3a36c31d55c96 (diff) | |
| download | olio-uboot-2014.01-55faa58976c74ebc7351a87c59568f05394ff7c5.tar.xz olio-uboot-2014.01-55faa58976c74ebc7351a87c59568f05394ff7c5.zip | |
omap24xx_i2c: add 2-byte address support
Various devices like EEPROMs require 2-byte address support to
be properly accessed. This patch adds this support for OMAP2/3/4
I2C controller driver.
I've tested it with EEPROM (16 bit address) and TPS65217 chip
(8 bit address) on TI Beaglebone board.
Unfortunately I don't have access to any compatible hardware
with 16bit data register so I can't test if those #ifdef
clauses really work.
CC: Tom Rini <trini@ti.com>
Signed-off-by: Ilya Yanok <ilya.yanok@cogentembedded.com>
Diffstat (limited to 'drivers/i2c')
| -rw-r--r-- | drivers/i2c/omap24xx_i2c.c | 58 | 
1 files changed, 26 insertions, 32 deletions
| diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c index 81193b0e6..978507ba2 100644 --- a/drivers/i2c/omap24xx_i2c.c +++ b/drivers/i2c/omap24xx_i2c.c @@ -150,16 +150,19 @@ void i2c_init(int speed, int slaveadd)  		bus_initialized[current_bus] = 1;  } -static int i2c_read_byte(u8 devaddr, u8 regoffset, u8 *value) +static int i2c_read_byte(u8 devaddr, u16 regoffset, u8 alen, u8 *value)  {  	int i2c_error = 0;  	u16 status; +	int i = 2 - alen; +	u8 tmpbuf[2] = {(regoffset) >> 8, regoffset & 0xff}; +	u16 w;  	/* wait until bus not busy */  	wait_for_bb();  	/* one byte only */ -	writew(1, &i2c_base->cnt); +	writew(alen, &i2c_base->cnt);  	/* set slave address */  	writew(devaddr, &i2c_base->sa);  	/* no stop bit needed here */ @@ -174,8 +177,12 @@ static int i2c_read_byte(u8 devaddr, u8 regoffset, u8 *value)  			goto read_exit;  		}  		if (status & I2C_STAT_XRDY) { -			/* Important: have to use byte access */ -			writeb(regoffset, &i2c_base->data); +			w = tmpbuf[i++]; +#if !(defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \ +	defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX)) +			w |= tmpbuf[i++] << 8; +#endif +			writew(w, &i2c_base->data);  			writew(I2C_STAT_XRDY, &i2c_base->stat);  		}  		if (status & I2C_STAT_ARDY) { @@ -303,18 +310,18 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)  {  	int i; -	if (alen > 1) { +	if (alen > 2) {  		printf("I2C read: addr len %d not supported\n", alen);  		return 1;  	} -	if (addr + len > 256) { +	if (addr + len > (1 << 16)) {  		puts("I2C read: address out of range\n");  		return 1;  	}  	for (i = 0; i < len; i++) { -		if (i2c_read_byte(chip, addr + i, &buffer[i])) { +		if (i2c_read_byte(chip, addr + i, alen, &buffer[i])) {  			puts("I2C read: I/O error\n");  			i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);  			return 1; @@ -329,13 +336,15 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)  	int i;  	u16 status;  	int i2c_error = 0; +	u16 w; +	u8 tmpbuf[2] = {addr >> 8, addr & 0xff}; -	if (alen > 1) { +	if (alen > 2) {  		printf("I2C write: addr len %d not supported\n", alen);  		return 1;  	} -	if (addr + len > 256) { +	if (addr + len > (1 << 16)) {  		printf("I2C write: address 0x%x + 0x%x out of range\n",  				addr, len);  		return 1; @@ -353,28 +362,8 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)  	writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX |  		I2C_CON_STP, &i2c_base->con); -	/* Send address byte */ -	status = wait_for_pin(); - -	if (status == 0 || status & I2C_STAT_NACK) { -		i2c_error = 1; -		printf("error waiting for i2c address ACK (status=0x%x)\n", -		      status); -		goto write_exit; -	} - -	if (status & I2C_STAT_XRDY) { -		writeb(addr & 0xFF, &i2c_base->data); -		writew(I2C_STAT_XRDY, &i2c_base->stat); -	} else { -		i2c_error = 1; -		printf("i2c bus not ready for transmit (status=0x%x)\n", -		      status); -		goto write_exit; -	} - -	/* address phase is over, now write data */ -	for (i = 0; i < len; i++) { +	/* Send address and data */ +	for (i = -alen; i < len; i++) {  		status = wait_for_pin();  		if (status == 0 || status & I2C_STAT_NACK) { @@ -385,7 +374,12 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)  		}  		if (status & I2C_STAT_XRDY) { -			writeb(buffer[i], &i2c_base->data); +			w = (i < 0) ? tmpbuf[2+i] : buffer[i]; +#if !(defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \ +	defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX)) +			w |= ((++i < 0) ? tmpbuf[2+i] : buffer[i]) << 8; +#endif +			writew(w, &i2c_base->data);  			writew(I2C_STAT_XRDY, &i2c_base->stat);  		} else {  			i2c_error = 1; |