X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fi2c%2Ffsl_i2c.c;h=1c7265d897eea8f97fbd6254e3da4208ec7a3560;hb=412665b46134f93464c09405e02f08ac9c62526d;hp=4d5552bcd5356a790db0c868d46378ee38cb7c9c;hpb=99404202127346b9e91503bbd69deafa18c980c4;p=u-boot diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c index 4d5552bcd5..1c7265d897 100644 --- a/drivers/i2c/fsl_i2c.c +++ b/drivers/i2c/fsl_i2c.c @@ -214,40 +214,53 @@ static unsigned int set_i2c_bus_speed(const struct fsl_i2c *dev, return speed; } +static unsigned int get_i2c_clock(int bus) +{ + if (bus) + return gd->arch.i2c2_clk; /* I2C2 clock */ + else + return gd->arch.i2c1_clk; /* I2C1 clock */ +} + void i2c_init(int speed, int slaveadd) { - struct fsl_i2c *dev; + const struct fsl_i2c *dev; unsigned int temp; + int bus_num, i; #ifdef CONFIG_SYS_I2C_INIT_BOARD - /* call board specific i2c bus reset routine before accessing the */ - /* environment, which might be in a chip on that bus. For details */ - /* about this problem see doc/I2C_Edge_Conditions. */ + /* Call board specific i2c bus reset routine before accessing the + * environment, which might be in a chip on that bus. For details + * about this problem see doc/I2C_Edge_Conditions. + */ i2c_init_board(); #endif - dev = (struct fsl_i2c *) (CONFIG_SYS_IMMR + CONFIG_SYS_I2C_OFFSET); - - writeb(0, &dev->cr); /* stop I2C controller */ - udelay(5); /* let it shutdown in peace */ - temp = set_i2c_bus_speed(dev, gd->i2c1_clk, speed); - if (gd->flags & GD_FLG_RELOC) - i2c_bus_speed[0] = temp; - writeb(slaveadd << 1, &dev->adr); /* write slave address */ - writeb(0x0, &dev->sr); /* clear status register */ - writeb(I2C_CR_MEN, &dev->cr); /* start I2C controller */ - -#ifdef CONFIG_SYS_I2C2_OFFSET - dev = (struct fsl_i2c *) (CONFIG_SYS_IMMR + CONFIG_SYS_I2C2_OFFSET); - - writeb(0, &dev->cr); /* stop I2C controller */ - udelay(5); /* let it shutdown in peace */ - temp = set_i2c_bus_speed(dev, gd->i2c2_clk, speed); - if (gd->flags & GD_FLG_RELOC) - i2c_bus_speed[1] = temp; - writeb(slaveadd << 1, &dev->adr); /* write slave address */ - writeb(0x0, &dev->sr); /* clear status register */ - writeb(I2C_CR_MEN, &dev->cr); /* start I2C controller */ +#ifdef CONFIG_SYS_I2C2_OFFSET + bus_num = 2; +#else + bus_num = 1; +#endif + for (i = 0; i < bus_num; i++) { + dev = i2c_dev[i]; + + writeb(0, &dev->cr); /* stop I2C controller */ + udelay(5); /* let it shutdown in peace */ + temp = set_i2c_bus_speed(dev, get_i2c_clock(i), speed); + if (gd->flags & GD_FLG_RELOC) + i2c_bus_speed[i] = temp; + writeb(slaveadd << 1, &dev->adr);/* write slave address */ + writeb(0x0, &dev->sr); /* clear status register */ + writeb(I2C_CR_MEN, &dev->cr); /* start I2C controller */ + } + +#ifdef CONFIG_SYS_I2C_BOARD_LATE_INIT + /* Call board specific i2c bus reset routine AFTER the bus has been + * initialized. Use either this callpoint or i2c_init_board; + * which is called before i2c_init operations. + * For details about this problem see doc/I2C_Edge_Conditions. + */ + i2c_board_late_init(); #endif } @@ -353,9 +366,10 @@ __i2c_read(u8 *data, int length) writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_TXAK, &i2c_dev[i2c_bus_num]->cr); - /* Generate stop on last byte */ + /* Do not generate stop on last byte */ if (i == length - 1) - writeb(I2C_CR_MEN | I2C_CR_TXAK, &i2c_dev[i2c_bus_num]->cr); + writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_MTX, + &i2c_dev[i2c_bus_num]->cr); data[i] = readb(&i2c_dev[i2c_bus_num]->dr); } @@ -378,11 +392,11 @@ i2c_read(u8 dev, uint addr, int alen, u8 *data, int length) && i2c_write_addr(dev, I2C_READ_BIT, 1) != 0) i = __i2c_read(data, length); - if (length && i2c_wait4bus()) /* Wait until STOP */ - debug("i2c_read: wait4bus timed out\n"); - writeb(I2C_CR_MEN, &i2c_dev[i2c_bus_num]->cr); + if (i2c_wait4bus()) /* Wait until STOP */ + debug("i2c_read: wait4bus timed out\n"); + if (i == length) return 0; @@ -454,7 +468,8 @@ int i2c_set_bus_num(unsigned int bus) int i2c_set_bus_speed(unsigned int speed) { - unsigned int i2c_clk = (i2c_bus_num == 1) ? gd->i2c2_clk : gd->i2c1_clk; + unsigned int i2c_clk = (i2c_bus_num == 1) + ? gd->arch.i2c2_clk : gd->arch.i2c1_clk; writeb(0, &i2c_dev[i2c_bus_num]->cr); /* stop controller */ i2c_bus_speed[i2c_bus_num] =