clk: rockchip: support setting ddr clock via SCPI APIs
[firefly-linux-kernel-4.4.55.git] / drivers / gpio / tca6424.c
index ec7010708aa2b46ea07b1bdc3948bec930700d52..06e2ab9843db30d4de36bc8c164bf2aba053a163 100755 (executable)
  * GNU General Public License for more details.
  */
 /*******************************************************************/
-/*       COPYRIGHT (C)  ROCK-CHIPS FUZHOU . ALL RIGHTS RESERVED.                         */
+/*       COPYRIGHT (C)  ROCK-CHIPS FUZHOU . ALL RIGHTS RESERVED.*/
 /*******************************************************************
 FILE                   :       tca6424.c
 MODIFY         :       sxj
 DATE           :       2010-8-11
 NOTES          :
 ********************************************************************/
+#include <asm/mach/time.h>
 #include <linux/clk.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
@@ -41,38 +42,22 @@ NOTES               :
 #include <mach/board.h>
 #include <linux/delay.h>
 #include <linux/i2c/tca6424.h>
+#include <linux/ktime.h>
+#include "../drivers/gpio/expand_gpio_soft_interrupt.h"
 
 #if 0
-#define TCA6424DEB
 #define DBG(x...)      printk(KERN_INFO x)
 #else
 #define DBG(x...)
 #endif
-
-#if 1
 #define DBGERR(x...)   printk(KERN_INFO x)
