rk30: i2c: update i2c drivers for touch screen
authorkfx <kfx@rock-chips.com>
Sat, 24 Mar 2012 10:06:46 +0000 (18:06 +0800)
committerkfx <kfx@rock-chips.com>
Sat, 24 Mar 2012 10:06:46 +0000 (18:06 +0800)
drivers/i2c/busses/i2c-rk30-adapter.c
drivers/i2c/busses/i2c-rk30.h
drivers/i2c/i2c-core.c

index c0e773cb827ef27a610a2a6f9fee3ac693f3b5bd..ffb053e3067ddad539a3031a569f8242155bd0b5 100755 (executable)
 #include "i2c-rk30.h"
 
 /* Control register */
-#define I2C_CON         0X000
+#define I2C_CON                 0x000
+#define I2C_CON_EN              (1 << 0)
+#define I2C_CON_MOD(mod)        ((mod) << 1)
+#define I2C_CON_MASK            (3 << 1)
 enum{
-    I2C_EN_BIT  = 0,
-    I2C_MOD_BIT = 1,
-    I2C_START_BIT = 3,
-    I2C_STOP_BIT = 4,
-    I2C_LAST_ACK_BIT = 5,
-    I2C_ACT2ACK_BIT = 6,
+    I2C_CON_MOD_TX = 0,
+    I2C_CON_MOD_TRX,
+    I2C_CON_MOD_RX,
+    I2C_CON_MOD_RRX,
 };
-//send ACK to slave when the last byte received in RX only mode
-#define LAST_SEND_ACK   0
-//send NAK to slave when the last byte received in RX only mode
-#define LAST_SEND_NAK   1
-#define LAST_SEND_TYPE  LAST_SEND_ACK //LAST_SEND_NAK
+#define I2C_CON_START           (1 << 3)
+#define I2C_CON_STOP            (1 << 4)
+#define I2C_CON_LASTACK         (1 << 5)
+#define I2C_CON_ACTACK          (1 << 6)
 
-#define I2C_MOD_MASK    (3 << I2C_MOD_BIT)
-enum{
-    I2C_MOD_TX = 0,
-    I2C_MOD_TRX,
-    I2C_MOD_RX,
-    I2C_MOD_RRX,
-};
 /* Clock dividor register */
-#define I2C_CLKDIV      0x004
+#define I2C_CLKDIV              0x004
 #define I2C_CLKDIV_VAL(divl, divh) (((divl) & 0xffff) | (((divh) << 16) & 0xffff0000))    
+
 /* the slave address accessed  for master rx mode */
-#define I2C_MRXADDR     0x008
-#define I2C_MRXADDR_LOW     (1 << 24)
-#define I2C_MRXADDR_MID     (1 << 25)
-#define I2C_MRXADDR_HIGH     (1 << 26)
+#define I2C_MRXADDR             0x008
+#define I2C_MRXADDR_LOW         (1 << 24)
+#define I2C_MRXADDR_MID         (1 << 25)
+#define I2C_MRXADDR_HIGH        (1 << 26)
+
 /* the slave register address accessed  for master rx mode */
-#define I2C_MRXRADDR    0x00c
-#define I2C_MRXRADDR_LOW     (1 << 24)
-#define I2C_MRXRADDR_MID     (1 << 25)
-#define I2C_MRXRADDR_HIGH     (1 << 26)
+#define I2C_MRXRADDR            0x00c
+#define I2C_MRXRADDR_LOW        (1 << 24)
+#define I2C_MRXRADDR_MID        (1 << 25)
+#define I2C_MRXRADDR_HIGH       (1 << 26)
+
 /* master tx count */
-#define I2C_MTXCNT      0x010
+#define I2C_MTXCNT              0x010
+
 /* master rx count */
-#define I2C_MRXCNT      0x014
+#define I2C_MRXCNT              0x014
+
 /* interrupt enable register */
-#define I2C_IEN         0x018
-#define I2C_BTFIEN  (1 << 0)
-#define I2C_BRFIEN  (1 << 1)
-#define I2C_MBTFIEN  (1 << 2)
-#define I2C_MBRFIEN  (1 << 3)
-#define I2C_STARTIEN  (1 << 4)
-#define I2C_STOPIEN  (1 << 5)
-#define I2C_NAKRCVIEN  (1 << 6)
-#define IRQ_MST_ENABLE (I2C_MBTFIEN | I2C_MBRFIEN | I2C_NAKRCVIEN | I2C_STARTIEN | I2C_STOPIEN)
-#define IRQ_ALL_DISABLE 0
+#define I2C_IEN                 0x018
+#define I2C_BTFIEN              (1 << 0)
+#define I2C_BRFIEN              (1 << 1)
+#define I2C_MBTFIEN             (1 << 2)
+#define I2C_MBRFIEN             (1 << 3)
+#define I2C_STARTIEN            (1 << 4)
+#define I2C_STOPIEN             (1 << 5)
+#define I2C_NAKRCVIEN           (1 << 6)
+#define IRQ_MST_ENABLE          (I2C_MBTFIEN | I2C_MBRFIEN | I2C_NAKRCVIEN | I2C_STARTIEN | I2C_STOPIEN)
+#define IRQ_ALL_DISABLE         0
+
 /* interrupt pending register */
