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