rk30: i2c: support 'I2C_M_TEN flag'
authorkfx <kfx@rock-chips.com>
Tue, 23 Apr 2013 06:33:09 +0000 (14:33 +0800)
committerkfx <kfx@rock-chips.com>
Tue, 23 Apr 2013 06:33:09 +0000 (14:33 +0800)
drivers/i2c/busses/i2c-rk30-adapter.c
drivers/i2c/busses/i2c-rk30.h

index cae8bde0aaf70bb19f2f96a953050a78f69446fe..21503f5c172f2852260299c42e516d1e0b2b3bdb 100755 (executable)
@@ -322,9 +322,11 @@ static void rk30_irq_write_prepare(struct rk30_i2c *i2c)
         for(j = 0; j < 4; j++) {
             if(is_msgend(i2c)) 
                 break;
-            if(i2c->msg_ptr == 0 && cnt == 0)
-                byte = (i2c->addr & 0x7f) << 1;
-            else
+            if((i2c->msg_ptr == 0) && (cnt == 0))
+                byte = (i2c->addr_1st & 0x7f) << 1;
+            else if((i2c->msg_ptr == 0) && (cnt == 1) && (i2c->msg->flags & I2C_M_TEN))
+               byte = i2c->addr_2nd; 
+           else
                 byte =  i2c->msg->buf[i2c->msg_ptr++];
             cnt++;
             data |= (byte << (j * 8));
@@ -341,7 +343,7 @@ static void rk30_i2c_irq_nextblock(struct rk30_i2c *i2c, unsigned int ipd)
         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);
+                        dev_err(i2c->dev, "Addr[0x%04x] no start irq in STATE_START\n", i2c->addr);
                         rk30_show_regs(i2c);
                         i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD);
                         goto out;
@@ -361,7 +363,7 @@ static void rk30_i2c_irq_nextblock(struct rk30_i2c *i2c, unsigned int ipd)
         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);
+                        dev_err(i2c->dev, "Addr[0x%04x] no mbtf irq in STATE_WRITE\n", i2c->addr);
                         rk30_show_regs(i2c);
                         i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD);
                         goto out;
@@ -374,7 +376,7 @@ prepare_write:
         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, ipd = 0x%x\n", i2c->addr, ipd);
+                        dev_err(i2c->dev, "Addr[0x%04x] no mbrf irq in STATE_READ, ipd = 0x%x\n", i2c->addr, ipd);
                         rk30_show_regs(i2c);
                         i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD);
                         goto out;
@@ -388,7 +390,7 @@ prepare_read:
         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);
+                        dev_err(i2c->dev, "Addr[0x%04x] no stop irq in STATE_STOP\n", i2c->addr);
                         rk30_show_regs(i2c);
                         i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD);
                         goto out;
@@ -414,7 +416,7 @@ static irqreturn_t rk30_i2c_irq(int irq, void *dev_id)
         spin_lock(&i2c->lock);
         ipd = i2c_readl(i2c->regs + I2C_IPD);
         if(i2c->state == STATE_IDLE){
-                dev_info(i2c->dev, "Addr[0x%02x]  irq in STATE_IDLE, ipd = 0x%x\n", i2c->addr, ipd);
+                dev_info(i2c->dev, "Addr[0x%04x]  irq in STATE_IDLE, ipd = 0x%x\n", i2c->addr, ipd);
                 i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD);
                 goto out;
         }
