modify expand gpio tca6424'interrupt to respond Matrix Keyboard,At the same
author宋秀杰 <sxj@rock-chips.com>
Wed, 8 Sep 2010 02:18:03 +0000 (19:18 -0700)
committer宋秀杰 <sxj@rock-chips.com>
Wed, 8 Sep 2010 02:18:03 +0000 (19:18 -0700)
time separate soft interrupt from tca6424.c

Details:rk2818_info_defconfig default open soft interrupt and matrix keyboard.
board-infosdk.c modify I2C1 mode from IRQ to POLL,add member for struct
rk2818_tca6424_data, add  privata data for Matrix Keyboard.board.h modify
tca6424_platform_data.Kconfig and Makefile add soft interrupt Configuration.
soft_interrupt.c and tca6424.c are the main modify, they will not affect other
 modules.i2c-rk2818.c retain control SCL function for old tca6424 device,it
will remove later.Matrix Keyboard.c is modify based on kernel Matrix Keyboard.c
file.

arch/arm/configs/rk2818_info_defconfig
arch/arm/mach-rk2818/board-infosdk.c
arch/arm/mach-rk2818/include/mach/board.h
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/soft_interrupt.c [new file with mode: 0755]
drivers/gpio/soft_interrupt.h [new file with mode: 0755]
drivers/gpio/tca6424.c
drivers/i2c/busses/i2c-rk2818.c
drivers/input/keyboard/matrix_keypad.c [changed mode: 0644->0755]
include/linux/i2c/tca6424.h

index e338e7330a382841724579a1d1556d9f1cb45ee6..3507cdfdd5b95ea37f00b4dc1ba817f1ef87128d 100755 (executable)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.32.9
-# Fri Sep  3 11:41:57 2010
+# Tue Sep  7 18:19:13 2010
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -711,7 +711,7 @@ CONFIG_INPUT_KEYBOARD=y
 # CONFIG_QT2160 is not set
 # CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_GPIO is not set
-# CONFIG_KEYBOARD_MATRIX is not set
+CONFIG_KEYBOARD_MATRIX=y
 # CONFIG_KEYBOARD_MAX7359 is not set
 # CONFIG_KEYBOARD_NEWTON is not set
 # CONFIG_KEYBOARD_OPENCORES is not set
@@ -888,6 +888,7 @@ CONFIG_GPIOLIB=y
 CONFIG_IOEXTEND_TCA6424=y
 CONFIG_EXPANDED_GPIO_NUM=24
 CONFIG_EXPANDED_GPIO_IRQ_NUM=24
+CONFIG_SOFT_INTERRUPT=y
 CONFIG_SPI_FPGA_GPIO_NUM=0
 CONFIG_SPI_FPGA_GPIO_IRQ_NUM=0
 # CONFIG_W1 is not set
@@ -941,6 +942,7 @@ CONFIG_REGULATOR_DEBUG=y
 # CONFIG_REGULATOR_LP3971 is not set
 # CONFIG_REGULATOR_TPS65023 is not set
 # CONFIG_REGULATOR_TPS6507X is not set
+# CONFIG_RK2818_REGULATOR_CHARGE is not set
 # CONFIG_RK2818_REGULATOR_LP8725 is not set
 CONFIG_MEDIA_SUPPORT=y
 
@@ -1909,4 +1911,4 @@ CONFIG_REED_SOLOMON_DEC8=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
-CONFIG_NLATTR=y
+CONFIG_NLATTR=y
\ No newline at end of file
index 695d44bdd85789766d4238be7fe3a30fe76ece64..609707151bfd2fdbdefaa00f04dac93ad6bb39eb 100755 (executable)
@@ -45,6 +45,9 @@
 
 #include "devices.h"
 
+#include <linux/input/matrix_keypad.h>
+
+
 #include "../../../drivers/spi/rk2818_spim.h"
 #include "../../../drivers/input/touchscreen/xpt2046_ts.h"
 #include "../../../drivers/staging/android/timed_gpio.h"
