static ssize_t touchkey_idac1_show(struct device *dev,
					struct device_attribute *attr,
					char *buf)
{
	struct cptk_data *tkey_i2c = dev_get_drvdata(dev);
	u8 data = -1;

	cptk_i2c_read(tkey_i2c, IDAC_REG+1, &data, sizeof(data));

	return sprintf(buf, "%d\n", data);
}
static ssize_t touchkey_threshold_show(struct device *dev,
					struct device_attribute *attr,
					char *buf)
{
	struct cptk_data *tkey_i2c = dev_get_drvdata(dev);
	u8 data;
	int ret;

	ret = cptk_i2c_read(tkey_i2c, THRESHOLD_REG, &data, sizeof(data));

	return sprintf(buf, "%d\n", data);

}
static ssize_t touchkey_raw_data1_show(struct device *dev,
					struct device_attribute *attr,
					char *buf)
{
	struct cptk_data *tkey_i2c = dev_get_drvdata(dev);
	u8 data[2];
	u16 raw_data1 = 0;

	if (cptk_i2c_read(tkey_i2c, RAW_DATA_REG + 2, data, sizeof(data)) >= 0)
		raw_data1 = ((0x00FF & data[0]) << 8) | data[1];

	return sprintf(buf, "%d\n", raw_data1);
}
static ssize_t touchkey_autocal_status_show(struct device *dev,
						struct device_attribute *attr,
						char *buf)
{
	struct cptk_data *tkey_i2c = dev_get_drvdata(dev);
	u8 data;
	int ret;

	ret = cptk_i2c_read(tkey_i2c, AUTOCAL_REG, &data, sizeof(data));
	if (data & TK_BIT_AUTOCAL)
		return sprintf(buf, "Enabled\n");

	return sprintf(buf, "Disabled\n");
}
static void cptk_update_firmware_cb(const struct firmware *fw, void *context)
{

	int ret;
	struct cptk_data *cptk = context;
	struct device *dev = &cptk->input_dev->dev;
	int retries = 3;

	pr_info("cptk: firware download start\n");

	if (fw->size != FW_SIZE) {
		dev_err(dev, "%s: Firmware file size invalid size:%d\n",
							__func__, fw->size);
		return;
	}

	mutex_lock(&cptk->lock);

	disable_irq(cptk->client->irq);

	/* Lock the i2c bus since the firmware updater accesses it */
	i2c_lock_adapter(cptk->client->adapter);
	while (retries--) {
		ret = touchkey_flash_firmware(cptk->pdata, fw->data);
		if (!ret)
			break;
	}
	if (ret) {
		cptk->touchkey_update_status = -1;
		dev_err(dev, "%s: Firmware update failed\n", __func__);
	} else {
		cptk->touchkey_update_status = 0;
		pr_info("cptk: firware download finished\n");
	}

	i2c_unlock_adapter(cptk->client->adapter);
	enable_irq(cptk->client->irq);

	release_firmware(fw);
	mutex_unlock(&cptk->lock);

	cptk_i2c_read(cptk, KEYCODE_REG, cptk->cur_firm_ver,
						sizeof(cptk->cur_firm_ver));

	pr_info("cptk: current firm ver = 0x%.2x, latest firm ver = 0x%.2x\n",
				cptk->cur_firm_ver[1], cptk->pdata->firm_ver);

	return;
}
static ssize_t touchkey_menu_show(struct device *dev,
					struct device_attribute *attr,
					char *buf)
{
	struct cptk_data *cptk = dev_get_drvdata(dev);
	u8 data[2];
	int menu_sensitivity = 0;

	mutex_lock(&cptk->lock);
	if (cptk_i2c_read(cptk, DIFF_DATA_REG, data, sizeof(data)) >= 0)
		menu_sensitivity = ((0x00FF&data[0])<<8)|data[1];

	pr_debug("cptk: menu_sensitivity = %d\n", menu_sensitivity);

	mutex_unlock(&cptk->lock);

	return sprintf(buf, "%d\n", menu_sensitivity);
}
static ssize_t touchkey_back_show(struct device *dev,
		struct device_attribute *attr, char *buf)
{

	u8 data[2];
	int ret;
	int back_sensitivity;

	struct cptk_data *cptk = dev_get_drvdata(dev);
	mutex_lock(&cptk->lock);
	ret = cptk_i2c_read(cptk, DIFF_DATA_REG + 2,
			data, sizeof(data));

	back_sensitivity = ((0x00FF&data[0])<<8)|data[1];
	pr_debug("cptk : back_sensitivity = %d\n", back_sensitivity);

	mutex_unlock(&cptk->lock);

