]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
designware_i2c: Added s/w generation of stop bit
authorArmando Visconti <armando.visconti@st.com>
Thu, 6 Dec 2012 00:04:16 +0000 (00:04 +0000)
committerTom Rini <trini@ti.com>
Tue, 11 Dec 2012 20:17:32 +0000 (13:17 -0700)
In the newer versions of designware i2c IP there is the possibility
of configuring it with IC_EMPTYFIFO_HOLD_MASTER_EN=1, which basically
requires the s/w to generate the stop bit condition directly, as
the h/w will not automatically generate it when TX_FIFO is empty.

To avoid generation of an extra 0x0 byte sent as data, the
IC_STOP command must be sent along with the last IC_CMD.

This patch always writes bit[9] of ic_data_cmd even in the
older versions, assuming that it is a noop there.

Signed-off-by: Armando Visconti <armando.visconti@st.com>
drivers/i2c/designware_i2c.c
drivers/i2c/designware_i2c.h

index 4e4bfd4f57d952eb93f6f664db6833b58a046517..eab3131025febe54a96f03c6a3f4572738284b98 100644 (file)
@@ -283,7 +283,10 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
 
        start_time_rx = get_timer(0);
        while (len) {
-               writel(IC_CMD, &i2c_regs_p->ic_cmd_data);
+               if (len == 1)
+                       writel(IC_CMD | IC_STOP, &i2c_regs_p->ic_cmd_data);
+               else
+                       writel(IC_CMD, &i2c_regs_p->ic_cmd_data);
 
                if (readl(&i2c_regs_p->ic_status) & IC_STATUS_RFNE) {
                        *buffer++ = (uchar)readl(&i2c_regs_p->ic_cmd_data);
@@ -322,9 +325,11 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
        start_time_tx = get_timer(0);
        while (len) {
                if (readl(&i2c_regs_p->ic_status) & IC_STATUS_TFNF) {
-                       writel(*buffer, &i2c_regs_p->ic_cmd_data);
+                       if (--len == 0)
+                               writel(*buffer | IC_STOP, &i2c_regs_p->ic_cmd_data);
+                       else
+                               writel(*buffer, &i2c_regs_p->ic_cmd_data);
                        buffer++;
-                       len--;
                        start_time_tx = get_timer(0);
 
                } else if (get_timer(start_time_tx) > (nb * I2C_BYTE_TO)) {
index 03b520ed43a0a48def984d0a98db0e89c1c71c29..e004152ac34b200b69faeb4fbb2f48c718c6f9b0 100644 (file)
@@ -95,6 +95,7 @@ struct i2c_regs {
 
 /* i2c data buffer and command register definitions */
 #define IC_CMD                 0x0100
+#define IC_STOP                        0x0200
 
 /* i2c interrupt status register definitions */
 #define IC_GEN_CALL            0x0800