update i2c drivers
authorkfx <kfx@rock-chips.com>
Thu, 6 Jan 2011 02:47:49 +0000 (10:47 +0800)
committerkfx <kfx@rock-chips.com>
Thu, 6 Jan 2011 02:49:16 +0000 (10:49 +0800)
arch/arm/mach-rk29/board-rk29sdk.c
drivers/i2c/busses/i2c-rk29.c

index 344270dd89129212757e82a3bbef22f747bc007f..14a2f29c177c0ed81d7722102a8f692f9fc317ec 100755 (executable)
@@ -379,16 +379,6 @@ struct mma8452_platform_data mma8452_info = {
 *****************************************************************************************/
 static int rk29_i2c0_io_init(void)
 {
-       rk29_mux_api_set(GPIO2B7_I2C0SCL_NAME, 0);
-       rk29_mux_api_set(GPIO2B6_I2C0SDA_NAME, 0);
-       gpio_request(RK29_PIN2_PB6, "i2c0_sda");
-       gpio_set_value(RK29_PIN2_PB6, GPIO_HIGH);
-       gpio_pull_updown(RK29_PIN2_PB6, PullDisable);
-
-       gpio_request(RK29_PIN2_PB7, "i2c0_scl");
-       gpio_set_value(RK29_PIN2_PB7, GPIO_HIGH);
-       gpio_pull_updown(RK29_PIN2_PB7, PullDisable);
-       
        rk29_mux_api_set(GPIO2B7_I2C0SCL_NAME, GPIO2L_I2C0_SCL);
        rk29_mux_api_set(GPIO2B6_I2C0SDA_NAME, GPIO2L_I2C0_SDA);
        return 0;
@@ -396,28 +386,12 @@ static int rk29_i2c0_io_init(void)
 
 static int rk29_i2c1_io_init(void)
 {
-       gpio_request(RK29_PIN1_PA6, "i2c1_sda");
-       gpio_set_value(RK29_PIN1_PA6, GPIO_HIGH);
-       gpio_pull_updown(RK29_PIN1_PA6, PullDisable);
-
-       gpio_request(RK29_PIN1_PA7, "i2c1_scl");
-       gpio_set_value(RK29_PIN1_PA7, GPIO_HIGH);
-       gpio_pull_updown(RK29_PIN1_PA7, PullDisable);
-       
        rk29_mux_api_set(GPIO1A7_I2C1SCL_NAME, GPIO1L_I2C1_SCL);
        rk29_mux_api_set(GPIO1A6_I2C1SDA_NAME, GPIO1L_I2C1_SDA);
        return 0;
 }
 static int rk29_i2c2_io_init(void)
 {
-       gpio_request(RK29_PIN5_PD3, "i2c2_sda");
-       gpio_set_value(RK29_PIN5_PD3, GPIO_HIGH);
-       gpio_pull_updown(RK29_PIN5_PD3, PullDisable);
-
-       gpio_request(RK29_PIN5_PD4, "i2c2_scl");
-       gpio_set_value(RK29_PIN5_PD4, GPIO_HIGH);
-       gpio_pull_updown(RK29_PIN5_PD4, PullDisable);
-       
        rk29_mux_api_set(GPIO5D4_I2C2SCL_NAME, GPIO5H_I2C2_SCL);
        rk29_mux_api_set(GPIO5D3_I2C2SDA_NAME, GPIO5H_I2C2_SDA);
        return 0;
@@ -425,14 +399,6 @@ static int rk29_i2c2_io_init(void)
 
 static int rk29_i2c3_io_init(void)
 {
-       gpio_request(RK29_PIN2_PB4, "i2c3_sda");
-       gpio_set_value(RK29_PIN2_PB4, GPIO_HIGH);
-       gpio_pull_updown(RK29_PIN2_PB4, PullDisable);
-
-       gpio_request(RK29_PIN2_PB5, "i2c3_scl");
-       gpio_set_value(RK29_PIN2_PB5, GPIO_HIGH);
-       gpio_pull_updown(RK29_PIN2_PB5, PullDisable);
-       
        rk29_mux_api_set(GPIO2B5_UART3RTSN_I2C3SCL_NAME, GPIO2L_I2C3_SCL);
        rk29_mux_api_set(GPIO2B4_UART3CTSN_I2C3SDA_NAME, GPIO2L_I2C3_SDA);
        return 0;
index 3a48ea7f3f57574046afa70362b9accc7f9a3532..d020ddda31d1b33f51519011a4980fa0b5d41f61 100755 (executable)
 
 #include "i2c-rk29.h"
 #define DRV_NAME       "rk29_i2c"
-#define RETRY_NUM      3
+#define RETRY_NUM      1
 
-#define RK2818_I2C_TIMEOUT             (msecs_to_jiffies(100))
-#define RK2818_DELAY_TIME              2
+#define RK29_I2C_TIMEOUT(x)            (msecs_to_jiffies(x))
 
 #if 0
 #define i2c_dbg(dev, format, arg...)           \
 
 #else
 #define i2c_dbg(dev, format, arg...)
-#define i2c_err(dev, format, arg...)
+#define i2c_err(dev, format, arg...)   
 
 #endif
 
 enum rk29_error {
-       RK2818_ERROR_NONE = 0,
-       RK2818_ERROR_ARBITR_LOSE,
-       RK2818_ERROR_UNKNOWN
+       RK29_ERROR_NONE = 0,
+       RK29_ERROR_ARBITR_LOSE,
+       RK29_ERROR_UNKNOWN
 };
 
 enum rk29_event {
-       RK2818_EVENT_NONE = 0,
+       RK29_EVENT_NONE = 0,
        /* master has received ack(MTX mode) 
           means that data has been sent to slave.
         */
-       RK2818_EVENT_MTX_RCVD_ACK,      
+       RK29_EVENT_MTX_RCVD_ACK,        
        /* master needs to send ack to slave(MRX mode) 
           means that data has been received from slave.
         */
-       RK2818_EVENT_MRX_NEED_ACK,       
-       RK2818_EVENT_MAX
+       RK29_EVENT_MRX_NEED_ACK,         
+       RK29_EVENT_MAX
 };
 
 struct rk29_i2c_data {
@@ -81,6 +80,8 @@ struct rk29_i2c_data {
        unsigned int                    mode;
        int                                     retry;
 
+       int                                     poll_status;
+
        unsigned int                    irq;
 
        spinlock_t                              cmd_lock;
@@ -96,8 +97,6 @@ struct rk29_i2c_data {
 #endif 
 };
 
-static void rk29_i2c_init_hw(struct rk29_i2c_data *i2c);
-
 static void rk29_set_ack(struct rk29_i2c_data *i2c)
 {
        unsigned long conr = readl(i2c->regs + I2C_CONR);
@@ -159,11 +158,8 @@ static void rk29_i2c_calcdivisor(unsigned long pclk,
 /* set i2c bus scl rate */
 static void  rk29_i2c_clockrate(struct rk29_i2c_data *i2c)
 {
-#ifdef CONFIG_ARCH_RK2818
-       struct rk2818_i2c_platform_data *pdata = i2c->dev->platform_data;
-#else
+
        struct rk29_i2c_platform_data *pdata = i2c->dev->platform_data;
-#endif
        unsigned int rem = 0, exp = 0;
        unsigned long scl_rate, real_rate = 0, tmp;
 
@@ -187,22 +183,22 @@ static void  rk29_i2c_clockrate(struct rk29_i2c_data *i2c)
 }
 static int rk29_event_occurred(struct rk29_i2c_data *i2c)
 {
-       unsigned long isr;
+       unsigned long isr, lsr;
 
        isr = readl(i2c->regs + I2C_ISR);
-       i2c_dbg(i2c->dev,"event occurred, isr = %lx\n", isr);
+       lsr = readl(i2c->regs + I2C_LSR);
+       i2c_dbg(i2c->dev,"event occurred, isr = %lx, lsr = %lx\n", isr, lsr);
        if(isr & I2C_ISR_ARBITR_LOSE)
        {
-               isr &= ~I2C_ISR_ARBITR_LOSE;
-               writel(isr, i2c->regs + I2C_ISR);
-               i2c->cmd_err = RK2818_ERROR_ARBITR_LOSE;
+               writel(0, i2c->regs + I2C_ISR);
+               i2c->cmd_err = RK29_ERROR_ARBITR_LOSE;
                i2c_err(i2c->dev, "<error>arbitration loss\n");
-               return 1;
+               return 0;
        }
 
        switch(i2c->cmd_event)
        {
-               case RK2818_EVENT_MTX_RCVD_ACK:
+               case RK29_EVENT_MTX_RCVD_ACK:
                        if(isr & I2C_ISR_MTX_RCVD_ACK)
                        {
                                isr &= ~I2C_ISR_MTX_RCVD_ACK;
@@ -210,7 +206,7 @@ static int rk29_event_occurred(struct rk29_i2c_data *i2c)
                                return 1;
                        }
                break;
-               case RK2818_EVENT_MRX_NEED_ACK:
+               case RK29_EVENT_MRX_NEED_ACK:
                        if(isr & I2C_ISR_MRX_NEED_ACK)
                        {
                                isr &= ~I2C_ISR_MRX_NEED_ACK;
@@ -221,7 +217,8 @@ static int rk29_event_occurred(struct rk29_i2c_data *i2c)
                default:
                        break;
        }
-       i2c->cmd_err = RK2818_ERROR_UNKNOWN;
+       writel(0, i2c->regs + I2C_ISR);
+       i2c->cmd_err = RK29_ERROR_UNKNOWN;
        return 0;
 }
 
@@ -234,56 +231,51 @@ static irqreturn_t rk29_i2c_irq(int irq, void *data)
        spin_lock(&i2c->cmd_lock);
        res = rk29_event_occurred(i2c);
        if(res)
-       //if(res || i2c->cmd_err != RK2818_ERROR_NONE)
-               complete(&i2c->cmd_complete);
+       {
+               if(i2c->mode == I2C_MODE_IRQ)
+                       complete(&i2c->cmd_complete);
+               else
+                       i2c->poll_status = 1;
+       }
        spin_unlock(&i2c->cmd_lock);
        return IRQ_HANDLED;
 }
-static int wait_for_completion_poll_timeout(struct rk29_i2c_data *i2c, unsigned long timeout)
+static int wait_for_completion_poll_timeout(struct rk29_i2c_data *i2c)
 {
-       unsigned int time = RK2818_DELAY_TIME;
-       int res;
-
-       while(!time_after(jiffies, jiffies + timeout))
+       int tmo = 10000;
+       
+       while(--tmo)
        {
-               res = rk29_event_occurred(i2c);
-               if(res)
-               //if(res || (i2c->cmd_err != RK2818_ERROR_NONE && i2c->cmd_err != RK2818_ERROR_UNKNOWN))
+               if(i2c->poll_status == 1)
                        return 1;
-               udelay(time);
-               time *= 2;
+               udelay(400*1000/i2c->scl_rate);
        }
        return 0;
-
 }
 static int rk29_wait_event(struct rk29_i2c_data *i2c,
                                        enum rk29_event mr_event)
 {
        int ret = 0;
-       unsigned long flags;
-       if(i2c->mode == I2C_MODE_IRQ)
+
+       if(unlikely(irqs_disabled()))
        {
-               if(unlikely(irqs_disabled()))
-               {
-                       i2c_err(i2c->dev, "irqs are disabled on this system!\n");
-                       return -EIO;
-               }
+               i2c_err(i2c->dev, "irqs are disabled on this system!\n");
+               return -EIO;
        }
-       spin_lock_irqsave(&i2c->cmd_lock,flags);
-       i2c->cmd_err = RK2818_ERROR_NONE;
+       i2c->cmd_err = RK29_ERROR_NONE;
        i2c->cmd_event = mr_event;
-
-       init_completion(&i2c->cmd_complete);
-
-       spin_unlock_irqrestore(&i2c->cmd_lock,flags);
-
        rk29_i2c_enable_irqs(i2c);
        if(i2c->mode == I2C_MODE_IRQ)
+       {
+               init_completion(&i2c->cmd_complete);
                ret = wait_for_completion_interruptible_timeout(&i2c->cmd_complete,
-                                                               RK2818_I2C_TIMEOUT);
+                                                               RK29_I2C_TIMEOUT(40000 * 1000/i2c->scl_rate));
+       }
        else
-               ret = wait_for_completion_poll_timeout(i2c, RK2818_I2C_TIMEOUT);
-       
+       {
+               i2c->poll_status = 0;
+               ret = wait_for_completion_poll_timeout(i2c);
+       }
        if(ret < 0)
        {
                i2c_err(i2c->dev, "i2c wait for event %04x, retrun %d \n", mr_event, ret);
@@ -296,66 +288,59 @@ static int rk29_wait_event(struct rk29_i2c_data *i2c,
        return 0;
 }
 
-static int rk29_wait_while_busy(struct rk29_i2c_data *i2c)
+static void rk29_i2c_stop(struct rk29_i2c_data *i2c)
 {
-       unsigned long timeout = jiffies + RK2818_I2C_TIMEOUT/1000;
-       unsigned long lsr;
-       unsigned int time = RK2818_DELAY_TIME;
+       int tmo = 10000 * 1000/i2c->scl_rate;
 
-       while(!time_after(jiffies, timeout))
+       writel(I2C_LCMR_STOP|I2C_LCMR_RESUME, i2c->regs + I2C_LCMR);
+       while(--tmo && !(readl(i2c->regs + I2C_LCMR) & I2C_LCMR_STOP))
        {
-               lsr = readl(i2c->regs + I2C_LSR);
-               if(!(lsr & I2C_LSR_BUSY))
-                       return 0;
-               udelay(time);
-               time *= 2;
+               udelay(400*1000/i2c->scl_rate);
        }
-       return 0;
+       writel(0, i2c->regs + I2C_ISR);
+       rk29_i2c_disable_irqs(i2c);
+       
+       udelay(tmo);
+       return;
 }
-static int rk29_i2c_stop(struct rk29_i2c_data *i2c)
+static void rk29_wait_while_busy(struct rk29_i2c_data *i2c)
 {
-       unsigned long timeout = jiffies + RK2818_I2C_TIMEOUT/1000;
-       unsigned int time = RK2818_DELAY_TIME;
-
-       writel(I2C_LCMR_STOP|I2C_LCMR_RESUME, i2c->regs + I2C_LCMR);
-       while(!time_after(jiffies, timeout))
+       int tmo = 10000 * 1000/i2c->scl_rate;
+       
+       while(--tmo && (readl(i2c->regs + I2C_LSR) & I2C_LSR_BUSY))
        {
-               if(!(readl(i2c->regs + I2C_LCMR) & I2C_LCMR_STOP))
-               {
-                       udelay(100);
-                       return 0;
-               }
-               udelay(time);
-               time *= 2;
+               udelay(400*1000/i2c->scl_rate);
        }
-       return 0;
+       return;
 }
+
 static int rk29_send_2nd_addr(struct rk29_i2c_data *i2c,
                                                struct i2c_msg *msg, int start)
 {
        int ret = 0;
+       unsigned long lsr;
        unsigned long addr_2nd = msg->addr & 0xff;
-       unsigned long conr = readl(i2c->regs + I2C_CONR);
 
-       conr |= I2C_CONR_MTX_MODE;
-       //conr &= I2C_CONR_ACK;
-       writel(conr, i2c->regs + I2C_CONR);
-       
        i2c_dbg(i2c->dev, "i2c send addr_2nd: %lx\n", addr_2nd);        
        writel(addr_2nd, i2c->regs + I2C_MTXR);
        writel(I2C_LCMR_RESUME, i2c->regs + I2C_LCMR);
-       if((ret = rk29_wait_event(i2c, RK2818_EVENT_MTX_RCVD_ACK)) != 0)
+       rk29_set_ack(i2c);
+       
+       if((ret = rk29_wait_event(i2c, RK29_EVENT_MTX_RCVD_ACK)) != 0)
        {
                i2c_err(i2c->dev, "after sent addr_2nd, i2c wait for ACK timeout\n");
                return ret;
        }
+       lsr = readl(i2c->regs + I2C_LSR);
+       if(lsr & I2C_LSR_RCV_NAK)
+               return -EINVAL;
        return ret;
 }
 static int rk29_send_address(struct rk29_i2c_data *i2c,
                                                struct i2c_msg *msg, int start)
 {
        unsigned long addr_1st;
-       unsigned long conr = readl(i2c->regs + I2C_CONR);
+       unsigned long conr,lsr;
        int ret = 0;
        
        if(msg->flags & I2C_M_TEN)
@@ -367,29 +352,29 @@ static int rk29_send_address(struct rk29_i2c_data *i2c,
                addr_1st |= 0x01;
        else
                addr_1st &= (~0x01);
-       rk29_set_ack(i2c);
+
+       if(start)
+               rk29_wait_while_busy(i2c);
+       
+       writel(0, i2c->regs + I2C_ISR);
+       conr = readl(i2c->regs + I2C_CONR);
        conr |= I2C_CONR_MTX_MODE;
+       conr |= I2C_CONR_MPORT_ENABLE;
        writel(conr, i2c->regs + I2C_CONR);
-       
+
        i2c_dbg(i2c->dev, "i2c send addr_1st: %lx\n", addr_1st);
-       
        writel(addr_1st, i2c->regs + I2C_MTXR);
-       
-       if (start)
-       {
-               if((ret = rk29_wait_while_busy(i2c)) != 0)
-               {
-                       i2c_err(i2c->dev, "i2c is busy, when send address\n");
-                       return ret;
-               }
-       }
+       rk29_set_ack(i2c);
        writel(I2C_LCMR_START|I2C_LCMR_RESUME, i2c->regs + I2C_LCMR);
 
-       if((ret = rk29_wait_event(i2c, RK2818_EVENT_MTX_RCVD_ACK)) != 0)
+       if((ret = rk29_wait_event(i2c, RK29_EVENT_MTX_RCVD_ACK)) != 0)
        {
                i2c_err(i2c->dev, "after sent addr_1st, i2c wait for ACK timeout\n");
                return ret;
        }
+       lsr = readl(i2c->regs + I2C_LSR);
+       if(lsr & I2C_LSR_RCV_NAK)
+               return -EINVAL;
        if(start && (msg->flags & I2C_M_TEN))
                ret = rk29_send_2nd_addr(i2c, msg, start);
        return ret;
@@ -398,23 +383,26 @@ static int rk29_send_address(struct rk29_i2c_data *i2c,
 static int rk29_i2c_send_msg(struct rk29_i2c_data *i2c, struct i2c_msg *msg)
 {
        int i, ret = 0;
-       unsigned long conr = readl(i2c->regs + I2C_CONR);
+       unsigned long conr, lsr;
        
        conr = readl(i2c->regs + I2C_CONR);
        conr |= I2C_CONR_MTX_MODE;
+       //conr |= I2C_CONR_MPORT_ENABLE;
        writel(conr, i2c->regs + I2C_CONR);
-
-       rk29_set_ack(i2c);
+       
        for(i = 0; i < msg->len; i++)
        {
-               i2c_dbg(i2c->dev, "i2c send buf[%d]: %x\n", i, msg->buf[i]);
+               i2c_dbg(i2c->dev, "i2c send buf[%d]: %x\n", i, msg->buf[i]);    
                writel(msg->buf[i], i2c->regs + I2C_MTXR);
+               rk29_set_ack(i2c);
                writel(I2C_LCMR_RESUME, i2c->regs + I2C_LCMR);
 
-               if((ret = rk29_wait_event(i2c, RK2818_EVENT_MTX_RCVD_ACK)) != 0)
+               if((ret = rk29_wait_event(i2c, RK29_EVENT_MTX_RCVD_ACK)) != 0)
                        return ret;
-               if(readl(i2c->regs + I2C_LSR) & I2C_LSR_RCV_NAK)
-                       rk29_set_nak(i2c);
+               lsr = readl(i2c->regs + I2C_LSR);
+               if((lsr & I2C_LSR_RCV_NAK) && (i != msg->len -1))
+                       return -EINVAL;
+
        }
        return ret;
 }
@@ -423,19 +411,22 @@ static int rk29_i2c_recv_msg(struct rk29_i2c_data *i2c, struct i2c_msg *msg)
        int i, ret = 0;
        unsigned long conr;
 
-       rk29_set_ack(i2c);
        conr = readl(i2c->regs + I2C_CONR);
        conr &= I2C_CONR_MRX_MODE;
+       //conr |= I2C_CONR_MPORT_ENABLE;
        writel(conr, i2c->regs + I2C_CONR);
+       
        for(i = 0; i < msg->len; i++)
        {
                writel(I2C_LCMR_RESUME, i2c->regs + I2C_LCMR);
-               if((ret = rk29_wait_event(i2c, RK2818_EVENT_MRX_NEED_ACK)) != 0)
+               if((ret = rk29_wait_event(i2c, RK29_EVENT_MRX_NEED_ACK)) != 0)
                        return ret;
                msg->buf[i] = (uint8_t)readl(i2c->regs + I2C_MRXR);
 
-               if( i == msg->len - 1)
+               if( i == msg->len -1)
                        rk29_set_nak(i2c);
+               else
+                       rk29_set_ack(i2c);
                i2c_dbg(i2c->dev, "i2c recv >>>>>>>>>>>> buf[%d]: %x\n", i, msg->buf[i]);
        }
        return ret;
@@ -446,10 +437,6 @@ static int rk29_xfer_msg(struct i2c_adapter *adap,
        struct rk29_i2c_data *i2c = (struct rk29_i2c_data *)adap->algo_data;
        int ret = 0;
        
-       #if defined (CONFIG_IOEXTEND_TCA6424)
-       struct tca6424_platform_data  *pdata = adap->dev.platform_data;
-       #endif
-       
        if(msg->len == 0)
        {
                ret = -EINVAL;
@@ -459,6 +446,7 @@ static int rk29_xfer_msg(struct i2c_adapter *adap,
 
        if((ret = rk29_send_address(i2c, msg, start))!= 0)
        {
+               rk29_set_nak(i2c);
                i2c_err(i2c->dev, "<error>rk29_send_address timeout\n");
                goto exit;
        }
@@ -474,32 +462,17 @@ static int rk29_xfer_msg(struct i2c_adapter *adap,
        {
                if((ret = rk29_i2c_send_msg(i2c, msg)) != 0)
                {
+                       rk29_set_nak(i2c);
                        i2c_err(i2c->dev, "<error>rk29_i2c_send_msg timeout\n");
                        goto exit;
                }
        }
        
 exit:  
-       if(stop || ret < 0)
-       {
-               if(ret < 0)
-                       rk29_set_nak(i2c);
-               if((ret = rk29_i2c_stop(i2c)) != 0)
-               {
-                       i2c_err(i2c->dev, "<error>rk29_i2c_stop timeout\n");
-               }
-#if 0
-               //not I2C code,add by sxj,used for extend gpio intrrupt,set SCL and SDA pin.
-               if(msg->flags & I2C_M_RD)
-               {
-                       #if defined (CONFIG_IOEXTEND_TCA6424)
-                       if (pdata && pdata->reseti2cpin) {
-                               pdata->reseti2cpin();
-                       }
-                       #endif  
-               }
-#endif                 
-       }
+       //if(stop || ret < 0)
+       //{
+               rk29_i2c_stop(i2c);                     
+       //}
        return ret;
 
 }
@@ -510,26 +483,16 @@ static int rk29_i2c_xfer(struct i2c_adapter *adap,
        int ret = -1;
        int i;
        struct rk29_i2c_data *i2c = (struct rk29_i2c_data *)adap->algo_data;
-       int retry = i2c->retry;
-       unsigned long conr = readl(i2c->regs + I2C_CONR);
+       //int retry = i2c->retry;
        /*
        if(i2c->suspended ==1)
                return -EIO;
        */
-retry:
        if(msgs[0].scl_rate <= 400000 && msgs[0].scl_rate > 0)
                i2c->scl_rate = msgs[0].scl_rate;
        else
-               i2c->scl_rate = 400000;
-       
-       conr |= I2C_CONR_MPORT_ENABLE;
-       writel(conr, i2c->regs + I2C_CONR);
-       
-       rk29_i2c_init_hw(i2c);
-       
-       conr = readl(i2c->regs + I2C_CONR);
-       conr &= I2C_CONR_ACK;
-       writel(conr, i2c->regs + I2C_CONR);
+               i2c->scl_rate = 400000; 
+       rk29_i2c_clockrate(i2c);
 
        for (i = 0; i < num; i++) 
        {
@@ -541,16 +504,15 @@ retry:
                        break;
                }
        }
-       conr = readl(i2c->regs + I2C_CONR);
-       conr &= I2C_CONR_MPORT_DISABLE;
-       writel(conr, i2c->regs + I2C_CONR);
+       /*
        if( --retry && num < 0)
        {
-               mdelay(1);
+               udelay(10000 * 1000/i2c->scl_rate);
                goto retry;
        }
+       */
        if(num < 0)
-               dev_err(i2c->dev, "i2c transfer err, client address is 0x%x", msgs[0].addr);
+               dev_err(i2c->dev, "i2c transfer err, client address is 0x%x [20110106]\n", msgs[0].addr);
        return num;
 }
 
@@ -574,21 +536,33 @@ int i2c_suspended(struct i2c_adapter *adap)
        return i2c->suspended;
 }
 EXPORT_SYMBOL(i2c_suspended);
-       
-static void rk29_i2c_init_hw(struct rk29_i2c_data *i2c)
+
+static void rk29_i2c_deinit_hw(struct rk29_i2c_data *i2c)
 {
-       unsigned long lcmr = 0x00000000;
+       unsigned long opr = readl(i2c->regs + I2C_OPR);
 
+       opr &= ~I2C_OPR_RESET_STATUS;
+       writel(opr, i2c->regs);
+       return;
+}
+static void rk29_i2c_init_hw(struct rk29_i2c_data *i2c)
+{
        unsigned long opr = readl(i2c->regs + I2C_OPR);
+       
        opr |= I2C_OPR_RESET_STATUS;
        writel(opr, i2c->regs + I2C_OPR);
+
+       udelay(10);
+       opr = readl(i2c->regs + I2C_OPR);
+       opr &= ~I2C_OPR_RESET_STATUS;
+       writel(opr, i2c->regs + I2C_OPR);
        
-       writel(lcmr, i2c->regs + I2C_LCMR);
+       rk29_i2c_clockrate(i2c); 
 
        rk29_i2c_disable_irqs(i2c);
-
-       rk29_i2c_clockrate(i2c); 
-       i2c->io_init();
+       writel(0, i2c->regs + I2C_LCMR);
+       writel(0, i2c->regs + I2C_LCMR);
+       
        opr = readl(i2c->regs + I2C_OPR);
        opr |= I2C_OPR_CORE_ENABLE;
        writel(opr, i2c->regs + I2C_OPR);
@@ -647,11 +621,7 @@ static inline void rk29_i2c_unregister_cpufreq(struct rk29_i2c_data *i2c)
 static int rk29_i2c_probe(struct platform_device *pdev)
 {
        struct rk29_i2c_data *i2c;
-#ifdef CONFIG_ARCH_RK2818
-       struct rk2818_i2c_platform_data *pdata = NULL;
-#else
        struct rk29_i2c_platform_data *pdata = NULL;
-#endif
        struct resource *res;
        int ret;
 
@@ -719,22 +689,18 @@ static int rk29_i2c_probe(struct platform_device *pdev)
                i2c->io_init = pdata->io_init;
                pdata->io_init();
        } 
-       rk29_i2c_init_hw(i2c);
 
        i2c->irq = ret = platform_get_irq(pdev, 0);
        if (ret <= 0) {
                i2c_err(&pdev->dev, "cannot find IRQ\n");
                goto err_iomap;
        }
-       if(i2c->mode == I2C_MODE_IRQ)
-       {
-               ret = request_irq(i2c->irq, rk29_i2c_irq, IRQF_DISABLED,
+       ret = request_irq(i2c->irq, rk29_i2c_irq, IRQF_DISABLED,
                                dev_name(&pdev->dev), i2c);
 
-               if (ret != 0) {
-                       i2c_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
-                       goto err_iomap;
-               }
+       if (ret != 0) {
+               i2c_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
+               goto err_iomap;
        }
        ret = rk29_i2c_register_cpufreq(i2c);
        if (ret < 0) {
@@ -750,16 +716,16 @@ static int rk29_i2c_probe(struct platform_device *pdev)
        }
 
        platform_set_drvdata(pdev, i2c);
-
-       dev_info(&pdev->dev, "%s: RK2818 I2C adapter\n", dev_name(&i2c->adap.dev));
+       rk29_i2c_init_hw(i2c);
+       
+       dev_info(&pdev->dev, "%s: RK29 I2C adapter\n", dev_name(&i2c->adap.dev));
        return 0;
 
  err_cpufreq:
        rk29_i2c_unregister_cpufreq(i2c);
 
  err_irq:
-       if(i2c->mode == I2C_MODE_IRQ)
-               free_irq(i2c->irq, i2c);
+       free_irq(i2c->irq, i2c);
 
  err_iomap:
        iounmap(i2c->regs);
@@ -782,11 +748,12 @@ static int rk29_i2c_remove(struct platform_device *pdev)
 {
        struct rk29_i2c_data *i2c = platform_get_drvdata(pdev);
 
+
+       rk29_i2c_deinit_hw(i2c);
        rk29_i2c_unregister_cpufreq(i2c);
 
        i2c_del_adapter(&i2c->adap);
-        if(i2c->mode == I2C_MODE_IRQ)
-               free_irq(i2c->irq, i2c);
+       free_irq(i2c->irq, i2c);
 
        clk_disable(i2c->clk);
        clk_put(i2c->clk);
@@ -848,6 +815,6 @@ static void __exit rk29_i2c_adap_exit(void)
 subsys_initcall(rk29_i2c_adap_init);
 module_exit(rk29_i2c_adap_exit);
 
-MODULE_DESCRIPTION("Driver for RK2818 I2C Bus");
+MODULE_DESCRIPTION("Driver for RK29 I2C Bus");
 MODULE_AUTHOR("kfx, kfx@rock-chips.com");
 MODULE_LICENSE("GPL");