static ssize_t touchkey_firmup_store(struct device *dev,
        struct device_attribute *attr, const char *buf, size_t size)
{
	if(Flip_status){
		printk(KERN_ERR "[TKEY] flip opened\n");
		melfas_touchkey_switch_early_resume(Flip_status,1);
	}else{
		disable_irq(touchkey_driver->client->irq);
	}
	printk(TCHKEY_KERN_DEBUG "Touchkey firm-up start!\n");
	get_touchkey_data(version_info, 3);
	printk(TCHKEY_KERN_DEBUG "F/W version: 0x%x, Module version:0x%x\n", version_info[1], version_info[2]);
	if ((version_info[1] < MCS5080_last_ver) || (version_info[1] == 0xff)){
		mdelay(350);
		mcsdl_download_binary_data(MCS5080_CHIP);
		mdelay(100);
		get_touchkey_data(version_info, 3);
		printk(TCHKEY_KERN_DEBUG "Updated F/W version: 0x%x, Module version:0x%x\n", version_info[1], version_info[2]);
	}
	else
		printk(KERN_ERR "Touchkey IC module is new, can't update!");
	if(Flip_status){
		printk(KERN_ERR "[TKEY] flip opened\n");
		melfas_touchkey_switch_early_suspend(Flip_status,1);
	}else{
		enable_irq(touchkey_driver->client->irq);
	}
	return size;
}
static ssize_t touchkey_firmup_show(struct device *dev,
        struct device_attribute *attr, char *buf)
{
	printk(TCHKEY_KERN_DEBUG "Touchkey firm-up start!\n");
	if(version_info[2]==MCS5000_CHIP)
		mcsdl_download_binary_data(MCS5000_CHIP);
	else if(version_info[2]==MCS5080_CHIP)
		mcsdl_download_binary_data(MCS5080_CHIP);
	else
		printk(KERN_ERR "Touchkey IC module is old, can't update!");

	get_touchkey_data(version_info, 3);
	printk(TCHKEY_KERN_DEBUG "Updated F/W version: 0x%x, Module version:0x%x\n", version_info[1], version_info[2]);
	return sprintf(buf,"%02x\n",version_info[1]);
}
static int i2c_touchkey_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
	struct device *dev = &client->dev;
	struct input_dev *input_dev;
	struct melfas_touchkey_platform_data *pdata;
	int err = 0;
printk(KERN_ERR "[TKEY] %s\n",__func__);
	printk("melfas touchkey probe called!\n");
	touchkey_driver = kzalloc(sizeof(struct i2c_touchkey_driver), GFP_KERNEL);
	if (touchkey_driver == NULL)
	{
		dev_err(dev, "failed to create our state\n");
		return -ENOMEM;
	}

	if (client->dev.of_node) {
		pdata = devm_kzalloc(&client->dev,
			sizeof(struct melfas_touchkey_platform_data),
				GFP_KERNEL);
		if (!pdata) {
			dev_info(&client->dev, "Failed to allocate memory\n");
			return -ENOMEM;
		}

		err = melfas_parse_dt(&client->dev, pdata);
		if (err)
			return err;
	}else
		pdata = client->dev.platform_data;

	melfas_request_gpio(pdata);