@@ -449,6 +452,10 @@ struct tca6424_platform_data rk2818_tca6424_data={
        .gpio_irq_start=NR_AIC_IRQS + 2*NUM_GROUP + CONFIG_SPI_FPGA_GPIO_IRQ_NUM,
        .irq_pin_num=CONFIG_EXPANDED_GPIO_IRQ_NUM,
        .tca6424_irq_pin=RK2818_PIN_PA1,
+       .expand_port_group = 3,
+       .expand_port_pinnum = 8,
+       .rk_irq_mode = IRQF_TRIGGER_LOW,
+       .rk_irq_gpio_pull_up_down = GPIOPullUp,
        .settinginfo=extgpio_tca6424_settinginfo,
        .settinginfolen=ARRAY_SIZE(extgpio_tca6424_settinginfo),
        .names="extend_gpio_tca6424",
@@ -513,7 +520,7 @@ struct rk2818_i2c_platform_data default_i2c1_data = {
        .flags      = 0,
        .slave_addr = 0xff,
        .scl_rate  = 400*1000,
-       .mode           = I2C_MODE_IRQ,
+       .mode           = I2C_MODE_POLL,
        .io_init = rk2818_i2c1_io_init,
 };
 
@@ -1377,6 +1384,125 @@ struct platform_device rk2818_device_dm9k = {
 };
 #endif
 
+#ifdef CONFIG_KEYBOARD_MATRIX
+/*
+ * InfoPhone Matrix Keyboard Device
+ */
+
+#define KEYOUT0     TCA6424_P01
+#define KEYOUT1                TCA6424_P02
+#define KEYOUT2                TCA6424_P03
+#define KEYOUT3                TCA6424_P04
+#define KEYOUT4                TCA6424_P05
+
+#define KEYIN0         TCA6424_P12
+#define KEYIN1         TCA6424_P13
+#define KEYIN2         TCA6424_P14
+#define KEYIN3         TCA6424_P15
+
+
+#if 1
+static const uint32_t rk2818matrix_keymap[] = {
+#if 0
+       KEY(0, 0, KEY_1),
+       KEY(0, 1, KEY_3),
+       KEY(0, 2, KEY_5),
+       KEY(0, 3, KEY_6),
+       KEY(0, 4, KEY_7),
+       KEY(1, 0, KEY_2),
+       KEY(1, 1, KEY_4),
+       KEY(1, 2, KEY_R),
+       KEY(1, 3, KEY_Y),
+       KEY(1, 4, KEY_8),
+       KEY(2, 0, KEY_TAB),
+       KEY(2, 1, KEY_Q),
+       KEY(2, 2, KEY_E),
+       KEY(2, 3, KEY_T),
+       KEY(2, 4, KEY_G),
+       KEY(3, 0, KEY_LEFTCTRL),
+       KEY(3, 1, KEY_W),
+       KEY(3, 2, KEY_S),
+       KEY(3, 3, KEY_F),
+       KEY(3, 4, KEY_V),
+#else
+       KEY(0, 0, KEY_1),
+       KEY(1, 0, KEY_2),
+       KEY(2, 0, KEY_3),
+       KEY(3, 0, KEY_TAB),
+       KEY(0, 1, KEY_4),
+       KEY(1, 1, KEY_5),
+       KEY(2, 1, KEY_6),
+       KEY(3, 1, KEY_R),
+       KEY(0, 2, KEY_7),
+       KEY(1, 2, KEY_8),
+       KEY(2, 2, KEY_9),
+       KEY(3, 2, KEY_Q),
+       KEY(0, 3, KEY_E),
+       KEY(1, 3, KEY_0),
+       KEY(2, 3, KEY_G),
+       KEY(3, 3, KEY_LEFTCTRL),
+       KEY(0, 4, KEY_W),
+       KEY(1, 4, KEY_S),
+       KEY(2, 4, KEY_F),
+       KEY(3, 4, KEY_V),
+#endif
+};
+#else
+static const uint32_t rk2818matrix_keymap[] = {
+       KEY(0, 0, KEY_1),
+       KEY(0, 1, KEY_2),
+       KEY(0, 2, KEY_3),
+       KEY(0, 3, KEY_TAB),
+       KEY(1, 0, KEY_4),
+       KEY(1, 1, KEY_5),
+       KEY(1, 2, KEY_6),
+       KEY(1, 3, KEY_R),
+       KEY(2, 0, KEY_7),
+       KEY(2, 1, KEY_8),
+       KEY(2, 2, KEY_9),
+       KEY(2, 3, KEY_LEFTCTRL),
+       KEY(3, 0, KEY_SWITCHVIDEOMODE),
+       KEY(3, 1, KEY_0),
+       KEY(3, 2, KEY_S),
+       KEY(3, 3, KEY_F),
+       KEY(4, 0, KEY_G),
+       KEY(4, 1, KEY_W),
+       KEY(4, 2, KEY_S),
+       KEY(4, 3, KEY_F),
+};
+
+#endif
+
+static struct matrix_keymap_data rk2818matrix_keymap_data = {
+       .keymap         = rk2818matrix_keymap,
+       .keymap_size    = ARRAY_SIZE(rk2818matrix_keymap),
+};
+
+static const int rk2818matrix_row_gpios[] =
+               { KEYIN0, KEYIN1, KEYIN2, KEYIN3 };
+static const int rk2818matrix_col_gpios[] =
+               { KEYOUT0, KEYOUT1, KEYOUT2, KEYOUT3, KEYOUT4 };
+
+static struct matrix_keypad_platform_data rk2818matrixkey_pdata = {
+       .keymap_data            = &rk2818matrix_keymap_data,
+       .row_gpios              = rk2818matrix_row_gpios,
+       .col_gpios              = rk2818matrix_col_gpios,
+       .num_row_gpios          = ARRAY_SIZE(rk2818matrix_row_gpios),
+       .num_col_gpios          = ARRAY_SIZE(rk2818matrix_col_gpios),
+       .col_scan_delay_us      = 100,
+       .debounce_ms            = 10,
+       .wakeup                 = 1,
+};
+
+static struct platform_device rk2818_device_matrixkey = {
+       .name           = "matrix-keypad",
+       .id             = -1,
+       .dev            = {
+               .platform_data = &rk2818matrixkey_pdata,
+       },
+};
+#endif /* CONFIG_KEYBOARD_MATRIX */
+
 #ifdef CONFIG_HEADSET_DET
 struct rk2818_headset_data rk2818_headset_info = {
        .irq            = TCA6424_P23,
@@ -1482,6 +1608,9 @@ static struct platform_device *devices[] __initdata = {
 #ifdef CONFIG_DM9000
        &rk2818_device_dm9k,
 #endif
+#ifdef CONFIG_KEYBOARD_MATRIX  
+       &rk2818_device_matrixkey,
+#endif
 #ifdef CONFIG_HEADSET_DET
     &rk28_device_headset,
 #endif
index da9cd0960895289b845ebbaee347de78984c63f8..4074b90848ae58d97d16b02836a8734d9c836fa8 100755 (executable)
@@ -127,42 +127,47 @@ struct rk2818_gpio_expander_info {
 
 struct pca9554_platform_data {
        /*  the first extern gpio number in all of gpio groups */
-       unsigned gpio_base;
-       unsigned        gpio_pin_num;
+       unsigned int gpio_base;
+       unsigned int gpio_pin_num;
        /*  the first gpio irq  number in all of irq source */
 
-       unsigned gpio_irq_start;
-       unsigned irq_pin_num;        //ÖжϵĸöÊý
-       unsigned    pca9954_irq_pin;        //À©Õ¹IOµÄÖжϹÒÔÚÄĸögpio
+       unsigned int gpio_irq_start;
+       unsigned int irq_pin_num;        //ÖжϵĸöÊý
+       unsigned int pca9954_irq_pin;        //À©Õ¹IOµÄÖжϹÒÔÚÄĸögpio
        /* initial polarity inversion setting */
-       uint16_t        invert;
+       uint16_t invert;
        struct rk2818_gpio_expander_info  *settinginfo;
        int  settinginfolen;
-       void            *context;       /* param to setup/teardown */
+       void    *context;       /* param to setup/teardown */
 
        int             (*setup)(struct i2c_client *client,unsigned gpio, unsigned ngpio,void *context);
        int             (*teardown)(struct i2c_client *client,unsigned gpio, unsigned ngpio,void *context);
-       char            **names;
+       char    **names;
 };
 
 struct tca6424_platform_data {
        /*  the first extern gpio number in all of gpio groups */
-       unsigned gpio_base;
-       unsigned        gpio_pin_num;
+       unsigned int gpio_base;
+       unsigned int gpio_pin_num;
        /*  the first gpio irq  number in all of irq source */
 
-       unsigned gpio_irq_start;
-       unsigned irq_pin_num;        //ÖжϵĸöÊý
-       unsigned tca6424_irq_pin;        //À©Õ¹IOµÄÖжϹÒÔÚÄĸögpio
+       unsigned int gpio_irq_start;
+       unsigned int irq_pin_num;        //ÖжϵĸöÊý
+       unsigned int tca6424_irq_pin;     //À©Õ¹IOµÄÖжϹÒÔÚÄĸögpio
+       unsigned int expand_port_group;
+       unsigned int expand_port_pinnum;
+       unsigned int rk_irq_mode;
+       unsigned int rk_irq_gpio_pull_up_down;
+       
        /* initial polarity inversion setting */
        uint16_t        invert;
        struct rk2818_gpio_expander_info  *settinginfo;
        int  settinginfolen;
-       void            *context;       /* param to setup/teardown */
+       void    *context;       /* param to setup/teardown */
 
        int             (*setup)(struct i2c_client *client,unsigned gpio, unsigned ngpio,void *context);
        int             (*teardown)(struct i2c_client *client,unsigned gpio, unsigned ngpio,void *context);
-       char            **names;
+       char    **names;
        void    (*reseti2cpin)(void);
 };
 
index c474b7b6c1d7e9d5fa60b61d04b03352352ec5fd..604fa05d470f079cf2c3fd263c57832540357d99 100755 (executable)
@@ -252,6 +252,10 @@ config EXPANDED_GPIO_IRQ_NUM
        int "setting the amount of expanded gpio irqs"
        help
          for tca6424, set 24   
+config SOFT_INTERRUPT
+       bool "soft interrupt for expand gpio use"
+       help
+         if you want expand gpio support interrupt,choose it
 
 config SPI_FPGA_GPIO_NUM  
        default 96
index e8500c2d9d7e8bff76fc0be32ac7d0400819913e..27efb0654627d4ce297d8e7b308a5dd11d4a4574 100755 (executable)
@@ -21,3 +21,4 @@ obj-$(CONFIG_GPIO_VR41XX)     += vr41xx_giu.o
 obj-$(CONFIG_GPIO_WM831X)      += wm831x-gpio.o
 obj-$(CONFIG_GPIO_PCA9554)     += pca9554.o
 obj-$(CONFIG_IOEXTEND_TCA6424) += tca6424.o
+obj-$(CONFIG_SOFT_INTERRUPT) += soft_interrupt.o
diff --git a/drivers/gpio/soft_interrupt.c b/drivers/gpio/soft_interrupt.c
new file mode 100755 (executable)
index 0000000..6868d54
--- /dev/null
@@ -0,0 +1,448 @@
+/*\r
+ * Copyright (C) 2010 ROCKCHIP, Inc.\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ */\r
\r
+/*******************************************************************/\r
+/*       COPYRIGHT (C)  ROCK-CHIPS FUZHOU . ALL RIGHTS RESERVED.*/\r
+/*******************************************************************\r
+FILE                   :       Soft_interrupt.c\r
+MODIFY         :       sxj\r
+DATE           :       2010-9-2\r
+NOTES          :\r
+********************************************************************/\r
+#include <asm/mach/time.h>\r
+#include <linux/clk.h>\r
+#include <linux/errno.h>\r
+#include <linux/interrupt.h>\r
+#include <asm/mach-types.h>\r
+#include <linux/irq.h>\r
+#include <linux/debugfs.h>\r
+#include <linux/seq_file.h>\r
+#include <linux/kernel.h>\r
+#include <linux/list.h>\r
+#include <linux/module.h>\r
+#include <linux/io.h>\r
+#include <mach/hardware.h>\r
+#include <mach/gpio.h>\r
+#include <mach/rk2818_iomap.h>\r
+#include <mach/iomux.h>\r
+#include <linux/device.h>\r
+#include <mach/gpio.h>\r
+#include <asm/gpio.h>\r
+#include <linux/i2c.h>\r
+#include <linux/workqueue.h>\r
+#include <mach/board.h>\r
+#include <linux/delay.h>\r
+#include <linux/i2c/tca6424.h>\r
+#include <linux/ktime.h>\r
+#include "../drivers/gpio/soft_interrupt.h"\r
+\r
+#if 0\r
+#define DBG(x...)      printk(KERN_INFO x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+#if 0\r
+#define DBGERR(x...)   printk(KERN_INFO x)\r
+#else\r
+#define DBGERR(x...)\r
+#endif\r
+\r
+#define EXTPAND_GPIO_GET_BIT(a,num) (((a)>>(num))&0x01)\r
+#define EXTPAND_GPIO_SET_BIT(a,num) ((a)|(0x01<<(num)))\r
+#define EXTPAND_GPIO_CLEAR_BIT(a,num) ((a)&(~(0x01<<(num))))\r
+#define MIN(x,y) (((x)<(y))?(x):(y)) \r
+\r
+\r
+int expand_gpio_irq_en = -1;\r
+int expand_gpio_irq_ctrflag = -1;\r
+unsigned int expand_gpio_irq_num = 0;\r
+\r
+struct workqueue_struct *irqworkqueue;\r
+extern struct lock_class_key gpio_lock_class;\r
+struct expand_gpio_soft_int expand_irq_data;\r
+\r
+void expand_gpio_irq_ctr_dis(int irq,int ctrflag)\r
+{\r
+               expand_gpio_irq_ctrflag=0;\r
+               if(expand_gpio_irq_en)\r
+               {       \r
+                       expand_gpio_irq_en=0;\r
+                       disable_irq_nosync(irq);\r
+                       DBG("***********%s %d***********\n",__FUNCTION__,__LINE__);\r
+               }\r
+               if(ctrflag)\r
+               {\r
+                       expand_gpio_irq_ctrflag=-1;\r
+               }\r
+}\r
+\r
+void expand_gpio_irq_ctr_en(int irq)\r
+{      \r
+               if(!expand_gpio_irq_en)\r
+               {       \r
+                    DBG("***********%s %d***********\n",__FUNCTION__,__LINE__);\r
+                        expand_gpio_irq_en = -1;\r
+                        enable_irq(irq);\r
+               }\r
+}\r
+\r
+static int expand_checkrange(int start,int num,int val)\r
+{\r
+   \r
+       if((val<(start+num))&&(val>=start))\r
+       {\r
+               return 0;\r
+       }\r
+       else \r
+       {\r
+               return -1;\r
+       }\r
+\r
+}\r
+\r
+static void expand_gpio_irq_enable(unsigned irq)\r
+{\r
+       struct irq_desc *desc = irq_to_desc(irq);\r
+       struct expand_gpio_soft_int *pchip=(struct expand_gpio_soft_int *)desc->chip_data;\r
+       uint8_t gpioPortNum;\r
+       uint8_t gpioPortPinNum;    \r
+       uint8_t expandpinnum;\r
+\r
+       if(!expand_checkrange(pchip->gpio_irq_start,pchip->irq_pin_num,irq))\r
+       {\r
+               expandpinnum = irq - pchip->gpio_irq_start;//irq_to_gpio(irq)\r
+       }\r
+       else \r
+       {\r
+               return;\r
+       }\r
+       gpioPortNum = expandpinnum/(pchip->expand_port_pinnum);\r
+       gpioPortPinNum= expandpinnum%(pchip->expand_port_pinnum);\r
+\r
+       if((gpioPortNum>=(pchip->expand_port_group))||(gpioPortPinNum>=(pchip->expand_port_pinnum)))\r
+               return;\r
+       //DBG("**%s**\n",__FUNCTION__);\r
+       pchip->interrupt_en[gpioPortNum]=EXTPAND_GPIO_SET_BIT(pchip->interrupt_en[gpioPortNum],gpioPortPinNum); \r
+}\r
+static void expand_gpio_irq_disable(unsigned irq)\r
+{\r
+       struct irq_desc *desc = irq_to_desc(irq);\r
+       struct expand_gpio_soft_int *pchip=(struct expand_gpio_soft_int *)desc->chip_data;\r
+       uint8_t gpioPortNum;\r
+       uint8_t gpioPortPinNum;    \r
+       uint8_t expandpinnum;\r
+\r
+       if(!expand_checkrange(pchip->gpio_irq_start,pchip->irq_pin_num,irq))\r
+       {\r
+               expandpinnum=irq - pchip->gpio_irq_start;//irq_to_gpio(irq)\r
+       }\r
+       else \r
+       {\r
+               return;\r
+       }\r
+       gpioPortNum = expandpinnum/(pchip->expand_port_pinnum);\r
+       gpioPortPinNum= expandpinnum%(pchip->expand_port_pinnum);\r
+\r
+       if((gpioPortNum>=(pchip->expand_port_group))||(gpioPortPinNum>=(pchip->expand_port_pinnum)))\r
+               return;\r
+       //DBG("**%s**\n",__FUNCTION__);\r
+       pchip->interrupt_en[gpioPortNum]=EXTPAND_GPIO_CLEAR_BIT(pchip->interrupt_en[gpioPortNum],gpioPortPinNum);\r
+               \r
+}\r
+\r
+static void expand_gpio_irq_mask(unsigned irq)\r
+{\r
+       struct irq_desc *desc = irq_to_desc(irq);\r
+       struct expand_gpio_soft_int *pchip=(struct expand_gpio_soft_int *)desc->chip_data;\r
+       uint8_t gpioPortNum;\r
+       uint8_t gpioPortPinNum;    \r
+       uint8_t expandpinnum;\r
+\r
+       if(!expand_checkrange(pchip->gpio_irq_start,pchip->irq_pin_num,irq))\r
+       {\r
+               expandpinnum=irq-pchip->gpio_irq_start;//irq_to_gpio(irq)\r
+       }\r
+       else \r
+       {\r
+               return;\r
+       }\r
+       gpioPortNum = expandpinnum/(pchip->expand_port_pinnum);\r
+       gpioPortPinNum= expandpinnum%(pchip->expand_port_pinnum);\r
+       if((gpioPortNum>=(pchip->expand_port_group))||(gpioPortPinNum>=(pchip->expand_port_pinnum)))\r
+               return;\r
+       //DBG("**%s**\n",__FUNCTION__);\r
+       pchip->interrupt_mask[gpioPortNum]=EXTPAND_GPIO_SET_BIT(pchip->interrupt_mask[gpioPortNum],gpioPortPinNum);     \r
+}\r
+\r
+static void expand_gpio_irq_unmask(unsigned irq)\r
+{\r
+       struct irq_desc *desc = irq_to_desc(irq);\r
+       struct expand_gpio_soft_int *pchip=(struct expand_gpio_soft_int *)desc->chip_data;\r
+       uint8_t gpioPortNum;\r
+       uint8_t gpioPortPinNum;    \r
+       uint8_t expandpinnum;\r
+\r
+    if(!expand_checkrange(pchip->gpio_irq_start,pchip->irq_pin_num,irq))\r
+    {\r
+               expandpinnum=irq-pchip->gpio_irq_start;//irq_to_gpio(irq)\r
+       }\r
+       else \r
+       {\r
+               return;\r
+       }\r
+       gpioPortNum = expandpinnum/(pchip->expand_port_pinnum);\r
+       gpioPortPinNum= expandpinnum%(pchip->expand_port_pinnum);\r
+       if((gpioPortNum>=(pchip->expand_port_group))||(gpioPortPinNum>=(pchip->expand_port_pinnum)))\r
+               return;\r
+       //DBG("**%s**\n",__FUNCTION__);\r
+       pchip->interrupt_mask[gpioPortNum]=EXTPAND_GPIO_CLEAR_BIT(pchip->interrupt_mask[gpioPortNum],gpioPortPinNum);\r
+}\r
+\r
+static int expand_gpio_irq_type(unsigned int irq, unsigned int type)\r
+{\r
+       struct irq_desc *desc_irq=irq_to_desc(irq);\r
+       struct expand_gpio_soft_int *pchip=(struct expand_gpio_soft_int *)desc_irq->chip_data;\r
+       uint8_t gpioPortNum;\r
+       uint8_t gpioPortPinNum;    \r
+       uint8_t expandpinnum;\r
+       if(!expand_checkrange(pchip->gpio_irq_start,pchip->irq_pin_num,irq))\r
+       {\r
+               expandpinnum = irq - pchip->gpio_irq_start;//irq_to_gpio(irq)\r
+       }\r
+       else\r
+       {\r
+               return -1;\r
+       }\r
+\r
+       gpioPortNum = expandpinnum/(pchip->expand_port_pinnum);\r
+       gpioPortPinNum= expandpinnum%(pchip->expand_port_pinnum);\r
+       if((gpioPortNum>=(pchip->expand_port_group))||(gpioPortPinNum>=(pchip->expand_port_pinnum)))\r
+               return -1;\r
+       DBG("**%s %d PortNum=%d,PortPinNum=%d**\n",__FUNCTION__,__LINE__,gpioPortNum,gpioPortPinNum);\r
+       switch (type) {\r
+               case IRQ_TYPE_NONE:\r
+                       pchip->inttype_set[gpioPortNum]=EXTPAND_GPIO_CLEAR_BIT(pchip->inttype_set[gpioPortNum],gpioPortPinNum);\r
+                       DBG("**%s IRQ_TYPE_NONE**\n",__FUNCTION__);\r
+                       break;\r
+               case IRQ_TYPE_EDGE_RISING:\r
+                       pchip->inttype_set[gpioPortNum]=EXTPAND_GPIO_SET_BIT(pchip->inttype_set[gpioPortNum],gpioPortPinNum);\r
+                       pchip->inttype[gpioPortNum]=EXTPAND_GPIO_SET_BIT(pchip->inttype[gpioPortNum],gpioPortPinNum);\r
+                       pchip->inttype1[gpioPortNum]=EXTPAND_GPIO_CLEAR_BIT(pchip->inttype1[gpioPortNum],gpioPortPinNum);\r
+                       DBG("**%s IRQ_TYPE_EDGE_RISING,inttype=%x,inttype1=%x**\n",__FUNCTION__,pchip->inttype[gpioPortNum],pchip->inttype1[gpioPortNum]);\r
+                       break;\r
+               case IRQ_TYPE_EDGE_FALLING:\r
+                       pchip->inttype_set[gpioPortNum]=EXTPAND_GPIO_SET_BIT(pchip->inttype_set[gpioPortNum],gpioPortPinNum);\r
+                       pchip->inttype[gpioPortNum]=EXTPAND_GPIO_CLEAR_BIT(pchip->inttype[gpioPortNum],gpioPortPinNum);\r
+                       pchip->inttype1[gpioPortNum]=EXTPAND_GPIO_CLEAR_BIT(pchip->inttype1[gpioPortNum],gpioPortPinNum);       \r
+                       DBG("**%s IRQ_TYPE_EDGE_RISING,inttype=%x,inttype1=%x**\n",__FUNCTION__,pchip->inttype[gpioPortNum],pchip->inttype1[gpioPortNum]);\r
+                       break;\r
+               case IRQ_TYPE_EDGE_BOTH:\r
+                       pchip->inttype_set[gpioPortNum]=EXTPAND_GPIO_SET_BIT(pchip->inttype_set[gpioPortNum],gpioPortPinNum);\r
+                       pchip->inttype1[gpioPortNum]=EXTPAND_GPIO_SET_BIT(pchip->inttype1[gpioPortNum],gpioPortPinNum);\r
+                       DBG("**%s IRQ_TYPE_EDGE_RISING,inttype=%x,inttype1=%x**\n",__FUNCTION__,pchip->inttype[gpioPortNum],pchip->inttype1[gpioPortNum]);\r
+                       break;\r
+               case IRQ_TYPE_LEVEL_HIGH:\r
+                       pchip->inttype_set[gpioPortNum]=EXTPAND_GPIO_CLEAR_BIT(pchip->inttype_set[gpioPortNum],gpioPortPinNum);\r
+                       DBG("extern gpios does not support IRQ_TYPE_LEVEL_HIGH irq typ");\r
+                       break;\r
+               case IRQ_TYPE_LEVEL_LOW:\r
+                       pchip->inttype_set[gpioPortNum]=EXTPAND_GPIO_CLEAR_BIT(pchip->inttype_set[gpioPortNum],gpioPortPinNum);\r
+                       DBG("extern gpios does not support IRQ_TYPE_LEVEL_LOW irq typ");\r
+                       break;\r
+               default:\r
+                       return -EINVAL;\r
+       }\r
+       return 0;\r
+}\r
+\r
+static int expand_gpio_irq_set_wake(unsigned irq, unsigned state)\r
+{\r
+    //no irq wake\r
+       return 0;\r
+}\r
+static struct irq_chip expand_gpio_irqchip = {\r
+       .name           = "expand_gpio_expand ",\r
+       .enable         = expand_gpio_irq_enable,\r
+       .disable        = expand_gpio_irq_disable,\r
+       .mask           = expand_gpio_irq_mask,\r
+       .unmask         = expand_gpio_irq_unmask,\r
+       .set_type       = expand_gpio_irq_type, \r
+       .set_wake       = expand_gpio_irq_set_wake,\r
+};\r
+\r
+static irqreturn_t expand_gpio_irq_handler(int irq, void * dev_id)\r
+{\r
+       struct irq_desc *gpio_irq_desc = irq_to_desc(irq);\r
+       struct expand_gpio_soft_int *pchip=(struct expand_gpio_soft_int *)gpio_irq_desc->chip_data;\r
+       u8 oldintputreg[MAX_SUPPORT_PORT_GROUP]={0,0,0,0,0};\r
+       u8 tempintputreg[MAX_SUPPORT_PORT_GROUP]={0,0,0,0,0};\r
+       u8 tempallowint=0;                      \r
+       u8 levelchg=0;                  \r
+       u8 intbit[MAX_SUPPORT_PORT_GROUP]={0,0,0,0,0};                  \r
+       u8 tempinttype=0;\r
+       u8 int_en_flag=0;\r
+       int i,j;\r
+\r
+       DBG("******************%s*******************\n",__FUNCTION__);\r
+       expand_gpio_irq_ctr_dis(pchip->irq_chain,0);\r
+       memcpy(&oldintputreg[0],&pchip->gvar->reg_input[0],pchip->expand_port_pinnum);\r
+       if(pchip->irq_data.read_allinputreg(pchip->irq_data.data,&tempintputreg[0]))\r
+       {\r
+               expand_gpio_irq_ctr_dis(pchip->irq_chain,-1);\r
+               DBG("**%s[%d] reading reg is error\n",__FUNCTION__,__LINE__); \r
+               queue_work(irqworkqueue,&pchip->irq_work);\r
+               return IRQ_HANDLED;\r
+       }\r
+       \r
+       memcpy(&pchip->gvar->reg_input[0],&tempintputreg[0],pchip->expand_port_pinnum);\r
+       //DBG("**has run at %s**,input[0] = %x,input[1] = %x,input[2] = %x\n",__FUNCTION__,pchip->gvar.reg_input[0],pchip->gvar.reg_input[1],pchip->gvar.reg_input[2]);\r
+\r
+       //Handle for different expand_port_group \r
+    for(i=0,int_en_flag=0;i<MIN(pchip->expand_port_group,MAX_SUPPORT_PORT_GROUP);i++)\r
+    {\r
+               int_en_flag|=pchip->interrupt_en[i];\r
+    }\r
+\r
+       if(!int_en_flag)\r
+       {               \r
+               if(expand_gpio_irq_num<0xFFFFFFFF)\r
+               {\r
+                       expand_gpio_irq_num++;\r
+               }\r
+               else\r
+               {\r
+                       expand_gpio_irq_num=0;\r
+               }\r
+               DBGERR("there are no pin reg irq\n"); \r
+               expand_gpio_irq_ctr_en(pchip->irq_chain);\r
+               return IRQ_HANDLED;\r
+       }\r
+\r
+       for(i=0;i<pchip->expand_port_group;i++)\r
+       {\r
+               tempallowint=pchip->interrupt_en[i]&pchip->gvar->reg_direction[i]&(~pchip->interrupt_mask[i]);// Âú×ãÖжÏÌõ¼þ\r
+               levelchg=oldintputreg[i]^tempintputreg[i];// ÕÒ³öǰºó״̬²»Ò»ÑùµÄpin\r
+               tempinttype=~(tempintputreg[i]^pchip->inttype[i]);// ÕÒ³ö´¥·¢×´Ì¬ºÍµ±Ç°pin״̬һÑùµÄpin£¬×¢ÒâÖ»Ö§³Ölow highÁ½ÖÖpin´¥·¢\r
+\r
+           tempinttype=(~pchip->inttype1[i])&tempinttype;// inttype1 ÎªÕæµÄλ¶ÔÓ¦µÄtempinttypeλÇåÁ㣬ÒòΪ¸ÃλֻÊÜinttype1¿ØÖÆ\r
+               tempinttype|=pchip->inttype1[i];//µçƽֻҪÊDZ仯¾Í²úÉúÖжÏ\r
+               tempinttype&=pchip->inttype_set[i];//ÒѾ­ÉèÖÃÁËtypeÀàÐÍ\r
+\r
+               intbit[i]=tempallowint&levelchg&tempinttype;\r
+               //DBG(" tempallowint=%x,levelchg=%x,tempinttype=%x,intbit=%d\n",tempallowint,levelchg,tempinttype,intbit[i]);\r
+       }\r
+       if(expand_gpio_irq_num<0xFFFFFFFF)\r
+       {\r
+               expand_gpio_irq_num++;\r
+       }\r
+       else\r
+       {\r
+               expand_gpio_irq_num=0;\r
+       }\r
+       for(i=0;i<pchip->expand_port_group;i++)\r
+       {\r
+               if(intbit[i])\r
+               {\r
+                       for(j=0;j<pchip->expand_port_pinnum;j++)\r
+                       {\r
+                               if(EXTPAND_GPIO_GET_BIT(intbit[i],j))\r
+                               {\r
+                                       irq=pchip->gpio_irq_start+pchip->expand_port_pinnum*i+j;\r
+                                       gpio_irq_desc = irq_to_desc(irq);\r
+                                       gpio_irq_desc->chip->mask(irq);\r
+                                       generic_handle_irq(irq);\r
+                                       gpio_irq_desc->chip->unmask(irq);\r
+                                       //DBG("expand_i2c_irq_handler port=%d,pin=%d,pinlevel=%d\n",i,j,EXTPAND_GPIO_GET_BIT(tempintputreg[i],j));\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+       expand_gpio_irq_ctr_en(pchip->irq_chain);\r
+       return IRQ_HANDLED;\r
+}\r
+\r
+static void irq_call_back_handler(struct work_struct *work)\r
+{\r
+       struct expand_gpio_soft_int *pchip = container_of(work, struct expand_gpio_soft_int,irq_work);\r
+       //printk("irq_call_back_handle\n");\r
+       expand_gpio_irq_handler(pchip->irq_chain,NULL);\r
+}\r
+\r
+void expand_gpio_irq_setup(struct expand_gpio_soft_int *pchip)\r
+{\r
+    unsigned int pioc, irq_num;\r
+    int ret;\r
+       struct irq_desc *desc;\r
+    irq_num = pchip->gpio_irq_start;   //ÖжϺţ¬À©Õ¹ioµÄÖжϺÅÓ¦¸Ã½ô¸úÔÚÄÚ²¿ioÖжϺŵĺóÃæ¡£ÈçrkÄÚ²¿ÖжÏ48¸ö£¬¼ÓÉÏÄÚ²¿gpio 16¸öÐéÄâÖжϣ¬ÕâÀïpinÓ¦¸Ã´Ó48+16¿ªÊ¼\r
+\r
+       DBG("**%s**\n",__FUNCTION__);\r
+    for (pioc = 0; pioc < pchip->irq_pin_num; pioc++,irq_num++)\r
+    {\r
+        lockdep_set_class(&irq_desc[irq_num].lock, &gpio_lock_class);\r
+        /*\r
+         * Can use the "simple" and not "edge" handler since it's\r
+         * shorter, and the AIC handles interrupts sanely.\r
+        */\r
+               set_irq_chip(irq_num, &expand_gpio_irqchip);   \r
+               set_irq_handler(irq_num, handle_simple_irq);\r
+               set_irq_chip_data(irq_num,(void *)pchip);\r
+               desc = irq_to_desc(irq_num);\r
+               DBG("**%s line=%d,irq_num=%d**\n",__FUNCTION__,__LINE__,irq_num);\r
+               set_irq_flags(irq_num, IRQF_VALID);       \r
+    }\r
+       ret = gpio_request(pchip->irq_gpiopin,NULL);\r
+       if(ret!=0)\r
+       {\r
+               gpio_free(pchip->irq_gpiopin);\r
+               DBG("expand_gpio_irq_setup request gpio is err\n");\r
+       }\r
+       gpio_pull_updown(pchip->irq_gpiopin, pchip->rk_irq_gpio_pull_up_down);        //gpio ÐèÒªÀ­¸ßirq_to_gpio(pchip->irq_chain)\r
+       irqworkqueue=create_rt_workqueue("irq workqueue");\r
+       INIT_WORK(&pchip->irq_work,irq_call_back_handler);\r
+       set_irq_chip_data(pchip->irq_chain, pchip);\r
+       if(request_irq(pchip->irq_chain,expand_gpio_irq_handler,pchip->rk_irq_mode, "expand", pchip)!=0)\r
+       {\r
+               DBG("**%s line=%d is err**\n",__FUNCTION__,__LINE__);\r
+       }\r
+}\r
+\r
+int wait_untill_input_reg_flash(void)\r
+{\r
+       unsigned int num = 0;\r
+    unsigned int tempnum = expand_gpio_irq_num;\r
+\r
+       while(expand_gpio_irq_ctrflag&&(expand_gpio_irq_num==tempnum))\r
+       {\r
+               mdelay(1);\r
+               num++;\r
+               if(num>5)\r
+                       return -1;\r
+       }\r
+       return 0;\r
+}\r
+\r
+void expand_irq_init(void *data,struct expand_gpio_global_variable *var,irq_read_inputreg handler)\r
+{\r
+       expand_irq_data.irq_data.data = data;\r
+       expand_irq_data.irq_data.read_allinputreg = handler;\r
+       expand_irq_data.gvar = var;\r
+       expand_gpio_irq_setup(&expand_irq_data);\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/drivers/gpio/soft_interrupt.h b/drivers/gpio/soft_interrupt.h
new file mode 100755 (executable)
index 0000000..f04f688
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef _SOFT_INTERRUPT_H\r
+#define _SOFT_INTERRUPT_H
+\r
+#define MAX_SUPPORT_PORT_GROUP 5\r
+\r
+typedef int (*irq_read_inputreg)(void *,char *);\r
+struct expand_gpio_irq_data\r
+{\r
+       void *data;\r
+       irq_read_inputreg read_allinputreg;\r
+};\r
+\r
+struct expand_gpio_global_variable\r
+{\r
+       uint8_t reg_input[MAX_SUPPORT_PORT_GROUP];\r
+       uint8_t reg_output[MAX_SUPPORT_PORT_GROUP];\r
+       uint8_t reg_direction[MAX_SUPPORT_PORT_GROUP];\r
+};\r
+struct expand_gpio_soft_int\r
+{\r
+       unsigned int gpio_irq_start;\r
+       unsigned int irq_pin_num;                                       //ÖжϵĸöÊý\r
+       unsigned int irq_gpiopin;                               //¸¸ÖжϵÄÖжϠ½Å\r
+       unsigned int irq_chain;                                 //¸¸ÖжϵÄÖжϺÅ\r
+\r
+       unsigned int expand_port_group;\r
+       unsigned int expand_port_pinnum;\r
+       unsigned int rk_irq_mode;\r
+       unsigned int rk_irq_gpio_pull_up_down;\r
+       \r
+       uint8_t interrupt_en[MAX_SUPPORT_PORT_GROUP];           // 0 dis\r
+       uint8_t interrupt_mask[MAX_SUPPORT_PORT_GROUP];         // 0 unmask\r
+       uint8_t inttype_set[MAX_SUPPORT_PORT_GROUP];            // Inttype  enable\r
+       uint8_t inttype[MAX_SUPPORT_PORT_GROUP];        \r
+       uint8_t inttype1[MAX_SUPPORT_PORT_GROUP];\r
+       \r
+       struct expand_gpio_irq_data irq_data;\r
+       struct work_struct irq_work;\r
+       struct expand_gpio_global_variable *gvar;\r
+};\r
+\r
+extern struct expand_gpio_soft_int expand_irq_data;\r
+extern int wait_untill_input_reg_flash(void);\r
+extern void expand_irq_init(void *data,struct expand_gpio_global_variable *var,irq_read_inputreg handler);\r
+\r
+#endif\r
+\r
index 11ce469035e3e9a70320663dd059be5bf0322866..b9e043199a9d83077cab40db2cf034fd02f7139a 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,6 +42,8 @@ NOTES         :
 #include <mach/board.h>
 #include <linux/delay.h>
 #include <linux/i2c/tca6424.h>
+#include <linux/ktime.h>
+#include "../drivers/gpio/soft_interrupt.h"
 
 #if 0
 #define TCA6424DEB
@@ -49,30 +52,17 @@ NOTES               :
 #define DBG(x...)
 #endif
 
-#if 1
+#if 0
 #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 +72,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 +89,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 +118,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,6 +149,20 @@ static int tca6424_read_reg(struct i2c_client *client, uint8_t reg, uint8_t *val
 
 }
 
+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, uint8_t pin_num)
 {
        struct tca6424_chip *chip;
@@ -172,29 +178,28 @@ 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;
 }
 
@@ -203,8 +208,8 @@ static int tca6424_gpio_direction_output(struct gpio_chip *gc,uint8_t pin_num, i
        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 +218,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 +226,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,29 +255,31 @@ 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;
 }
 
@@ -276,44 +288,34 @@ static int tca6424_gpio_get_value(struct gpio_chip *gc, uint8_t 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);
+
+       #ifdef CONFIG_SOFT_INTERRUPT
+       ret = wait_untill_input_reg_flash( );
+       if(ret<0)
+               return -1;
+       #endif
+       
        gpioPortNum = pin_num/8;
        gpioPortPinNum= pin_num%8;
-
+       Regaddr = TCA6424_OutputLevel_Reg+gpioPortNum;  
+       
        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))
-       {
-               DBGERR("**%s[%d]Did not get the inputreglock**\n",__FUNCTION__,__LINE__);
-               return -1;
-       }
-       #endif
-
+       #ifndef CONFIG_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)
@@ -324,365 +326,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)
-       {
-       
-               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))
+    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)))
        {
-               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 +406,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 +439,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,37 +459,32 @@ 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;
 }
 
