update i2c driver and enable gpio pull control(PullDisable-->disable pull, PullEnable...
authorkfx <kfx@rock-chips.com>
Mon, 3 Jan 2011 11:18:25 +0000 (19:18 +0800)
committerkfx <kfx@rock-chips.com>
Mon, 3 Jan 2011 11:18:25 +0000 (19:18 +0800)
arch/arm/mach-rk29/board-rk29sdk.c
arch/arm/mach-rk29/gpio.c
arch/arm/mach-rk29/include/mach/gpio.h
drivers/i2c/busses/i2c-rk29.c

index 653cd2f41bc3a90c31d9773d6e7c688c01befece..2edc6e2a5a726d7f6c94494cab716ff4d75c3955 100755 (executable)
@@ -379,6 +379,16 @@ 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;
@@ -386,12 +396,28 @@ 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;
@@ -399,6 +425,14 @@ 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 5495c485ab408c9432fa9aa24b1371f98e4087dd..6e4a08728a4068a18df0a2cf7aa1959cc2296a03 100755 (executable)
@@ -418,15 +418,18 @@ static int GPIOPullUpDown(struct gpio_chip *chip, unsigned int offset, unsigned
                return -1;
        }
        
-       if(offset >= 8)
+       if(offset >= 32)
        {
                return -1;
        }
-
-       if(rk29_gpio->bank->id%2 == 1)
-       {
-               temp = 16;
-       }
+       temp = __raw_readl(pGrfRegBase + 0x78 +(rk29_gpio->bank->id)*4);
+       if(!enable)
+               temp |= 1<<offset;
+       else
+               temp &= ~(1<<offset);
+       //temp = (temp & (~(1 << offset)))| ((~enable) << offset);      
+       __raw_writel(temp,pGrfRegBase + 0x78 +(rk29_gpio->bank->id)*4);
+       
        return 0;
 }
 