//	init_hw();
/*
	melfas_power_onoff(pdata,1);

	msleep(100);

	get_touchkey_data(version_info, 3);

	printk(TCHKEY_KERN_DEBUG "%s F/W version: 0x%x, Module version:0x%x\n",__FUNCTION__, version_info[1], version_info[2]);
*/

	irq_set_irq_type(gpio_to_irq(pdata->gpio_int), IRQF_TRIGGER_FALLING);

	melfas_config_gpio_i2c(pdata, 0);

	get_touchkey_data(version_info, 3);

	printk(TCHKEY_KERN_DEBUG "%s F/W version: 0x%x, Module version:0x%x\n",__FUNCTION__, version_info[1], version_info[2]);



	touchkey_driver->client = client;

	touchkey_driver->client->irq = gpio_to_irq(pdata->gpio_int);

	strlcpy(touchkey_driver->client->name, "melfas_touchkey", I2C_NAME_SIZE);

	input_dev = input_allocate_device();

	if (!input_dev)
		return -ENOMEM;

	touchkey_driver->input_dev = input_dev;

	input_dev->name = DEVICE_NAME;
	input_dev->phys = "melfas_touchkey/input0";
	input_dev->id.bustype = BUS_HOST;

	set_bit(EV_SYN, input_dev->evbit);
	set_bit(EV_LED, input_dev->evbit);
	set_bit(LED_MISC, input_dev->ledbit);
	set_bit(EV_KEY, input_dev->evbit);
	set_bit(touchkey_keycode[1], input_dev->keybit);
	set_bit(touchkey_keycode[2], input_dev->keybit);
	set_bit(touchkey_keycode[3], input_dev->keybit);
	set_bit(touchkey_keycode[4], input_dev->keybit);

	mutex_init(&melfas_tsk_lock);

	err = input_register_device(input_dev);
	if (err)
	{
		input_free_device(input_dev);
		return err;
	}

	gpio_pend_mask_mem = ioremap(INT_PEND_BASE, 0x10);
	touchkey_wq = create_singlethread_workqueue("melfas_touchkey_wq");
	if (!touchkey_wq)
		return -ENOMEM;

	INIT_WORK(&touchkey_driver->work, touchkey_work_func);

#ifdef CONFIG_HAS_EARLYSUSPEND
	touchkey_driver->early_suspend.suspend = melfas_touchkey_early_suspend;
	touchkey_driver->early_suspend.resume = melfas_touchkey_early_resume;
	register_early_suspend(&touchkey_driver->early_suspend);