@@ -840,8 +493,6 @@ static int __devinit tca6424_probe(struct i2c_client *client,const struct i2c_de
        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;
@@ -855,46 +506,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->names = pdata->names;
+
+       #ifdef CONFIG_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_SOFT_INTERRUPT
+       expand_irq_init(chip,&chip->gtca6424_struct,tca6424_irq_read_inputreg);
+       #endif
+       return 0;
 out_failed:
-       
        kfree(chip);
     return 0;
 }
@@ -924,6 +577,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 = {
@@ -933,9 +597,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;
index 4cd29a2667c0e4d505ae3006156ac1e0a5af41b8..5f8500e970c6e9707009795af548346d688cb233 100755 (executable)
@@ -463,14 +463,12 @@ exit:
                }
 
                //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  
+               #if defined (CONFIG_IOEXTEND_TCA6424)
+               if (pdata && pdata->reseti2cpin) {
+                       pdata->reseti2cpin();
                }
+               #endif  
+       
                        
        }
        return ret;
old mode 100644 (file)
new mode 100755 (executable)
index 91cfe51..368b770
@@ -44,13 +44,14 @@ struct matrix_keypad {
 static void __activate_col(const struct matrix_keypad_platform_data *pdata,
                           int col, bool on)
 {
-       bool level_on = !pdata->active_low;
+       // bool level_on = !pdata->active_low;
+       bool level_on = pdata->active_low;
 
        if (on) {
                gpio_direction_output(pdata->col_gpios[col], level_on);
        } else {
                gpio_set_value_cansleep(pdata->col_gpios[col], !level_on);
-               gpio_direction_input(pdata->col_gpios[col]);
+               //gpio_direction_input(pdata->col_gpios[col]);
        }
 }
 
@@ -84,6 +85,7 @@ static void enable_row_irqs(struct matrix_keypad *keypad)
        const struct matrix_keypad_platform_data *pdata = keypad->pdata;
        int i;
 
+       //printk("enable_row_irqs \n");
        for (i = 0; i < pdata->num_row_gpios; i++)
                enable_irq(gpio_to_irq(pdata->row_gpios[i]));
 }
