summaryrefslogtreecommitdiff
path: root/drivers/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/at91_i2c.c18
-rw-r--r--drivers/i2c/designware_i2c.c23
2 files changed, 18 insertions, 23 deletions
diff --git a/drivers/i2c/at91_i2c.c b/drivers/i2c/at91_i2c.c
index d71f75c5faa..4bc54eea596 100644
--- a/drivers/i2c/at91_i2c.c
+++ b/drivers/i2c/at91_i2c.c
@@ -176,37 +176,21 @@ static void at91_calc_i2c_clock(struct udevice *dev, int i2c_clk)
static int at91_i2c_enable_clk(struct udevice *dev)
{
struct at91_i2c_bus *bus = dev_get_priv(dev);
- struct udevice *dev_clk;
struct clk clk;
ulong clk_rate;
- int periph;
int ret;
ret = clk_get_by_index(dev, 0, &clk);
if (ret)
return -EINVAL;
- periph = fdtdec_get_uint(gd->fdt_blob, clk.dev->of_offset, "reg", -1);
- if (periph < 0)
- return -EINVAL;
-
- dev_clk = dev_get_parent(clk.dev);
- ret = clk_request(dev_clk, &clk);
- if (ret)
- return ret;
-
- clk.id = periph;
ret = clk_enable(&clk);
if (ret)
return ret;
- ret = clk_get_by_index(dev_clk, 0, &clk);
- if (ret)
- return ret;
-
clk_rate = clk_get_rate(&clk);
if (!clk_rate)
- return -ENODEV;
+ return -EINVAL;
bus->bus_clk_rate = clk_rate;
diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index e60fd0a4190..c68ff6420b2 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -249,6 +249,7 @@ static int __dw_i2c_read(struct i2c_regs *i2c_base, u8 dev, uint addr,
int alen, u8 *buffer, int len)
{
unsigned long start_time_rx;
+ unsigned int active = 0;
#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
/*
@@ -274,18 +275,28 @@ static int __dw_i2c_read(struct i2c_regs *i2c_base, u8 dev, uint addr,
start_time_rx = get_timer(0);
while (len) {
- if (len == 1)
- writel(IC_CMD | IC_STOP, &i2c_base->ic_cmd_data);
- else
- writel(IC_CMD, &i2c_base->ic_cmd_data);
+ if (!active) {
+ /*
+ * Avoid writing to ic_cmd_data multiple times
+ * in case this loop spins too quickly and the
+ * ic_status RFNE bit isn't set after the first
+ * write. Subsequent writes to ic_cmd_data can
+ * trigger spurious i2c transfer.
+ */
+ if (len == 1)
+ writel(IC_CMD | IC_STOP, &i2c_base->ic_cmd_data);
+ else
+ writel(IC_CMD, &i2c_base->ic_cmd_data);
+ active = 1;
+ }
if (readl(&i2c_base->ic_status) & IC_STATUS_RFNE) {
*buffer++ = (uchar)readl(&i2c_base->ic_cmd_data);
len--;
start_time_rx = get_timer(0);
-
+ active = 0;
} else if (get_timer(start_time_rx) > I2C_BYTE_TO) {
- return 1;
+ return 1;
}
}