index 7953ceb039cec6577223d8d484cd7d36a17de619..66f0534567492a7a3798b3100db5b12a8eff6919 100755 (executable)
@@ -29,10 +29,12 @@ typedef enum eGPIOPinDirection
 }eGPIOPinDirection_t;
 
 typedef enum GPIOPullType {
-       GPIONormal,
-       GPIOPullUp,
-       GPIOPullDown,
-       GPIONOInit
+       PullDisable = 0,
+       PullEnable,
+       GPIONormal,  //PullEnable, please do not use it
+       GPIOPullUp,     //PullEnable, please do not use it
+       GPIOPullDown,//PullEnable, please do not use it
+       GPIONOInit,//PullEnable, please do not use it
 }eGPIOPullType_t;
 
 typedef enum GPIOIntType {
index 45f4afb0e1fe28aa70f6b5762d8e2f8bc960f203..eafef9acc4dae177533df44f9f896b72145ff751 100755 (executable)
 
 #include "i2c-rk29.h"
 #define DRV_NAME       "rk29_i2c"
+#define RETRY_NUM      3
 
-#define RK2818_I2C_TIMEOUT             (msecs_to_jiffies(500))
+#define RK2818_I2C_TIMEOUT             (msecs_to_jiffies(100))
 #define RK2818_DELAY_TIME              2
 
 #if 0
 #define i2c_dbg(dev, format, arg...)           \
        dev_printk(KERN_INFO , dev , format , ## arg)
+#define i2c_err(dev, format, arg...)           \
+               dev_printk(KERN_ERR , dev , format , ## arg)
+
 #else
-#define i2c_dbg(dev, format, arg...)   
+#define i2c_dbg(dev, format, arg...)
+#define i2c_err(dev, format, arg...)
+
 #endif
 
 enum rk29_error {
@@ -73,6 +79,7 @@ struct rk29_i2c_data {
        struct clk                              *clk;
 
        unsigned int                    mode;
+       int                                     retry;
 
        unsigned int                    irq;
 
@@ -83,6 +90,7 @@ struct rk29_i2c_data {
 
        unsigned int                    msg_idx;
        unsigned int                    msg_num;
+       int (*io_init)(void);
 #ifdef CONFIG_CPU_FREQ
                struct notifier_block   freq_transition;
 #endif 
@@ -90,6 +98,24 @@ struct rk29_i2c_data {
 
 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);
+
+       conr &= I2C_CONR_ACK;
+       writel(conr,i2c->regs + I2C_CONR);
+       return;
+}
+static void rk29_set_nak(struct rk29_i2c_data *i2c)
+{
+       unsigned long conr = readl(i2c->regs + I2C_CONR);
+
+       conr |= I2C_CONR_NAK;
+       writel(conr,i2c->regs + I2C_CONR);
+       return;
+}
+
+
 static inline void rk29_i2c_disable_irqs(struct rk29_i2c_data *i2c)
 {
        unsigned long tmp;
@@ -170,7 +196,7 @@ static int rk29_event_occurred(struct rk29_i2c_data *i2c)
                isr &= ~I2C_ISR_ARBITR_LOSE;
                writel(isr, i2c->regs + I2C_ISR);
                i2c->cmd_err = RK2818_ERROR_ARBITR_LOSE;
-               dev_err(i2c->dev, "<error>arbitration loss\n");
+               i2c_err(i2c->dev, "<error>arbitration loss\n");
                return 1;
        }
 
@@ -239,7 +265,7 @@ static int rk29_wait_event(struct rk29_i2c_data *i2c,
        {
                if(unlikely(irqs_disabled()))
                {
-                       dev_err(i2c->dev, "irqs are disabled on this system!\n");
+                       i2c_err(i2c->dev, "irqs are disabled on this system!\n");
                        return -EIO;
                }
        }
@@ -260,7 +286,7 @@ static int rk29_wait_event(struct rk29_i2c_data *i2c,
        
        if(ret < 0)
        {
-               dev_err(i2c->dev, "i2c wait for event %04x, retrun %d \n", mr_event, ret);
+               i2c_err(i2c->dev, "i2c wait for event %04x, retrun %d \n", mr_event, ret);
                return ret;
        }
        if(ret == 0)
@@ -272,7 +298,7 @@ static int rk29_wait_event(struct rk29_i2c_data *i2c,
 
 static int rk29_wait_while_busy(struct rk29_i2c_data *i2c)
 {
-       unsigned long timeout = jiffies + RK2818_I2C_TIMEOUT;
+       unsigned long timeout = jiffies + RK2818_I2C_TIMEOUT/1000;
        unsigned long lsr;
        unsigned int time = RK2818_DELAY_TIME;
 
@@ -284,11 +310,11 @@ static int rk29_wait_while_busy(struct rk29_i2c_data *i2c)
                udelay(time);
                time *= 2;
        }
-       return -ETIMEDOUT;
+       return 0;
 }
 static int rk29_i2c_stop(struct rk29_i2c_data *i2c)
 {
-       unsigned long timeout = jiffies + RK2818_I2C_TIMEOUT;
+       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);
@@ -296,14 +322,13 @@ static int rk29_i2c_stop(struct rk29_i2c_data *i2c)
        {
                if(!(readl(i2c->regs + I2C_LCMR) & I2C_LCMR_STOP))
                {
-                       i2c_dbg(i2c->dev, "i2c stop successfully\n");
+                       udelay(100);
                        return 0;
                }
                udelay(time);
                time *= 2;
        }
-       return -ETIMEDOUT;
-    
+       return 0;
 }
 static int rk29_send_2nd_addr(struct rk29_i2c_data *i2c,
                                                struct i2c_msg *msg, int start)
@@ -321,7 +346,7 @@ static int rk29_send_2nd_addr(struct rk29_i2c_data *i2c,
        writel(I2C_LCMR_RESUME, i2c->regs + I2C_LCMR);
        if((ret = rk29_wait_event(i2c, RK2818_EVENT_MTX_RCVD_ACK)) != 0)
        {
-               dev_err(i2c->dev, "after sent addr_2nd, i2c wait for ACK timeout\n");
+               i2c_err(i2c->dev, "after sent addr_2nd, i2c wait for ACK timeout\n");
                return ret;
        }
        return ret;
@@ -342,10 +367,10 @@ static int rk29_send_address(struct rk29_i2c_data *i2c,
                addr_1st |= 0x01;
        else
                addr_1st &= (~0x01);
-
+       rk29_set_ack(i2c);
        conr |= I2C_CONR_MTX_MODE;
-       //conr &= I2C_CONR_ACK;
        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);
@@ -354,7 +379,7 @@ static int rk29_send_address(struct rk29_i2c_data *i2c,
        {
                if((ret = rk29_wait_while_busy(i2c)) != 0)
                {
-                       dev_err(i2c->dev, "i2c is busy, when send address\n");
+                       i2c_err(i2c->dev, "i2c is busy, when send address\n");
                        return ret;
                }
                writel(I2C_LCMR_START, i2c->regs + I2C_LCMR);
@@ -364,7 +389,7 @@ static int rk29_send_address(struct rk29_i2c_data *i2c,
 
        if((ret = rk29_wait_event(i2c, RK2818_EVENT_MTX_RCVD_ACK)) != 0)
        {
-               dev_err(i2c->dev, "after sent addr_1st, i2c wait for ACK timeout\n");
+               i2c_err(i2c->dev, "after sent addr_1st, i2c wait for ACK timeout\n");
                return ret;
        }
        if(start && (msg->flags & I2C_M_TEN))
@@ -380,40 +405,39 @@ static int rk29_i2c_send_msg(struct rk29_i2c_data *i2c, struct i2c_msg *msg)
        conr = readl(i2c->regs + I2C_CONR);
        conr |= I2C_CONR_MTX_MODE;
        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]);
                writel(msg->buf[i], i2c->regs + I2C_MTXR);
-               /*
-               conr = readl(i2c->regs + I2C_CONR);
-               conr &= I2C_CONR_ACK;
-               writel(conr, i2c->regs + I2C_CONR);
-               */
                writel(I2C_LCMR_RESUME, i2c->regs + I2C_LCMR);
 
                if((ret = rk29_wait_event(i2c, RK2818_EVENT_MTX_RCVD_ACK)) != 0)
                        return ret;
+               if(readl(i2c->regs + I2C_LSR) & I2C_LSR_RCV_NAK)
+                       rk29_set_nak(i2c);
        }
        return ret;
 }
 static int rk29_i2c_recv_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;
 
+       rk29_set_ack(i2c);
        conr = readl(i2c->regs + I2C_CONR);
        conr &= I2C_CONR_MRX_MODE;
        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)
                        return ret;
-               conr = readl(i2c->regs + I2C_CONR);
-               conr &= I2C_CONR_ACK;
-               writel(conr, i2c->regs + I2C_CONR);
                msg->buf[i] = (uint8_t)readl(i2c->regs + I2C_MRXR);
+
+               if( i == msg->len - 1)
+                       rk29_set_nak(i2c);
                i2c_dbg(i2c->dev, "i2c recv >>>>>>>>>>>> buf[%d]: %x\n", i, msg->buf[i]);
        }
        return ret;
@@ -422,7 +446,6 @@ static int rk29_xfer_msg(struct i2c_adapter *adap,
                                                 struct i2c_msg *msg, int start, int stop)
 {
        struct rk29_i2c_data *i2c = (struct rk29_i2c_data *)adap->algo_data;
-       unsigned long conr = readl(i2c->regs + I2C_CONR);
        int ret = 0;
        
        #if defined (CONFIG_IOEXTEND_TCA6424)
@@ -432,20 +455,20 @@ static int rk29_xfer_msg(struct i2c_adapter *adap,
        if(msg->len == 0)
        {
                ret = -EINVAL;
-               dev_err(i2c->dev, "<error>msg->len = %d\n", msg->len);
+               i2c_err(i2c->dev, "<error>msg->len = %d\n", msg->len);
                goto exit;
        }
 
        if((ret = rk29_send_address(i2c, msg, start))!= 0)
        {
-               dev_err(i2c->dev, "<error>rk29_send_address timeout\n");
+               i2c_err(i2c->dev, "<error>rk29_send_address timeout\n");
                goto exit;
        }
        if(msg->flags & I2C_M_RD)
        {       
                if((ret = rk29_i2c_recv_msg(i2c, msg)) != 0)
                {
-                       dev_err(i2c->dev, "<error>rk29_i2c_recv_msg timeout\n");
+                       i2c_err(i2c->dev, "<error>rk29_i2c_recv_msg timeout\n");
                        goto exit;
                }
        }
@@ -453,20 +476,19 @@ static int rk29_xfer_msg(struct i2c_adapter *adap,
        {
                if((ret = rk29_i2c_send_msg(i2c, msg)) != 0)
                {
-                       dev_err(i2c->dev, "<error>rk29_i2c_send_msg timeout\n");
+                       i2c_err(i2c->dev, "<error>rk29_i2c_send_msg timeout\n");
                        goto exit;
                }
        }
        
 exit:  
-       if(stop)
+       if(stop || ret < 0)
        {
-               conr = readl(i2c->regs + I2C_CONR);
-               conr |= I2C_CONR_NAK;
-               writel(conr, i2c->regs + I2C_CONR);
+               if(ret < 0)
+                       rk29_set_nak(i2c);
                if((ret = rk29_i2c_stop(i2c)) != 0)
                {
-                       dev_err(i2c->dev, "<error>rk29_i2c_stop timeout\n");
+                       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.
@@ -490,11 +512,13 @@ 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);
        /*
        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
@@ -515,13 +539,20 @@ static int rk29_i2c_xfer(struct i2c_adapter *adap,
                if (ret != 0)
                {
                        num = ret;
-                       dev_err(i2c->dev, "rk29_xfer_msg error, ret = %d\n", ret);
+                       i2c_err(i2c->dev, "rk29_xfer_msg error, ret = %d\n", ret);
                        break;
                }
        }
        conr = readl(i2c->regs + I2C_CONR);
        conr &= I2C_CONR_MPORT_DISABLE;
        writel(conr, i2c->regs + I2C_CONR);
+       if( --retry && num < 0)
+       {
+               mdelay(1);
+               goto retry;
+       }
+       if(num < 0)
+               dev_err(i2c->dev, "i2c transfer err, client address is 0x%x", msgs[0].addr);
        return num;
 }
 
@@ -559,7 +590,7 @@ static void rk29_i2c_init_hw(struct rk29_i2c_data *i2c)
        rk29_i2c_disable_irqs(i2c);
 
        rk29_i2c_clockrate(i2c); 
-
+       i2c->io_init();
        opr = readl(i2c->regs + I2C_OPR);
        opr |= I2C_OPR_CORE_ENABLE;
        writel(opr, i2c->regs + I2C_OPR);
@@ -629,15 +660,16 @@ static int rk29_i2c_probe(struct platform_device *pdev)
        pdata = pdev->dev.platform_data;
        if (!pdata) 
        {
-               dev_err(&pdev->dev, "<error>no platform data\n");
+               i2c_err(&pdev->dev, "<error>no platform data\n");
                return -EINVAL;
        }
        i2c = kzalloc(sizeof(struct rk29_i2c_data), GFP_KERNEL);
        if (!i2c) 
        {
-               dev_err(&pdev->dev, "<error>no memory for state\n");
+               i2c_err(&pdev->dev, "<error>no memory for state\n");
                return -ENOMEM;
        }
+       i2c->retry = RETRY_NUM;
        i2c->mode = pdata->mode;
        i2c->scl_rate = (pdata->scl_rate) ? pdata->scl_rate : 100000;
 
@@ -651,7 +683,7 @@ static int rk29_i2c_probe(struct platform_device *pdev)
        
        i2c->clk = clk_get(&pdev->dev, "i2c");
        if (IS_ERR(i2c->clk)) {
-               dev_err(&pdev->dev, "<error>cannot get clock\n");
+               i2c_err(&pdev->dev, "<error>cannot get clock\n");
                ret = -ENOENT;
                goto err_noclk;
        }
@@ -660,7 +692,7 @@ static int rk29_i2c_probe(struct platform_device *pdev)
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (res == NULL) {
-               dev_err(&pdev->dev, "<error>cannot find IO resource\n");
+               i2c_err(&pdev->dev, "<error>cannot find IO resource\n");
                ret = -ENOENT;
                goto err_clk;
        }
@@ -669,7 +701,7 @@ static int rk29_i2c_probe(struct platform_device *pdev)
                                         pdev->name);
 
        if (i2c->ioarea == NULL) {
-               dev_err(&pdev->dev, "<error>cannot request IO\n");
+               i2c_err(&pdev->dev, "<error>cannot request IO\n");
                ret = -ENXIO;
                goto err_clk;
        }
@@ -677,7 +709,7 @@ static int rk29_i2c_probe(struct platform_device *pdev)
        i2c->regs = ioremap(res->start, res->end - res->start + 1);
 
        if (i2c->regs == NULL) {
-               dev_err(&pdev->dev, "<error>annot map IO\n");
+               i2c_err(&pdev->dev, "<error>annot map IO\n");
                ret = -ENXIO;
                goto err_ioarea;
        }
@@ -685,13 +717,15 @@ static int rk29_i2c_probe(struct platform_device *pdev)
        i2c->adap.dev.parent = &pdev->dev;
 
        if(pdata->io_init)
+       {
+               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) {
-               dev_err(&pdev->dev, "cannot find IRQ\n");
+               i2c_err(&pdev->dev, "cannot find IRQ\n");
                goto err_iomap;
        }
        if(i2c->mode == I2C_MODE_IRQ)
@@ -700,20 +734,20 @@ static int rk29_i2c_probe(struct platform_device *pdev)
                                dev_name(&pdev->dev), i2c);
 
                if (ret != 0) {
-                       dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
+                       i2c_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
                        goto err_iomap;
                }
        }
        ret = rk29_i2c_register_cpufreq(i2c);
        if (ret < 0) {
-               dev_err(&pdev->dev, "failed to register cpufreq notifier\n");
+               i2c_err(&pdev->dev, "failed to register cpufreq notifier\n");
                goto err_irq;
        }
 
        i2c->adap.nr = pdata->bus_num;
        ret = i2c_add_numbered_adapter(&i2c->adap);
        if (ret < 0) {
-               dev_err(&pdev->dev, "failed to add bus to i2c core\n");
+               i2c_err(&pdev->dev, "failed to add bus to i2c core\n");
                goto err_cpufreq;
        }