-#define I2C_IPD         0x01c
-#define I2C_BTFIPD  (1 << 0)
-#define I2C_BRFIPD  (1 << 1)
-#define I2C_MBTFIPD  (1 << 2)
-#define I2C_MBRFIPD  (1 << 3)
-#define I2C_STARTIPD  (1 << 4)
-#define I2C_STOPIPD  (1 << 5)
-#define I2C_NAKRCVIPD  (1 << 6)
+#define I2C_IPD                 0x01c
+#define I2C_BTFIPD              (1 << 0)
+#define I2C_BRFIPD              (1 << 1)
+#define I2C_MBTFIPD             (1 << 2)
+#define I2C_MBRFIPD             (1 << 3)
+#define I2C_STARTIPD            (1 << 4)
+#define I2C_STOPIPD             (1 << 5)
+#define I2C_NAKRCVIPD           (1 << 6)
+#define I2C_IPD_ALL_CLEAN       0x7f
+
 /* finished count */
-#define I2C_FCNT        0x020
+#define I2C_FCNT                0x020
+
 /* I2C tx data register */
-#define I2C_TXDATA_BASE 0X100
+#define I2C_TXDATA_BASE         0X100
+
 /* I2C rx data register */
-#define I2C_RXDATA_BASE 0x200
+#define I2C_RXDATA_BASE         0x200
+
+
 static void rk30_show_regs(struct rk30_i2c *i2c)
 {
-    i2c_dbg(i2c->dev, "I2C_CON: 0x%08x\n", readl(i2c->regs + I2C_CON));
-    i2c_dbg(i2c->dev, "I2C_CLKDIV: 0x%08x\n", readl(i2c->regs + I2C_CLKDIV));
-    i2c_dbg(i2c->dev, "I2C_MRXADDR: 0x%08x\n", readl(i2c->regs + I2C_MRXADDR));
-    i2c_dbg(i2c->dev, "I2C_MRXRADDR: 0x%08x\n", readl(i2c->regs + I2C_MRXRADDR));
-    i2c_dbg(i2c->dev, "I2C_MTXCNT: 0x%08x\n", readl(i2c->regs + I2C_MTXCNT));
-    i2c_dbg(i2c->dev, "I2C_MRXCNT: 0x%08x\n", readl(i2c->regs + I2C_MRXCNT));
-    i2c_dbg(i2c->dev, "I2C_IEN: 0x%08x\n", readl(i2c->regs + I2C_IEN));
-    i2c_dbg(i2c->dev, "I2C_IPD: 0x%08x\n", readl(i2c->regs + I2C_IPD));
-    i2c_dbg(i2c->dev, "I2C_FCNT: 0x%08x\n", readl(i2c->regs + I2C_FCNT));
-    i2c_dbg(i2c->dev, "I2C_TXDATA0: 0x%08x\n", readl(i2c->regs + I2C_TXDATA_BASE + 0));
-    i2c_dbg(i2c->dev, "I2C_RXDATA0: 0x%08x\n", readl(i2c->regs + I2C_RXDATA_BASE + 0));
+        int i;
+        i2c_dbg(i2c->dev, "i2c->start = %d\n", i2c->state);
+        i2c_dbg(i2c->dev, "I2C_CON: 0x%08x\n", readl(i2c->regs + I2C_CON));
+        i2c_dbg(i2c->dev, "I2C_CLKDIV: 0x%08x\n", readl(i2c->regs + I2C_CLKDIV));
+        i2c_dbg(i2c->dev, "I2C_MRXADDR: 0x%08x\n", readl(i2c->regs + I2C_MRXADDR));
+        i2c_dbg(i2c->dev, "I2C_MRXRADDR: 0x%08x\n", readl(i2c->regs + I2C_MRXRADDR));
+        i2c_dbg(i2c->dev, "I2C_MTXCNT: 0x%08x\n", readl(i2c->regs + I2C_MTXCNT));
+        i2c_dbg(i2c->dev, "I2C_MRXCNT: 0x%08x\n", readl(i2c->regs + I2C_MRXCNT));
+        i2c_dbg(i2c->dev, "I2C_IEN: 0x%08x\n", readl(i2c->regs + I2C_IEN));
+        i2c_dbg(i2c->dev, "I2C_IPD: 0x%08x\n", readl(i2c->regs + I2C_IPD));
+        i2c_dbg(i2c->dev, "I2C_FCNT: 0x%08x\n", readl(i2c->regs + I2C_FCNT));
+        for( i = 0; i < 8; i ++) 
+                i2c_dbg(i2c->dev, "I2C_TXDATA%d: 0x%08x\n", i, readl(i2c->regs + I2C_TXDATA_BASE + i * 4));
+        for( i = 0; i < 8; i ++) 
+                i2c_dbg(i2c->dev, "I2C_RXDATA%d: 0x%08x\n", i, readl(i2c->regs + I2C_RXDATA_BASE + i * 4));
 }
