This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Tca8418 i2c communication

Other Parts Discussed in Thread: TCA8418, TCA8418E

Hi all,

I am working in Tca8418  interface with android (4.4.2 kitkat)

my tca8418 connected in i2c.. i configured platform data 

static struct tca8418_keypad_platform_data tca8418_data =
{
.keymap_data = &mx6sl_evk_map_data, //tca8418_mkdata,//&mx6sl_evk_map_data,//imx6_keymap_data,
.rows = 8,
.cols = 7,
.rep = 1,
.irq_is_gpio = 1,

};

 i compiled  and loaded . . 

in  boot log 

input: tca8418_keypad as /devices/platform/imx-i2c.1/i2c-1/1-0034/input/input0.

occured..  /dev/input/event0 

i need demo.exe to test whether keypad is configured  correctly.

  • Hello Thangameena,

    We do not have any demo/source code that we distribute with the TCA8418. THe device was made to be used on a very large set of OSes and systems, and for this reason, we cannot supply source code for every platform.

    If you search online, there is an open source community driver for the TCA8418 that is used for Linux and should be fairly close to android.

    One thing I would like to bring to your attention in that source code, is that the settings to "enable debounce" are incorrect and backwards. Writing a 1 to the debounce registers actually disables debounce. You want the debounce_disable registers to be set to 0.
  • Hi Jonathan,

    Thanks for your reply,

    i am using imx6sl platform. i referred the data sheet..
    i need to check whether keypad is working correctly or not. then only i can configure in android layer.

    using i2cget
    i check the status register 0x02
    it displaying as 0x01 constant even i didnt press the key . while pressing only this bit( bit 0) have to set right?

    & 0x01(config reg) it displaying as 0x19 constant .. even i press or didnt press. while pressing only this bit( bit 0) have to set right?

    event count 0x03: initially shows 0x01.
    if i press the key (single press)the key count register 0x03 is incremented by 2
    e.g if i press four key continuously then it will show 0x08 . if i press more than 5 times the value be constant 0x0a. until i clear the Key event A (fifo) 0x04. after cleared there will be 0x00 in the event count register 0x03.. if i press more than 5 times it will be 0x0a constant.

    e2e.ti.com/.../264771
    according to above link i check its working

    1. i don know why 0x03 its incrementing by 2..
    2. how to configure INT pin(keypad) & i connected this pin to my processor. but in platform data irq_is_gpio =1 is given.
    3. how to test the keypad using i2c ..
  • Hi Jonathan..

    i found that event count register is incremented by 2 due to key press and key release. so if i press two key then its stored as 4 due to two times the key released.

    the config register 0x01 should write as 0x01.. but it showing 0x19.. is this due to overflow bit set?
  • Hello Thangameena,

    You are correct, that each press AND release of a key counts as a separate event. This is why a key press (and release) increments your event counter by 2.

    The configuration register (0x01) is used to setup which interrupts you want to have be sent through the interrupt pin to the host processor.

    Writing 0x01 to the CFG register should store 0x01 in it. If you are not seeing this behavior, I would suggest grabbing a scope shot of the I2C lines during the transaction and making sure that data is being sent as we'd expect.

    Beyond testing the device, we must first know your physicall connection from the boards to the TCA8418E so that we can know which rows and columns need to be setup in keyscan mode per the datasheet.

    IN short, the shortest, and most basic setup for the TCA8418 is the following:
    1) Write 0x11 to register 0x01 (CFG)
    2) Determine which rows and columns need to be configured for keyscan mode and set them in registers 0x1D-0x1F (KP_GPIO).
    3) Write 0xFF to register 0x02 (INT_STAT) to reset any interrupts.

    Any keypresses from this point, will pull the INT line low and keys will be in the FIFO (register 0x04)
  • i am using int pin connected to my processor. but i don't know how to configure this..
    in platform data //
    irq_is_gpio =1

    if (pdata->irq_is_gpio)
    client->irq = gpio_to_irq(client->irq);

    error = request_threaded_irq(client->irq, NULL,
    tca8418_irq_handler,
    IRQF_TRIGGER_FALLING,
    client->name, keypad_data);...
    this function have to probe tca8418_irq_handler and then keypad read .. i am i right? but whille booting and pressing key its not responding.

    as for your basic setup i configured those 3 points in tca8418_configuration.
  • i am using this application to check my keypad

    fd = open("/dev/input/event0", O_RDONLY);
    struct input_event ev;

    while (1)
    {
    read(fd, &ev, sizeof(struct input_event));

    if(ev.type == 1)
    //printf("key %i state %i\n", ev.code, ev.value);
    if(ev.value == 0)
    printf("Pressed key value:%d\n ", ev.code);
    }

    but i didnt get any output while pressing..
    also i checked using command cat /dev/input/event0.. i didnt get any response.
  • Thangameena,

    I am not familiar with Android-based implementations at the software level. Unfortunately, this means the extent of the help I can provide you is going to be on the register values you need to set and the proper procedure on how to read from the device at the I2C level. Your questions at the OS level about IRQ is not something I have any experience with, as my experience is specifically at the microcontroller C-based level.

    Have you looked at the open source Linux Driver for the TCA8418 that is online? It's not a written by TI, but I've had several customers look to that file as a starting point and modify it to fit their needs.

    In regards to the schematics you sent, it looks like you have some nodes named differently. For example, ROW1 coming out of the TCA8418E is labeled as ROW2_1, but on the buttons you refer to 'ROW2'. I notice some other inconsistencies like this on other buttons too. Perhaps it is how your editor splits the node, but I would check and make sure that all of these buttons are correctly connected.

    Also, I do not see a pull-up resistor on the INT pin from the TCA8418. Can you check to make sure that there is a 10k pull-up resistor (or similarly sized pullup). The INT pin is an open drain setup, so that you may pull the voltage up to any voltage you need for the CPU. The TCA8418 will pull the INT line low whenever there is an interrupt.

    You are using ROW0 - ROW7 and COL0-COL6 for your keypad array, so your KP_GPIO1-3 registers (0x1D-0x1F) should have ethe following values:
    0x1D (KP_GPIO1): 0xFF
    0x1E (KP_GPIO2): 0x7F
    0x1F (KP_GPIO3): 0x00

    Make sure that your debounce registers are all set to 0x00 to ENABLE debouncing
    0x29 (DEBOUNCE_DIS1): 0x00
    0x2A (DEBOUNCE_DIS2): 0x00
    0x2B (DEBOUNCE_DIS3): 0x00

    And you will require the internal pullups to be activated, so make sure the pull-up registers are set to 0x00 to enable the pullups (even on unused ports to prevent them from floating and setting random INTs)
    0x2C (GPIO_PULL1): 0x00
    0x2D (GPIO_PULL2): 0x00
    0x2E (GPIO_PULL3): 0x00


    Once you've set all of this up, I would make sure that the interrupts are all cleared by doing the following:
    1) Read KEY_EVENT_A (0x04) until you read back 0x00 to empty the FIFO
    2) Write 0xFF to INT_STAT (0x02) to reset all interrupts
    3) Make sure that the KE_IEN bit 0 is set in 0x01 to make sure key pad interrupts are enabled)

    Device should now be ready to read keypresses.

    In the event of a key press, your driver should get the interrupt request and your driver should:
    1) Read INT_STAT (0x02) register to see which interrupt was set. Chances are it will be the K_INT bit 0 for the keypad interrupt
    2) Read KEY_LCK_EC (0x03) register to check bits 0:3 to see how many events are stored in the FIFO.
    3) Read from KEY_EVENT_A register (0x04) to see which keys were pressed.
    4) Once the FIFO is empty (reading 0x00 from register 0x04 or the KLEC[3:0] bits are at 0), you need to clear the interrupt by writing 0xFF to INT_STAT (0x02) register.
    5) Then you wait for more key presses.
  • Hi Jonathan,

    Thanks for you brief explain... thank you.

     i didnt pull up the int pin instead i done high in my board file like as

    static void __init keypad_init(void){

    gpio_request(MX6SL_BRD_KEYPAD_INT, "keypad-int");

    gpio_direction_output(MX6SL_BRD_KEYPAD_INT, 1);

    }. but i am giving direction as output so it wont be low at the time of interrupt  am i right?

    but my config register bit 0(KE_IEN IS ALWAYS 1)  becoz initiallyi set configure as 0x11 to config regster(0x01)..

    my doubt is if i pullup the int pin my KE_IEN bit will get low at the time of interrupt? 

    another one is if i press the key its not going into my driver file.? i put a print statement at the irq_handler.. while booting time alone driver get loaded ..

  • Hello Thangameena,

    Am i to understand that you have your CPU outputting a high onto the INT pin?

    You are correct that you would not have the INT pin go low, but this could damage a device (either your CPU or the TCA8418) because of the CPU driver being high, and the TCA8418 trying to pull the signal low, this results in a short to ground for the CPU.

    Another issue with this approach is that your CPU will never know when the TCA8418 is requesting an interrupt. So unless you have your processor constantly polling the TCA8418, you will never get any keypresses.

    The proper approach is to use a pull-up resistor on the INT line (~10k ohms) to VCC and then have the INT line connected to the CPU and use that INT line (the high to low edge) as a trigger for your IRQ request.

  • Hi jonathan,

    thanks for your valuable reply,

    i understood that i have to pullup the int pin is must..

     then how can i tell my cpu the int pin is getting low for key interrupt . becoz in platform data we didn't mention the int pin.  i already mentioned my platform data. 

    irq|_is_gpio =1.  did i need to change?  in driver file  this only calling the interrupt.   i attached my driver.

    tca8418_keypad.c
    /*
    + * Driver for TCA8418 I2C keyboard
    + *
    + * Copyright (C) 2011 Fuel7, Inc.  All rights reserved.
    + *
    + * Author: Kyle Manna <kyle.manna@xxxxxxxxx>
    + *
    + * This program is free software; you can redistribute it and/or
    + * modify it under the terms of the GNU General Public
    + * License v2 as published by the Free Software Foundation.
    + *
    + * 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.
    + *
    + * You should have received a copy of the GNU General Public
    + * License along with this program; if not, write to the
    + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    + * Boston, MA 021110-1307, USA.
    + *
    + * If you can't comply with GPLv2, alternative licensing terms may be
    + * arranged. Please contact Fuel7, Inc. (http://fuel7.com/) for proprietary
    + * alternative licensing inquiries.
    + */
    
    #include <linux/types.h>
    #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/delay.h>
    #include <linux/slab.h>
    #include <linux/interrupt.h>
    #include <linux/workqueue.h>
    #include <linux/gpio.h>
    #include <linux/i2c.h>
    #include <linux/input.h>
    #include <linux/input/tca8418_keypad.h>
    
    /* TCA8418 hardware limits */
    #define TCA8418_MAX_ROWS	8
    #define TCA8418_MAX_COLS	10
    
    /* TCA8418 register offsets */
    #define REG_CFG			0x01
    #define REG_INT_STAT		0x02
    #define REG_KEY_LCK_EC		0x03
    #define REG_KEY_EVENT_A		0x04
    #define REG_KEY_EVENT_B		0x05
    #define REG_KEY_EVENT_C		0x06
    #define REG_KEY_EVENT_D		0x07
    #define REG_KEY_EVENT_E		0x08
    #define REG_KEY_EVENT_F		0x09
    #define REG_KEY_EVENT_G		0x0A
    #define REG_KEY_EVENT_H		0x0B
    #define REG_KEY_EVENT_I		0x0C
    #define REG_KEY_EVENT_J		0x0D
    #define REG_KP_LCK_TIMER	0x0E
    #define REG_UNLOCK1		0x0F
    #define REG_UNLOCK2		0x10
    #define REG_GPIO_INT_STAT1	0x11
    #define REG_GPIO_INT_STAT2	0x12
    #define REG_GPIO_INT_STAT3	0x13
    #define REG_GPIO_DAT_STAT1	0x14
    #define REG_GPIO_DAT_STAT2	0x15
    #define REG_GPIO_DAT_STAT3	0x16
    #define REG_GPIO_DAT_OUT1	0x17
    #define REG_GPIO_DAT_OUT2	0x18
    #define REG_GPIO_DAT_OUT3	0x19
    #define REG_GPIO_INT_EN1	0x1A
    #define REG_GPIO_INT_EN2	0x1B
    #define REG_GPIO_INT_EN3	0x1C
    #define REG_KP_GPIO1		0x1D
    #define REG_KP_GPIO2		0x1E
    #define REG_KP_GPIO3		0x1F
    #define REG_GPI_EM1		0x20
    #define REG_GPI_EM2		0x21
    #define REG_GPI_EM3		0x22
    #define REG_GPIO_DIR1		0x23
    #define REG_GPIO_DIR2		0x24
    #define REG_GPIO_DIR3		0x25
    #define REG_GPIO_INT_LVL1	0x26
    #define REG_GPIO_INT_LVL2	0x27
    #define REG_GPIO_INT_LVL3	0x28
    #define REG_DEBOUNCE_DIS1	0x29
    #define REG_DEBOUNCE_DIS2	0x2A
    #define REG_DEBOUNCE_DIS3	0x2B
    #define REG_GPIO_PULL1		0x2C
    #define REG_GPIO_PULL2		0x2D
    #define REG_GPIO_PULL3		0x2E
    
    /* TCA8418 bit definitions */
    #define CFG_AI			BIT(7)
    #define CFG_GPI_E_CFG		BIT(6)
    #define CFG_OVR_FLOW_M		BIT(5)
    #define CFG_INT_CFG		BIT(4)
    #define CFG_OVR_FLOW_IEN	BIT(3)
    #define CFG_K_LCK_IEN		BIT(2)
    #define CFG_GPI_IEN		BIT(1)
    #define CFG_KE_IEN		BIT(0)
    
    #define INT_STAT_CAD_INT	BIT(4)
    #define INT_STAT_OVR_FLOW_INT	BIT(3)
    #define INT_STAT_K_LCK_INT	BIT(2)
    #define INT_STAT_GPI_INT	BIT(1)
    #define INT_STAT_K_INT		BIT(0)
    
    /* TCA8418 register masks */
    #define KEY_LCK_EC_KEC		0x7
    #define KEY_EVENT_CODE		0x7f
    #define KEY_EVENT_VALUE		0x80
    
    
    static const struct i2c_device_id tca8418_id[] = {
    	{ TCA8418_NAME, 8418, },
    	{ }
    };
    MODULE_DEVICE_TABLE(i2c, tca8418_id);
    
    struct tca8418_keypad {
    	unsigned int	rows;
    	unsigned int	cols;
    	unsigned int	keypad_mask; /* Mask for keypad col/rol regs */
    	unsigned int	irq;
    	unsigned int	row_shift;
    
    	struct i2c_client *client;
    	struct input_dev  *input;
    
    	/* Flexible array member, must be at end of struct */
    	unsigned short	keymap[];
    };
    
    /*
     * Write a byte to the TCA8418
     */
    static int tca8418_write_byte(struct tca8418_keypad *keypad_data,
    		int reg, u8 val)
    {
    	int error;
    
    	error = i2c_smbus_write_byte_data(keypad_data->client, reg, val);
    
    printk("\n tca8418_write_byte keypad_data->client=");
    	if (error < 0) {
    printk("\n tca8418_write_byte error");
    		dev_err(&keypad_data->client->dev,
    				"%s failed, reg: %d, val: %d, error: %d\n",
    				__func__, reg, val, error);
    		return error;
    	}
    
    	return 0;
    }
    
    /*
     * Read a byte from the TCA8418
     */
    static int tca8418_read_byte(struct tca8418_keypad *keypad_data, int reg,
    		u8 *val)
    {
    	int error;
    	error = i2c_smbus_read_byte_data(keypad_data->client, reg);
    printk("\n tca8418_read_byte  keypad_data->client=");
    	if (error < 0) {
    printk("\n tca8418_read_byte error");
    		dev_err(&keypad_data->client->dev,
    				"%s failed, reg: %d, error: %d\n",
    				__func__, reg, error);
    		return error;
    	}
    
    	*val = (u8)error;
    	return 0;
    }
    
    static void tca8418_read_keypad(struct tca8418_keypad *keypad_data)
    {
    	int error, col, row;
    	u8 reg, state, code;
    	/* Initial read of the key event FIFO */
    	error = tca8418_read_byte(keypad_data, REG_KEY_EVENT_A, &reg);
    
    printk("\n tca8418_read_keypad");
    
    	/* Assume that key code 0 signifies empty FIFO */
    	while (error >= 0 && reg > 0) {
    printk("\n tca8418_read_keypad reg=%d  ",reg);
    		state = reg & KEY_EVENT_VALUE;
    		code  = reg & KEY_EVENT_CODE;
    
    		row = code / TCA8418_MAX_COLS;
    		col = code % TCA8418_MAX_COLS;
    
    		row = (col) ? row : row - 1;
    		col = (col) ? col - 1 : TCA8418_MAX_COLS - 1;
    
    		code = MATRIX_SCAN_CODE(row, col, keypad_data->row_shift);
    		input_event(keypad_data->input, EV_MSC, MSC_SCAN, code);
    		input_report_key(keypad_data->input,
    				keypad_data->keymap[code], state);
    
    		/* Read for next loop */
    		error = tca8418_read_byte(keypad_data, REG_KEY_EVENT_A, &reg);
    	};
    
    	if (error < 0){
    printk("\n tca8418_read_keypad error  ");
    		dev_err(&keypad_data->client->dev,
    				"unable to read REG_KEY_EVENT_A\n");
    }
    	input_sync(keypad_data->input);
    }
    
    static tca8418_irq_handler1(int irq, void *dev_id)
    {
    
    struct tca8418_keypad *keypad_data = dev_id;
    	u8 reg;
    	int error;
    
    	error = tca8418_read_byte(keypad_data, REG_INT_STAT, &reg);
    printk("\ntca8418 REG_INT_STAT1 =%d reg=%d",REG_INT_STAT,&reg);
    	if (error) {
    printk("\ntca8418 tca8418_irq_handler1 error");
    		dev_err(&keypad_data->client->dev,
    				"unable to read REG_INT_STAT\n");
    		goto exit;
    	}
    
    	if (reg & INT_STAT_OVR_FLOW_INT){
    printk("\ntca8418 reg =%d INT_STAT_OVR_FLOW_INT1%d",reg,INT_STAT_OVR_FLOW_INT);
    		dev_warn(&keypad_data->client->dev, "overflow occurred\n");
    }
    	if (reg & INT_STAT_K_INT){
    printk("\ntca8418 reg =%d INT_STAT_K_INT1=%d",reg,INT_STAT_K_INT);
    		tca8418_read_keypad(keypad_data);
    }
    
    exit:
    	/* Clear all interrupts, even IRQs we didn't check (GPI, CAD, LCK) */
    	reg = 0xff;
    	error = tca8418_write_byte(keypad_data, REG_INT_STAT, reg);
    printk("\ntca8418 tca8418_irq_handler REG_INT_STAT1 ");
    	if (error){
    printk("\ntca8418 tca8418_irq_handler1 error11");
    		dev_err(&keypad_data->client->dev,
    				"unable to clear REG_INT_STAT\n");
    }
    	return IRQ_HANDLED;
    }
    /*
     * Threaded IRQ handler and this can (and will) sleep.
     */
    static irqreturn_t tca8418_irq_handler(int irq, void *dev_id)
    {
    	struct tca8418_keypad *keypad_data = dev_id;
    	u8 reg;
    	int error;
    
    	error = tca8418_read_byte(keypad_data, REG_INT_STAT, &reg);
    printk("\ntca8418 REG_INT_STAT =%d reg=%d",REG_INT_STAT,&reg);
    	if (error) {
    printk("\ntca8418 tca8418_irq_handler error");
    		dev_err(&keypad_data->client->dev,
    				"unable to read REG_INT_STAT\n");
    		goto exit;
    	}
    
    	if (reg & INT_STAT_OVR_FLOW_INT){
    printk("\ntca8418 reg =%d INT_STAT_OVR_FLOW_INT=%d",reg,INT_STAT_OVR_FLOW_INT);
    		dev_warn(&keypad_data->client->dev, "overflow occurred\n");
    }
    	if (reg & INT_STAT_K_INT){
    printk("\ntca8418 reg =%d INT_STAT_K_INT=%d",reg,INT_STAT_K_INT);
    		tca8418_read_keypad(keypad_data);
    }
    
    exit:
    	/* Clear all interrupts, even IRQs we didn't check (GPI, CAD, LCK) */
    	reg = 0xff;
    	error = tca8418_write_byte(keypad_data, REG_INT_STAT, reg);
    printk("\ntca8418 tca8418_irq_handler REG_INT_STAT ");
    	if (error){
    printk("\ntca8418 tca8418_irq_handler error11");
    		dev_err(&keypad_data->client->dev,
    				"unable to clear REG_INT_STAT\n");
    }
    	return IRQ_HANDLED;
    }
    
    /*
     * Configure the TCA8418 for keypad operation
     */
    static int __devinit tca8418_configure(struct tca8418_keypad *keypad_data)
    {
    	int reg, error;
    
    	/* Write config register, if this fails assume device not present */
    	error = tca8418_write_byte(keypad_data, REG_CFG, CFG_INT_CFG | CFG_KE_IEN);
    				//CFG_INT_CFG | CFG_OVR_FLOW_IEN | CFG_KE_IEN);
    	if (error < 0)
    		return -ENODEV;
    printk("\ntca8418_configure");
    
    	/* Assemble a mask for row and column registers */
    	reg  =  ~(~0 << keypad_data->rows);
    	reg += (~(~0 << keypad_data->cols))<<8;
    	keypad_data->keypad_mask = reg;
    
    	/* Set registers to keypad mode */
    	error |= tca8418_write_byte(keypad_data, REG_KP_GPIO1, reg);
    	error |= tca8418_write_byte(keypad_data, REG_KP_GPIO2, reg>>8);
    	error |= tca8418_write_byte(keypad_data, REG_KP_GPIO3, reg>>16);
    
    reg =0x00;
    	/* Enable column debouncing */
    	error |= tca8418_write_byte(keypad_data, REG_DEBOUNCE_DIS1, reg);
    	error |= tca8418_write_byte(keypad_data, REG_DEBOUNCE_DIS2, reg>>8);
    	error |= tca8418_write_byte(keypad_data, REG_DEBOUNCE_DIS3, reg>>16);
    
    reg = 0xff;
    	error = tca8418_write_byte(keypad_data, REG_INT_STAT, reg);
    printk("\ntca8418 tca8418_irq_handler REG_INT_STAT ");
    
    	return error;
    }
    
    static int __devinit tca8418_keypad_probe(struct i2c_client *client,
    				   const struct i2c_device_id *id)
    {
    	struct tca8418_keypad_platform_data *pdata = client->dev.platform_data;
    	struct tca8418_keypad *keypad_data;
    	struct input_dev *input;
    	int error, row_shift, max_keys;
    
    printk("\ntca8418 start");
    
    	/* Copy the platform data */
    	if (!pdata) {
    		dev_dbg(&client->dev, "no platform data\n");
    		return -EINVAL;
    	}
    
    	if (!pdata->keymap_data) {
    		dev_err(&client->dev, "no keymap data defined\n");
    		return -EINVAL;
    	}
    
    	if (!pdata->rows || pdata->rows > TCA8418_MAX_ROWS) {
    		dev_err(&client->dev, "invalid rows\n");
    		return -EINVAL;
    	}
    	if (!pdata->cols || pdata->cols > TCA8418_MAX_COLS) {
    		dev_err(&client->dev, "invalid columns\n");
    		return -EINVAL;
    	}
    
    printk("\ntca8418 start1");
    	/* Check i2c driver capabilities */
    	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) {
    		dev_err(&client->dev, "%s adapter not supported\n",
    			dev_driver_string(&client->adapter->dev));
              printk("\ntca8418 i2c_check_functionality");
    		return -ENODEV;
    	}
    	row_shift = get_count_order(pdata->cols);
    	max_keys = pdata->rows << row_shift;
    
    	/* Allocate memory for keypad_data, keymap and input device */
    	keypad_data = kzalloc(sizeof(*keypad_data) +
    			max_keys * sizeof(keypad_data->keymap[0]), GFP_KERNEL);
    	if (!keypad_data)
    		return -ENOMEM;
    printk("\ntca8418 start2");
    
    	keypad_data->rows = pdata->rows;
    	keypad_data->cols = pdata->cols;
    	keypad_data->client = client;
    	keypad_data->row_shift = row_shift;
    
    
    	/* Initialize the chip or fail if chip isn't present */
    	error = tca8418_configure(keypad_data);
    	if (error < 0)
    		goto fail1;
    
    printk("\ntca8418 start3");
    	/* Configure input device */
    	input = input_allocate_device();
    	if (!input) {
    		error = -ENOMEM;
    		goto fail1;
    	}
    
    printk("\ntca8418 start4");
    	keypad_data->input = input;
    
    	input->name = client->name;
    	input->dev.parent = &client->dev;
    
    	input->id.bustype = BUS_I2C;
    	input->id.vendor  = 0x0001;
    	input->id.product = 0x001;
    	input->id.version = 0x0001;
    
    	input->keycode     = keypad_data->keymap;
    	input->keycodesize = sizeof(keypad_data->keymap[0]);
    	input->keycodemax  = max_keys;
    
            printk("\ntca8418 start4.1");
    	__set_bit(EV_KEY, input->evbit);
    	if (pdata->rep)
    		__set_bit(EV_REP, input->evbit);
            printk("\ntca8418 start4.2");
    	input_set_capability(input, EV_MSC, MSC_SCAN);
    
             printk("\ntca8418 start4.3");
    
    	input_set_drvdata(input, keypad_data);
    
               
    
    	matrix_keypad_build_keymap(pdata->keymap_data, row_shift,
    			input->keycode, input->keybit);
    
    	if (pdata->irq_is_gpio)
    		client->irq = gpio_to_irq(client->irq);
    
    	error = request_threaded_irq(client->irq, NULL,
    				     tca8418_irq_handler,
    				     //IRQF_TRIGGER_FALLING,
                                         //IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
                                            IRQF_TRIGGER_FALLING |
                                                     IRQF_SHARED |
                                                     IRQF_ONESHOT,
    				     client->name, keypad_data);
    
    
    	if (error) {
    		dev_dbg(&client->dev,
    		"Unable to claim irq %d; error %d\n",
    			client->irq, error);
           printk("\ntca8418 start4.4");
    		goto fail2;
    	}
    tca8418_irq_handler1(client->name,keypad_data);
    printk("\ntca8418 start5");
    	error = input_register_device(input);
    	if (error) {
    		dev_dbg(&client->dev,
    			"Unable to register input device, error: %d\n", error);
    		goto fail3;
    	}
    printk("\ntca8418 start6");
    	i2c_set_clientdata(client, keypad_data);
    	goto exit;
    
    
    fail3:
    	free_irq(client->irq, keypad_data);
    fail2:
    	input_free_device(input);
    fail1:
    	kfree(keypad_data);
    exit:
    	return error;
    }
    
    static int __devexit tca8418_keypad_remove(struct i2c_client *client)
    {
    	struct tca8418_keypad *keypad_data = i2c_get_clientdata(client);
    
    	free_irq(keypad_data->client->irq, keypad_data);
    
    	input_unregister_device(keypad_data->input);
    printk("\ntca8418 _keypad_remove");
    	kfree(keypad_data);
    
    	return 0;
    }
    
    
    static struct i2c_driver tca8418_keypad_driver = {
    	.driver = {
    		.name	= TCA8418_NAME,
    		.owner	= THIS_MODULE,
    	},
    	.probe		= tca8418_keypad_probe,
    	.remove		= __devexit_p(tca8418_keypad_remove),
    	.id_table	= tca8418_id,
    };
    
    static int __init tca8418_keypad_init(void)
    {
    	return i2c_add_driver(&tca8418_keypad_driver);
    }
    subsys_initcall(tca8418_keypad_init);
    
    static void __exit tca8418_keypad_exit(void)
    {
    	i2c_del_driver(&tca8418_keypad_driver);
    }
    module_exit(tca8418_keypad_exit);
    
    MODULE_AUTHOR("Kyle Manna <kyle.manna@xxxxxxxxx>");
    MODULE_DESCRIPTION("Keypad driver for TCA8418");
    MODULE_LICENSE("GPL");
    

  • Hello Jonathan ,

    i referred this link e2e.ti.com/.../388003

    this is dts file for kernel 3.10. they mention the gpio for interrupt.. they have inbuilt driver file.

    i am using kernel 3.0 & kitkat 4.4.2, tca8418 will support? i downloaded driver from website..
  • Thangameena,

    UNfortunately, as this is a linux driver on I.MX6 processor question, I do not have the ability to answer.

    From what I've found when looking online, it appears that in some versions of the linux kernal, the irq_is_gpio function was removed. I do not know if this is the case with KitKat 4.4.2 and kernel 3.0. It looks like it was in a later version of the kernel, so you might be ok here.


    The IRQ pin is defined during the __tca8418_keypad_probe function, getting passed in through the platform data struct. This it taken from the dts file. You will need to include the GPIO pin you are using in the DTS file.

    At this point, you might need to head over to the freescale forums as this is a general software question for their I.mx6. The driver you have should work, but you need to make sure you have a dts entry for the TCA8418.
  • Hi Jonathan,

    thankyou  . now  iam clear the driver will work

     .without the use of interrupt making low.. how can i communicate through i2c for key interrupt while pressing is it possible? becoz i can't pull up now . for that we need to do again.

  • Hi Jonathan,

    Thankyou so much....................thanks

    my keypad is working in now . tested using cat /dev/input/event0 then added executable

    i changed the platform data
    irq_is_gpio=0,

    then i gave
    I2C_BOARD_INFO(TCA8418_NAME, 0x34),
    .platform_data = &tca8418_data,
    .irq = gpio_to_irq(MX6SL_BRD_KEYPAD_INT),

    now it taking interrupt while pressing its load interrupt function in driver file and read keypad


    now i need to bring this in android .
    for that i added keylayout and idc file under/system/usr.

    did i need anything else?
  • Glad to hear it is working for you.

    Your follow-up question for bringing the keypresses into android, will require some research on the android API. I do not have any experience with this, and cannot provide any help, unfortunately.
  • Hi Jonathan,

    Thanks for your information.

     where can i get documents related  android keyboard interface.  did i need any apk for this..

    becoz when i opened  browser page or something touch keypad will pop up and we will give input using touch..

    then how can i interface my tca8418 keypad will give input in the window. i didn get a clear idea regarding this. 

  • Hello Thangameena,

    While I do not have any Android programming experience, I found this android reference on the android source website (source.android.com): source.android.com/.../keyboard-devices.html

    I would suggest searching through that website, as they seem to have a lot of the interfacing code there.
  • Hi Jonathan,

    thanks..Yes i have seen ..  i will try  this..

    Thanks for your support.

  • Hello,

    It seems that TCA8418 linux driver does not support gpio (only through matrx).
    Is that correct ? How can I add gpio support ?

    Regards,
    Ran
  • Hello Ran,

    I have replied to your other thread. Please see e2e.ti.com/.../1702469
  • It is correct. Thank you