1ac1dc6b2SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
266aee900SScott Liu /*
366aee900SScott Liu  * Elan Microelectronics touch panels with I2C interface
466aee900SScott Liu  *
566aee900SScott Liu  * Copyright (C) 2014 Elan Microelectronics Corporation.
666aee900SScott Liu  * Scott Liu <scott.liu@emc.com.tw>
766aee900SScott Liu  *
866aee900SScott Liu  * This code is partly based on hid-multitouch.c:
966aee900SScott Liu  *
1066aee900SScott Liu  *  Copyright (c) 2010-2012 Stephane Chatty <chatty@enac.fr>
1166aee900SScott Liu  *  Copyright (c) 2010-2012 Benjamin Tissoires <benjamin.tissoires@gmail.com>
1266aee900SScott Liu  *  Copyright (c) 2010-2012 Ecole Nationale de l'Aviation Civile, France
1366aee900SScott Liu  *
1466aee900SScott Liu  * This code is partly based on i2c-hid.c:
1566aee900SScott Liu  *
1666aee900SScott Liu  * Copyright (c) 2012 Benjamin Tissoires <benjamin.tissoires@gmail.com>
1766aee900SScott Liu  * Copyright (c) 2012 Ecole Nationale de l'Aviation Civile, France
1866aee900SScott Liu  * Copyright (c) 2012 Red Hat, Inc
1966aee900SScott Liu  */
2066aee900SScott Liu 
2166aee900SScott Liu 
22f27ad893SJohnny Chuang #include <linux/bits.h>
2366aee900SScott Liu #include <linux/module.h>
2466aee900SScott Liu #include <linux/input.h>
2566aee900SScott Liu #include <linux/interrupt.h>
264c83c071SDmitry Torokhov #include <linux/irq.h>
2766aee900SScott Liu #include <linux/platform_device.h>
2866aee900SScott Liu #include <linux/async.h>
2966aee900SScott Liu #include <linux/i2c.h>
3066aee900SScott Liu #include <linux/delay.h>
3166aee900SScott Liu #include <linux/uaccess.h>
3266aee900SScott Liu #include <linux/buffer_head.h>
3366aee900SScott Liu #include <linux/slab.h>
3466aee900SScott Liu #include <linux/firmware.h>
3566aee900SScott Liu #include <linux/input/mt.h>
3668334dbaSMichał Mirosław #include <linux/input/touchscreen.h>
3766aee900SScott Liu #include <linux/acpi.h>
3866aee900SScott Liu #include <linux/of.h>
39afe10358SDmitry Torokhov #include <linux/gpio/consumer.h>
40afe10358SDmitry Torokhov #include <linux/regulator/consumer.h>
4166aee900SScott Liu #include <asm/unaligned.h>
4266aee900SScott Liu 
4366aee900SScott Liu /* Device, Driver information */
4466aee900SScott Liu #define DEVICE_NAME	"elants_i2c"
4566aee900SScott Liu 
4666aee900SScott Liu /* Convert from rows or columns into resolution */
4766aee900SScott Liu #define ELAN_TS_RESOLUTION(n, m)   (((n) - 1) * (m))
4866aee900SScott Liu 
4966aee900SScott Liu /* FW header data */
5066aee900SScott Liu #define HEADER_SIZE		4
5166aee900SScott Liu #define FW_HDR_TYPE		0
5266aee900SScott Liu #define FW_HDR_COUNT		1
5366aee900SScott Liu #define FW_HDR_LENGTH		2
5466aee900SScott Liu 
5566aee900SScott Liu /* Buffer mode Queue Header information */
5666aee900SScott Liu #define QUEUE_HEADER_SINGLE	0x62
5766aee900SScott Liu #define QUEUE_HEADER_NORMAL	0X63
5866aee900SScott Liu #define QUEUE_HEADER_WAIT	0x64
5966aee900SScott Liu 
6066aee900SScott Liu /* Command header definition */
6166aee900SScott Liu #define CMD_HEADER_WRITE	0x54
6266aee900SScott Liu #define CMD_HEADER_READ		0x53
6366aee900SScott Liu #define CMD_HEADER_6B_READ	0x5B
64f0b57e19SJohnny.Chuang #define CMD_HEADER_ROM_READ	0x96
6566aee900SScott Liu #define CMD_HEADER_RESP		0x52
6666aee900SScott Liu #define CMD_HEADER_6B_RESP	0x9B
67f0b57e19SJohnny.Chuang #define CMD_HEADER_ROM_RESP	0x95
6866aee900SScott Liu #define CMD_HEADER_HELLO	0x55
6966aee900SScott Liu #define CMD_HEADER_REK		0x66
7066aee900SScott Liu 
7166aee900SScott Liu /* FW position data */
7266aee900SScott Liu #define PACKET_SIZE		55
7366aee900SScott Liu #define MAX_CONTACT_NUM		10
7466aee900SScott Liu #define FW_POS_HEADER		0
7566aee900SScott Liu #define FW_POS_STATE		1
7666aee900SScott Liu #define FW_POS_TOTAL		2
7766aee900SScott Liu #define FW_POS_XY		3
78f27ad893SJohnny Chuang #define FW_POS_TOOL_TYPE	33
7966aee900SScott Liu #define FW_POS_CHECKSUM		34
8066aee900SScott Liu #define FW_POS_WIDTH		35
8166aee900SScott Liu #define FW_POS_PRESSURE		45
8266aee900SScott Liu 
8366aee900SScott Liu #define HEADER_REPORT_10_FINGER	0x62
8466aee900SScott Liu 
8566aee900SScott Liu /* Header (4 bytes) plus 3 fill 10-finger packets */
8666aee900SScott Liu #define MAX_PACKET_SIZE		169
8766aee900SScott Liu 
8866aee900SScott Liu #define BOOT_TIME_DELAY_MS	50
8966aee900SScott Liu 
9066aee900SScott Liu /* FW read command, 0x53 0x?? 0x0, 0x01 */
9166aee900SScott Liu #define E_ELAN_INFO_FW_VER	0x00
9266aee900SScott Liu #define E_ELAN_INFO_BC_VER	0x10
93cf520c64SJohnny Chuang #define E_ELAN_INFO_REK		0xE0
9466aee900SScott Liu #define E_ELAN_INFO_TEST_VER	0xE0
9566aee900SScott Liu #define E_ELAN_INFO_FW_ID	0xF0
9666aee900SScott Liu #define E_INFO_OSR		0xD6
9766aee900SScott Liu #define E_INFO_PHY_SCAN		0xD7
9866aee900SScott Liu #define E_INFO_PHY_DRIVER	0xD8
9966aee900SScott Liu 
10066aee900SScott Liu #define MAX_RETRIES		3
10166aee900SScott Liu #define MAX_FW_UPDATE_RETRIES	30
10266aee900SScott Liu 
10366aee900SScott Liu #define ELAN_FW_PAGESIZE	132
10466aee900SScott Liu 
10566aee900SScott Liu /* calibration timeout definition */
10622c15e5eSJames Chen #define ELAN_CALI_TIMEOUT_MSEC	12000
10766aee900SScott Liu 
108afe10358SDmitry Torokhov #define ELAN_POWERON_DELAY_USEC	500
109afe10358SDmitry Torokhov #define ELAN_RESET_DELAY_MSEC	20
110afe10358SDmitry Torokhov 
11166aee900SScott Liu enum elants_state {
11266aee900SScott Liu 	ELAN_STATE_NORMAL,
11366aee900SScott Liu 	ELAN_WAIT_QUEUE_HEADER,
11466aee900SScott Liu 	ELAN_WAIT_RECALIBRATION,
11566aee900SScott Liu };
11666aee900SScott Liu 
11766aee900SScott Liu enum elants_iap_mode {
11866aee900SScott Liu 	ELAN_IAP_OPERATIONAL,
11966aee900SScott Liu 	ELAN_IAP_RECOVERY,
12066aee900SScott Liu };
12166aee900SScott Liu 
12266aee900SScott Liu /* struct elants_data - represents state of Elan touchscreen device */
12366aee900SScott Liu struct elants_data {
12466aee900SScott Liu 	struct i2c_client *client;
12566aee900SScott Liu 	struct input_dev *input;
12666aee900SScott Liu 
127afe10358SDmitry Torokhov 	struct regulator *vcc33;
128afe10358SDmitry Torokhov 	struct regulator *vccio;
129afe10358SDmitry Torokhov 	struct gpio_desc *reset_gpio;
130afe10358SDmitry Torokhov 
13166aee900SScott Liu 	u16 fw_version;
13266aee900SScott Liu 	u8 test_version;
13366aee900SScott Liu 	u8 solution_version;
13466aee900SScott Liu 	u8 bc_version;
13566aee900SScott Liu 	u8 iap_version;
13666aee900SScott Liu 	u16 hw_version;
13766aee900SScott Liu 	unsigned int x_res;	/* resolution in units/mm */
13866aee900SScott Liu 	unsigned int y_res;
13966aee900SScott Liu 	unsigned int x_max;
14066aee900SScott Liu 	unsigned int y_max;
14168334dbaSMichał Mirosław 	struct touchscreen_properties prop;
14266aee900SScott Liu 
14366aee900SScott Liu 	enum elants_state state;
14466aee900SScott Liu 	enum elants_iap_mode iap_mode;
14566aee900SScott Liu 
14666aee900SScott Liu 	/* Guards against concurrent access to the device via sysfs */
14766aee900SScott Liu 	struct mutex sysfs_mutex;
14866aee900SScott Liu 
14966aee900SScott Liu 	u8 cmd_resp[HEADER_SIZE];
15066aee900SScott Liu 	struct completion cmd_done;
15166aee900SScott Liu 
15266aee900SScott Liu 	bool wake_irq_enabled;
153afe10358SDmitry Torokhov 	bool keep_power_in_suspend;
15400f73f97SStephen Boyd 
15500f73f97SStephen Boyd 	/* Must be last to be used for DMA operations */
15600f73f97SStephen Boyd 	u8 buf[MAX_PACKET_SIZE] ____cacheline_aligned;
15766aee900SScott Liu };
15866aee900SScott Liu 
15966aee900SScott Liu static int elants_i2c_send(struct i2c_client *client,
16066aee900SScott Liu 			   const void *data, size_t size)
16166aee900SScott Liu {
16266aee900SScott Liu 	int ret;
16366aee900SScott Liu 
16466aee900SScott Liu 	ret = i2c_master_send(client, data, size);
16566aee900SScott Liu 	if (ret == size)
16666aee900SScott Liu 		return 0;
16766aee900SScott Liu 
16866aee900SScott Liu 	if (ret >= 0)
16966aee900SScott Liu 		ret = -EIO;
17066aee900SScott Liu 
17166aee900SScott Liu 	dev_err(&client->dev, "%s failed (%*ph): %d\n",
17266aee900SScott Liu 		__func__, (int)size, data, ret);
17366aee900SScott Liu 
17466aee900SScott Liu 	return ret;
17566aee900SScott Liu }
17666aee900SScott Liu 
17766aee900SScott Liu static int elants_i2c_read(struct i2c_client *client, void *data, size_t size)
17866aee900SScott Liu {
17966aee900SScott Liu 	int ret;
18066aee900SScott Liu 
18166aee900SScott Liu 	ret = i2c_master_recv(client, data, size);
18266aee900SScott Liu 	if (ret == size)
18366aee900SScott Liu 		return 0;
18466aee900SScott Liu 
18566aee900SScott Liu 	if (ret >= 0)
18666aee900SScott Liu 		ret = -EIO;
18766aee900SScott Liu 
18866aee900SScott Liu 	dev_err(&client->dev, "%s failed: %d\n", __func__, ret);
18966aee900SScott Liu 
19066aee900SScott Liu 	return ret;
19166aee900SScott Liu }
19266aee900SScott Liu 
19366aee900SScott Liu static int elants_i2c_execute_command(struct i2c_client *client,
19466aee900SScott Liu 				      const u8 *cmd, size_t cmd_size,
19566aee900SScott Liu 				      u8 *resp, size_t resp_size)
19666aee900SScott Liu {
19766aee900SScott Liu 	struct i2c_msg msgs[2];
19866aee900SScott Liu 	int ret;
19966aee900SScott Liu 	u8 expected_response;
20066aee900SScott Liu 
20166aee900SScott Liu 	switch (cmd[0]) {
20266aee900SScott Liu 	case CMD_HEADER_READ:
20366aee900SScott Liu 		expected_response = CMD_HEADER_RESP;
20466aee900SScott Liu 		break;
20566aee900SScott Liu 
20666aee900SScott Liu 	case CMD_HEADER_6B_READ:
20766aee900SScott Liu 		expected_response = CMD_HEADER_6B_RESP;
20866aee900SScott Liu 		break;
20966aee900SScott Liu 
210f0b57e19SJohnny.Chuang 	case CMD_HEADER_ROM_READ:
211f0b57e19SJohnny.Chuang 		expected_response = CMD_HEADER_ROM_RESP;
212f0b57e19SJohnny.Chuang 		break;
213f0b57e19SJohnny.Chuang 
21466aee900SScott Liu 	default:
21566aee900SScott Liu 		dev_err(&client->dev, "%s: invalid command %*ph\n",
21666aee900SScott Liu 			__func__, (int)cmd_size, cmd);
21766aee900SScott Liu 		return -EINVAL;
21866aee900SScott Liu 	}
21966aee900SScott Liu 
22066aee900SScott Liu 	msgs[0].addr = client->addr;
22166aee900SScott Liu 	msgs[0].flags = client->flags & I2C_M_TEN;
22266aee900SScott Liu 	msgs[0].len = cmd_size;
22366aee900SScott Liu 	msgs[0].buf = (u8 *)cmd;
22466aee900SScott Liu 
22566aee900SScott Liu 	msgs[1].addr = client->addr;
22666aee900SScott Liu 	msgs[1].flags = client->flags & I2C_M_TEN;
22766aee900SScott Liu 	msgs[1].flags |= I2C_M_RD;
22866aee900SScott Liu 	msgs[1].len = resp_size;
22966aee900SScott Liu 	msgs[1].buf = resp;
23066aee900SScott Liu 
23166aee900SScott Liu 	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
23266aee900SScott Liu 	if (ret < 0)
23366aee900SScott Liu 		return ret;
23466aee900SScott Liu 
23566aee900SScott Liu 	if (ret != ARRAY_SIZE(msgs) || resp[FW_HDR_TYPE] != expected_response)
23666aee900SScott Liu 		return -EIO;
23766aee900SScott Liu 
23866aee900SScott Liu 	return 0;
23966aee900SScott Liu }
24066aee900SScott Liu 
24166aee900SScott Liu static int elants_i2c_calibrate(struct elants_data *ts)
24266aee900SScott Liu {
24366aee900SScott Liu 	struct i2c_client *client = ts->client;
24466aee900SScott Liu 	int ret, error;
24566aee900SScott Liu 	static const u8 w_flashkey[] = { 0x54, 0xC0, 0xE1, 0x5A };
24666aee900SScott Liu 	static const u8 rek[] = { 0x54, 0x29, 0x00, 0x01 };
24766aee900SScott Liu 	static const u8 rek_resp[] = { CMD_HEADER_REK, 0x66, 0x66, 0x66 };
24866aee900SScott Liu 
24966aee900SScott Liu 	disable_irq(client->irq);
25066aee900SScott Liu 
25166aee900SScott Liu 	ts->state = ELAN_WAIT_RECALIBRATION;
25266aee900SScott Liu 	reinit_completion(&ts->cmd_done);
25366aee900SScott Liu 
25466aee900SScott Liu 	elants_i2c_send(client, w_flashkey, sizeof(w_flashkey));
25566aee900SScott Liu 	elants_i2c_send(client, rek, sizeof(rek));
25666aee900SScott Liu 
25766aee900SScott Liu 	enable_irq(client->irq);
25866aee900SScott Liu 
25966aee900SScott Liu 	ret = wait_for_completion_interruptible_timeout(&ts->cmd_done,
26066aee900SScott Liu 				msecs_to_jiffies(ELAN_CALI_TIMEOUT_MSEC));
26166aee900SScott Liu 
26266aee900SScott Liu 	ts->state = ELAN_STATE_NORMAL;
26366aee900SScott Liu 
26466aee900SScott Liu 	if (ret <= 0) {
26566aee900SScott Liu 		error = ret < 0 ? ret : -ETIMEDOUT;
26666aee900SScott Liu 		dev_err(&client->dev,
26766aee900SScott Liu 			"error while waiting for calibration to complete: %d\n",
26866aee900SScott Liu 			error);
26966aee900SScott Liu 		return error;
27066aee900SScott Liu 	}
27166aee900SScott Liu 
27266aee900SScott Liu 	if (memcmp(rek_resp, ts->cmd_resp, sizeof(rek_resp))) {
27366aee900SScott Liu 		dev_err(&client->dev,
27466aee900SScott Liu 			"unexpected calibration response: %*ph\n",
27566aee900SScott Liu 			(int)sizeof(ts->cmd_resp), ts->cmd_resp);
27666aee900SScott Liu 		return -EINVAL;
27766aee900SScott Liu 	}
27866aee900SScott Liu 
27966aee900SScott Liu 	return 0;
28066aee900SScott Liu }
28166aee900SScott Liu 
28266aee900SScott Liu static int elants_i2c_sw_reset(struct i2c_client *client)
28366aee900SScott Liu {
28466aee900SScott Liu 	const u8 soft_rst_cmd[] = { 0x77, 0x77, 0x77, 0x77 };
28566aee900SScott Liu 	int error;
28666aee900SScott Liu 
28766aee900SScott Liu 	error = elants_i2c_send(client, soft_rst_cmd,
28866aee900SScott Liu 				sizeof(soft_rst_cmd));
28966aee900SScott Liu 	if (error) {
29066aee900SScott Liu 		dev_err(&client->dev, "software reset failed: %d\n", error);
29166aee900SScott Liu 		return error;
29266aee900SScott Liu 	}
29366aee900SScott Liu 
29466aee900SScott Liu 	/*
29566aee900SScott Liu 	 * We should wait at least 10 msec (but no more than 40) before
29666aee900SScott Liu 	 * sending fastboot or IAP command to the device.
29766aee900SScott Liu 	 */
29866aee900SScott Liu 	msleep(30);
29966aee900SScott Liu 
30066aee900SScott Liu 	return 0;
30166aee900SScott Liu }
30266aee900SScott Liu 
30366aee900SScott Liu static u16 elants_i2c_parse_version(u8 *buf)
30466aee900SScott Liu {
30566aee900SScott Liu 	return get_unaligned_be32(buf) >> 4;
30666aee900SScott Liu }
30766aee900SScott Liu 
308bc1d57feSJohnny Chuang static int elants_i2c_query_hw_version(struct elants_data *ts)
30966aee900SScott Liu {
31066aee900SScott Liu 	struct i2c_client *client = ts->client;
31166aee900SScott Liu 	int error, retry_cnt;
31266aee900SScott Liu 	const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_FW_ID, 0x00, 0x01 };
31366aee900SScott Liu 	u8 resp[HEADER_SIZE];
31466aee900SScott Liu 
31566aee900SScott Liu 	for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) {
31666aee900SScott Liu 		error = elants_i2c_execute_command(client, cmd, sizeof(cmd),
31766aee900SScott Liu 						   resp, sizeof(resp));
31866aee900SScott Liu 		if (!error) {
31966aee900SScott Liu 			ts->hw_version = elants_i2c_parse_version(resp);
32066aee900SScott Liu 			if (ts->hw_version != 0xffff)
32166aee900SScott Liu 				return 0;
32266aee900SScott Liu 		}
32366aee900SScott Liu 
32466aee900SScott Liu 		dev_dbg(&client->dev, "read fw id error=%d, buf=%*phC\n",
32566aee900SScott Liu 			error, (int)sizeof(resp), resp);
32666aee900SScott Liu 	}
32766aee900SScott Liu 
328bc1d57feSJohnny Chuang 	if (error) {
32966aee900SScott Liu 		dev_err(&client->dev,
330bc1d57feSJohnny Chuang 			"Failed to read fw id: %d\n", error);
331bc1d57feSJohnny Chuang 		return error;
332bc1d57feSJohnny Chuang 	}
333bc1d57feSJohnny Chuang 
334bc1d57feSJohnny Chuang 	dev_err(&client->dev, "Invalid fw id: %#04x\n", ts->hw_version);
33566aee900SScott Liu 
33666aee900SScott Liu 	return -EINVAL;
33766aee900SScott Liu }
33866aee900SScott Liu 
33966aee900SScott Liu static int elants_i2c_query_fw_version(struct elants_data *ts)
34066aee900SScott Liu {
34166aee900SScott Liu 	struct i2c_client *client = ts->client;
34266aee900SScott Liu 	int error, retry_cnt;
34366aee900SScott Liu 	const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_FW_VER, 0x00, 0x01 };
34466aee900SScott Liu 	u8 resp[HEADER_SIZE];
34566aee900SScott Liu 
34666aee900SScott Liu 	for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) {
34766aee900SScott Liu 		error = elants_i2c_execute_command(client, cmd, sizeof(cmd),
34866aee900SScott Liu 						   resp, sizeof(resp));
34966aee900SScott Liu 		if (!error) {
35066aee900SScott Liu 			ts->fw_version = elants_i2c_parse_version(resp);
35166aee900SScott Liu 			if (ts->fw_version != 0x0000 &&
35266aee900SScott Liu 			    ts->fw_version != 0xffff)
35366aee900SScott Liu 				return 0;
35466aee900SScott Liu 		}
35566aee900SScott Liu 
35666aee900SScott Liu 		dev_dbg(&client->dev, "read fw version error=%d, buf=%*phC\n",
35766aee900SScott Liu 			error, (int)sizeof(resp), resp);
35866aee900SScott Liu 	}
35966aee900SScott Liu 
36066aee900SScott Liu 	dev_err(&client->dev,
36166aee900SScott Liu 		"Failed to read fw version or fw version is invalid\n");
36266aee900SScott Liu 
36366aee900SScott Liu 	return -EINVAL;
36466aee900SScott Liu }
36566aee900SScott Liu 
36666aee900SScott Liu static int elants_i2c_query_test_version(struct elants_data *ts)
36766aee900SScott Liu {
36866aee900SScott Liu 	struct i2c_client *client = ts->client;
36966aee900SScott Liu 	int error, retry_cnt;
37066aee900SScott Liu 	u16 version;
37166aee900SScott Liu 	const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_TEST_VER, 0x00, 0x01 };
37266aee900SScott Liu 	u8 resp[HEADER_SIZE];
37366aee900SScott Liu 
37466aee900SScott Liu 	for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) {
37566aee900SScott Liu 		error = elants_i2c_execute_command(client, cmd, sizeof(cmd),
37666aee900SScott Liu 						   resp, sizeof(resp));
37766aee900SScott Liu 		if (!error) {
37866aee900SScott Liu 			version = elants_i2c_parse_version(resp);
37966aee900SScott Liu 			ts->test_version = version >> 8;
38066aee900SScott Liu 			ts->solution_version = version & 0xff;
38166aee900SScott Liu 
38266aee900SScott Liu 			return 0;
38366aee900SScott Liu 		}
38466aee900SScott Liu 
38566aee900SScott Liu 		dev_dbg(&client->dev,
38666aee900SScott Liu 			"read test version error rc=%d, buf=%*phC\n",
38766aee900SScott Liu 			error, (int)sizeof(resp), resp);
38866aee900SScott Liu 	}
38966aee900SScott Liu 
39066aee900SScott Liu 	dev_err(&client->dev, "Failed to read test version\n");
39166aee900SScott Liu 
39266aee900SScott Liu 	return -EINVAL;
39366aee900SScott Liu }
39466aee900SScott Liu 
39566aee900SScott Liu static int elants_i2c_query_bc_version(struct elants_data *ts)
39666aee900SScott Liu {
39766aee900SScott Liu 	struct i2c_client *client = ts->client;
39866aee900SScott Liu 	const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_BC_VER, 0x00, 0x01 };
39966aee900SScott Liu 	u8 resp[HEADER_SIZE];
40066aee900SScott Liu 	u16 version;
40166aee900SScott Liu 	int error;
40266aee900SScott Liu 
40366aee900SScott Liu 	error = elants_i2c_execute_command(client, cmd, sizeof(cmd),
40466aee900SScott Liu 					   resp, sizeof(resp));
40566aee900SScott Liu 	if (error) {
40666aee900SScott Liu 		dev_err(&client->dev,
40766aee900SScott Liu 			"read BC version error=%d, buf=%*phC\n",
40866aee900SScott Liu 			error, (int)sizeof(resp), resp);
40966aee900SScott Liu 		return error;
41066aee900SScott Liu 	}
41166aee900SScott Liu 
41266aee900SScott Liu 	version = elants_i2c_parse_version(resp);
41366aee900SScott Liu 	ts->bc_version = version >> 8;
41466aee900SScott Liu 	ts->iap_version = version & 0xff;
41566aee900SScott Liu 
41666aee900SScott Liu 	return 0;
41766aee900SScott Liu }
41866aee900SScott Liu 
41966aee900SScott Liu static int elants_i2c_query_ts_info(struct elants_data *ts)
42066aee900SScott Liu {
42166aee900SScott Liu 	struct i2c_client *client = ts->client;
42266aee900SScott Liu 	int error;
42366aee900SScott Liu 	u8 resp[17];
42466aee900SScott Liu 	u16 phy_x, phy_y, rows, cols, osr;
42566aee900SScott Liu 	const u8 get_resolution_cmd[] = {
42666aee900SScott Liu 		CMD_HEADER_6B_READ, 0x00, 0x00, 0x00, 0x00, 0x00
42766aee900SScott Liu 	};
42866aee900SScott Liu 	const u8 get_osr_cmd[] = {
42966aee900SScott Liu 		CMD_HEADER_READ, E_INFO_OSR, 0x00, 0x01
43066aee900SScott Liu 	};
43166aee900SScott Liu 	const u8 get_physical_scan_cmd[] = {
43266aee900SScott Liu 		CMD_HEADER_READ, E_INFO_PHY_SCAN, 0x00, 0x01
43366aee900SScott Liu 	};
43466aee900SScott Liu 	const u8 get_physical_drive_cmd[] = {
43566aee900SScott Liu 		CMD_HEADER_READ, E_INFO_PHY_DRIVER, 0x00, 0x01
43666aee900SScott Liu 	};
43766aee900SScott Liu 
43866aee900SScott Liu 	/* Get trace number */
43966aee900SScott Liu 	error = elants_i2c_execute_command(client,
44066aee900SScott Liu 					   get_resolution_cmd,
44166aee900SScott Liu 					   sizeof(get_resolution_cmd),
44266aee900SScott Liu 					   resp, sizeof(resp));
44366aee900SScott Liu 	if (error) {
44466aee900SScott Liu 		dev_err(&client->dev, "get resolution command failed: %d\n",
44566aee900SScott Liu 			error);
44666aee900SScott Liu 		return error;
44766aee900SScott Liu 	}
44866aee900SScott Liu 
44966aee900SScott Liu 	rows = resp[2] + resp[6] + resp[10];
45066aee900SScott Liu 	cols = resp[3] + resp[7] + resp[11];
45166aee900SScott Liu 
45266aee900SScott Liu 	/* Process mm_to_pixel information */
45366aee900SScott Liu 	error = elants_i2c_execute_command(client,
45466aee900SScott Liu 					   get_osr_cmd, sizeof(get_osr_cmd),
45566aee900SScott Liu 					   resp, sizeof(resp));
45666aee900SScott Liu 	if (error) {
45766aee900SScott Liu 		dev_err(&client->dev, "get osr command failed: %d\n",
45866aee900SScott Liu 			error);
45966aee900SScott Liu 		return error;
46066aee900SScott Liu 	}
46166aee900SScott Liu 
46266aee900SScott Liu 	osr = resp[3];
46366aee900SScott Liu 
46466aee900SScott Liu 	error = elants_i2c_execute_command(client,
46566aee900SScott Liu 					   get_physical_scan_cmd,
46666aee900SScott Liu 					   sizeof(get_physical_scan_cmd),
46766aee900SScott Liu 					   resp, sizeof(resp));
46866aee900SScott Liu 	if (error) {
46966aee900SScott Liu 		dev_err(&client->dev, "get physical scan command failed: %d\n",
47066aee900SScott Liu 			error);
47166aee900SScott Liu 		return error;
47266aee900SScott Liu 	}
47366aee900SScott Liu 
47466aee900SScott Liu 	phy_x = get_unaligned_be16(&resp[2]);
47566aee900SScott Liu 
47666aee900SScott Liu 	error = elants_i2c_execute_command(client,
47766aee900SScott Liu 					   get_physical_drive_cmd,
47866aee900SScott Liu 					   sizeof(get_physical_drive_cmd),
47966aee900SScott Liu 					   resp, sizeof(resp));
48066aee900SScott Liu 	if (error) {
48166aee900SScott Liu 		dev_err(&client->dev, "get physical drive command failed: %d\n",
48266aee900SScott Liu 			error);
48366aee900SScott Liu 		return error;
48466aee900SScott Liu 	}
48566aee900SScott Liu 
48666aee900SScott Liu 	phy_y = get_unaligned_be16(&resp[2]);
48766aee900SScott Liu 
48866aee900SScott Liu 	dev_dbg(&client->dev, "phy_x=%d, phy_y=%d\n", phy_x, phy_y);
48966aee900SScott Liu 
49066aee900SScott Liu 	if (rows == 0 || cols == 0 || osr == 0) {
49166aee900SScott Liu 		dev_warn(&client->dev,
49266aee900SScott Liu 			 "invalid trace number data: %d, %d, %d\n",
49366aee900SScott Liu 			 rows, cols, osr);
49466aee900SScott Liu 	} else {
49566aee900SScott Liu 		/* translate trace number to TS resolution */
49666aee900SScott Liu 		ts->x_max = ELAN_TS_RESOLUTION(rows, osr);
49766aee900SScott Liu 		ts->x_res = DIV_ROUND_CLOSEST(ts->x_max, phy_x);
49866aee900SScott Liu 		ts->y_max = ELAN_TS_RESOLUTION(cols, osr);
49966aee900SScott Liu 		ts->y_res = DIV_ROUND_CLOSEST(ts->y_max, phy_y);
50066aee900SScott Liu 	}
50166aee900SScott Liu 
50266aee900SScott Liu 	return 0;
50366aee900SScott Liu }
50466aee900SScott Liu 
50566aee900SScott Liu static int elants_i2c_fastboot(struct i2c_client *client)
50666aee900SScott Liu {
50766aee900SScott Liu 	const u8 boot_cmd[] = { 0x4D, 0x61, 0x69, 0x6E };
50866aee900SScott Liu 	int error;
50966aee900SScott Liu 
51066aee900SScott Liu 	error = elants_i2c_send(client, boot_cmd, sizeof(boot_cmd));
51166aee900SScott Liu 	if (error) {
51266aee900SScott Liu 		dev_err(&client->dev, "boot failed: %d\n", error);
51366aee900SScott Liu 		return error;
51466aee900SScott Liu 	}
51566aee900SScott Liu 
51666aee900SScott Liu 	dev_dbg(&client->dev, "boot success -- 0x%x\n", client->addr);
51766aee900SScott Liu 	return 0;
51866aee900SScott Liu }
51966aee900SScott Liu 
52066aee900SScott Liu static int elants_i2c_initialize(struct elants_data *ts)
52166aee900SScott Liu {
52266aee900SScott Liu 	struct i2c_client *client = ts->client;
523bc1d57feSJohnny Chuang 	int error, error2, retry_cnt;
52466aee900SScott Liu 	const u8 hello_packet[] = { 0x55, 0x55, 0x55, 0x55 };
52566aee900SScott Liu 	const u8 recov_packet[] = { 0x55, 0x55, 0x80, 0x80 };
52666aee900SScott Liu 	u8 buf[HEADER_SIZE];
52766aee900SScott Liu 
52866aee900SScott Liu 	for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) {
52966aee900SScott Liu 		error = elants_i2c_sw_reset(client);
53066aee900SScott Liu 		if (error) {
53166aee900SScott Liu 			/* Continue initializing if it's the last try */
53266aee900SScott Liu 			if (retry_cnt < MAX_RETRIES - 1)
53366aee900SScott Liu 				continue;
53466aee900SScott Liu 		}
53566aee900SScott Liu 
53666aee900SScott Liu 		error = elants_i2c_fastboot(client);
53766aee900SScott Liu 		if (error) {
53866aee900SScott Liu 			/* Continue initializing if it's the last try */
53966aee900SScott Liu 			if (retry_cnt < MAX_RETRIES - 1)
54066aee900SScott Liu 				continue;
54166aee900SScott Liu 		}
54266aee900SScott Liu 
54366aee900SScott Liu 		/* Wait for Hello packet */
54466aee900SScott Liu 		msleep(BOOT_TIME_DELAY_MS);
54566aee900SScott Liu 
54666aee900SScott Liu 		error = elants_i2c_read(client, buf, sizeof(buf));
54766aee900SScott Liu 		if (error) {
54866aee900SScott Liu 			dev_err(&client->dev,
54966aee900SScott Liu 				"failed to read 'hello' packet: %d\n", error);
55066aee900SScott Liu 		} else if (!memcmp(buf, hello_packet, sizeof(hello_packet))) {
55166aee900SScott Liu 			ts->iap_mode = ELAN_IAP_OPERATIONAL;
55266aee900SScott Liu 			break;
55366aee900SScott Liu 		} else if (!memcmp(buf, recov_packet, sizeof(recov_packet))) {
55466aee900SScott Liu 			/*
55566aee900SScott Liu 			 * Setting error code will mark device
55666aee900SScott Liu 			 * in recovery mode below.
55766aee900SScott Liu 			 */
55866aee900SScott Liu 			error = -EIO;
55966aee900SScott Liu 			break;
56066aee900SScott Liu 		} else {
56166aee900SScott Liu 			error = -EINVAL;
56266aee900SScott Liu 			dev_err(&client->dev,
56366aee900SScott Liu 				"invalid 'hello' packet: %*ph\n",
56466aee900SScott Liu 				(int)sizeof(buf), buf);
56566aee900SScott Liu 		}
56666aee900SScott Liu 	}
56766aee900SScott Liu 
568bc1d57feSJohnny Chuang 	/* hw version is available even if device in recovery state */
569bc1d57feSJohnny Chuang 	error2 = elants_i2c_query_hw_version(ts);
570f0b57e19SJohnny.Chuang 	if (!error2)
571f0b57e19SJohnny.Chuang 		error2 = elants_i2c_query_bc_version(ts);
57266aee900SScott Liu 	if (!error)
573bc1d57feSJohnny Chuang 		error = error2;
574bc1d57feSJohnny Chuang 
57566aee900SScott Liu 	if (!error)
57666aee900SScott Liu 		error = elants_i2c_query_fw_version(ts);
577bc1d57feSJohnny Chuang 	if (!error)
578bc1d57feSJohnny Chuang 		error = elants_i2c_query_test_version(ts);
579bc1d57feSJohnny Chuang 	if (!error)
580bc1d57feSJohnny Chuang 		error = elants_i2c_query_ts_info(ts);
58166aee900SScott Liu 
582bc1d57feSJohnny Chuang 	if (error)
58366aee900SScott Liu 		ts->iap_mode = ELAN_IAP_RECOVERY;
58466aee900SScott Liu 
58566aee900SScott Liu 	return 0;
58666aee900SScott Liu }
58766aee900SScott Liu 
58866aee900SScott Liu /*
58966aee900SScott Liu  * Firmware update interface.
59066aee900SScott Liu  */
59166aee900SScott Liu 
59266aee900SScott Liu static int elants_i2c_fw_write_page(struct i2c_client *client,
59366aee900SScott Liu 				    const void *page)
59466aee900SScott Liu {
59566aee900SScott Liu 	const u8 ack_ok[] = { 0xaa, 0xaa };
59666aee900SScott Liu 	u8 buf[2];
59766aee900SScott Liu 	int retry;
59866aee900SScott Liu 	int error;
59966aee900SScott Liu 
60066aee900SScott Liu 	for (retry = 0; retry < MAX_FW_UPDATE_RETRIES; retry++) {
60166aee900SScott Liu 		error = elants_i2c_send(client, page, ELAN_FW_PAGESIZE);
60266aee900SScott Liu 		if (error) {
60366aee900SScott Liu 			dev_err(&client->dev,
60466aee900SScott Liu 				"IAP Write Page failed: %d\n", error);
60566aee900SScott Liu 			continue;
60666aee900SScott Liu 		}
60766aee900SScott Liu 
60866aee900SScott Liu 		error = elants_i2c_read(client, buf, 2);
60966aee900SScott Liu 		if (error) {
61066aee900SScott Liu 			dev_err(&client->dev,
61166aee900SScott Liu 				"IAP Ack read failed: %d\n", error);
61266aee900SScott Liu 			return error;
61366aee900SScott Liu 		}
61466aee900SScott Liu 
61566aee900SScott Liu 		if (!memcmp(buf, ack_ok, sizeof(ack_ok)))
61666aee900SScott Liu 			return 0;
61766aee900SScott Liu 
61866aee900SScott Liu 		error = -EIO;
61966aee900SScott Liu 		dev_err(&client->dev,
62066aee900SScott Liu 			"IAP Get Ack Error [%02x:%02x]\n",
62166aee900SScott Liu 			buf[0], buf[1]);
62266aee900SScott Liu 	}
62366aee900SScott Liu 
62466aee900SScott Liu 	return error;
62566aee900SScott Liu }
62666aee900SScott Liu 
627f0b57e19SJohnny.Chuang static int elants_i2c_validate_remark_id(struct elants_data *ts,
628f0b57e19SJohnny.Chuang 					 const struct firmware *fw)
629f0b57e19SJohnny.Chuang {
630f0b57e19SJohnny.Chuang 	struct i2c_client *client = ts->client;
631f0b57e19SJohnny.Chuang 	int error;
632f0b57e19SJohnny.Chuang 	const u8 cmd[] = { CMD_HEADER_ROM_READ, 0x80, 0x1F, 0x00, 0x00, 0x21 };
633f0b57e19SJohnny.Chuang 	u8 resp[6] = { 0 };
634f0b57e19SJohnny.Chuang 	u16 ts_remark_id = 0;
635f0b57e19SJohnny.Chuang 	u16 fw_remark_id = 0;
636f0b57e19SJohnny.Chuang 
637f0b57e19SJohnny.Chuang 	/* Compare TS Remark ID and FW Remark ID */
638f0b57e19SJohnny.Chuang 	error = elants_i2c_execute_command(client, cmd, sizeof(cmd),
639f0b57e19SJohnny.Chuang 					resp, sizeof(resp));
640f0b57e19SJohnny.Chuang 	if (error) {
641f0b57e19SJohnny.Chuang 		dev_err(&client->dev, "failed to query Remark ID: %d\n", error);
642f0b57e19SJohnny.Chuang 		return error;
643f0b57e19SJohnny.Chuang 	}
644f0b57e19SJohnny.Chuang 
645f0b57e19SJohnny.Chuang 	ts_remark_id = get_unaligned_be16(&resp[3]);
646f0b57e19SJohnny.Chuang 
647f0b57e19SJohnny.Chuang 	fw_remark_id = get_unaligned_le16(&fw->data[fw->size - 4]);
648f0b57e19SJohnny.Chuang 
649f0b57e19SJohnny.Chuang 	if (fw_remark_id != ts_remark_id) {
650f0b57e19SJohnny.Chuang 		dev_err(&client->dev,
651f0b57e19SJohnny.Chuang 			"Remark ID Mismatched: ts_remark_id=0x%04x, fw_remark_id=0x%04x.\n",
652f0b57e19SJohnny.Chuang 			ts_remark_id, fw_remark_id);
653f0b57e19SJohnny.Chuang 		return -EINVAL;
654f0b57e19SJohnny.Chuang 	}
655f0b57e19SJohnny.Chuang 
656f0b57e19SJohnny.Chuang 	return 0;
657f0b57e19SJohnny.Chuang }
658f0b57e19SJohnny.Chuang 
65966aee900SScott Liu static int elants_i2c_do_update_firmware(struct i2c_client *client,
66066aee900SScott Liu 					 const struct firmware *fw,
66166aee900SScott Liu 					 bool force)
66266aee900SScott Liu {
663f0b57e19SJohnny.Chuang 	struct elants_data *ts = i2c_get_clientdata(client);
66466aee900SScott Liu 	const u8 enter_iap[] = { 0x45, 0x49, 0x41, 0x50 };
66566aee900SScott Liu 	const u8 enter_iap2[] = { 0x54, 0x00, 0x12, 0x34 };
66666aee900SScott Liu 	const u8 iap_ack[] = { 0x55, 0xaa, 0x33, 0xcc };
6676fd38502SJames Chen 	const u8 close_idle[] = { 0x54, 0x2c, 0x01, 0x01 };
66866aee900SScott Liu 	u8 buf[HEADER_SIZE];
66966aee900SScott Liu 	u16 send_id;
67066aee900SScott Liu 	int page, n_fw_pages;
67166aee900SScott Liu 	int error;
672f0b57e19SJohnny.Chuang 	bool check_remark_id = ts->iap_version >= 0x60;
67366aee900SScott Liu 
67466aee900SScott Liu 	/* Recovery mode detection! */
67566aee900SScott Liu 	if (force) {
67666aee900SScott Liu 		dev_dbg(&client->dev, "Recovery mode procedure\n");
677f0b57e19SJohnny.Chuang 
678f0b57e19SJohnny.Chuang 		if (check_remark_id) {
679f0b57e19SJohnny.Chuang 			error = elants_i2c_validate_remark_id(ts, fw);
680f0b57e19SJohnny.Chuang 			if (error)
681f0b57e19SJohnny.Chuang 				return error;
682f0b57e19SJohnny.Chuang 		}
683f0b57e19SJohnny.Chuang 
68466aee900SScott Liu 		error = elants_i2c_send(client, enter_iap2, sizeof(enter_iap2));
685f0b57e19SJohnny.Chuang 		if (error) {
686f0b57e19SJohnny.Chuang 			dev_err(&client->dev, "failed to enter IAP mode: %d\n",
687f0b57e19SJohnny.Chuang 				error);
688f0b57e19SJohnny.Chuang 			return error;
689f0b57e19SJohnny.Chuang 		}
69066aee900SScott Liu 	} else {
69166aee900SScott Liu 		/* Start IAP Procedure */
69266aee900SScott Liu 		dev_dbg(&client->dev, "Normal IAP procedure\n");
693f0b57e19SJohnny.Chuang 
6946fd38502SJames Chen 		/* Close idle mode */
6956fd38502SJames Chen 		error = elants_i2c_send(client, close_idle, sizeof(close_idle));
6966fd38502SJames Chen 		if (error)
6976fd38502SJames Chen 			dev_err(&client->dev, "Failed close idle: %d\n", error);
6986fd38502SJames Chen 		msleep(60);
699f0b57e19SJohnny.Chuang 
70066aee900SScott Liu 		elants_i2c_sw_reset(client);
7016fd38502SJames Chen 		msleep(20);
702f0b57e19SJohnny.Chuang 
703f0b57e19SJohnny.Chuang 		if (check_remark_id) {
704f0b57e19SJohnny.Chuang 			error = elants_i2c_validate_remark_id(ts, fw);
705f0b57e19SJohnny.Chuang 			if (error)
706f0b57e19SJohnny.Chuang 				return error;
70766aee900SScott Liu 		}
70866aee900SScott Liu 
709f0b57e19SJohnny.Chuang 		error = elants_i2c_send(client, enter_iap, sizeof(enter_iap));
71066aee900SScott Liu 		if (error) {
711f0b57e19SJohnny.Chuang 			dev_err(&client->dev, "failed to enter IAP mode: %d\n",
712f0b57e19SJohnny.Chuang 				error);
71366aee900SScott Liu 			return error;
71466aee900SScott Liu 		}
715f0b57e19SJohnny.Chuang 	}
71666aee900SScott Liu 
71766aee900SScott Liu 	msleep(20);
71866aee900SScott Liu 
71966aee900SScott Liu 	/* check IAP state */
72066aee900SScott Liu 	error = elants_i2c_read(client, buf, 4);
72166aee900SScott Liu 	if (error) {
72266aee900SScott Liu 		dev_err(&client->dev,
72366aee900SScott Liu 			"failed to read IAP acknowledgement: %d\n",
72466aee900SScott Liu 			error);
72566aee900SScott Liu 		return error;
72666aee900SScott Liu 	}
72766aee900SScott Liu 
72866aee900SScott Liu 	if (memcmp(buf, iap_ack, sizeof(iap_ack))) {
72966aee900SScott Liu 		dev_err(&client->dev,
73066aee900SScott Liu 			"failed to enter IAP: %*ph (expected %*ph)\n",
73166aee900SScott Liu 			(int)sizeof(buf), buf, (int)sizeof(iap_ack), iap_ack);
73266aee900SScott Liu 		return -EIO;
73366aee900SScott Liu 	}
73466aee900SScott Liu 
73566aee900SScott Liu 	dev_info(&client->dev, "successfully entered IAP mode");
73666aee900SScott Liu 
73766aee900SScott Liu 	send_id = client->addr;
73866aee900SScott Liu 	error = elants_i2c_send(client, &send_id, 1);
73966aee900SScott Liu 	if (error) {
74066aee900SScott Liu 		dev_err(&client->dev, "sending dummy byte failed: %d\n",
74166aee900SScott Liu 			error);
74266aee900SScott Liu 		return error;
74366aee900SScott Liu 	}
74466aee900SScott Liu 
74566aee900SScott Liu 	/* Clear the last page of Master */
74666aee900SScott Liu 	error = elants_i2c_send(client, fw->data, ELAN_FW_PAGESIZE);
74766aee900SScott Liu 	if (error) {
74866aee900SScott Liu 		dev_err(&client->dev, "clearing of the last page failed: %d\n",
74966aee900SScott Liu 			error);
75066aee900SScott Liu 		return error;
75166aee900SScott Liu 	}
75266aee900SScott Liu 
75366aee900SScott Liu 	error = elants_i2c_read(client, buf, 2);
75466aee900SScott Liu 	if (error) {
75566aee900SScott Liu 		dev_err(&client->dev,
75666aee900SScott Liu 			"failed to read ACK for clearing the last page: %d\n",
75766aee900SScott Liu 			error);
75866aee900SScott Liu 		return error;
75966aee900SScott Liu 	}
76066aee900SScott Liu 
76166aee900SScott Liu 	n_fw_pages = fw->size / ELAN_FW_PAGESIZE;
76266aee900SScott Liu 	dev_dbg(&client->dev, "IAP Pages = %d\n", n_fw_pages);
76366aee900SScott Liu 
76466aee900SScott Liu 	for (page = 0; page < n_fw_pages; page++) {
76566aee900SScott Liu 		error = elants_i2c_fw_write_page(client,
76666aee900SScott Liu 					fw->data + page * ELAN_FW_PAGESIZE);
76766aee900SScott Liu 		if (error) {
76866aee900SScott Liu 			dev_err(&client->dev,
76966aee900SScott Liu 				"failed to write FW page %d: %d\n",
77066aee900SScott Liu 				page, error);
77166aee900SScott Liu 			return error;
77266aee900SScott Liu 		}
77366aee900SScott Liu 	}
77466aee900SScott Liu 
77566aee900SScott Liu 	/* Old iap needs to wait 200ms for WDT and rest is for hello packets */
77666aee900SScott Liu 	msleep(300);
77766aee900SScott Liu 
77866aee900SScott Liu 	dev_info(&client->dev, "firmware update completed\n");
77966aee900SScott Liu 	return 0;
78066aee900SScott Liu }
78166aee900SScott Liu 
78266aee900SScott Liu static int elants_i2c_fw_update(struct elants_data *ts)
78366aee900SScott Liu {
78466aee900SScott Liu 	struct i2c_client *client = ts->client;
78566aee900SScott Liu 	const struct firmware *fw;
78637dee1acSCharlie Mooney 	char *fw_name;
78766aee900SScott Liu 	int error;
78866aee900SScott Liu 
7898c0776a8SDmitry Torokhov 	fw_name = kasprintf(GFP_KERNEL, "elants_i2c_%04x.bin", ts->hw_version);
79037dee1acSCharlie Mooney 	if (!fw_name)
79137dee1acSCharlie Mooney 		return -ENOMEM;
79237dee1acSCharlie Mooney 
79337dee1acSCharlie Mooney 	dev_info(&client->dev, "requesting fw name = %s\n", fw_name);
79437dee1acSCharlie Mooney 	error = request_firmware(&fw, fw_name, &client->dev);
79537dee1acSCharlie Mooney 	kfree(fw_name);
79666aee900SScott Liu 	if (error) {
79737dee1acSCharlie Mooney 		dev_err(&client->dev, "failed to request firmware: %d\n",
79837dee1acSCharlie Mooney 			error);
79966aee900SScott Liu 		return error;
80066aee900SScott Liu 	}
80166aee900SScott Liu 
80266aee900SScott Liu 	if (fw->size % ELAN_FW_PAGESIZE) {
80366aee900SScott Liu 		dev_err(&client->dev, "invalid firmware length: %zu\n",
80466aee900SScott Liu 			fw->size);
80566aee900SScott Liu 		error = -EINVAL;
80666aee900SScott Liu 		goto out;
80766aee900SScott Liu 	}
80866aee900SScott Liu 
80966aee900SScott Liu 	disable_irq(client->irq);
81066aee900SScott Liu 
81166aee900SScott Liu 	error = elants_i2c_do_update_firmware(client, fw,
81266aee900SScott Liu 					ts->iap_mode == ELAN_IAP_RECOVERY);
81366aee900SScott Liu 	if (error) {
81466aee900SScott Liu 		dev_err(&client->dev, "firmware update failed: %d\n", error);
81566aee900SScott Liu 		ts->iap_mode = ELAN_IAP_RECOVERY;
81666aee900SScott Liu 		goto out_enable_irq;
81766aee900SScott Liu 	}
81866aee900SScott Liu 
81966aee900SScott Liu 	error = elants_i2c_initialize(ts);
82066aee900SScott Liu 	if (error) {
82166aee900SScott Liu 		dev_err(&client->dev,
82266aee900SScott Liu 			"failed to initialize device after firmware update: %d\n",
82366aee900SScott Liu 			error);
82466aee900SScott Liu 		ts->iap_mode = ELAN_IAP_RECOVERY;
82566aee900SScott Liu 		goto out_enable_irq;
82666aee900SScott Liu 	}
82766aee900SScott Liu 
82866aee900SScott Liu 	ts->iap_mode = ELAN_IAP_OPERATIONAL;
82966aee900SScott Liu 
83066aee900SScott Liu out_enable_irq:
83166aee900SScott Liu 	ts->state = ELAN_STATE_NORMAL;
83266aee900SScott Liu 	enable_irq(client->irq);
83366aee900SScott Liu 	msleep(100);
83466aee900SScott Liu 
83566aee900SScott Liu 	if (!error)
83666aee900SScott Liu 		elants_i2c_calibrate(ts);
83766aee900SScott Liu out:
83866aee900SScott Liu 	release_firmware(fw);
83966aee900SScott Liu 	return error;
84066aee900SScott Liu }
84166aee900SScott Liu 
84266aee900SScott Liu /*
84366aee900SScott Liu  * Event reporting.
84466aee900SScott Liu  */
84566aee900SScott Liu 
84666aee900SScott Liu static void elants_i2c_mt_event(struct elants_data *ts, u8 *buf)
84766aee900SScott Liu {
84866aee900SScott Liu 	struct input_dev *input = ts->input;
84966aee900SScott Liu 	unsigned int n_fingers;
850f27ad893SJohnny Chuang 	unsigned int tool_type;
85166aee900SScott Liu 	u16 finger_state;
85266aee900SScott Liu 	int i;
85366aee900SScott Liu 
85466aee900SScott Liu 	n_fingers = buf[FW_POS_STATE + 1] & 0x0f;
85566aee900SScott Liu 	finger_state = ((buf[FW_POS_STATE + 1] & 0x30) << 4) |
85666aee900SScott Liu 			buf[FW_POS_STATE];
85766aee900SScott Liu 
85866aee900SScott Liu 	dev_dbg(&ts->client->dev,
85966aee900SScott Liu 		"n_fingers: %u, state: %04x\n",  n_fingers, finger_state);
86066aee900SScott Liu 
861f27ad893SJohnny Chuang 	/* Note: all fingers have the same tool type */
862f27ad893SJohnny Chuang 	tool_type = buf[FW_POS_TOOL_TYPE] & BIT(0) ?
863f27ad893SJohnny Chuang 			MT_TOOL_FINGER : MT_TOOL_PALM;
864f27ad893SJohnny Chuang 
86566aee900SScott Liu 	for (i = 0; i < MAX_CONTACT_NUM && n_fingers; i++) {
86666aee900SScott Liu 		if (finger_state & 1) {
86766aee900SScott Liu 			unsigned int x, y, p, w;
86866aee900SScott Liu 			u8 *pos;
86966aee900SScott Liu 
87066aee900SScott Liu 			pos = &buf[FW_POS_XY + i * 3];
87166aee900SScott Liu 			x = (((u16)pos[0] & 0xf0) << 4) | pos[1];
87266aee900SScott Liu 			y = (((u16)pos[0] & 0x0f) << 8) | pos[2];
87366aee900SScott Liu 			p = buf[FW_POS_PRESSURE + i];
87466aee900SScott Liu 			w = buf[FW_POS_WIDTH + i];
87566aee900SScott Liu 
87666aee900SScott Liu 			dev_dbg(&ts->client->dev, "i=%d x=%d y=%d p=%d w=%d\n",
87766aee900SScott Liu 				i, x, y, p, w);
87866aee900SScott Liu 
87966aee900SScott Liu 			input_mt_slot(input, i);
880f27ad893SJohnny Chuang 			input_mt_report_slot_state(input, tool_type, true);
88168334dbaSMichał Mirosław 			touchscreen_report_pos(input, &ts->prop, x, y, true);
88266aee900SScott Liu 			input_event(input, EV_ABS, ABS_MT_PRESSURE, p);
88366aee900SScott Liu 			input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, w);
88466aee900SScott Liu 
88566aee900SScott Liu 			n_fingers--;
88666aee900SScott Liu 		}
88766aee900SScott Liu 
88866aee900SScott Liu 		finger_state >>= 1;
88966aee900SScott Liu 	}
89066aee900SScott Liu 
89166aee900SScott Liu 	input_mt_sync_frame(input);
89266aee900SScott Liu 	input_sync(input);
89366aee900SScott Liu }
89466aee900SScott Liu 
89566aee900SScott Liu static u8 elants_i2c_calculate_checksum(u8 *buf)
89666aee900SScott Liu {
89766aee900SScott Liu 	u8 checksum = 0;
89866aee900SScott Liu 	u8 i;
89966aee900SScott Liu 
90066aee900SScott Liu 	for (i = 0; i < FW_POS_CHECKSUM; i++)
90166aee900SScott Liu 		checksum += buf[i];
90266aee900SScott Liu 
90366aee900SScott Liu 	return checksum;
90466aee900SScott Liu }
90566aee900SScott Liu 
90666aee900SScott Liu static void elants_i2c_event(struct elants_data *ts, u8 *buf)
90766aee900SScott Liu {
90866aee900SScott Liu 	u8 checksum = elants_i2c_calculate_checksum(buf);
90966aee900SScott Liu 
91066aee900SScott Liu 	if (unlikely(buf[FW_POS_CHECKSUM] != checksum))
91166aee900SScott Liu 		dev_warn(&ts->client->dev,
91266aee900SScott Liu 			 "%s: invalid checksum for packet %02x: %02x vs. %02x\n",
91366aee900SScott Liu 			 __func__, buf[FW_POS_HEADER],
91466aee900SScott Liu 			 checksum, buf[FW_POS_CHECKSUM]);
91566aee900SScott Liu 	else if (unlikely(buf[FW_POS_HEADER] != HEADER_REPORT_10_FINGER))
91666aee900SScott Liu 		dev_warn(&ts->client->dev,
91766aee900SScott Liu 			 "%s: unknown packet type: %02x\n",
91866aee900SScott Liu 			 __func__, buf[FW_POS_HEADER]);
91966aee900SScott Liu 	else
92066aee900SScott Liu 		elants_i2c_mt_event(ts, buf);
92166aee900SScott Liu }
92266aee900SScott Liu 
92366aee900SScott Liu static irqreturn_t elants_i2c_irq(int irq, void *_dev)
92466aee900SScott Liu {
92566aee900SScott Liu 	const u8 wait_packet[] = { 0x64, 0x64, 0x64, 0x64 };
92666aee900SScott Liu 	struct elants_data *ts = _dev;
92766aee900SScott Liu 	struct i2c_client *client = ts->client;
92866aee900SScott Liu 	int report_count, report_len;
92966aee900SScott Liu 	int i;
93066aee900SScott Liu 	int len;
93166aee900SScott Liu 
93200f73f97SStephen Boyd 	len = i2c_master_recv_dmasafe(client, ts->buf, sizeof(ts->buf));
93366aee900SScott Liu 	if (len < 0) {
93466aee900SScott Liu 		dev_err(&client->dev, "%s: failed to read data: %d\n",
93566aee900SScott Liu 			__func__, len);
93666aee900SScott Liu 		goto out;
93766aee900SScott Liu 	}
93866aee900SScott Liu 
93966aee900SScott Liu 	dev_dbg(&client->dev, "%s: packet %*ph\n",
94066aee900SScott Liu 		__func__, HEADER_SIZE, ts->buf);
94166aee900SScott Liu 
94266aee900SScott Liu 	switch (ts->state) {
94366aee900SScott Liu 	case ELAN_WAIT_RECALIBRATION:
94466aee900SScott Liu 		if (ts->buf[FW_HDR_TYPE] == CMD_HEADER_REK) {
94566aee900SScott Liu 			memcpy(ts->cmd_resp, ts->buf, sizeof(ts->cmd_resp));
94666aee900SScott Liu 			complete(&ts->cmd_done);
94766aee900SScott Liu 			ts->state = ELAN_STATE_NORMAL;
94866aee900SScott Liu 		}
94966aee900SScott Liu 		break;
95066aee900SScott Liu 
95166aee900SScott Liu 	case ELAN_WAIT_QUEUE_HEADER:
95266aee900SScott Liu 		if (ts->buf[FW_HDR_TYPE] != QUEUE_HEADER_NORMAL)
95366aee900SScott Liu 			break;
95466aee900SScott Liu 
95566aee900SScott Liu 		ts->state = ELAN_STATE_NORMAL;
95666aee900SScott Liu 		/* fall through */
95766aee900SScott Liu 
95866aee900SScott Liu 	case ELAN_STATE_NORMAL:
95966aee900SScott Liu 
96066aee900SScott Liu 		switch (ts->buf[FW_HDR_TYPE]) {
96166aee900SScott Liu 		case CMD_HEADER_HELLO:
96266aee900SScott Liu 		case CMD_HEADER_RESP:
96366aee900SScott Liu 		case CMD_HEADER_REK:
96466aee900SScott Liu 			break;
96566aee900SScott Liu 
96666aee900SScott Liu 		case QUEUE_HEADER_WAIT:
96766aee900SScott Liu 			if (memcmp(ts->buf, wait_packet, sizeof(wait_packet))) {
96866aee900SScott Liu 				dev_err(&client->dev,
96966aee900SScott Liu 					"invalid wait packet %*ph\n",
97066aee900SScott Liu 					HEADER_SIZE, ts->buf);
97166aee900SScott Liu 			} else {
97266aee900SScott Liu 				ts->state = ELAN_WAIT_QUEUE_HEADER;
97366aee900SScott Liu 				udelay(30);
97466aee900SScott Liu 			}
97566aee900SScott Liu 			break;
97666aee900SScott Liu 
97766aee900SScott Liu 		case QUEUE_HEADER_SINGLE:
97866aee900SScott Liu 			elants_i2c_event(ts, &ts->buf[HEADER_SIZE]);
97966aee900SScott Liu 			break;
98066aee900SScott Liu 
98166aee900SScott Liu 		case QUEUE_HEADER_NORMAL:
98266aee900SScott Liu 			report_count = ts->buf[FW_HDR_COUNT];
9831c3415a0SGuenter Roeck 			if (report_count == 0 || report_count > 3) {
98466aee900SScott Liu 				dev_err(&client->dev,
9851c3415a0SGuenter Roeck 					"bad report count: %*ph\n",
98666aee900SScott Liu 					HEADER_SIZE, ts->buf);
98766aee900SScott Liu 				break;
98866aee900SScott Liu 			}
98966aee900SScott Liu 
99066aee900SScott Liu 			report_len = ts->buf[FW_HDR_LENGTH] / report_count;
99166aee900SScott Liu 			if (report_len != PACKET_SIZE) {
99266aee900SScott Liu 				dev_err(&client->dev,
99366aee900SScott Liu 					"mismatching report length: %*ph\n",
99466aee900SScott Liu 					HEADER_SIZE, ts->buf);
99566aee900SScott Liu 				break;
99666aee900SScott Liu 			}
99766aee900SScott Liu 
99866aee900SScott Liu 			for (i = 0; i < report_count; i++) {
99966aee900SScott Liu 				u8 *buf = ts->buf + HEADER_SIZE +
100066aee900SScott Liu 							i * PACKET_SIZE;
100166aee900SScott Liu 				elants_i2c_event(ts, buf);
100266aee900SScott Liu 			}
100366aee900SScott Liu 			break;
100466aee900SScott Liu 
100566aee900SScott Liu 		default:
100666aee900SScott Liu 			dev_err(&client->dev, "unknown packet %*ph\n",
100766aee900SScott Liu 				HEADER_SIZE, ts->buf);
100866aee900SScott Liu 			break;
100966aee900SScott Liu 		}
101066aee900SScott Liu 		break;
101166aee900SScott Liu 	}
101266aee900SScott Liu 
101366aee900SScott Liu out:
101466aee900SScott Liu 	return IRQ_HANDLED;
101566aee900SScott Liu }
101666aee900SScott Liu 
101766aee900SScott Liu /*
101866aee900SScott Liu  * sysfs interface
101966aee900SScott Liu  */
102066aee900SScott Liu static ssize_t calibrate_store(struct device *dev,
102166aee900SScott Liu 			       struct device_attribute *attr,
102266aee900SScott Liu 			       const char *buf, size_t count)
102366aee900SScott Liu {
102466aee900SScott Liu 	struct i2c_client *client = to_i2c_client(dev);
102566aee900SScott Liu 	struct elants_data *ts = i2c_get_clientdata(client);
102666aee900SScott Liu 	int error;
102766aee900SScott Liu 
102866aee900SScott Liu 	error = mutex_lock_interruptible(&ts->sysfs_mutex);
102966aee900SScott Liu 	if (error)
103066aee900SScott Liu 		return error;
103166aee900SScott Liu 
103266aee900SScott Liu 	error = elants_i2c_calibrate(ts);
103366aee900SScott Liu 
103466aee900SScott Liu 	mutex_unlock(&ts->sysfs_mutex);
103566aee900SScott Liu 	return error ?: count;
103666aee900SScott Liu }
103766aee900SScott Liu 
103866aee900SScott Liu static ssize_t write_update_fw(struct device *dev,
103966aee900SScott Liu 			       struct device_attribute *attr,
104066aee900SScott Liu 			       const char *buf, size_t count)
104166aee900SScott Liu {
104266aee900SScott Liu 	struct i2c_client *client = to_i2c_client(dev);
104366aee900SScott Liu 	struct elants_data *ts = i2c_get_clientdata(client);
104466aee900SScott Liu 	int error;
104566aee900SScott Liu 
104666aee900SScott Liu 	error = mutex_lock_interruptible(&ts->sysfs_mutex);
104766aee900SScott Liu 	if (error)
104866aee900SScott Liu 		return error;
104966aee900SScott Liu 
105066aee900SScott Liu 	error = elants_i2c_fw_update(ts);
105166aee900SScott Liu 	dev_dbg(dev, "firmware update result: %d\n", error);
105266aee900SScott Liu 
105366aee900SScott Liu 	mutex_unlock(&ts->sysfs_mutex);
105466aee900SScott Liu 	return error ?: count;
105566aee900SScott Liu }
105666aee900SScott Liu 
105766aee900SScott Liu static ssize_t show_iap_mode(struct device *dev,
105866aee900SScott Liu 			     struct device_attribute *attr, char *buf)
105966aee900SScott Liu {
106066aee900SScott Liu 	struct i2c_client *client = to_i2c_client(dev);
106166aee900SScott Liu 	struct elants_data *ts = i2c_get_clientdata(client);
106266aee900SScott Liu 
106366aee900SScott Liu 	return sprintf(buf, "%s\n",
106466aee900SScott Liu 		       ts->iap_mode == ELAN_IAP_OPERATIONAL ?
106566aee900SScott Liu 				"Normal" : "Recovery");
106666aee900SScott Liu }
106766aee900SScott Liu 
1068cf520c64SJohnny Chuang static ssize_t show_calibration_count(struct device *dev,
1069cf520c64SJohnny Chuang 				      struct device_attribute *attr, char *buf)
1070cf520c64SJohnny Chuang {
1071cf520c64SJohnny Chuang 	struct i2c_client *client = to_i2c_client(dev);
1072cf520c64SJohnny Chuang 	const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_REK, 0x00, 0x01 };
1073cf520c64SJohnny Chuang 	u8 resp[HEADER_SIZE];
1074cf520c64SJohnny Chuang 	u16 rek_count;
1075cf520c64SJohnny Chuang 	int error;
1076cf520c64SJohnny Chuang 
1077cf520c64SJohnny Chuang 	error = elants_i2c_execute_command(client, cmd, sizeof(cmd),
1078cf520c64SJohnny Chuang 						resp, sizeof(resp));
1079cf520c64SJohnny Chuang 	if (error) {
1080cf520c64SJohnny Chuang 		dev_err(&client->dev,
1081cf520c64SJohnny Chuang 			"read ReK status error=%d, buf=%*phC\n",
1082cf520c64SJohnny Chuang 			error, (int)sizeof(resp), resp);
1083cf520c64SJohnny Chuang 		return sprintf(buf, "%d\n", error);
1084cf520c64SJohnny Chuang 	}
1085cf520c64SJohnny Chuang 
1086cf520c64SJohnny Chuang 	rek_count = get_unaligned_be16(&resp[2]);
1087cf520c64SJohnny Chuang 
1088cf520c64SJohnny Chuang 	return sprintf(buf, "0x%04x\n", rek_count);
1089cf520c64SJohnny Chuang }
1090cf520c64SJohnny Chuang 
10916cbaefb4SJoe Perches static DEVICE_ATTR_WO(calibrate);
109266aee900SScott Liu static DEVICE_ATTR(iap_mode, S_IRUGO, show_iap_mode, NULL);
1093cf520c64SJohnny Chuang static DEVICE_ATTR(calibration_count, S_IRUGO, show_calibration_count, NULL);
109466aee900SScott Liu static DEVICE_ATTR(update_fw, S_IWUSR, NULL, write_update_fw);
109566aee900SScott Liu 
109666aee900SScott Liu struct elants_version_attribute {
109766aee900SScott Liu 	struct device_attribute dattr;
109866aee900SScott Liu 	size_t field_offset;
109966aee900SScott Liu 	size_t field_size;
110066aee900SScott Liu };
110166aee900SScott Liu 
110266aee900SScott Liu #define __ELANTS_FIELD_SIZE(_field)					\
110366aee900SScott Liu 	sizeof(((struct elants_data *)NULL)->_field)
110466aee900SScott Liu #define __ELANTS_VERIFY_SIZE(_field)					\
110566aee900SScott Liu 	(BUILD_BUG_ON_ZERO(__ELANTS_FIELD_SIZE(_field) > 2) +		\
110666aee900SScott Liu 	 __ELANTS_FIELD_SIZE(_field))
110766aee900SScott Liu #define ELANTS_VERSION_ATTR(_field)					\
110866aee900SScott Liu 	struct elants_version_attribute elants_ver_attr_##_field = {	\
110966aee900SScott Liu 		.dattr = __ATTR(_field, S_IRUGO,			\
111066aee900SScott Liu 				elants_version_attribute_show, NULL),	\
111166aee900SScott Liu 		.field_offset = offsetof(struct elants_data, _field),	\
111266aee900SScott Liu 		.field_size = __ELANTS_VERIFY_SIZE(_field),		\
111366aee900SScott Liu 	}
111466aee900SScott Liu 
111566aee900SScott Liu static ssize_t elants_version_attribute_show(struct device *dev,
111666aee900SScott Liu 					     struct device_attribute *dattr,
111766aee900SScott Liu 					     char *buf)
111866aee900SScott Liu {
111966aee900SScott Liu 	struct i2c_client *client = to_i2c_client(dev);
112066aee900SScott Liu 	struct elants_data *ts = i2c_get_clientdata(client);
112166aee900SScott Liu 	struct elants_version_attribute *attr =
112266aee900SScott Liu 		container_of(dattr, struct elants_version_attribute, dattr);
112366aee900SScott Liu 	u8 *field = (u8 *)((char *)ts + attr->field_offset);
112466aee900SScott Liu 	unsigned int fmt_size;
112566aee900SScott Liu 	unsigned int val;
112666aee900SScott Liu 
112766aee900SScott Liu 	if (attr->field_size == 1) {
112866aee900SScott Liu 		val = *field;
112966aee900SScott Liu 		fmt_size = 2; /* 2 HEX digits */
113066aee900SScott Liu 	} else {
113166aee900SScott Liu 		val = *(u16 *)field;
113266aee900SScott Liu 		fmt_size = 4; /* 4 HEX digits */
113366aee900SScott Liu 	}
113466aee900SScott Liu 
113566aee900SScott Liu 	return sprintf(buf, "%0*x\n", fmt_size, val);
113666aee900SScott Liu }
113766aee900SScott Liu 
113866aee900SScott Liu static ELANTS_VERSION_ATTR(fw_version);
113966aee900SScott Liu static ELANTS_VERSION_ATTR(hw_version);
114066aee900SScott Liu static ELANTS_VERSION_ATTR(test_version);
114166aee900SScott Liu static ELANTS_VERSION_ATTR(solution_version);
114266aee900SScott Liu static ELANTS_VERSION_ATTR(bc_version);
114366aee900SScott Liu static ELANTS_VERSION_ATTR(iap_version);
114466aee900SScott Liu 
114566aee900SScott Liu static struct attribute *elants_attributes[] = {
114666aee900SScott Liu 	&dev_attr_calibrate.attr,
114766aee900SScott Liu 	&dev_attr_update_fw.attr,
114866aee900SScott Liu 	&dev_attr_iap_mode.attr,
1149cf520c64SJohnny Chuang 	&dev_attr_calibration_count.attr,
115066aee900SScott Liu 
115166aee900SScott Liu 	&elants_ver_attr_fw_version.dattr.attr,
115266aee900SScott Liu 	&elants_ver_attr_hw_version.dattr.attr,
115366aee900SScott Liu 	&elants_ver_attr_test_version.dattr.attr,
115466aee900SScott Liu 	&elants_ver_attr_solution_version.dattr.attr,
115566aee900SScott Liu 	&elants_ver_attr_bc_version.dattr.attr,
115666aee900SScott Liu 	&elants_ver_attr_iap_version.dattr.attr,
115766aee900SScott Liu 	NULL
115866aee900SScott Liu };
115966aee900SScott Liu 
116048f960ddSArvind Yadav static const struct attribute_group elants_attribute_group = {
116166aee900SScott Liu 	.attrs = elants_attributes,
116266aee900SScott Liu };
116366aee900SScott Liu 
1164afe10358SDmitry Torokhov static int elants_i2c_power_on(struct elants_data *ts)
1165afe10358SDmitry Torokhov {
1166afe10358SDmitry Torokhov 	int error;
1167afe10358SDmitry Torokhov 
1168afe10358SDmitry Torokhov 	/*
1169afe10358SDmitry Torokhov 	 * If we do not have reset gpio assume platform firmware
1170afe10358SDmitry Torokhov 	 * controls regulators and does power them on for us.
1171afe10358SDmitry Torokhov 	 */
1172afe10358SDmitry Torokhov 	if (IS_ERR_OR_NULL(ts->reset_gpio))
1173afe10358SDmitry Torokhov 		return 0;
1174afe10358SDmitry Torokhov 
1175afe10358SDmitry Torokhov 	gpiod_set_value_cansleep(ts->reset_gpio, 1);
1176afe10358SDmitry Torokhov 
1177afe10358SDmitry Torokhov 	error = regulator_enable(ts->vcc33);
1178afe10358SDmitry Torokhov 	if (error) {
1179afe10358SDmitry Torokhov 		dev_err(&ts->client->dev,
1180afe10358SDmitry Torokhov 			"failed to enable vcc33 regulator: %d\n",
1181afe10358SDmitry Torokhov 			error);
1182afe10358SDmitry Torokhov 		goto release_reset_gpio;
1183afe10358SDmitry Torokhov 	}
1184afe10358SDmitry Torokhov 
1185afe10358SDmitry Torokhov 	error = regulator_enable(ts->vccio);
1186afe10358SDmitry Torokhov 	if (error) {
1187afe10358SDmitry Torokhov 		dev_err(&ts->client->dev,
1188afe10358SDmitry Torokhov 			"failed to enable vccio regulator: %d\n",
1189afe10358SDmitry Torokhov 			error);
1190afe10358SDmitry Torokhov 		regulator_disable(ts->vcc33);
1191afe10358SDmitry Torokhov 		goto release_reset_gpio;
1192afe10358SDmitry Torokhov 	}
1193afe10358SDmitry Torokhov 
1194afe10358SDmitry Torokhov 	/*
1195afe10358SDmitry Torokhov 	 * We need to wait a bit after powering on controller before
1196afe10358SDmitry Torokhov 	 * we are allowed to release reset GPIO.
1197afe10358SDmitry Torokhov 	 */
1198afe10358SDmitry Torokhov 	udelay(ELAN_POWERON_DELAY_USEC);
1199afe10358SDmitry Torokhov 
1200afe10358SDmitry Torokhov release_reset_gpio:
1201afe10358SDmitry Torokhov 	gpiod_set_value_cansleep(ts->reset_gpio, 0);
1202afe10358SDmitry Torokhov 	if (error)
1203afe10358SDmitry Torokhov 		return error;
1204afe10358SDmitry Torokhov 
1205afe10358SDmitry Torokhov 	msleep(ELAN_RESET_DELAY_MSEC);
1206afe10358SDmitry Torokhov 
1207afe10358SDmitry Torokhov 	return 0;
1208afe10358SDmitry Torokhov }
1209afe10358SDmitry Torokhov 
1210afe10358SDmitry Torokhov static void elants_i2c_power_off(void *_data)
1211afe10358SDmitry Torokhov {
1212afe10358SDmitry Torokhov 	struct elants_data *ts = _data;
1213afe10358SDmitry Torokhov 
1214afe10358SDmitry Torokhov 	if (!IS_ERR_OR_NULL(ts->reset_gpio)) {
1215afe10358SDmitry Torokhov 		/*
1216afe10358SDmitry Torokhov 		 * Activate reset gpio to prevent leakage through the
1217afe10358SDmitry Torokhov 		 * pin once we shut off power to the controller.
1218afe10358SDmitry Torokhov 		 */
1219afe10358SDmitry Torokhov 		gpiod_set_value_cansleep(ts->reset_gpio, 1);
1220afe10358SDmitry Torokhov 		regulator_disable(ts->vccio);
1221afe10358SDmitry Torokhov 		regulator_disable(ts->vcc33);
1222afe10358SDmitry Torokhov 	}
1223afe10358SDmitry Torokhov }
1224afe10358SDmitry Torokhov 
122566aee900SScott Liu static int elants_i2c_probe(struct i2c_client *client,
122666aee900SScott Liu 			    const struct i2c_device_id *id)
122766aee900SScott Liu {
122866aee900SScott Liu 	union i2c_smbus_data dummy;
122966aee900SScott Liu 	struct elants_data *ts;
123066aee900SScott Liu 	unsigned long irqflags;
123166aee900SScott Liu 	int error;
123266aee900SScott Liu 
123366aee900SScott Liu 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
123466aee900SScott Liu 		dev_err(&client->dev,
123566aee900SScott Liu 			"%s: i2c check functionality error\n", DEVICE_NAME);
123666aee900SScott Liu 		return -ENXIO;
123766aee900SScott Liu 	}
123866aee900SScott Liu 
123966aee900SScott Liu 	ts = devm_kzalloc(&client->dev, sizeof(struct elants_data), GFP_KERNEL);
124066aee900SScott Liu 	if (!ts)
124166aee900SScott Liu 		return -ENOMEM;
124266aee900SScott Liu 
124366aee900SScott Liu 	mutex_init(&ts->sysfs_mutex);
124466aee900SScott Liu 	init_completion(&ts->cmd_done);
124566aee900SScott Liu 
124666aee900SScott Liu 	ts->client = client;
124766aee900SScott Liu 	i2c_set_clientdata(client, ts);
124866aee900SScott Liu 
1249afe10358SDmitry Torokhov 	ts->vcc33 = devm_regulator_get(&client->dev, "vcc33");
1250afe10358SDmitry Torokhov 	if (IS_ERR(ts->vcc33)) {
1251afe10358SDmitry Torokhov 		error = PTR_ERR(ts->vcc33);
1252afe10358SDmitry Torokhov 		if (error != -EPROBE_DEFER)
1253afe10358SDmitry Torokhov 			dev_err(&client->dev,
1254afe10358SDmitry Torokhov 				"Failed to get 'vcc33' regulator: %d\n",
1255afe10358SDmitry Torokhov 				error);
1256afe10358SDmitry Torokhov 		return error;
1257afe10358SDmitry Torokhov 	}
1258afe10358SDmitry Torokhov 
1259afe10358SDmitry Torokhov 	ts->vccio = devm_regulator_get(&client->dev, "vccio");
1260afe10358SDmitry Torokhov 	if (IS_ERR(ts->vccio)) {
1261afe10358SDmitry Torokhov 		error = PTR_ERR(ts->vccio);
1262afe10358SDmitry Torokhov 		if (error != -EPROBE_DEFER)
1263afe10358SDmitry Torokhov 			dev_err(&client->dev,
1264afe10358SDmitry Torokhov 				"Failed to get 'vccio' regulator: %d\n",
1265afe10358SDmitry Torokhov 				error);
1266afe10358SDmitry Torokhov 		return error;
1267afe10358SDmitry Torokhov 	}
1268afe10358SDmitry Torokhov 
12697229b87bSStephen Rothwell 	ts->reset_gpio = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_LOW);
1270afe10358SDmitry Torokhov 	if (IS_ERR(ts->reset_gpio)) {
1271afe10358SDmitry Torokhov 		error = PTR_ERR(ts->reset_gpio);
1272afe10358SDmitry Torokhov 
1273afe10358SDmitry Torokhov 		if (error == -EPROBE_DEFER)
1274afe10358SDmitry Torokhov 			return error;
1275afe10358SDmitry Torokhov 
1276afe10358SDmitry Torokhov 		if (error != -ENOENT && error != -ENOSYS) {
1277afe10358SDmitry Torokhov 			dev_err(&client->dev,
1278afe10358SDmitry Torokhov 				"failed to get reset gpio: %d\n",
1279afe10358SDmitry Torokhov 				error);
1280afe10358SDmitry Torokhov 			return error;
1281afe10358SDmitry Torokhov 		}
1282afe10358SDmitry Torokhov 
1283afe10358SDmitry Torokhov 		ts->keep_power_in_suspend = true;
1284afe10358SDmitry Torokhov 	}
1285afe10358SDmitry Torokhov 
1286afe10358SDmitry Torokhov 	error = elants_i2c_power_on(ts);
1287afe10358SDmitry Torokhov 	if (error)
1288afe10358SDmitry Torokhov 		return error;
1289afe10358SDmitry Torokhov 
1290afe10358SDmitry Torokhov 	error = devm_add_action(&client->dev, elants_i2c_power_off, ts);
1291afe10358SDmitry Torokhov 	if (error) {
1292afe10358SDmitry Torokhov 		dev_err(&client->dev,
1293afe10358SDmitry Torokhov 			"failed to install power off action: %d\n", error);
1294afe10358SDmitry Torokhov 		elants_i2c_power_off(ts);
1295afe10358SDmitry Torokhov 		return error;
1296afe10358SDmitry Torokhov 	}
1297afe10358SDmitry Torokhov 
1298afe10358SDmitry Torokhov 	/* Make sure there is something at this address */
1299afe10358SDmitry Torokhov 	if (i2c_smbus_xfer(client->adapter, client->addr, 0,
1300afe10358SDmitry Torokhov 			   I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &dummy) < 0) {
1301afe10358SDmitry Torokhov 		dev_err(&client->dev, "nothing at this address\n");
1302afe10358SDmitry Torokhov 		return -ENXIO;
1303afe10358SDmitry Torokhov 	}
1304afe10358SDmitry Torokhov 
130566aee900SScott Liu 	error = elants_i2c_initialize(ts);
130666aee900SScott Liu 	if (error) {
130766aee900SScott Liu 		dev_err(&client->dev, "failed to initialize: %d\n", error);
130866aee900SScott Liu 		return error;
130966aee900SScott Liu 	}
131066aee900SScott Liu 
131166aee900SScott Liu 	ts->input = devm_input_allocate_device(&client->dev);
131266aee900SScott Liu 	if (!ts->input) {
131366aee900SScott Liu 		dev_err(&client->dev, "Failed to allocate input device\n");
131466aee900SScott Liu 		return -ENOMEM;
131566aee900SScott Liu 	}
131666aee900SScott Liu 
131766aee900SScott Liu 	ts->input->name = "Elan Touchscreen";
131866aee900SScott Liu 	ts->input->id.bustype = BUS_I2C;
131966aee900SScott Liu 
132066aee900SScott Liu 	/* Multitouch input params setup */
132166aee900SScott Liu 
132266aee900SScott Liu 	input_set_abs_params(ts->input, ABS_MT_POSITION_X, 0, ts->x_max, 0, 0);
132366aee900SScott Liu 	input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, ts->y_max, 0, 0);
132466aee900SScott Liu 	input_set_abs_params(ts->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
132566aee900SScott Liu 	input_set_abs_params(ts->input, ABS_MT_PRESSURE, 0, 255, 0, 0);
1326f27ad893SJohnny Chuang 	input_set_abs_params(ts->input, ABS_MT_TOOL_TYPE,
1327f27ad893SJohnny Chuang 			     0, MT_TOOL_PALM, 0, 0);
132866aee900SScott Liu 	input_abs_set_res(ts->input, ABS_MT_POSITION_X, ts->x_res);
132966aee900SScott Liu 	input_abs_set_res(ts->input, ABS_MT_POSITION_Y, ts->y_res);
133006170671SJohnny Chuang 	input_abs_set_res(ts->input, ABS_MT_TOUCH_MAJOR, 1);
133166aee900SScott Liu 
133268334dbaSMichał Mirosław 	touchscreen_parse_properties(ts->input, true, &ts->prop);
133368334dbaSMichał Mirosław 
13346def17b1SMichał Mirosław 	error = input_mt_init_slots(ts->input, MAX_CONTACT_NUM,
13356def17b1SMichał Mirosław 				    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
13366def17b1SMichał Mirosław 	if (error) {
13376def17b1SMichał Mirosław 		dev_err(&client->dev,
13386def17b1SMichał Mirosław 			"failed to initialize MT slots: %d\n", error);
13396def17b1SMichał Mirosław 		return error;
13406def17b1SMichał Mirosław 	}
13416def17b1SMichał Mirosław 
134266aee900SScott Liu 	error = input_register_device(ts->input);
134366aee900SScott Liu 	if (error) {
134466aee900SScott Liu 		dev_err(&client->dev,
134566aee900SScott Liu 			"unable to register input device: %d\n", error);
134666aee900SScott Liu 		return error;
134766aee900SScott Liu 	}
134866aee900SScott Liu 
134966aee900SScott Liu 	/*
13504c83c071SDmitry Torokhov 	 * Platform code (ACPI, DTS) should normally set up interrupt
13514c83c071SDmitry Torokhov 	 * for us, but in case it did not let's fall back to using falling
13524c83c071SDmitry Torokhov 	 * edge to be compatible with older Chromebooks.
135366aee900SScott Liu 	 */
13544c83c071SDmitry Torokhov 	irqflags = irq_get_trigger_type(client->irq);
13554c83c071SDmitry Torokhov 	if (!irqflags)
13564c83c071SDmitry Torokhov 		irqflags = IRQF_TRIGGER_FALLING;
135766aee900SScott Liu 
135866aee900SScott Liu 	error = devm_request_threaded_irq(&client->dev, client->irq,
135966aee900SScott Liu 					  NULL, elants_i2c_irq,
136066aee900SScott Liu 					  irqflags | IRQF_ONESHOT,
136166aee900SScott Liu 					  client->name, ts);
136266aee900SScott Liu 	if (error) {
136366aee900SScott Liu 		dev_err(&client->dev, "Failed to register interrupt\n");
136466aee900SScott Liu 		return error;
136566aee900SScott Liu 	}
136666aee900SScott Liu 
136766aee900SScott Liu 	/*
136866aee900SScott Liu 	 * Systems using device tree should set up wakeup via DTS,
136966aee900SScott Liu 	 * the rest will configure device as wakeup source by default.
137066aee900SScott Liu 	 */
137166aee900SScott Liu 	if (!client->dev.of_node)
137266aee900SScott Liu 		device_init_wakeup(&client->dev, true);
137366aee900SScott Liu 
13748db69a9aSAndi Shyti 	error = devm_device_add_group(&client->dev, &elants_attribute_group);
137566aee900SScott Liu 	if (error) {
137666aee900SScott Liu 		dev_err(&client->dev, "failed to create sysfs attributes: %d\n",
137766aee900SScott Liu 			error);
137866aee900SScott Liu 		return error;
137966aee900SScott Liu 	}
138066aee900SScott Liu 
138166aee900SScott Liu 	return 0;
138266aee900SScott Liu }
138366aee900SScott Liu 
138466aee900SScott Liu static int __maybe_unused elants_i2c_suspend(struct device *dev)
138566aee900SScott Liu {
138666aee900SScott Liu 	struct i2c_client *client = to_i2c_client(dev);
138766aee900SScott Liu 	struct elants_data *ts = i2c_get_clientdata(client);
138866aee900SScott Liu 	const u8 set_sleep_cmd[] = { 0x54, 0x50, 0x00, 0x01 };
138966aee900SScott Liu 	int retry_cnt;
139066aee900SScott Liu 	int error;
139166aee900SScott Liu 
139266aee900SScott Liu 	/* Command not support in IAP recovery mode */
139366aee900SScott Liu 	if (ts->iap_mode != ELAN_IAP_OPERATIONAL)
139466aee900SScott Liu 		return -EBUSY;
139566aee900SScott Liu 
139666aee900SScott Liu 	disable_irq(client->irq);
139766aee900SScott Liu 
1398478e5ed1SJames Chen 	if (device_may_wakeup(dev)) {
1399478e5ed1SJames Chen 		/*
1400478e5ed1SJames Chen 		 * The device will automatically enter idle mode
1401478e5ed1SJames Chen 		 * that has reduced power consumption.
1402478e5ed1SJames Chen 		 */
1403478e5ed1SJames Chen 		ts->wake_irq_enabled = (enable_irq_wake(client->irq) == 0);
1404478e5ed1SJames Chen 	} else if (ts->keep_power_in_suspend) {
140566aee900SScott Liu 		for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) {
140666aee900SScott Liu 			error = elants_i2c_send(client, set_sleep_cmd,
140766aee900SScott Liu 						sizeof(set_sleep_cmd));
140866aee900SScott Liu 			if (!error)
140966aee900SScott Liu 				break;
141066aee900SScott Liu 
1411afe10358SDmitry Torokhov 			dev_err(&client->dev,
1412afe10358SDmitry Torokhov 				"suspend command failed: %d\n", error);
141366aee900SScott Liu 		}
1414afe10358SDmitry Torokhov 	} else {
1415afe10358SDmitry Torokhov 		elants_i2c_power_off(ts);
1416afe10358SDmitry Torokhov 	}
141766aee900SScott Liu 
141866aee900SScott Liu 	return 0;
141966aee900SScott Liu }
142066aee900SScott Liu 
142166aee900SScott Liu static int __maybe_unused elants_i2c_resume(struct device *dev)
142266aee900SScott Liu {
142366aee900SScott Liu 	struct i2c_client *client = to_i2c_client(dev);
142466aee900SScott Liu 	struct elants_data *ts = i2c_get_clientdata(client);
142566aee900SScott Liu 	const u8 set_active_cmd[] = { 0x54, 0x58, 0x00, 0x01 };
142666aee900SScott Liu 	int retry_cnt;
142766aee900SScott Liu 	int error;
142866aee900SScott Liu 
1429478e5ed1SJames Chen 	if (device_may_wakeup(dev)) {
1430478e5ed1SJames Chen 		if (ts->wake_irq_enabled)
143166aee900SScott Liu 			disable_irq_wake(client->irq);
1432478e5ed1SJames Chen 		elants_i2c_sw_reset(client);
1433478e5ed1SJames Chen 	} else if (ts->keep_power_in_suspend) {
143466aee900SScott Liu 		for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) {
143566aee900SScott Liu 			error = elants_i2c_send(client, set_active_cmd,
143666aee900SScott Liu 						sizeof(set_active_cmd));
143766aee900SScott Liu 			if (!error)
143866aee900SScott Liu 				break;
143966aee900SScott Liu 
1440afe10358SDmitry Torokhov 			dev_err(&client->dev,
1441afe10358SDmitry Torokhov 				"resume command failed: %d\n", error);
1442afe10358SDmitry Torokhov 		}
1443afe10358SDmitry Torokhov 	} else {
1444afe10358SDmitry Torokhov 		elants_i2c_power_on(ts);
1445afe10358SDmitry Torokhov 		elants_i2c_initialize(ts);
144666aee900SScott Liu 	}
144766aee900SScott Liu 
144866aee900SScott Liu 	ts->state = ELAN_STATE_NORMAL;
144966aee900SScott Liu 	enable_irq(client->irq);
145066aee900SScott Liu 
145166aee900SScott Liu 	return 0;
145266aee900SScott Liu }
145366aee900SScott Liu 
145466aee900SScott Liu static SIMPLE_DEV_PM_OPS(elants_i2c_pm_ops,
145566aee900SScott Liu 			 elants_i2c_suspend, elants_i2c_resume);
145666aee900SScott Liu 
145766aee900SScott Liu static const struct i2c_device_id elants_i2c_id[] = {
145866aee900SScott Liu 	{ DEVICE_NAME, 0 },
145966aee900SScott Liu 	{ }
146066aee900SScott Liu };
146166aee900SScott Liu MODULE_DEVICE_TABLE(i2c, elants_i2c_id);
146266aee900SScott Liu 
146366aee900SScott Liu #ifdef CONFIG_ACPI
146466aee900SScott Liu static const struct acpi_device_id elants_acpi_id[] = {
146566aee900SScott Liu 	{ "ELAN0001", 0 },
146666aee900SScott Liu 	{ }
146766aee900SScott Liu };
146866aee900SScott Liu MODULE_DEVICE_TABLE(acpi, elants_acpi_id);
146966aee900SScott Liu #endif
147066aee900SScott Liu 
147166aee900SScott Liu #ifdef CONFIG_OF
147266aee900SScott Liu static const struct of_device_id elants_of_match[] = {
147366aee900SScott Liu 	{ .compatible = "elan,ekth3500" },
147466aee900SScott Liu 	{ /* sentinel */ }
147566aee900SScott Liu };
147666aee900SScott Liu MODULE_DEVICE_TABLE(of, elants_of_match);
147766aee900SScott Liu #endif
147866aee900SScott Liu 
147966aee900SScott Liu static struct i2c_driver elants_i2c_driver = {
148066aee900SScott Liu 	.probe = elants_i2c_probe,
148166aee900SScott Liu 	.id_table = elants_i2c_id,
148266aee900SScott Liu 	.driver = {
148366aee900SScott Liu 		.name = DEVICE_NAME,
148466aee900SScott Liu 		.pm = &elants_i2c_pm_ops,
148566aee900SScott Liu 		.acpi_match_table = ACPI_PTR(elants_acpi_id),
148666aee900SScott Liu 		.of_match_table = of_match_ptr(elants_of_match),
14879f6a07b6SDmitry Torokhov 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
148866aee900SScott Liu 	},
148966aee900SScott Liu };
149066aee900SScott Liu module_i2c_driver(elants_i2c_driver);
149166aee900SScott Liu 
149266aee900SScott Liu MODULE_AUTHOR("Scott Liu <scott.liu@emc.com.tw>");
149366aee900SScott Liu MODULE_DESCRIPTION("Elan I2c Touchscreen driver");
149466aee900SScott Liu MODULE_LICENSE("GPL");
1495