-static inline void rk30_i2c_last_ack(struct rk30_i2c *i2c, int enable)
+static inline void rk30_i2c_enable(struct rk30_i2c *i2c, unsigned int lastnak)
 {
-    unsigned int p = readl(i2c->regs + I2C_CON);
-
-    p = rk30_set_bit(p, 0, I2C_START_BIT);
-    p = rk30_set_bit(p, 0, I2C_STOP_BIT);
-    writel(rk30_set_bit(p, enable, I2C_LAST_ACK_BIT), i2c->regs + I2C_CON);
+        unsigned int con = 0;
+
+        con |= I2C_CON_EN;
+        con |= I2C_CON_MOD(i2c->mode);
+        if(lastnak)
+                con |= I2C_CON_LASTACK;
+        con |= I2C_CON_START;
+        writel(con, i2c->regs + I2C_CON);
 }
-static inline void rk30_i2c_act2ack(struct rk30_i2c *i2c, int enable)
+static inline void rk30_i2c_disable(struct rk30_i2c *i2c)
 {
-    unsigned int p = readl(i2c->regs + I2C_CON);
-
-    p = rk30_set_bit(p, 0, I2C_START_BIT);
-    p = rk30_set_bit(p, 0, I2C_STOP_BIT);
-    writel(rk30_set_bit(p, enable, I2C_ACT2ACK_BIT), i2c->regs + I2C_CON);
+        writel( 0, i2c->regs + I2C_CON);
 }
-static inline void rk30_i2c_enable(struct rk30_i2c *i2c, int enable)
+
+static inline void rk30_i2c_clean_start(struct rk30_i2c *i2c)
 {
-    unsigned int p = readl(i2c->regs + I2C_CON);
+        unsigned int con = readl(i2c->regs + I2C_CON);
 
-    p = rk30_set_bit(p, 0, I2C_START_BIT);
-    p = rk30_set_bit(p, 0, I2C_STOP_BIT);
+        con &= ~I2C_CON_START;
+        writel(con, i2c->regs + I2C_CON);
+}
+static inline void rk30_i2c_send_start(struct rk30_i2c *i2c)
+{
+        unsigned int con = readl(i2c->regs + I2C_CON);
 
-    writel(rk30_set_bit(p, enable, I2C_EN_BIT), i2c->regs + I2C_CON);
+        con |= I2C_CON_START;
+        if(con & I2C_CON_STOP)
+                dev_warn(i2c->dev, "I2C_CON: stop bit is set\n");
+        
+        writel(con, i2c->regs + I2C_CON);
 }
-static inline void rk30_i2c_set_mode(struct rk30_i2c *i2c)
+static inline void rk30_i2c_send_stop(struct rk30_i2c *i2c)
 {
-    unsigned int p = readl(i2c->regs + I2C_CON);
-    
-    p = rk30_set_bit(p, 0, I2C_START_BIT);
-    p = rk30_set_bit(p, 0, I2C_STOP_BIT);
-    writel(rk30_set_bits(p, i2c->mode, I2C_MOD_BIT, I2C_MOD_MASK), i2c->regs + I2C_CON);
+        unsigned int con = readl(i2c->regs + I2C_CON);
+
+        con |= I2C_CON_STOP;
+        if(con & I2C_CON_START)
+                dev_warn(i2c->dev, "I2C_CON: start bit is set\n");
+        
+        writel(con, i2c->regs + I2C_CON);
 }
-static inline void rk30_i2c_disable_irq(struct rk30_i2c *i2c)
+static inline void rk30_i2c_clean_stop(struct rk30_i2c *i2c)
 {
-    writel(IRQ_ALL_DISABLE, i2c->regs + I2C_IEN);
+        unsigned int con = readl(i2c->regs + I2C_CON);
+
+        con &= ~I2C_CON_STOP;
+        writel(con, i2c->regs + I2C_CON);
 }
 
-static inline void rk30_i2c_enable_irq(struct rk30_i2c *i2c)
+static inline void rk30_i2c_disable_irq(struct rk30_i2c *i2c)
 {
-    writel(IRQ_MST_ENABLE, i2c->regs + I2C_IEN);
+        writel(IRQ_ALL_DISABLE, i2c->regs + I2C_IEN);
 }
 
-static inline void rk30_i2c_send_start(struct rk30_i2c *i2c)
+static inline void rk30_i2c_enable_irq(struct rk30_i2c *i2c)
 {
-    unsigned int p = readl(i2c->regs + I2C_CON);
-    
-    p = rk30_set_bit(p, 1, I2C_START_BIT);
-    p = rk30_set_bit(p, 0, I2C_STOP_BIT);
-    writel(p, i2c->regs + I2C_CON);
+        writel(IRQ_MST_ENABLE, i2c->regs + I2C_IEN);
 }