#endif				/* CONFIG_HAS_EARLYSUSPEND */
	touchkey_enable = 1;
	if (request_irq(touchkey_driver->client->irq, touchkey_interrupt, IRQF_DISABLED, DEVICE_NAME, touchkey_driver))
	{
		printk(KERN_ERR "%s Can't allocate irq ..\n", __FUNCTION__);
		return -EBUSY;
	}
	return 0;
}
static int __init touchkey_init(void)
{

	int ret = 0;

	u8 updated = 0;
	if ((ret = gpio_request(_3_GPIO_TOUCH_EN, "_3_GPIO_TOUCH_EN")))
		printk(KERN_ERR "Failed to request gpio %s:%d\n", __func__, __LINE__);

//	if (ret = gpio_request(_3_GPIO_TOUCH_INT, "_3_GPIO_TOUCH_INT"))
//		printk(KERN_ERR "Failed to request gpio %s:%d\n", __func__, __LINE__);

	ret = misc_register(&touchkey_update_device);
	if (ret) {
		printk(KERN_ERR "%s misc_register fail\n",__FUNCTION__);
	}

	if (device_create_file(touchkey_update_device.this_device, &dev_attr_touchkey_activation) < 0)
	{
		printk(KERN_ERR "%s device_create_file fail dev_attr_touchkey_activation\n",__FUNCTION__);
		pr_err("Failed to create device file(%s)!\n", dev_attr_touchkey_activation.attr.name);
	}

	if (device_create_file(touchkey_update_device.this_device, &dev_attr_touchkey_version) < 0)
	{
		printk(KERN_ERR "%s device_create_file fail dev_attr_touchkey_version\n",__FUNCTION__);
		pr_err("Failed to create device file(%s)!\n", dev_attr_touchkey_version.attr.name);
	}

	if (device_create_file(touchkey_update_device.this_device, &dev_attr_touchkey_recommend) < 0)
	{
		printk(KERN_ERR "%s device_create_file fail dev_attr_touchkey_recommend\n",__FUNCTION__);
		pr_err("Failed to create device file(%s)!\n", dev_attr_touchkey_recommend.attr.name);
	}

	if (device_create_file(touchkey_update_device.this_device, &dev_attr_touchkey_firmup) < 0)
	{
		printk(KERN_ERR "%s device_create_file fail dev_attr_touchkey_firmup\n",__FUNCTION__);
		pr_err("Failed to create device file(%s)!\n", dev_attr_touchkey_firmup.attr.name);
	}

	if (device_create_file(touchkey_update_device.this_device, &dev_attr_touchkey_init) < 0)
	{
		printk(KERN_ERR "%s device_create_file fail dev_attr_touchkey_init\n",__FUNCTION__);
		pr_err("Failed to create device file(%s)!\n", dev_attr_touchkey_init.attr.name);
	}

	if (device_create_file(touchkey_update_device.this_device, &dev_attr_touchkey_menu) < 0)
	{
		printk(KERN_ERR "%s device_create_file fail dev_attr_touchkey_menu\n",__FUNCTION__);
		pr_err("Failed to create device file(%s)!\n", dev_attr_touchkey_menu.attr.name);
	}

	if (device_create_file(touchkey_update_device.this_device, &dev_attr_touchkey_back) < 0)
	{
		printk(KERN_ERR "%s device_create_file fail dev_attr_touchkey_back\n",__FUNCTION__);
		pr_err("Failed to create device file(%s)!\n", dev_attr_touchkey_back.attr.name);
	}

	if (device_create_file(touchkey_update_device.this_device, &dev_attr_brightness) < 0)
	{
		printk(KERN_ERR "%s device_create_file fail dev_attr_brightness\n",__FUNCTION__);
		pr_err("Failed to create device file(%s)!\n", dev_attr_brightness.attr.name);
	}

	if (device_create_file(touchkey_update_device.this_device, &dev_attr_enable_disable) < 0)
	{
		printk(KERN_ERR "%s device_create_file fail dev_attr_touch_update\n",__FUNCTION__);
		pr_err("Failed to create device file(%s)!\n", dev_attr_enable_disable.attr.name);
	}

	init_hw();

	get_touchkey_data(version_info, 3);
	printk(TCHKEY_KERN_DEBUG "%s F/W version: 0x%x, Module version:0x%x\n",__FUNCTION__, version_info[1], version_info[2]);

//-------------------   Auto Firmware Update Routine Start   -------------------//
	if(HWREV>=8)
	{
		if(version_info[1]==0xff) //unknown firmware state
		{
			if(!mcsdl_download_binary_data(MCS5000_CHIP)) //try MCS-5000 download
				mcsdl_download_binary_data(MCS5080_CHIP); // if first try is fail, MCS-5080 download

			updated = 1;
		}
		else
		{
			if(version_info[2]>=MCS5000_CHIP) //MCS-5000
			{
				if(version_info[1]!=MCS5000_last_ver) //not latest version
				{
					mcsdl_download_binary_data(MCS5000_CHIP);
					updated = 1;
				}
			}
			else if(version_info[2]==MCS5080_CHIP)//MCS-5080
			{
				if(version_info[1]!=MCS5080_last_ver) //not latest version
				{
					mcsdl_download_binary_data(MCS5080_CHIP);
					updated = 1;
				}
			}
			else
				printk("Touchkey IC module is old, can't update!");
		}

		if(updated)
		{
			get_touchkey_data(version_info, 3);
			printk(TCHKEY_KERN_DEBUG "Updated F/W version: 0x%x, Module version:0x%x\n", version_info[1], version_info[2]);
		}
	}
//-------------------   Auto Firmware Update Routine End   -------------------//

	ret = i2c_add_driver(&touchkey_i2c_driver);

	if(ret||(touchkey_driver==NULL))
	{
		touchkey_dead = 1;
		printk("ret = %d, touch_driver= %p:", ret, touchkey_driver);
		printk(KERN_ERR
		       "melfas touch keypad registration failed, module not inserted.ret= %d\n",
		       ret);
	}

	return ret;
}
void  touchkey_work_func(struct work_struct * p)
{
	u8 data[5];
	int keycode;
	int retry = 10;

	if(!gpio_get_value(_3_GPIO_TOUCH_INT) && !touchkey_dead)
	{
		get_touchkey_data(data, 5);

		if((data[0] & ESD_STATE_BIT)|(data[3]>=45)|(data[4]>=45)) // ESD state or abnormal sensitivity
		{
			is_suspending = 1;
			printk(KERN_ERR "touchkey ESD_STATE_BIT set\n");
			if(user_press_on==1)
			{
				input_report_key(touchkey_driver->input_dev, TOUCHKEY_KEYCODE_MENU, 0);
				printk(TCHKEY_KERN_DEBUG "ESD release menu key\n");
			}
			else if(user_press_on==2)
			{
				input_report_key(touchkey_driver->input_dev, TOUCHKEY_KEYCODE_BACK, 0);
				printk(TCHKEY_KERN_DEBUG "ESD release back key\n");
			}
			user_press_on = 0;

			while(retry--)
			{
				gpio_direction_output(_3_GPIO_TOUCH_EN, 0);
				gpio_direction_output(_3_TOUCH_SDA_28V, 0);
				gpio_direction_output(_3_TOUCH_SCL_28V, 0);
				msleep(300);
				init_hw();
				if(i2c_touchkey_read(KEYCODE_REG, data, 3)>=0)
				{
					printk(TCHKEY_KERN_DEBUG "touchkey ESD init success\n");
					enable_irq(IRQ_TOUCH_INT);
					is_suspending = 0;
					return;
				}
				printk(KERN_ERR "i2c transfer error after ESD, retry...%d",retry);
			}
			touchkey_dead = 1;
			gpio_direction_output(_3_GPIO_TOUCH_EN, 0);
			gpio_direction_output(_3_TOUCH_SDA_28V, 0);
			gpio_direction_output(_3_TOUCH_SCL_28V, 0);
			printk(KERN_ERR "touchkey died after ESD");
			return;
		}
		else
		{
			keycode = touchkey_keycode[data[0] & KEYCODE_BIT];
		}

		if(activation_onoff){
			if(data[0] & UPDOWN_EVENT_BIT) // key released
			{
				user_press_on = 0;
				input_report_key(touchkey_driver->input_dev, keycode, 0);
				input_sync(touchkey_driver->input_dev);
//				printk(TCHKEY_KERN_DEBUG "touchkey release keycode: %d\n", keycode);
			}
			else // key pressed
			{

				if(touch_state_val == 1)
				{
					printk(TCHKEY_KERN_DEBUG "touchkey pressed but don't send event because touch is pressed. \n");
				}
				else
				{
					if(keycode==TOUCHKEY_KEYCODE_BACK)
					{
						//TSP_forced_release(); Jiseong.oh
#ifdef CONFIG_CPU_FREQ
//						set_dvfs_target_level(LEV_800MHZ);//set to comment temporarily by mseok.chae 2011.01.11
#endif
						user_press_on = 2;
						back_sensitivity = data[4];
						input_report_key(touchkey_driver->input_dev, keycode,1);
						input_sync(touchkey_driver->input_dev);
//						printk(TCHKEY_KERN_DEBUG "back key sensitivity = %d\n",back_sensitivity);
//						printk(TCHKEY_KERN_DEBUG " touchkey press keycode: %d\n", keycode);
					}
					else if(keycode==TOUCHKEY_KEYCODE_MENU)
					{
						user_press_on = 1;
						menu_sensitivity = data[3];
						input_report_key(touchkey_driver->input_dev, keycode,1);
						input_sync(touchkey_driver->input_dev);
//						printk(TCHKEY_KERN_DEBUG "menu key sensitivity = %d\n",menu_sensitivity);
//						printk(TCHKEY_KERN_DEBUG " touchkey press keycode: %d\n", keycode);
					}
				}
			}
		}
	}
	else
		printk(KERN_ERR "touchkey interrupt line is high!\n");

	enable_irq(IRQ_TOUCH_INT);
	return ;
}