X-Git-Url: https://git.kernelconcepts.de/?p=karo-tx-uboot.git;a=blobdiff_plain;f=drivers%2Fi2c%2Fomap24xx_i2c.c;h=81193b0e6eb7b69de254c7187d00aedc6e623fdf;hp=4ae237aa8e74314f6344df6d4a28428cf5589030;hb=402d17fc4c406fe49a7b2d94aee640f389a68738;hpb=89677b27d3393d34fe5d4caad868a9dbb32edd87 diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c index 4ae237aa8e..81193b0e6e 100644 --- a/drivers/i2c/omap24xx_i2c.c +++ b/drivers/i2c/omap24xx_i2c.c @@ -35,10 +35,15 @@ 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; - -static unsigned int bus_initialized[I2C_BUS_MAX]; -static unsigned int current_bus; +/* + * For SPL boot some boards need i2c before SDRAM is initialised so force + * variables to live in SRAM + */ +static struct i2c __attribute__((section (".data"))) *i2c_base = + (struct i2c *)I2C_DEFAULT_BASE; +static unsigned int __attribute__((section (".data"))) bus_initialized[I2C_BUS_MAX] = + { [0 ... (I2C_BUS_MAX-1)] = 0 }; +static unsigned int __attribute__((section (".data"))) current_bus = 0; void i2c_init(int speed, int slaveadd) { @@ -73,7 +78,7 @@ void i2c_init(int speed, int slaveadd) fssclh -= I2C_HIGHSPEED_PHASE_ONE_SCLH_TRIM; if (((fsscll < 0) || (fssclh < 0)) || ((fsscll > 255) || (fssclh > 255))) { - printf("Error : I2C initializing first phase clock\n"); + puts("Error : I2C initializing first phase clock\n"); return; } @@ -84,7 +89,7 @@ void i2c_init(int speed, int slaveadd) hssclh -= I2C_HIGHSPEED_PHASE_TWO_SCLH_TRIM; if (((fsscll < 0) || (fssclh < 0)) || ((fsscll > 255) || (fssclh > 255))) { - printf("Error : I2C initializing second phase clock\n"); + puts("Error : I2C initializing second phase clock\n"); return; } @@ -99,7 +104,7 @@ void i2c_init(int speed, int slaveadd) fssclh -= I2C_FASTSPEED_SCLH_TRIM; if (((fsscll < 0) || (fssclh < 0)) || ((fsscll > 255) || (fssclh > 255))) { - printf("Error : I2C initializing clock\n"); + puts("Error : I2C initializing clock\n"); return; } @@ -118,7 +123,7 @@ void i2c_init(int speed, int slaveadd) writew(I2C_CON_EN, &i2c_base->con); while (!(readw(&i2c_base->syss) & I2C_SYSS_RDONE) && timeout--) { if (timeout <= 0) { - printf("ERROR: Timeout in soft-reset\n"); + puts("ERROR: Timeout in soft-reset\n"); return; } udelay(1000); @@ -197,7 +202,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) || defined(CONFIG_AM33XX) *value = readb(&i2c_base->data); #else *value = readw(&i2c_base->data); @@ -227,7 +232,7 @@ static void flush_fifo(void) stat = readw(&i2c_base->stat); if (stat == I2C_STAT_RRDY) { #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \ - defined(CONFIG_OMAP44XX) + defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) readb(&i2c_base->data); #else readw(&i2c_base->data); @@ -250,23 +255,43 @@ int i2c_probe(uchar chip) /* wait until bus not busy */ wait_for_bb(); - /* try to write one byte */ + /* try to read 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_TRX | - I2C_CON_STP, &i2c_base->con); - - status = wait_for_pin(); - - /* check for ACK (!NAK) */ - if (!(status & I2C_STAT_NACK)) - res = 0; + writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, &i2c_base->con); - /* abort transfer (force idle state) */ - writew(0, &i2c_base->con); + while (1) { + status = wait_for_pin(); + if (status == 0 || status & I2C_STAT_AL) { + res = 1; + goto probe_exit; + } + if (status & I2C_STAT_NACK) { + res = 1; + writew(0xff, &i2c_base->stat); + writew (readw (&i2c_base->con) | I2C_CON_STP, &i2c_base->con); + wait_for_bb (); + break; + } + if (status & I2C_STAT_ARDY) { + writew(I2C_STAT_ARDY, &i2c_base->stat); + break; + } + if (status & I2C_STAT_RRDY) { + res = 0; +#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \ + defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) + readb(&i2c_base->data); +#else + readw(&i2c_base->data); +#endif + writew(I2C_STAT_RRDY, &i2c_base->stat); + } + } +probe_exit: flush_fifo(); /* don't allow any more data in... we don't want it. */ writew(0, &i2c_base->cnt); @@ -284,13 +309,13 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) } if (addr + len > 256) { - printf("I2C read: address out of range\n"); + 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])) { - printf("I2C read: I/O error\n"); + puts("I2C read: I/O error\n"); i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); return 1; }