@@ -92,7 +94,7 @@ static void disable_row_irqs(struct matrix_keypad *keypad)
 {
        const struct matrix_keypad_platform_data *pdata = keypad->pdata;
        int i;
-
+       //printk("disable_row_irqs \n");
        for (i = 0; i < pdata->num_row_gpios; i++)
                disable_irq_nosync(gpio_to_irq(pdata->row_gpios[i]));
 }
@@ -102,13 +104,14 @@ static void disable_row_irqs(struct matrix_keypad *keypad)
  */
 static void matrix_keypad_scan(struct work_struct *work)
 {
+
        struct matrix_keypad *keypad =
                container_of(work, struct matrix_keypad, work.work);
        struct input_dev *input_dev = keypad->input_dev;
        const struct matrix_keypad_platform_data *pdata = keypad->pdata;
        uint32_t new_state[MATRIX_MAX_COLS];
        int row, col, code;
-
+#if 1
        /* de-activate all columns for scanning */
        activate_all_cols(pdata, false);
 
@@ -121,11 +124,16 @@ static void matrix_keypad_scan(struct work_struct *work)
 
                for (row = 0; row < pdata->num_row_gpios; row++)
                        new_state[col] |=
-                               row_asserted(pdata, row) ? (1 << row) : 0;
+               //      new_state[col] &=
+               //              row_asserted(pdata, row) ? (1 << row) : 0;
+                               row_asserted(pdata, row) ? 0: (1 << row) ;
+
+              //printk("matrix_keypad_scan: new_state[0]=0x%x,new_state[1]=0x%x,new_state[2]=0x%x,new_state[3]=0x%x \n",new_state[0] ,new_state[1] ,new_state[2] ,new_state[3]);
+            //  printk("matrix_keypad_scan: row0=0x%x,row1=0x%x,row2=0x%x,row3=0x%x \n",row_asserted(pdata, 0),row_asserted(pdata, 1),row_asserted(pdata, 2),row_asserted(pdata,3));
 
                activate_col(pdata, col, false);
        }
