summaryrefslogtreecommitdiff
path: root/drivers/i2c
diff options
context:
space:
mode:
authorAlbert ARIBAUD <albert.u.boot@aribaud.net>2014-05-09 10:47:05 +0200
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>2014-05-09 11:50:14 +0200
commitd2a3e911390f9fc4d8c0ee4b3c7fc75f4fd3fd19 (patch)
treed71aae6d706d1f3b01da5f944e247abe308feea0 /drivers/i2c
parent7904b70885f3c589c239f6ac978f299a6744557f (diff)
parent173d294b94cfec10063a5be40934d6d8fb7981ce (diff)
downloadu-boot-imx-d2a3e911390f9fc4d8c0ee4b3c7fc75f4fd3fd19.zip
u-boot-imx-d2a3e911390f9fc4d8c0ee4b3c7fc75f4fd3fd19.tar.gz
u-boot-imx-d2a3e911390f9fc4d8c0ee4b3c7fc75f4fd3fd19.tar.bz2
Merge branch 'u-boot/master'
Conflicts: drivers/net/Makefile (trivial merge)
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/fsl_i2c.c41
-rw-r--r--drivers/i2c/mxc_i2c.c18
2 files changed, 42 insertions, 17 deletions
diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c
index 291ad94..aa159f8 100644
--- a/drivers/i2c/fsl_i2c.c
+++ b/drivers/i2c/fsl_i2c.c
@@ -423,18 +423,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);
diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c
index 595019b..48468d7 100644
--- a/drivers/i2c/mxc_i2c.c
+++ b/drivers/i2c/mxc_i2c.c
@@ -22,6 +22,8 @@
#include <i2c.h>
#include <watchdog.h>
+DECLARE_GLOBAL_DATA_PTR;
+
#ifdef I2C_QUIRK_REG
struct mxc_i2c_regs {
uint8_t iadr;
@@ -411,12 +413,6 @@ struct sram_data {
struct i2c_parms i2c_data[3];
};
-/*
- * For SPL boot some boards need i2c before SDRAM is initialized so force
- * variables to live in SRAM
- */
-static struct sram_data __attribute__((section(".data"))) srdata;
-
static void * const i2c_bases[] = {
#if defined(CONFIG_MX25)
(void *)IMX_I2C_BASE,
@@ -445,9 +441,10 @@ void *i2c_get_base(struct i2c_adapter *adap)
static struct i2c_parms *i2c_get_parms(void *base)
{
+ struct sram_data *srdata = (void *)gd->srdata;
int i = 0;
- struct i2c_parms *p = srdata.i2c_data;
- while (i < ARRAY_SIZE(srdata.i2c_data)) {
+ struct i2c_parms *p = srdata->i2c_data;
+ while (i < ARRAY_SIZE(srdata->i2c_data)) {
if (p->base == base)
return p;
p++;
@@ -490,8 +487,9 @@ static int mxc_i2c_probe(struct i2c_adapter *adap, uint8_t chip)
void bus_i2c_init(void *base, int speed, int unused,
int (*idle_bus_fn)(void *p), void *idle_bus_data)
{
+ struct sram_data *srdata = (void *)gd->srdata;
int i = 0;
- struct i2c_parms *p = srdata.i2c_data;
+ struct i2c_parms *p = srdata->i2c_data;
if (!base)
return;
for (;;) {
@@ -505,7 +503,7 @@ void bus_i2c_init(void *base, int speed, int unused,
}
p++;
i++;
- if (i >= ARRAY_SIZE(srdata.i2c_data))
+ if (i >= ARRAY_SIZE(srdata->i2c_data))
return;
}
bus_i2c_set_bus_speed(base, speed);