-static inline void rk30_i2c_send_stop(struct rk30_i2c *i2c)
-{
-    unsigned int p = readl(i2c->regs + I2C_CON);
-
-    p = rk30_set_bit(p, 0, I2C_START_BIT);
-    p = rk30_set_bit(p, 1, I2C_STOP_BIT);
-    writel(p, i2c->regs + I2C_CON);
 
-}
 /* SCL Divisor = 8 * (CLKDIVL + CLKDIVH)
  * SCL = i2c_rate/ SCLK Divisor
 */
 static void  rk30_i2c_set_clk(struct rk30_i2c *i2c, unsigned long scl_rate)
 {
-    unsigned long i2c_rate = clk_get_rate(i2c->clk);
-
-    unsigned int div, divl, divh;
-
-    if((scl_rate == i2c->scl_rate) && (i2c_rate == i2c->i2c_rate))
-        return; 
-    i2c->i2c_rate = i2c_rate;
-    i2c->scl_rate = scl_rate;
-    div = rk30_ceil(i2c_rate, scl_rate * 8);
-    divh = divl = rk30_ceil(div, 2);
-    i2c_dbg(i2c->dev, "div divh divl: %d %d %d\n", div, divh, divl);
-    writel(I2C_CLKDIV_VAL(divl, divh), i2c->regs + I2C_CLKDIV);
-    return;
+        unsigned long i2c_rate = clk_get_rate(i2c->clk);
+
+        unsigned int div, divl, divh;
+
+        if((scl_rate == i2c->scl_rate) && (i2c_rate == i2c->i2c_rate))
+                return; 
+        i2c->i2c_rate = i2c_rate;
+        i2c->scl_rate = scl_rate;
+        div = rk30_ceil(i2c_rate, scl_rate * 8);
+        divh = divl = rk30_ceil(div, 2);
+        writel(I2C_CLKDIV_VAL(divl, divh), i2c->regs + I2C_CLKDIV);
+        i2c_dbg(i2c->dev, "set clk(I2C_CLKDIV: 0x%08x)\n", readl(i2c->regs + I2C_CLKDIV));
+        return;
 }
 static void rk30_i2c_init_hw(struct rk30_i2c *i2c, unsigned long scl_rate)
 {
-    rk30_i2c_set_clk(i2c, scl_rate);
+        i2c->scl_rate = 0;
+        rk30_i2c_set_clk(i2c, scl_rate);
        return;
 }
 /* returns TRUE if we this is the last byte in the current message */
@@ -195,19 +206,32 @@ static void rk30_i2c_stop(struct rk30_i2c *i2c, int ret)
 
     i2c->msg_ptr = 0;
        i2c->msg = NULL;
-       i2c->msg_idx++;
        i2c->msg_num = 0;
        if (ret)
                i2c->msg_idx = ret;
