From: 宋秀杰 Date: Wed, 8 Sep 2010 02:18:03 +0000 (-0700) Subject: modify expand gpio tca6424'interrupt to respond Matrix Keyboard,At the same X-Git-Tag: firefly_0821_release~11175^2~5 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=bc93e99079fada2ba11e706797e52054d59ad47b;p=firefly-linux-kernel-4.4.55.git modify expand gpio tca6424'interrupt to respond Matrix Keyboard,At the same 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. --- diff --git a/arch/arm/configs/rk2818_info_defconfig b/arch/arm/configs/rk2818_info_defconfig index e338e7330a38..3507cdfdd5b9 100755 --- a/arch/arm/configs/rk2818_info_defconfig +++ b/arch/arm/configs/rk2818_info_defconfig @@ -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 diff --git a/arch/arm/mach-rk2818/board-infosdk.c b/arch/arm/mach-rk2818/board-infosdk.c index 695d44bdd857..609707151bfd 100755 --- a/arch/arm/mach-rk2818/board-infosdk.c +++ b/arch/arm/mach-rk2818/board-infosdk.c @@ -45,6 +45,9 @@ #include "devices.h" +#include + + #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 diff --git a/arch/arm/mach-rk2818/include/mach/board.h b/arch/arm/mach-rk2818/include/mach/board.h index da9cd0960895..4074b90848ae 100755 --- a/arch/arm/mach-rk2818/include/mach/board.h +++ b/arch/arm/mach-rk2818/include/mach/board.h @@ -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); }; diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index c474b7b6c1d7..604fa05d470f 100755 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -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 diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index e8500c2d9d7e..27efb0654627 100755 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -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 index 000000000000..6868d549d75c --- /dev/null +++ b/drivers/gpio/soft_interrupt.c @@ -0,0 +1,448 @@ +/* + * Copyright (C) 2010 ROCKCHIP, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/*******************************************************************/ +/* COPYRIGHT (C) ROCK-CHIPS FUZHOU . ALL RIGHTS RESERVED.*/ +/******************************************************************* +FILE : Soft_interrupt.c +MODIFY : sxj +DATE : 2010-9-2 +NOTES : +********************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../drivers/gpio/soft_interrupt.h" + +#if 0 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif + +#if 0 +#define DBGERR(x...) printk(KERN_INFO x) +#else +#define DBGERR(x...) +#endif + +#define EXTPAND_GPIO_GET_BIT(a,num) (((a)>>(num))&0x01) +#define EXTPAND_GPIO_SET_BIT(a,num) ((a)|(0x01<<(num))) +#define EXTPAND_GPIO_CLEAR_BIT(a,num) ((a)&(~(0x01<<(num)))) +#define MIN(x,y) (((x)<(y))?(x):(y)) + + +int expand_gpio_irq_en = -1; +int expand_gpio_irq_ctrflag = -1; +unsigned int expand_gpio_irq_num = 0; + +struct workqueue_struct *irqworkqueue; +extern struct lock_class_key gpio_lock_class; +struct expand_gpio_soft_int expand_irq_data; + +void expand_gpio_irq_ctr_dis(int irq,int ctrflag) +{ + expand_gpio_irq_ctrflag=0; + if(expand_gpio_irq_en) + { + expand_gpio_irq_en=0; + disable_irq_nosync(irq); + DBG("***********%s %d***********\n",__FUNCTION__,__LINE__); + } + if(ctrflag) + { + expand_gpio_irq_ctrflag=-1; + } +} + +void expand_gpio_irq_ctr_en(int irq) +{ + if(!expand_gpio_irq_en) + { + DBG("***********%s %d***********\n",__FUNCTION__,__LINE__); + expand_gpio_irq_en = -1; + enable_irq(irq); + } +} + +static int expand_checkrange(int start,int num,int val) +{ + + if((val<(start+num))&&(val>=start)) + { + return 0; + } + else + { + return -1; + } + +} + +static void expand_gpio_irq_enable(unsigned irq) +{ + struct irq_desc *desc = irq_to_desc(irq); + struct expand_gpio_soft_int *pchip=(struct expand_gpio_soft_int *)desc->chip_data; + uint8_t gpioPortNum; + uint8_t gpioPortPinNum; + uint8_t expandpinnum; + + if(!expand_checkrange(pchip->gpio_irq_start,pchip->irq_pin_num,irq)) + { + expandpinnum = irq - pchip->gpio_irq_start;//irq_to_gpio(irq) + } + else + { + return; + } + gpioPortNum = expandpinnum/(pchip->expand_port_pinnum); + gpioPortPinNum= expandpinnum%(pchip->expand_port_pinnum); + + if((gpioPortNum>=(pchip->expand_port_group))||(gpioPortPinNum>=(pchip->expand_port_pinnum))) + return; + //DBG("**%s**\n",__FUNCTION__); + pchip->interrupt_en[gpioPortNum]=EXTPAND_GPIO_SET_BIT(pchip->interrupt_en[gpioPortNum],gpioPortPinNum); +} +static void expand_gpio_irq_disable(unsigned irq) +{ + struct irq_desc *desc = irq_to_desc(irq); + struct expand_gpio_soft_int *pchip=(struct expand_gpio_soft_int *)desc->chip_data; + uint8_t gpioPortNum; + uint8_t gpioPortPinNum; + uint8_t expandpinnum; + + if(!expand_checkrange(pchip->gpio_irq_start,pchip->irq_pin_num,irq)) + { + expandpinnum=irq - pchip->gpio_irq_start;//irq_to_gpio(irq) + } + else + { + return; + } + gpioPortNum = expandpinnum/(pchip->expand_port_pinnum); + gpioPortPinNum= expandpinnum%(pchip->expand_port_pinnum); + + if((gpioPortNum>=(pchip->expand_port_group))||(gpioPortPinNum>=(pchip->expand_port_pinnum))) + return; + //DBG("**%s**\n",__FUNCTION__); + pchip->interrupt_en[gpioPortNum]=EXTPAND_GPIO_CLEAR_BIT(pchip->interrupt_en[gpioPortNum],gpioPortPinNum); + +} + +static void expand_gpio_irq_mask(unsigned irq) +{ + struct irq_desc *desc = irq_to_desc(irq); + struct expand_gpio_soft_int *pchip=(struct expand_gpio_soft_int *)desc->chip_data; + uint8_t gpioPortNum; + uint8_t gpioPortPinNum; + uint8_t expandpinnum; + + if(!expand_checkrange(pchip->gpio_irq_start,pchip->irq_pin_num,irq)) + { + expandpinnum=irq-pchip->gpio_irq_start;//irq_to_gpio(irq) + } + else + { + return; + } + gpioPortNum = expandpinnum/(pchip->expand_port_pinnum); + gpioPortPinNum= expandpinnum%(pchip->expand_port_pinnum); + if((gpioPortNum>=(pchip->expand_port_group))||(gpioPortPinNum>=(pchip->expand_port_pinnum))) + return; + //DBG("**%s**\n",__FUNCTION__); + pchip->interrupt_mask[gpioPortNum]=EXTPAND_GPIO_SET_BIT(pchip->interrupt_mask[gpioPortNum],gpioPortPinNum); +} + +static void expand_gpio_irq_unmask(unsigned irq) +{ + struct irq_desc *desc = irq_to_desc(irq); + struct expand_gpio_soft_int *pchip=(struct expand_gpio_soft_int *)desc->chip_data; + uint8_t gpioPortNum; + uint8_t gpioPortPinNum; + uint8_t expandpinnum; + + if(!expand_checkrange(pchip->gpio_irq_start,pchip->irq_pin_num,irq)) + { + expandpinnum=irq-pchip->gpio_irq_start;//irq_to_gpio(irq) + } + else + { + return; + } + gpioPortNum = expandpinnum/(pchip->expand_port_pinnum); + gpioPortPinNum= expandpinnum%(pchip->expand_port_pinnum); + if((gpioPortNum>=(pchip->expand_port_group))||(gpioPortPinNum>=(pchip->expand_port_pinnum))) + return; + //DBG("**%s**\n",__FUNCTION__); + pchip->interrupt_mask[gpioPortNum]=EXTPAND_GPIO_CLEAR_BIT(pchip->interrupt_mask[gpioPortNum],gpioPortPinNum); +} + +static int expand_gpio_irq_type(unsigned int irq, unsigned int type) +{ + struct irq_desc *desc_irq=irq_to_desc(irq); + struct expand_gpio_soft_int *pchip=(struct expand_gpio_soft_int *)desc_irq->chip_data; + uint8_t gpioPortNum; + uint8_t gpioPortPinNum; + uint8_t expandpinnum; + if(!expand_checkrange(pchip->gpio_irq_start,pchip->irq_pin_num,irq)) + { + expandpinnum = irq - pchip->gpio_irq_start;//irq_to_gpio(irq) + } + else + { + return -1; + } + + gpioPortNum = expandpinnum/(pchip->expand_port_pinnum); + gpioPortPinNum= expandpinnum%(pchip->expand_port_pinnum); + if((gpioPortNum>=(pchip->expand_port_group))||(gpioPortPinNum>=(pchip->expand_port_pinnum))) + return -1; + DBG("**%s %d PortNum=%d,PortPinNum=%d**\n",__FUNCTION__,__LINE__,gpioPortNum,gpioPortPinNum); + switch (type) { + case IRQ_TYPE_NONE: + pchip->inttype_set[gpioPortNum]=EXTPAND_GPIO_CLEAR_BIT(pchip->inttype_set[gpioPortNum],gpioPortPinNum); + DBG("**%s IRQ_TYPE_NONE**\n",__FUNCTION__); + break; + case IRQ_TYPE_EDGE_RISING: + pchip->inttype_set[gpioPortNum]=EXTPAND_GPIO_SET_BIT(pchip->inttype_set[gpioPortNum],gpioPortPinNum); + pchip->inttype[gpioPortNum]=EXTPAND_GPIO_SET_BIT(pchip->inttype[gpioPortNum],gpioPortPinNum); + pchip->inttype1[gpioPortNum]=EXTPAND_GPIO_CLEAR_BIT(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]=EXTPAND_GPIO_SET_BIT(pchip->inttype_set[gpioPortNum],gpioPortPinNum); + pchip->inttype[gpioPortNum]=EXTPAND_GPIO_CLEAR_BIT(pchip->inttype[gpioPortNum],gpioPortPinNum); + pchip->inttype1[gpioPortNum]=EXTPAND_GPIO_CLEAR_BIT(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]=EXTPAND_GPIO_SET_BIT(pchip->inttype_set[gpioPortNum],gpioPortPinNum); + pchip->inttype1[gpioPortNum]=EXTPAND_GPIO_SET_BIT(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]=EXTPAND_GPIO_CLEAR_BIT(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]=EXTPAND_GPIO_CLEAR_BIT(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 expand_gpio_irq_set_wake(unsigned irq, unsigned state) +{ + //no irq wake + return 0; +} +static struct irq_chip expand_gpio_irqchip = { + .name = "expand_gpio_expand ", + .enable = expand_gpio_irq_enable, + .disable = expand_gpio_irq_disable, + .mask = expand_gpio_irq_mask, + .unmask = expand_gpio_irq_unmask, + .set_type = expand_gpio_irq_type, + .set_wake = expand_gpio_irq_set_wake, +}; + +static irqreturn_t expand_gpio_irq_handler(int irq, void * dev_id) +{ + struct irq_desc *gpio_irq_desc = irq_to_desc(irq); + struct expand_gpio_soft_int *pchip=(struct expand_gpio_soft_int *)gpio_irq_desc->chip_data; + u8 oldintputreg[MAX_SUPPORT_PORT_GROUP]={0,0,0,0,0}; + u8 tempintputreg[MAX_SUPPORT_PORT_GROUP]={0,0,0,0,0}; + u8 tempallowint=0; + u8 levelchg=0; + u8 intbit[MAX_SUPPORT_PORT_GROUP]={0,0,0,0,0}; + u8 tempinttype=0; + u8 int_en_flag=0; + int i,j; + + DBG("******************%s*******************\n",__FUNCTION__); + expand_gpio_irq_ctr_dis(pchip->irq_chain,0); + memcpy(&oldintputreg[0],&pchip->gvar->reg_input[0],pchip->expand_port_pinnum); + if(pchip->irq_data.read_allinputreg(pchip->irq_data.data,&tempintputreg[0])) + { + expand_gpio_irq_ctr_dis(pchip->irq_chain,-1); + DBG("**%s[%d] reading reg is error\n",__FUNCTION__,__LINE__); + queue_work(irqworkqueue,&pchip->irq_work); + return IRQ_HANDLED; + } + + memcpy(&pchip->gvar->reg_input[0],&tempintputreg[0],pchip->expand_port_pinnum); + //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]); + + //Handle for different expand_port_group + for(i=0,int_en_flag=0;iexpand_port_group,MAX_SUPPORT_PORT_GROUP);i++) + { + int_en_flag|=pchip->interrupt_en[i]; + } + + if(!int_en_flag) + { + if(expand_gpio_irq_num<0xFFFFFFFF) + { + expand_gpio_irq_num++; + } + else + { + expand_gpio_irq_num=0; + } + DBGERR("there are no pin reg irq\n"); + expand_gpio_irq_ctr_en(pchip->irq_chain); + return IRQ_HANDLED; + } + + for(i=0;iexpand_port_group;i++) + { + tempallowint=pchip->interrupt_en[i]&pchip->gvar->reg_direction[i]&(~pchip->interrupt_mask[i]);// Âú×ãÖжÏÌõ¼þ + levelchg=oldintputreg[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[i]=tempallowint&levelchg&tempinttype; + //DBG(" tempallowint=%x,levelchg=%x,tempinttype=%x,intbit=%d\n",tempallowint,levelchg,tempinttype,intbit[i]); + } + if(expand_gpio_irq_num<0xFFFFFFFF) + { + expand_gpio_irq_num++; + } + else + { + expand_gpio_irq_num=0; + } + for(i=0;iexpand_port_group;i++) + { + if(intbit[i]) + { + for(j=0;jexpand_port_pinnum;j++) + { + if(EXTPAND_GPIO_GET_BIT(intbit[i],j)) + { + irq=pchip->gpio_irq_start+pchip->expand_port_pinnum*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("expand_i2c_irq_handler port=%d,pin=%d,pinlevel=%d\n",i,j,EXTPAND_GPIO_GET_BIT(tempintputreg[i],j)); + } + } + } + } + expand_gpio_irq_ctr_en(pchip->irq_chain); + return IRQ_HANDLED; +} + +static void irq_call_back_handler(struct work_struct *work) +{ + struct expand_gpio_soft_int *pchip = container_of(work, struct expand_gpio_soft_int,irq_work); + //printk("irq_call_back_handle\n"); + expand_gpio_irq_handler(pchip->irq_chain,NULL); +} + +void expand_gpio_irq_setup(struct expand_gpio_soft_int *pchip) +{ + unsigned int pioc, irq_num; + int ret; + struct irq_desc *desc; + irq_num = pchip->gpio_irq_start; //ÖжϺţ¬À©Õ¹ioµÄÖжϺÅÓ¦¸Ã½ô¸úÔÚÄÚ²¿ioÖжϺŵĺóÃæ¡£ÈçrkÄÚ²¿ÖжÏ48¸ö£¬¼ÓÉÏÄÚ²¿gpio 16¸öÐéÄâÖжϣ¬ÕâÀïpinÓ¦¸Ã´Ó48+16¿ªÊ¼ + + DBG("**%s**\n",__FUNCTION__); + 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. + */ + set_irq_chip(irq_num, &expand_gpio_irqchip); + set_irq_handler(irq_num, handle_simple_irq); + set_irq_chip_data(irq_num,(void *)pchip); + desc = irq_to_desc(irq_num); + DBG("**%s line=%d,irq_num=%d**\n",__FUNCTION__,__LINE__,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("expand_gpio_irq_setup request gpio is err\n"); + } + gpio_pull_updown(pchip->irq_gpiopin, pchip->rk_irq_gpio_pull_up_down); //gpio ÐèÒªÀ­¸ßirq_to_gpio(pchip->irq_chain) + irqworkqueue=create_rt_workqueue("irq workqueue"); + INIT_WORK(&pchip->irq_work,irq_call_back_handler); + set_irq_chip_data(pchip->irq_chain, pchip); + if(request_irq(pchip->irq_chain,expand_gpio_irq_handler,pchip->rk_irq_mode, "expand", pchip)!=0) + { + DBG("**%s line=%d is err**\n",__FUNCTION__,__LINE__); + } +} + +int wait_untill_input_reg_flash(void) +{ + unsigned int num = 0; + unsigned int tempnum = expand_gpio_irq_num; + + while(expand_gpio_irq_ctrflag&&(expand_gpio_irq_num==tempnum)) + { + mdelay(1); + num++; + if(num>5) + return -1; + } + return 0; +} + +void expand_irq_init(void *data,struct expand_gpio_global_variable *var,irq_read_inputreg handler) +{ + expand_irq_data.irq_data.data = data; + expand_irq_data.irq_data.read_allinputreg = handler; + expand_irq_data.gvar = var; + expand_gpio_irq_setup(&expand_irq_data); +} + + + + + + + diff --git a/drivers/gpio/soft_interrupt.h b/drivers/gpio/soft_interrupt.h new file mode 100755 index 000000000000..f04f6885b610 --- /dev/null +++ b/drivers/gpio/soft_interrupt.h @@ -0,0 +1,47 @@ +#ifndef _SOFT_INTERRUPT_H +#define _SOFT_INTERRUPT_H + +#define MAX_SUPPORT_PORT_GROUP 5 + +typedef int (*irq_read_inputreg)(void *,char *); +struct expand_gpio_irq_data +{ + void *data; + irq_read_inputreg read_allinputreg; +}; + +struct expand_gpio_global_variable +{ + uint8_t reg_input[MAX_SUPPORT_PORT_GROUP]; + uint8_t reg_output[MAX_SUPPORT_PORT_GROUP]; + uint8_t reg_direction[MAX_SUPPORT_PORT_GROUP]; +}; +struct expand_gpio_soft_int +{ + unsigned int gpio_irq_start; + unsigned int irq_pin_num; //ÖжϵĸöÊý + unsigned int irq_gpiopin; //¸¸ÖжϵÄÖÐ¶Ï ½Å + unsigned int irq_chain; //¸¸ÖжϵÄÖжϺŠ+ + unsigned int expand_port_group; + unsigned int expand_port_pinnum; + unsigned int rk_irq_mode; + unsigned int rk_irq_gpio_pull_up_down; + + uint8_t interrupt_en[MAX_SUPPORT_PORT_GROUP]; // 0 dis + uint8_t interrupt_mask[MAX_SUPPORT_PORT_GROUP]; // 0 unmask + uint8_t inttype_set[MAX_SUPPORT_PORT_GROUP]; // Inttype enable + uint8_t inttype[MAX_SUPPORT_PORT_GROUP]; + uint8_t inttype1[MAX_SUPPORT_PORT_GROUP]; + + struct expand_gpio_irq_data irq_data; + struct work_struct irq_work; + struct expand_gpio_global_variable *gvar; +}; + +extern struct expand_gpio_soft_int expand_irq_data; +extern int wait_untill_input_reg_flash(void); +extern void expand_irq_init(void *data,struct expand_gpio_global_variable *var,irq_read_inputreg handler); + +#endif + diff --git a/drivers/gpio/tca6424.c b/drivers/gpio/tca6424.c index 11ce469035e3..b9e043199a9d 100755 --- a/drivers/gpio/tca6424.c +++ b/drivers/gpio/tca6424.c @@ -11,13 +11,14 @@ * 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 #include #include #include @@ -41,6 +42,8 @@ NOTES : #include #include #include +#include +#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, ®_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;iinterrupt_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;jgpio_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 , ®_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, ®_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, ®_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; ireg_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; + chip->expand->expand_port_pinnum = pdata->expand_port_pinnum; + chip->expand->rk_irq_mode = pdata->rk_irq_mode; + 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; diff --git a/drivers/i2c/busses/i2c-rk2818.c b/drivers/i2c/busses/i2c-rk2818.c index 4cd29a2667c0..5f8500e970c6 100755 --- a/drivers/i2c/busses/i2c-rk2818.c +++ b/drivers/i2c/busses/i2c-rk2818.c @@ -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; diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c old mode 100644 new mode 100755 index 91cfe5170265..368b77092419 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c @@ -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: diff --git a/include/linux/i2c/tca6424.h b/include/linux/i2c/tca6424.h index 6cb23359a9c6..6ea4ef9a0db3 100755 --- a/include/linux/i2c/tca6424.h +++ b/include/linux/i2c/tca6424.h @@ -18,6 +18,8 @@ $Log: gpio.h,v $ #define TCA6424_Port0PinNum 8 #define TCA6424_Port1PinNum 8 #define TCA6424_Port2PinNum 8 +#define EXTGPIO_OUTPUT 0 +#define EXTGPIO_INPUT 1 #define TCA6424_TotalPortPinNum (TCA6424_Port0PinNum+TCA6424_Port1PinNum+TCA6424_Port2PinNum) @@ -40,6 +42,6 @@ $Log: gpio.h,v $ #define tca6424setbit(a,num) ((a)|(0x01<<(num))) #define tca6424clearbit(a,num) ((a)&(~(0x01<<(num)))) -#define TCA6424_I2C_RATE 300*1000 +#define TCA6424_I2C_RATE 400*1000 #endif