--- /dev/null
+/*\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
* 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>
#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
#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
#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;
};
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)
{
msg.len = 1 +1;
msg.flags = client->flags;
msg.scl_rate = TCA6424_I2C_RATE;
-
ret = i2c_transfer(adap, &msg, 1);
return ret;
}
}
+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;
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;
}
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);
if((gpioPortNum>=TCA6424_PortNum)||(gpioPortPinNum>=portnum[gpioPortNum]))
return ret;
Regaddr = TCA6424_Config_Reg+gpioPortNum;
-
+
#ifdef TCA6424_CONFIGREGLOCK
if (!mutex_trylock(&chip->configreglock))
{
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))
{
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;
}
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)
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;
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;
}
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);
- }
}
}
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; 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;
}
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;
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;
}
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 = {
.probe = tca6424_probe,
.remove = tca6424_remove,
.id_table = tca6424_id,
+ .resume = tca6424_resume,
+ .suspend = tca6424_suspend,
};
-
-
static int __init tca6424_init(void)
{
int tmp;