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;
}