xref: /OK3568_Linux_fs/kernel/drivers/input/touchscreen/melfas_mip4.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * MELFAS MIP4 Touchscreen
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2016 MELFAS Inc.
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Author : Sangwon Jee <jeesw@melfas.com>
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <linux/acpi.h>
11*4882a593Smuzhiyun #include <linux/delay.h>
12*4882a593Smuzhiyun #include <linux/firmware.h>
13*4882a593Smuzhiyun #include <linux/gpio/consumer.h>
14*4882a593Smuzhiyun #include <linux/i2c.h>
15*4882a593Smuzhiyun #include <linux/input.h>
16*4882a593Smuzhiyun #include <linux/input/mt.h>
17*4882a593Smuzhiyun #include <linux/interrupt.h>
18*4882a593Smuzhiyun #include <linux/module.h>
19*4882a593Smuzhiyun #include <linux/of.h>
20*4882a593Smuzhiyun #include <linux/slab.h>
21*4882a593Smuzhiyun #include <asm/unaligned.h>
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #define MIP4_DEVICE_NAME	"mip4_ts"
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun /*****************************************************************
26*4882a593Smuzhiyun  * Protocol
27*4882a593Smuzhiyun  * Version : MIP 4.0 Rev 5.4
28*4882a593Smuzhiyun  *****************************************************************/
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun /* Address */
31*4882a593Smuzhiyun #define MIP4_R0_BOOT				0x00
32*4882a593Smuzhiyun #define MIP4_R1_BOOT_MODE			0x01
33*4882a593Smuzhiyun #define MIP4_R1_BOOT_BUF_ADDR			0x10
34*4882a593Smuzhiyun #define MIP4_R1_BOOT_STATUS			0x20
35*4882a593Smuzhiyun #define MIP4_R1_BOOT_CMD			0x30
36*4882a593Smuzhiyun #define MIP4_R1_BOOT_TARGET_ADDR		0x40
37*4882a593Smuzhiyun #define MIP4_R1_BOOT_SIZE			0x44
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun #define MIP4_R0_INFO				0x01
40*4882a593Smuzhiyun #define MIP4_R1_INFO_PRODUCT_NAME		0x00
41*4882a593Smuzhiyun #define MIP4_R1_INFO_RESOLUTION_X		0x10
42*4882a593Smuzhiyun #define MIP4_R1_INFO_RESOLUTION_Y		0x12
43*4882a593Smuzhiyun #define MIP4_R1_INFO_NODE_NUM_X			0x14
44*4882a593Smuzhiyun #define MIP4_R1_INFO_NODE_NUM_Y			0x15
45*4882a593Smuzhiyun #define MIP4_R1_INFO_KEY_NUM			0x16
46*4882a593Smuzhiyun #define MIP4_R1_INFO_PRESSURE_NUM		0x17
47*4882a593Smuzhiyun #define MIP4_R1_INFO_LENGTH_X			0x18
48*4882a593Smuzhiyun #define MIP4_R1_INFO_LENGTH_Y			0x1A
49*4882a593Smuzhiyun #define MIP4_R1_INFO_PPM_X			0x1C
50*4882a593Smuzhiyun #define MIP4_R1_INFO_PPM_Y			0x1D
51*4882a593Smuzhiyun #define MIP4_R1_INFO_VERSION_BOOT		0x20
52*4882a593Smuzhiyun #define MIP4_R1_INFO_VERSION_CORE		0x22
53*4882a593Smuzhiyun #define MIP4_R1_INFO_VERSION_APP		0x24
54*4882a593Smuzhiyun #define MIP4_R1_INFO_VERSION_PARAM		0x26
55*4882a593Smuzhiyun #define MIP4_R1_INFO_SECT_BOOT_START		0x30
56*4882a593Smuzhiyun #define MIP4_R1_INFO_SECT_BOOT_END		0x31
57*4882a593Smuzhiyun #define MIP4_R1_INFO_SECT_CORE_START		0x32
58*4882a593Smuzhiyun #define MIP4_R1_INFO_SECT_CORE_END		0x33
59*4882a593Smuzhiyun #define MIP4_R1_INFO_SECT_APP_START		0x34
60*4882a593Smuzhiyun #define MIP4_R1_INFO_SECT_APP_END		0x35
61*4882a593Smuzhiyun #define MIP4_R1_INFO_SECT_PARAM_START		0x36
62*4882a593Smuzhiyun #define MIP4_R1_INFO_SECT_PARAM_END		0x37
63*4882a593Smuzhiyun #define MIP4_R1_INFO_BUILD_DATE			0x40
64*4882a593Smuzhiyun #define MIP4_R1_INFO_BUILD_TIME			0x44
65*4882a593Smuzhiyun #define MIP4_R1_INFO_CHECKSUM_PRECALC		0x48
66*4882a593Smuzhiyun #define MIP4_R1_INFO_CHECKSUM_REALTIME		0x4A
67*4882a593Smuzhiyun #define MIP4_R1_INFO_PROTOCOL_NAME		0x50
68*4882a593Smuzhiyun #define MIP4_R1_INFO_PROTOCOL_VERSION		0x58
69*4882a593Smuzhiyun #define MIP4_R1_INFO_IC_ID			0x70
70*4882a593Smuzhiyun #define MIP4_R1_INFO_IC_NAME			0x71
71*4882a593Smuzhiyun #define MIP4_R1_INFO_IC_VENDOR_ID		0x75
72*4882a593Smuzhiyun #define MIP4_R1_INFO_IC_HW_CATEGORY		0x77
73*4882a593Smuzhiyun #define MIP4_R1_INFO_CONTACT_THD_SCR		0x78
74*4882a593Smuzhiyun #define MIP4_R1_INFO_CONTACT_THD_KEY		0x7A
75*4882a593Smuzhiyun #define MIP4_R1_INFO_PID				0x7C
76*4882a593Smuzhiyun #define MIP4_R1_INFO_VID				0x7E
77*4882a593Smuzhiyun #define MIP4_R1_INFO_SLAVE_ADDR			0x80
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun #define MIP4_R0_EVENT				0x02
80*4882a593Smuzhiyun #define MIP4_R1_EVENT_SUPPORTED_FUNC		0x00
81*4882a593Smuzhiyun #define MIP4_R1_EVENT_FORMAT			0x04
82*4882a593Smuzhiyun #define MIP4_R1_EVENT_SIZE			0x06
83*4882a593Smuzhiyun #define MIP4_R1_EVENT_PACKET_INFO		0x10
84*4882a593Smuzhiyun #define MIP4_R1_EVENT_PACKET_DATA		0x11
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun #define MIP4_R0_CTRL				0x06
87*4882a593Smuzhiyun #define MIP4_R1_CTRL_READY_STATUS		0x00
88*4882a593Smuzhiyun #define MIP4_R1_CTRL_EVENT_READY		0x01
89*4882a593Smuzhiyun #define MIP4_R1_CTRL_MODE			0x10
90*4882a593Smuzhiyun #define MIP4_R1_CTRL_EVENT_TRIGGER_TYPE		0x11
91*4882a593Smuzhiyun #define MIP4_R1_CTRL_RECALIBRATE		0x12
92*4882a593Smuzhiyun #define MIP4_R1_CTRL_POWER_STATE		0x13
93*4882a593Smuzhiyun #define MIP4_R1_CTRL_GESTURE_TYPE		0x14
94*4882a593Smuzhiyun #define MIP4_R1_CTRL_DISABLE_ESD_ALERT		0x18
95*4882a593Smuzhiyun #define MIP4_R1_CTRL_CHARGER_MODE		0x19
96*4882a593Smuzhiyun #define MIP4_R1_CTRL_HIGH_SENS_MODE		0x1A
97*4882a593Smuzhiyun #define MIP4_R1_CTRL_WINDOW_MODE		0x1B
98*4882a593Smuzhiyun #define MIP4_R1_CTRL_PALM_REJECTION		0x1C
99*4882a593Smuzhiyun #define MIP4_R1_CTRL_EDGE_CORRECTION		0x1D
100*4882a593Smuzhiyun #define MIP4_R1_CTRL_ENTER_GLOVE_MODE		0x1E
101*4882a593Smuzhiyun #define MIP4_R1_CTRL_I2C_ON_LPM			0x1F
102*4882a593Smuzhiyun #define MIP4_R1_CTRL_GESTURE_DEBUG		0x20
103*4882a593Smuzhiyun #define MIP4_R1_CTRL_PALM_EVENT			0x22
104*4882a593Smuzhiyun #define MIP4_R1_CTRL_PROXIMITY_SENSING		0x23
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun /* Value */
107*4882a593Smuzhiyun #define MIP4_BOOT_MODE_BOOT			0x01
108*4882a593Smuzhiyun #define MIP4_BOOT_MODE_APP			0x02
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun #define MIP4_BOOT_STATUS_BUSY			0x05
111*4882a593Smuzhiyun #define MIP4_BOOT_STATUS_ERROR			0x0E
112*4882a593Smuzhiyun #define MIP4_BOOT_STATUS_DONE			0xA0
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun #define MIP4_BOOT_CMD_MASS_ERASE		0x15
115*4882a593Smuzhiyun #define MIP4_BOOT_CMD_PROGRAM			0x54
116*4882a593Smuzhiyun #define MIP4_BOOT_CMD_ERASE			0x8F
117*4882a593Smuzhiyun #define MIP4_BOOT_CMD_WRITE			0xA5
118*4882a593Smuzhiyun #define MIP4_BOOT_CMD_READ			0xC2
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun #define MIP4_EVENT_INPUT_TYPE_KEY		0
121*4882a593Smuzhiyun #define MIP4_EVENT_INPUT_TYPE_SCREEN		1
122*4882a593Smuzhiyun #define MIP4_EVENT_INPUT_TYPE_PROXIMITY		2
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun #define I2C_RETRY_COUNT				3	/* 2~ */
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun #define MIP4_BUF_SIZE				128
127*4882a593Smuzhiyun #define MIP4_MAX_FINGERS			10
128*4882a593Smuzhiyun #define MIP4_MAX_KEYS				4
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun #define MIP4_TOUCH_MAJOR_MIN			0
131*4882a593Smuzhiyun #define MIP4_TOUCH_MAJOR_MAX			255
132*4882a593Smuzhiyun #define MIP4_TOUCH_MINOR_MIN			0
133*4882a593Smuzhiyun #define MIP4_TOUCH_MINOR_MAX			255
134*4882a593Smuzhiyun #define MIP4_PRESSURE_MIN			0
135*4882a593Smuzhiyun #define MIP4_PRESSURE_MAX			255
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun #define MIP4_FW_NAME			"melfas_mip4.fw"
138*4882a593Smuzhiyun #define MIP4_FW_UPDATE_DEBUG		0	/* 0 (default) or 1 */
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun struct mip4_fw_version {
141*4882a593Smuzhiyun 	u16 boot;
142*4882a593Smuzhiyun 	u16 core;
143*4882a593Smuzhiyun 	u16 app;
144*4882a593Smuzhiyun 	u16 param;
145*4882a593Smuzhiyun };
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun struct mip4_ts {
148*4882a593Smuzhiyun 	struct i2c_client *client;
149*4882a593Smuzhiyun 	struct input_dev *input;
150*4882a593Smuzhiyun 	struct gpio_desc *gpio_ce;
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	char phys[32];
153*4882a593Smuzhiyun 	char product_name[16];
154*4882a593Smuzhiyun 	u16 product_id;
155*4882a593Smuzhiyun 	char ic_name[4];
156*4882a593Smuzhiyun 	char fw_name[32];
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	unsigned int max_x;
159*4882a593Smuzhiyun 	unsigned int max_y;
160*4882a593Smuzhiyun 	u8 node_x;
161*4882a593Smuzhiyun 	u8 node_y;
162*4882a593Smuzhiyun 	u8 node_key;
163*4882a593Smuzhiyun 	unsigned int ppm_x;
164*4882a593Smuzhiyun 	unsigned int ppm_y;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	struct mip4_fw_version fw_version;
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 	unsigned int event_size;
169*4882a593Smuzhiyun 	unsigned int event_format;
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	unsigned int key_num;
172*4882a593Smuzhiyun 	unsigned short key_code[MIP4_MAX_KEYS];
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	bool wake_irq_enabled;
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	u8 buf[MIP4_BUF_SIZE];
177*4882a593Smuzhiyun };
178*4882a593Smuzhiyun 
mip4_i2c_xfer(struct mip4_ts * ts,char * write_buf,unsigned int write_len,char * read_buf,unsigned int read_len)179*4882a593Smuzhiyun static int mip4_i2c_xfer(struct mip4_ts *ts,
180*4882a593Smuzhiyun 			 char *write_buf, unsigned int write_len,
181*4882a593Smuzhiyun 			 char *read_buf, unsigned int read_len)
182*4882a593Smuzhiyun {
183*4882a593Smuzhiyun 	struct i2c_msg msg[] = {
184*4882a593Smuzhiyun 		{
185*4882a593Smuzhiyun 			.addr = ts->client->addr,
186*4882a593Smuzhiyun 			.flags = 0,
187*4882a593Smuzhiyun 			.buf = write_buf,
188*4882a593Smuzhiyun 			.len = write_len,
189*4882a593Smuzhiyun 		}, {
190*4882a593Smuzhiyun 			.addr = ts->client->addr,
191*4882a593Smuzhiyun 			.flags = I2C_M_RD,
192*4882a593Smuzhiyun 			.buf = read_buf,
193*4882a593Smuzhiyun 			.len = read_len,
194*4882a593Smuzhiyun 		},
195*4882a593Smuzhiyun 	};
196*4882a593Smuzhiyun 	int retry = I2C_RETRY_COUNT;
197*4882a593Smuzhiyun 	int res;
198*4882a593Smuzhiyun 	int error;
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	do {
201*4882a593Smuzhiyun 		res = i2c_transfer(ts->client->adapter, msg, ARRAY_SIZE(msg));
202*4882a593Smuzhiyun 		if (res == ARRAY_SIZE(msg))
203*4882a593Smuzhiyun 			return 0;
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 		error = res < 0 ? res : -EIO;
206*4882a593Smuzhiyun 		dev_err(&ts->client->dev,
207*4882a593Smuzhiyun 			"%s - i2c_transfer failed: %d (%d)\n",
208*4882a593Smuzhiyun 			__func__, error, res);
209*4882a593Smuzhiyun 	} while (--retry);
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 	return error;
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun 
mip4_parse_fw_version(const u8 * buf,struct mip4_fw_version * v)214*4882a593Smuzhiyun static void mip4_parse_fw_version(const u8 *buf, struct mip4_fw_version *v)
215*4882a593Smuzhiyun {
216*4882a593Smuzhiyun 	v->boot  = get_unaligned_le16(buf + 0);
217*4882a593Smuzhiyun 	v->core  = get_unaligned_le16(buf + 2);
218*4882a593Smuzhiyun 	v->app   = get_unaligned_le16(buf + 4);
219*4882a593Smuzhiyun 	v->param = get_unaligned_le16(buf + 6);
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun /*
223*4882a593Smuzhiyun  * Read chip firmware version
224*4882a593Smuzhiyun  */
mip4_get_fw_version(struct mip4_ts * ts)225*4882a593Smuzhiyun static int mip4_get_fw_version(struct mip4_ts *ts)
226*4882a593Smuzhiyun {
227*4882a593Smuzhiyun 	u8 cmd[] = { MIP4_R0_INFO, MIP4_R1_INFO_VERSION_BOOT };
228*4882a593Smuzhiyun 	u8 buf[sizeof(ts->fw_version)];
229*4882a593Smuzhiyun 	int error;
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	error = mip4_i2c_xfer(ts, cmd, sizeof(cmd), buf, sizeof(buf));
232*4882a593Smuzhiyun 	if (error) {
233*4882a593Smuzhiyun 		memset(&ts->fw_version, 0xff, sizeof(ts->fw_version));
234*4882a593Smuzhiyun 		return error;
235*4882a593Smuzhiyun 	}
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 	mip4_parse_fw_version(buf, &ts->fw_version);
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	return 0;
240*4882a593Smuzhiyun }
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun /*
243*4882a593Smuzhiyun  * Fetch device characteristics
244*4882a593Smuzhiyun  */
mip4_query_device(struct mip4_ts * ts)245*4882a593Smuzhiyun static int mip4_query_device(struct mip4_ts *ts)
246*4882a593Smuzhiyun {
247*4882a593Smuzhiyun 	union i2c_smbus_data dummy;
248*4882a593Smuzhiyun 	int error;
249*4882a593Smuzhiyun 	u8 cmd[2];
250*4882a593Smuzhiyun 	u8 buf[14];
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	/*
253*4882a593Smuzhiyun 	 * Make sure there is something at this address as we do not
254*4882a593Smuzhiyun 	 * consider subsequent failures as fatal.
255*4882a593Smuzhiyun 	 */
256*4882a593Smuzhiyun 	if (i2c_smbus_xfer(ts->client->adapter, ts->client->addr,
257*4882a593Smuzhiyun 			   0, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &dummy) < 0) {
258*4882a593Smuzhiyun 		dev_err(&ts->client->dev, "nothing at this address\n");
259*4882a593Smuzhiyun 		return -ENXIO;
260*4882a593Smuzhiyun 	}
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	/* Product name */
263*4882a593Smuzhiyun 	cmd[0] = MIP4_R0_INFO;
264*4882a593Smuzhiyun 	cmd[1] = MIP4_R1_INFO_PRODUCT_NAME;
265*4882a593Smuzhiyun 	error = mip4_i2c_xfer(ts, cmd, sizeof(cmd),
266*4882a593Smuzhiyun 			      ts->product_name, sizeof(ts->product_name));
267*4882a593Smuzhiyun 	if (error)
268*4882a593Smuzhiyun 		dev_warn(&ts->client->dev,
269*4882a593Smuzhiyun 			 "Failed to retrieve product name: %d\n", error);
270*4882a593Smuzhiyun 	else
271*4882a593Smuzhiyun 		dev_dbg(&ts->client->dev, "product name: %.*s\n",
272*4882a593Smuzhiyun 			(int)sizeof(ts->product_name), ts->product_name);
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 	/* Product ID */
275*4882a593Smuzhiyun 	cmd[0] = MIP4_R0_INFO;
276*4882a593Smuzhiyun 	cmd[1] = MIP4_R1_INFO_PID;
277*4882a593Smuzhiyun 	error = mip4_i2c_xfer(ts, cmd, sizeof(cmd), buf, 2);
278*4882a593Smuzhiyun 	if (error) {
279*4882a593Smuzhiyun 		dev_warn(&ts->client->dev,
280*4882a593Smuzhiyun 			 "Failed to retrieve product id: %d\n", error);
281*4882a593Smuzhiyun 	} else {
282*4882a593Smuzhiyun 		ts->product_id = get_unaligned_le16(&buf[0]);
283*4882a593Smuzhiyun 		dev_dbg(&ts->client->dev, "product id: %04X\n", ts->product_id);
284*4882a593Smuzhiyun 	}
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	/* Firmware name */
287*4882a593Smuzhiyun 	snprintf(ts->fw_name, sizeof(ts->fw_name),
288*4882a593Smuzhiyun 		"melfas_mip4_%04X.fw", ts->product_id);
289*4882a593Smuzhiyun 	dev_dbg(&ts->client->dev, "firmware name: %s\n", ts->fw_name);
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	/* IC name */
292*4882a593Smuzhiyun 	cmd[0] = MIP4_R0_INFO;
293*4882a593Smuzhiyun 	cmd[1] = MIP4_R1_INFO_IC_NAME;
294*4882a593Smuzhiyun 	error = mip4_i2c_xfer(ts, cmd, sizeof(cmd),
295*4882a593Smuzhiyun 			      ts->ic_name, sizeof(ts->ic_name));
296*4882a593Smuzhiyun 	if (error)
297*4882a593Smuzhiyun 		dev_warn(&ts->client->dev,
298*4882a593Smuzhiyun 			 "Failed to retrieve IC name: %d\n", error);
299*4882a593Smuzhiyun 	else
300*4882a593Smuzhiyun 		dev_dbg(&ts->client->dev, "IC name: %.*s\n",
301*4882a593Smuzhiyun 			(int)sizeof(ts->ic_name), ts->ic_name);
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun 	/* Firmware version */
304*4882a593Smuzhiyun 	error = mip4_get_fw_version(ts);
305*4882a593Smuzhiyun 	if (error)
306*4882a593Smuzhiyun 		dev_warn(&ts->client->dev,
307*4882a593Smuzhiyun 			"Failed to retrieve FW version: %d\n", error);
308*4882a593Smuzhiyun 	else
309*4882a593Smuzhiyun 		dev_dbg(&ts->client->dev, "F/W Version: %04X %04X %04X %04X\n",
310*4882a593Smuzhiyun 			 ts->fw_version.boot, ts->fw_version.core,
311*4882a593Smuzhiyun 			 ts->fw_version.app, ts->fw_version.param);
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	/* Resolution */
314*4882a593Smuzhiyun 	cmd[0] = MIP4_R0_INFO;
315*4882a593Smuzhiyun 	cmd[1] = MIP4_R1_INFO_RESOLUTION_X;
316*4882a593Smuzhiyun 	error = mip4_i2c_xfer(ts, cmd, sizeof(cmd), buf, 14);
317*4882a593Smuzhiyun 	if (error) {
318*4882a593Smuzhiyun 		dev_warn(&ts->client->dev,
319*4882a593Smuzhiyun 			 "Failed to retrieve touchscreen parameters: %d\n",
320*4882a593Smuzhiyun 			 error);
321*4882a593Smuzhiyun 	} else {
322*4882a593Smuzhiyun 		ts->max_x = get_unaligned_le16(&buf[0]);
323*4882a593Smuzhiyun 		ts->max_y = get_unaligned_le16(&buf[2]);
324*4882a593Smuzhiyun 		dev_dbg(&ts->client->dev, "max_x: %d, max_y: %d\n",
325*4882a593Smuzhiyun 			ts->max_x, ts->max_y);
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 		ts->node_x = buf[4];
328*4882a593Smuzhiyun 		ts->node_y = buf[5];
329*4882a593Smuzhiyun 		ts->node_key = buf[6];
330*4882a593Smuzhiyun 		dev_dbg(&ts->client->dev,
331*4882a593Smuzhiyun 			"node_x: %d, node_y: %d, node_key: %d\n",
332*4882a593Smuzhiyun 			ts->node_x, ts->node_y, ts->node_key);
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 		ts->ppm_x = buf[12];
335*4882a593Smuzhiyun 		ts->ppm_y = buf[13];
336*4882a593Smuzhiyun 		dev_dbg(&ts->client->dev, "ppm_x: %d, ppm_y: %d\n",
337*4882a593Smuzhiyun 			ts->ppm_x, ts->ppm_y);
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 		/* Key ts */
340*4882a593Smuzhiyun 		if (ts->node_key > 0)
341*4882a593Smuzhiyun 			ts->key_num = ts->node_key;
342*4882a593Smuzhiyun 	}
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 	/* Protocol */
345*4882a593Smuzhiyun 	cmd[0] = MIP4_R0_EVENT;
346*4882a593Smuzhiyun 	cmd[1] = MIP4_R1_EVENT_SUPPORTED_FUNC;
347*4882a593Smuzhiyun 	error = mip4_i2c_xfer(ts, cmd, sizeof(cmd), buf, 7);
348*4882a593Smuzhiyun 	if (error) {
349*4882a593Smuzhiyun 		dev_warn(&ts->client->dev,
350*4882a593Smuzhiyun 			"Failed to retrieve device type: %d\n", error);
351*4882a593Smuzhiyun 		ts->event_format = 0xff;
352*4882a593Smuzhiyun 	} else {
353*4882a593Smuzhiyun 		ts->event_format = get_unaligned_le16(&buf[4]);
354*4882a593Smuzhiyun 		ts->event_size = buf[6];
355*4882a593Smuzhiyun 		dev_dbg(&ts->client->dev, "event_format: %d, event_size: %d\n",
356*4882a593Smuzhiyun 			ts->event_format, ts->event_size);
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 		if (ts->event_format == 2 || ts->event_format > 3)
359*4882a593Smuzhiyun 			dev_warn(&ts->client->dev,
360*4882a593Smuzhiyun 				 "Unknown event format %d\n", ts->event_format);
361*4882a593Smuzhiyun 	}
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun 	return 0;
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun 
mip4_power_on(struct mip4_ts * ts)366*4882a593Smuzhiyun static int mip4_power_on(struct mip4_ts *ts)
367*4882a593Smuzhiyun {
368*4882a593Smuzhiyun 	if (ts->gpio_ce) {
369*4882a593Smuzhiyun 		gpiod_set_value_cansleep(ts->gpio_ce, 1);
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 		/* Booting delay : 200~300ms */
372*4882a593Smuzhiyun 		usleep_range(200 * 1000, 300 * 1000);
373*4882a593Smuzhiyun 	}
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	return 0;
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun 
mip4_power_off(struct mip4_ts * ts)378*4882a593Smuzhiyun static void mip4_power_off(struct mip4_ts *ts)
379*4882a593Smuzhiyun {
380*4882a593Smuzhiyun 	if (ts->gpio_ce)
381*4882a593Smuzhiyun 		gpiod_set_value_cansleep(ts->gpio_ce, 0);
382*4882a593Smuzhiyun }
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun /*
385*4882a593Smuzhiyun  * Clear touch input event status
386*4882a593Smuzhiyun  */
mip4_clear_input(struct mip4_ts * ts)387*4882a593Smuzhiyun static void mip4_clear_input(struct mip4_ts *ts)
388*4882a593Smuzhiyun {
389*4882a593Smuzhiyun 	int i;
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun 	/* Screen */
392*4882a593Smuzhiyun 	for (i = 0; i < MIP4_MAX_FINGERS; i++) {
393*4882a593Smuzhiyun 		input_mt_slot(ts->input, i);
394*4882a593Smuzhiyun 		input_mt_report_slot_inactive(ts->input);
395*4882a593Smuzhiyun 	}
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 	/* Keys */
398*4882a593Smuzhiyun 	for (i = 0; i < ts->key_num; i++)
399*4882a593Smuzhiyun 		input_report_key(ts->input, ts->key_code[i], 0);
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 	input_sync(ts->input);
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun 
mip4_enable(struct mip4_ts * ts)404*4882a593Smuzhiyun static int mip4_enable(struct mip4_ts *ts)
405*4882a593Smuzhiyun {
406*4882a593Smuzhiyun 	int error;
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun 	error = mip4_power_on(ts);
409*4882a593Smuzhiyun 	if (error)
410*4882a593Smuzhiyun 		return error;
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun 	enable_irq(ts->client->irq);
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 	return 0;
415*4882a593Smuzhiyun }
416*4882a593Smuzhiyun 
mip4_disable(struct mip4_ts * ts)417*4882a593Smuzhiyun static void mip4_disable(struct mip4_ts *ts)
418*4882a593Smuzhiyun {
419*4882a593Smuzhiyun 	disable_irq(ts->client->irq);
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 	mip4_power_off(ts);
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	mip4_clear_input(ts);
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun /*****************************************************************
427*4882a593Smuzhiyun  * Input handling
428*4882a593Smuzhiyun  *****************************************************************/
429*4882a593Smuzhiyun 
mip4_report_keys(struct mip4_ts * ts,u8 * packet)430*4882a593Smuzhiyun static void mip4_report_keys(struct mip4_ts *ts, u8 *packet)
431*4882a593Smuzhiyun {
432*4882a593Smuzhiyun 	u8 key;
433*4882a593Smuzhiyun 	bool down;
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun 	switch (ts->event_format) {
436*4882a593Smuzhiyun 	case 0:
437*4882a593Smuzhiyun 	case 1:
438*4882a593Smuzhiyun 		key = packet[0] & 0x0F;
439*4882a593Smuzhiyun 		down = packet[0] & 0x80;
440*4882a593Smuzhiyun 		break;
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun 	case 3:
443*4882a593Smuzhiyun 	default:
444*4882a593Smuzhiyun 		key = packet[0] & 0x0F;
445*4882a593Smuzhiyun 		down = packet[1] & 0x01;
446*4882a593Smuzhiyun 		break;
447*4882a593Smuzhiyun 	}
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 	/* Report key event */
450*4882a593Smuzhiyun 	if (key >= 1 && key <= ts->key_num) {
451*4882a593Smuzhiyun 		unsigned short keycode = ts->key_code[key - 1];
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 		dev_dbg(&ts->client->dev,
454*4882a593Smuzhiyun 			"Key - ID: %d, keycode: %d, state: %d\n",
455*4882a593Smuzhiyun 			key, keycode, down);
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun 		input_event(ts->input, EV_MSC, MSC_SCAN, keycode);
458*4882a593Smuzhiyun 		input_report_key(ts->input, keycode, down);
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun 	} else {
461*4882a593Smuzhiyun 		dev_err(&ts->client->dev, "Unknown key: %d\n", key);
462*4882a593Smuzhiyun 	}
463*4882a593Smuzhiyun }
464*4882a593Smuzhiyun 
mip4_report_touch(struct mip4_ts * ts,u8 * packet)465*4882a593Smuzhiyun static void mip4_report_touch(struct mip4_ts *ts, u8 *packet)
466*4882a593Smuzhiyun {
467*4882a593Smuzhiyun 	int id;
468*4882a593Smuzhiyun 	bool hover;
469*4882a593Smuzhiyun 	bool palm;
470*4882a593Smuzhiyun 	bool state;
471*4882a593Smuzhiyun 	u16 x, y;
472*4882a593Smuzhiyun 	u8 pressure_stage = 0;
473*4882a593Smuzhiyun 	u8 pressure;
474*4882a593Smuzhiyun 	u8 size;
475*4882a593Smuzhiyun 	u8 touch_major;
476*4882a593Smuzhiyun 	u8 touch_minor;
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun 	switch (ts->event_format) {
479*4882a593Smuzhiyun 	case 0:
480*4882a593Smuzhiyun 	case 1:
481*4882a593Smuzhiyun 		/* Touch only */
482*4882a593Smuzhiyun 		state = packet[0] & BIT(7);
483*4882a593Smuzhiyun 		hover = packet[0] & BIT(5);
484*4882a593Smuzhiyun 		palm = packet[0] & BIT(4);
485*4882a593Smuzhiyun 		id = (packet[0] & 0x0F) - 1;
486*4882a593Smuzhiyun 		x = ((packet[1] & 0x0F) << 8) | packet[2];
487*4882a593Smuzhiyun 		y = (((packet[1] >> 4) & 0x0F) << 8) |
488*4882a593Smuzhiyun 			packet[3];
489*4882a593Smuzhiyun 		pressure = packet[4];
490*4882a593Smuzhiyun 		size = packet[5];
491*4882a593Smuzhiyun 		if (ts->event_format == 0) {
492*4882a593Smuzhiyun 			touch_major = packet[5];
493*4882a593Smuzhiyun 			touch_minor = packet[5];
494*4882a593Smuzhiyun 		} else {
495*4882a593Smuzhiyun 			touch_major = packet[6];
496*4882a593Smuzhiyun 			touch_minor = packet[7];
497*4882a593Smuzhiyun 		}
498*4882a593Smuzhiyun 		break;
499*4882a593Smuzhiyun 
500*4882a593Smuzhiyun 	case 3:
501*4882a593Smuzhiyun 	default:
502*4882a593Smuzhiyun 		/* Touch + Force(Pressure) */
503*4882a593Smuzhiyun 		id = (packet[0] & 0x0F) - 1;
504*4882a593Smuzhiyun 		hover = packet[1] & BIT(2);
505*4882a593Smuzhiyun 		palm = packet[1] & BIT(1);
506*4882a593Smuzhiyun 		state = packet[1] & BIT(0);
507*4882a593Smuzhiyun 		x = ((packet[2] & 0x0F) << 8) | packet[3];
508*4882a593Smuzhiyun 		y = (((packet[2] >> 4) & 0x0F) << 8) |
509*4882a593Smuzhiyun 			packet[4];
510*4882a593Smuzhiyun 		size = packet[6];
511*4882a593Smuzhiyun 		pressure_stage = (packet[7] & 0xF0) >> 4;
512*4882a593Smuzhiyun 		pressure = ((packet[7] & 0x0F) << 8) |
513*4882a593Smuzhiyun 			packet[8];
514*4882a593Smuzhiyun 		touch_major = packet[9];
515*4882a593Smuzhiyun 		touch_minor = packet[10];
516*4882a593Smuzhiyun 		break;
517*4882a593Smuzhiyun 	}
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun 	dev_dbg(&ts->client->dev,
520*4882a593Smuzhiyun 		"Screen - Slot: %d State: %d X: %04d Y: %04d Z: %d\n",
521*4882a593Smuzhiyun 		id, state, x, y, pressure);
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun 	if (unlikely(id < 0 || id >= MIP4_MAX_FINGERS)) {
524*4882a593Smuzhiyun 		dev_err(&ts->client->dev, "Screen - invalid slot ID: %d\n", id);
525*4882a593Smuzhiyun 	} else if (state) {
526*4882a593Smuzhiyun 		/* Press or Move event */
527*4882a593Smuzhiyun 		input_mt_slot(ts->input, id);
528*4882a593Smuzhiyun 		input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, true);
529*4882a593Smuzhiyun 		input_report_abs(ts->input, ABS_MT_POSITION_X, x);
530*4882a593Smuzhiyun 		input_report_abs(ts->input, ABS_MT_POSITION_Y, y);
531*4882a593Smuzhiyun 		input_report_abs(ts->input, ABS_MT_PRESSURE, pressure);
532*4882a593Smuzhiyun 		input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, touch_major);
533*4882a593Smuzhiyun 		input_report_abs(ts->input, ABS_MT_TOUCH_MINOR, touch_minor);
534*4882a593Smuzhiyun 	} else {
535*4882a593Smuzhiyun 		/* Release event */
536*4882a593Smuzhiyun 		input_mt_slot(ts->input, id);
537*4882a593Smuzhiyun 		input_mt_report_slot_inactive(ts->input);
538*4882a593Smuzhiyun 	}
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun 	input_mt_sync_frame(ts->input);
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun 
mip4_handle_packet(struct mip4_ts * ts,u8 * packet)543*4882a593Smuzhiyun static int mip4_handle_packet(struct mip4_ts *ts, u8 *packet)
544*4882a593Smuzhiyun {
545*4882a593Smuzhiyun 	u8 type;
546*4882a593Smuzhiyun 
547*4882a593Smuzhiyun 	switch (ts->event_format) {
548*4882a593Smuzhiyun 	case 0:
549*4882a593Smuzhiyun 	case 1:
550*4882a593Smuzhiyun 		type = (packet[0] & 0x40) >> 6;
551*4882a593Smuzhiyun 		break;
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 	case 3:
554*4882a593Smuzhiyun 		type = (packet[0] & 0xF0) >> 4;
555*4882a593Smuzhiyun 		break;
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun 	default:
558*4882a593Smuzhiyun 		/* Should not happen unless we have corrupted firmware */
559*4882a593Smuzhiyun 		return -EINVAL;
560*4882a593Smuzhiyun 	}
561*4882a593Smuzhiyun 
562*4882a593Smuzhiyun 	dev_dbg(&ts->client->dev, "Type: %d\n", type);
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 	/* Report input event */
565*4882a593Smuzhiyun 	switch (type) {
566*4882a593Smuzhiyun 	case MIP4_EVENT_INPUT_TYPE_KEY:
567*4882a593Smuzhiyun 		mip4_report_keys(ts, packet);
568*4882a593Smuzhiyun 		break;
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun 	case MIP4_EVENT_INPUT_TYPE_SCREEN:
571*4882a593Smuzhiyun 		mip4_report_touch(ts, packet);
572*4882a593Smuzhiyun 		break;
573*4882a593Smuzhiyun 
574*4882a593Smuzhiyun 	default:
575*4882a593Smuzhiyun 		dev_err(&ts->client->dev, "Unknown event type: %d\n", type);
576*4882a593Smuzhiyun 		break;
577*4882a593Smuzhiyun 	}
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun 	return 0;
580*4882a593Smuzhiyun }
581*4882a593Smuzhiyun 
mip4_interrupt(int irq,void * dev_id)582*4882a593Smuzhiyun static irqreturn_t mip4_interrupt(int irq, void *dev_id)
583*4882a593Smuzhiyun {
584*4882a593Smuzhiyun 	struct mip4_ts *ts = dev_id;
585*4882a593Smuzhiyun 	struct i2c_client *client = ts->client;
586*4882a593Smuzhiyun 	unsigned int i;
587*4882a593Smuzhiyun 	int error;
588*4882a593Smuzhiyun 	u8 cmd[2];
589*4882a593Smuzhiyun 	u8 size;
590*4882a593Smuzhiyun 	bool alert;
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun 	/* Read packet info */
593*4882a593Smuzhiyun 	cmd[0] = MIP4_R0_EVENT;
594*4882a593Smuzhiyun 	cmd[1] = MIP4_R1_EVENT_PACKET_INFO;
595*4882a593Smuzhiyun 	error = mip4_i2c_xfer(ts, cmd, sizeof(cmd), ts->buf, 1);
596*4882a593Smuzhiyun 	if (error) {
597*4882a593Smuzhiyun 		dev_err(&client->dev,
598*4882a593Smuzhiyun 			"Failed to read packet info: %d\n", error);
599*4882a593Smuzhiyun 		goto out;
600*4882a593Smuzhiyun 	}
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun 	size = ts->buf[0] & 0x7F;
603*4882a593Smuzhiyun 	alert = ts->buf[0] & BIT(7);
604*4882a593Smuzhiyun 	dev_dbg(&client->dev, "packet size: %d, alert: %d\n", size, alert);
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun 	/* Check size */
607*4882a593Smuzhiyun 	if (!size) {
608*4882a593Smuzhiyun 		dev_err(&client->dev, "Empty packet\n");
609*4882a593Smuzhiyun 		goto out;
610*4882a593Smuzhiyun 	}
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun 	/* Read packet data */
613*4882a593Smuzhiyun 	cmd[0] = MIP4_R0_EVENT;
614*4882a593Smuzhiyun 	cmd[1] = MIP4_R1_EVENT_PACKET_DATA;
615*4882a593Smuzhiyun 	error = mip4_i2c_xfer(ts, cmd, sizeof(cmd), ts->buf, size);
616*4882a593Smuzhiyun 	if (error) {
617*4882a593Smuzhiyun 		dev_err(&client->dev,
618*4882a593Smuzhiyun 			"Failed to read packet data: %d\n", error);
619*4882a593Smuzhiyun 		goto out;
620*4882a593Smuzhiyun 	}
621*4882a593Smuzhiyun 
622*4882a593Smuzhiyun 	if (alert) {
623*4882a593Smuzhiyun 		dev_dbg(&client->dev, "Alert: %d\n", ts->buf[0]);
624*4882a593Smuzhiyun 	} else {
625*4882a593Smuzhiyun 		for (i = 0; i < size; i += ts->event_size) {
626*4882a593Smuzhiyun 			error = mip4_handle_packet(ts, &ts->buf[i]);
627*4882a593Smuzhiyun 			if (error)
628*4882a593Smuzhiyun 				break;
629*4882a593Smuzhiyun 		}
630*4882a593Smuzhiyun 
631*4882a593Smuzhiyun 		input_sync(ts->input);
632*4882a593Smuzhiyun 	}
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun out:
635*4882a593Smuzhiyun 	return IRQ_HANDLED;
636*4882a593Smuzhiyun }
637*4882a593Smuzhiyun 
mip4_input_open(struct input_dev * dev)638*4882a593Smuzhiyun static int mip4_input_open(struct input_dev *dev)
639*4882a593Smuzhiyun {
640*4882a593Smuzhiyun 	struct mip4_ts *ts = input_get_drvdata(dev);
641*4882a593Smuzhiyun 
642*4882a593Smuzhiyun 	return mip4_enable(ts);
643*4882a593Smuzhiyun }
644*4882a593Smuzhiyun 
mip4_input_close(struct input_dev * dev)645*4882a593Smuzhiyun static void mip4_input_close(struct input_dev *dev)
646*4882a593Smuzhiyun {
647*4882a593Smuzhiyun 	struct mip4_ts *ts = input_get_drvdata(dev);
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun 	mip4_disable(ts);
650*4882a593Smuzhiyun }
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun /*****************************************************************
653*4882a593Smuzhiyun  * Firmware update
654*4882a593Smuzhiyun  *****************************************************************/
655*4882a593Smuzhiyun 
656*4882a593Smuzhiyun /* Firmware Info */
657*4882a593Smuzhiyun #define MIP4_BL_PAGE_SIZE		512	/* 512 */
658*4882a593Smuzhiyun #define MIP4_BL_PACKET_SIZE		512	/* 512, 256, 128, 64, ... */
659*4882a593Smuzhiyun 
660*4882a593Smuzhiyun /*
661*4882a593Smuzhiyun  * Firmware binary tail info
662*4882a593Smuzhiyun  */
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun struct mip4_bin_tail {
665*4882a593Smuzhiyun 	u8 tail_mark[4];
666*4882a593Smuzhiyun 	u8 chip_name[4];
667*4882a593Smuzhiyun 
668*4882a593Smuzhiyun 	__le32 bin_start_addr;
669*4882a593Smuzhiyun 	__le32 bin_length;
670*4882a593Smuzhiyun 
671*4882a593Smuzhiyun 	__le16 ver_boot;
672*4882a593Smuzhiyun 	__le16 ver_core;
673*4882a593Smuzhiyun 	__le16 ver_app;
674*4882a593Smuzhiyun 	__le16 ver_param;
675*4882a593Smuzhiyun 
676*4882a593Smuzhiyun 	u8 boot_start;
677*4882a593Smuzhiyun 	u8 boot_end;
678*4882a593Smuzhiyun 	u8 core_start;
679*4882a593Smuzhiyun 	u8 core_end;
680*4882a593Smuzhiyun 	u8 app_start;
681*4882a593Smuzhiyun 	u8 app_end;
682*4882a593Smuzhiyun 	u8 param_start;
683*4882a593Smuzhiyun 	u8 param_end;
684*4882a593Smuzhiyun 
685*4882a593Smuzhiyun 	u8 checksum_type;
686*4882a593Smuzhiyun 	u8 hw_category;
687*4882a593Smuzhiyun 
688*4882a593Smuzhiyun 	__le16 param_id;
689*4882a593Smuzhiyun 	__le32 param_length;
690*4882a593Smuzhiyun 	__le32 build_date;
691*4882a593Smuzhiyun 	__le32 build_time;
692*4882a593Smuzhiyun 
693*4882a593Smuzhiyun 	__le32 reserved1;
694*4882a593Smuzhiyun 	__le32 reserved2;
695*4882a593Smuzhiyun 	__le16 reserved3;
696*4882a593Smuzhiyun 	__le16 tail_size;
697*4882a593Smuzhiyun 	__le32 crc;
698*4882a593Smuzhiyun } __packed;
699*4882a593Smuzhiyun 
700*4882a593Smuzhiyun #define MIP4_BIN_TAIL_MARK	"MBT\001"
701*4882a593Smuzhiyun #define MIP4_BIN_TAIL_SIZE	(sizeof(struct mip4_bin_tail))
702*4882a593Smuzhiyun 
703*4882a593Smuzhiyun /*
704*4882a593Smuzhiyun * Bootloader - Read status
705*4882a593Smuzhiyun */
mip4_bl_read_status(struct mip4_ts * ts)706*4882a593Smuzhiyun static int mip4_bl_read_status(struct mip4_ts *ts)
707*4882a593Smuzhiyun {
708*4882a593Smuzhiyun 	u8 cmd[] = { MIP4_R0_BOOT, MIP4_R1_BOOT_STATUS };
709*4882a593Smuzhiyun 	u8 result;
710*4882a593Smuzhiyun 	struct i2c_msg msg[] = {
711*4882a593Smuzhiyun 		{
712*4882a593Smuzhiyun 			.addr = ts->client->addr,
713*4882a593Smuzhiyun 			.flags = 0,
714*4882a593Smuzhiyun 			.buf = cmd,
715*4882a593Smuzhiyun 			.len = sizeof(cmd),
716*4882a593Smuzhiyun 		}, {
717*4882a593Smuzhiyun 			.addr = ts->client->addr,
718*4882a593Smuzhiyun 			.flags = I2C_M_RD,
719*4882a593Smuzhiyun 			.buf = &result,
720*4882a593Smuzhiyun 			.len = sizeof(result),
721*4882a593Smuzhiyun 		},
722*4882a593Smuzhiyun 	};
723*4882a593Smuzhiyun 	int ret;
724*4882a593Smuzhiyun 	int error;
725*4882a593Smuzhiyun 	int retry = 1000;
726*4882a593Smuzhiyun 
727*4882a593Smuzhiyun 	do {
728*4882a593Smuzhiyun 		ret = i2c_transfer(ts->client->adapter, msg, ARRAY_SIZE(msg));
729*4882a593Smuzhiyun 		if (ret != ARRAY_SIZE(msg)) {
730*4882a593Smuzhiyun 			error = ret < 0 ? ret : -EIO;
731*4882a593Smuzhiyun 			dev_err(&ts->client->dev,
732*4882a593Smuzhiyun 				"Failed to read bootloader status: %d\n",
733*4882a593Smuzhiyun 				error);
734*4882a593Smuzhiyun 			return error;
735*4882a593Smuzhiyun 		}
736*4882a593Smuzhiyun 
737*4882a593Smuzhiyun 		switch (result) {
738*4882a593Smuzhiyun 		case MIP4_BOOT_STATUS_DONE:
739*4882a593Smuzhiyun 			dev_dbg(&ts->client->dev, "%s - done\n", __func__);
740*4882a593Smuzhiyun 			return 0;
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun 		case MIP4_BOOT_STATUS_ERROR:
743*4882a593Smuzhiyun 			dev_err(&ts->client->dev, "Bootloader failure\n");
744*4882a593Smuzhiyun 			return -EIO;
745*4882a593Smuzhiyun 
746*4882a593Smuzhiyun 		case MIP4_BOOT_STATUS_BUSY:
747*4882a593Smuzhiyun 			dev_dbg(&ts->client->dev, "%s - Busy\n", __func__);
748*4882a593Smuzhiyun 			error = -EBUSY;
749*4882a593Smuzhiyun 			break;
750*4882a593Smuzhiyun 
751*4882a593Smuzhiyun 		default:
752*4882a593Smuzhiyun 			dev_err(&ts->client->dev,
753*4882a593Smuzhiyun 				"Unexpected bootloader status: %#02x\n",
754*4882a593Smuzhiyun 				result);
755*4882a593Smuzhiyun 			error = -EINVAL;
756*4882a593Smuzhiyun 			break;
757*4882a593Smuzhiyun 		}
758*4882a593Smuzhiyun 
759*4882a593Smuzhiyun 		usleep_range(1000, 2000);
760*4882a593Smuzhiyun 	} while (--retry);
761*4882a593Smuzhiyun 
762*4882a593Smuzhiyun 	return error;
763*4882a593Smuzhiyun }
764*4882a593Smuzhiyun 
765*4882a593Smuzhiyun /*
766*4882a593Smuzhiyun * Bootloader - Change mode
767*4882a593Smuzhiyun */
mip4_bl_change_mode(struct mip4_ts * ts,u8 mode)768*4882a593Smuzhiyun static int mip4_bl_change_mode(struct mip4_ts *ts, u8 mode)
769*4882a593Smuzhiyun {
770*4882a593Smuzhiyun 	u8 mode_chg_cmd[] = { MIP4_R0_BOOT, MIP4_R1_BOOT_MODE, mode };
771*4882a593Smuzhiyun 	u8 mode_read_cmd[] = { MIP4_R0_BOOT, MIP4_R1_BOOT_MODE };
772*4882a593Smuzhiyun 	u8 result;
773*4882a593Smuzhiyun 	struct i2c_msg msg[] = {
774*4882a593Smuzhiyun 		{
775*4882a593Smuzhiyun 			.addr = ts->client->addr,
776*4882a593Smuzhiyun 			.flags = 0,
777*4882a593Smuzhiyun 			.buf = mode_read_cmd,
778*4882a593Smuzhiyun 			.len = sizeof(mode_read_cmd),
779*4882a593Smuzhiyun 		}, {
780*4882a593Smuzhiyun 			.addr = ts->client->addr,
781*4882a593Smuzhiyun 			.flags = I2C_M_RD,
782*4882a593Smuzhiyun 			.buf = &result,
783*4882a593Smuzhiyun 			.len = sizeof(result),
784*4882a593Smuzhiyun 		},
785*4882a593Smuzhiyun 	};
786*4882a593Smuzhiyun 	int retry = 10;
787*4882a593Smuzhiyun 	int ret;
788*4882a593Smuzhiyun 	int error;
789*4882a593Smuzhiyun 
790*4882a593Smuzhiyun 	do {
791*4882a593Smuzhiyun 		/* Send mode change command */
792*4882a593Smuzhiyun 		ret = i2c_master_send(ts->client,
793*4882a593Smuzhiyun 				      mode_chg_cmd, sizeof(mode_chg_cmd));
794*4882a593Smuzhiyun 		if (ret != sizeof(mode_chg_cmd)) {
795*4882a593Smuzhiyun 			error = ret < 0 ? ret : -EIO;
796*4882a593Smuzhiyun 			dev_err(&ts->client->dev,
797*4882a593Smuzhiyun 				"Failed to send %d mode change: %d (%d)\n",
798*4882a593Smuzhiyun 				mode, error, ret);
799*4882a593Smuzhiyun 			return error;
800*4882a593Smuzhiyun 		}
801*4882a593Smuzhiyun 
802*4882a593Smuzhiyun 		dev_dbg(&ts->client->dev,
803*4882a593Smuzhiyun 			"Sent mode change request (mode: %d)\n", mode);
804*4882a593Smuzhiyun 
805*4882a593Smuzhiyun 		/* Wait */
806*4882a593Smuzhiyun 		msleep(1000);
807*4882a593Smuzhiyun 
808*4882a593Smuzhiyun 		/* Verify target mode */
809*4882a593Smuzhiyun 		ret = i2c_transfer(ts->client->adapter, msg, ARRAY_SIZE(msg));
810*4882a593Smuzhiyun 		if (ret != ARRAY_SIZE(msg)) {
811*4882a593Smuzhiyun 			error = ret < 0 ? ret : -EIO;
812*4882a593Smuzhiyun 			dev_err(&ts->client->dev,
813*4882a593Smuzhiyun 				"Failed to read device mode: %d\n", error);
814*4882a593Smuzhiyun 			return error;
815*4882a593Smuzhiyun 		}
816*4882a593Smuzhiyun 
817*4882a593Smuzhiyun 		dev_dbg(&ts->client->dev,
818*4882a593Smuzhiyun 			"Current device mode: %d, want: %d\n", result, mode);
819*4882a593Smuzhiyun 
820*4882a593Smuzhiyun 		if (result == mode)
821*4882a593Smuzhiyun 			return 0;
822*4882a593Smuzhiyun 
823*4882a593Smuzhiyun 	} while (--retry);
824*4882a593Smuzhiyun 
825*4882a593Smuzhiyun 	return -EIO;
826*4882a593Smuzhiyun }
827*4882a593Smuzhiyun 
828*4882a593Smuzhiyun /*
829*4882a593Smuzhiyun  * Bootloader - Start bootloader mode
830*4882a593Smuzhiyun  */
mip4_bl_enter(struct mip4_ts * ts)831*4882a593Smuzhiyun static int mip4_bl_enter(struct mip4_ts *ts)
832*4882a593Smuzhiyun {
833*4882a593Smuzhiyun 	return mip4_bl_change_mode(ts, MIP4_BOOT_MODE_BOOT);
834*4882a593Smuzhiyun }
835*4882a593Smuzhiyun 
836*4882a593Smuzhiyun /*
837*4882a593Smuzhiyun  * Bootloader - Exit bootloader mode
838*4882a593Smuzhiyun  */
mip4_bl_exit(struct mip4_ts * ts)839*4882a593Smuzhiyun static int mip4_bl_exit(struct mip4_ts *ts)
840*4882a593Smuzhiyun {
841*4882a593Smuzhiyun 	return mip4_bl_change_mode(ts, MIP4_BOOT_MODE_APP);
842*4882a593Smuzhiyun }
843*4882a593Smuzhiyun 
mip4_bl_get_address(struct mip4_ts * ts,u16 * buf_addr)844*4882a593Smuzhiyun static int mip4_bl_get_address(struct mip4_ts *ts, u16 *buf_addr)
845*4882a593Smuzhiyun {
846*4882a593Smuzhiyun 	u8 cmd[] = { MIP4_R0_BOOT, MIP4_R1_BOOT_BUF_ADDR };
847*4882a593Smuzhiyun 	u8 result[sizeof(u16)];
848*4882a593Smuzhiyun 	struct i2c_msg msg[] = {
849*4882a593Smuzhiyun 		{
850*4882a593Smuzhiyun 			.addr = ts->client->addr,
851*4882a593Smuzhiyun 			.flags = 0,
852*4882a593Smuzhiyun 			.buf = cmd,
853*4882a593Smuzhiyun 			.len = sizeof(cmd),
854*4882a593Smuzhiyun 		}, {
855*4882a593Smuzhiyun 			.addr = ts->client->addr,
856*4882a593Smuzhiyun 			.flags = I2C_M_RD,
857*4882a593Smuzhiyun 			.buf = result,
858*4882a593Smuzhiyun 			.len = sizeof(result),
859*4882a593Smuzhiyun 		},
860*4882a593Smuzhiyun 	};
861*4882a593Smuzhiyun 	int ret;
862*4882a593Smuzhiyun 	int error;
863*4882a593Smuzhiyun 
864*4882a593Smuzhiyun 	ret = i2c_transfer(ts->client->adapter, msg, ARRAY_SIZE(msg));
865*4882a593Smuzhiyun 	if (ret != ARRAY_SIZE(msg)) {
866*4882a593Smuzhiyun 		error = ret < 0 ? ret : -EIO;
867*4882a593Smuzhiyun 		dev_err(&ts->client->dev,
868*4882a593Smuzhiyun 			"Failed to retrieve bootloader buffer address: %d\n",
869*4882a593Smuzhiyun 			error);
870*4882a593Smuzhiyun 		return error;
871*4882a593Smuzhiyun 	}
872*4882a593Smuzhiyun 
873*4882a593Smuzhiyun 	*buf_addr = get_unaligned_le16(result);
874*4882a593Smuzhiyun 	dev_dbg(&ts->client->dev,
875*4882a593Smuzhiyun 		"Bootloader buffer address %#04x\n", *buf_addr);
876*4882a593Smuzhiyun 
877*4882a593Smuzhiyun 	return 0;
878*4882a593Smuzhiyun }
879*4882a593Smuzhiyun 
mip4_bl_program_page(struct mip4_ts * ts,int offset,const u8 * data,int length,u16 buf_addr)880*4882a593Smuzhiyun static int mip4_bl_program_page(struct mip4_ts *ts, int offset,
881*4882a593Smuzhiyun 				const u8 *data, int length, u16 buf_addr)
882*4882a593Smuzhiyun {
883*4882a593Smuzhiyun 	u8 cmd[6];
884*4882a593Smuzhiyun 	u8 *data_buf;
885*4882a593Smuzhiyun 	u16 buf_offset;
886*4882a593Smuzhiyun 	int ret;
887*4882a593Smuzhiyun 	int error;
888*4882a593Smuzhiyun 
889*4882a593Smuzhiyun 	dev_dbg(&ts->client->dev, "Writing page @%#06x (%d)\n",
890*4882a593Smuzhiyun 		offset, length);
891*4882a593Smuzhiyun 
892*4882a593Smuzhiyun 	if (length > MIP4_BL_PAGE_SIZE || length % MIP4_BL_PACKET_SIZE) {
893*4882a593Smuzhiyun 		dev_err(&ts->client->dev,
894*4882a593Smuzhiyun 			"Invalid page length: %d\n", length);
895*4882a593Smuzhiyun 		return -EINVAL;
896*4882a593Smuzhiyun 	}
897*4882a593Smuzhiyun 
898*4882a593Smuzhiyun 	data_buf = kmalloc(2 + MIP4_BL_PACKET_SIZE, GFP_KERNEL);
899*4882a593Smuzhiyun 	if (!data_buf)
900*4882a593Smuzhiyun 		return -ENOMEM;
901*4882a593Smuzhiyun 
902*4882a593Smuzhiyun 	/* Addr */
903*4882a593Smuzhiyun 	cmd[0] = MIP4_R0_BOOT;
904*4882a593Smuzhiyun 	cmd[1] = MIP4_R1_BOOT_TARGET_ADDR;
905*4882a593Smuzhiyun 	put_unaligned_le32(offset, &cmd[2]);
906*4882a593Smuzhiyun 	ret = i2c_master_send(ts->client, cmd, 6);
907*4882a593Smuzhiyun 	if (ret != 6) {
908*4882a593Smuzhiyun 		error = ret < 0 ? ret : -EIO;
909*4882a593Smuzhiyun 		dev_err(&ts->client->dev,
910*4882a593Smuzhiyun 			"Failed to send write page address: %d\n", error);
911*4882a593Smuzhiyun 		goto out;
912*4882a593Smuzhiyun 	}
913*4882a593Smuzhiyun 
914*4882a593Smuzhiyun 	/* Size */
915*4882a593Smuzhiyun 	cmd[0] = MIP4_R0_BOOT;
916*4882a593Smuzhiyun 	cmd[1] = MIP4_R1_BOOT_SIZE;
917*4882a593Smuzhiyun 	put_unaligned_le32(length, &cmd[2]);
918*4882a593Smuzhiyun 	ret = i2c_master_send(ts->client, cmd, 6);
919*4882a593Smuzhiyun 	if (ret != 6) {
920*4882a593Smuzhiyun 		error = ret < 0 ? ret : -EIO;
921*4882a593Smuzhiyun 		dev_err(&ts->client->dev,
922*4882a593Smuzhiyun 			"Failed to send write page size: %d\n", error);
923*4882a593Smuzhiyun 		goto out;
924*4882a593Smuzhiyun 	}
925*4882a593Smuzhiyun 
926*4882a593Smuzhiyun 	/* Data */
927*4882a593Smuzhiyun 	for (buf_offset = 0;
928*4882a593Smuzhiyun 	     buf_offset < length;
929*4882a593Smuzhiyun 	     buf_offset += MIP4_BL_PACKET_SIZE) {
930*4882a593Smuzhiyun 		dev_dbg(&ts->client->dev,
931*4882a593Smuzhiyun 			"writing chunk at %#04x (size %d)\n",
932*4882a593Smuzhiyun 			buf_offset, MIP4_BL_PACKET_SIZE);
933*4882a593Smuzhiyun 		put_unaligned_be16(buf_addr + buf_offset, data_buf);
934*4882a593Smuzhiyun 		memcpy(&data_buf[2], &data[buf_offset], MIP4_BL_PACKET_SIZE);
935*4882a593Smuzhiyun 		ret = i2c_master_send(ts->client,
936*4882a593Smuzhiyun 				      data_buf, 2 + MIP4_BL_PACKET_SIZE);
937*4882a593Smuzhiyun 		if (ret != 2 + MIP4_BL_PACKET_SIZE) {
938*4882a593Smuzhiyun 			error = ret < 0 ? ret : -EIO;
939*4882a593Smuzhiyun 			dev_err(&ts->client->dev,
940*4882a593Smuzhiyun 				"Failed to read chunk at %#04x (size %d): %d\n",
941*4882a593Smuzhiyun 				buf_offset, MIP4_BL_PACKET_SIZE, error);
942*4882a593Smuzhiyun 			goto out;
943*4882a593Smuzhiyun 		}
944*4882a593Smuzhiyun 	}
945*4882a593Smuzhiyun 
946*4882a593Smuzhiyun 	/* Command */
947*4882a593Smuzhiyun 	cmd[0] = MIP4_R0_BOOT;
948*4882a593Smuzhiyun 	cmd[1] = MIP4_R1_BOOT_CMD;
949*4882a593Smuzhiyun 	cmd[2] = MIP4_BOOT_CMD_PROGRAM;
950*4882a593Smuzhiyun 	ret = i2c_master_send(ts->client, cmd, 3);
951*4882a593Smuzhiyun 	if (ret != 3) {
952*4882a593Smuzhiyun 		error = ret < 0 ? ret : -EIO;
953*4882a593Smuzhiyun 		dev_err(&ts->client->dev,
954*4882a593Smuzhiyun 			"Failed to send 'write' command: %d\n", error);
955*4882a593Smuzhiyun 		goto out;
956*4882a593Smuzhiyun 	}
957*4882a593Smuzhiyun 
958*4882a593Smuzhiyun 	/* Status */
959*4882a593Smuzhiyun 	error = mip4_bl_read_status(ts);
960*4882a593Smuzhiyun 
961*4882a593Smuzhiyun out:
962*4882a593Smuzhiyun 	kfree(data_buf);
963*4882a593Smuzhiyun 	return error ? error : 0;
964*4882a593Smuzhiyun }
965*4882a593Smuzhiyun 
mip4_bl_verify_page(struct mip4_ts * ts,int offset,const u8 * data,int length,int buf_addr)966*4882a593Smuzhiyun static int mip4_bl_verify_page(struct mip4_ts *ts, int offset,
967*4882a593Smuzhiyun 			       const u8 *data, int length, int buf_addr)
968*4882a593Smuzhiyun {
969*4882a593Smuzhiyun 	u8 cmd[8];
970*4882a593Smuzhiyun 	u8 *read_buf;
971*4882a593Smuzhiyun 	int buf_offset;
972*4882a593Smuzhiyun 	struct i2c_msg msg[] = {
973*4882a593Smuzhiyun 		{
974*4882a593Smuzhiyun 			.addr = ts->client->addr,
975*4882a593Smuzhiyun 			.flags = 0,
976*4882a593Smuzhiyun 			.buf = cmd,
977*4882a593Smuzhiyun 			.len = 2,
978*4882a593Smuzhiyun 		}, {
979*4882a593Smuzhiyun 			.addr = ts->client->addr,
980*4882a593Smuzhiyun 			.flags = I2C_M_RD,
981*4882a593Smuzhiyun 			.len = MIP4_BL_PACKET_SIZE,
982*4882a593Smuzhiyun 		},
983*4882a593Smuzhiyun 	};
984*4882a593Smuzhiyun 	int ret;
985*4882a593Smuzhiyun 	int error;
986*4882a593Smuzhiyun 
987*4882a593Smuzhiyun 	dev_dbg(&ts->client->dev, "Validating page @%#06x (%d)\n",
988*4882a593Smuzhiyun 		offset, length);
989*4882a593Smuzhiyun 
990*4882a593Smuzhiyun 	/* Addr */
991*4882a593Smuzhiyun 	cmd[0] = MIP4_R0_BOOT;
992*4882a593Smuzhiyun 	cmd[1] = MIP4_R1_BOOT_TARGET_ADDR;
993*4882a593Smuzhiyun 	put_unaligned_le32(offset, &cmd[2]);
994*4882a593Smuzhiyun 	ret = i2c_master_send(ts->client, cmd, 6);
995*4882a593Smuzhiyun 	if (ret != 6) {
996*4882a593Smuzhiyun 		error = ret < 0 ? ret : -EIO;
997*4882a593Smuzhiyun 		dev_err(&ts->client->dev,
998*4882a593Smuzhiyun 			"Failed to send read page address: %d\n", error);
999*4882a593Smuzhiyun 		return error;
1000*4882a593Smuzhiyun 	}
1001*4882a593Smuzhiyun 
1002*4882a593Smuzhiyun 	/* Size */
1003*4882a593Smuzhiyun 	cmd[0] = MIP4_R0_BOOT;
1004*4882a593Smuzhiyun 	cmd[1] = MIP4_R1_BOOT_SIZE;
1005*4882a593Smuzhiyun 	put_unaligned_le32(length, &cmd[2]);
1006*4882a593Smuzhiyun 	ret = i2c_master_send(ts->client, cmd, 6);
1007*4882a593Smuzhiyun 	if (ret != 6) {
1008*4882a593Smuzhiyun 		error = ret < 0 ? ret : -EIO;
1009*4882a593Smuzhiyun 		dev_err(&ts->client->dev,
1010*4882a593Smuzhiyun 			"Failed to send read page size: %d\n", error);
1011*4882a593Smuzhiyun 		return error;
1012*4882a593Smuzhiyun 	}
1013*4882a593Smuzhiyun 
1014*4882a593Smuzhiyun 	/* Command */
1015*4882a593Smuzhiyun 	cmd[0] = MIP4_R0_BOOT;
1016*4882a593Smuzhiyun 	cmd[1] = MIP4_R1_BOOT_CMD;
1017*4882a593Smuzhiyun 	cmd[2] = MIP4_BOOT_CMD_READ;
1018*4882a593Smuzhiyun 	ret = i2c_master_send(ts->client, cmd, 3);
1019*4882a593Smuzhiyun 	if (ret != 3) {
1020*4882a593Smuzhiyun 		error = ret < 0 ? ret : -EIO;
1021*4882a593Smuzhiyun 		dev_err(&ts->client->dev,
1022*4882a593Smuzhiyun 			"Failed to send 'read' command: %d\n", error);
1023*4882a593Smuzhiyun 		return error;
1024*4882a593Smuzhiyun 	}
1025*4882a593Smuzhiyun 
1026*4882a593Smuzhiyun 	/* Status */
1027*4882a593Smuzhiyun 	error = mip4_bl_read_status(ts);
1028*4882a593Smuzhiyun 	if (error)
1029*4882a593Smuzhiyun 		return error;
1030*4882a593Smuzhiyun 
1031*4882a593Smuzhiyun 	/* Read */
1032*4882a593Smuzhiyun 	msg[1].buf = read_buf = kmalloc(MIP4_BL_PACKET_SIZE, GFP_KERNEL);
1033*4882a593Smuzhiyun 	if (!read_buf)
1034*4882a593Smuzhiyun 		return -ENOMEM;
1035*4882a593Smuzhiyun 
1036*4882a593Smuzhiyun 	for (buf_offset = 0;
1037*4882a593Smuzhiyun 	     buf_offset < length;
1038*4882a593Smuzhiyun 	     buf_offset += MIP4_BL_PACKET_SIZE) {
1039*4882a593Smuzhiyun 		dev_dbg(&ts->client->dev,
1040*4882a593Smuzhiyun 			"reading chunk at %#04x (size %d)\n",
1041*4882a593Smuzhiyun 			buf_offset, MIP4_BL_PACKET_SIZE);
1042*4882a593Smuzhiyun 		put_unaligned_be16(buf_addr + buf_offset, cmd);
1043*4882a593Smuzhiyun 		ret = i2c_transfer(ts->client->adapter, msg, ARRAY_SIZE(msg));
1044*4882a593Smuzhiyun 		if (ret != ARRAY_SIZE(msg)) {
1045*4882a593Smuzhiyun 			error = ret < 0 ? ret : -EIO;
1046*4882a593Smuzhiyun 			dev_err(&ts->client->dev,
1047*4882a593Smuzhiyun 				"Failed to read chunk at %#04x (size %d): %d\n",
1048*4882a593Smuzhiyun 				buf_offset, MIP4_BL_PACKET_SIZE, error);
1049*4882a593Smuzhiyun 			break;
1050*4882a593Smuzhiyun 		}
1051*4882a593Smuzhiyun 
1052*4882a593Smuzhiyun 		if (memcmp(&data[buf_offset], read_buf, MIP4_BL_PACKET_SIZE)) {
1053*4882a593Smuzhiyun 			dev_err(&ts->client->dev,
1054*4882a593Smuzhiyun 				"Failed to validate chunk at %#04x (size %d)\n",
1055*4882a593Smuzhiyun 				buf_offset, MIP4_BL_PACKET_SIZE);
1056*4882a593Smuzhiyun #if MIP4_FW_UPDATE_DEBUG
1057*4882a593Smuzhiyun 			print_hex_dump(KERN_DEBUG,
1058*4882a593Smuzhiyun 				       MIP4_DEVICE_NAME " F/W File: ",
1059*4882a593Smuzhiyun 				       DUMP_PREFIX_OFFSET, 16, 1,
1060*4882a593Smuzhiyun 				       data + offset, MIP4_BL_PACKET_SIZE,
1061*4882a593Smuzhiyun 				       false);
1062*4882a593Smuzhiyun 			print_hex_dump(KERN_DEBUG,
1063*4882a593Smuzhiyun 				       MIP4_DEVICE_NAME " F/W Chip: ",
1064*4882a593Smuzhiyun 				       DUMP_PREFIX_OFFSET, 16, 1,
1065*4882a593Smuzhiyun 				       read_buf, MIP4_BL_PAGE_SIZE, false);
1066*4882a593Smuzhiyun #endif
1067*4882a593Smuzhiyun 			error = -EINVAL;
1068*4882a593Smuzhiyun 			break;
1069*4882a593Smuzhiyun 		}
1070*4882a593Smuzhiyun 	}
1071*4882a593Smuzhiyun 
1072*4882a593Smuzhiyun 	kfree(read_buf);
1073*4882a593Smuzhiyun 	return error ? error : 0;
1074*4882a593Smuzhiyun }
1075*4882a593Smuzhiyun 
1076*4882a593Smuzhiyun /*
1077*4882a593Smuzhiyun  * Flash chip firmware
1078*4882a593Smuzhiyun  */
mip4_flash_fw(struct mip4_ts * ts,const u8 * fw_data,u32 fw_size,u32 fw_offset)1079*4882a593Smuzhiyun static int mip4_flash_fw(struct mip4_ts *ts,
1080*4882a593Smuzhiyun 			 const u8 *fw_data, u32 fw_size, u32 fw_offset)
1081*4882a593Smuzhiyun {
1082*4882a593Smuzhiyun 	struct i2c_client *client = ts->client;
1083*4882a593Smuzhiyun 	int offset;
1084*4882a593Smuzhiyun 	u16 buf_addr;
1085*4882a593Smuzhiyun 	int error, error2;
1086*4882a593Smuzhiyun 
1087*4882a593Smuzhiyun 	/* Enter bootloader mode */
1088*4882a593Smuzhiyun 	dev_dbg(&client->dev, "Entering bootloader mode\n");
1089*4882a593Smuzhiyun 
1090*4882a593Smuzhiyun 	error = mip4_bl_enter(ts);
1091*4882a593Smuzhiyun 	if (error) {
1092*4882a593Smuzhiyun 		dev_err(&client->dev,
1093*4882a593Smuzhiyun 			"Failed to enter bootloader mode: %d\n",
1094*4882a593Smuzhiyun 			error);
1095*4882a593Smuzhiyun 		return error;
1096*4882a593Smuzhiyun 	}
1097*4882a593Smuzhiyun 
1098*4882a593Smuzhiyun 	/* Read info */
1099*4882a593Smuzhiyun 	error = mip4_bl_get_address(ts, &buf_addr);
1100*4882a593Smuzhiyun 	if (error)
1101*4882a593Smuzhiyun 		goto exit_bl;
1102*4882a593Smuzhiyun 
1103*4882a593Smuzhiyun 	/* Program & Verify */
1104*4882a593Smuzhiyun 	dev_dbg(&client->dev,
1105*4882a593Smuzhiyun 		"Program & Verify, page size: %d, packet size: %d\n",
1106*4882a593Smuzhiyun 		MIP4_BL_PAGE_SIZE, MIP4_BL_PACKET_SIZE);
1107*4882a593Smuzhiyun 
1108*4882a593Smuzhiyun 	for (offset = fw_offset;
1109*4882a593Smuzhiyun 	     offset < fw_offset + fw_size;
1110*4882a593Smuzhiyun 	     offset += MIP4_BL_PAGE_SIZE) {
1111*4882a593Smuzhiyun 		/* Program */
1112*4882a593Smuzhiyun 		error = mip4_bl_program_page(ts, offset, fw_data + offset,
1113*4882a593Smuzhiyun 					     MIP4_BL_PAGE_SIZE, buf_addr);
1114*4882a593Smuzhiyun 		if (error)
1115*4882a593Smuzhiyun 			break;
1116*4882a593Smuzhiyun 
1117*4882a593Smuzhiyun 		/* Verify */
1118*4882a593Smuzhiyun 		error = mip4_bl_verify_page(ts, offset, fw_data + offset,
1119*4882a593Smuzhiyun 					    MIP4_BL_PAGE_SIZE, buf_addr);
1120*4882a593Smuzhiyun 		if (error)
1121*4882a593Smuzhiyun 			break;
1122*4882a593Smuzhiyun 	}
1123*4882a593Smuzhiyun 
1124*4882a593Smuzhiyun exit_bl:
1125*4882a593Smuzhiyun 	/* Exit bootloader mode */
1126*4882a593Smuzhiyun 	dev_dbg(&client->dev, "Exiting bootloader mode\n");
1127*4882a593Smuzhiyun 
1128*4882a593Smuzhiyun 	error2 = mip4_bl_exit(ts);
1129*4882a593Smuzhiyun 	if (error2) {
1130*4882a593Smuzhiyun 		dev_err(&client->dev,
1131*4882a593Smuzhiyun 			"Failed to exit bootloader mode: %d\n", error2);
1132*4882a593Smuzhiyun 		if (!error)
1133*4882a593Smuzhiyun 			error = error2;
1134*4882a593Smuzhiyun 	}
1135*4882a593Smuzhiyun 
1136*4882a593Smuzhiyun 	/* Reset chip */
1137*4882a593Smuzhiyun 	mip4_power_off(ts);
1138*4882a593Smuzhiyun 	mip4_power_on(ts);
1139*4882a593Smuzhiyun 
1140*4882a593Smuzhiyun 	mip4_query_device(ts);
1141*4882a593Smuzhiyun 
1142*4882a593Smuzhiyun 	/* Refresh device parameters */
1143*4882a593Smuzhiyun 	input_set_abs_params(ts->input, ABS_MT_POSITION_X, 0, ts->max_x, 0, 0);
1144*4882a593Smuzhiyun 	input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, ts->max_y, 0, 0);
1145*4882a593Smuzhiyun 	input_set_abs_params(ts->input, ABS_X, 0, ts->max_x, 0, 0);
1146*4882a593Smuzhiyun 	input_set_abs_params(ts->input, ABS_Y, 0, ts->max_y, 0, 0);
1147*4882a593Smuzhiyun 	input_abs_set_res(ts->input, ABS_MT_POSITION_X, ts->ppm_x);
1148*4882a593Smuzhiyun 	input_abs_set_res(ts->input, ABS_MT_POSITION_Y, ts->ppm_y);
1149*4882a593Smuzhiyun 	input_abs_set_res(ts->input, ABS_X, ts->ppm_x);
1150*4882a593Smuzhiyun 	input_abs_set_res(ts->input, ABS_Y, ts->ppm_y);
1151*4882a593Smuzhiyun 
1152*4882a593Smuzhiyun 	return error ? error : 0;
1153*4882a593Smuzhiyun }
1154*4882a593Smuzhiyun 
mip4_parse_firmware(struct mip4_ts * ts,const struct firmware * fw,u32 * fw_offset_start,u32 * fw_size,const struct mip4_bin_tail ** pfw_info)1155*4882a593Smuzhiyun static int mip4_parse_firmware(struct mip4_ts *ts, const struct firmware *fw,
1156*4882a593Smuzhiyun 			       u32 *fw_offset_start, u32 *fw_size,
1157*4882a593Smuzhiyun 			       const struct mip4_bin_tail **pfw_info)
1158*4882a593Smuzhiyun {
1159*4882a593Smuzhiyun 	const struct mip4_bin_tail *fw_info;
1160*4882a593Smuzhiyun 	struct mip4_fw_version fw_version;
1161*4882a593Smuzhiyun 	u16 tail_size;
1162*4882a593Smuzhiyun 
1163*4882a593Smuzhiyun 	if (fw->size < MIP4_BIN_TAIL_SIZE) {
1164*4882a593Smuzhiyun 		dev_err(&ts->client->dev,
1165*4882a593Smuzhiyun 			"Invalid firmware, size mismatch (tail %zd vs %zd)\n",
1166*4882a593Smuzhiyun 			MIP4_BIN_TAIL_SIZE, fw->size);
1167*4882a593Smuzhiyun 		return -EINVAL;
1168*4882a593Smuzhiyun 	}
1169*4882a593Smuzhiyun 
1170*4882a593Smuzhiyun 	fw_info = (const void *)&fw->data[fw->size - MIP4_BIN_TAIL_SIZE];
1171*4882a593Smuzhiyun 
1172*4882a593Smuzhiyun #if MIP4_FW_UPDATE_DEBUG
1173*4882a593Smuzhiyun 	print_hex_dump(KERN_ERR, MIP4_DEVICE_NAME " Bin Info: ",
1174*4882a593Smuzhiyun 		       DUMP_PREFIX_OFFSET, 16, 1, *fw_info, tail_size, false);
1175*4882a593Smuzhiyun #endif
1176*4882a593Smuzhiyun 
1177*4882a593Smuzhiyun 	tail_size = get_unaligned_le16(&fw_info->tail_size);
1178*4882a593Smuzhiyun 	if (tail_size != MIP4_BIN_TAIL_SIZE) {
1179*4882a593Smuzhiyun 		dev_err(&ts->client->dev,
1180*4882a593Smuzhiyun 			"wrong tail size: %d (expected %zd)\n",
1181*4882a593Smuzhiyun 			tail_size, MIP4_BIN_TAIL_SIZE);
1182*4882a593Smuzhiyun 		return -EINVAL;
1183*4882a593Smuzhiyun 	}
1184*4882a593Smuzhiyun 
1185*4882a593Smuzhiyun 	/* Check bin format */
1186*4882a593Smuzhiyun 	if (memcmp(fw_info->tail_mark, MIP4_BIN_TAIL_MARK,
1187*4882a593Smuzhiyun 		   sizeof(fw_info->tail_mark))) {
1188*4882a593Smuzhiyun 		dev_err(&ts->client->dev,
1189*4882a593Smuzhiyun 			"unable to locate tail marker (%*ph vs %*ph)\n",
1190*4882a593Smuzhiyun 			(int)sizeof(fw_info->tail_mark), fw_info->tail_mark,
1191*4882a593Smuzhiyun 			(int)sizeof(fw_info->tail_mark), MIP4_BIN_TAIL_MARK);
1192*4882a593Smuzhiyun 		return -EINVAL;
1193*4882a593Smuzhiyun 	}
1194*4882a593Smuzhiyun 
1195*4882a593Smuzhiyun 	*fw_offset_start = get_unaligned_le32(&fw_info->bin_start_addr);
1196*4882a593Smuzhiyun 	*fw_size = get_unaligned_le32(&fw_info->bin_length);
1197*4882a593Smuzhiyun 
1198*4882a593Smuzhiyun 	dev_dbg(&ts->client->dev,
1199*4882a593Smuzhiyun 		"F/W Data offset: %#08x, size: %d\n",
1200*4882a593Smuzhiyun 		*fw_offset_start, *fw_size);
1201*4882a593Smuzhiyun 
1202*4882a593Smuzhiyun 	if (*fw_size % MIP4_BL_PAGE_SIZE) {
1203*4882a593Smuzhiyun 		dev_err(&ts->client->dev,
1204*4882a593Smuzhiyun 			"encoded fw length %d is not multiple of pages (%d)\n",
1205*4882a593Smuzhiyun 			*fw_size, MIP4_BL_PAGE_SIZE);
1206*4882a593Smuzhiyun 		return -EINVAL;
1207*4882a593Smuzhiyun 	}
1208*4882a593Smuzhiyun 
1209*4882a593Smuzhiyun 	if (fw->size != *fw_offset_start + *fw_size) {
1210*4882a593Smuzhiyun 		dev_err(&ts->client->dev,
1211*4882a593Smuzhiyun 			"Wrong firmware size, expected %d bytes, got %zd\n",
1212*4882a593Smuzhiyun 			*fw_offset_start + *fw_size, fw->size);
1213*4882a593Smuzhiyun 		return -EINVAL;
1214*4882a593Smuzhiyun 	}
1215*4882a593Smuzhiyun 
1216*4882a593Smuzhiyun 	mip4_parse_fw_version((const u8 *)&fw_info->ver_boot, &fw_version);
1217*4882a593Smuzhiyun 
1218*4882a593Smuzhiyun 	dev_dbg(&ts->client->dev,
1219*4882a593Smuzhiyun 		"F/W file version %04X %04X %04X %04X\n",
1220*4882a593Smuzhiyun 		fw_version.boot, fw_version.core,
1221*4882a593Smuzhiyun 		fw_version.app, fw_version.param);
1222*4882a593Smuzhiyun 
1223*4882a593Smuzhiyun 	dev_dbg(&ts->client->dev, "F/W chip version: %04X %04X %04X %04X\n",
1224*4882a593Smuzhiyun 		 ts->fw_version.boot, ts->fw_version.core,
1225*4882a593Smuzhiyun 		 ts->fw_version.app, ts->fw_version.param);
1226*4882a593Smuzhiyun 
1227*4882a593Smuzhiyun 	/* Check F/W type */
1228*4882a593Smuzhiyun 	if (fw_version.boot != 0xEEEE && fw_version.boot != 0xFFFF &&
1229*4882a593Smuzhiyun 	    fw_version.core == 0xEEEE &&
1230*4882a593Smuzhiyun 	    fw_version.app == 0xEEEE &&
1231*4882a593Smuzhiyun 	    fw_version.param == 0xEEEE) {
1232*4882a593Smuzhiyun 		dev_dbg(&ts->client->dev, "F/W type: Bootloader\n");
1233*4882a593Smuzhiyun 	} else if (fw_version.boot == 0xEEEE &&
1234*4882a593Smuzhiyun 		   fw_version.core != 0xEEEE && fw_version.core != 0xFFFF &&
1235*4882a593Smuzhiyun 		   fw_version.app != 0xEEEE && fw_version.app != 0xFFFF &&
1236*4882a593Smuzhiyun 		   fw_version.param != 0xEEEE && fw_version.param != 0xFFFF) {
1237*4882a593Smuzhiyun 		dev_dbg(&ts->client->dev, "F/W type: Main\n");
1238*4882a593Smuzhiyun 	} else {
1239*4882a593Smuzhiyun 		dev_err(&ts->client->dev, "Wrong firmware type\n");
1240*4882a593Smuzhiyun 		return -EINVAL;
1241*4882a593Smuzhiyun 	}
1242*4882a593Smuzhiyun 
1243*4882a593Smuzhiyun 	return 0;
1244*4882a593Smuzhiyun }
1245*4882a593Smuzhiyun 
mip4_execute_fw_update(struct mip4_ts * ts,const struct firmware * fw)1246*4882a593Smuzhiyun static int mip4_execute_fw_update(struct mip4_ts *ts, const struct firmware *fw)
1247*4882a593Smuzhiyun {
1248*4882a593Smuzhiyun 	const struct mip4_bin_tail *fw_info;
1249*4882a593Smuzhiyun 	u32 fw_start_offset;
1250*4882a593Smuzhiyun 	u32 fw_size;
1251*4882a593Smuzhiyun 	int retires = 3;
1252*4882a593Smuzhiyun 	int error;
1253*4882a593Smuzhiyun 
1254*4882a593Smuzhiyun 	error = mip4_parse_firmware(ts, fw,
1255*4882a593Smuzhiyun 				    &fw_start_offset, &fw_size, &fw_info);
1256*4882a593Smuzhiyun 	if (error)
1257*4882a593Smuzhiyun 		return error;
1258*4882a593Smuzhiyun 
1259*4882a593Smuzhiyun 	if (ts->input->users) {
1260*4882a593Smuzhiyun 		disable_irq(ts->client->irq);
1261*4882a593Smuzhiyun 	} else {
1262*4882a593Smuzhiyun 		error = mip4_power_on(ts);
1263*4882a593Smuzhiyun 		if (error)
1264*4882a593Smuzhiyun 			return error;
1265*4882a593Smuzhiyun 	}
1266*4882a593Smuzhiyun 
1267*4882a593Smuzhiyun 	/* Update firmware */
1268*4882a593Smuzhiyun 	do {
1269*4882a593Smuzhiyun 		error = mip4_flash_fw(ts, fw->data, fw_size, fw_start_offset);
1270*4882a593Smuzhiyun 		if (!error)
1271*4882a593Smuzhiyun 			break;
1272*4882a593Smuzhiyun 	} while (--retires);
1273*4882a593Smuzhiyun 
1274*4882a593Smuzhiyun 	if (error)
1275*4882a593Smuzhiyun 		dev_err(&ts->client->dev,
1276*4882a593Smuzhiyun 			"Failed to flash firmware: %d\n", error);
1277*4882a593Smuzhiyun 
1278*4882a593Smuzhiyun 	/* Enable IRQ */
1279*4882a593Smuzhiyun 	if (ts->input->users)
1280*4882a593Smuzhiyun 		enable_irq(ts->client->irq);
1281*4882a593Smuzhiyun 	else
1282*4882a593Smuzhiyun 		mip4_power_off(ts);
1283*4882a593Smuzhiyun 
1284*4882a593Smuzhiyun 	return error ? error : 0;
1285*4882a593Smuzhiyun }
1286*4882a593Smuzhiyun 
mip4_sysfs_fw_update(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1287*4882a593Smuzhiyun static ssize_t mip4_sysfs_fw_update(struct device *dev,
1288*4882a593Smuzhiyun 				    struct device_attribute *attr,
1289*4882a593Smuzhiyun 				    const char *buf, size_t count)
1290*4882a593Smuzhiyun {
1291*4882a593Smuzhiyun 	struct i2c_client *client = to_i2c_client(dev);
1292*4882a593Smuzhiyun 	struct mip4_ts *ts = i2c_get_clientdata(client);
1293*4882a593Smuzhiyun 	const struct firmware *fw;
1294*4882a593Smuzhiyun 	int error;
1295*4882a593Smuzhiyun 
1296*4882a593Smuzhiyun 	error = request_firmware(&fw, ts->fw_name, dev);
1297*4882a593Smuzhiyun 	if (error) {
1298*4882a593Smuzhiyun 		dev_err(&ts->client->dev,
1299*4882a593Smuzhiyun 			"Failed to retrieve firmware %s: %d\n",
1300*4882a593Smuzhiyun 			ts->fw_name, error);
1301*4882a593Smuzhiyun 		return error;
1302*4882a593Smuzhiyun 	}
1303*4882a593Smuzhiyun 
1304*4882a593Smuzhiyun 	/*
1305*4882a593Smuzhiyun 	 * Take input mutex to prevent racing with itself and also with
1306*4882a593Smuzhiyun 	 * userspace opening and closing the device and also suspend/resume
1307*4882a593Smuzhiyun 	 * transitions.
1308*4882a593Smuzhiyun 	 */
1309*4882a593Smuzhiyun 	mutex_lock(&ts->input->mutex);
1310*4882a593Smuzhiyun 
1311*4882a593Smuzhiyun 	error = mip4_execute_fw_update(ts, fw);
1312*4882a593Smuzhiyun 
1313*4882a593Smuzhiyun 	mutex_unlock(&ts->input->mutex);
1314*4882a593Smuzhiyun 
1315*4882a593Smuzhiyun 	release_firmware(fw);
1316*4882a593Smuzhiyun 
1317*4882a593Smuzhiyun 	if (error) {
1318*4882a593Smuzhiyun 		dev_err(&ts->client->dev,
1319*4882a593Smuzhiyun 			"Firmware update failed: %d\n", error);
1320*4882a593Smuzhiyun 		return error;
1321*4882a593Smuzhiyun 	}
1322*4882a593Smuzhiyun 
1323*4882a593Smuzhiyun 	return count;
1324*4882a593Smuzhiyun }
1325*4882a593Smuzhiyun 
1326*4882a593Smuzhiyun static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mip4_sysfs_fw_update);
1327*4882a593Smuzhiyun 
mip4_sysfs_read_fw_version(struct device * dev,struct device_attribute * attr,char * buf)1328*4882a593Smuzhiyun static ssize_t mip4_sysfs_read_fw_version(struct device *dev,
1329*4882a593Smuzhiyun 					  struct device_attribute *attr,
1330*4882a593Smuzhiyun 					  char *buf)
1331*4882a593Smuzhiyun {
1332*4882a593Smuzhiyun 	struct i2c_client *client = to_i2c_client(dev);
1333*4882a593Smuzhiyun 	struct mip4_ts *ts = i2c_get_clientdata(client);
1334*4882a593Smuzhiyun 	size_t count;
1335*4882a593Smuzhiyun 
1336*4882a593Smuzhiyun 	/* Take lock to prevent racing with firmware update */
1337*4882a593Smuzhiyun 	mutex_lock(&ts->input->mutex);
1338*4882a593Smuzhiyun 
1339*4882a593Smuzhiyun 	count = snprintf(buf, PAGE_SIZE, "%04X %04X %04X %04X\n",
1340*4882a593Smuzhiyun 			 ts->fw_version.boot, ts->fw_version.core,
1341*4882a593Smuzhiyun 			 ts->fw_version.app, ts->fw_version.param);
1342*4882a593Smuzhiyun 
1343*4882a593Smuzhiyun 	mutex_unlock(&ts->input->mutex);
1344*4882a593Smuzhiyun 
1345*4882a593Smuzhiyun 	return count;
1346*4882a593Smuzhiyun }
1347*4882a593Smuzhiyun 
1348*4882a593Smuzhiyun static DEVICE_ATTR(fw_version, S_IRUGO, mip4_sysfs_read_fw_version, NULL);
1349*4882a593Smuzhiyun 
mip4_sysfs_read_hw_version(struct device * dev,struct device_attribute * attr,char * buf)1350*4882a593Smuzhiyun static ssize_t mip4_sysfs_read_hw_version(struct device *dev,
1351*4882a593Smuzhiyun 					  struct device_attribute *attr,
1352*4882a593Smuzhiyun 					  char *buf)
1353*4882a593Smuzhiyun {
1354*4882a593Smuzhiyun 	struct i2c_client *client = to_i2c_client(dev);
1355*4882a593Smuzhiyun 	struct mip4_ts *ts = i2c_get_clientdata(client);
1356*4882a593Smuzhiyun 	size_t count;
1357*4882a593Smuzhiyun 
1358*4882a593Smuzhiyun 	/* Take lock to prevent racing with firmware update */
1359*4882a593Smuzhiyun 	mutex_lock(&ts->input->mutex);
1360*4882a593Smuzhiyun 
1361*4882a593Smuzhiyun 	/*
1362*4882a593Smuzhiyun 	 * product_name shows the name or version of the hardware
1363*4882a593Smuzhiyun 	 * paired with current firmware in the chip.
1364*4882a593Smuzhiyun 	 */
1365*4882a593Smuzhiyun 	count = snprintf(buf, PAGE_SIZE, "%.*s\n",
1366*4882a593Smuzhiyun 			 (int)sizeof(ts->product_name), ts->product_name);
1367*4882a593Smuzhiyun 
1368*4882a593Smuzhiyun 	mutex_unlock(&ts->input->mutex);
1369*4882a593Smuzhiyun 
1370*4882a593Smuzhiyun 	return count;
1371*4882a593Smuzhiyun }
1372*4882a593Smuzhiyun 
1373*4882a593Smuzhiyun static DEVICE_ATTR(hw_version, S_IRUGO, mip4_sysfs_read_hw_version, NULL);
1374*4882a593Smuzhiyun 
mip4_sysfs_read_product_id(struct device * dev,struct device_attribute * attr,char * buf)1375*4882a593Smuzhiyun static ssize_t mip4_sysfs_read_product_id(struct device *dev,
1376*4882a593Smuzhiyun 					  struct device_attribute *attr,
1377*4882a593Smuzhiyun 					  char *buf)
1378*4882a593Smuzhiyun {
1379*4882a593Smuzhiyun 	struct i2c_client *client = to_i2c_client(dev);
1380*4882a593Smuzhiyun 	struct mip4_ts *ts = i2c_get_clientdata(client);
1381*4882a593Smuzhiyun 	size_t count;
1382*4882a593Smuzhiyun 
1383*4882a593Smuzhiyun 	mutex_lock(&ts->input->mutex);
1384*4882a593Smuzhiyun 
1385*4882a593Smuzhiyun 	count = snprintf(buf, PAGE_SIZE, "%04X\n", ts->product_id);
1386*4882a593Smuzhiyun 
1387*4882a593Smuzhiyun 	mutex_unlock(&ts->input->mutex);
1388*4882a593Smuzhiyun 
1389*4882a593Smuzhiyun 	return count;
1390*4882a593Smuzhiyun }
1391*4882a593Smuzhiyun 
1392*4882a593Smuzhiyun static DEVICE_ATTR(product_id, S_IRUGO, mip4_sysfs_read_product_id, NULL);
1393*4882a593Smuzhiyun 
mip4_sysfs_read_ic_name(struct device * dev,struct device_attribute * attr,char * buf)1394*4882a593Smuzhiyun static ssize_t mip4_sysfs_read_ic_name(struct device *dev,
1395*4882a593Smuzhiyun 					  struct device_attribute *attr,
1396*4882a593Smuzhiyun 					  char *buf)
1397*4882a593Smuzhiyun {
1398*4882a593Smuzhiyun 	struct i2c_client *client = to_i2c_client(dev);
1399*4882a593Smuzhiyun 	struct mip4_ts *ts = i2c_get_clientdata(client);
1400*4882a593Smuzhiyun 	size_t count;
1401*4882a593Smuzhiyun 
1402*4882a593Smuzhiyun 	mutex_lock(&ts->input->mutex);
1403*4882a593Smuzhiyun 
1404*4882a593Smuzhiyun 	count = snprintf(buf, PAGE_SIZE, "%.*s\n",
1405*4882a593Smuzhiyun 			 (int)sizeof(ts->ic_name), ts->ic_name);
1406*4882a593Smuzhiyun 
1407*4882a593Smuzhiyun 	mutex_unlock(&ts->input->mutex);
1408*4882a593Smuzhiyun 
1409*4882a593Smuzhiyun 	return count;
1410*4882a593Smuzhiyun }
1411*4882a593Smuzhiyun 
1412*4882a593Smuzhiyun static DEVICE_ATTR(ic_name, S_IRUGO, mip4_sysfs_read_ic_name, NULL);
1413*4882a593Smuzhiyun 
1414*4882a593Smuzhiyun static struct attribute *mip4_attrs[] = {
1415*4882a593Smuzhiyun 	&dev_attr_fw_version.attr,
1416*4882a593Smuzhiyun 	&dev_attr_hw_version.attr,
1417*4882a593Smuzhiyun 	&dev_attr_product_id.attr,
1418*4882a593Smuzhiyun 	&dev_attr_ic_name.attr,
1419*4882a593Smuzhiyun 	&dev_attr_update_fw.attr,
1420*4882a593Smuzhiyun 	NULL,
1421*4882a593Smuzhiyun };
1422*4882a593Smuzhiyun 
1423*4882a593Smuzhiyun static const struct attribute_group mip4_attr_group = {
1424*4882a593Smuzhiyun 	.attrs = mip4_attrs,
1425*4882a593Smuzhiyun };
1426*4882a593Smuzhiyun 
mip4_probe(struct i2c_client * client,const struct i2c_device_id * id)1427*4882a593Smuzhiyun static int mip4_probe(struct i2c_client *client, const struct i2c_device_id *id)
1428*4882a593Smuzhiyun {
1429*4882a593Smuzhiyun 	struct mip4_ts *ts;
1430*4882a593Smuzhiyun 	struct input_dev *input;
1431*4882a593Smuzhiyun 	int error;
1432*4882a593Smuzhiyun 
1433*4882a593Smuzhiyun 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
1434*4882a593Smuzhiyun 		dev_err(&client->dev, "Not supported I2C adapter\n");
1435*4882a593Smuzhiyun 		return -ENXIO;
1436*4882a593Smuzhiyun 	}
1437*4882a593Smuzhiyun 
1438*4882a593Smuzhiyun 	ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
1439*4882a593Smuzhiyun 	if (!ts)
1440*4882a593Smuzhiyun 		return -ENOMEM;
1441*4882a593Smuzhiyun 
1442*4882a593Smuzhiyun 	input = devm_input_allocate_device(&client->dev);
1443*4882a593Smuzhiyun 	if (!input)
1444*4882a593Smuzhiyun 		return -ENOMEM;
1445*4882a593Smuzhiyun 
1446*4882a593Smuzhiyun 	ts->client = client;
1447*4882a593Smuzhiyun 	ts->input = input;
1448*4882a593Smuzhiyun 
1449*4882a593Smuzhiyun 	snprintf(ts->phys, sizeof(ts->phys),
1450*4882a593Smuzhiyun 		 "%s/input0", dev_name(&client->dev));
1451*4882a593Smuzhiyun 
1452*4882a593Smuzhiyun 	ts->gpio_ce = devm_gpiod_get_optional(&client->dev,
1453*4882a593Smuzhiyun 					      "ce", GPIOD_OUT_LOW);
1454*4882a593Smuzhiyun 	if (IS_ERR(ts->gpio_ce)) {
1455*4882a593Smuzhiyun 		error = PTR_ERR(ts->gpio_ce);
1456*4882a593Smuzhiyun 		if (error != -EPROBE_DEFER)
1457*4882a593Smuzhiyun 			dev_err(&client->dev,
1458*4882a593Smuzhiyun 				"Failed to get gpio: %d\n", error);
1459*4882a593Smuzhiyun 		return error;
1460*4882a593Smuzhiyun 	}
1461*4882a593Smuzhiyun 
1462*4882a593Smuzhiyun 	error = mip4_power_on(ts);
1463*4882a593Smuzhiyun 	if (error)
1464*4882a593Smuzhiyun 		return error;
1465*4882a593Smuzhiyun 	error = mip4_query_device(ts);
1466*4882a593Smuzhiyun 	mip4_power_off(ts);
1467*4882a593Smuzhiyun 	if (error)
1468*4882a593Smuzhiyun 		return error;
1469*4882a593Smuzhiyun 
1470*4882a593Smuzhiyun 	input->name = "MELFAS MIP4 Touchscreen";
1471*4882a593Smuzhiyun 	input->phys = ts->phys;
1472*4882a593Smuzhiyun 
1473*4882a593Smuzhiyun 	input->id.bustype = BUS_I2C;
1474*4882a593Smuzhiyun 	input->id.vendor = 0x13c5;
1475*4882a593Smuzhiyun 	input->id.product = ts->product_id;
1476*4882a593Smuzhiyun 
1477*4882a593Smuzhiyun 	input->open = mip4_input_open;
1478*4882a593Smuzhiyun 	input->close = mip4_input_close;
1479*4882a593Smuzhiyun 
1480*4882a593Smuzhiyun 	input_set_drvdata(input, ts);
1481*4882a593Smuzhiyun 
1482*4882a593Smuzhiyun 	input->keycode = ts->key_code;
1483*4882a593Smuzhiyun 	input->keycodesize = sizeof(*ts->key_code);
1484*4882a593Smuzhiyun 	input->keycodemax = ts->key_num;
1485*4882a593Smuzhiyun 
1486*4882a593Smuzhiyun 	input_set_abs_params(input, ABS_MT_POSITION_X, 0, ts->max_x, 0, 0);
1487*4882a593Smuzhiyun 	input_set_abs_params(input, ABS_MT_POSITION_Y, 0, ts->max_y, 0, 0);
1488*4882a593Smuzhiyun 	input_set_abs_params(input, ABS_MT_PRESSURE,
1489*4882a593Smuzhiyun 			     MIP4_PRESSURE_MIN, MIP4_PRESSURE_MAX, 0, 0);
1490*4882a593Smuzhiyun 	input_set_abs_params(input, ABS_MT_TOUCH_MAJOR,
1491*4882a593Smuzhiyun 			     MIP4_TOUCH_MAJOR_MIN, MIP4_TOUCH_MAJOR_MAX, 0, 0);
1492*4882a593Smuzhiyun 	input_set_abs_params(input, ABS_MT_TOUCH_MINOR,
1493*4882a593Smuzhiyun 			     MIP4_TOUCH_MINOR_MIN, MIP4_TOUCH_MINOR_MAX, 0, 0);
1494*4882a593Smuzhiyun 	input_abs_set_res(ts->input, ABS_MT_POSITION_X, ts->ppm_x);
1495*4882a593Smuzhiyun 	input_abs_set_res(ts->input, ABS_MT_POSITION_Y, ts->ppm_y);
1496*4882a593Smuzhiyun 
1497*4882a593Smuzhiyun 	error = input_mt_init_slots(input, MIP4_MAX_FINGERS, INPUT_MT_DIRECT);
1498*4882a593Smuzhiyun 	if (error)
1499*4882a593Smuzhiyun 		return error;
1500*4882a593Smuzhiyun 
1501*4882a593Smuzhiyun 	i2c_set_clientdata(client, ts);
1502*4882a593Smuzhiyun 
1503*4882a593Smuzhiyun 	error = devm_request_threaded_irq(&client->dev, client->irq,
1504*4882a593Smuzhiyun 					  NULL, mip4_interrupt,
1505*4882a593Smuzhiyun 					  IRQF_ONESHOT, MIP4_DEVICE_NAME, ts);
1506*4882a593Smuzhiyun 	if (error) {
1507*4882a593Smuzhiyun 		dev_err(&client->dev,
1508*4882a593Smuzhiyun 			"Failed to request interrupt %d: %d\n",
1509*4882a593Smuzhiyun 			client->irq, error);
1510*4882a593Smuzhiyun 		return error;
1511*4882a593Smuzhiyun 	}
1512*4882a593Smuzhiyun 
1513*4882a593Smuzhiyun 	disable_irq(client->irq);
1514*4882a593Smuzhiyun 
1515*4882a593Smuzhiyun 	error = input_register_device(input);
1516*4882a593Smuzhiyun 	if (error) {
1517*4882a593Smuzhiyun 		dev_err(&client->dev,
1518*4882a593Smuzhiyun 			"Failed to register input device: %d\n", error);
1519*4882a593Smuzhiyun 		return error;
1520*4882a593Smuzhiyun 	}
1521*4882a593Smuzhiyun 
1522*4882a593Smuzhiyun 	error = devm_device_add_group(&client->dev, &mip4_attr_group);
1523*4882a593Smuzhiyun 	if (error) {
1524*4882a593Smuzhiyun 		dev_err(&client->dev,
1525*4882a593Smuzhiyun 			"Failed to create sysfs attribute group: %d\n", error);
1526*4882a593Smuzhiyun 		return error;
1527*4882a593Smuzhiyun 	}
1528*4882a593Smuzhiyun 
1529*4882a593Smuzhiyun 	return 0;
1530*4882a593Smuzhiyun }
1531*4882a593Smuzhiyun 
mip4_suspend(struct device * dev)1532*4882a593Smuzhiyun static int __maybe_unused mip4_suspend(struct device *dev)
1533*4882a593Smuzhiyun {
1534*4882a593Smuzhiyun 	struct i2c_client *client = to_i2c_client(dev);
1535*4882a593Smuzhiyun 	struct mip4_ts *ts = i2c_get_clientdata(client);
1536*4882a593Smuzhiyun 	struct input_dev *input = ts->input;
1537*4882a593Smuzhiyun 
1538*4882a593Smuzhiyun 	mutex_lock(&input->mutex);
1539*4882a593Smuzhiyun 
1540*4882a593Smuzhiyun 	if (device_may_wakeup(dev))
1541*4882a593Smuzhiyun 		ts->wake_irq_enabled = enable_irq_wake(client->irq) == 0;
1542*4882a593Smuzhiyun 	else if (input->users)
1543*4882a593Smuzhiyun 		mip4_disable(ts);
1544*4882a593Smuzhiyun 
1545*4882a593Smuzhiyun 	mutex_unlock(&input->mutex);
1546*4882a593Smuzhiyun 
1547*4882a593Smuzhiyun 	return 0;
1548*4882a593Smuzhiyun }
1549*4882a593Smuzhiyun 
mip4_resume(struct device * dev)1550*4882a593Smuzhiyun static int __maybe_unused mip4_resume(struct device *dev)
1551*4882a593Smuzhiyun {
1552*4882a593Smuzhiyun 	struct i2c_client *client = to_i2c_client(dev);
1553*4882a593Smuzhiyun 	struct mip4_ts *ts = i2c_get_clientdata(client);
1554*4882a593Smuzhiyun 	struct input_dev *input = ts->input;
1555*4882a593Smuzhiyun 
1556*4882a593Smuzhiyun 	mutex_lock(&input->mutex);
1557*4882a593Smuzhiyun 
1558*4882a593Smuzhiyun 	if (ts->wake_irq_enabled)
1559*4882a593Smuzhiyun 		disable_irq_wake(client->irq);
1560*4882a593Smuzhiyun 	else if (input->users)
1561*4882a593Smuzhiyun 		mip4_enable(ts);
1562*4882a593Smuzhiyun 
1563*4882a593Smuzhiyun 	mutex_unlock(&input->mutex);
1564*4882a593Smuzhiyun 
1565*4882a593Smuzhiyun 	return 0;
1566*4882a593Smuzhiyun }
1567*4882a593Smuzhiyun 
1568*4882a593Smuzhiyun static SIMPLE_DEV_PM_OPS(mip4_pm_ops, mip4_suspend, mip4_resume);
1569*4882a593Smuzhiyun 
1570*4882a593Smuzhiyun #ifdef CONFIG_OF
1571*4882a593Smuzhiyun static const struct of_device_id mip4_of_match[] = {
1572*4882a593Smuzhiyun 	{ .compatible = "melfas,"MIP4_DEVICE_NAME, },
1573*4882a593Smuzhiyun 	{ },
1574*4882a593Smuzhiyun };
1575*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, mip4_of_match);
1576*4882a593Smuzhiyun #endif
1577*4882a593Smuzhiyun 
1578*4882a593Smuzhiyun #ifdef CONFIG_ACPI
1579*4882a593Smuzhiyun static const struct acpi_device_id mip4_acpi_match[] = {
1580*4882a593Smuzhiyun 	{ "MLFS0000", 0},
1581*4882a593Smuzhiyun 	{ },
1582*4882a593Smuzhiyun };
1583*4882a593Smuzhiyun MODULE_DEVICE_TABLE(acpi, mip4_acpi_match);
1584*4882a593Smuzhiyun #endif
1585*4882a593Smuzhiyun 
1586*4882a593Smuzhiyun static const struct i2c_device_id mip4_i2c_ids[] = {
1587*4882a593Smuzhiyun 	{ MIP4_DEVICE_NAME, 0 },
1588*4882a593Smuzhiyun 	{ },
1589*4882a593Smuzhiyun };
1590*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, mip4_i2c_ids);
1591*4882a593Smuzhiyun 
1592*4882a593Smuzhiyun static struct i2c_driver mip4_driver = {
1593*4882a593Smuzhiyun 	.id_table = mip4_i2c_ids,
1594*4882a593Smuzhiyun 	.probe = mip4_probe,
1595*4882a593Smuzhiyun 	.driver = {
1596*4882a593Smuzhiyun 		.name = MIP4_DEVICE_NAME,
1597*4882a593Smuzhiyun 		.of_match_table = of_match_ptr(mip4_of_match),
1598*4882a593Smuzhiyun 		.acpi_match_table = ACPI_PTR(mip4_acpi_match),
1599*4882a593Smuzhiyun 		.pm = &mip4_pm_ops,
1600*4882a593Smuzhiyun 	},
1601*4882a593Smuzhiyun };
1602*4882a593Smuzhiyun module_i2c_driver(mip4_driver);
1603*4882a593Smuzhiyun 
1604*4882a593Smuzhiyun MODULE_DESCRIPTION("MELFAS MIP4 Touchscreen");
1605*4882a593Smuzhiyun MODULE_AUTHOR("Sangwon Jee <jeesw@melfas.com>");
1606*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1607