-
+   
        for (col = 0; col < pdata->num_col_gpios; col++) {
                uint32_t bits_changed;
 
@@ -138,12 +146,16 @@ static void matrix_keypad_scan(struct work_struct *work)
                                continue;
 
                        code = MATRIX_SCAN_CODE(row, col, keypad->row_shift);
+                       //printk("matrix_keypad_scan: MATRIX_SCAN_CODE = 0x%x \n",code);
                        input_event(input_dev, EV_MSC, MSC_SCAN, code);
-                       input_report_key(input_dev,
+                      input_report_key(input_dev,
                                         keypad->keycodes[code],
                                         new_state[col] & (1 << row));
+                       //printk("matrix_keypad_scan:input_report_key- keypad->keycodes[code] = 0x%x,state=0x%x \n", keypad->keycodes[code], new_state[col] & (1 << row));
+               
                }
-       }
+       }       
+
        input_sync(input_dev);
 
        memcpy(keypad->last_key_state, new_state, sizeof(new_state));
@@ -155,6 +167,17 @@ static void matrix_keypad_scan(struct work_struct *work)
        keypad->scan_pending = false;
        enable_row_irqs(keypad);
        spin_unlock_irq(&keypad->lock);
+       
+#else
+       //activate_all_cols(pdata, false);
+       activate_all_cols(pdata, true);
+       //row_asserted(pdata, 0);
+       /* Enable IRQs again */
+       spin_lock_irq(&keypad->lock);
+       keypad->scan_pending = false;
+       enable_row_irqs(keypad);
+       spin_unlock_irq(&keypad->lock);
+#endif
 }
 
 static irqreturn_t matrix_keypad_interrupt(int irq, void *id)