+        writel(I2C_STOPIEN, i2c->regs + I2C_IEN);
+        i2c->state = STATE_STOP;
+        rk30_i2c_send_stop(i2c);
+}
+static inline void rk30_set_rx_mode(struct rk30_i2c *i2c, unsigned int lastnak)
+{
+        unsigned long con = readl(i2c->regs + I2C_CON);
 
-        mdelay(10);
-    i2c->state = STATE_STOP;
-    rk30_i2c_send_stop(i2c);
+        con &= (~I2C_CON_MASK);
+        con |= (I2C_CON_MOD_RX << 1);
+        if(lastnak)
+                con |= I2C_CON_LASTACK;
+        writel(con, i2c->regs + I2C_CON);
 }
 static void rk30_irq_read_prepare(struct rk30_i2c *i2c)
 {
     unsigned int cnt, len = i2c->msg->len - i2c->msg_ptr;
 
+    if(len <= 32 && i2c->msg_ptr != 0) 
+            rk30_set_rx_mode(i2c, 1);
+    else if(i2c->msg_ptr != 0)
+            rk30_set_rx_mode(i2c, 0);
+
     if(is_msgend(i2c)) {
         rk30_i2c_stop(i2c, 0);
         return;
@@ -216,7 +240,6 @@ static void rk30_irq_read_prepare(struct rk30_i2c *i2c)
         cnt = 32;
     else
         cnt = len;
-
     writel(cnt, i2c->regs + I2C_MRXCNT);
 }
 static void rk30_irq_read_get_data(struct rk30_i2c *i2c)
@@ -263,147 +286,162 @@ static void rk30_irq_write_prepare(struct rk30_i2c *i2c)
 }
 static void rk30_i2c_irq_nextblock(struct rk30_i2c *i2c, unsigned int ipd)
 {
-    switch (i2c->state) {
-       case STATE_IDLE:
-               dev_err(i2c->dev, "Addr[0x%02x] called in STATE_IDLE\n", i2c->addr);
-               goto out;
-    case STATE_START:
-        if(!(ipd & I2C_STARTIPD)){
-            if(ipd & I2C_STOPIPD){
-                writel(I2C_STOPIPD, i2c->regs + I2C_IPD);
-            }
-            else {
-                rk30_i2c_stop(i2c, -ENXIO);
-                           dev_err(i2c->dev, "Addr[0x%02x] no start irq in STATE_START\n", i2c->addr);
+        switch (i2c->state) {
+        case STATE_IDLE:
+                dev_err(i2c->dev, "Addr[0x%02x] called in STATE_IDLE\n", i2c->addr);
                 rk30_show_regs(i2c);
-            }
-            goto out;
-        }
-        writel(I2C_STARTIPD, i2c->regs + I2C_IPD);
-        if(i2c->mode ==  I2C_MOD_TX){
-            i2c->state = STATE_WRITE;
-            goto prepare_write;
-        }
-        else {
-             i2c->state = STATE_READ;
-             goto prepare_read;
-        }
-    case STATE_WRITE:
-        if(!(ipd & I2C_MBTFIPD)){
-            goto out;
-        }
-        writel(I2C_MBTFIPD, i2c->regs + I2C_IPD);
+                writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD);
+                goto out;
+        case STATE_START:
+                if(!(ipd & I2C_STARTIPD)){
+                        rk30_i2c_stop(i2c, -ENXIO);
+                        dev_err(i2c->dev, "Addr[0x%02x] no start irq in STATE_START\n", i2c->addr);
+                        rk30_show_regs(i2c);
+                        writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD);
+                        goto out;
+                }
+
+                        rk30_show_regs(i2c);
+                writel(I2C_STARTIPD, i2c->regs + I2C_IPD);
+                rk30_i2c_clean_start(i2c);
+                if(i2c->mode ==  I2C_CON_MOD_TX){
+                        writel(I2C_MBTFIEN  | I2C_NAKRCVIEN, i2c->regs + I2C_IEN);
+                        i2c->state = STATE_WRITE;
+                        goto prepare_write;
+                } else {
+                        writel(I2C_MBRFIEN | I2C_NAKRCVIEN, i2c->regs + I2C_IEN);
+                        i2c->state = STATE_READ;
+                        goto prepare_read;
+                }
+        case STATE_WRITE:
+                if(!(ipd & I2C_MBTFIPD)){
+                        rk30_i2c_stop(i2c, -ENXIO);
+                        dev_err(i2c->dev, "Addr[0x%02x] no mbtf irq in STATE_WRITE\n", i2c->addr);
+                        rk30_show_regs(i2c);
+                        writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD);
+                        goto out;
+                }
+                        rk30_show_regs(i2c);
+                writel(I2C_MBTFIPD, i2c->regs + I2C_IPD);
 prepare_write:
-        rk30_irq_write_prepare(i2c);
-        break;
-    case STATE_READ:
-        if(!(ipd & I2C_MBRFIPD)){
-            goto out;
-        }
-        writel(I2C_MBRFIPD, i2c->regs + I2C_IPD);
-        rk30_irq_read_get_data(i2c);
+                rk30_irq_write_prepare(i2c);
+                break;
+        case STATE_READ:
+                if(!(ipd & I2C_MBRFIPD)){
+                        rk30_i2c_stop(i2c, -ENXIO);
+                        dev_err(i2c->dev, "Addr[0x%02x] no mbrf irq in STATE_READ\n", i2c->addr);
+                        rk30_show_regs(i2c);
+                        writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD);
+                        goto out;
+                }
+                        rk30_show_regs(i2c);
+                writel(I2C_MBRFIPD, i2c->regs + I2C_IPD);
+                rk30_irq_read_get_data(i2c);
 prepare_read:
-        rk30_irq_read_prepare(i2c);
-        break;
-    case STATE_STOP:
-        if(ipd & I2C_STOPIPD){
-            writel(0xff, i2c->regs + I2C_IPD);
-            i2c->state = STATE_IDLE;
-               rk30_i2c_disable_irq(i2c);
+                rk30_irq_read_prepare(i2c);
+                break;
+        case STATE_STOP:
+                if(!(ipd & I2C_STOPIPD)){
+                        rk30_i2c_stop(i2c, -ENXIO);
+                        dev_err(i2c->dev, "Addr[0x%02x] no stop irq in STATE_STOP\n", i2c->addr);
+                        rk30_show_regs(i2c);
+                        writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD);
+                        goto out;
+                }
+                        rk30_show_regs(i2c);
+                rk30_i2c_clean_stop(i2c);
+                writel(I2C_STOPIPD, i2c->regs + I2C_IPD);
+                i2c->state = STATE_IDLE;
                wake_up(&i2c->wait);
+                break;
+        default:
+                break;
         }
