xref: /openbmc/linux/drivers/input/mouse/elan_i2c_smbus.c (revision 6696777c6506fa52b2a0282121195843ed855be6)
1*6696777cSDuson Lin /*
2*6696777cSDuson Lin  * Elan I2C/SMBus Touchpad driver - SMBus interface
3*6696777cSDuson Lin  *
4*6696777cSDuson Lin  * Copyright (c) 2013 ELAN Microelectronics Corp.
5*6696777cSDuson Lin  *
6*6696777cSDuson Lin  * Author: 林政維 (Duson Lin) <dusonlin@emc.com.tw>
7*6696777cSDuson Lin  * Version: 1.5.5
8*6696777cSDuson Lin  *
9*6696777cSDuson Lin  * Based on cyapa driver:
10*6696777cSDuson Lin  * copyright (c) 2011-2012 Cypress Semiconductor, Inc.
11*6696777cSDuson Lin  * copyright (c) 2011-2012 Google, Inc.
12*6696777cSDuson Lin  *
13*6696777cSDuson Lin  * This program is free software; you can redistribute it and/or modify it
14*6696777cSDuson Lin  * under the terms of the GNU General Public License version 2 as published
15*6696777cSDuson Lin  * by the Free Software Foundation.
16*6696777cSDuson Lin  *
17*6696777cSDuson Lin  * Trademarks are the property of their respective owners.
18*6696777cSDuson Lin  */
19*6696777cSDuson Lin 
20*6696777cSDuson Lin #include <linux/delay.h>
21*6696777cSDuson Lin #include <linux/i2c.h>
22*6696777cSDuson Lin #include <linux/init.h>
23*6696777cSDuson Lin #include <linux/kernel.h>
24*6696777cSDuson Lin 
25*6696777cSDuson Lin #include "elan_i2c.h"
26*6696777cSDuson Lin 
27*6696777cSDuson Lin /* Elan SMbus commands */
28*6696777cSDuson Lin #define ETP_SMBUS_IAP_CMD		0x00
29*6696777cSDuson Lin #define ETP_SMBUS_ENABLE_TP		0x20
30*6696777cSDuson Lin #define ETP_SMBUS_SLEEP_CMD		0x21
31*6696777cSDuson Lin #define ETP_SMBUS_IAP_PASSWORD_WRITE	0x29
32*6696777cSDuson Lin #define ETP_SMBUS_IAP_PASSWORD_READ	0x80
33*6696777cSDuson Lin #define ETP_SMBUS_WRITE_FW_BLOCK	0x2A
34*6696777cSDuson Lin #define ETP_SMBUS_IAP_RESET_CMD		0x2B
35*6696777cSDuson Lin #define ETP_SMBUS_RANGE_CMD		0xA0
36*6696777cSDuson Lin #define ETP_SMBUS_FW_VERSION_CMD	0xA1
37*6696777cSDuson Lin #define ETP_SMBUS_XY_TRACENUM_CMD	0xA2
38*6696777cSDuson Lin #define ETP_SMBUS_SM_VERSION_CMD	0xA3
39*6696777cSDuson Lin #define ETP_SMBUS_UNIQUEID_CMD		0xA3
40*6696777cSDuson Lin #define ETP_SMBUS_RESOLUTION_CMD	0xA4
41*6696777cSDuson Lin #define ETP_SMBUS_HELLOPACKET_CMD	0xA7
42*6696777cSDuson Lin #define ETP_SMBUS_PACKET_QUERY		0xA8
43*6696777cSDuson Lin #define ETP_SMBUS_IAP_VERSION_CMD	0xAC
44*6696777cSDuson Lin #define ETP_SMBUS_IAP_CTRL_CMD		0xAD
45*6696777cSDuson Lin #define ETP_SMBUS_IAP_CHECKSUM_CMD	0xAE
46*6696777cSDuson Lin #define ETP_SMBUS_FW_CHECKSUM_CMD	0xAF
47*6696777cSDuson Lin #define ETP_SMBUS_MAX_BASELINE_CMD	0xC3
48*6696777cSDuson Lin #define ETP_SMBUS_MIN_BASELINE_CMD	0xC4
49*6696777cSDuson Lin #define ETP_SMBUS_CALIBRATE_QUERY	0xC5
50*6696777cSDuson Lin 
51*6696777cSDuson Lin #define ETP_SMBUS_REPORT_LEN		32
52*6696777cSDuson Lin #define ETP_SMBUS_REPORT_OFFSET		2
53*6696777cSDuson Lin #define ETP_SMBUS_HELLOPACKET_LEN	5
54*6696777cSDuson Lin #define ETP_SMBUS_IAP_PASSWORD		0x1234
55*6696777cSDuson Lin #define ETP_SMBUS_IAP_MODE_ON		(1 << 6)
56*6696777cSDuson Lin 
57*6696777cSDuson Lin static int elan_smbus_initialize(struct i2c_client *client)
58*6696777cSDuson Lin {
59*6696777cSDuson Lin 	u8 check[ETP_SMBUS_HELLOPACKET_LEN] = { 0x55, 0x55, 0x55, 0x55, 0x55 };
60*6696777cSDuson Lin 	u8 values[ETP_SMBUS_HELLOPACKET_LEN] = { 0, 0, 0, 0, 0 };
61*6696777cSDuson Lin 	int len, error;
62*6696777cSDuson Lin 
63*6696777cSDuson Lin 	/* Get hello packet */
64*6696777cSDuson Lin 	len = i2c_smbus_read_block_data(client,
65*6696777cSDuson Lin 					ETP_SMBUS_HELLOPACKET_CMD, values);
66*6696777cSDuson Lin 	if (len != ETP_SMBUS_HELLOPACKET_LEN) {
67*6696777cSDuson Lin 		dev_err(&client->dev, "hello packet length fail: %d\n", len);
68*6696777cSDuson Lin 		error = len < 0 ? len : -EIO;
69*6696777cSDuson Lin 		return error;
70*6696777cSDuson Lin 	}
71*6696777cSDuson Lin 
72*6696777cSDuson Lin 	/* compare hello packet */
73*6696777cSDuson Lin 	if (memcmp(values, check, ETP_SMBUS_HELLOPACKET_LEN)) {
74*6696777cSDuson Lin 		dev_err(&client->dev, "hello packet fail [%*px]\n",
75*6696777cSDuson Lin 			ETP_SMBUS_HELLOPACKET_LEN, values);
76*6696777cSDuson Lin 		return -ENXIO;
77*6696777cSDuson Lin 	}
78*6696777cSDuson Lin 
79*6696777cSDuson Lin 	/* enable tp */
80*6696777cSDuson Lin 	error = i2c_smbus_write_byte(client, ETP_SMBUS_ENABLE_TP);
81*6696777cSDuson Lin 	if (error) {
82*6696777cSDuson Lin 		dev_err(&client->dev, "failed to enable touchpad: %d\n", error);
83*6696777cSDuson Lin 		return error;
84*6696777cSDuson Lin 	}
85*6696777cSDuson Lin 
86*6696777cSDuson Lin 	return 0;
87*6696777cSDuson Lin }
88*6696777cSDuson Lin 
89*6696777cSDuson Lin static int elan_smbus_set_mode(struct i2c_client *client, u8 mode)
90*6696777cSDuson Lin {
91*6696777cSDuson Lin 	u8 cmd[4] = { 0x00, 0x07, 0x00, mode };
92*6696777cSDuson Lin 
93*6696777cSDuson Lin 	return i2c_smbus_write_block_data(client, ETP_SMBUS_IAP_CMD,
94*6696777cSDuson Lin 					  sizeof(cmd), cmd);
95*6696777cSDuson Lin }
96*6696777cSDuson Lin 
97*6696777cSDuson Lin static int elan_smbus_sleep_control(struct i2c_client *client, bool sleep)
98*6696777cSDuson Lin {
99*6696777cSDuson Lin 	if (sleep)
100*6696777cSDuson Lin 		return i2c_smbus_write_byte(client, ETP_SMBUS_SLEEP_CMD);
101*6696777cSDuson Lin 	else
102*6696777cSDuson Lin 		return 0; /* XXX should we send ETP_SMBUS_ENABLE_TP here? */
103*6696777cSDuson Lin }
104*6696777cSDuson Lin 
105*6696777cSDuson Lin static int elan_smbus_power_control(struct i2c_client *client, bool enable)
106*6696777cSDuson Lin {
107*6696777cSDuson Lin 	return 0; /* A no-op */
108*6696777cSDuson Lin }
109*6696777cSDuson Lin 
110*6696777cSDuson Lin static int elan_smbus_calibrate(struct i2c_client *client)
111*6696777cSDuson Lin {
112*6696777cSDuson Lin 	u8 cmd[4] = { 0x00, 0x08, 0x00, 0x01 };
113*6696777cSDuson Lin 
114*6696777cSDuson Lin 	return i2c_smbus_write_block_data(client, ETP_SMBUS_IAP_CMD,
115*6696777cSDuson Lin 					  sizeof(cmd), cmd);
116*6696777cSDuson Lin }
117*6696777cSDuson Lin 
118*6696777cSDuson Lin static int elan_smbus_calibrate_result(struct i2c_client *client, u8 *val)
119*6696777cSDuson Lin {
120*6696777cSDuson Lin 	int error;
121*6696777cSDuson Lin 
122*6696777cSDuson Lin 	error = i2c_smbus_read_block_data(client,
123*6696777cSDuson Lin 					  ETP_SMBUS_CALIBRATE_QUERY, val);
124*6696777cSDuson Lin 	if (error < 0)
125*6696777cSDuson Lin 		return error;
126*6696777cSDuson Lin 
127*6696777cSDuson Lin 	return 0;
128*6696777cSDuson Lin }
129*6696777cSDuson Lin 
130*6696777cSDuson Lin static int elan_smbus_get_baseline_data(struct i2c_client *client,
131*6696777cSDuson Lin 					bool max_baseline, u8 *value)
132*6696777cSDuson Lin {
133*6696777cSDuson Lin 	int error;
134*6696777cSDuson Lin 	u8 val[3];
135*6696777cSDuson Lin 
136*6696777cSDuson Lin 	error = i2c_smbus_read_block_data(client,
137*6696777cSDuson Lin 					  max_baseline ?
138*6696777cSDuson Lin 						ETP_SMBUS_MAX_BASELINE_CMD :
139*6696777cSDuson Lin 						ETP_SMBUS_MIN_BASELINE_CMD,
140*6696777cSDuson Lin 					  val);
141*6696777cSDuson Lin 	if (error < 0)
142*6696777cSDuson Lin 		return error;
143*6696777cSDuson Lin 
144*6696777cSDuson Lin 	*value = be16_to_cpup((__be16 *)val);
145*6696777cSDuson Lin 
146*6696777cSDuson Lin 	return 0;
147*6696777cSDuson Lin }
148*6696777cSDuson Lin 
149*6696777cSDuson Lin static int elan_smbus_get_version(struct i2c_client *client,
150*6696777cSDuson Lin 				  bool iap, u8 *version)
151*6696777cSDuson Lin {
152*6696777cSDuson Lin 	int error;
153*6696777cSDuson Lin 	u8 val[3];
154*6696777cSDuson Lin 
155*6696777cSDuson Lin 	error = i2c_smbus_read_block_data(client,
156*6696777cSDuson Lin 					  iap ? ETP_SMBUS_IAP_VERSION_CMD :
157*6696777cSDuson Lin 						ETP_SMBUS_FW_VERSION_CMD,
158*6696777cSDuson Lin 					  val);
159*6696777cSDuson Lin 	if (error < 0) {
160*6696777cSDuson Lin 		dev_err(&client->dev, "failed to get %s version: %d\n",
161*6696777cSDuson Lin 			iap ? "IAP" : "FW", error);
162*6696777cSDuson Lin 		return error;
163*6696777cSDuson Lin 	}
164*6696777cSDuson Lin 
165*6696777cSDuson Lin 	*version = val[2];
166*6696777cSDuson Lin 	return 0;
167*6696777cSDuson Lin }
168*6696777cSDuson Lin 
169*6696777cSDuson Lin static int elan_smbus_get_sm_version(struct i2c_client *client, u8 *version)
170*6696777cSDuson Lin {
171*6696777cSDuson Lin 	int error;
172*6696777cSDuson Lin 	u8 val[3];
173*6696777cSDuson Lin 
174*6696777cSDuson Lin 	error = i2c_smbus_read_block_data(client,
175*6696777cSDuson Lin 					  ETP_SMBUS_SM_VERSION_CMD, val);
176*6696777cSDuson Lin 	if (error < 0) {
177*6696777cSDuson Lin 		dev_err(&client->dev, "failed to get SM version: %d\n", error);
178*6696777cSDuson Lin 		return error;
179*6696777cSDuson Lin 	}
180*6696777cSDuson Lin 
181*6696777cSDuson Lin 	*version = val[0]; /* XXX Why 0 and not 2 as in IAP/FW versions? */
182*6696777cSDuson Lin 	return 0;
183*6696777cSDuson Lin }
184*6696777cSDuson Lin 
185*6696777cSDuson Lin static int elan_smbus_get_product_id(struct i2c_client *client, u8 *id)
186*6696777cSDuson Lin {
187*6696777cSDuson Lin 	int error;
188*6696777cSDuson Lin 	u8 val[3];
189*6696777cSDuson Lin 
190*6696777cSDuson Lin 	error = i2c_smbus_read_block_data(client,
191*6696777cSDuson Lin 					  ETP_SMBUS_UNIQUEID_CMD, val);
192*6696777cSDuson Lin 	if (error < 0) {
193*6696777cSDuson Lin 		dev_err(&client->dev, "failed to get product ID: %d\n", error);
194*6696777cSDuson Lin 		return error;
195*6696777cSDuson Lin 	}
196*6696777cSDuson Lin 
197*6696777cSDuson Lin 	*id = val[1];
198*6696777cSDuson Lin 	return 0;
199*6696777cSDuson Lin }
200*6696777cSDuson Lin 
201*6696777cSDuson Lin static int elan_smbus_get_checksum(struct i2c_client *client,
202*6696777cSDuson Lin 				   bool iap, u16 *csum)
203*6696777cSDuson Lin {
204*6696777cSDuson Lin 	int error;
205*6696777cSDuson Lin 	u8 val[3];
206*6696777cSDuson Lin 
207*6696777cSDuson Lin 	error = i2c_smbus_read_block_data(client,
208*6696777cSDuson Lin 					  iap ? ETP_SMBUS_FW_CHECKSUM_CMD :
209*6696777cSDuson Lin 						ETP_SMBUS_IAP_CHECKSUM_CMD,
210*6696777cSDuson Lin 					  val);
211*6696777cSDuson Lin 	if (error < 0) {
212*6696777cSDuson Lin 		dev_err(&client->dev, "failed to get %s checksum: %d\n",
213*6696777cSDuson Lin 			iap ? "IAP" : "FW", error);
214*6696777cSDuson Lin 		return error;
215*6696777cSDuson Lin 	}
216*6696777cSDuson Lin 
217*6696777cSDuson Lin 	*csum = be16_to_cpup((__be16 *)val);
218*6696777cSDuson Lin 	return 0;
219*6696777cSDuson Lin }
220*6696777cSDuson Lin 
221*6696777cSDuson Lin static int elan_smbus_get_max(struct i2c_client *client,
222*6696777cSDuson Lin 			      unsigned int *max_x, unsigned int *max_y)
223*6696777cSDuson Lin {
224*6696777cSDuson Lin 	int error;
225*6696777cSDuson Lin 	u8 val[3];
226*6696777cSDuson Lin 
227*6696777cSDuson Lin 	error = i2c_smbus_read_block_data(client, ETP_SMBUS_RANGE_CMD, val);
228*6696777cSDuson Lin 	if (error) {
229*6696777cSDuson Lin 		dev_err(&client->dev, "failed to get dimensions: %d\n", error);
230*6696777cSDuson Lin 		return error;
231*6696777cSDuson Lin 	}
232*6696777cSDuson Lin 
233*6696777cSDuson Lin 	*max_x = (0x0f & val[0]) << 8 | val[1];
234*6696777cSDuson Lin 	*max_y = (0xf0 & val[0]) << 4 | val[2];
235*6696777cSDuson Lin 
236*6696777cSDuson Lin 	return 0;
237*6696777cSDuson Lin }
238*6696777cSDuson Lin 
239*6696777cSDuson Lin static int elan_smbus_get_resolution(struct i2c_client *client,
240*6696777cSDuson Lin 				     u8 *hw_res_x, u8 *hw_res_y)
241*6696777cSDuson Lin {
242*6696777cSDuson Lin 	int error;
243*6696777cSDuson Lin 	u8 val[3];
244*6696777cSDuson Lin 
245*6696777cSDuson Lin 	error = i2c_smbus_read_block_data(client,
246*6696777cSDuson Lin 					  ETP_SMBUS_RESOLUTION_CMD, val);
247*6696777cSDuson Lin 	if (error) {
248*6696777cSDuson Lin 		dev_err(&client->dev, "failed to get resolution: %d\n", error);
249*6696777cSDuson Lin 		return error;
250*6696777cSDuson Lin 	}
251*6696777cSDuson Lin 
252*6696777cSDuson Lin 	*hw_res_x = val[1] & 0x0F;
253*6696777cSDuson Lin 	*hw_res_y = (val[1] & 0xF0) >> 4;
254*6696777cSDuson Lin 
255*6696777cSDuson Lin 	return 0;
256*6696777cSDuson Lin }
257*6696777cSDuson Lin 
258*6696777cSDuson Lin static int elan_smbus_get_num_traces(struct i2c_client *client,
259*6696777cSDuson Lin 				     unsigned int *x_traces,
260*6696777cSDuson Lin 				     unsigned int *y_traces)
261*6696777cSDuson Lin {
262*6696777cSDuson Lin 	int error;
263*6696777cSDuson Lin 	u8 val[3];
264*6696777cSDuson Lin 
265*6696777cSDuson Lin 	error = i2c_smbus_read_block_data(client,
266*6696777cSDuson Lin 					  ETP_SMBUS_XY_TRACENUM_CMD, val);
267*6696777cSDuson Lin 	if (error) {
268*6696777cSDuson Lin 		dev_err(&client->dev, "failed to get trace info: %d\n", error);
269*6696777cSDuson Lin 		return error;
270*6696777cSDuson Lin 	}
271*6696777cSDuson Lin 
272*6696777cSDuson Lin 	*x_traces = val[1] - 1;
273*6696777cSDuson Lin 	*y_traces = val[2] - 1;
274*6696777cSDuson Lin 
275*6696777cSDuson Lin 	return 0;
276*6696777cSDuson Lin }
277*6696777cSDuson Lin 
278*6696777cSDuson Lin static int elan_smbus_iap_get_mode(struct i2c_client *client,
279*6696777cSDuson Lin 				   enum tp_mode *mode)
280*6696777cSDuson Lin {
281*6696777cSDuson Lin 	int error;
282*6696777cSDuson Lin 	u16 constant;
283*6696777cSDuson Lin 	u8 val[3];
284*6696777cSDuson Lin 
285*6696777cSDuson Lin 	error = i2c_smbus_read_block_data(client, ETP_SMBUS_IAP_CTRL_CMD, val);
286*6696777cSDuson Lin 	if (error < 0) {
287*6696777cSDuson Lin 		dev_err(&client->dev, "failed to read iap ctrol register: %d\n",
288*6696777cSDuson Lin 			error);
289*6696777cSDuson Lin 		return error;
290*6696777cSDuson Lin 	}
291*6696777cSDuson Lin 
292*6696777cSDuson Lin 	constant = be16_to_cpup((__be16 *)val);
293*6696777cSDuson Lin 	dev_dbg(&client->dev, "iap control reg: 0x%04x.\n", constant);
294*6696777cSDuson Lin 
295*6696777cSDuson Lin 	*mode = (constant & ETP_SMBUS_IAP_MODE_ON) ? IAP_MODE : MAIN_MODE;
296*6696777cSDuson Lin 
297*6696777cSDuson Lin 	return 0;
298*6696777cSDuson Lin }
299*6696777cSDuson Lin 
300*6696777cSDuson Lin static int elan_smbus_iap_reset(struct i2c_client *client)
301*6696777cSDuson Lin {
302*6696777cSDuson Lin 	int error;
303*6696777cSDuson Lin 
304*6696777cSDuson Lin 	error = i2c_smbus_write_byte(client, ETP_SMBUS_IAP_RESET_CMD);
305*6696777cSDuson Lin 	if (error) {
306*6696777cSDuson Lin 		dev_err(&client->dev, "cannot reset IC: %d\n", error);
307*6696777cSDuson Lin 		return error;
308*6696777cSDuson Lin 	}
309*6696777cSDuson Lin 
310*6696777cSDuson Lin 	return 0;
311*6696777cSDuson Lin }
312*6696777cSDuson Lin 
313*6696777cSDuson Lin static int elan_smbus_set_flash_key(struct i2c_client *client)
314*6696777cSDuson Lin {
315*6696777cSDuson Lin 	int error;
316*6696777cSDuson Lin 	u8 cmd[4] = { 0x00, 0x0B, 0x00, 0x5A };
317*6696777cSDuson Lin 
318*6696777cSDuson Lin 	error = i2c_smbus_write_block_data(client, ETP_SMBUS_IAP_CMD,
319*6696777cSDuson Lin 					   sizeof(cmd), cmd);
320*6696777cSDuson Lin 	if (error) {
321*6696777cSDuson Lin 		dev_err(&client->dev, "cannot set flash key: %d\n", error);
322*6696777cSDuson Lin 		return error;
323*6696777cSDuson Lin 	}
324*6696777cSDuson Lin 
325*6696777cSDuson Lin 	return 0;
326*6696777cSDuson Lin }
327*6696777cSDuson Lin 
328*6696777cSDuson Lin static int elan_smbus_prepare_fw_update(struct i2c_client *client)
329*6696777cSDuson Lin {
330*6696777cSDuson Lin 	struct device *dev = &client->dev;
331*6696777cSDuson Lin 	int len;
332*6696777cSDuson Lin 	int error;
333*6696777cSDuson Lin 	enum tp_mode mode;
334*6696777cSDuson Lin 	u8 val[3];
335*6696777cSDuson Lin 	u8 cmd[4] = {0x0F, 0x78, 0x00, 0x06};
336*6696777cSDuson Lin 	u16 password;
337*6696777cSDuson Lin 
338*6696777cSDuson Lin 	/* Get FW in which mode	(IAP_MODE/MAIN_MODE)  */
339*6696777cSDuson Lin 	error = elan_smbus_iap_get_mode(client, &mode);
340*6696777cSDuson Lin 	if (error)
341*6696777cSDuson Lin 		return error;
342*6696777cSDuson Lin 
343*6696777cSDuson Lin 	if (mode == MAIN_MODE) {
344*6696777cSDuson Lin 
345*6696777cSDuson Lin 		/* set flash key */
346*6696777cSDuson Lin 		error = elan_smbus_set_flash_key(client);
347*6696777cSDuson Lin 		if (error)
348*6696777cSDuson Lin 			return error;
349*6696777cSDuson Lin 
350*6696777cSDuson Lin 		/* write iap password */
351*6696777cSDuson Lin 		if (i2c_smbus_write_byte(client,
352*6696777cSDuson Lin 					 ETP_SMBUS_IAP_PASSWORD_WRITE) < 0) {
353*6696777cSDuson Lin 			dev_err(dev, "cannot write iap password\n");
354*6696777cSDuson Lin 			return -EIO;
355*6696777cSDuson Lin 		}
356*6696777cSDuson Lin 
357*6696777cSDuson Lin 		error = i2c_smbus_write_block_data(client, ETP_SMBUS_IAP_CMD,
358*6696777cSDuson Lin 						   sizeof(cmd), cmd);
359*6696777cSDuson Lin 		if (error) {
360*6696777cSDuson Lin 			dev_err(dev, "failed to write iap password: %d\n",
361*6696777cSDuson Lin 				error);
362*6696777cSDuson Lin 			return error;
363*6696777cSDuson Lin 		}
364*6696777cSDuson Lin 
365*6696777cSDuson Lin 		/*
366*6696777cSDuson Lin 		 * Read back password to make sure we enabled flash
367*6696777cSDuson Lin 		 * successfully.
368*6696777cSDuson Lin 		 */
369*6696777cSDuson Lin 		len = i2c_smbus_read_block_data(client,
370*6696777cSDuson Lin 						ETP_SMBUS_IAP_PASSWORD_READ,
371*6696777cSDuson Lin 						val);
372*6696777cSDuson Lin 		if (len < sizeof(u16)) {
373*6696777cSDuson Lin 			error = len < 0 ? len : -EIO;
374*6696777cSDuson Lin 			dev_err(dev, "failed to read iap password: %d\n",
375*6696777cSDuson Lin 				error);
376*6696777cSDuson Lin 			return error;
377*6696777cSDuson Lin 		}
378*6696777cSDuson Lin 
379*6696777cSDuson Lin 		password = be16_to_cpup((__be16 *)val);
380*6696777cSDuson Lin 		if (password != ETP_SMBUS_IAP_PASSWORD) {
381*6696777cSDuson Lin 			dev_err(dev, "wrong iap password = 0x%X\n", password);
382*6696777cSDuson Lin 			return -EIO;
383*6696777cSDuson Lin 		}
384*6696777cSDuson Lin 
385*6696777cSDuson Lin 		/* Wait 30ms for MAIN_MODE change to IAP_MODE */
386*6696777cSDuson Lin 		msleep(30);
387*6696777cSDuson Lin 	}
388*6696777cSDuson Lin 
389*6696777cSDuson Lin 	error = elan_smbus_set_flash_key(client);
390*6696777cSDuson Lin 	if (error)
391*6696777cSDuson Lin 		return error;
392*6696777cSDuson Lin 
393*6696777cSDuson Lin 	/* Reset IC */
394*6696777cSDuson Lin 	error = elan_smbus_iap_reset(client);
395*6696777cSDuson Lin 	if (error)
396*6696777cSDuson Lin 		return error;
397*6696777cSDuson Lin 
398*6696777cSDuson Lin 	return 0;
399*6696777cSDuson Lin }
400*6696777cSDuson Lin 
401*6696777cSDuson Lin 
402*6696777cSDuson Lin static int elan_smbus_write_fw_block(struct i2c_client *client,
403*6696777cSDuson Lin 				     const u8 *page, u16 checksum, int idx)
404*6696777cSDuson Lin {
405*6696777cSDuson Lin 	struct device *dev = &client->dev;
406*6696777cSDuson Lin 	int error;
407*6696777cSDuson Lin 	u16 result;
408*6696777cSDuson Lin 	u8 val[3];
409*6696777cSDuson Lin 
410*6696777cSDuson Lin 	/*
411*6696777cSDuson Lin 	 * Due to the limitation of smbus protocol limiting
412*6696777cSDuson Lin 	 * transfer to 32 bytes at a time, we must split block
413*6696777cSDuson Lin 	 * in 2 transfers.
414*6696777cSDuson Lin 	 */
415*6696777cSDuson Lin 	error = i2c_smbus_write_block_data(client,
416*6696777cSDuson Lin 					   ETP_SMBUS_WRITE_FW_BLOCK,
417*6696777cSDuson Lin 					   ETP_FW_PAGE_SIZE / 2,
418*6696777cSDuson Lin 					   page);
419*6696777cSDuson Lin 	if (error) {
420*6696777cSDuson Lin 		dev_err(dev, "Failed to write page %d (part %d): %d\n",
421*6696777cSDuson Lin 			idx, 1, error);
422*6696777cSDuson Lin 		return error;
423*6696777cSDuson Lin 	}
424*6696777cSDuson Lin 
425*6696777cSDuson Lin 	error = i2c_smbus_write_block_data(client,
426*6696777cSDuson Lin 					   ETP_SMBUS_WRITE_FW_BLOCK,
427*6696777cSDuson Lin 					   ETP_FW_PAGE_SIZE / 2,
428*6696777cSDuson Lin 					   page + ETP_FW_PAGE_SIZE / 2);
429*6696777cSDuson Lin 	if (error) {
430*6696777cSDuson Lin 		dev_err(dev, "Failed to write page %d (part %d): %d\n",
431*6696777cSDuson Lin 			idx, 2, error);
432*6696777cSDuson Lin 		return error;
433*6696777cSDuson Lin 	}
434*6696777cSDuson Lin 
435*6696777cSDuson Lin 
436*6696777cSDuson Lin 	/* Wait for F/W to update one page ROM data. */
437*6696777cSDuson Lin 	usleep_range(8000, 10000);
438*6696777cSDuson Lin 
439*6696777cSDuson Lin 	error = i2c_smbus_read_block_data(client,
440*6696777cSDuson Lin 					  ETP_SMBUS_IAP_CTRL_CMD, val);
441*6696777cSDuson Lin 	if (error < 0) {
442*6696777cSDuson Lin 		dev_err(dev, "Failed to read IAP write result: %d\n",
443*6696777cSDuson Lin 			error);
444*6696777cSDuson Lin 		return error;
445*6696777cSDuson Lin 	}
446*6696777cSDuson Lin 
447*6696777cSDuson Lin 	result = be16_to_cpup((__be16 *)val);
448*6696777cSDuson Lin 	if (result & (ETP_FW_IAP_PAGE_ERR | ETP_FW_IAP_INTF_ERR)) {
449*6696777cSDuson Lin 		dev_err(dev, "IAP reports failed write: %04hx\n",
450*6696777cSDuson Lin 			result);
451*6696777cSDuson Lin 		return -EIO;
452*6696777cSDuson Lin 	}
453*6696777cSDuson Lin 
454*6696777cSDuson Lin 	return 0;
455*6696777cSDuson Lin }
456*6696777cSDuson Lin 
457*6696777cSDuson Lin static int elan_smbus_get_report(struct i2c_client *client, u8 *report)
458*6696777cSDuson Lin {
459*6696777cSDuson Lin 	int len;
460*6696777cSDuson Lin 
461*6696777cSDuson Lin 	len = i2c_smbus_read_block_data(client,
462*6696777cSDuson Lin 					ETP_SMBUS_PACKET_QUERY,
463*6696777cSDuson Lin 					&report[ETP_SMBUS_REPORT_OFFSET]);
464*6696777cSDuson Lin 	if (len < 0) {
465*6696777cSDuson Lin 		dev_err(&client->dev, "failed to read report data: %d\n", len);
466*6696777cSDuson Lin 		return len;
467*6696777cSDuson Lin 	}
468*6696777cSDuson Lin 
469*6696777cSDuson Lin 	if (len != ETP_SMBUS_REPORT_LEN) {
470*6696777cSDuson Lin 		dev_err(&client->dev,
471*6696777cSDuson Lin 			"wrong report length (%d vs %d expected)\n",
472*6696777cSDuson Lin 			len, ETP_SMBUS_REPORT_LEN);
473*6696777cSDuson Lin 		return -EIO;
474*6696777cSDuson Lin 	}
475*6696777cSDuson Lin 
476*6696777cSDuson Lin 	return 0;
477*6696777cSDuson Lin }
478*6696777cSDuson Lin 
479*6696777cSDuson Lin static int elan_smbus_finish_fw_update(struct i2c_client *client,
480*6696777cSDuson Lin 				       struct completion *fw_completion)
481*6696777cSDuson Lin {
482*6696777cSDuson Lin 	/* No special handling unlike I2C transport */
483*6696777cSDuson Lin 	return 0;
484*6696777cSDuson Lin }
485*6696777cSDuson Lin 
486*6696777cSDuson Lin const struct elan_transport_ops elan_smbus_ops = {
487*6696777cSDuson Lin 	.initialize		= elan_smbus_initialize,
488*6696777cSDuson Lin 	.sleep_control		= elan_smbus_sleep_control,
489*6696777cSDuson Lin 	.power_control		= elan_smbus_power_control,
490*6696777cSDuson Lin 	.set_mode		= elan_smbus_set_mode,
491*6696777cSDuson Lin 
492*6696777cSDuson Lin 	.calibrate		= elan_smbus_calibrate,
493*6696777cSDuson Lin 	.calibrate_result	= elan_smbus_calibrate_result,
494*6696777cSDuson Lin 
495*6696777cSDuson Lin 	.get_baseline_data	= elan_smbus_get_baseline_data,
496*6696777cSDuson Lin 
497*6696777cSDuson Lin 	.get_version		= elan_smbus_get_version,
498*6696777cSDuson Lin 	.get_sm_version		= elan_smbus_get_sm_version,
499*6696777cSDuson Lin 	.get_product_id		= elan_smbus_get_product_id,
500*6696777cSDuson Lin 	.get_checksum		= elan_smbus_get_checksum,
501*6696777cSDuson Lin 
502*6696777cSDuson Lin 	.get_max		= elan_smbus_get_max,
503*6696777cSDuson Lin 	.get_resolution		= elan_smbus_get_resolution,
504*6696777cSDuson Lin 	.get_num_traces		= elan_smbus_get_num_traces,
505*6696777cSDuson Lin 
506*6696777cSDuson Lin 	.iap_get_mode		= elan_smbus_iap_get_mode,
507*6696777cSDuson Lin 	.iap_reset		= elan_smbus_iap_reset,
508*6696777cSDuson Lin 
509*6696777cSDuson Lin 	.prepare_fw_update	= elan_smbus_prepare_fw_update,
510*6696777cSDuson Lin 	.write_fw_block		= elan_smbus_write_fw_block,
511*6696777cSDuson Lin 	.finish_fw_update	= elan_smbus_finish_fw_update,
512*6696777cSDuson Lin 
513*6696777cSDuson Lin 	.get_report		= elan_smbus_get_report,
514*6696777cSDuson Lin };
515