New I2C driver that fixes read-related issues with some types
of I2C chips. The i2c_read function now performs bulk read of
the requested number of bytes in a single transaction and
completes much faster. Whether to use Stop-Start or Repeated
Start between the address and data phases is configurable
(e.g. in the board config header).
Signed-off-by: Lubomir Popov
---
The main feature of this new driver is that now i2c_read operates
correctly with chips that have addressable registers wider than 8 bits
(such as TI temperature sensors), or that have multiple non-addressable
registers that have to be retrieved in a bulk transaction (such as TI
clock distributors). The old driver (omap24xx_i2c.c) performs separate
read transactions for every byte requested and returns invalid data in
these cases (except possibly the first byte; this invalid data is in
fact presented by the chips, so the driver does not know that it is
invalid).
The new driver performs a standard bulk read transaction (with S-P by
default, or with Sr if configured so) and works correctly with all types
of I2C devices.
The i2c_write and i2c_probe functions have also been modified.
I have tested the driver on OMAP4430, 4460, 4470 and 5430 and found no
issues so far. Nevertheless, folks, any additional testing is strongly
encouraged; the driver should also work on OMAP3 and derivatives, but I
didn't have this opportunity, so any feedback is welcome.
drivers/i2c/omap4x5x_i2c.c | 562
drivers/i2c/omap4x5x_i2c.h | 176 ++
2 files changed, 738 insertions(+)
create mode 100644 drivers/i2c/omap4x5x_i2c.c
create mode 100644 drivers/i2c/omap4x5x_i2c.h
diff --git a/drivers/i2c/omap4x5x_i2c.c b/drivers/i2c/omap4x5x_i2c.c
new file mode 100644
index 000..44d7813
--- /dev/null
+++ b/drivers/i2c/omap4x5x_i2c.c
@@ -0,0 +1,562 @@
+/*
+ * Basic I2C functions
+ *
+ * Copyright (c) 2004 Texas Instruments
+ *
+ * This package is free software; you can redistribute it and/or
+ * modify it under the terms of the license found in the file
+ * named COPYING that should have accompanied this file.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author: Jian Zhang jzh...@ti.com, Texas Instruments
+ *
+ * Copyright (c) 2003 Wolfgang Denk, w...@denx.de
+ * Rewritten to fit into the current U-Boot framework
+ *
+ * Adapted for OMAP2420 I2C, r-woodru...@ti.com
+ *
+ * Copyright (c) 2013 Lubomir Popov , MM Solutions
+ * Based on omap24xx_i2c.c and modified for OMAP4/5:
+ * - i2c_read now operates correctly, with bulk transfer;
+ * - i2c_probe performs write access vs read;
+ * - Driver tries to identify I2C pads not properly padconf'd;
+ * - Should work with OMAP3/AM33xx as well, but is not tested.
+ */
+
+#include
+
+#include
+#include
+
+#include "omap4x5x_i2c.h"
+
+#undef I2C_DBG
+
+#ifdef I2C_DBG
+#define I2C_PRINTF(fmt, args...) printf(fmt , ##args)
+#else
+#define I2C_PRINTF(fmt, args...)
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define I2C_TIMEOUT1000
+
+static int wait_for_bus_free(void);
+static u16 wait_for_event(void);
+static void flush_fifo(void);
+
+/*
+ * 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)
+{
+ int psc, fsscll, fssclh;
+ int hsscll = 0, hssclh = 0;
+ u32 scll, sclh;
+ int timeout = I2C_TIMEOUT;
+
+ /* Only handle standard, fast and high speeds */
+ if ((speed != OMAP_I2C_STANDARD) &&
+ (speed != OMAP_I2C_FAST_MODE) &&
+ (speed != OMAP_I2C_HIGH_SPEED)) {
+ printf("Error : I2C unsupported speed %d\n", speed);
+ return;
+ }
+
+ psc = I2C_IP_CLK / I2C_INTERNAL_SAMPLING_CLK;
+ psc -= 1;
+ if (psc < I2C_PSC_MIN) {
+ printf("Error : I2C unsupported prescalar %d\n", psc);
+ return;
+ }
+
+ if (speed == OMAP_I2C_HIGH_SPEED) {
+ /* High speed */
+
+ /* For first phase of HS mode */
+ fsscll = fssclh = I2C_INTERNAL_SAMPLING_CLK /
+ (2 * OMAP_I2C_FAST_MODE);
+
+ fsscll -= I2C_HIGHSPEED_PHASE_ONE_SCLL_TRIM;
+ fssclh -= I2C_HIGHSPEED_PHASE_ONE_SCLH_TRIM;
+ if (((fsscll < 0) || (fssclh < 0)) ||
+ ((fsscll > 255) || (fssclh > 255))) {
+