1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 27e577a17SAhmet Inan /* 37e577a17SAhmet Inan * Driver for I2C connected EETI EXC3000 multiple touch controller 47e577a17SAhmet Inan * 57e577a17SAhmet Inan * Copyright (C) 2017 Ahmet Inan <inan@distec.de> 67e577a17SAhmet Inan * 77e577a17SAhmet Inan * minimal implementation based on egalax_ts.c and egalax_i2c.c 87e577a17SAhmet Inan */ 97e577a17SAhmet Inan 107e577a17SAhmet Inan #include <linux/bitops.h> 1127aced19SSebastian Reichel #include <linux/delay.h> 127e577a17SAhmet Inan #include <linux/device.h> 1327aced19SSebastian Reichel #include <linux/gpio/consumer.h> 147e577a17SAhmet Inan #include <linux/i2c.h> 157e577a17SAhmet Inan #include <linux/input.h> 167e577a17SAhmet Inan #include <linux/input/mt.h> 177e577a17SAhmet Inan #include <linux/input/touchscreen.h> 187e577a17SAhmet Inan #include <linux/interrupt.h> 197e577a17SAhmet Inan #include <linux/module.h> 207e577a17SAhmet Inan #include <linux/of.h> 213bdd21c6SSebastian Reichel #include <linux/sizes.h> 227e577a17SAhmet Inan #include <linux/timer.h> 237e577a17SAhmet Inan #include <asm/unaligned.h> 247e577a17SAhmet Inan 257e577a17SAhmet Inan #define EXC3000_NUM_SLOTS 10 267e577a17SAhmet Inan #define EXC3000_SLOTS_PER_FRAME 5 277e577a17SAhmet Inan #define EXC3000_LEN_FRAME 66 28102feb1dSLucas Stach #define EXC3000_LEN_VENDOR_REQUEST 68 297e577a17SAhmet Inan #define EXC3000_LEN_POINT 10 303bdd21c6SSebastian Reichel 31d862a306SSebastian Reichel #define EXC3000_LEN_MODEL_NAME 16 32d862a306SSebastian Reichel #define EXC3000_LEN_FW_VERSION 16 33d862a306SSebastian Reichel 34a63d0120SLucas Stach #define EXC3000_VENDOR_EVENT 0x03 353bdd21c6SSebastian Reichel #define EXC3000_MT1_EVENT 0x06 363bdd21c6SSebastian Reichel #define EXC3000_MT2_EVENT 0x18 373bdd21c6SSebastian Reichel 387e577a17SAhmet Inan #define EXC3000_TIMEOUT_MS 100 397e577a17SAhmet Inan 4027aced19SSebastian Reichel #define EXC3000_RESET_MS 10 4127aced19SSebastian Reichel #define EXC3000_READY_MS 100 4227aced19SSebastian Reichel 433bdd21c6SSebastian Reichel static const struct i2c_device_id exc3000_id[]; 443bdd21c6SSebastian Reichel 453bdd21c6SSebastian Reichel struct eeti_dev_info { 463bdd21c6SSebastian Reichel const char *name; 473bdd21c6SSebastian Reichel int max_xy; 483bdd21c6SSebastian Reichel }; 493bdd21c6SSebastian Reichel 503bdd21c6SSebastian Reichel enum eeti_dev_id { 513bdd21c6SSebastian Reichel EETI_EXC3000, 523bdd21c6SSebastian Reichel EETI_EXC80H60, 533bdd21c6SSebastian Reichel EETI_EXC80H84, 543bdd21c6SSebastian Reichel }; 553bdd21c6SSebastian Reichel 563bdd21c6SSebastian Reichel static struct eeti_dev_info exc3000_info[] = { 573bdd21c6SSebastian Reichel [EETI_EXC3000] = { 583bdd21c6SSebastian Reichel .name = "EETI EXC3000 Touch Screen", 593bdd21c6SSebastian Reichel .max_xy = SZ_4K - 1, 603bdd21c6SSebastian Reichel }, 613bdd21c6SSebastian Reichel [EETI_EXC80H60] = { 623bdd21c6SSebastian Reichel .name = "EETI EXC80H60 Touch Screen", 633bdd21c6SSebastian Reichel .max_xy = SZ_16K - 1, 643bdd21c6SSebastian Reichel }, 653bdd21c6SSebastian Reichel [EETI_EXC80H84] = { 663bdd21c6SSebastian Reichel .name = "EETI EXC80H84 Touch Screen", 673bdd21c6SSebastian Reichel .max_xy = SZ_16K - 1, 683bdd21c6SSebastian Reichel }, 693bdd21c6SSebastian Reichel }; 703bdd21c6SSebastian Reichel 717e577a17SAhmet Inan struct exc3000_data { 727e577a17SAhmet Inan struct i2c_client *client; 733bdd21c6SSebastian Reichel const struct eeti_dev_info *info; 747e577a17SAhmet Inan struct input_dev *input; 757e577a17SAhmet Inan struct touchscreen_properties prop; 7627aced19SSebastian Reichel struct gpio_desc *reset; 777e577a17SAhmet Inan struct timer_list timer; 787e577a17SAhmet Inan u8 buf[2 * EXC3000_LEN_FRAME]; 79d862a306SSebastian Reichel struct completion wait_event; 80d862a306SSebastian Reichel struct mutex query_lock; 817e577a17SAhmet Inan }; 827e577a17SAhmet Inan 837e577a17SAhmet Inan static void exc3000_report_slots(struct input_dev *input, 847e577a17SAhmet Inan struct touchscreen_properties *prop, 857e577a17SAhmet Inan const u8 *buf, int num) 867e577a17SAhmet Inan { 877e577a17SAhmet Inan for (; num--; buf += EXC3000_LEN_POINT) { 887e577a17SAhmet Inan if (buf[0] & BIT(0)) { 897e577a17SAhmet Inan input_mt_slot(input, buf[1]); 907e577a17SAhmet Inan input_mt_report_slot_state(input, MT_TOOL_FINGER, true); 917e577a17SAhmet Inan touchscreen_report_pos(input, prop, 927e577a17SAhmet Inan get_unaligned_le16(buf + 2), 937e577a17SAhmet Inan get_unaligned_le16(buf + 4), 947e577a17SAhmet Inan true); 957e577a17SAhmet Inan } 967e577a17SAhmet Inan } 977e577a17SAhmet Inan } 987e577a17SAhmet Inan 997e577a17SAhmet Inan static void exc3000_timer(struct timer_list *t) 1007e577a17SAhmet Inan { 1017e577a17SAhmet Inan struct exc3000_data *data = from_timer(data, t, timer); 1027e577a17SAhmet Inan 1037e577a17SAhmet Inan input_mt_sync_frame(data->input); 1047e577a17SAhmet Inan input_sync(data->input); 1057e577a17SAhmet Inan } 1067e577a17SAhmet Inan 107a63d0120SLucas Stach static inline void exc3000_schedule_timer(struct exc3000_data *data) 108a63d0120SLucas Stach { 109a63d0120SLucas Stach mod_timer(&data->timer, jiffies + msecs_to_jiffies(EXC3000_TIMEOUT_MS)); 110a63d0120SLucas Stach } 111a63d0120SLucas Stach 1123bdd21c6SSebastian Reichel static int exc3000_read_frame(struct exc3000_data *data, u8 *buf) 1137e577a17SAhmet Inan { 1143bdd21c6SSebastian Reichel struct i2c_client *client = data->client; 1157e577a17SAhmet Inan int ret; 1167e577a17SAhmet Inan 1177e577a17SAhmet Inan ret = i2c_master_send(client, "'", 2); 1187e577a17SAhmet Inan if (ret < 0) 1197e577a17SAhmet Inan return ret; 1207e577a17SAhmet Inan 1217e577a17SAhmet Inan if (ret != 2) 1227e577a17SAhmet Inan return -EIO; 1237e577a17SAhmet Inan 1247e577a17SAhmet Inan ret = i2c_master_recv(client, buf, EXC3000_LEN_FRAME); 1257e577a17SAhmet Inan if (ret < 0) 1267e577a17SAhmet Inan return ret; 1277e577a17SAhmet Inan 1287e577a17SAhmet Inan if (ret != EXC3000_LEN_FRAME) 1297e577a17SAhmet Inan return -EIO; 1307e577a17SAhmet Inan 1313bdd21c6SSebastian Reichel if (get_unaligned_le16(buf) != EXC3000_LEN_FRAME) 1323bdd21c6SSebastian Reichel return -EINVAL; 1333bdd21c6SSebastian Reichel 1347e577a17SAhmet Inan return 0; 1357e577a17SAhmet Inan } 1367e577a17SAhmet Inan 137a63d0120SLucas Stach static int exc3000_handle_mt_event(struct exc3000_data *data) 1387e577a17SAhmet Inan { 139a63d0120SLucas Stach struct input_dev *input = data->input; 140a63d0120SLucas Stach int ret, total_slots; 141a63d0120SLucas Stach u8 *buf = data->buf; 1427e577a17SAhmet Inan 143a63d0120SLucas Stach total_slots = buf[3]; 144a63d0120SLucas Stach if (!total_slots || total_slots > EXC3000_NUM_SLOTS) { 145a63d0120SLucas Stach ret = -EINVAL; 146a63d0120SLucas Stach goto out_fail; 147a63d0120SLucas Stach } 1487e577a17SAhmet Inan 149a63d0120SLucas Stach if (total_slots > EXC3000_SLOTS_PER_FRAME) { 1507e577a17SAhmet Inan /* Read 2nd frame to get the rest of the contacts. */ 151a63d0120SLucas Stach ret = exc3000_read_frame(data, buf + EXC3000_LEN_FRAME); 152a63d0120SLucas Stach if (ret) 153a63d0120SLucas Stach goto out_fail; 1547e577a17SAhmet Inan 1557e577a17SAhmet Inan /* 2nd chunk must have number of contacts set to 0. */ 156a63d0120SLucas Stach if (buf[EXC3000_LEN_FRAME + 3] != 0) { 157a63d0120SLucas Stach ret = -EINVAL; 158a63d0120SLucas Stach goto out_fail; 159a63d0120SLucas Stach } 1607e577a17SAhmet Inan } 1617e577a17SAhmet Inan 162a63d0120SLucas Stach /* 163a63d0120SLucas Stach * We read full state successfully, no contacts will be "stuck". 164a63d0120SLucas Stach */ 165a63d0120SLucas Stach del_timer_sync(&data->timer); 166a63d0120SLucas Stach 167a63d0120SLucas Stach while (total_slots > 0) { 168a63d0120SLucas Stach int slots = min(total_slots, EXC3000_SLOTS_PER_FRAME); 169a63d0120SLucas Stach 170a63d0120SLucas Stach exc3000_report_slots(input, &data->prop, buf + 4, slots); 171a63d0120SLucas Stach total_slots -= slots; 172a63d0120SLucas Stach buf += EXC3000_LEN_FRAME; 173a63d0120SLucas Stach } 174a63d0120SLucas Stach 175a63d0120SLucas Stach input_mt_sync_frame(input); 176a63d0120SLucas Stach input_sync(input); 177a63d0120SLucas Stach 1787e577a17SAhmet Inan return 0; 179a63d0120SLucas Stach 180a63d0120SLucas Stach out_fail: 181a63d0120SLucas Stach /* Schedule a timer to release "stuck" contacts */ 182a63d0120SLucas Stach exc3000_schedule_timer(data); 183a63d0120SLucas Stach 184a63d0120SLucas Stach return ret; 1857e577a17SAhmet Inan } 1867e577a17SAhmet Inan 1877e577a17SAhmet Inan static irqreturn_t exc3000_interrupt(int irq, void *dev_id) 1887e577a17SAhmet Inan { 1897e577a17SAhmet Inan struct exc3000_data *data = dev_id; 1907e577a17SAhmet Inan u8 *buf = data->buf; 191a63d0120SLucas Stach int ret; 1927e577a17SAhmet Inan 193a63d0120SLucas Stach ret = exc3000_read_frame(data, buf); 194a63d0120SLucas Stach if (ret) { 195a63d0120SLucas Stach /* Schedule a timer to release "stuck" contacts */ 196a63d0120SLucas Stach exc3000_schedule_timer(data); 197a63d0120SLucas Stach goto out; 198a63d0120SLucas Stach } 199a63d0120SLucas Stach 200a63d0120SLucas Stach switch (buf[2]) { 201a63d0120SLucas Stach case EXC3000_VENDOR_EVENT: 202d862a306SSebastian Reichel complete(&data->wait_event); 203a63d0120SLucas Stach break; 204a63d0120SLucas Stach 205a63d0120SLucas Stach case EXC3000_MT1_EVENT: 206a63d0120SLucas Stach case EXC3000_MT2_EVENT: 207a63d0120SLucas Stach exc3000_handle_mt_event(data); 208a63d0120SLucas Stach break; 209a63d0120SLucas Stach 210a63d0120SLucas Stach default: 211a63d0120SLucas Stach break; 212d862a306SSebastian Reichel } 213d862a306SSebastian Reichel 2147e577a17SAhmet Inan out: 2157e577a17SAhmet Inan return IRQ_HANDLED; 2167e577a17SAhmet Inan } 2177e577a17SAhmet Inan 218102feb1dSLucas Stach static int exc3000_vendor_data_request(struct exc3000_data *data, u8 *request, 219102feb1dSLucas Stach u8 request_len, u8 *response, int timeout) 220102feb1dSLucas Stach { 221102feb1dSLucas Stach u8 buf[EXC3000_LEN_VENDOR_REQUEST] = { 0x67, 0x00, 0x42, 0x00, 0x03 }; 222102feb1dSLucas Stach int ret; 223*6bb7144cSMiaoqian Lin unsigned long time_left; 224102feb1dSLucas Stach 225102feb1dSLucas Stach mutex_lock(&data->query_lock); 226102feb1dSLucas Stach 227102feb1dSLucas Stach reinit_completion(&data->wait_event); 228102feb1dSLucas Stach 229102feb1dSLucas Stach buf[5] = request_len; 230102feb1dSLucas Stach memcpy(&buf[6], request, request_len); 231102feb1dSLucas Stach 232102feb1dSLucas Stach ret = i2c_master_send(data->client, buf, EXC3000_LEN_VENDOR_REQUEST); 233102feb1dSLucas Stach if (ret < 0) 234102feb1dSLucas Stach goto out_unlock; 235102feb1dSLucas Stach 236102feb1dSLucas Stach if (response) { 237*6bb7144cSMiaoqian Lin time_left = wait_for_completion_timeout(&data->wait_event, 238102feb1dSLucas Stach timeout * HZ); 239*6bb7144cSMiaoqian Lin if (time_left == 0) { 240102feb1dSLucas Stach ret = -ETIMEDOUT; 241102feb1dSLucas Stach goto out_unlock; 242102feb1dSLucas Stach } 243102feb1dSLucas Stach 244102feb1dSLucas Stach if (data->buf[3] >= EXC3000_LEN_FRAME) { 245102feb1dSLucas Stach ret = -ENOSPC; 246102feb1dSLucas Stach goto out_unlock; 247102feb1dSLucas Stach } 248102feb1dSLucas Stach 249102feb1dSLucas Stach memcpy(response, &data->buf[4], data->buf[3]); 250102feb1dSLucas Stach ret = data->buf[3]; 251102feb1dSLucas Stach } 252102feb1dSLucas Stach 253102feb1dSLucas Stach out_unlock: 254102feb1dSLucas Stach mutex_unlock(&data->query_lock); 255102feb1dSLucas Stach 256102feb1dSLucas Stach return ret; 257102feb1dSLucas Stach } 258102feb1dSLucas Stach 259d862a306SSebastian Reichel static ssize_t fw_version_show(struct device *dev, 260d862a306SSebastian Reichel struct device_attribute *attr, char *buf) 261d862a306SSebastian Reichel { 262d862a306SSebastian Reichel struct i2c_client *client = to_i2c_client(dev); 263d862a306SSebastian Reichel struct exc3000_data *data = i2c_get_clientdata(client); 264102feb1dSLucas Stach u8 response[EXC3000_LEN_FRAME]; 265102feb1dSLucas Stach int ret; 266d862a306SSebastian Reichel 267c929ac9eSLucas Stach /* query bootloader info */ 268c929ac9eSLucas Stach ret = exc3000_vendor_data_request(data, 269c929ac9eSLucas Stach (u8[]){0x39, 0x02}, 2, response, 1); 270c929ac9eSLucas Stach if (ret < 0) 271c929ac9eSLucas Stach return ret; 272c929ac9eSLucas Stach 273c929ac9eSLucas Stach /* 274c929ac9eSLucas Stach * If the bootloader version is non-zero then the device is in 275c929ac9eSLucas Stach * bootloader mode and won't answer a query for the application FW 276c929ac9eSLucas Stach * version, so we just use the bootloader version info. 277c929ac9eSLucas Stach */ 278c929ac9eSLucas Stach if (response[2] || response[3]) 279c929ac9eSLucas Stach return sprintf(buf, "%d.%d\n", response[2], response[3]); 280c929ac9eSLucas Stach 281102feb1dSLucas Stach ret = exc3000_vendor_data_request(data, (u8[]){'D'}, 1, response, 1); 282102feb1dSLucas Stach if (ret < 0) 283102feb1dSLucas Stach return ret; 284d862a306SSebastian Reichel 285102feb1dSLucas Stach return sprintf(buf, "%s\n", &response[1]); 286d862a306SSebastian Reichel } 287d862a306SSebastian Reichel static DEVICE_ATTR_RO(fw_version); 288d862a306SSebastian Reichel 289d862a306SSebastian Reichel static ssize_t model_show(struct device *dev, 290d862a306SSebastian Reichel struct device_attribute *attr, char *buf) 291d862a306SSebastian Reichel { 292d862a306SSebastian Reichel struct i2c_client *client = to_i2c_client(dev); 293d862a306SSebastian Reichel struct exc3000_data *data = i2c_get_clientdata(client); 294102feb1dSLucas Stach u8 response[EXC3000_LEN_FRAME]; 295102feb1dSLucas Stach int ret; 296d862a306SSebastian Reichel 297102feb1dSLucas Stach ret = exc3000_vendor_data_request(data, (u8[]){'E'}, 1, response, 1); 298102feb1dSLucas Stach if (ret < 0) 299102feb1dSLucas Stach return ret; 300d862a306SSebastian Reichel 301102feb1dSLucas Stach return sprintf(buf, "%s\n", &response[1]); 302d862a306SSebastian Reichel } 303d862a306SSebastian Reichel static DEVICE_ATTR_RO(model); 304d862a306SSebastian Reichel 305ad117c55SLucas Stach static ssize_t type_show(struct device *dev, 306ad117c55SLucas Stach struct device_attribute *attr, char *buf) 307ad117c55SLucas Stach { 308ad117c55SLucas Stach struct i2c_client *client = to_i2c_client(dev); 309ad117c55SLucas Stach struct exc3000_data *data = i2c_get_clientdata(client); 310ad117c55SLucas Stach u8 response[EXC3000_LEN_FRAME]; 311ad117c55SLucas Stach int ret; 312ad117c55SLucas Stach 313ad117c55SLucas Stach ret = exc3000_vendor_data_request(data, (u8[]){'F'}, 1, response, 1); 314ad117c55SLucas Stach if (ret < 0) 315ad117c55SLucas Stach return ret; 316ad117c55SLucas Stach 317ad117c55SLucas Stach return sprintf(buf, "%s\n", &response[1]); 318ad117c55SLucas Stach } 319ad117c55SLucas Stach static DEVICE_ATTR_RO(type); 320ad117c55SLucas Stach 321d862a306SSebastian Reichel static struct attribute *sysfs_attrs[] = { 322d862a306SSebastian Reichel &dev_attr_fw_version.attr, 323d862a306SSebastian Reichel &dev_attr_model.attr, 324ad117c55SLucas Stach &dev_attr_type.attr, 325d862a306SSebastian Reichel NULL 326d862a306SSebastian Reichel }; 327d862a306SSebastian Reichel 328d862a306SSebastian Reichel static struct attribute_group exc3000_attribute_group = { 329d862a306SSebastian Reichel .attrs = sysfs_attrs 330d862a306SSebastian Reichel }; 331d862a306SSebastian Reichel 332deae5764SSebastian Reichel static int exc3000_probe(struct i2c_client *client) 3337e577a17SAhmet Inan { 3347e577a17SAhmet Inan struct exc3000_data *data; 3357e577a17SAhmet Inan struct input_dev *input; 336d862a306SSebastian Reichel int error, max_xy, retry; 3377e577a17SAhmet Inan 3387e577a17SAhmet Inan data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); 3397e577a17SAhmet Inan if (!data) 3407e577a17SAhmet Inan return -ENOMEM; 3417e577a17SAhmet Inan 3427e577a17SAhmet Inan data->client = client; 3433bdd21c6SSebastian Reichel data->info = device_get_match_data(&client->dev); 3443bdd21c6SSebastian Reichel if (!data->info) { 3453bdd21c6SSebastian Reichel enum eeti_dev_id eeti_dev_id = 3463bdd21c6SSebastian Reichel i2c_match_id(exc3000_id, client)->driver_data; 3473bdd21c6SSebastian Reichel data->info = &exc3000_info[eeti_dev_id]; 3483bdd21c6SSebastian Reichel } 3497e577a17SAhmet Inan timer_setup(&data->timer, exc3000_timer, 0); 350d862a306SSebastian Reichel init_completion(&data->wait_event); 351d862a306SSebastian Reichel mutex_init(&data->query_lock); 3527e577a17SAhmet Inan 35327aced19SSebastian Reichel data->reset = devm_gpiod_get_optional(&client->dev, "reset", 35427aced19SSebastian Reichel GPIOD_OUT_HIGH); 35527aced19SSebastian Reichel if (IS_ERR(data->reset)) 35627aced19SSebastian Reichel return PTR_ERR(data->reset); 35727aced19SSebastian Reichel 35827aced19SSebastian Reichel if (data->reset) { 35927aced19SSebastian Reichel msleep(EXC3000_RESET_MS); 36027aced19SSebastian Reichel gpiod_set_value_cansleep(data->reset, 0); 36127aced19SSebastian Reichel msleep(EXC3000_READY_MS); 36227aced19SSebastian Reichel } 36327aced19SSebastian Reichel 3647e577a17SAhmet Inan input = devm_input_allocate_device(&client->dev); 3657e577a17SAhmet Inan if (!input) 3667e577a17SAhmet Inan return -ENOMEM; 3677e577a17SAhmet Inan 3687e577a17SAhmet Inan data->input = input; 369d862a306SSebastian Reichel input_set_drvdata(input, data); 3707e577a17SAhmet Inan 3713bdd21c6SSebastian Reichel input->name = data->info->name; 3727e577a17SAhmet Inan input->id.bustype = BUS_I2C; 3737e577a17SAhmet Inan 3743bdd21c6SSebastian Reichel max_xy = data->info->max_xy; 3753bdd21c6SSebastian Reichel input_set_abs_params(input, ABS_MT_POSITION_X, 0, max_xy, 0, 0); 3763bdd21c6SSebastian Reichel input_set_abs_params(input, ABS_MT_POSITION_Y, 0, max_xy, 0, 0); 3773bdd21c6SSebastian Reichel 3787e577a17SAhmet Inan touchscreen_parse_properties(input, true, &data->prop); 3797e577a17SAhmet Inan 3807e577a17SAhmet Inan error = input_mt_init_slots(input, EXC3000_NUM_SLOTS, 3817e577a17SAhmet Inan INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); 3827e577a17SAhmet Inan if (error) 3837e577a17SAhmet Inan return error; 3847e577a17SAhmet Inan 3857e577a17SAhmet Inan error = input_register_device(input); 3867e577a17SAhmet Inan if (error) 3877e577a17SAhmet Inan return error; 3887e577a17SAhmet Inan 3897e577a17SAhmet Inan error = devm_request_threaded_irq(&client->dev, client->irq, 3907e577a17SAhmet Inan NULL, exc3000_interrupt, IRQF_ONESHOT, 3917e577a17SAhmet Inan client->name, data); 3927e577a17SAhmet Inan if (error) 3937e577a17SAhmet Inan return error; 3947e577a17SAhmet Inan 395d862a306SSebastian Reichel /* 396d862a306SSebastian Reichel * I²C does not have built-in recovery, so retry on failure. This 397d862a306SSebastian Reichel * ensures, that the device probe will not fail for temporary issues 398d862a306SSebastian Reichel * on the bus. This is not needed for the sysfs calls (userspace 399d862a306SSebastian Reichel * will receive the error code and can start another query) and 400d862a306SSebastian Reichel * cannot be done for touch events (but that only means loosing one 401d862a306SSebastian Reichel * or two touch events anyways). 402d862a306SSebastian Reichel */ 403d862a306SSebastian Reichel for (retry = 0; retry < 3; retry++) { 404102feb1dSLucas Stach u8 response[EXC3000_LEN_FRAME]; 405102feb1dSLucas Stach 406102feb1dSLucas Stach error = exc3000_vendor_data_request(data, (u8[]){'E'}, 1, 407102feb1dSLucas Stach response, 1); 408102feb1dSLucas Stach if (error > 0) { 409102feb1dSLucas Stach dev_dbg(&client->dev, "TS Model: %s", &response[1]); 410102feb1dSLucas Stach error = 0; 411d862a306SSebastian Reichel break; 412102feb1dSLucas Stach } 413d862a306SSebastian Reichel dev_warn(&client->dev, "Retry %d get EETI EXC3000 model: %d\n", 414d862a306SSebastian Reichel retry + 1, error); 415d862a306SSebastian Reichel } 416d862a306SSebastian Reichel 417d862a306SSebastian Reichel if (error) 418d862a306SSebastian Reichel return error; 419d862a306SSebastian Reichel 420d862a306SSebastian Reichel i2c_set_clientdata(client, data); 421d862a306SSebastian Reichel 422d862a306SSebastian Reichel error = devm_device_add_group(&client->dev, &exc3000_attribute_group); 423d862a306SSebastian Reichel if (error) 424d862a306SSebastian Reichel return error; 425d862a306SSebastian Reichel 4267e577a17SAhmet Inan return 0; 4277e577a17SAhmet Inan } 4287e577a17SAhmet Inan 4297e577a17SAhmet Inan static const struct i2c_device_id exc3000_id[] = { 4303bdd21c6SSebastian Reichel { "exc3000", EETI_EXC3000 }, 4313bdd21c6SSebastian Reichel { "exc80h60", EETI_EXC80H60 }, 4323bdd21c6SSebastian Reichel { "exc80h84", EETI_EXC80H84 }, 4337e577a17SAhmet Inan { } 4347e577a17SAhmet Inan }; 4357e577a17SAhmet Inan MODULE_DEVICE_TABLE(i2c, exc3000_id); 4367e577a17SAhmet Inan 4377e577a17SAhmet Inan #ifdef CONFIG_OF 4387e577a17SAhmet Inan static const struct of_device_id exc3000_of_match[] = { 4393bdd21c6SSebastian Reichel { .compatible = "eeti,exc3000", .data = &exc3000_info[EETI_EXC3000] }, 4403bdd21c6SSebastian Reichel { .compatible = "eeti,exc80h60", .data = &exc3000_info[EETI_EXC80H60] }, 4413bdd21c6SSebastian Reichel { .compatible = "eeti,exc80h84", .data = &exc3000_info[EETI_EXC80H84] }, 4427e577a17SAhmet Inan { } 4437e577a17SAhmet Inan }; 4447e577a17SAhmet Inan MODULE_DEVICE_TABLE(of, exc3000_of_match); 4457e577a17SAhmet Inan #endif 4467e577a17SAhmet Inan 4477e577a17SAhmet Inan static struct i2c_driver exc3000_driver = { 4487e577a17SAhmet Inan .driver = { 4497e577a17SAhmet Inan .name = "exc3000", 4507e577a17SAhmet Inan .of_match_table = of_match_ptr(exc3000_of_match), 4517e577a17SAhmet Inan }, 4527e577a17SAhmet Inan .id_table = exc3000_id, 453deae5764SSebastian Reichel .probe_new = exc3000_probe, 4547e577a17SAhmet Inan }; 4557e577a17SAhmet Inan 4567e577a17SAhmet Inan module_i2c_driver(exc3000_driver); 4577e577a17SAhmet Inan 4587e577a17SAhmet Inan MODULE_AUTHOR("Ahmet Inan <inan@distec.de>"); 4597e577a17SAhmet Inan MODULE_DESCRIPTION("I2C connected EETI EXC3000 multiple touch controller driver"); 4607e577a17SAhmet Inan MODULE_LICENSE("GPL v2"); 461