@@ -162,6 +185,8 @@ static irqreturn_t matrix_keypad_interrupt(int irq, void *id)
        struct matrix_keypad *keypad = id;
        unsigned long flags;
 
+       //printk("enter matrix_keypad_interrupt \n");
+          
        spin_lock_irqsave(&keypad->lock, flags);
 
        /*
@@ -172,7 +197,7 @@ static irqreturn_t matrix_keypad_interrupt(int irq, void *id)
        if (unlikely(keypad->scan_pending || keypad->stopped))
                goto out;
 
-       disable_row_irqs(keypad);
+       disable_row_irqs(keypad);
        keypad->scan_pending = true;
        schedule_delayed_work(&keypad->work,
                msecs_to_jiffies(keypad->pdata->debounce_ms));
@@ -263,9 +288,12 @@ static int __devinit init_matrix_gpio(struct platform_device *pdev,
                        goto err_free_cols;
                }
 
-               gpio_direction_output(pdata->col_gpios[i], !pdata->active_low);
+               //gpio_direction_output(pdata->col_gpios[i], !pdata->active_low);
+               gpio_direction_output(pdata->col_gpios[i], pdata->active_low);
        }
 
+       //printk("init_matrix_gpio:pdata->active_low = 0x%x \n",pdata->active_low);
+          
        for (i = 0; i < pdata->num_row_gpios; i++) {
                err = gpio_request(pdata->row_gpios[i], "matrix_kbd_row");
                if (err) {
@@ -279,10 +307,11 @@ static int __devinit init_matrix_gpio(struct platform_device *pdev,
        }
 
        for (i = 0; i < pdata->num_row_gpios; i++) {
+               printk("%d %d\n", pdata->row_gpios[i], gpio_to_irq(pdata->row_gpios[i]));
                err = request_irq(gpio_to_irq(pdata->row_gpios[i]),
                                matrix_keypad_interrupt,
-                               IRQF_DISABLED |
-                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+                               /*IRQF_DISABLED |*/
+                               IRQ_TYPE_EDGE_BOTH,
                                "matrix-keypad", keypad);
                if (err) {
                        dev_err(&pdev->dev,
@@ -321,6 +350,7 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev)
        unsigned int row_shift;
        int err;
 
+          
        pdata = pdev->dev.platform_data;
        if (!pdata) {
                dev_err(&pdev->dev, "no platform data defined\n");
@@ -381,6 +411,8 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev)
        device_init_wakeup(&pdev->dev, pdata->wakeup);
        platform_set_drvdata(pdev, keypad);
 
+       printk(KERN_INFO "matrix keypad: driver initialized\n");
+          
        return 0;
 
 err_free_mem:
index 6cb23359a9c646c8c99fc862ecdc7848613dfe78..6ea4ef9a0db333ab8fc3cb325cd749826147007a 100755 (executable)
@@ -18,6 +18,8 @@ $Log: gpio.h,v $
 #define TCA6424_Port0PinNum 8\r
 #define TCA6424_Port1PinNum 8\r
 #define TCA6424_Port2PinNum 8\r
+#define EXTGPIO_OUTPUT         0\r
+#define EXTGPIO_INPUT  1\r
 \r
 #define TCA6424_TotalPortPinNum (TCA6424_Port0PinNum+TCA6424_Port1PinNum+TCA6424_Port2PinNum)\r
 \r
@@ -40,6 +42,6 @@ $Log: gpio.h,v $
 #define tca6424setbit(a,num) ((a)|(0x01<<(num)))\r
 #define tca6424clearbit(a,num) ((a)&(~(0x01<<(num))))\r
 \r
-#define TCA6424_I2C_RATE 300*1000\r
+#define TCA6424_I2C_RATE 400*1000\r
 \r
 #endif\r