X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fi2c%2Ffsl_i2c.c;h=811033b0b83757815208dc88c2ab7b9ce165ad90;hb=f2c8d7f591e28d3437155c7a6eae8c8d9e3fe552;hp=291ad946dba19a8b358b4be6fe3c12be018d73a1;hpb=19d829fa60fc4e6df514a046142faaaf9fc8185d;p=u-boot diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c index 291ad946db..811033b0b8 100644 --- a/drivers/i2c/fsl_i2c.c +++ b/drivers/i2c/fsl_i2c.c @@ -46,10 +46,16 @@ DECLARE_GLOBAL_DATA_PTR; -static const struct fsl_i2c *i2c_dev[2] = { +static const struct fsl_i2c *i2c_dev[4] = { (struct fsl_i2c *)(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_I2C_OFFSET), #ifdef CONFIG_SYS_FSL_I2C2_OFFSET - (struct fsl_i2c *)(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_I2C2_OFFSET) + (struct fsl_i2c *)(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_I2C2_OFFSET), +#endif +#ifdef CONFIG_SYS_FSL_I2C3_OFFSET + (struct fsl_i2c *)(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_I2C3_OFFSET), +#endif +#ifdef CONFIG_SYS_FSL_I2C4_OFFSET + (struct fsl_i2c *)(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_I2C4_OFFSET) #endif }; @@ -423,18 +429,45 @@ fsl_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr, int alen, u8 *data, struct fsl_i2c *device = (struct fsl_i2c *)i2c_dev[adap->hwadapnr]; int i = -1; /* signal error */ u8 *a = (u8*)&addr; + int len = alen * -1; if (i2c_wait4bus(adap) < 0) return -1; - if ((!length || alen > 0) - && i2c_write_addr(adap, dev, I2C_WRITE_BIT, 0) != 0 - && __i2c_write(adap, &a[4 - alen], alen) == alen) - i = 0; /* No error so far */ + /* To handle the need of I2C devices that require to write few bytes + * (more than 4 bytes of address as in the case of else part) + * of data before reading, Negative equivalent of length(bytes to write) + * is passed, but used the +ve part of len for writing data + */ + if (alen < 0) { + /* Generate a START and send the Address and + * the Tx Bytes to the slave. + * "START: Address: Write bytes data[len]" + * IF part supports writing any number of bytes in contrast + * to the else part, which supports writing address offset + * of upto 4 bytes only. + * bytes that need to be written are passed in + * "data", which will eventually keep the data READ, + * after writing the len bytes out of it + */ + if (i2c_write_addr(adap, dev, I2C_WRITE_BIT, 0) != 0) + i = __i2c_write(adap, data, len); + + if (i != len) + return -1; - if (length && - i2c_write_addr(adap, dev, I2C_READ_BIT, alen ? 1 : 0) != 0) - i = __i2c_read(adap, data, length); + if (length && i2c_write_addr(adap, dev, I2C_READ_BIT, 1) != 0) + i = __i2c_read(adap, data, length); + } else { + if ((!length || alen > 0) && + i2c_write_addr(adap, dev, I2C_WRITE_BIT, 0) != 0 && + __i2c_write(adap, &a[4 - alen], alen) == alen) + i = 0; /* No error so far */ + + if (length && + i2c_write_addr(adap, dev, I2C_READ_BIT, alen ? 1 : 0) != 0) + i = __i2c_read(adap, data, length); + } writeb(I2C_CR_MEN, &device->cr); @@ -512,3 +545,15 @@ U_BOOT_I2C_ADAP_COMPLETE(fsl_1, fsl_i2c_init, fsl_i2c_probe, fsl_i2c_read, CONFIG_SYS_FSL_I2C2_SPEED, CONFIG_SYS_FSL_I2C2_SLAVE, 1) #endif +#ifdef CONFIG_SYS_FSL_I2C3_OFFSET +U_BOOT_I2C_ADAP_COMPLETE(fsl_2, fsl_i2c_init, fsl_i2c_probe, fsl_i2c_read, + fsl_i2c_write, fsl_i2c_set_bus_speed, + CONFIG_SYS_FSL_I2C3_SPEED, CONFIG_SYS_FSL_I2C3_SLAVE, + 2) +#endif +#ifdef CONFIG_SYS_FSL_I2C4_OFFSET +U_BOOT_I2C_ADAP_COMPLETE(fsl_3, fsl_i2c_init, fsl_i2c_probe, fsl_i2c_read, + fsl_i2c_write, fsl_i2c_set_bus_speed, + CONFIG_SYS_FSL_I2C4_SPEED, CONFIG_SYS_FSL_I2C4_SLAVE, + 3) +#endif