X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fi2c%2Fomap24xx_i2c.c;h=4ae237aa8e74314f6344df6d4a28428cf5589030;hb=84d018268a8af1d9f271b398748652c5112e951a;hp=966ffc4bfff768859dc5afb9ddfbf4363ca4a218;hpb=9023ae305919d0aecb4a22726b9d08c6b08189d7;p=u-boot diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c index 966ffc4bff..4ae237aa8e 100644 --- a/drivers/i2c/omap24xx_i2c.c +++ b/drivers/i2c/omap24xx_i2c.c @@ -31,8 +31,8 @@ DECLARE_GLOBAL_DATA_PTR; #define I2C_TIMEOUT 1000 -static void wait_for_bb (void); -static u16 wait_for_pin (void); +static void wait_for_bb(void); +static u16 wait_for_pin(void); static void flush_fifo(void); static struct i2c *i2c_base = (struct i2c *)I2C_DEFAULT_BASE; @@ -40,7 +40,7 @@ static struct i2c *i2c_base = (struct i2c *)I2C_DEFAULT_BASE; static unsigned int bus_initialized[I2C_BUS_MAX]; static unsigned int current_bus; -void i2c_init (int speed, int slaveadd) +void i2c_init(int speed, int slaveadd) { int psc, fsscll, fssclh; int hsscll = 0, hssclh = 0; @@ -107,9 +107,9 @@ void i2c_init (int speed, int slaveadd) sclh = (unsigned int)fssclh; } - if (readw (&i2c_base->con) & I2C_CON_EN) { - writew (0, &i2c_base->con); - udelay (50000); + 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 */ @@ -130,35 +130,36 @@ void i2c_init (int speed, int slaveadd) writew(sclh, &i2c_base->sclh); /* own address */ - writew (slaveadd, &i2c_base->oa); - writew (I2C_CON_EN, &i2c_base->con); + writew(slaveadd, &i2c_base->oa); + writew(I2C_CON_EN, &i2c_base->con); /* have to enable intrrupts or OMAP i2c module doesn't work */ - writew (I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | + writew(I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | I2C_IE_NACK_IE | I2C_IE_AL_IE, &i2c_base->ie); - udelay (1000); + udelay(1000); flush_fifo(); - writew (0xFFFF, &i2c_base->stat); - writew (0, &i2c_base->cnt); + 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) +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 (); + wait_for_bb(); /* one byte only */ - writew (1, &i2c_base->cnt); + writew(1, &i2c_base->cnt); /* set slave address */ - writew (devaddr, &i2c_base->sa); + 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); + writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | + I2C_CON_TRX, &i2c_base->con); /* send register offset */ while (1) { @@ -196,7 +197,7 @@ static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value) } if (status & I2C_STAT_RRDY) { #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \ - defined(CONFIG_OMAP44XX) + defined(CONFIG_OMAP44XX) *value = readb(&i2c_base->data); #else *value = readw(&i2c_base->data); @@ -211,79 +212,8 @@ static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value) read_exit: flush_fifo(); - writew (0xFFFF, &i2c_base->stat); - writew (0, &i2c_base->cnt); - return i2c_error; -} - -static int i2c_write_byte (u8 devaddr, u8 regoffset, u8 value) -{ - int i2c_error = 0; - u16 status; - - /* wait until bus not busy */ - wait_for_bb (); - - /* two bytes */ - writew (2, &i2c_base->cnt); - /* set slave address */ - writew (devaddr, &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); - - while (1) { - status = wait_for_pin(); - if (status == 0 || status & I2C_STAT_NACK) { - i2c_error = 1; - goto write_exit; - } - if (status & I2C_STAT_XRDY) { -#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \ - defined(CONFIG_OMAP44XX) - /* send register offset */ - writeb(regoffset, &i2c_base->data); - writew(I2C_STAT_XRDY, &i2c_base->stat); - - while (1) { - status = wait_for_pin(); - if (status == 0 || status & I2C_STAT_NACK) { - i2c_error = 1; - goto write_exit; - } - if (status & I2C_STAT_XRDY) { - /* send data */ - writeb(value, &i2c_base->data); - writew(I2C_STAT_XRDY, &i2c_base->stat); - } - if (status & I2C_STAT_ARDY) { - writew(I2C_STAT_ARDY, &i2c_base->stat); - break; - } - } - break; -#else - /* send out two bytes */ - writew((value << 8) + regoffset, &i2c_base->data); - writew(I2C_STAT_XRDY, &i2c_base->stat); -#endif - } - if (status & I2C_STAT_ARDY) { - writew(I2C_STAT_ARDY, &i2c_base->stat); - break; - } - } - - wait_for_bb(); - - status = readw(&i2c_base->stat); - if (status & I2C_STAT_NACK) - i2c_error = 1; - -write_exit: - flush_fifo(); - writew (0xFFFF, &i2c_base->stat); - writew (0, &i2c_base->cnt); + writew(0xFFFF, &i2c_base->stat); + writew(0, &i2c_base->cnt); return i2c_error; } @@ -293,38 +223,37 @@ static void flush_fifo(void) /* note: if you try and read data when its not there or ready * you get a bus error */ - while(1){ + while (1) { stat = readw(&i2c_base->stat); - if(stat == I2C_STAT_RRDY){ + if (stat == I2C_STAT_RRDY) { #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \ - defined(CONFIG_OMAP44XX) + defined(CONFIG_OMAP44XX) readb(&i2c_base->data); #else readw(&i2c_base->data); #endif - writew(I2C_STAT_RRDY,&i2c_base->stat); + writew(I2C_STAT_RRDY, &i2c_base->stat); udelay(1000); - }else + } else break; } } -int i2c_probe (uchar chip) +int i2c_probe(uchar chip) { u16 status; int res = 1; /* default = fail */ - if (chip == readw (&i2c_base->oa)) { + if (chip == readw(&i2c_base->oa)) return res; - } /* wait until bus not busy */ - wait_for_bb (); + wait_for_bb(); /* try to write one byte */ - writew (1, &i2c_base->cnt); + writew(1, &i2c_base->cnt); /* set slave address */ - writew (chip, &i2c_base->sa); + 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); @@ -339,29 +268,30 @@ int i2c_probe (uchar chip) writew(0, &i2c_base->con); flush_fifo(); - writew (0, &i2c_base->cnt); /* don't allow any more data in...we don't want it.*/ + /* don't allow any more data in... we don't want it. */ + writew(0, &i2c_base->cnt); writew(0xFFFF, &i2c_base->stat); return res; } -int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len) +int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) { int i; if (alen > 1) { - printf ("I2C read: addr len %d not supported\n", alen); + printf("I2C read: addr len %d not supported\n", alen); return 1; } if (addr + len > 256) { - printf ("I2C read: address out of range\n"); + printf("I2C read: address out of range\n"); return 1; } for (i = 0; i < len; i++) { - if (i2c_read_byte (chip, addr + i, &buffer[i])) { - printf ("I2C read: I/O error\n"); - i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); + if (i2c_read_byte(chip, addr + i, &buffer[i])) { + printf("I2C read: I/O error\n"); + i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); return 1; } } @@ -369,65 +299,116 @@ int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len) return 0; } -int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len) +int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) { int i; + u16 status; + int i2c_error = 0; if (alen > 1) { - printf ("I2C read: addr len %d not supported\n", alen); + printf("I2C write: addr len %d not supported\n", alen); return 1; } if (addr + len > 256) { - printf ("I2C read: address out of range\n"); + printf("I2C write: address 0x%x + 0x%x out of range\n", + addr, len); return 1; } + /* wait until bus not busy */ + wait_for_bb(); + + /* 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); + + /* 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++) { - if (i2c_write_byte (chip, addr + i, buffer[i])) { - printf ("I2C read: I/O error\n"); - i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); - return 1; + status = wait_for_pin(); + + 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; } } - return 0; +write_exit: + flush_fifo(); + writew(0xFFFF, &i2c_base->stat); + return i2c_error; } -static void wait_for_bb (void) +static void wait_for_bb(void) { int timeout = I2C_TIMEOUT; 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); + while ((stat = readw(&i2c_base->stat) & I2C_STAT_BB) && timeout--) { + writew(stat, &i2c_base->stat); udelay(1000); } if (timeout <= 0) { - printf ("timed out in wait_for_bb: I2C_STAT=%x\n", - readw (&i2c_base->stat)); + printf("timed out in wait_for_bb: I2C_STAT=%x\n", + readw(&i2c_base->stat)); } writew(0xFFFF, &i2c_base->stat); /* clear delayed stuff*/ } -static u16 wait_for_pin (void) +static u16 wait_for_pin(void) { u16 status; int timeout = I2C_TIMEOUT; do { - udelay (1000); - status = readw (&i2c_base->stat); - } while ( !(status & + udelay(1000); + status = readw(&i2c_base->stat); + } 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_pin: I2C_STAT=%x\n", - readw (&i2c_base->stat)); + printf("timed out in wait_for_pin: I2C_STAT=%x\n", + readw(&i2c_base->stat)); writew(0xFFFF, &i2c_base->stat); status = 0; } @@ -442,7 +423,7 @@ int i2c_set_bus_num(unsigned int bus) return -1; } -#if I2C_BUS_MAX==3 +#if I2C_BUS_MAX == 3 if (bus == 2) i2c_base = (struct i2c *)I2C_BASE3; else @@ -454,7 +435,7 @@ int i2c_set_bus_num(unsigned int bus) current_bus = bus; - if(!bus_initialized[current_bus]) + if (!bus_initialized[current_bus]) i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); return 0;