static ssize_t set_touchkey_firm_update_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct cptk_data *cptk = dev_get_drvdata(dev); if (*buf == 'S' || *buf == 'F') { if ((*buf != 'F' && cptk->cur_firm_ver[1] >= cptk->pdata->firm_ver) && cptk->cur_firm_ver[1] != 0xFF) { cptk->touchkey_update_status = 0; pr_debug("cptk: already updated latest version\n"); return size; } cptk_update_firmware(cptk); } return size; }
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; }