166603243SChris Morgan // SPDX-License-Identifier: GPL-2.0-only 266603243SChris Morgan /* 366603243SChris Morgan * Driver for Hynitron cstxxx Touchscreen 466603243SChris Morgan * 566603243SChris Morgan * Copyright (c) 2022 Chris Morgan <macromorgan@hotmail.com> 666603243SChris Morgan * 766603243SChris Morgan * This code is based on hynitron_core.c authored by Hynitron. 866603243SChris Morgan * Note that no datasheet was available, so much of these registers 966603243SChris Morgan * are undocumented. This is essentially a cleaned-up version of the 1066603243SChris Morgan * vendor driver with support removed for hardware I cannot test and 1166603243SChris Morgan * device-specific functions replated with generic functions wherever 1266603243SChris Morgan * possible. 1366603243SChris Morgan */ 1466603243SChris Morgan 1566603243SChris Morgan #include <linux/delay.h> 1666603243SChris Morgan #include <linux/err.h> 1766603243SChris Morgan #include <linux/gpio/consumer.h> 1866603243SChris Morgan #include <linux/i2c.h> 1966603243SChris Morgan #include <linux/input.h> 2066603243SChris Morgan #include <linux/input/mt.h> 2166603243SChris Morgan #include <linux/input/touchscreen.h> 2266603243SChris Morgan #include <linux/mod_devicetable.h> 2366603243SChris Morgan #include <linux/module.h> 2466603243SChris Morgan #include <linux/property.h> 2566603243SChris Morgan #include <asm/unaligned.h> 2666603243SChris Morgan 2766603243SChris Morgan /* Per chip data */ 2866603243SChris Morgan struct hynitron_ts_chip_data { 2966603243SChris Morgan unsigned int max_touch_num; 3066603243SChris Morgan u32 ic_chkcode; 3166603243SChris Morgan int (*firmware_info)(struct i2c_client *client); 3266603243SChris Morgan int (*bootloader_enter)(struct i2c_client *client); 3366603243SChris Morgan int (*init_input)(struct i2c_client *client); 3466603243SChris Morgan void (*report_touch)(struct i2c_client *client); 3566603243SChris Morgan }; 3666603243SChris Morgan 3766603243SChris Morgan /* Data generic to all (supported and non-supported) controllers. */ 3866603243SChris Morgan struct hynitron_ts_data { 3966603243SChris Morgan const struct hynitron_ts_chip_data *chip; 4066603243SChris Morgan struct i2c_client *client; 4166603243SChris Morgan struct input_dev *input_dev; 4266603243SChris Morgan struct touchscreen_properties prop; 4366603243SChris Morgan struct gpio_desc *reset_gpio; 4466603243SChris Morgan }; 4566603243SChris Morgan 4666603243SChris Morgan /* 4766603243SChris Morgan * Since I have no datasheet, these values are guessed and/or assumed 4866603243SChris Morgan * based on observation and testing. 4966603243SChris Morgan */ 5066603243SChris Morgan #define CST3XX_FIRMWARE_INFO_START_CMD 0x01d1 5166603243SChris Morgan #define CST3XX_FIRMWARE_INFO_END_CMD 0x09d1 5266603243SChris Morgan #define CST3XX_FIRMWARE_CHK_CODE_REG 0xfcd1 5366603243SChris Morgan #define CST3XX_FIRMWARE_VERSION_REG 0x08d2 5466603243SChris Morgan #define CST3XX_FIRMWARE_VER_INVALID_VAL 0xa5a5a5a5 5566603243SChris Morgan 5666603243SChris Morgan #define CST3XX_BOOTLDR_PROG_CMD 0xaa01a0 5766603243SChris Morgan #define CST3XX_BOOTLDR_PROG_CHK_REG 0x02a0 5866603243SChris Morgan #define CST3XX_BOOTLDR_CHK_VAL 0xac 5966603243SChris Morgan 6066603243SChris Morgan #define CST3XX_TOUCH_DATA_PART_REG 0x00d0 6166603243SChris Morgan #define CST3XX_TOUCH_DATA_FULL_REG 0x07d0 6266603243SChris Morgan #define CST3XX_TOUCH_DATA_CHK_VAL 0xab 6366603243SChris Morgan #define CST3XX_TOUCH_DATA_TOUCH_VAL 0x03 6466603243SChris Morgan #define CST3XX_TOUCH_DATA_STOP_CMD 0xab00d0 6566603243SChris Morgan #define CST3XX_TOUCH_COUNT_MASK GENMASK(6, 0) 6666603243SChris Morgan 6766603243SChris Morgan 6866603243SChris Morgan /* 6966603243SChris Morgan * Hard coded reset delay value of 20ms not IC dependent in 7066603243SChris Morgan * vendor driver. 7166603243SChris Morgan */ 7266603243SChris Morgan static void hyn_reset_proc(struct i2c_client *client, int delay) 7366603243SChris Morgan { 7466603243SChris Morgan struct hynitron_ts_data *ts_data = i2c_get_clientdata(client); 7566603243SChris Morgan 7666603243SChris Morgan gpiod_set_value_cansleep(ts_data->reset_gpio, 1); 7766603243SChris Morgan msleep(20); 7866603243SChris Morgan gpiod_set_value_cansleep(ts_data->reset_gpio, 0); 7966603243SChris Morgan if (delay) 8066603243SChris Morgan fsleep(delay * 1000); 8166603243SChris Morgan } 8266603243SChris Morgan 8366603243SChris Morgan static irqreturn_t hyn_interrupt_handler(int irq, void *dev_id) 8466603243SChris Morgan { 8566603243SChris Morgan struct i2c_client *client = dev_id; 8666603243SChris Morgan struct hynitron_ts_data *ts_data = i2c_get_clientdata(client); 8766603243SChris Morgan 8866603243SChris Morgan ts_data->chip->report_touch(client); 8966603243SChris Morgan 9066603243SChris Morgan return IRQ_HANDLED; 9166603243SChris Morgan } 9266603243SChris Morgan 9366603243SChris Morgan /* 9466603243SChris Morgan * The vendor driver would retry twice before failing to read or write 9566603243SChris Morgan * to the i2c device. 9666603243SChris Morgan */ 9766603243SChris Morgan 9866603243SChris Morgan static int cst3xx_i2c_write(struct i2c_client *client, 9966603243SChris Morgan unsigned char *buf, int len) 10066603243SChris Morgan { 10166603243SChris Morgan int ret; 10266603243SChris Morgan int retries = 0; 10366603243SChris Morgan 10466603243SChris Morgan while (retries < 2) { 10566603243SChris Morgan ret = i2c_master_send(client, buf, len); 10666603243SChris Morgan if (ret == len) 10766603243SChris Morgan return 0; 10866603243SChris Morgan if (ret <= 0) 10966603243SChris Morgan retries++; 11066603243SChris Morgan else 11166603243SChris Morgan break; 11266603243SChris Morgan } 11366603243SChris Morgan 11466603243SChris Morgan return ret < 0 ? ret : -EIO; 11566603243SChris Morgan } 11666603243SChris Morgan 11766603243SChris Morgan static int cst3xx_i2c_read_register(struct i2c_client *client, u16 reg, 11866603243SChris Morgan u8 *val, u16 len) 11966603243SChris Morgan { 12066603243SChris Morgan __le16 buf = cpu_to_le16(reg); 12166603243SChris Morgan struct i2c_msg msgs[] = { 12266603243SChris Morgan { 12366603243SChris Morgan .addr = client->addr, 12466603243SChris Morgan .flags = 0, 12566603243SChris Morgan .len = 2, 12666603243SChris Morgan .buf = (u8 *)&buf, 12766603243SChris Morgan }, 12866603243SChris Morgan { 12966603243SChris Morgan .addr = client->addr, 13066603243SChris Morgan .flags = I2C_M_RD, 13166603243SChris Morgan .len = len, 13266603243SChris Morgan .buf = val, 13366603243SChris Morgan } 13466603243SChris Morgan }; 13566603243SChris Morgan int err; 13666603243SChris Morgan int ret; 13766603243SChris Morgan 13866603243SChris Morgan ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); 13966603243SChris Morgan if (ret == ARRAY_SIZE(msgs)) 14066603243SChris Morgan return 0; 14166603243SChris Morgan 14266603243SChris Morgan err = ret < 0 ? ret : -EIO; 14366603243SChris Morgan dev_err(&client->dev, "Error reading %d bytes from 0x%04x: %d (%d)\n", 14466603243SChris Morgan len, reg, err, ret); 14566603243SChris Morgan 14666603243SChris Morgan return err; 14766603243SChris Morgan } 14866603243SChris Morgan 14966603243SChris Morgan static int cst3xx_firmware_info(struct i2c_client *client) 15066603243SChris Morgan { 15166603243SChris Morgan struct hynitron_ts_data *ts_data = i2c_get_clientdata(client); 15266603243SChris Morgan int err; 15366603243SChris Morgan u32 tmp; 15466603243SChris Morgan unsigned char buf[4]; 15566603243SChris Morgan 15666603243SChris Morgan /* 15766603243SChris Morgan * Tests suggest this command needed to read firmware regs. 15866603243SChris Morgan */ 15966603243SChris Morgan put_unaligned_le16(CST3XX_FIRMWARE_INFO_START_CMD, buf); 16066603243SChris Morgan err = cst3xx_i2c_write(client, buf, 2); 16166603243SChris Morgan if (err) 16266603243SChris Morgan return err; 16366603243SChris Morgan 16466603243SChris Morgan usleep_range(10000, 11000); 16566603243SChris Morgan 16666603243SChris Morgan /* 16766603243SChris Morgan * Read register for check-code to determine if device detected 16866603243SChris Morgan * correctly. 16966603243SChris Morgan */ 17066603243SChris Morgan err = cst3xx_i2c_read_register(client, CST3XX_FIRMWARE_CHK_CODE_REG, 17166603243SChris Morgan buf, 4); 17266603243SChris Morgan if (err) 17366603243SChris Morgan return err; 17466603243SChris Morgan 17566603243SChris Morgan tmp = get_unaligned_le32(buf); 17666603243SChris Morgan if ((tmp & 0xffff0000) != ts_data->chip->ic_chkcode) { 17766603243SChris Morgan dev_err(&client->dev, "%s ic mismatch, chkcode is %u\n", 17866603243SChris Morgan __func__, tmp); 17966603243SChris Morgan return -ENODEV; 18066603243SChris Morgan } 18166603243SChris Morgan 18266603243SChris Morgan usleep_range(10000, 11000); 18366603243SChris Morgan 18466603243SChris Morgan /* Read firmware version and test if firmware missing. */ 18566603243SChris Morgan err = cst3xx_i2c_read_register(client, CST3XX_FIRMWARE_VERSION_REG, 18666603243SChris Morgan buf, 4); 18766603243SChris Morgan if (err) 18866603243SChris Morgan return err; 18966603243SChris Morgan 19066603243SChris Morgan tmp = get_unaligned_le32(buf); 19166603243SChris Morgan if (tmp == CST3XX_FIRMWARE_VER_INVALID_VAL) { 19266603243SChris Morgan dev_err(&client->dev, "Device firmware missing\n"); 19366603243SChris Morgan return -ENODEV; 19466603243SChris Morgan } 19566603243SChris Morgan 19666603243SChris Morgan /* 19766603243SChris Morgan * Tests suggest cmd required to exit reading firmware regs. 19866603243SChris Morgan */ 19966603243SChris Morgan put_unaligned_le16(CST3XX_FIRMWARE_INFO_END_CMD, buf); 20066603243SChris Morgan err = cst3xx_i2c_write(client, buf, 2); 20166603243SChris Morgan if (err) 20266603243SChris Morgan return err; 20366603243SChris Morgan 20466603243SChris Morgan usleep_range(5000, 6000); 20566603243SChris Morgan 20666603243SChris Morgan return 0; 20766603243SChris Morgan } 20866603243SChris Morgan 20966603243SChris Morgan static int cst3xx_bootloader_enter(struct i2c_client *client) 21066603243SChris Morgan { 21166603243SChris Morgan int err; 21266603243SChris Morgan u8 retry; 213*c7f43645SChris Morgan u32 tmp = 0; 21466603243SChris Morgan unsigned char buf[3]; 21566603243SChris Morgan 21666603243SChris Morgan for (retry = 0; retry < 5; retry++) { 21766603243SChris Morgan hyn_reset_proc(client, (7 + retry)); 21866603243SChris Morgan /* set cmd to enter program mode */ 21966603243SChris Morgan put_unaligned_le24(CST3XX_BOOTLDR_PROG_CMD, buf); 22066603243SChris Morgan err = cst3xx_i2c_write(client, buf, 3); 22166603243SChris Morgan if (err) 22266603243SChris Morgan continue; 22366603243SChris Morgan 22466603243SChris Morgan usleep_range(2000, 2500); 22566603243SChris Morgan 22666603243SChris Morgan /* check whether in program mode */ 22766603243SChris Morgan err = cst3xx_i2c_read_register(client, 22866603243SChris Morgan CST3XX_BOOTLDR_PROG_CHK_REG, 22966603243SChris Morgan buf, 1); 23066603243SChris Morgan if (err) 23166603243SChris Morgan continue; 23266603243SChris Morgan 23366603243SChris Morgan tmp = get_unaligned(buf); 23466603243SChris Morgan if (tmp == CST3XX_BOOTLDR_CHK_VAL) 23566603243SChris Morgan break; 23666603243SChris Morgan } 23766603243SChris Morgan 23866603243SChris Morgan if (tmp != CST3XX_BOOTLDR_CHK_VAL) { 23966603243SChris Morgan dev_err(&client->dev, "%s unable to enter bootloader mode\n", 24066603243SChris Morgan __func__); 24166603243SChris Morgan return -ENODEV; 24266603243SChris Morgan } 24366603243SChris Morgan 24466603243SChris Morgan hyn_reset_proc(client, 40); 24566603243SChris Morgan 24666603243SChris Morgan return 0; 24766603243SChris Morgan } 24866603243SChris Morgan 24966603243SChris Morgan static void cst3xx_report_contact(struct hynitron_ts_data *ts_data, 25066603243SChris Morgan u8 id, unsigned int x, unsigned int y, u8 w) 25166603243SChris Morgan { 25266603243SChris Morgan input_mt_slot(ts_data->input_dev, id); 25366603243SChris Morgan input_mt_report_slot_state(ts_data->input_dev, MT_TOOL_FINGER, 1); 25466603243SChris Morgan touchscreen_report_pos(ts_data->input_dev, &ts_data->prop, x, y, true); 25566603243SChris Morgan input_report_abs(ts_data->input_dev, ABS_MT_TOUCH_MAJOR, w); 25666603243SChris Morgan } 25766603243SChris Morgan 25866603243SChris Morgan static int cst3xx_finish_touch_read(struct i2c_client *client) 25966603243SChris Morgan { 26066603243SChris Morgan unsigned char buf[3]; 26166603243SChris Morgan int err; 26266603243SChris Morgan 26366603243SChris Morgan put_unaligned_le24(CST3XX_TOUCH_DATA_STOP_CMD, buf); 26466603243SChris Morgan err = cst3xx_i2c_write(client, buf, 3); 26566603243SChris Morgan if (err) { 26666603243SChris Morgan dev_err(&client->dev, 26766603243SChris Morgan "send read touch info ending failed: %d\n", err); 26866603243SChris Morgan return err; 26966603243SChris Morgan } 27066603243SChris Morgan 27166603243SChris Morgan return 0; 27266603243SChris Morgan } 27366603243SChris Morgan 27466603243SChris Morgan /* 27566603243SChris Morgan * Handle events from IRQ. Note that for cst3xx it appears that IRQ 27666603243SChris Morgan * fires continuously while touched, otherwise once every 1500ms 27766603243SChris Morgan * when not touched (assume touchscreen waking up periodically). 27866603243SChris Morgan * Note buffer is sized for 5 fingers, if more needed buffer must 27966603243SChris Morgan * be increased. The buffer contains 5 bytes for each touch point, 28066603243SChris Morgan * a touch count byte, a check byte, and then a second check byte after 28166603243SChris Morgan * all other touch points. 28266603243SChris Morgan * 28366603243SChris Morgan * For example 1 touch would look like this: 28466603243SChris Morgan * touch1[5]:touch_count[1]:chk_byte[1] 28566603243SChris Morgan * 28666603243SChris Morgan * 3 touches would look like this: 28766603243SChris Morgan * touch1[5]:touch_count[1]:chk_byte[1]:touch2[5]:touch3[5]:chk_byte[1] 28866603243SChris Morgan */ 28966603243SChris Morgan static void cst3xx_touch_report(struct i2c_client *client) 29066603243SChris Morgan { 29166603243SChris Morgan struct hynitron_ts_data *ts_data = i2c_get_clientdata(client); 29266603243SChris Morgan u8 buf[28]; 29366603243SChris Morgan u8 finger_id, sw, w; 29466603243SChris Morgan unsigned int x, y; 29566603243SChris Morgan unsigned int touch_cnt, end_byte; 29666603243SChris Morgan unsigned int idx = 0; 29766603243SChris Morgan unsigned int i; 29866603243SChris Morgan int err; 29966603243SChris Morgan 30066603243SChris Morgan /* Read and validate the first bits of input data. */ 30166603243SChris Morgan err = cst3xx_i2c_read_register(client, CST3XX_TOUCH_DATA_PART_REG, 30266603243SChris Morgan buf, 28); 30366603243SChris Morgan if (err || 30466603243SChris Morgan buf[6] != CST3XX_TOUCH_DATA_CHK_VAL || 30566603243SChris Morgan buf[0] == CST3XX_TOUCH_DATA_CHK_VAL) { 30666603243SChris Morgan dev_err(&client->dev, "cst3xx touch read failure\n"); 30766603243SChris Morgan return; 30866603243SChris Morgan } 30966603243SChris Morgan 31066603243SChris Morgan /* Report to the device we're done reading the touch data. */ 31166603243SChris Morgan err = cst3xx_finish_touch_read(client); 31266603243SChris Morgan if (err) 31366603243SChris Morgan return; 31466603243SChris Morgan 31566603243SChris Morgan touch_cnt = buf[5] & CST3XX_TOUCH_COUNT_MASK; 31666603243SChris Morgan /* 31766603243SChris Morgan * Check the check bit of the last touch slot. The check bit is 31866603243SChris Morgan * always present after touch point 1 for valid data, and then 31966603243SChris Morgan * appears as the last byte after all other touch data. 32066603243SChris Morgan */ 32166603243SChris Morgan if (touch_cnt > 1) { 32266603243SChris Morgan end_byte = touch_cnt * 5 + 2; 32366603243SChris Morgan if (buf[end_byte] != CST3XX_TOUCH_DATA_CHK_VAL) { 32466603243SChris Morgan dev_err(&client->dev, "cst3xx touch read failure\n"); 32566603243SChris Morgan return; 32666603243SChris Morgan } 32766603243SChris Morgan } 32866603243SChris Morgan 32966603243SChris Morgan /* Parse through the buffer to capture touch data. */ 33066603243SChris Morgan for (i = 0; i < touch_cnt; i++) { 33166603243SChris Morgan x = ((buf[idx + 1] << 4) | ((buf[idx + 3] >> 4) & 0x0f)); 33266603243SChris Morgan y = ((buf[idx + 2] << 4) | (buf[idx + 3] & 0x0f)); 33366603243SChris Morgan w = (buf[idx + 4] >> 3); 33466603243SChris Morgan sw = (buf[idx] & 0x0f) >> 1; 33566603243SChris Morgan finger_id = (buf[idx] >> 4) & 0x0f; 33666603243SChris Morgan 33766603243SChris Morgan /* Sanity check we don't have more fingers than we expect */ 33866603243SChris Morgan if (ts_data->chip->max_touch_num < finger_id) { 33966603243SChris Morgan dev_err(&client->dev, "cst3xx touch read failure\n"); 34066603243SChris Morgan break; 34166603243SChris Morgan } 34266603243SChris Morgan 34366603243SChris Morgan /* sw value of 0 means no touch, 0x03 means touch */ 34466603243SChris Morgan if (sw == CST3XX_TOUCH_DATA_TOUCH_VAL) 34566603243SChris Morgan cst3xx_report_contact(ts_data, finger_id, x, y, w); 34666603243SChris Morgan 34766603243SChris Morgan idx += 5; 34866603243SChris Morgan 34966603243SChris Morgan /* Skip the 2 bytes between point 1 and point 2 */ 35066603243SChris Morgan if (i == 0) 35166603243SChris Morgan idx += 2; 35266603243SChris Morgan } 35366603243SChris Morgan 35466603243SChris Morgan input_mt_sync_frame(ts_data->input_dev); 35566603243SChris Morgan input_sync(ts_data->input_dev); 35666603243SChris Morgan } 35766603243SChris Morgan 35866603243SChris Morgan static int cst3xx_input_dev_int(struct i2c_client *client) 35966603243SChris Morgan { 36066603243SChris Morgan struct hynitron_ts_data *ts_data = i2c_get_clientdata(client); 36166603243SChris Morgan int err; 36266603243SChris Morgan 36366603243SChris Morgan ts_data->input_dev = devm_input_allocate_device(&client->dev); 36466603243SChris Morgan if (!ts_data->input_dev) { 36566603243SChris Morgan dev_err(&client->dev, "Failed to allocate input device\n"); 36666603243SChris Morgan return -ENOMEM; 36766603243SChris Morgan } 36866603243SChris Morgan 36966603243SChris Morgan ts_data->input_dev->name = "Hynitron cst3xx Touchscreen"; 37066603243SChris Morgan ts_data->input_dev->phys = "input/ts"; 37166603243SChris Morgan ts_data->input_dev->id.bustype = BUS_I2C; 37266603243SChris Morgan 37366603243SChris Morgan input_set_drvdata(ts_data->input_dev, ts_data); 37466603243SChris Morgan 37566603243SChris Morgan input_set_capability(ts_data->input_dev, EV_ABS, ABS_MT_POSITION_X); 37666603243SChris Morgan input_set_capability(ts_data->input_dev, EV_ABS, ABS_MT_POSITION_Y); 37766603243SChris Morgan input_set_abs_params(ts_data->input_dev, ABS_MT_TOUCH_MAJOR, 37866603243SChris Morgan 0, 255, 0, 0); 37966603243SChris Morgan 38066603243SChris Morgan touchscreen_parse_properties(ts_data->input_dev, true, &ts_data->prop); 38166603243SChris Morgan 38266603243SChris Morgan if (!ts_data->prop.max_x || !ts_data->prop.max_y) { 38366603243SChris Morgan dev_err(&client->dev, 38466603243SChris Morgan "Invalid x/y (%d, %d), using defaults\n", 38566603243SChris Morgan ts_data->prop.max_x, ts_data->prop.max_y); 38666603243SChris Morgan ts_data->prop.max_x = 1152; 38766603243SChris Morgan ts_data->prop.max_y = 1920; 38866603243SChris Morgan input_abs_set_max(ts_data->input_dev, 38966603243SChris Morgan ABS_MT_POSITION_X, ts_data->prop.max_x); 39066603243SChris Morgan input_abs_set_max(ts_data->input_dev, 39166603243SChris Morgan ABS_MT_POSITION_Y, ts_data->prop.max_y); 39266603243SChris Morgan } 39366603243SChris Morgan 39466603243SChris Morgan err = input_mt_init_slots(ts_data->input_dev, 39566603243SChris Morgan ts_data->chip->max_touch_num, 39666603243SChris Morgan INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); 39766603243SChris Morgan if (err) { 39866603243SChris Morgan dev_err(&client->dev, 39966603243SChris Morgan "Failed to initialize input slots: %d\n", err); 40066603243SChris Morgan return err; 40166603243SChris Morgan } 40266603243SChris Morgan 40366603243SChris Morgan err = input_register_device(ts_data->input_dev); 40466603243SChris Morgan if (err) { 40566603243SChris Morgan dev_err(&client->dev, 40666603243SChris Morgan "Input device registration failed: %d\n", err); 40766603243SChris Morgan return err; 40866603243SChris Morgan } 40966603243SChris Morgan 41066603243SChris Morgan return 0; 41166603243SChris Morgan } 41266603243SChris Morgan 41366603243SChris Morgan static int hyn_probe(struct i2c_client *client) 41466603243SChris Morgan { 41566603243SChris Morgan struct hynitron_ts_data *ts_data; 41666603243SChris Morgan int err; 41766603243SChris Morgan 41866603243SChris Morgan ts_data = devm_kzalloc(&client->dev, sizeof(*ts_data), GFP_KERNEL); 41966603243SChris Morgan if (!ts_data) 42066603243SChris Morgan return -ENOMEM; 42166603243SChris Morgan 42266603243SChris Morgan ts_data->client = client; 42366603243SChris Morgan i2c_set_clientdata(client, ts_data); 42466603243SChris Morgan 42566603243SChris Morgan ts_data->chip = device_get_match_data(&client->dev); 42666603243SChris Morgan if (!ts_data->chip) 42766603243SChris Morgan return -EINVAL; 42866603243SChris Morgan 42966603243SChris Morgan ts_data->reset_gpio = devm_gpiod_get(&client->dev, 43066603243SChris Morgan "reset", GPIOD_OUT_LOW); 43166603243SChris Morgan err = PTR_ERR_OR_ZERO(ts_data->reset_gpio); 43266603243SChris Morgan if (err) { 43366603243SChris Morgan dev_err(&client->dev, "request reset gpio failed: %d\n", err); 43466603243SChris Morgan return err; 43566603243SChris Morgan } 43666603243SChris Morgan 43766603243SChris Morgan hyn_reset_proc(client, 60); 43866603243SChris Morgan 43966603243SChris Morgan err = ts_data->chip->bootloader_enter(client); 44066603243SChris Morgan if (err < 0) 44166603243SChris Morgan return err; 44266603243SChris Morgan 44366603243SChris Morgan err = ts_data->chip->init_input(client); 44466603243SChris Morgan if (err < 0) 44566603243SChris Morgan return err; 44666603243SChris Morgan 44766603243SChris Morgan err = ts_data->chip->firmware_info(client); 44866603243SChris Morgan if (err < 0) 44966603243SChris Morgan return err; 45066603243SChris Morgan 45166603243SChris Morgan err = devm_request_threaded_irq(&client->dev, client->irq, 45266603243SChris Morgan NULL, hyn_interrupt_handler, 45366603243SChris Morgan IRQF_ONESHOT, 45466603243SChris Morgan "Hynitron Touch Int", client); 45566603243SChris Morgan if (err) { 45666603243SChris Morgan dev_err(&client->dev, "failed to request IRQ: %d\n", err); 45766603243SChris Morgan return err; 45866603243SChris Morgan } 45966603243SChris Morgan 46066603243SChris Morgan return 0; 46166603243SChris Morgan } 46266603243SChris Morgan 46366603243SChris Morgan static const struct hynitron_ts_chip_data cst3xx_data = { 46466603243SChris Morgan .max_touch_num = 5, 46566603243SChris Morgan .ic_chkcode = 0xcaca0000, 46666603243SChris Morgan .firmware_info = &cst3xx_firmware_info, 46766603243SChris Morgan .bootloader_enter = &cst3xx_bootloader_enter, 46866603243SChris Morgan .init_input = &cst3xx_input_dev_int, 46966603243SChris Morgan .report_touch = &cst3xx_touch_report, 47066603243SChris Morgan }; 47166603243SChris Morgan 47266603243SChris Morgan static const struct i2c_device_id hyn_tpd_id[] = { 47366603243SChris Morgan { .name = "hynitron_ts", 0 }, 47466603243SChris Morgan { /* sentinel */ }, 47566603243SChris Morgan }; 47666603243SChris Morgan MODULE_DEVICE_TABLE(i2c, hyn_tpd_id); 47766603243SChris Morgan 47866603243SChris Morgan static const struct of_device_id hyn_dt_match[] = { 47966603243SChris Morgan { .compatible = "hynitron,cst340", .data = &cst3xx_data }, 48066603243SChris Morgan { /* sentinel */ }, 48166603243SChris Morgan }; 48266603243SChris Morgan MODULE_DEVICE_TABLE(of, hyn_dt_match); 48366603243SChris Morgan 48466603243SChris Morgan static struct i2c_driver hynitron_i2c_driver = { 48566603243SChris Morgan .driver = { 48666603243SChris Morgan .name = "Hynitron-TS", 48766603243SChris Morgan .of_match_table = hyn_dt_match, 48866603243SChris Morgan .probe_type = PROBE_PREFER_ASYNCHRONOUS, 48966603243SChris Morgan }, 49066603243SChris Morgan .id_table = hyn_tpd_id, 49166603243SChris Morgan .probe_new = hyn_probe, 49266603243SChris Morgan }; 49366603243SChris Morgan 49466603243SChris Morgan module_i2c_driver(hynitron_i2c_driver); 49566603243SChris Morgan 49666603243SChris Morgan MODULE_AUTHOR("Chris Morgan"); 49766603243SChris Morgan MODULE_DESCRIPTION("Hynitron Touchscreen Driver"); 49866603243SChris Morgan MODULE_LICENSE("GPL"); 499