-        break;
-    default:
-        break;
-    }
 out:
-    return;
+        return;
 }
 static irqreturn_t rk30_i2c_irq(int irq, void *dev_id)
 {
-    struct rk30_i2c *i2c = dev_id;
-    unsigned int ipd;
-    spin_lock(&i2c->lock);
-    ipd = readl(i2c->regs + I2C_IPD);
-
-    if(ipd & I2C_NAKRCVIPD) {
-        writel(I2C_NAKRCVIPD, i2c->regs + I2C_IPD);
-        rk30_i2c_stop(i2c, -EAGAIN);
-               dev_dbg(i2c->dev, "Addr[0x%02x] ack was not received\n", i2c->addr);
-        rk30_show_regs(i2c);
-        goto out;
-    }
-
-    rk30_i2c_irq_nextblock(i2c, ipd);
+        struct rk30_i2c *i2c = dev_id;
+        unsigned int ipd;
+
+        spin_lock(&i2c->lock);
+        ipd = readl(i2c->regs + I2C_IPD);
+#if 1
+        if((ipd & I2C_NAKRCVIPD)  && (i2c->state != STATE_STOP)){
+               dev_err(i2c->dev, "Addr[0x%02x] ack was not received\n", i2c->addr);
+                rk30_show_regs(i2c);
+                writel(I2C_NAKRCVIPD, i2c->regs + I2C_IPD);
+                rk30_i2c_stop(i2c, -EAGAIN);
+                goto out;
+        }
+#endif
+        rk30_i2c_irq_nextblock(i2c, ipd);
 out:
-    spin_unlock(&i2c->lock);
-       return IRQ_HANDLED;
+        spin_unlock(&i2c->lock);
+        return IRQ_HANDLED;
 }
 
 
 static int rk30_i2c_set_master(struct rk30_i2c *i2c, struct i2c_msg *msgs, int num)
 {
-    unsigned int addr = (msgs[0].addr & 0x7f) << 1;
-    unsigned int reg_valid_bits = 0;
-    unsigned int reg_addr = 0;
+        unsigned int addr = (msgs[0].addr & 0x7f) << 1;
+        unsigned int reg_valid_bits = 0;
+        unsigned int reg_addr = 0;
     
-    if(num == 1) {
-        if(!(msgs[0].flags & I2C_M_RD)){
-               i2c->msg = &msgs[0];
-            i2c->mode = I2C_MOD_TX;
+        if(num == 1) {
+                i2c->count = msgs[0].len;
+                if(!(msgs[0].flags & I2C_M_RD)){
+                        i2c->msg = &msgs[0];
+                        i2c->mode = I2C_CON_MOD_TX;
+                }
+                else {
+                        addr |= 1;
+                        i2c->msg = &msgs[0];
+                        writel(addr | I2C_MRXADDR_LOW, i2c->regs + I2C_MRXADDR);
+                        i2c->mode = I2C_CON_MOD_RX;
+                }
         }
-        else {
-            addr |= 1;
-               i2c->msg = &msgs[0];
-            writel(addr | I2C_MRXADDR_LOW, i2c->regs + I2C_MRXADDR);
-            i2c->mode = I2C_MOD_RX;
+        else if(num == 2) {
+                i2c->count = msgs[1].len;
+                switch(msgs[0].len){
+                case 1:
+                        reg_addr = msgs[0].buf[0];
+                        reg_valid_bits |= I2C_MRXADDR_LOW;
+                        break;
+                case 2:
+                        reg_addr = msgs[0].buf[0] | (msgs[0].buf[1] << 8);
+                        reg_valid_bits |= I2C_MRXADDR_LOW | I2C_MRXADDR_MID;
+                        break;
+                case 3:
+                        reg_addr = msgs[0].buf[0] | (msgs[0].buf[1] << 8) | (msgs[0].buf[2] << 16);
+                        reg_valid_bits |= I2C_MRXADDR_LOW | I2C_MRXADDR_MID | I2C_MRXADDR_HIGH;
+                        break;
+                default:
+                        return -EIO;
+                }
+                if((msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD)) {
+                        addr |= 1;
+                        i2c->msg = &msgs[1];
+                        writel(addr | I2C_MRXADDR_LOW, i2c->regs + I2C_MRXADDR);
+                        writel(reg_addr | reg_valid_bits, i2c->regs + I2C_MRXRADDR);
+                        i2c->mode = I2C_CON_MOD_RRX;
+                }
+                else if(!(msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD)) {
+                        i2c->msg = &msgs[1];
+                        writel(addr | I2C_MRXADDR_LOW, i2c->regs + I2C_MRXADDR);
+                        writel(reg_addr | reg_valid_bits, i2c->regs + I2C_MRXRADDR);
+                        i2c->mode = I2C_CON_MOD_TRX;
+                }
+                else 
+                        return -EIO;
         }
-    }
-    else if(num == 2) {
-        switch(msgs[0].len){
-            case 1:
-                reg_addr = msgs[0].buf[0];
-                reg_valid_bits |= I2C_MRXADDR_LOW;
-                break;
-            case 2:
-                reg_addr = msgs[0].buf[0] | (msgs[0].buf[1] << 8);
-                reg_valid_bits |= I2C_MRXADDR_LOW | I2C_MRXADDR_MID;
-                break;
-            case 3:
-                reg_addr = msgs[0].buf[0] | (msgs[0].buf[1] << 8) | (msgs[0].buf[2] << 16);
-                reg_valid_bits |= I2C_MRXADDR_LOW | I2C_MRXADDR_MID | I2C_MRXADDR_HIGH;
-                break;
-            default:
+        else {
+                dev_err(i2c->dev, "This case(num > 2) has not been support now\n");
                 return -EIO;
         }
-        if((msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD)) {
-            addr |= 1;
-               i2c->msg = &msgs[1];
-            writel(addr | I2C_MRXADDR_LOW, i2c->regs + I2C_MRXADDR);
-            writel(reg_addr | reg_valid_bits, i2c->regs + I2C_MRXRADDR);
-            i2c->mode = I2C_MOD_RRX;
-        }
-        else if(!(msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD)) {
-               i2c->msg = &msgs[1];
-            writel(addr | I2C_MRXADDR_LOW, i2c->regs + I2C_MRXADDR);
-            writel(reg_addr | reg_valid_bits, i2c->regs + I2C_MRXRADDR);
-            i2c->mode = I2C_MOD_TRX;
-        }
-        else 
-            return -EIO;
-    }
-    else {
-        dev_err(i2c->dev, "This case(num > 2) has not been support now\n");
-        return -EIO;
-    }
-    rk30_i2c_set_mode(i2c);
-    rk30_i2c_last_ack(i2c, LAST_SEND_TYPE);
-    if(msgs[0].flags & I2C_M_IGNORE_NAK)
-        rk30_i2c_act2ack(i2c, 0);
-    else
-        rk30_i2c_act2ack(i2c, 1);
 
-    return 0;
+        return 0;
 }
 /* rk30_i2c_doxfer
  *
@@ -420,38 +458,41 @@ static int rk30_i2c_doxfer(struct rk30_i2c *i2c,
 
        ret = rk30_i2c_set_master(i2c, msgs, num);
        if (ret != 0) {
-        dev_err(i2c->dev, "addr[0x%02x] set master error\n", msgs[0].addr);  
-       return ret;
-    }
+                dev_err(i2c->dev, "addr[0x%02x] set master error\n", msgs[0].addr);  
+               return ret;
+        }
        spin_lock_irq(&i2c->lock);
 
-    i2c->addr = msgs[0].addr;
+        i2c->addr = msgs[0].addr;
        i2c->msg_num = num;
-    i2c->msg_ptr = 0;
-    i2c->msg_idx = 0;
-    i2c->state = STATE_START;
+        i2c->msg_ptr = 0;
+        i2c->msg_idx = num;
+        i2c->state = STATE_START;
 
        spin_unlock_irq(&i2c->lock);
 
-       rk30_i2c_enable_irq(i2c);
-    rk30_i2c_send_start(i2c);
+        writel(I2C_STARTIEN, i2c->regs + I2C_IEN);
+        rk30_i2c_enable(i2c, (i2c->count > 32)?0:1); //if count > 32,  byte(32) send ack
+        rk30_show_regs(i2c);
+       //rk30_i2c_enable_irq(i2c);
+        //rk30_i2c_send_start(i2c);
 
-       timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, msecs_to_jiffies(I2C_WAIT_TIMEOUT));
+       timeout = wait_event_timeout(i2c->wait, (i2c->msg_num == 0), msecs_to_jiffies(I2C_WAIT_TIMEOUT));
 
        ret = i2c->msg_idx;
 
        if (timeout == 0){
-        dev_err(i2c->dev, "addr[0x%02x] wait event timeout, state = %d\n", msgs[0].addr, i2c->state);  
+                dev_err(i2c->dev, "addr[0x%02x] wait event timeout, state = %d\n", msgs[0].addr, i2c->state);  
+                rk30_show_regs(i2c);
+                if(i2c->state != STATE_STOP)
+                        rk30_i2c_send_stop(i2c);
+                ret = -ETIMEDOUT;
+        }
+        writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD);
+       rk30_i2c_disable_irq(i2c);
+        rk30_i2c_disable(i2c);
+        i2c_dbg(i2c->dev, "i2c transfer finished ret = %d\n", ret);
         rk30_show_regs(i2c);
-        writel(0xff, i2c->regs + I2C_IPD);
-           rk30_i2c_disable_irq(i2c);
-        rk30_i2c_send_stop(i2c);
-        if(ret >= 0)
-            ret = -ETIMEDOUT;
-        return ret;
-    }
-    if(ret > 0)
-        ret = num;
        return ret;
 }
 
@@ -465,10 +506,10 @@ static int rk30_i2c_xfer(struct i2c_adapter *adap,
                        struct i2c_msg *msgs, int num)
 {
        int ret = 0;
-    unsigned long scl_rate;
+        unsigned long scl_rate;
        struct rk30_i2c *i2c = (struct rk30_i2c *)adap->algo_data;
 
-    if(msgs[0].scl_rate <= 400000 && msgs[0].scl_rate >= 10000)
+        if(msgs[0].scl_rate <= 400000 && msgs[0].scl_rate >= 10000)
                scl_rate = msgs[0].scl_rate;
        else if(msgs[0].scl_rate > 400000){
                dev_warn(i2c->dev, "Warning: addr[0x%x] msg[0].scl_rate( = %dKhz) is too high!",
@@ -480,19 +521,16 @@ static int rk30_i2c_xfer(struct i2c_adapter *adap,
                        msgs[0].addr, msgs[0].scl_rate/1000);
                scl_rate = 10000;
        }
-    if(i2c->is_div_from_arm[i2c->adap.nr])
+        if(i2c->is_div_from_arm[i2c->adap.nr])
                wake_lock(&i2c->idlelock[i2c->adap.nr]);
 
-    rk30_i2c_enable(i2c, 1);
        rk30_i2c_set_clk(i2c, scl_rate);
-    udelay(i2c->tx_setup);
-
-    i2c_dbg(i2c->dev, "i2c transfer: addr[0x%x], scl_reate[%ldKhz]\n", msgs[0].addr, scl_rate/1000);
+        udelay(i2c->tx_setup);
+        i2c_dbg(i2c->dev, "i2c transfer: addr[0x%x], scl_reate[%ldKhz], len = %d\n", msgs[0].addr, scl_rate/1000, i2c->count);
        ret = rk30_i2c_doxfer(i2c, msgs, num);
 
-    rk30_i2c_enable(i2c, 0);
-    i2c->state = STATE_IDLE;
-    if(i2c->is_div_from_arm[i2c->adap.nr])
+        i2c->state = STATE_IDLE;
+        if(i2c->is_div_from_arm[i2c->adap.nr])
                wake_unlock(&i2c->idlelock[i2c->adap.nr]);
        return ret;
 }
@@ -512,17 +550,17 @@ static const struct i2c_algorithm rk30_i2c_algorithm = {
 
 int i2c_add_rk30_adapter(struct i2c_adapter *adap)
 {
-    int ret = 0;
-    struct rk30_i2c *i2c = (struct rk30_i2c *)adap->algo_data;
+        int ret = 0;
+        struct rk30_i2c *i2c = (struct rk30_i2c *)adap->algo_data;
 
-    adap->algo = &rk30_i2c_algorithm;
+        adap->algo = &rk30_i2c_algorithm;
 
-    i2c->i2c_init_hw = &rk30_i2c_init_hw;
-    i2c->i2c_set_clk = &rk30_i2c_set_clk;
-    i2c->i2c_irq = &rk30_i2c_irq;
+        i2c->i2c_init_hw = &rk30_i2c_init_hw;
+        i2c->i2c_set_clk = &rk30_i2c_set_clk;
+        i2c->i2c_irq = &rk30_i2c_irq;
 
-    ret = i2c_add_numbered_adapter(adap);
+        ret = i2c_add_numbered_adapter(adap);
 
-    return ret;
+        return ret;
 }
 
index 05db8a4c22a655dc221df435cd46164a31552d3a..68daa5cb535c8832e68fa14d951fcecffce225e1 100755 (executable)
@@ -28,7 +28,7 @@
 #define i2c_dbg(dev, format, arg...)
 #endif
 
-#define I2C_WAIT_TIMEOUT            100  //100ms
+#define I2C_WAIT_TIMEOUT            200  //100ms
 
 #define rk30_set_bit(p, v, b)        (((p) & ~(1 << (b))) | ((v) << (b)))
 #define rk30_get_bit(p, b)           (((p) & (1 << (b))) >> (b))
@@ -75,6 +75,7 @@ struct rk30_i2c {
        unsigned long           i2c_rate;
     unsigned int        addr;
     unsigned int        mode;
+    unsigned int        count;
 
     struct wake_lock    idlelock[5];
     int is_div_from_arm[5];
index b32f5654c6c15a82a858a28b623e5b775fc798d0..d37266328952e53657de055c111bba25cd80cc17 100755 (executable)
@@ -1456,7 +1456,7 @@ int i2c_master_recv(const struct i2c_client *client, char *buf, int count)
        msg.flags = client->flags | I2C_M_RD;
        msg.len = count;
        msg.buf = (char *)buf;
-       msg.scl_rate = 400 * 1000;
+       msg.scl_rate = 100 * 1000;
        msg.udelay = client->udelay;
 
        ret = i2c_transfer(adap, &msg, 1);