@@ -433,9 +435,9 @@ out:
 
 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 = (i2c->addr_1st << 1) | 1;
     
         if(num == 1) {
                 i2c->count = msgs[0].len;
@@ -444,7 +446,6 @@ static int rk30_i2c_set_master(struct rk30_i2c *i2c, struct i2c_msg *msgs, int n
                         i2c->mode = I2C_CON_MOD_TX;
                 }
                 else {
-                        addr |= 1;
                         i2c->msg = &msgs[0];
                         i2c_writel(addr | I2C_MRXADDR_LOW, i2c->regs + I2C_MRXADDR);
                         i2c_writel(0, i2c->regs + I2C_MRXRADDR);
@@ -454,24 +455,39 @@ static int rk30_i2c_set_master(struct rk30_i2c *i2c, struct i2c_msg *msgs, int n
         }
         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;
+               
+               if(msgs[0].flags & I2C_M_TEN){
+                       switch(msgs[0].len){
+                               case 1:
+                               reg_addr = i2c->addr_2nd | (msgs[0].buf[0] << 8);
+                               reg_valid_bits |= I2C_MRXADDR_LOW | I2C_MRXADDR_MID;
+                               break;
+                       case 2:
+                               reg_addr = i2c->addr_2nd | (msgs[0].buf[0] << 8) | (msgs[0].buf[1] << 16);
+                               reg_valid_bits |= I2C_MRXADDR_LOW | I2C_MRXADDR_MID | I2C_MRXADDR_HIGH;
+                               break;
+                       default:
+                               return -EIO;
+                       }
+               }else{
+                       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;
-                }
+                       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];
                         i2c_writel(addr | I2C_MRXADDR_LOW, i2c->regs + I2C_MRXADDR);
                         i2c_writel(reg_addr | reg_valid_bits, i2c->regs + I2C_MRXRADDR);
@@ -516,12 +532,22 @@ static int rk30_i2c_doxfer(struct rk30_i2c *i2c,
         }
 
        spin_lock_irqsave(&i2c->lock, flags);
+        i2c->addr = msgs[0].addr;
+       if(msgs[0].flags & I2C_M_TEN){
+               i2c->addr_1st = ((i2c->addr & 0x0300)>>8) | 0x78;
+               i2c->addr_2nd = i2c->addr & 0x00ff;
+       }else{
+               i2c->addr_1st = i2c->addr & 0x007f;
+               i2c->addr_2nd = 0;
+       }
+       i2c_dbg(i2c->dev, "addr: 0x%04x, addr_1st: 0x%02x, addr_2nd: 0x%02x\n",
+                       i2c->addr, i2c->addr_1st, i2c->addr_2nd);
+
        if(rk30_i2c_set_master(i2c, msgs, num) < 0){
                spin_unlock_irqrestore(&i2c->lock, flags);
-                dev_err(i2c->dev, "addr[0x%02x] set master error\n", msgs[0].addr);  
+                dev_err(i2c->dev, "addr[0x%04x] set master error\n", msgs[0].addr);  
                return -EIO;
         }
-        i2c->addr = msgs[0].addr;
         i2c->msg_ptr = 0;
         i2c->error = 0;
        i2c->is_busy = 1;
@@ -549,7 +575,7 @@ static int rk30_i2c_doxfer(struct rk30_i2c *i2c,
                 if(error < 0)
                         i2c_dbg(i2c->dev, "error = %d\n", error);
                 else if((i2c->complete_what !=COMPLETE_READ  && i2c->complete_what != COMPLETE_WRITE)){
-                        dev_err(i2c->dev, "Addr[0x%02x] wait event timeout, state: %d, is_busy: %d, error: %d, complete_what: 0x%x, ipd: 0x%x\n", 
+                        dev_err(i2c->dev, "Addr[0x%04x] wait event timeout, state: %d, is_busy: %d, error: %d, complete_what: 0x%x, ipd: 0x%x\n", 
                                 msgs[0].addr, i2c->state, i2c->is_busy, error, i2c->complete_what, i2c_readl(i2c->regs + I2C_IPD));  
                         //rk30_show_regs(i2c);
                         error = -ETIMEDOUT;
@@ -571,7 +597,7 @@ static int rk30_i2c_doxfer(struct rk30_i2c *i2c,
         rk30_i2c_disable(i2c);
 
         if(error == -EAGAIN)
-                i2c_dbg(i2c->dev, "No ack(complete_what: 0x%x), Maybe slave(addr: 0x%02x) not exist or abnormal power-on\n",
+                i2c_dbg(i2c->dev, "No ack(complete_what: 0x%x), Maybe slave(addr: 0x%04x) not exist or abnormal power-on\n",
                                 i2c->complete_what, i2c->addr);
        return error;
 }
@@ -606,12 +632,12 @@ static int rk30_i2c_xfer(struct i2c_adapter *adap,
         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!",
+               dev_warn(i2c->dev, "Warning: addr[0x%04x] msg[0].scl_rate( = %dKhz) is too high!",
                        msgs[0].addr, msgs[0].scl_rate/1000);
                scl_rate = 400000;      
        }
        else{
-               dev_warn(i2c->dev, "Warning: addr[0x%x] msg[0].scl_rate( = %dKhz) is too low!",
+               dev_warn(i2c->dev, "Warning: addr[0x%04x] msg[0].scl_rate( = %dKhz) is too low!",
                        msgs[0].addr, msgs[0].scl_rate/1000);
                scl_rate = 10000;
        }
@@ -620,9 +646,9 @@ static int rk30_i2c_xfer(struct i2c_adapter *adap,
         }
 
        rk30_i2c_set_clk(i2c, scl_rate);
-        i2c_dbg(i2c->dev, "i2c transfer start: addr: 0x%x, scl_reate: %ldKhz, len: %d\n", msgs[0].addr, scl_rate/1000, num);
+        i2c_dbg(i2c->dev, "i2c transfer start: addr: 0x%04x, scl_reate: %ldKhz, len: %d\n", msgs[0].addr, scl_rate/1000, num);
        ret = rk30_i2c_doxfer(i2c, msgs, num);
-        i2c_dbg(i2c->dev, "i2c transfer stop: addr: 0x%x, state: %d, ret: %d\n", msgs[0].addr, ret, i2c->state);
+        i2c_dbg(i2c->dev, "i2c transfer stop: addr: 0x%04x, state: %d, ret: %d\n", msgs[0].addr, ret, i2c->state);
 
         if(i2c->is_div_from_arm[i2c->adap.nr]){
                 mutex_unlock(&i2c->m_lock);
index 0cb6d9e35a2b8c60b6b70f7e0f1e9038916b8bc0..13b5c559569fe8c3dee96d89fc24d477f3f3b23c 100755 (executable)
@@ -96,6 +96,7 @@ struct rk30_i2c {
         unsigned long          scl_rate;
        unsigned long           i2c_rate;
         unsigned int        addr;
+       unsigned char       addr_1st, addr_2nd;
         unsigned int        mode;
         unsigned int        count;