	return sprintf(buf, "%d\n", back_sensitivity);
}
static ssize_t set_touchkey_firm_version_read_show
(struct device *dev, struct device_attribute *attr, char *buf)
{
	char data[3] = { 0, };
	int count, ret;
	struct cptk_data *cptk = dev_get_drvdata(dev);

	mutex_lock(&cptk->lock);
	ret = cptk_i2c_read(cptk, KEYCODE_REG, data, 3);
	if (ret) {
		pr_err("cptk : %s: error in cptk_i2c_read\n" , __func__);
		mutex_unlock(&cptk->lock);
		return ret;
	}
	mutex_unlock(&cptk->lock);
	count = sprintf(buf, "0x%X\n", data[1]);
	pr_debug("cptk :touch_version_read 0x%X\n", data[1]);

	return count;
}
static irqreturn_t cptk_irq_thread(int irq, void *data)
{
	struct cptk_data *cptk = data;
	int ret;
	u8 keycode;

	mutex_lock(&cptk->lock);
	if (!gpio_get_value(cptk->pdata->gpio)) {
		ret = cptk_i2c_read(cptk, KEYCODE_REG, &keycode, 1);
		if (keycode & UPDOWN_EVENT_BIT)
			input_report_key(cptk->input_dev,
					cptk->pdata->keymap[keycode &
					KEYCODE_BIT], 0);
		else
			input_report_key(cptk->input_dev,
					cptk->pdata->keymap[keycode &
					KEYCODE_BIT], 1);

		input_sync(cptk->input_dev);
	}
	mutex_unlock(&cptk->lock);

	return IRQ_HANDLED;
}
static int __init cptk_i2c_probe(struct i2c_client *client,
						const struct i2c_device_id *id)
{
	struct cptk_data		*cptk;
	struct cptk_platform_data       *pdata = client->dev.platform_data;
	struct device_node *np = client->dev.of_node;
	int ret = -ENODEV;
	int i;

	if (IS_ENABLED(CONFIG_OF)) {
		if (!pdata) {
			pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
			if (unlikely(!pdata))
				return -ENOMEM;
		}
		ret = cptk_probe_dt(np, &client->dev, pdata);
		if (ret)
			goto err_exit1;
	}
	else if (!pdata) {
		dev_err(&client->dev, "%s: missing pdata\n", __func__);
		return ret;
	}

	cptk = kzalloc(sizeof(struct cptk_data), GFP_KERNEL);
	if (unlikely(!cptk)) {
		dev_err(&client->dev, "failed to allocate driver data\n");
		ret = -ENOMEM;
		goto err_exit1;
	}

	cptk->pdata = pdata;

	ret = gpio_request(pdata->gpio, "TOUCHKEY_INT");
	if (ret < 0) {
		pr_err("%s: gpio request touchkey interrupt failed!, ret = %d\n", __func__, ret);
		goto err_exit2;
	}

	ret = gpio_request(pdata->en_pin, "TOUCHKEY_EN");
	if (ret < 0) {
		pr_err("%s: gpio request for touchkey ldo failed!, ret = %d\n", __func__, ret);
		goto err_exit3;
	}
	gpio_direction_output(pdata->en_pin, GPIOF_INIT_LOW);

	cptk->input_dev = input_allocate_device();
	if (unlikely(!cptk->input_dev)) {
		dev_err(&client->dev, "failed to allocate memory\n");
		ret = -ENOMEM;
		goto err_exit4;
	}

	cptk->client = client;
	strlcpy(cptk->client->name, "cypress-touchkey", I2C_NAME_SIZE);
	cptk->client->dev.init_name = DEVICE_NAME;
	i2c_set_clientdata(client, cptk);

	cptk->input_dev->name = DEVICE_NAME;
	cptk->input_dev->phys = "cypress-touchkey/input0";
	cptk->input_dev->id.bustype = BUS_HOST;
	cptk->input_dev->dev.parent = &client->dev;

	set_bit(EV_SYN, cptk->input_dev->evbit);
	set_bit(EV_KEY, cptk->input_dev->evbit);
	set_bit(EV_LED, cptk->input_dev->evbit);
	set_bit(LED_MISC, cptk->input_dev->ledbit);

	for (i = 1; i < cptk->pdata->keymap_size; i++)
		set_bit(cptk->pdata->keymap[i], cptk->input_dev->keybit);

	ret = input_register_device(cptk->input_dev);
	if (ret) {
		input_free_device(cptk->input_dev);
		goto err_exit4;
	}

	mutex_init(&cptk->i2c_lock);
	mutex_init(&cptk->lock);

	if (cptk->pdata->power)
		cptk->pdata->power(1);
	cptk->enable = true;

	/* Check Touch Key IC connect properly && read IC fw. version */
	ret = cptk_i2c_read(cptk, KEYCODE_REG, cptk->cur_firm_ver,
						sizeof(cptk->cur_firm_ver));
	if (ret < 0) {
		pr_err("cptk: %s: touch key IC is not connected.\n", __func__);
		goto err_exit5;
	}

	pr_info("cptk: module ver = 0x%.2x, IC firm ver = 0x%.2x, binary firm ver = 0x%.2x\n",
			cptk->cur_firm_ver[2],
			cptk->cur_firm_ver[1],
			cptk->pdata->firm_ver);

	if (cptk->cur_firm_ver[2] == cptk->pdata->mod_ver) {
		if (cptk->cur_firm_ver[1] < cptk->pdata->firm_ver) {
			pr_info("cptk: force firmware update\n");
			ret = cptk_update_firmware(cptk);
			if (ret)
				goto err_exit5;
		}
	}

#ifdef CONFIG_PM_RUNTIME
	pm_runtime_enable(&client->dev);
#endif

	cptk_i2c_write(cptk, KEYCODE_REG, AUTO_CAL_MODE_CMD);
	cptk_i2c_write(cptk, CMD_REG, AUTO_CAL_EN_CMD);

	ret = request_threaded_irq(client->irq,
					NULL,
					cptk_irq_thread,
					IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
					DEVICE_NAME,
					cptk);
	if (ret < 0) {
		dev_err(&client->dev, "failed to register interrupt\n");
		goto err_exit5;
	}

#ifdef CONFIG_MACH_PXA_SAMSUNG
	ret = cptk_create_sec_touchkey(cptk);
	if (ret < 0)
		goto err_exit6;
#endif
	return 0;

err_exit6:
	free_irq(client->irq, cptk);
err_exit5:
	input_unregister_device(cptk->input_dev);
err_exit4:
	gpio_free(pdata->en_pin);
err_exit3:
	gpio_free(pdata->gpio);
err_exit2:
	kfree(cptk);
err_exit1:
	if(IS_ENABLED(CONFIG_OF) && pdata) {
		if(pdata->keymap)
			devm_kfree(&client->dev, (void *)pdata->keymap);
		devm_kfree(&client->dev, (void *)pdata);
	}
	return ret;
}
static int __devinit cptk_i2c_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{
	struct cptk_data *cptk;
	int ret;
	int i;

	cptk = kzalloc(sizeof(struct cptk_data), GFP_KERNEL);
	if (!cptk) {
		dev_err(&client->dev, "failed to allocate driver data\n");
		return -ENOMEM;
	}

	cptk->input_dev = input_allocate_device();
	if (!cptk->input_dev)
		return -ENOMEM;

	cptk->pdata = client->dev.platform_data;
	if (!cptk->pdata) {
		ret = -EINVAL;
		goto err_exit1;
	}
	cptk->client = client;
	strlcpy(cptk->client->name, "melfas-touchkey",
			I2C_NAME_SIZE);
	cptk->client->dev.init_name = DEVICE_NAME;
	i2c_set_clientdata(client, cptk);

	cptk->input_dev->name = DEVICE_NAME;
	cptk->input_dev->phys = "melfas-touchkey/input0";
	cptk->input_dev->id.bustype = BUS_HOST;

	set_bit(EV_SYN, cptk->input_dev->evbit);
	set_bit(EV_KEY, cptk->input_dev->evbit);
	set_bit(EV_LED, cptk->input_dev->evbit);
	set_bit(LED_MISC, cptk->input_dev->ledbit);

	for (i = 1; i < cptk->pdata->keymap_size; i++)
		set_bit(cptk->pdata->keymap[i], cptk->input_dev->keybit);

	ret = input_register_device(cptk->input_dev);
	if (ret) {
		input_free_device(cptk->input_dev);
		return ret;
	}

	mutex_init(&cptk->i2c_lock);
	mutex_init(&cptk->lock);

	if (cptk->pdata->power)
		cptk->pdata->power(1);
	cptk->enable = true;

	cptk_i2c_read(cptk, KEYCODE_REG,
			cptk->cur_firm_ver,
			sizeof(cptk->cur_firm_ver));

	pr_info("cptk :firm ver = 0x%x, mod ver = 0x%x\n",
			cptk->cur_firm_ver[1], cptk->cur_firm_ver[2]);

	if (cptk->cur_firm_ver[1] < cptk->pdata->firm_ver) {
		pr_info("cptk: force firmware update\n");
		cptk_update_firmware(cptk);
	}

#ifdef CONFIG_HAS_EARLYSUSPEND
	cptk->early_suspend.level =
		EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 2;
	cptk->early_suspend.suspend = (void *) cptk_early_suspend;
	cptk->early_suspend.resume = (void *) cptk_late_resume;
	register_early_suspend(&cptk->early_suspend);
#endif

	cptk_i2c_write(cptk, KEYCODE_REG, AUTO_CAL_MODE_CMD);
	cptk_i2c_write(cptk, CMD_REG, AUTO_CAL_EN_CMD);

	ret = request_threaded_irq(client->irq, NULL, cptk_irq_thread,
				   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
				   DEVICE_NAME, cptk);
	if (ret < 0)
		goto err_exit2;

	ret = cptk_create_sec_touchkey(cptk);
	if (ret < 0)
		goto err_exit2;

	return 0;

err_exit2:
err_exit1:
	kfree(cptk);
	return ret;
}