Revert "ARM: I2C: I2C Multi byte address support"
A message that is not in the archive (sent off-list or not yet received): 1329799757-17517-1-git-send-email-y
PATCH 2/2 Revert "ARM: I2C: I2C Multi byte address support"
From: Tom Rini <[email protected]>
This reverts commits 2faa76196af4b3e93bcb9e38ed9090cbd3b06db3 as this has introduced some large problems on all other platforms and have more changes in them than the commit message implies.
Cc Heiko Schocher <[email protected]>
Cc Patil, Rachna <[email protected]>
Signed-off-by Tom Rini <[email protected]>
--- drivers/i2c/omap24xx_i2c.c | 467 ++++++++++++++++---------------------------- drivers/i2c/omap24xx_i2c.h | 2 - 2 files changed, 173 insertions(+), 296 deletions(-)
drivers/i2c/omap24xx_i2c.c +173 -294
@@ -29,11 +29,10 @@DECLARE_GLOBAL_DATA_PTR ; -#define I2C_STAT_TIMEO (1 << 31) -#define I2C_TIMEOUT 10 +#define I2C_TIMEOUT 1000 -static u32 wait_for_bb (void ); -static u32 wait_for_status_mask (u16 mask); +static void wait_for_bb (void ); +static u16 wait_for_pin (void );static void flush_fifo (void );/*
@@ -51,6 +50,7 @@ void i2c_init(int speed, int slaveadd)int psc, fsscll, fssclh;int hsscll =0 , hssclh =0 ;u32 scll, sclh; +int timeout =I2C_TIMEOUT ;/* Only handle standard, fast and high speeds */ if ((speed != OMAP_I2C_STANDARD) &&
@@ -112,14 +112,24 @@ void i2c_init(int speed, int slaveadd) sclh = (unsigned int )fssclh; } -if (gd->flags &GD_FLG_RELOC ) - bus_initialized[current_bus] =1 ; -if (readw (&i2c_base->con) &I2C_CON_EN ) {writew (0 , &i2c_base->con);udelay (50000 ); } +writew (0x2 , &i2c_base->sysc);/* for ES2 after soft reset */ +udelay (1000 ); + +writew (I2C_CON_EN , &i2c_base->con); +while (!(readw (&i2c_base->syss) &I2C_SYSS_RDONE ) && timeout--) { +if (timeout <=0 ) { +puts ("ERROR: Timeout in soft-reset\n" ); +return ; + } +udelay (1000 ); + } + +writew (0 , &i2c_base->con);writew (psc, &i2c_base->psc);writew (scll, &i2c_base->scll);writew (sclh, &i2c_base->sclh);
@@ -135,6 +145,81 @@ void i2c_init(int speed, int slaveadd)flush_fifo ();writew (0xFFFF , &i2c_base->stat);writew (0 , &i2c_base->cnt); + +if (gd->flags &GD_FLG_RELOC ) + bus_initialized[current_bus] =1 ; +} + +static int i2c_read_byte (u8 devaddr,u8 regoffset,u8 *value) +{ +int i2c_error =0 ; +u16 status; + +/* wait until bus not busy */ +wait_for_bb (); + +/* one byte only */ +writew (1 , &i2c_base->cnt); +/* set slave address */ +writew (devaddr, &i2c_base->sa); +/* no stop bit needed here */ +writew (I2C_CON_EN |I2C_CON_MST |I2C_CON_STT | +I2C_CON_TRX , &i2c_base->con); + +/* send register offset */ +while (1 ) { + status =wait_for_pin (); +if (status ==0 || status &I2C_STAT_NACK ) { + i2c_error =1 ; + goto read_exit; + } +if (status &I2C_STAT_XRDY ) { +/* Important: have to use byte access */ +writeb (regoffset, &i2c_base->data); +writew (I2C_STAT_XRDY , &i2c_base->stat); + } +if (status &I2C_STAT_ARDY ) { +writew (I2C_STAT_ARDY , &i2c_base->stat); +break ; + } + } + +/* set slave address */ +writew (devaddr, &i2c_base->sa); +/* read one byte from slave */ +writew (1 , &i2c_base->cnt); +/* need stop bit here */ +writew (I2C_CON_EN |I2C_CON_MST | +I2C_CON_STT |I2C_CON_STP , + &i2c_base->con); + +/* receive data */ +while (1 ) { + status =wait_for_pin (); +if (status ==0 || status &I2C_STAT_NACK ) { + i2c_error =1 ; + goto read_exit; + } +if (status &I2C_STAT_RRDY ) { +#if defined(CONFIG_OMAP243X ) || defined(CONFIG_OMAP34XX ) || \ + defined(CONFIG_OMAP44XX ) + *value =readb (&i2c_base->data); +#else + *value =readw (&i2c_base->data); +#endif +writew (I2C_STAT_RRDY , &i2c_base->stat); + } +if (status &I2C_STAT_ARDY ) { +writew (I2C_STAT_ARDY , &i2c_base->stat); +break ; + } + } + +read_exit: +flush_fifo (); +writew (0xFFFF , &i2c_base->stat); +writew (0 , &i2c_base->cnt); +return i2c_error; }static void flush_fifo (void )
@@ -161,42 +246,32 @@ static void flush_fifo(void)int i2c_probe (uchar chip) { -u32 status; +u16 status;int res =1 ;/* default = fail */ if (chip ==readw (&i2c_base->oa))return res;/* wait until bus not busy */ - status =wait_for_bb (); -/* exit on BUS busy */ -if (status &I2C_STAT_TIMEO ) -return res; +wait_for_bb ();/* try to write one byte */ writew (1 , &i2c_base->cnt);/* set slave address */ writew (chip, &i2c_base->sa);/* stop bit needed here */ -writew (I2C_CON_EN |I2C_CON_MST |I2C_CON_STT - |I2C_CON_STP , &i2c_base->con); -/* enough delay for the NACK bit set */ -udelay (9000 ); - -if (!(readw (&i2c_base->stat) &I2C_STAT_NACK )) { - res =0 ;/* success case */ -flush_fifo (); -writew (0xFFFF , &i2c_base->stat); - }else { -/* failure, clear sources*/ -writew (0xFFFF , &i2c_base->stat); -/* finish up xfer */ -writew (readw (&i2c_base->con) |I2C_CON_STP , &i2c_base->con); - status =wait_for_bb (); -/* exit on BUS busy */ -if (status &I2C_STAT_TIMEO ) -return res; - } +writew (I2C_CON_EN |I2C_CON_MST |I2C_CON_STT |I2C_CON_TRX | +I2C_CON_STP , &i2c_base->con); + + status =wait_for_pin (); + +/* check for ACK (!NAK) */ +if (!(status &I2C_STAT_NACK )) + res =0 ; + +/* abort transfer (force idle state) */ +writew (0 , &i2c_base->con); +flush_fifo ();/* don't allow any more data in... we don't want it. */ writew (0 , &i2c_base->cnt);
@@ -206,309 +281,111 @@ int i2c_probe(uchar chip)int i2c_read (uchar chip,uint addr,int alen,uchar *buffer,int len) { -int i2c_error =0 , i; -u32 status; - -if ((alen >2 ) || (alen <0 )) -return 1 ; +int i; -if (alen <2 ) { -if (addr + len >256 ) -return 1 ; - }else if (addr + len >0xFFFF ) { +if (alen >1 ) { +printf ("I2C read: addr len %d not supported\n" , alen);return 1 ; } -/* wait until bus not busy */ - status =wait_for_bb (); - -/* exit on BUS busy */ -if (status &I2C_STAT_TIMEO ) +if (addr + len >256 ) { +puts ("I2C read: address out of range\n" );return 1 ; - -writew ((alen &0xFF ), &i2c_base->cnt); -/* set slave address */ -writew (chip, &i2c_base->sa); -/* Clear the Tx & Rx FIFOs */ -writew ((readw (&i2c_base->buf) |I2C_RXFIFO_CLEAR | -I2C_TXFIFO_CLEAR ), &i2c_base->buf); -/* no stop bit needed here */ -writew (I2C_CON_EN |I2C_CON_MST |I2C_CON_TRX | -I2C_CON_STT , &i2c_base->con); - -/* wait for Transmit ready condition */ - status =wait_for_status_mask (I2C_STAT_XRDY |I2C_STAT_NACK ); - -if (status & (I2C_STAT_NACK |I2C_STAT_TIMEO )) - i2c_error =1 ; - -if (!i2c_error) { -if (status &I2C_STAT_XRDY ) { -switch (alen) { -case 2 : -/* Send address MSByte */ -#if defined(CONFIG_OMAP243X ) || defined(CONFIG_OMAP34XX ) -writew (((addr >>8 ) &0xFF ), &i2c_base->data); - -/* Clearing XRDY event */ -writew ((status &I2C_STAT_XRDY ), - &i2c_base->stat); -/* wait for Transmit ready condition */ - status =wait_for_status_mask (I2C_STAT_XRDY | -I2C_STAT_NACK ); - -if (status & (I2C_STAT_NACK | -I2C_STAT_TIMEO )) { - i2c_error =1 ; -break ; - } -#endif -case 1 : -#if defined(CONFIG_OMAP243X ) || defined(CONFIG_OMAP34XX ) -/* Send address LSByte */ -writew ((addr &0xFF ), &i2c_base->data); -#else -/* Send address Short word */ -writew ((addr &0xFFFF ), &i2c_base->data); -#endif -/* Clearing XRDY event */ -writew ((status &I2C_STAT_XRDY ), - &i2c_base->stat); -/*wait for Transmit ready condition */ - status =wait_for_status_mask (I2C_STAT_ARDY | -I2C_STAT_NACK ); - -if (status & (I2C_STAT_NACK | -I2C_STAT_TIMEO )) { - i2c_error =1 ; -break ; - } - } - }else - i2c_error =1 ; } -/* Wait for ARDY to set */ - status =wait_for_status_mask (I2C_STAT_ARDY |I2C_STAT_NACK - |I2C_STAT_AL ); - -if (!i2c_error) { -/* set slave address */ -writew (chip, &i2c_base->sa); -writew ((len &0xFF ), &i2c_base->cnt); -/* Clear the Tx & Rx FIFOs */ -writew ((readw (&i2c_base->buf) |I2C_RXFIFO_CLEAR | -I2C_TXFIFO_CLEAR ), &i2c_base->buf); -/* need stop bit here */ -writew (I2C_CON_EN |I2C_CON_MST |I2C_CON_STT |I2C_CON_STP , - &i2c_base->con); - -for (i =0 ; i < len; i++) { -/* wait for Receive condition */ - status =wait_for_status_mask (I2C_STAT_RRDY | -I2C_STAT_NACK ); -if (status & (I2C_STAT_NACK |I2C_STAT_TIMEO )) { - i2c_error =1 ; -break ; - } - -if (status &I2C_STAT_RRDY ) { -#if defined(CONFIG_OMAP243X ) || defined(CONFIG_OMAP34XX ) - buffer[i] =readb (&i2c_base->data); -#else - *((u16 *)&buffer[i]) = -readw (&i2c_base->data) &0xFFFF ; - i++; -#endif -writew ((status &I2C_STAT_RRDY ), - &i2c_base->stat); -udelay (1000 ); - }else { - i2c_error =1 ; - } +for (i =0 ; i < len; i++) { +if (i2c_read_byte (chip, addr + i, &buffer[i])) { +puts ("I2C read: I/O error\n" ); +i2c_init (CONFIG_SYS_I2C_SPEED ,CONFIG_SYS_I2C_SLAVE ); +return 1 ; } } -/* Wait for ARDY to set */ - status =wait_for_status_mask (I2C_STAT_ARDY |I2C_STAT_NACK - |I2C_STAT_AL ); - -if (i2c_error) { -writew (0 , &i2c_base->con); -return 1 ; - } - -writew (I2C_CON_EN , &i2c_base->con); - -while (readw (&i2c_base->stat) - || (readw (&i2c_base->con) &I2C_CON_MST )) { -udelay (10000 ); -writew (0xFFFF , &i2c_base->stat); - } - -writew (I2C_CON_EN , &i2c_base->con); -flush_fifo (); -writew (0xFFFF , &i2c_base->stat); -writew (0 , &i2c_base->cnt); -return 0 ; }int i2c_write (uchar chip,uint addr,int alen,uchar *buffer,int len) { +int i; +u16 status; +int i2c_error =0 ; -int i, i2c_error =0 ; -u32 status; -u16 writelen; - -if (alen >2 ) +if (alen >1 ) { +printf ("I2C write: addr len %d not supported\n" , alen);return 1 ; + } -if (alen <2 ) { -if (addr + len >256 ) -return 1 ; - }else if (addr + len >0xFFFF ) { +if (addr + len >256 ) { +printf ("I2C write: address 0x%x + 0x%x out of range\n" , + addr, len);return 1 ; }/* wait until bus not busy */ - status =wait_for_bb (); - -/* exiting on BUS busy */ -if (status &I2C_STAT_TIMEO ) -return 1 ; +wait_for_bb (); - writelen = (len &0xFFFF ) + alen; - -/* two bytes */ -writew ((writelen &0xFFFF ), &i2c_base->cnt); -/* Clear the Tx & Rx FIFOs */ -writew ((readw (&i2c_base->buf) |I2C_RXFIFO_CLEAR | -I2C_TXFIFO_CLEAR ), &i2c_base->buf); +/* start address phase - will write regoffset + len bytes data */ +/* TODO consider case when !CONFIG_OMAP243X/34XX/44XX */ +writew (alen + len, &i2c_base->cnt);/* set slave address */ writew (chip, &i2c_base->sa);/* stop bit needed here */ writew (I2C_CON_EN |I2C_CON_MST |I2C_CON_STT |I2C_CON_TRX |I2C_CON_STP , &i2c_base->con); -/* wait for Transmit ready condition */ - status =wait_for_status_mask (I2C_STAT_XRDY |I2C_STAT_NACK ); +/* Send address byte */ + status =wait_for_pin (); -if (status & (I2C_STAT_NACK |I2C_STAT_TIMEO )) +if (status ==0 || status &I2C_STAT_NACK ) { i2c_error =1 ; - -if (!i2c_error) { -if (status &I2C_STAT_XRDY ) { -switch (alen) { -#if defined(CONFIG_OMAP243X ) || defined(CONFIG_OMAP34XX ) -case 2 : -/* send out MSB byte */ -writeb (((addr >>8 ) &0xFF ), &i2c_base->data); -#else -writeb ((addr &0xFFFF ), &i2c_base->data); -break ; -#endif -/* Clearing XRDY event */ -writew ((status &I2C_STAT_XRDY ), - &i2c_base->stat); -/*waiting for Transmit ready * condition */ - status =wait_for_status_mask (I2C_STAT_XRDY | -I2C_STAT_NACK ); - -if (status & (I2C_STAT_NACK |I2C_STAT_TIMEO )) { - i2c_error =1 ; -break ; - } -case 1 : -#if defined(CONFIG_OMAP243X ) || defined(CONFIG_OMAP34XX ) -/* send out MSB byte */ -writeb ((addr &0xFF ), &i2c_base->data); -#else -writew (((buffer[0 ] <<8 ) | (addr &0xFF )), - &i2c_base->data); -#endif - } - -/* Clearing XRDY event */ -writew ((status &I2C_STAT_XRDY ), &i2c_base->stat); - } - -/* waiting for Transmit ready condition */ - status =wait_for_status_mask (I2C_STAT_XRDY |I2C_STAT_NACK ); - -if (status & (I2C_STAT_NACK |I2C_STAT_TIMEO )) - i2c_error =1 ; - -if (!i2c_error) { -for (i = ((alen >1 ) ?0 :1 ); i < len; i++) { -if (status &I2C_STAT_XRDY ) { -#if defined(CONFIG_OMAP243X ) || defined(CONFIG_OMAP34XX ) -writeb ((buffer[i] &0xFF ), - &i2c_base->data); -#else -writew ((((buffer[i] <<8 ) | - buffer[i +1 ]) &0xFFFF ), - &i2c_base->data); - i++; -#endif - }else - i2c_error =1 ; -/* Clearing XRDY event */ -writew ((status &I2C_STAT_XRDY ), - &i2c_base->stat); -/* waiting for XRDY condition */ - status =wait_for_status_mask ( -I2C_STAT_XRDY | -I2C_STAT_ARDY | -I2C_STAT_NACK ); -if (status & (I2C_STAT_NACK | -I2C_STAT_TIMEO )) { - i2c_error =1 ; -break ; - } -if (status &I2C_STAT_ARDY ) -break ; - } - } +printf ("error waiting for i2c address ACK (status=0x%x)\n" , + status); + goto write_exit; } - status =wait_for_status_mask (I2C_STAT_ARDY |I2C_STAT_NACK | -I2C_STAT_AL ); - -if (status & (I2C_STAT_NACK |I2C_STAT_TIMEO )) +if (status &I2C_STAT_XRDY ) { +writeb (addr &0xFF , &i2c_base->data); +writew (I2C_STAT_XRDY , &i2c_base->stat); + }else { i2c_error =1 ; - -if (i2c_error) { -writew (0 , &i2c_base->con); -return 1 ; +printf ("i2c bus not ready for transmit (status=0x%x)\n" , + status); + goto write_exit; } -if (!i2c_error) { -int eout =200 ; +/* address phase is over, now write data */ +for (i =0 ; i < len; i++) { + status =wait_for_pin (); -writew (I2C_CON_EN , &i2c_base->con); -while ((status =readw (&i2c_base->stat)) || - (readw (&i2c_base->con) &I2C_CON_MST )) { -udelay (1000 ); -/* have to read to clear intrrupt */ -writew (0xFFFF , &i2c_base->stat); -if (--eout ==0 ) -/* better leave with error than hang */ -break ; +if (status ==0 || status &I2C_STAT_NACK ) { + i2c_error =1 ; +printf ("i2c error waiting for data ACK (status=0x%x)\n" , + status); + goto write_exit; + } + +if (status &I2C_STAT_XRDY ) { +writeb (buffer[i], &i2c_base->data); +writew (I2C_STAT_XRDY , &i2c_base->stat); + }else { + i2c_error =1 ; +printf ("i2c bus not ready for Tx (i=%d)\n" , i); + goto write_exit; } } +write_exit:flush_fifo ();writew (0xFFFF , &i2c_base->stat); -writew (0 , &i2c_base->cnt); -return 0 ; +return i2c_error; } -static u32 wait_for_bb (void ) +static void wait_for_bb (void ) {int timeout =I2C_TIMEOUT ; -u32 stat; +u16 stat; +writew (0xFFFF , &i2c_base->stat);/* clear current interrupts...*/ while ((stat =readw (&i2c_base->stat) &I2C_STAT_BB ) && timeout--) {writew (stat, &i2c_base->stat);udelay (1000 );
@@ -517,28 +394,30 @@ static u32 wait_for_bb(void)if (timeout <=0 ) {printf ("timed out in wait_for_bb: I2C_STAT=%x\n" ,readw (&i2c_base->stat)); - stat |=I2C_STAT_TIMEO ; }writew (0xFFFF , &i2c_base->stat);/* clear delayed stuff*/ -return stat; } -static u32 wait_for_status_mask (u16 mask) +static u16 wait_for_pin (void ) { -u32 status; +u16 status;int timeout =I2C_TIMEOUT ;do {udelay (1000 ); status =readw (&i2c_base->stat); - }while (!(status & mask) && timeout--); + }while (!(status & + (I2C_STAT_ROVR |I2C_STAT_XUDF |I2C_STAT_XRDY | +I2C_STAT_RRDY |I2C_STAT_ARDY |I2C_STAT_NACK | +I2C_STAT_AL )) && timeout--);if (timeout <=0 ) { -printf ("timed out in wait_for_status_mask: I2C_STAT=%x\n" , +printf ("timed out in wait_for_pin: I2C_STAT=%x\n" ,readw (&i2c_base->stat));writew (0xFFFF , &i2c_base->stat); - status |=I2C_STAT_TIMEO ; + status =0 ; } +return status; }
drivers/i2c/omap24xx_i2c.h +0 -2
@@ -60,9 +60,7 @@/* I2C Buffer Configuration Register (I2C_BUF): */ #define I2C_BUF_RDMA_EN (1 << 15)/* Receive DMA channel enable */ -#define I2C_RXFIFO_CLEAR (1 << 14)/* RX FIFO Clear */ #define I2C_BUF_XDMA_EN (1 << 7)/* Transmit DMA channel enable */ -#define I2C_TXFIFO_CLEAR (1 << 6)/* TX FIFO clear */ /* I2C Configuration Register (I2C_CON): */
Signature · 1 line
1.7.0.4
PATCH 2/2 Revert "ARM: I2C: I2C Multi byte address support"
Hello Tom,
Quoted 6 lines · tom.rini at gmail.com
From: Tom Rini <[email protected]>
This reverts commits
2faa76196af4b3e93bcb9e38ed9090cbd3b06db3as this has introduced some large problems on all other platforms and have more changes in them than the commit message implies.
Quoted 7 lines
Cc Heiko Schocher <[email protected]>Cc Patil, Rachna <[email protected]>Signed-off-by Tom Rini <[email protected]>--- drivers/i2c/omap24xx_i2c.c | 467 ++++++++++++++++---------------------------- drivers/i2c/omap24xx_i2c.h | 2 - 2 files changed, 173 insertions(+), 296 deletions(-)
Applied to u-boot-i2c.git.
Thanks!
bye,
Heiko
Signature · 2 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany