162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * TM2 touchkey device driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2005 Phil Blundell 662306a36Sopenharmony_ci * Copyright 2016 Samsung Electronics Co., Ltd. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Author: Beomho Seo <beomho.seo@samsung.com> 962306a36Sopenharmony_ci * Author: Jaechul Lee <jcsing.lee@samsung.com> 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/bitops.h> 1362306a36Sopenharmony_ci#include <linux/delay.h> 1462306a36Sopenharmony_ci#include <linux/device.h> 1562306a36Sopenharmony_ci#include <linux/i2c.h> 1662306a36Sopenharmony_ci#include <linux/input.h> 1762306a36Sopenharmony_ci#include <linux/interrupt.h> 1862306a36Sopenharmony_ci#include <linux/irq.h> 1962306a36Sopenharmony_ci#include <linux/leds.h> 2062306a36Sopenharmony_ci#include <linux/module.h> 2162306a36Sopenharmony_ci#include <linux/of.h> 2262306a36Sopenharmony_ci#include <linux/pm.h> 2362306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#define TM2_TOUCHKEY_DEV_NAME "tm2-touchkey" 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#define ARIES_TOUCHKEY_CMD_LED_ON 0x1 2862306a36Sopenharmony_ci#define ARIES_TOUCHKEY_CMD_LED_OFF 0x2 2962306a36Sopenharmony_ci#define TM2_TOUCHKEY_CMD_LED_ON 0x10 3062306a36Sopenharmony_ci#define TM2_TOUCHKEY_CMD_LED_OFF 0x20 3162306a36Sopenharmony_ci#define TM2_TOUCHKEY_BIT_PRESS_EV BIT(3) 3262306a36Sopenharmony_ci#define TM2_TOUCHKEY_BIT_KEYCODE GENMASK(2, 0) 3362306a36Sopenharmony_ci#define TM2_TOUCHKEY_LED_VOLTAGE_MIN 2500000 3462306a36Sopenharmony_ci#define TM2_TOUCHKEY_LED_VOLTAGE_MAX 3300000 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistruct touchkey_variant { 3762306a36Sopenharmony_ci u8 keycode_reg; 3862306a36Sopenharmony_ci u8 base_reg; 3962306a36Sopenharmony_ci u8 cmd_led_on; 4062306a36Sopenharmony_ci u8 cmd_led_off; 4162306a36Sopenharmony_ci bool no_reg; 4262306a36Sopenharmony_ci bool fixed_regulator; 4362306a36Sopenharmony_ci}; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistruct tm2_touchkey_data { 4662306a36Sopenharmony_ci struct i2c_client *client; 4762306a36Sopenharmony_ci struct input_dev *input_dev; 4862306a36Sopenharmony_ci struct led_classdev led_dev; 4962306a36Sopenharmony_ci struct regulator *vdd; 5062306a36Sopenharmony_ci struct regulator_bulk_data regulators[3]; 5162306a36Sopenharmony_ci const struct touchkey_variant *variant; 5262306a36Sopenharmony_ci u32 keycodes[4]; 5362306a36Sopenharmony_ci int num_keycodes; 5462306a36Sopenharmony_ci}; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic const struct touchkey_variant tm2_touchkey_variant = { 5762306a36Sopenharmony_ci .keycode_reg = 0x03, 5862306a36Sopenharmony_ci .base_reg = 0x00, 5962306a36Sopenharmony_ci .cmd_led_on = TM2_TOUCHKEY_CMD_LED_ON, 6062306a36Sopenharmony_ci .cmd_led_off = TM2_TOUCHKEY_CMD_LED_OFF, 6162306a36Sopenharmony_ci}; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_cistatic const struct touchkey_variant midas_touchkey_variant = { 6462306a36Sopenharmony_ci .keycode_reg = 0x00, 6562306a36Sopenharmony_ci .base_reg = 0x00, 6662306a36Sopenharmony_ci .cmd_led_on = TM2_TOUCHKEY_CMD_LED_ON, 6762306a36Sopenharmony_ci .cmd_led_off = TM2_TOUCHKEY_CMD_LED_OFF, 6862306a36Sopenharmony_ci}; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic struct touchkey_variant aries_touchkey_variant = { 7162306a36Sopenharmony_ci .no_reg = true, 7262306a36Sopenharmony_ci .fixed_regulator = true, 7362306a36Sopenharmony_ci .cmd_led_on = ARIES_TOUCHKEY_CMD_LED_ON, 7462306a36Sopenharmony_ci .cmd_led_off = ARIES_TOUCHKEY_CMD_LED_OFF, 7562306a36Sopenharmony_ci}; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic const struct touchkey_variant tc360_touchkey_variant = { 7862306a36Sopenharmony_ci .keycode_reg = 0x00, 7962306a36Sopenharmony_ci .base_reg = 0x00, 8062306a36Sopenharmony_ci .fixed_regulator = true, 8162306a36Sopenharmony_ci .cmd_led_on = TM2_TOUCHKEY_CMD_LED_ON, 8262306a36Sopenharmony_ci .cmd_led_off = TM2_TOUCHKEY_CMD_LED_OFF, 8362306a36Sopenharmony_ci}; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistatic int tm2_touchkey_led_brightness_set(struct led_classdev *led_dev, 8662306a36Sopenharmony_ci enum led_brightness brightness) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci struct tm2_touchkey_data *touchkey = 8962306a36Sopenharmony_ci container_of(led_dev, struct tm2_touchkey_data, led_dev); 9062306a36Sopenharmony_ci u32 volt; 9162306a36Sopenharmony_ci u8 data; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci if (brightness == LED_OFF) { 9462306a36Sopenharmony_ci volt = TM2_TOUCHKEY_LED_VOLTAGE_MIN; 9562306a36Sopenharmony_ci data = touchkey->variant->cmd_led_off; 9662306a36Sopenharmony_ci } else { 9762306a36Sopenharmony_ci volt = TM2_TOUCHKEY_LED_VOLTAGE_MAX; 9862306a36Sopenharmony_ci data = touchkey->variant->cmd_led_on; 9962306a36Sopenharmony_ci } 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci if (!touchkey->variant->fixed_regulator) 10262306a36Sopenharmony_ci regulator_set_voltage(touchkey->vdd, volt, volt); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci return touchkey->variant->no_reg ? 10562306a36Sopenharmony_ci i2c_smbus_write_byte(touchkey->client, data) : 10662306a36Sopenharmony_ci i2c_smbus_write_byte_data(touchkey->client, 10762306a36Sopenharmony_ci touchkey->variant->base_reg, data); 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistatic int tm2_touchkey_power_enable(struct tm2_touchkey_data *touchkey) 11162306a36Sopenharmony_ci{ 11262306a36Sopenharmony_ci int error; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci error = regulator_bulk_enable(ARRAY_SIZE(touchkey->regulators), 11562306a36Sopenharmony_ci touchkey->regulators); 11662306a36Sopenharmony_ci if (error) 11762306a36Sopenharmony_ci return error; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci /* waiting for device initialization, at least 150ms */ 12062306a36Sopenharmony_ci msleep(150); 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci return 0; 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cistatic void tm2_touchkey_power_disable(void *data) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci struct tm2_touchkey_data *touchkey = data; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci regulator_bulk_disable(ARRAY_SIZE(touchkey->regulators), 13062306a36Sopenharmony_ci touchkey->regulators); 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistatic irqreturn_t tm2_touchkey_irq_handler(int irq, void *devid) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci struct tm2_touchkey_data *touchkey = devid; 13662306a36Sopenharmony_ci int data; 13762306a36Sopenharmony_ci int index; 13862306a36Sopenharmony_ci int i; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci if (touchkey->variant->no_reg) 14162306a36Sopenharmony_ci data = i2c_smbus_read_byte(touchkey->client); 14262306a36Sopenharmony_ci else 14362306a36Sopenharmony_ci data = i2c_smbus_read_byte_data(touchkey->client, 14462306a36Sopenharmony_ci touchkey->variant->keycode_reg); 14562306a36Sopenharmony_ci if (data < 0) { 14662306a36Sopenharmony_ci dev_err(&touchkey->client->dev, 14762306a36Sopenharmony_ci "failed to read i2c data: %d\n", data); 14862306a36Sopenharmony_ci goto out; 14962306a36Sopenharmony_ci } 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci index = (data & TM2_TOUCHKEY_BIT_KEYCODE) - 1; 15262306a36Sopenharmony_ci if (index < 0 || index >= touchkey->num_keycodes) { 15362306a36Sopenharmony_ci dev_warn(&touchkey->client->dev, 15462306a36Sopenharmony_ci "invalid keycode index %d\n", index); 15562306a36Sopenharmony_ci goto out; 15662306a36Sopenharmony_ci } 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci input_event(touchkey->input_dev, EV_MSC, MSC_SCAN, index); 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci if (data & TM2_TOUCHKEY_BIT_PRESS_EV) { 16162306a36Sopenharmony_ci for (i = 0; i < touchkey->num_keycodes; i++) 16262306a36Sopenharmony_ci input_report_key(touchkey->input_dev, 16362306a36Sopenharmony_ci touchkey->keycodes[i], 0); 16462306a36Sopenharmony_ci } else { 16562306a36Sopenharmony_ci input_report_key(touchkey->input_dev, 16662306a36Sopenharmony_ci touchkey->keycodes[index], 1); 16762306a36Sopenharmony_ci } 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci input_sync(touchkey->input_dev); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ciout: 17262306a36Sopenharmony_ci if (touchkey->variant->fixed_regulator && 17362306a36Sopenharmony_ci data & TM2_TOUCHKEY_BIT_PRESS_EV) { 17462306a36Sopenharmony_ci /* touch turns backlight on, so make sure we're in sync */ 17562306a36Sopenharmony_ci if (touchkey->led_dev.brightness == LED_OFF) 17662306a36Sopenharmony_ci tm2_touchkey_led_brightness_set(&touchkey->led_dev, 17762306a36Sopenharmony_ci LED_OFF); 17862306a36Sopenharmony_ci } 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci return IRQ_HANDLED; 18162306a36Sopenharmony_ci} 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic int tm2_touchkey_probe(struct i2c_client *client) 18462306a36Sopenharmony_ci{ 18562306a36Sopenharmony_ci struct device_node *np = client->dev.of_node; 18662306a36Sopenharmony_ci struct tm2_touchkey_data *touchkey; 18762306a36Sopenharmony_ci int error; 18862306a36Sopenharmony_ci int i; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci if (!i2c_check_functionality(client->adapter, 19162306a36Sopenharmony_ci I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA)) { 19262306a36Sopenharmony_ci dev_err(&client->dev, "incompatible I2C adapter\n"); 19362306a36Sopenharmony_ci return -EIO; 19462306a36Sopenharmony_ci } 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci touchkey = devm_kzalloc(&client->dev, sizeof(*touchkey), GFP_KERNEL); 19762306a36Sopenharmony_ci if (!touchkey) 19862306a36Sopenharmony_ci return -ENOMEM; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci touchkey->client = client; 20162306a36Sopenharmony_ci i2c_set_clientdata(client, touchkey); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci touchkey->variant = of_device_get_match_data(&client->dev); 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci touchkey->regulators[0].supply = "vcc"; 20662306a36Sopenharmony_ci touchkey->regulators[1].supply = "vdd"; 20762306a36Sopenharmony_ci touchkey->regulators[2].supply = "vddio"; 20862306a36Sopenharmony_ci error = devm_regulator_bulk_get(&client->dev, 20962306a36Sopenharmony_ci ARRAY_SIZE(touchkey->regulators), 21062306a36Sopenharmony_ci touchkey->regulators); 21162306a36Sopenharmony_ci if (error) { 21262306a36Sopenharmony_ci dev_err(&client->dev, "failed to get regulators: %d\n", error); 21362306a36Sopenharmony_ci return error; 21462306a36Sopenharmony_ci } 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci /* Save VDD for easy access */ 21762306a36Sopenharmony_ci touchkey->vdd = touchkey->regulators[1].consumer; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci touchkey->num_keycodes = of_property_read_variable_u32_array(np, 22062306a36Sopenharmony_ci "linux,keycodes", touchkey->keycodes, 0, 22162306a36Sopenharmony_ci ARRAY_SIZE(touchkey->keycodes)); 22262306a36Sopenharmony_ci if (touchkey->num_keycodes <= 0) { 22362306a36Sopenharmony_ci /* default keycodes */ 22462306a36Sopenharmony_ci touchkey->keycodes[0] = KEY_PHONE; 22562306a36Sopenharmony_ci touchkey->keycodes[1] = KEY_BACK; 22662306a36Sopenharmony_ci touchkey->num_keycodes = 2; 22762306a36Sopenharmony_ci } 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci error = tm2_touchkey_power_enable(touchkey); 23062306a36Sopenharmony_ci if (error) { 23162306a36Sopenharmony_ci dev_err(&client->dev, "failed to power up device: %d\n", error); 23262306a36Sopenharmony_ci return error; 23362306a36Sopenharmony_ci } 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci error = devm_add_action_or_reset(&client->dev, 23662306a36Sopenharmony_ci tm2_touchkey_power_disable, touchkey); 23762306a36Sopenharmony_ci if (error) { 23862306a36Sopenharmony_ci dev_err(&client->dev, 23962306a36Sopenharmony_ci "failed to install poweroff handler: %d\n", error); 24062306a36Sopenharmony_ci return error; 24162306a36Sopenharmony_ci } 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci /* input device */ 24462306a36Sopenharmony_ci touchkey->input_dev = devm_input_allocate_device(&client->dev); 24562306a36Sopenharmony_ci if (!touchkey->input_dev) { 24662306a36Sopenharmony_ci dev_err(&client->dev, "failed to allocate input device\n"); 24762306a36Sopenharmony_ci return -ENOMEM; 24862306a36Sopenharmony_ci } 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci touchkey->input_dev->name = TM2_TOUCHKEY_DEV_NAME; 25162306a36Sopenharmony_ci touchkey->input_dev->id.bustype = BUS_I2C; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci touchkey->input_dev->keycode = touchkey->keycodes; 25462306a36Sopenharmony_ci touchkey->input_dev->keycodemax = touchkey->num_keycodes; 25562306a36Sopenharmony_ci touchkey->input_dev->keycodesize = sizeof(touchkey->keycodes[0]); 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci input_set_capability(touchkey->input_dev, EV_MSC, MSC_SCAN); 25862306a36Sopenharmony_ci for (i = 0; i < touchkey->num_keycodes; i++) 25962306a36Sopenharmony_ci input_set_capability(touchkey->input_dev, EV_KEY, 26062306a36Sopenharmony_ci touchkey->keycodes[i]); 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci error = input_register_device(touchkey->input_dev); 26362306a36Sopenharmony_ci if (error) { 26462306a36Sopenharmony_ci dev_err(&client->dev, 26562306a36Sopenharmony_ci "failed to register input device: %d\n", error); 26662306a36Sopenharmony_ci return error; 26762306a36Sopenharmony_ci } 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci error = devm_request_threaded_irq(&client->dev, client->irq, 27062306a36Sopenharmony_ci NULL, tm2_touchkey_irq_handler, 27162306a36Sopenharmony_ci IRQF_ONESHOT, 27262306a36Sopenharmony_ci TM2_TOUCHKEY_DEV_NAME, touchkey); 27362306a36Sopenharmony_ci if (error) { 27462306a36Sopenharmony_ci dev_err(&client->dev, 27562306a36Sopenharmony_ci "failed to request threaded irq: %d\n", error); 27662306a36Sopenharmony_ci return error; 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci /* led device */ 28062306a36Sopenharmony_ci touchkey->led_dev.name = TM2_TOUCHKEY_DEV_NAME; 28162306a36Sopenharmony_ci touchkey->led_dev.brightness = LED_ON; 28262306a36Sopenharmony_ci touchkey->led_dev.max_brightness = LED_ON; 28362306a36Sopenharmony_ci touchkey->led_dev.brightness_set_blocking = 28462306a36Sopenharmony_ci tm2_touchkey_led_brightness_set; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci error = devm_led_classdev_register(&client->dev, &touchkey->led_dev); 28762306a36Sopenharmony_ci if (error) { 28862306a36Sopenharmony_ci dev_err(&client->dev, 28962306a36Sopenharmony_ci "failed to register touchkey led: %d\n", error); 29062306a36Sopenharmony_ci return error; 29162306a36Sopenharmony_ci } 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci if (touchkey->variant->fixed_regulator) 29462306a36Sopenharmony_ci tm2_touchkey_led_brightness_set(&touchkey->led_dev, LED_ON); 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci return 0; 29762306a36Sopenharmony_ci} 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_cistatic int tm2_touchkey_suspend(struct device *dev) 30062306a36Sopenharmony_ci{ 30162306a36Sopenharmony_ci struct i2c_client *client = to_i2c_client(dev); 30262306a36Sopenharmony_ci struct tm2_touchkey_data *touchkey = i2c_get_clientdata(client); 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci disable_irq(client->irq); 30562306a36Sopenharmony_ci tm2_touchkey_power_disable(touchkey); 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci return 0; 30862306a36Sopenharmony_ci} 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_cistatic int tm2_touchkey_resume(struct device *dev) 31162306a36Sopenharmony_ci{ 31262306a36Sopenharmony_ci struct i2c_client *client = to_i2c_client(dev); 31362306a36Sopenharmony_ci struct tm2_touchkey_data *touchkey = i2c_get_clientdata(client); 31462306a36Sopenharmony_ci int ret; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci enable_irq(client->irq); 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci ret = tm2_touchkey_power_enable(touchkey); 31962306a36Sopenharmony_ci if (ret) 32062306a36Sopenharmony_ci dev_err(dev, "failed to enable power: %d\n", ret); 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci return ret; 32362306a36Sopenharmony_ci} 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_cistatic DEFINE_SIMPLE_DEV_PM_OPS(tm2_touchkey_pm_ops, 32662306a36Sopenharmony_ci tm2_touchkey_suspend, tm2_touchkey_resume); 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_cistatic const struct i2c_device_id tm2_touchkey_id_table[] = { 32962306a36Sopenharmony_ci { TM2_TOUCHKEY_DEV_NAME, 0 }, 33062306a36Sopenharmony_ci { }, 33162306a36Sopenharmony_ci}; 33262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, tm2_touchkey_id_table); 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_cistatic const struct of_device_id tm2_touchkey_of_match[] = { 33562306a36Sopenharmony_ci { 33662306a36Sopenharmony_ci .compatible = "cypress,tm2-touchkey", 33762306a36Sopenharmony_ci .data = &tm2_touchkey_variant, 33862306a36Sopenharmony_ci }, { 33962306a36Sopenharmony_ci .compatible = "cypress,midas-touchkey", 34062306a36Sopenharmony_ci .data = &midas_touchkey_variant, 34162306a36Sopenharmony_ci }, { 34262306a36Sopenharmony_ci .compatible = "cypress,aries-touchkey", 34362306a36Sopenharmony_ci .data = &aries_touchkey_variant, 34462306a36Sopenharmony_ci }, { 34562306a36Sopenharmony_ci .compatible = "coreriver,tc360-touchkey", 34662306a36Sopenharmony_ci .data = &tc360_touchkey_variant, 34762306a36Sopenharmony_ci }, 34862306a36Sopenharmony_ci { }, 34962306a36Sopenharmony_ci}; 35062306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, tm2_touchkey_of_match); 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_cistatic struct i2c_driver tm2_touchkey_driver = { 35362306a36Sopenharmony_ci .driver = { 35462306a36Sopenharmony_ci .name = TM2_TOUCHKEY_DEV_NAME, 35562306a36Sopenharmony_ci .pm = pm_sleep_ptr(&tm2_touchkey_pm_ops), 35662306a36Sopenharmony_ci .of_match_table = tm2_touchkey_of_match, 35762306a36Sopenharmony_ci }, 35862306a36Sopenharmony_ci .probe = tm2_touchkey_probe, 35962306a36Sopenharmony_ci .id_table = tm2_touchkey_id_table, 36062306a36Sopenharmony_ci}; 36162306a36Sopenharmony_cimodule_i2c_driver(tm2_touchkey_driver); 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ciMODULE_AUTHOR("Beomho Seo <beomho.seo@samsung.com>"); 36462306a36Sopenharmony_ciMODULE_AUTHOR("Jaechul Lee <jcsing.lee@samsung.com>"); 36562306a36Sopenharmony_ciMODULE_DESCRIPTION("Samsung touchkey driver"); 36662306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 367