-#else
-#define DBGERR(x...)
-#endif
+
 
 struct tca6424_chip {
-       /*  the first extern gpio number in all of gpio groups */
-       unsigned gpio_start;
-       unsigned gpio_pin_num;
-       /*  the first gpio irq  number in all of irq source */
-       unsigned gpio_irq_start;
-       unsigned irq_pin_num;                           //ÖжϵĸöÊý
-       unsigned irq_gpiopin;                           //¸¸ÖжϵÄÖжϺÅ
-       unsigned irq_chain;                             //¸¸ÖжϵÄÖжϺÅ
-       uint8_t reg_input[TCA6424_PortNum];
-       uint8_t reg_output[TCA6424_PortNum];
-       uint8_t reg_direction[TCA6424_PortNum];
-       uint8_t interrupt_en[TCA6424_PortNum];  // 0 dis
-       uint8_t interrupt_mask[TCA6424_PortNum];// 0 unmask
-       uint8_t inttype_set[TCA6424_PortNum];   // Inttype  enable
-       uint8_t inttype[TCA6424_PortNum];       
-       uint8_t inttype1[TCA6424_PortNum];
        
+       unsigned int gpio_start;
+       unsigned int gpio_pin_num;
+
        #ifdef TCA6424_OUTREGLOCK
                struct mutex outreglock;
        #endif
@@ -82,10 +67,10 @@ struct tca6424_chip {
        #ifdef TCA6424_CONFIGREGLOCK
                struct mutex configreglock;
        #endif
+
        struct i2c_client *client;
-       //struct extgpio_data_s *p;
-       struct tca6424_platform_data *dyn_pdata;
-       struct work_struct tca6424_work;
+       struct expand_gpio_soft_int *expand;
+       struct expand_gpio_global_variable gtca6424_struct;
        struct gpio_chip gpio_chip;
        char **names;
 };
@@ -99,14 +84,17 @@ MODULE_DEVICE_TABLE(i2c, tca6424_id);
 
 static short int portnum[TCA6424_PortNum]={ TCA6424_Port0PinNum,
                                             TCA6424_Port1PinNum,TCA6424_Port2PinNum};
-typedef struct _tca6424_access_{
-u8 portreg[TCA6424_PortNum];
-u8 accessflag[TCA6424_PortNum];//0 ²»½øÐвÙ×÷
-} tca6424_access;
 
 extern inline struct gpio_chip *gpio_to_chip(unsigned gpio);
-extern struct lock_class_key gpio_lock_class;
-struct workqueue_struct *tca6424workqueue;
+
+int tca6424_irq_read_inputreg(void *data,char *buf)
+{
+
+       struct tca6424_chip *tca6424data=(struct tca6424_chip *)data;
+       int ret = -1;
+       ret = i2c_master_reg8_recv(tca6424data->client, TCA6424_Auto_InputLevel_Reg, buf, 3, TCA6424_I2C_RATE);
+       return (ret>0)?0:ret;
+}
 
 static int tca6424_write_reg(struct i2c_client *client, uint8_t reg, uint8_t val)
 {
@@ -125,7 +113,6 @@ static int tca6424_write_reg(struct i2c_client *client, uint8_t reg, uint8_t val
        msg.len = 1 +1;
        msg.flags = client->flags;   
        msg.scl_rate = TCA6424_I2C_RATE;
-
        ret = i2c_transfer(adap, &msg, 1);
        return ret;  
 }
@@ -157,7 +144,21 @@ static int tca6424_read_reg(struct i2c_client *client, uint8_t reg, uint8_t *val
 
 }
 
-static int tca6424_gpio_direction_input(struct gpio_chip *gc, uint8_t pin_num)
+static int tca6424_write_three_reg(struct i2c_client *client, const char reg, const char *buf, int count, int rate)
+{
+       int ret = -1;
+       ret = i2c_master_reg8_send(client, reg, buf, count, rate);
+       return (ret>0)?0:ret;
+}
+
+static int tca6424_read_three_reg(struct i2c_client *client, const char reg, char *buf, int count, int rate)
+{
+       int ret = -1;
+       ret = i2c_master_reg8_recv(client, reg, buf, count, rate);
+       return (ret>0)?0:ret;
+}
+
+static int tca6424_gpio_direction_input(struct gpio_chip *gc, unsigned pin_num)
 {
        struct tca6424_chip *chip;
        uint8_t gpioPortNum;
@@ -172,39 +173,38 @@ static int tca6424_gpio_direction_input(struct gpio_chip *gc, uint8_t pin_num)
        if((gpioPortNum>=TCA6424_PortNum)||(gpioPortPinNum>=portnum[gpioPortNum]))
                return ret;
        Regaddr = TCA6424_Config_Reg+gpioPortNum;       
-
+       
        #ifdef TCA6424_CONFIGREGLOCK
        if (!mutex_trylock(&chip->configreglock))
        {
                DBGERR("**%s[%d]Did not get the configreglock**\n",__FUNCTION__,__LINE__);
-               return ret;
+               return -1;
        }
        #endif
 
-       reg_val = tca6424setbit(chip->reg_direction[gpioPortNum], gpioPortPinNum);
-       ret = tca6424_write_reg(chip->client, Regaddr, reg_val);
-       if(ret<0)
-               goto err;
-
-       chip->reg_direction[gpioPortNum] = reg_val;
+       if(((chip->gtca6424_struct.reg_direction[gpioPortNum]>>gpioPortPinNum)& 0x01)==EXTGPIO_OUTPUT)
+       {
+               reg_val = tca6424setbit(chip->gtca6424_struct.reg_direction[gpioPortNum], gpioPortPinNum);
+               ret = tca6424_write_reg(chip->client, Regaddr, reg_val);
+               if(ret<0)
+                       goto err;
+               chip->gtca6424_struct.reg_direction[gpioPortNum] = reg_val;
+               //DBG("**%s[%d],set config address[0x%2x]=%2x,ret=%d**\n",__FUNCTION__,__LINE__,Regaddr,reg_val,ret);   
+       }
 err:
-       
-       DBG("**%s[%d],config_reg=%2x,ret=%d**\n",__FUNCTION__,__LINE__,reg_val,ret);
-
        #ifdef TCA6424_CONFIGREGLOCK
-       mutex_unlock(&chip->configreglock);
+               mutex_unlock(&chip->configreglock);
        #endif
-
        return (ret<0)?-1:0;
 }
 
-static int tca6424_gpio_direction_output(struct gpio_chip *gc,uint8_t pin_num, int val)
+static int tca6424_gpio_direction_output(struct gpio_chip *gc, unsigned pin_num, int val)
 {
        struct tca6424_chip *chip;
        uint8_t gpioPortNum;
        uint8_t gpioPortPinNum;    
-       uint8_t reg_val;
-       uint8_t Regaddr;
+       uint8_t reg_val = 0;
+       uint8_t Regaddr = 0;
        int ret = -1;
        
        chip = container_of(gc, struct tca6424_chip, gpio_chip);
@@ -213,7 +213,7 @@ static int tca6424_gpio_direction_output(struct gpio_chip *gc,uint8_t pin_num, i
        if((gpioPortNum>=TCA6424_PortNum)||(gpioPortPinNum>=portnum[gpioPortNum]))
                return ret;
        Regaddr = TCA6424_Config_Reg+gpioPortNum;       
-       
+
        #ifdef TCA6424_CONFIGREGLOCK
        if (!mutex_trylock(&chip->configreglock))
        {
@@ -221,23 +221,28 @@ static int tca6424_gpio_direction_output(struct gpio_chip *gc,uint8_t pin_num, i
                return -1;
        }
        #endif
-       /* then direction */
-       reg_val = tca6424clearbit(chip->reg_direction[gpioPortNum], gpioPortPinNum);
-       DBG("**%s[%d],reg_val=%2x, Regaddr=%2x,**\n",__FUNCTION__,__LINE__,reg_val,Regaddr);    
-       ret = tca6424_write_reg(chip->client, Regaddr, reg_val);
-       if(ret<0)
+
+       if(((chip->gtca6424_struct.reg_direction[gpioPortNum]>>gpioPortPinNum)& 0x01)==EXTGPIO_INPUT)
        {
-               #ifdef TCA6424_CONFIGREGLOCK
-               mutex_unlock(&chip->configreglock);
-               #endif
-               DBGERR("**%s[%d] set direction reg is error,reg_val=%x,ret=%d**\n",__FUNCTION__,__LINE__,reg_val,ret);
+               reg_val = tca6424clearbit(chip->gtca6424_struct.reg_direction[gpioPortNum], gpioPortPinNum);
+               //DBG("**%s[%d],set config address[0x%2x]=%2x,**\n",__FUNCTION__,__LINE__,Regaddr,reg_val);     
+               ret = tca6424_write_reg(chip->client, Regaddr, reg_val);
+               if(ret<0)
+               {
+                       #ifdef TCA6424_CONFIGREGLOCK
+                       mutex_unlock(&chip->configreglock);
+                       #endif
+                       DBGERR("**%s[%d] set direction reg is error,reg_val=%x,ret=%d**\n",__FUNCTION__,__LINE__,reg_val,ret);
                return ret;
+               }
+               chip->gtca6424_struct.reg_direction[gpioPortNum] = reg_val;
        }
-       chip->reg_direction[gpioPortNum] = reg_val;
+       
        #ifdef TCA6424_CONFIGREGLOCK
        mutex_unlock(&chip->configreglock);
        #endif
-    ret=-1;
+       
+       ret = -1;
     #ifdef TCA6424_OUTREGLOCK
        if (!mutex_trylock(&chip->outreglock))
        {
@@ -245,78 +250,73 @@ static int tca6424_gpio_direction_output(struct gpio_chip *gc,uint8_t pin_num, i
                return ret;
        }
        #endif
-       /* set output level */
-       if (val)
-               reg_val = tca6424setbit(chip->reg_output[gpioPortNum], gpioPortPinNum);
-       else
-               reg_val = tca6424clearbit(chip->reg_output[gpioPortNum], gpioPortPinNum);
 
-       Regaddr = TCA6424_OutputLevel_Reg+gpioPortNum;  
-       ret = tca6424_write_reg(chip->client, Regaddr, reg_val);
-       if (ret<0)
+       if(((chip->gtca6424_struct.reg_output[gpioPortNum]>>gpioPortPinNum)& 0x01) != val)
        {
-               #ifdef TCA6424_OUTREGLOCK
-                       mutex_unlock(&chip->outreglock);
-               #endif
-               DBGERR("**%s[%d] set out reg is error,reg_val=%x,ret=%d**\n",__FUNCTION__,__LINE__,reg_val,ret);
-               return ret;
+               if (val)
+                       reg_val = tca6424setbit(chip->gtca6424_struct.reg_output[gpioPortNum], gpioPortPinNum);
+               else
+                       reg_val = tca6424clearbit(chip->gtca6424_struct.reg_output[gpioPortNum], gpioPortPinNum);
+
+               Regaddr = TCA6424_OutputLevel_Reg+gpioPortNum;  
+               ret = tca6424_write_reg(chip->client, Regaddr, reg_val);
+               if (ret<0)
+               {
+                       #ifdef TCA6424_OUTREGLOCK
+                               mutex_unlock(&chip->outreglock);
+                       #endif
+                       DBGERR("**%s[%d] set out reg is error,reg_val=%x,ret=%d**\n",__FUNCTION__,__LINE__,reg_val,ret);
+                       return ret;
+               }
+               chip->gtca6424_struct.reg_output[gpioPortNum] = reg_val;
        }
-       chip->reg_output[gpioPortNum] = reg_val;
 
        #ifdef TCA6424_OUTREGLOCK
                mutex_unlock(&chip->outreglock);
        #endif
-       
-       DBG("**%s[%d],output_reg=%2x,ret=%d**\n",__FUNCTION__,__LINE__,reg_val,ret);    
+       //DBG("**%s[%d],set output address[0x%2x]=%2x,ret=%d**\n",__FUNCTION__,__LINE__,Regaddr,reg_val,ret);   
     return (ret<0)?-1:0;
 }
 
-static int tca6424_gpio_get_value(struct gpio_chip *gc, uint8_t pin_num)
+static int tca6424_gpio_get_value(struct gpio_chip *gc, unsigned pin_num)
 {
        struct tca6424_chip *chip;
        uint8_t gpioPortNum;
        uint8_t gpioPortPinNum;
-       uint8_t reg_val;
        uint8_t Regaddr;
-       int ret=-1;
+       int ret;
 
        chip = container_of(gc, struct tca6424_chip, gpio_chip);
-       gpioPortNum = pin_num/8;
-       gpioPortPinNum= pin_num%8;
-
-       if((gpioPortNum>=TCA6424_PortNum)||(gpioPortPinNum>=portnum[gpioPortNum]))
-               return -1;
-
-       Regaddr = TCA6424_InputLevel_Reg+gpioPortNum;   
 
-       if(!tca6424getbit(chip->reg_direction[gpioPortNum],gpioPortPinNum))  //ÅжϸÃpinÊÇ·ñÉèÖóÉÊä³ö
-       {
-               DBG("**it is a output pin**\n");
-               return -1;
-       }
-       #ifdef TCA6424_INPUTREGLOCK
-       if (!mutex_trylock(&chip->inputreglock))
+       #ifdef CONFIG_EXPAND_GPIO_SOFT_INTERRUPT
+       ret = wait_untill_input_reg_flash( );
+       if(ret<0)
        {
-               DBGERR("**%s[%d]Did not get the inputreglock**\n",__FUNCTION__,__LINE__);
                return -1;
+               DBGERR("**********tca6424 get value error***************\n");
        }
        #endif
+       
+       gpioPortNum = pin_num/8;
+       gpioPortPinNum= pin_num%8;
+       Regaddr = TCA6424_OutputLevel_Reg+gpioPortNum;  
+       
+       if((gpioPortNum>=TCA6424_PortNum)||(gpioPortPinNum>=portnum[gpioPortNum]))
+               return -1;
 
+       #ifndef CONFIG_EXPAND_GPIO_SOFT_INTERRUPT
+       uint8_t reg_val;
        ret = tca6424_read_reg(chip->client, Regaddr, &reg_val);
        if (ret < 0) 
-               goto err;
-       chip->reg_input[gpioPortNum] = reg_val;
-       
-err:
-       #ifdef TCA6424_CONFIGREGLOCK
-               mutex_unlock(&chip->inputreglock);
+               return -1;
+       chip->gtca6424_struct.reg_input[gpioPortNum] = reg_val;
        #endif
-       DBGERR("**%s[%d] input_reg=%2x,ret=%d**\n",__FUNCTION__,__LINE__,reg_val,ret);
 
-       return (ret < 0)?-1:((chip->reg_input[gpioPortNum] >> gpioPortPinNum) & 0x01);
+       //DBG("**%s[%d] read input address[0x%2x]=%2x**\n",__FUNCTION__,__LINE__,Regaddr,chip->reg_input[gpioPortNum]);
+       return ((chip->gtca6424_struct.reg_input[gpioPortNum] >> gpioPortPinNum) & 0x01);
 }
 
-static void tca6424_gpio_set_value(struct gpio_chip *gc, uint8_t pin_num, int val)
+static void tca6424_gpio_set_value(struct gpio_chip *gc, unsigned pin_num, int val)
 {
        struct tca6424_chip *chip;
        uint8_t gpioPortNum;
@@ -324,365 +324,78 @@ static void tca6424_gpio_set_value(struct gpio_chip *gc, uint8_t pin_num, int va
        uint8_t reg_val;
        uint8_t Regaddr;
        int ret=-1;
-       DBG("**run in the %s**\n",__FUNCTION__);
-
+       
        chip = container_of(gc, struct tca6424_chip, gpio_chip);
-
        gpioPortNum = pin_num/8;
        gpioPortPinNum= pin_num%8;
-
        if((gpioPortNum>=TCA6424_PortNum)||(gpioPortPinNum>=portnum[gpioPortNum]))
-               return;// -1;
-
+               return;
        Regaddr = TCA6424_OutputLevel_Reg+gpioPortNum;  
-       
-       if(tca6424getbit(chip->reg_direction[gpioPortNum],gpioPortPinNum)) // input state
-               return;// -1;
-
-#ifdef TCA6424_OUTREGLOCK
+       if(tca6424getbit(chip->gtca6424_struct.reg_direction[gpioPortNum],gpioPortPinNum)) // input state
+       {
+               return;
+       }
+               
+       #ifdef TCA6424_OUTREGLOCK
        if (!mutex_trylock(&chip->outreglock))
        {
                DBGERR("**%s[%d] Did not get the outreglock**\n",__FUNCTION__,__LINE__);
-               return;// -1;
+               return;
        }
-#endif
-       if (val)
-               reg_val = tca6424setbit(chip->reg_output[gpioPortNum], gpioPortPinNum);
-       else
-               reg_val = tca6424clearbit(chip->reg_output[gpioPortNum], gpioPortPinNum);
+       #endif
+       if(((chip->gtca6424_struct.reg_output[gpioPortNum]>>gpioPortPinNum)& 0x01) != val)
+       {
+               if(val)
+                       reg_val = tca6424setbit(chip->gtca6424_struct.reg_output[gpioPortNum], gpioPortPinNum);
+               else
+                       reg_val = tca6424clearbit(chip->gtca6424_struct.reg_output[gpioPortNum], gpioPortPinNum);
 
-       ret = tca6424_write_reg(chip->client, Regaddr, reg_val);
-       if (ret<0)
-               goto err;
-       chip->reg_output[gpioPortNum] = reg_val;
-       
+               ret = tca6424_write_reg(chip->client, Regaddr, reg_val);
+               if (ret<0)
+                       goto err;
+               chip->gtca6424_struct.reg_output[gpioPortNum] = reg_val;
+               //DBG("**%s[%d],set output address[0x%2x]=%2x,ret=%d**\n",__FUNCTION__,__LINE__,Regaddr,reg_val,ret);
+       }
 err: 
        #ifdef TCA6424_OUTREGLOCK
                mutex_unlock(&chip->outreglock);
        #endif
-       
-       DBG("**%s[%d],output_reg=%2x,ret=%d**\n",__FUNCTION__,__LINE__,reg_val,ret);
-       return;// (ret<0)?-1:0;
-       
-}
-static int tca6424_gpio_to_irq(struct gpio_chip *chip,unsigned offset)
-{
-    struct tca6424_chip *pca_chip = container_of(chip, struct tca6424_chip, gpio_chip);
-       if(((pca_chip->gpio_start+offset)>=chip->base)&&((pca_chip->gpio_start+offset)<(chip->base+chip->ngpio)))
-       {
-               //DBG("**%s,offset=%d,gpio_irq_start=%d,base=%d,ngpio=%d,gpio_irq_start=%d**\n",
-               //      __FUNCTION__,offset,pca_chip->gpio_irq_start,chip->base,chip->ngpio,pca_chip->gpio_irq_start);
-               return (offset+pca_chip->gpio_irq_start);
-       }
-       else
-       {
-               return -1;
-       }
+       return;
 }
 
 int tca6424_checkrange(int start,int num,int val)
-{
-   
+{   
        if((val<(start+num))&&(val>=start))
                return 0;
-       else return -1;
-
-}
-
-static void tca6424_gpio_irq_enable(unsigned irq)
-{
-       struct irq_desc *desc = irq_to_desc(irq);
-       //int gpiopinnum;
-       struct tca6424_chip *pchip=(struct tca6424_chip *)desc->chip_data;
-       //struct gpio_chip *chip_gpio;
-       uint8_t gpio_num;
-       uint8_t gpioPortNum;
-       uint8_t gpioPortPinNum;    
-       uint8_t tca6424pinnum;
-
-
-       if(!tca6424_checkrange(pchip->gpio_irq_start,pchip->irq_pin_num,irq))
-       {
-               tca6424pinnum = irq-pchip->gpio_irq_start;
-       }
-       else 
-       {
-               return;
-       }
-       gpioPortNum = tca6424pinnum/8;
-       gpioPortPinNum= tca6424pinnum%8;
-       gpio_num=pchip->gpio_start+tca6424pinnum;
-       if((gpioPortNum>=TCA6424_PortNum)||(gpioPortPinNum>=portnum[gpioPortNum]))
-               return;
-       DBG("**%s**\n",__FUNCTION__);
-       pchip->interrupt_en[gpioPortNum]=tca6424setbit(pchip->interrupt_en[gpioPortNum],gpioPortPinNum);        
-}
-static void tca6424_gpio_irq_disable(unsigned irq)
-{
-       struct irq_desc *desc = irq_to_desc(irq);
-       struct tca6424_chip *pchip=(struct tca6424_chip *)desc->chip_data;
-       uint8_t gpioPortNum;
-       uint8_t gpioPortPinNum;    
-       uint8_t tca6424pinnum;
-
-       if(!tca6424_checkrange(pchip->gpio_irq_start,pchip->irq_pin_num,irq))
-       {
-               tca6424pinnum=irq-pchip->gpio_irq_start;//irq_to_gpio(irq)
-       }
-       else 
-       {
-               return;
-       }
-       gpioPortNum = tca6424pinnum/8;
-       gpioPortPinNum= tca6424pinnum%8;
-
-       if((gpioPortNum>=TCA6424_PortNum)||(gpioPortPinNum>=portnum[gpioPortNum]))
-               return;
-       DBG("**%s**\n",__FUNCTION__);
-
-       pchip->interrupt_en[gpioPortNum]=tca6424clearbit(pchip->interrupt_en[gpioPortNum],gpioPortPinNum);
-               
-}
-
-
-static void tca6424_gpio_irq_mask(unsigned irq)
-{
-       struct irq_desc *desc = irq_to_desc(irq);
-       struct tca6424_chip *pchip=(struct tca6424_chip *)desc->chip_data;
-       uint8_t gpioPortNum;
-       uint8_t gpioPortPinNum;    
-       uint8_t tca6424pinnum;
-
-       if(!tca6424_checkrange(pchip->gpio_irq_start,pchip->irq_pin_num,irq))
-       {
-               tca6424pinnum=irq-pchip->gpio_irq_start;//irq_to_gpio(irq)
-       }
        else 
-       {
-               return;
-       }
-       gpioPortNum = tca6424pinnum/8;
-       gpioPortPinNum= tca6424pinnum%8;
-       
-       if((gpioPortNum>=TCA6424_PortNum)||(gpioPortPinNum>=portnum[gpioPortNum]))
-               return;
-
-       DBG("**%s**\n",__FUNCTION__);
-
-       pchip->interrupt_mask[gpioPortNum]=tca6424setbit(pchip->interrupt_mask[gpioPortNum],gpioPortPinNum);
-               
-}
-
-static void tca6424_gpio_irq_unmask(unsigned irq)
-{
-       struct irq_desc *desc = irq_to_desc(irq);
-       //int gpiopinnum;//=irq_to_gpio(irq);
-       struct tca6424_chip *pchip=(struct tca6424_chip *)desc->chip_data;
-       uint8_t gpioPortNum;
-       uint8_t gpioPortPinNum;    
-       uint8_t tca6424pinnum;
-
-       DBG("**%s**\n",__FUNCTION__);
-
-    if(!tca6424_checkrange(pchip->gpio_irq_start,pchip->irq_pin_num,irq))
-    {
-               tca6424pinnum=irq-pchip->gpio_irq_start;//irq_to_gpio(irq)
-       }
-       else 
-       {
-               return;
-       }
-       gpioPortNum = tca6424pinnum/8;
-       gpioPortPinNum= tca6424pinnum%8;
-       
-       if((gpioPortNum>=TCA6424_PortNum)||(gpioPortPinNum>=portnum[gpioPortNum]))
-               return;
-       pchip->interrupt_mask[gpioPortNum]=tca6424clearbit(pchip->interrupt_mask[gpioPortNum],gpioPortPinNum);
-}
-
-static int tca6424_gpio_irq_type(unsigned int irq, unsigned int type)
-{
-       struct irq_desc *desc_irq=irq_to_desc(irq);
-       struct tca6424_chip *pchip=(struct tca6424_chip *)desc_irq->chip_data;
-       //struct gpio_chip *chip_gpio;
-       int gpio_num;
-       uint8_t gpioPortNum;
-       uint8_t gpioPortPinNum;    
-       uint8_t tca6424pinnum;
-       if(!tca6424_checkrange(pchip->gpio_irq_start,pchip->irq_pin_num,irq))
-       {
-               tca6424pinnum=irq-pchip->gpio_irq_start;//irq_to_gpio(irq)
-               gpio_num=pchip->gpio_start+tca6424pinnum;
-       }
-       else
                return -1;
-
-       gpioPortNum = tca6424pinnum/8;
-       gpioPortPinNum= tca6424pinnum%8;
-        //DBG("**%s %d gpio_num=%d,PortNum=%d,PortPinNum=%d**\n",__FUNCTION__,__LINE__,gpio_num,gpioPortNum,gpioPortPinNum);
-       switch (type) {
-               case IRQ_TYPE_NONE:
-                       pchip->inttype_set[gpioPortNum]=tca6424clearbit(pchip->inttype_set[gpioPortNum],gpioPortPinNum);
-                       DBG("**%s IRQ_TYPE_NONE**\n",__FUNCTION__);
-                       break;
-               case IRQ_TYPE_EDGE_RISING:
-                       pchip->inttype_set[gpioPortNum]=tca6424setbit(pchip->inttype_set[gpioPortNum],gpioPortPinNum);
-                       pchip->inttype[gpioPortNum]=tca6424setbit(pchip->inttype[gpioPortNum],gpioPortPinNum);
-                       pchip->inttype1[gpioPortNum]=tca6424clearbit(pchip->inttype1[gpioPortNum],gpioPortPinNum);
-                       DBG("**%s IRQ_TYPE_EDGE_RISING,inttype=%x,inttype1=%x**\n",__FUNCTION__,pchip->inttype[gpioPortNum],pchip->inttype1[gpioPortNum]);
-
-               break;
-               case IRQ_TYPE_EDGE_FALLING:
-                       pchip->inttype_set[gpioPortNum]=tca6424setbit(pchip->inttype_set[gpioPortNum],gpioPortPinNum);
-                       pchip->inttype[gpioPortNum]=tca6424clearbit(pchip->inttype[gpioPortNum],gpioPortPinNum);
-                       pchip->inttype1[gpioPortNum]=tca6424clearbit(pchip->inttype1[gpioPortNum],gpioPortPinNum);      
-                       DBG("**%s IRQ_TYPE_EDGE_RISING,inttype=%x,inttype1=%x**\n",__FUNCTION__,pchip->inttype[gpioPortNum],pchip->inttype1[gpioPortNum]);
-
-               break;
-               case IRQ_TYPE_EDGE_BOTH:
-                       pchip->inttype_set[gpioPortNum]=tca6424setbit(pchip->inttype_set[gpioPortNum],gpioPortPinNum);
-                       pchip->inttype1[gpioPortNum]=tca6424setbit(pchip->inttype1[gpioPortNum],gpioPortPinNum);
-                       DBG("**%s IRQ_TYPE_EDGE_RISING,inttype=%x,inttype1=%x**\n",__FUNCTION__,pchip->inttype[gpioPortNum],pchip->inttype1[gpioPortNum]);
-               break;
-               case IRQ_TYPE_LEVEL_HIGH:
-                       pchip->inttype_set[gpioPortNum]=tca6424clearbit(pchip->inttype_set[gpioPortNum],gpioPortPinNum);
-                       DBG("extern gpios does not support IRQ_TYPE_LEVEL_HIGH irq typ");
-               break;
-               case IRQ_TYPE_LEVEL_LOW:
-                       pchip->inttype_set[gpioPortNum]=tca6424clearbit(pchip->inttype_set[gpioPortNum],gpioPortPinNum);
-                       DBG("extern gpios does not support IRQ_TYPE_LEVEL_LOW irq typ");
-               break;
-               default:
-               return -EINVAL;
-       }
-return 0;
 }
 
-static int tca6424_gpio_irq_set_wake(unsigned irq, unsigned state)
+static int tca6424_gpio_to_irq(struct gpio_chip *chip,unsigned offset)
 {
-    //no irq wake
-       return 0;
-
-}
-static struct irq_chip tca6424_gpio_irqchip = {
-       .name           = "extend_gpio_tca6424",
-       .enable         = tca6424_gpio_irq_enable,
-       .disable        = tca6424_gpio_irq_disable,
-       .mask           = tca6424_gpio_irq_mask,
-       .unmask         = tca6424_gpio_irq_unmask,
-       .set_type       = tca6424_gpio_irq_type,        
-       .set_wake       = tca6424_gpio_irq_set_wake,
-};
-
-
-static void tca6424_extend_gpio_irq_handler(struct work_struct *work)
-{      
-    struct tca6424_chip *pchip = container_of(work, struct tca6424_chip,tca6424_work);
-       u8 tempintputreg[TCA6424_PortNum]={0,0,0};
-       u8 tempallowint=0;                      
-       u8 levelchg=0;                  
-       u8 intbit=0;                    
-       u8 tempinttype=0;
-       int i,j;
-       struct irq_desc *gpio_irq_desc;
-       unsigned int irq;
-       if(tca6424_read_reg(pchip->client,TCA6424_InputLevel_Reg,&tempintputreg[0])<0)
-       {
-       
-               DBG("**%s[%d] reading reg is error\n",__FUNCTION__,__LINE__); 
-               enable_irq(pchip->irq_chain);
-               return;
-       }
-       if(tca6424_read_reg(pchip->client,(TCA6424_InputLevel_Reg+1),&tempintputreg[1])<0)
+    struct tca6424_chip *pchip = container_of(chip, struct tca6424_chip, gpio_chip);
+       if(((pchip->gpio_start+offset)>=chip->base)&&((pchip->gpio_start+offset)<(chip->base+chip->ngpio)))
        {
-       
-               DBG("**%s[%d] reading reg is error\n",__FUNCTION__,__LINE__); 
-               enable_irq(pchip->irq_chain);
-               return;
-       }
-       if(tca6424_read_reg(pchip->client,(TCA6424_InputLevel_Reg+2),&tempintputreg[2])<0)
-       {
-       
-               DBG("**%s[%d] reading reg is error\n",__FUNCTION__,__LINE__); 
-               enable_irq(pchip->irq_chain);
-               return;
-       }
-       DBG("**has run at %s**,tempintreg[0] = %x,tempintreg[1] = %x,tempintreg[2] = %x\n",__FUNCTION__,tempintputreg[0],tempintputreg[1],tempintputreg[2]);
-       if((pchip->interrupt_en[0]==0)&&(pchip->interrupt_en[1]==0)&&(pchip->interrupt_en[2]==0))
-       {
-               memcpy(&pchip->reg_input[0],&tempintputreg[0],sizeof(tempintputreg));
-               DBGERR("there are no pin reg irq\n"); 
-               enable_irq(pchip->irq_chain);
-               return;
+               //DBG("**%s,offset=%d,gpio_irq_start=%d,base=%d,ngpio=%d,gpio_irq_start=%d**\n",
+               //      __FUNCTION__,offset,pchip->expand->gpio_irq_start,chip->base,chip->ngpio,pchip->expand->gpio_irq_start);
+               return (offset+pchip->expand->gpio_irq_start);
        }
-
-       for(i=0;i<TCA6424_PortNum;i++)
+       else
        {
-               tempallowint=pchip->interrupt_en[i]&pchip->reg_direction[i]&(~pchip->interrupt_mask[i]);// Âú×ãÖжÏÌõ¼þ
-               levelchg=pchip->reg_input[i]^tempintputreg[i];// ÕÒ³öÇ°ºó״̬²»Ò»ÑùµÄpin
-               tempinttype=~(tempintputreg[i]^pchip->inttype[i]);// ÕÒ³ö´¥·¢×´Ì¬ºÍµ±Ç°pin״̬һÑùµÄpin£¬×¢ÒâÖ»Ö§³Ölow highÁ½ÖÖpin´¥·¢
-
-           tempinttype=(~pchip->inttype1[i])&tempinttype;// inttype1 ÎªÕæµÄλ¶ÔÓ¦µÄtempinttypeλÇåÁ㣬ÒòΪ¸ÃλֻÊÜinttype1¿ØÖÆ
-               tempinttype|=pchip->inttype1[i];//µçƽֻҪÊDZ仯¾Í²úÉúÖжÏ
-               tempinttype&=pchip->inttype_set[i];//ÒѾ­ÉèÖÃÁËtypeÀàÐÍ
-
-               intbit=tempallowint&levelchg&tempinttype;
-               DBG(" tempallowint=%x,levelchg=%x,tempinttype=%x,intbit=%d\n",tempallowint,levelchg,tempinttype,intbit);
-
-               if(intbit)
-               for(j=0;j<portnum[i];j++)
-               {
-                       if(tca6424getbit(intbit,j))
-                       {
-                               irq=pchip->gpio_irq_start+TCA6424_PortPinNum*i+j;
-                               gpio_irq_desc = irq_to_desc(irq);
-                               gpio_irq_desc->chip->mask(irq);
-                               generic_handle_irq(irq);
-                               gpio_irq_desc->chip->unmask(irq);
-                               DBG("tca6424_i2c_irq_handler port=%d,pin=%d,pinlevel=%d\n",i,j,tca6424getbit(tempintputreg[i],j));
-                       }
-               }
-               
-               pchip->reg_input[i]=tempintputreg[i];
-
+               return -1;
        }
-       enable_irq(pchip->irq_chain);
-       return;
-}
-
-static irqreturn_t tca6424_gpio_irq_handler(int irq, void * dev_id)
-{
-
-       struct irq_desc *gpio_irq_desc = irq_to_desc(irq);
-       struct tca6424_chip *pchip=(struct tca6424_chip *)gpio_irq_desc->chip_data;
-
-       DBG("******************%s*******************\n",__FUNCTION__);
-       disable_irq_nosync(pchip->irq_chain);
-    queue_work(tca6424workqueue,&pchip->tca6424_work);
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t test_handler(int irq, void * dev_id)
-{
-
-       DBG("******************%s*******************\n",__FUNCTION__);
-       return IRQ_HANDLED;
 }
 
 static void tca6424_setup_gpio(struct tca6424_chip *chip, int gpios)
 {
     struct gpio_chip *gc;
-
     gc = &chip->gpio_chip;
-       
     gc->direction_input  = tca6424_gpio_direction_input;
     gc->direction_output = tca6424_gpio_direction_output;
     gc->get = tca6424_gpio_get_value;
     gc->set = tca6424_gpio_set_value;
     gc->to_irq = tca6424_gpio_to_irq;
-
     gc->can_sleep = 1;
-
     gc->base = chip->gpio_start;
     gc->ngpio = chip->gpio_pin_num;
     gc->label = chip->client->name;
@@ -691,69 +404,17 @@ static void tca6424_setup_gpio(struct tca6424_chip *chip, int gpios)
     gc->names = chip->names;
 }
 
-static void tca6424_gpio_irq_setup(struct tca6424_chip *pchip)
-{
-    unsigned        pioc, irq_num;
-    int ret;
-       int testprint1 = 0;
-       int testprint2 = 0;
-       struct irq_desc *desc;
-    irq_num = pchip->gpio_irq_start;   //ÖжϺţ¬À©Õ¹ioµÄÖжϺÅÓ¦¸Ã½ô¸úÔÚÄÚ²¿ioÖжϺŵĺóÃæ¡£ÈçrkÄÚ²¿ÖжÏ48¸ö£¬¼ÓÉÏÄÚ²¿gpio 16¸öÐéÄâÖжϣ¬ÕâÀïpinÓ¦¸Ã´Ó48+16¿ªÊ¼
-
-    for (pioc = 0; pioc < pchip->irq_pin_num; pioc++,irq_num++)
-    {
-        lockdep_set_class(&irq_desc[irq_num].lock, &gpio_lock_class);
-        /*
-         * Can use the "simple" and not "edge" handler since it's
-         * shorter, and the AIC handles interrupts sanely.
-        */
-               testprint1 = set_irq_chip(irq_num, &tca6424_gpio_irqchip);   
-               set_irq_handler(irq_num, handle_simple_irq);
-               testprint2 =  set_irq_chip_data(irq_num,(void *)pchip);
-               desc = irq_to_desc(irq_num);
-               DBG("**%s line=%d,test1=%d,test2=%d,desc=%x,chipdate=%x,pchip=%x,irq_num=%d**\n",__FUNCTION__,__LINE__,testprint1,testprint2,desc,desc->chip_data,pchip,irq_num);
-               set_irq_flags(irq_num, IRQF_VALID);       
-    }
-       ret = gpio_request(pchip->irq_gpiopin,NULL);
-       if(ret!=0)
-       {
-               gpio_free(pchip->irq_gpiopin);
-               DBG("tca6424_gpio_irq_setup request gpio is err\n");
-       }
-       
-       gpio_pull_updown(pchip->irq_gpiopin, GPIOPullUp);        //gpio ÐèÒªÀ­¸ßirq_to_gpio(pchip->irq_chain)
-
-#if 0
-
-       set_irq_chip_data(pchip->irq_chain, pchip);
-       set_irq_chained_handler(pchip->irq_chain, gpio_irq_handlerxxx);
-       set_irq_type(pchip->irq_chain,IRQ_TYPE_LEVEL_LOW);
-       enable_irq(pchip->irq_chain);
-
-#else
-       tca6424workqueue=create_workqueue("tca6424 workqueue");
-       INIT_WORK(&pchip->tca6424_work,tca6424_extend_gpio_irq_handler);
-       
-       set_irq_chip_data(pchip->irq_chain, pchip);
-       if(request_irq(pchip->irq_chain,tca6424_gpio_irq_handler, IRQF_TRIGGER_LOW, "tca6424", pchip)!=0)
-       {
-               DBG("**%s line=%d is err**\n",__FUNCTION__,__LINE__);
-       }
-
-#endif
-}
-
 int tca6424_init_pintype(struct tca6424_chip *chip,struct i2c_client *client)
 {
-    int i;
        struct tca6424_platform_data *platform_data=(struct tca6424_platform_data *)client->dev.platform_data;
        struct rk2818_gpio_expander_info *tca6424_gpio_settinginfo;
        uint8_t reg_output[TCA6424_PortNum]={0,0,0};
        uint8_t reg_direction[TCA6424_PortNum]={0,0,0};
+       uint8_t reg_invert[TCA6424_PortNum]={0,0,0};
        uint8_t tca6424_pin_num;
        uint8_t gpioPortNum;
        uint8_t gpioPortPinNum,tca6424_settingpin_num=0;
-
+       int i = 0;
        if(platform_data)
        {
                tca6424_gpio_settinginfo=platform_data->settinginfo;
@@ -776,15 +437,10 @@ int tca6424_init_pintype(struct tca6424_chip *chip,struct i2c_client *client)
                                        }
                                        else
                                        {
-                                               reg_direction[gpioPortNum]=tca6424clearbit(reg_direction[gpioPortNum],gpioPortPinNum);
                                                if(tca6424_gpio_settinginfo[i].pin_value==GPIO_HIGH)
                                                {
                                                        reg_output[gpioPortNum]=tca6424setbit(reg_output[gpioPortNum],gpioPortPinNum);
                                                }
-                                               else
-                                               {
-                                                       reg_output[gpioPortNum]=tca6424clearbit(reg_output[gpioPortNum],gpioPortPinNum);
-                                               }
                                        }
                                        
                                }
@@ -801,63 +457,40 @@ int tca6424_init_pintype(struct tca6424_chip *chip,struct i2c_client *client)
        mutex_init(&chip->configreglock);
        #endif
 
+       if(tca6424_write_three_reg(client, TCA6424_Auto_Config_Reg , &reg_direction[0], 3, TCA6424_I2C_RATE)<0)
+       {
+               DBGERR("*%s %d* write reg err\n",__FUNCTION__,__LINE__);
+               return -1;
+       }
+       if (tca6424_write_three_reg(client, TCA6424_Auto_OutputLevel_Reg, &reg_output[0], 3, TCA6424_I2C_RATE)<0)
+       {
+               DBGERR("*%s %d* write reg err\n",__FUNCTION__,__LINE__);
+               return -1;
+       }
+       if (tca6424_write_three_reg(client, TCA6424_Auto_Invert_Reg, &reg_invert[0], 3, TCA6424_I2C_RATE)<0)            //make sure this reg be 0
+       {
+               DBGERR("*%s %d* write reg err\n",__FUNCTION__,__LINE__);
+               return -1;
+       }
+       if(tca6424_read_three_reg(client, TCA6424_Auto_InputLevel_Reg, &chip->gtca6424_struct.reg_input[0], 3, TCA6424_I2C_RATE)<0)
+       {
+               DBGERR("*%s %d  read reg err*\n",__FUNCTION__,__LINE__);
+               return -1;
+       }         
        for(i=0; i<TCA6424_PortNum; i++)
        {
-       
-               if (tca6424_write_reg(client, (TCA6424_Config_Reg+i), reg_direction[i])<0)
-               {
-                       DBGERR("*%s %d* write reg err\n",__FUNCTION__,__LINE__);
-                       return -1;
-               }
-               chip->reg_direction[i]=reg_direction[i];
-               if (tca6424_write_reg(client, (TCA6424_OutputLevel_Reg+i), reg_output[i])<0)
-               {
-                       DBGERR("*%s %d  write reg err*\n",__FUNCTION__,__LINE__);
-                       return -1;
-               }
-               chip->reg_output[i]=reg_output[i];
-
-               if (tca6424_write_reg(client, (TCA6424_Invert_Reg+i), 0)<0)             //make sure this reg be 0
-               {
-                       DBGERR("*%s %d* write reg err\n",__FUNCTION__,__LINE__);
-                       return -1;
-               }
-       
-               if(tca6424_read_reg(client, (TCA6424_InputLevel_Reg+i), &chip->reg_input[i])<0)
-               {
-                       DBGERR("*%s %d  read reg err*\n",__FUNCTION__,__LINE__);
-                       return -1;
-               }         
-               //DBG("reg_direction=%x,reg_output=%x,reg_input=%x\n",chip->reg_direction[i],chip->reg_output[i],chip->reg_input[i]);
-
+               chip->gtca6424_struct.reg_direction[i]=reg_direction[i];
+               chip->gtca6424_struct.reg_output[i]=reg_output[i];
+               DBG("reg_direction=%x,reg_output=%x,reg_input=%x\n",chip->gtca6424_struct.reg_direction[i],chip->gtca6424_struct.reg_output[i],chip->gtca6424_struct.reg_input[i]);
        }
-
        return 0;
 }
-void tca6424_reset_itr(void)
-{
-               gpio_request(RK2818_PIN_PE6,NULL);
-               gpio_request(RK2818_PIN_PE7,NULL);
-
-               rk2818_mux_api_set(GPIOE_U1IR_I2C1_NAME, IOMUXA_GPIO1_A67);
-               gpio_direction_output(RK2818_PIN_PE6,GPIO_HIGH);
-               gpio_direction_output(RK2818_PIN_PE7,GPIO_LOW);
-               udelay(3);
-               gpio_set_value(RK2818_PIN_PE7,GPIO_HIGH);
-               udelay(1);
-               rk2818_mux_api_set(GPIOE_U1IR_I2C1_NAME, IOMUXA_I2C1);
-               
-               gpio_free(RK2818_PIN_PE6);
-               gpio_free(RK2818_PIN_PE7);
-}
 
 static int __devinit tca6424_probe(struct i2c_client *client,const struct i2c_device_id *id)
 {
        struct tca6424_chip *chip;
        struct tca6424_platform_data  *pdata;
        int ret;
-       uint8_t val;
-       
        DBG(KERN_ALERT"*******gpio %s in %d line,dev adr is %x**\n",__FUNCTION__,__LINE__,client->addr);
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
                return -EIO;
@@ -871,44 +504,48 @@ static int __devinit tca6424_probe(struct i2c_client *client,const struct i2c_de
                ret = -EINVAL;
                goto out_failed;
        }
+       //used by old tca6424,it will remove later
+       client->adapter->dev.platform_data = pdata;
        
        chip->gpio_start = pdata->gpio_base;
-       chip->gpio_irq_start =pdata->gpio_irq_start;
        chip->gpio_pin_num=pdata->gpio_pin_num;
-       chip->irq_pin_num = pdata->irq_pin_num;
-       chip->irq_gpiopin=pdata->tca6424_irq_pin;
-       chip->irq_chain = gpio_to_irq(pdata->tca6424_irq_pin);
-       chip->names =pdata->names;
+       chip->client = client;
+       chip->names = pdata->names;
+
+       #ifdef CONFIG_EXPAND_GPIO_SOFT_INTERRUPT
+       chip->expand = &expand_irq_data;
+       chip->expand->gpio_irq_start =pdata->gpio_irq_start;
+       chip->expand->irq_pin_num = pdata->irq_pin_num;
+       chip->expand->irq_gpiopin=pdata->tca6424_irq_pin;
+       chip->expand->irq_chain = gpio_to_irq(pdata->tca6424_irq_pin);
+       chip->expand->expand_port_group   = pdata->expand_port_group;\r
+       chip->expand->expand_port_pinnum = pdata->expand_port_pinnum;\r
+       chip->expand->rk_irq_mode =  pdata->rk_irq_mode;\r
+       chip->expand->rk_irq_gpio_pull_up_down = pdata->rk_irq_gpio_pull_up_down;
+       #endif
        
-       //DBG("**%s in %d start=%d,irq_start=%d,pin_num=%d,irq_pin_num=%d,irq_gpiopin=%d,irq_chain=%d,**\n",
-       //      __FUNCTION__,__LINE__,chip->gpio_start,chip->gpio_irq_start,chip->gpio_pin_num,chip->irq_pin_num,chip->irq_gpiopin
-       //      ,chip->irq_chain);
-
        /* initialize cached registers from their original values.
        * we can't share this chip with another i2c master.
        */
        tca6424_setup_gpio(chip, id->driver_data);
        ret = gpiochip_add(&chip->gpio_chip);
        if (ret)
-       goto out_failed;
-       
+               goto out_failed;
        if(tca6424_init_pintype(chip,client))
                goto out_failed;
-
        if (pdata->setup) {
                ret = pdata->setup(client, chip->gpio_chip.base,
                                chip->gpio_chip.ngpio, pdata->context);
                if (ret < 0)
                        DBGERR(" %s setup failed, %d\n",__FUNCTION__,ret);
        }
-
-       tca6424_gpio_irq_setup(chip);
        i2c_set_clientdata(client, chip);
-       chip->client = client;
-       return 0;
 
+       #ifdef CONFIG_EXPAND_GPIO_SOFT_INTERRUPT
+       expand_irq_init(chip,&chip->gtca6424_struct,tca6424_irq_read_inputreg);
+       #endif
+       return 0;
 out_failed:
-       
        kfree(chip);
     return 0;
 }
@@ -938,6 +575,17 @@ static int tca6424_remove(struct i2c_client *client)
        return 0;
 }
 
+static int tca6424_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+       DBG("*****************tca6424 suspend*******************");
+       return 0;
+}
+
+static int tca6424_resume(struct i2c_client *client)
+{
+       DBG("*****************tca6424 resume*******************");
+       return 0;
+}
 
 static struct i2c_driver tca6424_driver = {
     .driver = {
@@ -947,9 +595,9 @@ static struct i2c_driver tca6424_driver = {
     .probe      = tca6424_probe,
     .remove     = tca6424_remove,
     .id_table   = tca6424_id,
+    .resume = tca6424_resume,
+    .suspend = tca6424_suspend,
 };
-
-
 static int __init tca6424_init(void)
 {
        int tmp;
@@ -957,13 +605,13 @@ static int __init tca6424_init(void)
        tmp=i2c_add_driver(&tca6424_driver);
        return 0;
 }
+subsys_initcall(tca6424_init);
+
 static void __exit tca6424_exit(void)
 {
     DBG(KERN_ALERT"**********tca6424_exit**********\n");
        i2c_del_driver(&tca6424_driver);
 }
-
-module_init(tca6424_init);
 module_exit(tca6424_exit);
 
 MODULE_AUTHOR(" XXX  XXX@rock-chips.com");