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 112*79c81d13SDmitry Torokhov static void exc3000_shutdown_timer(void *timer) 113*79c81d13SDmitry Torokhov { 114*79c81d13SDmitry Torokhov timer_shutdown_sync(timer); 115*79c81d13SDmitry Torokhov } 116*79c81d13SDmitry Torokhov 1173bdd21c6SSebastian Reichel static int exc3000_read_frame(struct exc3000_data *data, u8 *buf) 1187e577a17SAhmet Inan { 1193bdd21c6SSebastian Reichel struct i2c_client *client = data->client; 1207e577a17SAhmet Inan int ret; 1217e577a17SAhmet Inan 1227e577a17SAhmet Inan ret = i2c_master_send(client, "'", 2); 1237e577a17SAhmet Inan if (ret < 0) 1247e577a17SAhmet Inan return ret; 1257e577a17SAhmet Inan 1267e577a17SAhmet Inan if (ret != 2) 1277e577a17SAhmet Inan return -EIO; 1287e577a17SAhmet Inan 1297e577a17SAhmet Inan ret = i2c_master_recv(client, buf, EXC3000_LEN_FRAME); 1307e577a17SAhmet Inan if (ret < 0) 1317e577a17SAhmet Inan return ret; 1327e577a17SAhmet Inan 1337e577a17SAhmet Inan if (ret != EXC3000_LEN_FRAME) 1347e577a17SAhmet Inan return -EIO; 1357e577a17SAhmet Inan 1363bdd21c6SSebastian Reichel if (get_unaligned_le16(buf) != EXC3000_LEN_FRAME) 1373bdd21c6SSebastian Reichel return -EINVAL; 1383bdd21c6SSebastian Reichel 1397e577a17SAhmet Inan return 0; 1407e577a17SAhmet Inan } 1417e577a17SAhmet Inan 142a63d0120SLucas Stach static int exc3000_handle_mt_event(struct exc3000_data *data) 1437e577a17SAhmet Inan { 144a63d0120SLucas Stach struct input_dev *input = data->input; 145a63d0120SLucas Stach int ret, total_slots; 146a63d0120SLucas Stach u8 *buf = data->buf; 1477e577a17SAhmet Inan 148a63d0120SLucas Stach total_slots = buf[3]; 149a63d0120SLucas Stach if (!total_slots || total_slots > EXC3000_NUM_SLOTS) { 150a63d0120SLucas Stach ret = -EINVAL; 151a63d0120SLucas Stach goto out_fail; 152a63d0120SLucas Stach } 1537e577a17SAhmet Inan 154a63d0120SLucas Stach if (total_slots > EXC3000_SLOTS_PER_FRAME) { 1557e577a17SAhmet Inan /* Read 2nd frame to get the rest of the contacts. */ 156a63d0120SLucas Stach ret = exc3000_read_frame(data, buf + EXC3000_LEN_FRAME); 157a63d0120SLucas Stach if (ret) 158a63d0120SLucas Stach goto out_fail; 1597e577a17SAhmet Inan 1607e577a17SAhmet Inan /* 2nd chunk must have number of contacts set to 0. */ 161a63d0120SLucas Stach if (buf[EXC3000_LEN_FRAME + 3] != 0) { 162a63d0120SLucas Stach ret = -EINVAL; 163a63d0120SLucas Stach goto out_fail; 164a63d0120SLucas Stach } 1657e577a17SAhmet Inan } 1667e577a17SAhmet Inan 167a63d0120SLucas Stach /* 168a63d0120SLucas Stach * We read full state successfully, no contacts will be "stuck". 169a63d0120SLucas Stach */ 170a63d0120SLucas Stach del_timer_sync(&data->timer); 171a63d0120SLucas Stach 172a63d0120SLucas Stach while (total_slots > 0) { 173a63d0120SLucas Stach int slots = min(total_slots, EXC3000_SLOTS_PER_FRAME); 174a63d0120SLucas Stach 175a63d0120SLucas Stach exc3000_report_slots(input, &data->prop, buf + 4, slots); 176a63d0120SLucas Stach total_slots -= slots; 177a63d0120SLucas Stach buf += EXC3000_LEN_FRAME; 178a63d0120SLucas Stach } 179a63d0120SLucas Stach 180a63d0120SLucas Stach input_mt_sync_frame(input); 181a63d0120SLucas Stach input_sync(input); 182a63d0120SLucas Stach 1837e577a17SAhmet Inan return 0; 184a63d0120SLucas Stach 185a63d0120SLucas Stach out_fail: 186a63d0120SLucas Stach /* Schedule a timer to release "stuck" contacts */ 187a63d0120SLucas Stach exc3000_schedule_timer(data); 188a63d0120SLucas Stach 189a63d0120SLucas Stach return ret; 1907e577a17SAhmet Inan } 1917e577a17SAhmet Inan 1927e577a17SAhmet Inan static irqreturn_t exc3000_interrupt(int irq, void *dev_id) 1937e577a17SAhmet Inan { 1947e577a17SAhmet Inan struct exc3000_data *data = dev_id; 1957e577a17SAhmet Inan u8 *buf = data->buf; 196a63d0120SLucas Stach int ret; 1977e577a17SAhmet Inan 198a63d0120SLucas Stach ret = exc3000_read_frame(data, buf); 199a63d0120SLucas Stach if (ret) { 200a63d0120SLucas Stach /* Schedule a timer to release "stuck" contacts */ 201a63d0120SLucas Stach exc3000_schedule_timer(data); 202a63d0120SLucas Stach goto out; 203a63d0120SLucas Stach } 204a63d0120SLucas Stach 205a63d0120SLucas Stach switch (buf[2]) { 206a63d0120SLucas Stach case EXC3000_VENDOR_EVENT: 207d862a306SSebastian Reichel complete(&data->wait_event); 208a63d0120SLucas Stach break; 209a63d0120SLucas Stach 210a63d0120SLucas Stach case EXC3000_MT1_EVENT: 211a63d0120SLucas Stach case EXC3000_MT2_EVENT: 212a63d0120SLucas Stach exc3000_handle_mt_event(data); 213a63d0120SLucas Stach break; 214a63d0120SLucas Stach 215a63d0120SLucas Stach default: 216a63d0120SLucas Stach break; 217d862a306SSebastian Reichel } 218d862a306SSebastian Reichel 2197e577a17SAhmet Inan out: 2207e577a17SAhmet Inan return IRQ_HANDLED; 2217e577a17SAhmet Inan } 2227e577a17SAhmet Inan 223102feb1dSLucas Stach static int exc3000_vendor_data_request(struct exc3000_data *data, u8 *request, 224102feb1dSLucas Stach u8 request_len, u8 *response, int timeout) 225102feb1dSLucas Stach { 226102feb1dSLucas Stach u8 buf[EXC3000_LEN_VENDOR_REQUEST] = { 0x67, 0x00, 0x42, 0x00, 0x03 }; 227102feb1dSLucas Stach int ret; 2286bb7144cSMiaoqian Lin unsigned long time_left; 229102feb1dSLucas Stach 230102feb1dSLucas Stach mutex_lock(&data->query_lock); 231102feb1dSLucas Stach 232102feb1dSLucas Stach reinit_completion(&data->wait_event); 233102feb1dSLucas Stach 234102feb1dSLucas Stach buf[5] = request_len; 235102feb1dSLucas Stach memcpy(&buf[6], request, request_len); 236102feb1dSLucas Stach 237102feb1dSLucas Stach ret = i2c_master_send(data->client, buf, EXC3000_LEN_VENDOR_REQUEST); 238102feb1dSLucas Stach if (ret < 0) 239102feb1dSLucas Stach goto out_unlock; 240102feb1dSLucas Stach 241102feb1dSLucas Stach if (response) { 2426bb7144cSMiaoqian Lin time_left = wait_for_completion_timeout(&data->wait_event, 243102feb1dSLucas Stach timeout * HZ); 2446bb7144cSMiaoqian Lin if (time_left == 0) { 245102feb1dSLucas Stach ret = -ETIMEDOUT; 246102feb1dSLucas Stach goto out_unlock; 247102feb1dSLucas Stach } 248102feb1dSLucas Stach 249102feb1dSLucas Stach if (data->buf[3] >= EXC3000_LEN_FRAME) { 250102feb1dSLucas Stach ret = -ENOSPC; 251102feb1dSLucas Stach goto out_unlock; 252102feb1dSLucas Stach } 253102feb1dSLucas Stach 254102feb1dSLucas Stach memcpy(response, &data->buf[4], data->buf[3]); 255102feb1dSLucas Stach ret = data->buf[3]; 256102feb1dSLucas Stach } 257102feb1dSLucas Stach 258102feb1dSLucas Stach out_unlock: 259102feb1dSLucas Stach mutex_unlock(&data->query_lock); 260102feb1dSLucas Stach 261102feb1dSLucas Stach return ret; 262102feb1dSLucas Stach } 263102feb1dSLucas Stach 264d862a306SSebastian Reichel static ssize_t fw_version_show(struct device *dev, 265d862a306SSebastian Reichel struct device_attribute *attr, char *buf) 266d862a306SSebastian Reichel { 267d862a306SSebastian Reichel struct i2c_client *client = to_i2c_client(dev); 268d862a306SSebastian Reichel struct exc3000_data *data = i2c_get_clientdata(client); 269102feb1dSLucas Stach u8 response[EXC3000_LEN_FRAME]; 270102feb1dSLucas Stach int ret; 271d862a306SSebastian Reichel 272c929ac9eSLucas Stach /* query bootloader info */ 273c929ac9eSLucas Stach ret = exc3000_vendor_data_request(data, 274c929ac9eSLucas Stach (u8[]){0x39, 0x02}, 2, response, 1); 275c929ac9eSLucas Stach if (ret < 0) 276c929ac9eSLucas Stach return ret; 277c929ac9eSLucas Stach 278c929ac9eSLucas Stach /* 279c929ac9eSLucas Stach * If the bootloader version is non-zero then the device is in 280c929ac9eSLucas Stach * bootloader mode and won't answer a query for the application FW 281c929ac9eSLucas Stach * version, so we just use the bootloader version info. 282c929ac9eSLucas Stach */ 283c929ac9eSLucas Stach if (response[2] || response[3]) 284c929ac9eSLucas Stach return sprintf(buf, "%d.%d\n", response[2], response[3]); 285c929ac9eSLucas Stach 286102feb1dSLucas Stach ret = exc3000_vendor_data_request(data, (u8[]){'D'}, 1, response, 1); 287102feb1dSLucas Stach if (ret < 0) 288102feb1dSLucas Stach return ret; 289d862a306SSebastian Reichel 290102feb1dSLucas Stach return sprintf(buf, "%s\n", &response[1]); 291d862a306SSebastian Reichel } 292d862a306SSebastian Reichel static DEVICE_ATTR_RO(fw_version); 293d862a306SSebastian Reichel 294d862a306SSebastian Reichel static ssize_t model_show(struct device *dev, 295d862a306SSebastian Reichel struct device_attribute *attr, char *buf) 296d862a306SSebastian Reichel { 297d862a306SSebastian Reichel struct i2c_client *client = to_i2c_client(dev); 298d862a306SSebastian Reichel struct exc3000_data *data = i2c_get_clientdata(client); 299102feb1dSLucas Stach u8 response[EXC3000_LEN_FRAME]; 300102feb1dSLucas Stach int ret; 301d862a306SSebastian Reichel 302102feb1dSLucas Stach ret = exc3000_vendor_data_request(data, (u8[]){'E'}, 1, response, 1); 303102feb1dSLucas Stach if (ret < 0) 304102feb1dSLucas Stach return ret; 305d862a306SSebastian Reichel 306102feb1dSLucas Stach return sprintf(buf, "%s\n", &response[1]); 307d862a306SSebastian Reichel } 308d862a306SSebastian Reichel static DEVICE_ATTR_RO(model); 309d862a306SSebastian Reichel 310ad117c55SLucas Stach static ssize_t type_show(struct device *dev, 311ad117c55SLucas Stach struct device_attribute *attr, char *buf) 312ad117c55SLucas Stach { 313ad117c55SLucas Stach struct i2c_client *client = to_i2c_client(dev); 314ad117c55SLucas Stach struct exc3000_data *data = i2c_get_clientdata(client); 315ad117c55SLucas Stach u8 response[EXC3000_LEN_FRAME]; 316ad117c55SLucas Stach int ret; 317ad117c55SLucas Stach 318ad117c55SLucas Stach ret = exc3000_vendor_data_request(data, (u8[]){'F'}, 1, response, 1); 319ad117c55SLucas Stach if (ret < 0) 320ad117c55SLucas Stach return ret; 321ad117c55SLucas Stach 322ad117c55SLucas Stach return sprintf(buf, "%s\n", &response[1]); 323ad117c55SLucas Stach } 324ad117c55SLucas Stach static DEVICE_ATTR_RO(type); 325ad117c55SLucas Stach 326d862a306SSebastian Reichel static struct attribute *sysfs_attrs[] = { 327d862a306SSebastian Reichel &dev_attr_fw_version.attr, 328d862a306SSebastian Reichel &dev_attr_model.attr, 329ad117c55SLucas Stach &dev_attr_type.attr, 330d862a306SSebastian Reichel NULL 331d862a306SSebastian Reichel }; 332d862a306SSebastian Reichel 333d862a306SSebastian Reichel static struct attribute_group exc3000_attribute_group = { 334d862a306SSebastian Reichel .attrs = sysfs_attrs 335d862a306SSebastian Reichel }; 336d862a306SSebastian Reichel 337deae5764SSebastian Reichel static int exc3000_probe(struct i2c_client *client) 3387e577a17SAhmet Inan { 3397e577a17SAhmet Inan struct exc3000_data *data; 3407e577a17SAhmet Inan struct input_dev *input; 341d862a306SSebastian Reichel int error, max_xy, retry; 3427e577a17SAhmet Inan 3437e577a17SAhmet Inan data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); 3447e577a17SAhmet Inan if (!data) 3457e577a17SAhmet Inan return -ENOMEM; 3467e577a17SAhmet Inan 3477e577a17SAhmet Inan data->client = client; 3483bdd21c6SSebastian Reichel data->info = device_get_match_data(&client->dev); 3493bdd21c6SSebastian Reichel if (!data->info) { 3503bdd21c6SSebastian Reichel enum eeti_dev_id eeti_dev_id = 3513bdd21c6SSebastian Reichel i2c_match_id(exc3000_id, client)->driver_data; 3523bdd21c6SSebastian Reichel data->info = &exc3000_info[eeti_dev_id]; 3533bdd21c6SSebastian Reichel } 3547e577a17SAhmet Inan timer_setup(&data->timer, exc3000_timer, 0); 355d862a306SSebastian Reichel init_completion(&data->wait_event); 356d862a306SSebastian Reichel mutex_init(&data->query_lock); 3577e577a17SAhmet Inan 35827aced19SSebastian Reichel data->reset = devm_gpiod_get_optional(&client->dev, "reset", 35927aced19SSebastian Reichel GPIOD_OUT_HIGH); 36027aced19SSebastian Reichel if (IS_ERR(data->reset)) 36127aced19SSebastian Reichel return PTR_ERR(data->reset); 36227aced19SSebastian Reichel 36327aced19SSebastian Reichel if (data->reset) { 36427aced19SSebastian Reichel msleep(EXC3000_RESET_MS); 36527aced19SSebastian Reichel gpiod_set_value_cansleep(data->reset, 0); 36627aced19SSebastian Reichel msleep(EXC3000_READY_MS); 36727aced19SSebastian Reichel } 36827aced19SSebastian Reichel 3697e577a17SAhmet Inan input = devm_input_allocate_device(&client->dev); 3707e577a17SAhmet Inan if (!input) 3717e577a17SAhmet Inan return -ENOMEM; 3727e577a17SAhmet Inan 3737e577a17SAhmet Inan data->input = input; 374d862a306SSebastian Reichel input_set_drvdata(input, data); 3757e577a17SAhmet Inan 3763bdd21c6SSebastian Reichel input->name = data->info->name; 3777e577a17SAhmet Inan input->id.bustype = BUS_I2C; 3787e577a17SAhmet Inan 3793bdd21c6SSebastian Reichel max_xy = data->info->max_xy; 3803bdd21c6SSebastian Reichel input_set_abs_params(input, ABS_MT_POSITION_X, 0, max_xy, 0, 0); 3813bdd21c6SSebastian Reichel input_set_abs_params(input, ABS_MT_POSITION_Y, 0, max_xy, 0, 0); 3823bdd21c6SSebastian Reichel 3837e577a17SAhmet Inan touchscreen_parse_properties(input, true, &data->prop); 3847e577a17SAhmet Inan 3857e577a17SAhmet Inan error = input_mt_init_slots(input, EXC3000_NUM_SLOTS, 3867e577a17SAhmet Inan INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); 3877e577a17SAhmet Inan if (error) 3887e577a17SAhmet Inan return error; 3897e577a17SAhmet Inan 3907e577a17SAhmet Inan error = input_register_device(input); 3917e577a17SAhmet Inan if (error) 3927e577a17SAhmet Inan return error; 3937e577a17SAhmet Inan 394*79c81d13SDmitry Torokhov error = devm_add_action_or_reset(&client->dev, exc3000_shutdown_timer, 395*79c81d13SDmitry Torokhov &data->timer); 396*79c81d13SDmitry Torokhov if (error) 397*79c81d13SDmitry Torokhov return error; 398*79c81d13SDmitry Torokhov 3997e577a17SAhmet Inan error = devm_request_threaded_irq(&client->dev, client->irq, 4007e577a17SAhmet Inan NULL, exc3000_interrupt, IRQF_ONESHOT, 4017e577a17SAhmet Inan client->name, data); 4027e577a17SAhmet Inan if (error) 4037e577a17SAhmet Inan return error; 4047e577a17SAhmet Inan 405d862a306SSebastian Reichel /* 406d862a306SSebastian Reichel * I²C does not have built-in recovery, so retry on failure. This 407d862a306SSebastian Reichel * ensures, that the device probe will not fail for temporary issues 408d862a306SSebastian Reichel * on the bus. This is not needed for the sysfs calls (userspace 409d862a306SSebastian Reichel * will receive the error code and can start another query) and 410d862a306SSebastian Reichel * cannot be done for touch events (but that only means loosing one 411d862a306SSebastian Reichel * or two touch events anyways). 412d862a306SSebastian Reichel */ 413d862a306SSebastian Reichel for (retry = 0; retry < 3; retry++) { 414102feb1dSLucas Stach u8 response[EXC3000_LEN_FRAME]; 415102feb1dSLucas Stach 416102feb1dSLucas Stach error = exc3000_vendor_data_request(data, (u8[]){'E'}, 1, 417102feb1dSLucas Stach response, 1); 418102feb1dSLucas Stach if (error > 0) { 419102feb1dSLucas Stach dev_dbg(&client->dev, "TS Model: %s", &response[1]); 420102feb1dSLucas Stach error = 0; 421d862a306SSebastian Reichel break; 422102feb1dSLucas Stach } 423d862a306SSebastian Reichel dev_warn(&client->dev, "Retry %d get EETI EXC3000 model: %d\n", 424d862a306SSebastian Reichel retry + 1, error); 425d862a306SSebastian Reichel } 426d862a306SSebastian Reichel 427d862a306SSebastian Reichel if (error) 428d862a306SSebastian Reichel return error; 429d862a306SSebastian Reichel 430d862a306SSebastian Reichel i2c_set_clientdata(client, data); 431d862a306SSebastian Reichel 432d862a306SSebastian Reichel error = devm_device_add_group(&client->dev, &exc3000_attribute_group); 433d862a306SSebastian Reichel if (error) 434d862a306SSebastian Reichel return error; 435d862a306SSebastian Reichel 4367e577a17SAhmet Inan return 0; 4377e577a17SAhmet Inan } 4387e577a17SAhmet Inan 4397e577a17SAhmet Inan static const struct i2c_device_id exc3000_id[] = { 4403bdd21c6SSebastian Reichel { "exc3000", EETI_EXC3000 }, 4413bdd21c6SSebastian Reichel { "exc80h60", EETI_EXC80H60 }, 4423bdd21c6SSebastian Reichel { "exc80h84", EETI_EXC80H84 }, 4437e577a17SAhmet Inan { } 4447e577a17SAhmet Inan }; 4457e577a17SAhmet Inan MODULE_DEVICE_TABLE(i2c, exc3000_id); 4467e577a17SAhmet Inan 4477e577a17SAhmet Inan #ifdef CONFIG_OF 4487e577a17SAhmet Inan static const struct of_device_id exc3000_of_match[] = { 4493bdd21c6SSebastian Reichel { .compatible = "eeti,exc3000", .data = &exc3000_info[EETI_EXC3000] }, 4503bdd21c6SSebastian Reichel { .compatible = "eeti,exc80h60", .data = &exc3000_info[EETI_EXC80H60] }, 4513bdd21c6SSebastian Reichel { .compatible = "eeti,exc80h84", .data = &exc3000_info[EETI_EXC80H84] }, 4527e577a17SAhmet Inan { } 4537e577a17SAhmet Inan }; 4547e577a17SAhmet Inan MODULE_DEVICE_TABLE(of, exc3000_of_match); 4557e577a17SAhmet Inan #endif 4567e577a17SAhmet Inan 4577e577a17SAhmet Inan static struct i2c_driver exc3000_driver = { 4587e577a17SAhmet Inan .driver = { 4597e577a17SAhmet Inan .name = "exc3000", 4607e577a17SAhmet Inan .of_match_table = of_match_ptr(exc3000_of_match), 4617e577a17SAhmet Inan }, 4627e577a17SAhmet Inan .id_table = exc3000_id, 463deae5764SSebastian Reichel .probe_new = exc3000_probe, 4647e577a17SAhmet Inan }; 4657e577a17SAhmet Inan 4667e577a17SAhmet Inan module_i2c_driver(exc3000_driver); 4677e577a17SAhmet Inan 4687e577a17SAhmet Inan MODULE_AUTHOR("Ahmet Inan <inan@distec.de>"); 4697e577a17SAhmet Inan MODULE_DESCRIPTION("I2C connected EETI EXC3000 multiple touch controller driver"); 4707e577a17SAhmet Inan MODULE_LICENSE("GPL v2"); 471