1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | #include <linux/crc-ccitt.h> |
3 | #include <linux/delay.h> |
4 | #include <linux/gpio/consumer.h> |
5 | #include <linux/i2c.h> |
6 | #include <linux/ihex.h> |
7 | #include <linux/input.h> |
8 | #include <linux/input/mt.h> |
9 | #include <linux/input/touchscreen.h> |
10 | #include <linux/interrupt.h> |
11 | #include <linux/mod_devicetable.h> |
12 | #include <linux/module.h> |
13 | #include <linux/sizes.h> |
14 | #include <linux/slab.h> |
15 | #include <asm/unaligned.h> |
16 | |
17 | #define ILI2XXX_POLL_PERIOD 15 |
18 | |
19 | #define ILI210X_DATA_SIZE 64 |
20 | #define ILI211X_DATA_SIZE 43 |
21 | #define ILI251X_DATA_SIZE1 31 |
22 | #define ILI251X_DATA_SIZE2 20 |
23 | |
24 | /* Touchscreen commands */ |
25 | #define REG_TOUCHDATA 0x10 |
26 | #define REG_PANEL_INFO 0x20 |
27 | #define REG_FIRMWARE_VERSION 0x40 |
28 | #define REG_PROTOCOL_VERSION 0x42 |
29 | #define REG_KERNEL_VERSION 0x61 |
30 | #define REG_IC_BUSY 0x80 |
31 | #define REG_IC_BUSY_NOT_BUSY 0x50 |
32 | #define REG_GET_MODE 0xc0 |
33 | #define REG_GET_MODE_AP 0x5a |
34 | #define REG_GET_MODE_BL 0x55 |
35 | #define REG_SET_MODE_AP 0xc1 |
36 | #define REG_SET_MODE_BL 0xc2 |
37 | #define REG_WRITE_DATA 0xc3 |
38 | #define REG_WRITE_ENABLE 0xc4 |
39 | #define REG_READ_DATA_CRC 0xc7 |
40 | #define REG_CALIBRATE 0xcc |
41 | |
42 | #define ILI251X_FW_FILENAME "ilitek/ili251x.bin" |
43 | |
44 | struct ili2xxx_chip { |
45 | int (*read_reg)(struct i2c_client *client, u8 reg, |
46 | void *buf, size_t len); |
47 | int (*get_touch_data)(struct i2c_client *client, u8 *data); |
48 | bool (*parse_touch_data)(const u8 *data, unsigned int finger, |
49 | unsigned int *x, unsigned int *y, |
50 | unsigned int *z); |
51 | bool (*continue_polling)(const u8 *data, bool touch); |
52 | unsigned int max_touches; |
53 | unsigned int resolution; |
54 | bool has_calibrate_reg; |
55 | bool has_firmware_proto; |
56 | bool has_pressure_reg; |
57 | }; |
58 | |
59 | struct ili210x { |
60 | struct i2c_client *client; |
61 | struct input_dev *input; |
62 | struct gpio_desc *reset_gpio; |
63 | struct touchscreen_properties prop; |
64 | const struct ili2xxx_chip *chip; |
65 | u8 version_firmware[8]; |
66 | u8 version_kernel[5]; |
67 | u8 version_proto[2]; |
68 | u8 ic_mode[2]; |
69 | bool stop; |
70 | }; |
71 | |
72 | static int ili210x_read_reg(struct i2c_client *client, |
73 | u8 reg, void *buf, size_t len) |
74 | { |
75 | struct i2c_msg msg[] = { |
76 | { |
77 | .addr = client->addr, |
78 | .flags = 0, |
79 | .len = 1, |
80 | .buf = ®, |
81 | }, |
82 | { |
83 | .addr = client->addr, |
84 | .flags = I2C_M_RD, |
85 | .len = len, |
86 | .buf = buf, |
87 | } |
88 | }; |
89 | int error, ret; |
90 | |
91 | ret = i2c_transfer(adap: client->adapter, msgs: msg, ARRAY_SIZE(msg)); |
92 | if (ret != ARRAY_SIZE(msg)) { |
93 | error = ret < 0 ? ret : -EIO; |
94 | dev_err(&client->dev, "%s failed: %d\n" , __func__, error); |
95 | return error; |
96 | } |
97 | |
98 | return 0; |
99 | } |
100 | |
101 | static int ili210x_read_touch_data(struct i2c_client *client, u8 *data) |
102 | { |
103 | return ili210x_read_reg(client, REG_TOUCHDATA, |
104 | buf: data, ILI210X_DATA_SIZE); |
105 | } |
106 | |
107 | static bool ili210x_touchdata_to_coords(const u8 *touchdata, |
108 | unsigned int finger, |
109 | unsigned int *x, unsigned int *y, |
110 | unsigned int *z) |
111 | { |
112 | if (!(touchdata[0] & BIT(finger))) |
113 | return false; |
114 | |
115 | *x = get_unaligned_be16(p: touchdata + 1 + (finger * 4) + 0); |
116 | *y = get_unaligned_be16(p: touchdata + 1 + (finger * 4) + 2); |
117 | |
118 | return true; |
119 | } |
120 | |
121 | static bool ili210x_check_continue_polling(const u8 *data, bool touch) |
122 | { |
123 | return data[0] & 0xf3; |
124 | } |
125 | |
126 | static const struct ili2xxx_chip ili210x_chip = { |
127 | .read_reg = ili210x_read_reg, |
128 | .get_touch_data = ili210x_read_touch_data, |
129 | .parse_touch_data = ili210x_touchdata_to_coords, |
130 | .continue_polling = ili210x_check_continue_polling, |
131 | .max_touches = 2, |
132 | .has_calibrate_reg = true, |
133 | }; |
134 | |
135 | static int ili211x_read_touch_data(struct i2c_client *client, u8 *data) |
136 | { |
137 | s16 sum = 0; |
138 | int error; |
139 | int ret; |
140 | int i; |
141 | |
142 | ret = i2c_master_recv(client, buf: data, ILI211X_DATA_SIZE); |
143 | if (ret != ILI211X_DATA_SIZE) { |
144 | error = ret < 0 ? ret : -EIO; |
145 | dev_err(&client->dev, "%s failed: %d\n" , __func__, error); |
146 | return error; |
147 | } |
148 | |
149 | /* This chip uses custom checksum at the end of data */ |
150 | for (i = 0; i < ILI211X_DATA_SIZE - 1; i++) |
151 | sum = (sum + data[i]) & 0xff; |
152 | |
153 | if ((-sum & 0xff) != data[ILI211X_DATA_SIZE - 1]) { |
154 | dev_err(&client->dev, |
155 | "CRC error (crc=0x%02x expected=0x%02x)\n" , |
156 | sum, data[ILI211X_DATA_SIZE - 1]); |
157 | return -EIO; |
158 | } |
159 | |
160 | return 0; |
161 | } |
162 | |
163 | static bool ili211x_touchdata_to_coords(const u8 *touchdata, |
164 | unsigned int finger, |
165 | unsigned int *x, unsigned int *y, |
166 | unsigned int *z) |
167 | { |
168 | u32 data; |
169 | |
170 | data = get_unaligned_be32(p: touchdata + 1 + (finger * 4) + 0); |
171 | if (data == 0xffffffff) /* Finger up */ |
172 | return false; |
173 | |
174 | *x = ((touchdata[1 + (finger * 4) + 0] & 0xf0) << 4) | |
175 | touchdata[1 + (finger * 4) + 1]; |
176 | *y = ((touchdata[1 + (finger * 4) + 0] & 0x0f) << 8) | |
177 | touchdata[1 + (finger * 4) + 2]; |
178 | |
179 | return true; |
180 | } |
181 | |
182 | static bool ili211x_decline_polling(const u8 *data, bool touch) |
183 | { |
184 | return false; |
185 | } |
186 | |
187 | static const struct ili2xxx_chip ili211x_chip = { |
188 | .read_reg = ili210x_read_reg, |
189 | .get_touch_data = ili211x_read_touch_data, |
190 | .parse_touch_data = ili211x_touchdata_to_coords, |
191 | .continue_polling = ili211x_decline_polling, |
192 | .max_touches = 10, |
193 | .resolution = 2048, |
194 | }; |
195 | |
196 | static bool ili212x_touchdata_to_coords(const u8 *touchdata, |
197 | unsigned int finger, |
198 | unsigned int *x, unsigned int *y, |
199 | unsigned int *z) |
200 | { |
201 | u16 val; |
202 | |
203 | val = get_unaligned_be16(p: touchdata + 3 + (finger * 5) + 0); |
204 | if (!(val & BIT(15))) /* Touch indication */ |
205 | return false; |
206 | |
207 | *x = val & 0x3fff; |
208 | *y = get_unaligned_be16(p: touchdata + 3 + (finger * 5) + 2); |
209 | |
210 | return true; |
211 | } |
212 | |
213 | static bool ili212x_check_continue_polling(const u8 *data, bool touch) |
214 | { |
215 | return touch; |
216 | } |
217 | |
218 | static const struct ili2xxx_chip ili212x_chip = { |
219 | .read_reg = ili210x_read_reg, |
220 | .get_touch_data = ili210x_read_touch_data, |
221 | .parse_touch_data = ili212x_touchdata_to_coords, |
222 | .continue_polling = ili212x_check_continue_polling, |
223 | .max_touches = 10, |
224 | .has_calibrate_reg = true, |
225 | }; |
226 | |
227 | static int ili251x_read_reg_common(struct i2c_client *client, |
228 | u8 reg, void *buf, size_t len, |
229 | unsigned int delay) |
230 | { |
231 | int error; |
232 | int ret; |
233 | |
234 | ret = i2c_master_send(client, buf: ®, count: 1); |
235 | if (ret == 1) { |
236 | if (delay) |
237 | usleep_range(min: delay, max: delay + 500); |
238 | |
239 | ret = i2c_master_recv(client, buf, count: len); |
240 | if (ret == len) |
241 | return 0; |
242 | } |
243 | |
244 | error = ret < 0 ? ret : -EIO; |
245 | dev_err(&client->dev, "%s failed: %d\n" , __func__, error); |
246 | return ret; |
247 | } |
248 | |
249 | static int ili251x_read_reg(struct i2c_client *client, |
250 | u8 reg, void *buf, size_t len) |
251 | { |
252 | return ili251x_read_reg_common(client, reg, buf, len, delay: 5000); |
253 | } |
254 | |
255 | static int ili251x_read_touch_data(struct i2c_client *client, u8 *data) |
256 | { |
257 | int error; |
258 | |
259 | error = ili251x_read_reg_common(client, REG_TOUCHDATA, |
260 | buf: data, ILI251X_DATA_SIZE1, delay: 0); |
261 | if (!error && data[0] == 2) { |
262 | error = i2c_master_recv(client, buf: data + ILI251X_DATA_SIZE1, |
263 | ILI251X_DATA_SIZE2); |
264 | if (error >= 0 && error != ILI251X_DATA_SIZE2) |
265 | error = -EIO; |
266 | } |
267 | |
268 | return error; |
269 | } |
270 | |
271 | static bool ili251x_touchdata_to_coords(const u8 *touchdata, |
272 | unsigned int finger, |
273 | unsigned int *x, unsigned int *y, |
274 | unsigned int *z) |
275 | { |
276 | u16 val; |
277 | |
278 | val = get_unaligned_be16(p: touchdata + 1 + (finger * 5) + 0); |
279 | if (!(val & BIT(15))) /* Touch indication */ |
280 | return false; |
281 | |
282 | *x = val & 0x3fff; |
283 | *y = get_unaligned_be16(p: touchdata + 1 + (finger * 5) + 2); |
284 | *z = touchdata[1 + (finger * 5) + 4]; |
285 | |
286 | return true; |
287 | } |
288 | |
289 | static bool ili251x_check_continue_polling(const u8 *data, bool touch) |
290 | { |
291 | return touch; |
292 | } |
293 | |
294 | static const struct ili2xxx_chip ili251x_chip = { |
295 | .read_reg = ili251x_read_reg, |
296 | .get_touch_data = ili251x_read_touch_data, |
297 | .parse_touch_data = ili251x_touchdata_to_coords, |
298 | .continue_polling = ili251x_check_continue_polling, |
299 | .max_touches = 10, |
300 | .has_calibrate_reg = true, |
301 | .has_firmware_proto = true, |
302 | .has_pressure_reg = true, |
303 | }; |
304 | |
305 | static bool ili210x_report_events(struct ili210x *priv, u8 *touchdata) |
306 | { |
307 | struct input_dev *input = priv->input; |
308 | int i; |
309 | bool contact = false, touch; |
310 | unsigned int x = 0, y = 0, z = 0; |
311 | |
312 | for (i = 0; i < priv->chip->max_touches; i++) { |
313 | touch = priv->chip->parse_touch_data(touchdata, i, &x, &y, &z); |
314 | |
315 | input_mt_slot(dev: input, slot: i); |
316 | if (input_mt_report_slot_state(dev: input, MT_TOOL_FINGER, active: touch)) { |
317 | touchscreen_report_pos(input, prop: &priv->prop, x, y, multitouch: true); |
318 | if (priv->chip->has_pressure_reg) |
319 | input_report_abs(dev: input, ABS_MT_PRESSURE, value: z); |
320 | contact = true; |
321 | } |
322 | } |
323 | |
324 | input_mt_report_pointer_emulation(dev: input, use_count: false); |
325 | input_sync(dev: input); |
326 | |
327 | return contact; |
328 | } |
329 | |
330 | static irqreturn_t ili210x_irq(int irq, void *irq_data) |
331 | { |
332 | struct ili210x *priv = irq_data; |
333 | struct i2c_client *client = priv->client; |
334 | const struct ili2xxx_chip *chip = priv->chip; |
335 | u8 touchdata[ILI210X_DATA_SIZE] = { 0 }; |
336 | bool keep_polling; |
337 | ktime_t time_next; |
338 | s64 time_delta; |
339 | bool touch; |
340 | int error; |
341 | |
342 | do { |
343 | time_next = ktime_add_ms(kt: ktime_get(), ILI2XXX_POLL_PERIOD); |
344 | error = chip->get_touch_data(client, touchdata); |
345 | if (error) { |
346 | dev_err(&client->dev, |
347 | "Unable to get touch data: %d\n" , error); |
348 | break; |
349 | } |
350 | |
351 | touch = ili210x_report_events(priv, touchdata); |
352 | keep_polling = chip->continue_polling(touchdata, touch); |
353 | if (keep_polling) { |
354 | time_delta = ktime_us_delta(later: time_next, earlier: ktime_get()); |
355 | if (time_delta > 0) |
356 | usleep_range(min: time_delta, max: time_delta + 1000); |
357 | } |
358 | } while (!priv->stop && keep_polling); |
359 | |
360 | return IRQ_HANDLED; |
361 | } |
362 | |
363 | static int ili251x_firmware_update_resolution(struct device *dev) |
364 | { |
365 | struct i2c_client *client = to_i2c_client(dev); |
366 | struct ili210x *priv = i2c_get_clientdata(client); |
367 | u16 resx, resy; |
368 | u8 rs[10]; |
369 | int error; |
370 | |
371 | /* The firmware update blob might have changed the resolution. */ |
372 | error = priv->chip->read_reg(client, REG_PANEL_INFO, &rs, sizeof(rs)); |
373 | if (!error) { |
374 | resx = le16_to_cpup(p: (__le16 *)rs); |
375 | resy = le16_to_cpup(p: (__le16 *)(rs + 2)); |
376 | |
377 | /* The value reported by the firmware is invalid. */ |
378 | if (!resx || resx == 0xffff || !resy || resy == 0xffff) |
379 | error = -EINVAL; |
380 | } |
381 | |
382 | /* |
383 | * In case of error, the firmware might be stuck in bootloader mode, |
384 | * e.g. after a failed firmware update. Set maximum resolution, but |
385 | * do not fail to probe, so the user can re-trigger the firmware |
386 | * update and recover the touch controller. |
387 | */ |
388 | if (error) { |
389 | dev_warn(dev, "Invalid resolution reported by controller.\n" ); |
390 | resx = 16384; |
391 | resy = 16384; |
392 | } |
393 | |
394 | input_abs_set_max(dev: priv->input, ABS_X, val: resx - 1); |
395 | input_abs_set_max(dev: priv->input, ABS_Y, val: resy - 1); |
396 | input_abs_set_max(dev: priv->input, ABS_MT_POSITION_X, val: resx - 1); |
397 | input_abs_set_max(dev: priv->input, ABS_MT_POSITION_Y, val: resy - 1); |
398 | |
399 | return error; |
400 | } |
401 | |
402 | static ssize_t ili251x_firmware_update_firmware_version(struct device *dev) |
403 | { |
404 | struct i2c_client *client = to_i2c_client(dev); |
405 | struct ili210x *priv = i2c_get_clientdata(client); |
406 | int error; |
407 | u8 fw[8]; |
408 | |
409 | /* Get firmware version */ |
410 | error = priv->chip->read_reg(client, REG_FIRMWARE_VERSION, |
411 | &fw, sizeof(fw)); |
412 | if (!error) |
413 | memcpy(priv->version_firmware, fw, sizeof(fw)); |
414 | |
415 | return error; |
416 | } |
417 | |
418 | static ssize_t ili251x_firmware_update_kernel_version(struct device *dev) |
419 | { |
420 | struct i2c_client *client = to_i2c_client(dev); |
421 | struct ili210x *priv = i2c_get_clientdata(client); |
422 | int error; |
423 | u8 kv[5]; |
424 | |
425 | /* Get kernel version */ |
426 | error = priv->chip->read_reg(client, REG_KERNEL_VERSION, |
427 | &kv, sizeof(kv)); |
428 | if (!error) |
429 | memcpy(priv->version_kernel, kv, sizeof(kv)); |
430 | |
431 | return error; |
432 | } |
433 | |
434 | static ssize_t ili251x_firmware_update_protocol_version(struct device *dev) |
435 | { |
436 | struct i2c_client *client = to_i2c_client(dev); |
437 | struct ili210x *priv = i2c_get_clientdata(client); |
438 | int error; |
439 | u8 pv[2]; |
440 | |
441 | /* Get protocol version */ |
442 | error = priv->chip->read_reg(client, REG_PROTOCOL_VERSION, |
443 | &pv, sizeof(pv)); |
444 | if (!error) |
445 | memcpy(priv->version_proto, pv, sizeof(pv)); |
446 | |
447 | return error; |
448 | } |
449 | |
450 | static ssize_t ili251x_firmware_update_ic_mode(struct device *dev) |
451 | { |
452 | struct i2c_client *client = to_i2c_client(dev); |
453 | struct ili210x *priv = i2c_get_clientdata(client); |
454 | int error; |
455 | u8 md[2]; |
456 | |
457 | /* Get chip boot mode */ |
458 | error = priv->chip->read_reg(client, REG_GET_MODE, &md, sizeof(md)); |
459 | if (!error) |
460 | memcpy(priv->ic_mode, md, sizeof(md)); |
461 | |
462 | return error; |
463 | } |
464 | |
465 | static int ili251x_firmware_update_cached_state(struct device *dev) |
466 | { |
467 | struct i2c_client *client = to_i2c_client(dev); |
468 | struct ili210x *priv = i2c_get_clientdata(client); |
469 | int error; |
470 | |
471 | if (!priv->chip->has_firmware_proto) |
472 | return 0; |
473 | |
474 | /* Wait for firmware to boot and stabilize itself. */ |
475 | msleep(msecs: 200); |
476 | |
477 | /* Firmware does report valid information. */ |
478 | error = ili251x_firmware_update_resolution(dev); |
479 | if (error) |
480 | return error; |
481 | |
482 | error = ili251x_firmware_update_firmware_version(dev); |
483 | if (error) |
484 | return error; |
485 | |
486 | error = ili251x_firmware_update_kernel_version(dev); |
487 | if (error) |
488 | return error; |
489 | |
490 | error = ili251x_firmware_update_protocol_version(dev); |
491 | if (error) |
492 | return error; |
493 | |
494 | error = ili251x_firmware_update_ic_mode(dev); |
495 | if (error) |
496 | return error; |
497 | |
498 | return 0; |
499 | } |
500 | |
501 | static ssize_t ili251x_firmware_version_show(struct device *dev, |
502 | struct device_attribute *attr, |
503 | char *buf) |
504 | { |
505 | struct i2c_client *client = to_i2c_client(dev); |
506 | struct ili210x *priv = i2c_get_clientdata(client); |
507 | u8 *fw = priv->version_firmware; |
508 | |
509 | return sysfs_emit(buf, fmt: "%02x%02x.%02x%02x.%02x%02x.%02x%02x\n" , |
510 | fw[0], fw[1], fw[2], fw[3], |
511 | fw[4], fw[5], fw[6], fw[7]); |
512 | } |
513 | static DEVICE_ATTR(firmware_version, 0444, ili251x_firmware_version_show, NULL); |
514 | |
515 | static ssize_t ili251x_kernel_version_show(struct device *dev, |
516 | struct device_attribute *attr, |
517 | char *buf) |
518 | { |
519 | struct i2c_client *client = to_i2c_client(dev); |
520 | struct ili210x *priv = i2c_get_clientdata(client); |
521 | u8 *kv = priv->version_kernel; |
522 | |
523 | return sysfs_emit(buf, fmt: "%02x.%02x.%02x.%02x.%02x\n" , |
524 | kv[0], kv[1], kv[2], kv[3], kv[4]); |
525 | } |
526 | static DEVICE_ATTR(kernel_version, 0444, ili251x_kernel_version_show, NULL); |
527 | |
528 | static ssize_t ili251x_protocol_version_show(struct device *dev, |
529 | struct device_attribute *attr, |
530 | char *buf) |
531 | { |
532 | struct i2c_client *client = to_i2c_client(dev); |
533 | struct ili210x *priv = i2c_get_clientdata(client); |
534 | u8 *pv = priv->version_proto; |
535 | |
536 | return sysfs_emit(buf, fmt: "%02x.%02x\n" , pv[0], pv[1]); |
537 | } |
538 | static DEVICE_ATTR(protocol_version, 0444, ili251x_protocol_version_show, NULL); |
539 | |
540 | static ssize_t ili251x_mode_show(struct device *dev, |
541 | struct device_attribute *attr, char *buf) |
542 | { |
543 | struct i2c_client *client = to_i2c_client(dev); |
544 | struct ili210x *priv = i2c_get_clientdata(client); |
545 | u8 *md = priv->ic_mode; |
546 | char *mode = "AP" ; |
547 | |
548 | if (md[0] == REG_GET_MODE_AP) /* Application Mode */ |
549 | mode = "AP" ; |
550 | else if (md[0] == REG_GET_MODE_BL) /* BootLoader Mode */ |
551 | mode = "BL" ; |
552 | else /* Unknown Mode */ |
553 | mode = "??" ; |
554 | |
555 | return sysfs_emit(buf, fmt: "%02x.%02x:%s\n" , md[0], md[1], mode); |
556 | } |
557 | static DEVICE_ATTR(mode, 0444, ili251x_mode_show, NULL); |
558 | |
559 | static ssize_t ili210x_calibrate(struct device *dev, |
560 | struct device_attribute *attr, |
561 | const char *buf, size_t count) |
562 | { |
563 | struct i2c_client *client = to_i2c_client(dev); |
564 | struct ili210x *priv = i2c_get_clientdata(client); |
565 | unsigned long calibrate; |
566 | int rc; |
567 | u8 cmd = REG_CALIBRATE; |
568 | |
569 | if (kstrtoul(s: buf, base: 10, res: &calibrate)) |
570 | return -EINVAL; |
571 | |
572 | if (calibrate > 1) |
573 | return -EINVAL; |
574 | |
575 | if (calibrate) { |
576 | rc = i2c_master_send(client: priv->client, buf: &cmd, count: sizeof(cmd)); |
577 | if (rc != sizeof(cmd)) |
578 | return -EIO; |
579 | } |
580 | |
581 | return count; |
582 | } |
583 | static DEVICE_ATTR(calibrate, S_IWUSR, NULL, ili210x_calibrate); |
584 | |
585 | static int ili251x_firmware_to_buffer(const struct firmware *fw, |
586 | u8 **buf, u16 *ac_end, u16 *df_end) |
587 | { |
588 | const struct ihex_binrec *rec; |
589 | u32 fw_addr, fw_last_addr = 0; |
590 | u16 fw_len; |
591 | u8 *fw_buf; |
592 | int error; |
593 | |
594 | /* |
595 | * The firmware ihex blob can never be bigger than 64 kiB, so make this |
596 | * simple -- allocate a 64 kiB buffer, iterate over the ihex blob records |
597 | * once, copy them all into this buffer at the right locations, and then |
598 | * do all operations on this linear buffer. |
599 | */ |
600 | fw_buf = kzalloc(SZ_64K, GFP_KERNEL); |
601 | if (!fw_buf) |
602 | return -ENOMEM; |
603 | |
604 | rec = (const struct ihex_binrec *)fw->data; |
605 | while (rec) { |
606 | fw_addr = be32_to_cpu(rec->addr); |
607 | fw_len = be16_to_cpu(rec->len); |
608 | |
609 | /* The last 32 Byte firmware block can be 0xffe0 */ |
610 | if (fw_addr + fw_len > SZ_64K || fw_addr > SZ_64K - 32) { |
611 | error = -EFBIG; |
612 | goto err_big; |
613 | } |
614 | |
615 | /* Find the last address before DF start address, that is AC end */ |
616 | if (fw_addr == 0xf000) |
617 | *ac_end = fw_last_addr; |
618 | fw_last_addr = fw_addr + fw_len; |
619 | |
620 | memcpy(fw_buf + fw_addr, rec->data, fw_len); |
621 | rec = ihex_next_binrec(rec); |
622 | } |
623 | |
624 | /* DF end address is the last address in the firmware blob */ |
625 | *df_end = fw_addr + fw_len; |
626 | *buf = fw_buf; |
627 | return 0; |
628 | |
629 | err_big: |
630 | kfree(objp: fw_buf); |
631 | return error; |
632 | } |
633 | |
634 | /* Switch mode between Application and BootLoader */ |
635 | static int ili251x_switch_ic_mode(struct i2c_client *client, u8 cmd_mode) |
636 | { |
637 | struct ili210x *priv = i2c_get_clientdata(client); |
638 | u8 cmd_wren[3] = { REG_WRITE_ENABLE, 0x5a, 0xa5 }; |
639 | u8 md[2]; |
640 | int error; |
641 | |
642 | error = priv->chip->read_reg(client, REG_GET_MODE, md, sizeof(md)); |
643 | if (error) |
644 | return error; |
645 | /* Mode already set */ |
646 | if ((cmd_mode == REG_SET_MODE_AP && md[0] == REG_GET_MODE_AP) || |
647 | (cmd_mode == REG_SET_MODE_BL && md[0] == REG_GET_MODE_BL)) |
648 | return 0; |
649 | |
650 | /* Unlock writes */ |
651 | error = i2c_master_send(client, buf: cmd_wren, count: sizeof(cmd_wren)); |
652 | if (error != sizeof(cmd_wren)) |
653 | return -EINVAL; |
654 | |
655 | mdelay(20); |
656 | |
657 | /* Select mode (BootLoader or Application) */ |
658 | error = i2c_master_send(client, buf: &cmd_mode, count: 1); |
659 | if (error != 1) |
660 | return -EINVAL; |
661 | |
662 | mdelay(200); /* Reboot into bootloader takes a lot of time ... */ |
663 | |
664 | /* Read back mode */ |
665 | error = priv->chip->read_reg(client, REG_GET_MODE, md, sizeof(md)); |
666 | if (error) |
667 | return error; |
668 | /* Check if mode is correct now. */ |
669 | if ((cmd_mode == REG_SET_MODE_AP && md[0] == REG_GET_MODE_AP) || |
670 | (cmd_mode == REG_SET_MODE_BL && md[0] == REG_GET_MODE_BL)) |
671 | return 0; |
672 | |
673 | return -EINVAL; |
674 | } |
675 | |
676 | static int ili251x_firmware_busy(struct i2c_client *client) |
677 | { |
678 | struct ili210x *priv = i2c_get_clientdata(client); |
679 | int error, i = 0; |
680 | u8 data; |
681 | |
682 | do { |
683 | /* The read_reg already contains suitable delay */ |
684 | error = priv->chip->read_reg(client, REG_IC_BUSY, &data, 1); |
685 | if (error) |
686 | return error; |
687 | if (i++ == 100000) |
688 | return -ETIMEDOUT; |
689 | } while (data != REG_IC_BUSY_NOT_BUSY); |
690 | |
691 | return 0; |
692 | } |
693 | |
694 | static int ili251x_firmware_write_to_ic(struct device *dev, u8 *fwbuf, |
695 | u16 start, u16 end, u8 dataflash) |
696 | { |
697 | struct i2c_client *client = to_i2c_client(dev); |
698 | struct ili210x *priv = i2c_get_clientdata(client); |
699 | u8 cmd_crc = REG_READ_DATA_CRC; |
700 | u8 crcrb[4] = { 0 }; |
701 | u8 fw_data[33]; |
702 | u16 fw_addr; |
703 | int error; |
704 | |
705 | /* |
706 | * The DF (dataflash) needs 2 bytes offset for unknown reasons, |
707 | * the AC (application) has 2 bytes CRC16-CCITT at the end. |
708 | */ |
709 | u16 crc = crc_ccitt(crc: 0, buffer: fwbuf + start + (dataflash ? 2 : 0), |
710 | len: end - start - 2); |
711 | |
712 | /* Unlock write to either AC (application) or DF (dataflash) area */ |
713 | u8 cmd_wr[10] = { |
714 | REG_WRITE_ENABLE, 0x5a, 0xa5, dataflash, |
715 | (end >> 16) & 0xff, (end >> 8) & 0xff, end & 0xff, |
716 | (crc >> 16) & 0xff, (crc >> 8) & 0xff, crc & 0xff |
717 | }; |
718 | |
719 | error = i2c_master_send(client, buf: cmd_wr, count: sizeof(cmd_wr)); |
720 | if (error != sizeof(cmd_wr)) |
721 | return -EINVAL; |
722 | |
723 | error = ili251x_firmware_busy(client); |
724 | if (error) |
725 | return error; |
726 | |
727 | for (fw_addr = start; fw_addr < end; fw_addr += 32) { |
728 | fw_data[0] = REG_WRITE_DATA; |
729 | memcpy(&(fw_data[1]), fwbuf + fw_addr, 32); |
730 | error = i2c_master_send(client, buf: fw_data, count: 33); |
731 | if (error != sizeof(fw_data)) |
732 | return error; |
733 | error = ili251x_firmware_busy(client); |
734 | if (error) |
735 | return error; |
736 | } |
737 | |
738 | error = i2c_master_send(client, buf: &cmd_crc, count: 1); |
739 | if (error != 1) |
740 | return -EINVAL; |
741 | |
742 | error = ili251x_firmware_busy(client); |
743 | if (error) |
744 | return error; |
745 | |
746 | error = priv->chip->read_reg(client, REG_READ_DATA_CRC, |
747 | &crcrb, sizeof(crcrb)); |
748 | if (error) |
749 | return error; |
750 | |
751 | /* Check CRC readback */ |
752 | if ((crcrb[0] != (crc & 0xff)) || crcrb[1] != ((crc >> 8) & 0xff)) |
753 | return -EINVAL; |
754 | |
755 | return 0; |
756 | } |
757 | |
758 | static int ili251x_firmware_reset(struct i2c_client *client) |
759 | { |
760 | u8 cmd_reset[2] = { 0xf2, 0x01 }; |
761 | int error; |
762 | |
763 | error = i2c_master_send(client, buf: cmd_reset, count: sizeof(cmd_reset)); |
764 | if (error != sizeof(cmd_reset)) |
765 | return -EINVAL; |
766 | |
767 | return ili251x_firmware_busy(client); |
768 | } |
769 | |
770 | static void ili210x_hardware_reset(struct gpio_desc *reset_gpio) |
771 | { |
772 | /* Reset the controller */ |
773 | gpiod_set_value_cansleep(desc: reset_gpio, value: 1); |
774 | usleep_range(min: 12000, max: 15000); |
775 | gpiod_set_value_cansleep(desc: reset_gpio, value: 0); |
776 | msleep(msecs: 300); |
777 | } |
778 | |
779 | static ssize_t ili210x_firmware_update_store(struct device *dev, |
780 | struct device_attribute *attr, |
781 | const char *buf, size_t count) |
782 | { |
783 | struct i2c_client *client = to_i2c_client(dev); |
784 | struct ili210x *priv = i2c_get_clientdata(client); |
785 | const char *fwname = ILI251X_FW_FILENAME; |
786 | const struct firmware *fw; |
787 | u16 ac_end, df_end; |
788 | u8 *fwbuf; |
789 | int error; |
790 | int i; |
791 | |
792 | error = request_ihex_firmware(fw: &fw, fw_name: fwname, dev); |
793 | if (error) { |
794 | dev_err(dev, "Failed to request firmware %s, error=%d\n" , |
795 | fwname, error); |
796 | return error; |
797 | } |
798 | |
799 | error = ili251x_firmware_to_buffer(fw, buf: &fwbuf, ac_end: &ac_end, df_end: &df_end); |
800 | release_firmware(fw); |
801 | if (error) |
802 | return error; |
803 | |
804 | /* |
805 | * Disable touchscreen IRQ, so that we would not get spurious touch |
806 | * interrupt during firmware update, and so that the IRQ handler won't |
807 | * trigger and interfere with the firmware update. There is no bit in |
808 | * the touch controller to disable the IRQs during update, so we have |
809 | * to do it this way here. |
810 | */ |
811 | disable_irq(irq: client->irq); |
812 | |
813 | dev_dbg(dev, "Firmware update started, firmware=%s\n" , fwname); |
814 | |
815 | ili210x_hardware_reset(reset_gpio: priv->reset_gpio); |
816 | |
817 | error = ili251x_firmware_reset(client); |
818 | if (error) |
819 | goto exit; |
820 | |
821 | /* This may not succeed on first try, so re-try a few times. */ |
822 | for (i = 0; i < 5; i++) { |
823 | error = ili251x_switch_ic_mode(client, REG_SET_MODE_BL); |
824 | if (!error) |
825 | break; |
826 | } |
827 | |
828 | if (error) |
829 | goto exit; |
830 | |
831 | dev_dbg(dev, "IC is now in BootLoader mode\n" ); |
832 | |
833 | msleep(msecs: 200); /* The bootloader seems to need some time too. */ |
834 | |
835 | error = ili251x_firmware_write_to_ic(dev, fwbuf, start: 0xf000, end: df_end, dataflash: 1); |
836 | if (error) { |
837 | dev_err(dev, "DF firmware update failed, error=%d\n" , error); |
838 | goto exit; |
839 | } |
840 | |
841 | dev_dbg(dev, "DataFlash firmware written\n" ); |
842 | |
843 | error = ili251x_firmware_write_to_ic(dev, fwbuf, start: 0x2000, end: ac_end, dataflash: 0); |
844 | if (error) { |
845 | dev_err(dev, "AC firmware update failed, error=%d\n" , error); |
846 | goto exit; |
847 | } |
848 | |
849 | dev_dbg(dev, "Application firmware written\n" ); |
850 | |
851 | /* This may not succeed on first try, so re-try a few times. */ |
852 | for (i = 0; i < 5; i++) { |
853 | error = ili251x_switch_ic_mode(client, REG_SET_MODE_AP); |
854 | if (!error) |
855 | break; |
856 | } |
857 | |
858 | if (error) |
859 | goto exit; |
860 | |
861 | dev_dbg(dev, "IC is now in Application mode\n" ); |
862 | |
863 | error = ili251x_firmware_update_cached_state(dev); |
864 | if (error) |
865 | goto exit; |
866 | |
867 | error = count; |
868 | |
869 | exit: |
870 | ili210x_hardware_reset(reset_gpio: priv->reset_gpio); |
871 | dev_dbg(dev, "Firmware update ended, error=%i\n" , error); |
872 | enable_irq(irq: client->irq); |
873 | kfree(objp: fwbuf); |
874 | return error; |
875 | } |
876 | |
877 | static DEVICE_ATTR(firmware_update, 0200, NULL, ili210x_firmware_update_store); |
878 | |
879 | static struct attribute *ili210x_attributes[] = { |
880 | &dev_attr_calibrate.attr, |
881 | &dev_attr_firmware_update.attr, |
882 | &dev_attr_firmware_version.attr, |
883 | &dev_attr_kernel_version.attr, |
884 | &dev_attr_protocol_version.attr, |
885 | &dev_attr_mode.attr, |
886 | NULL, |
887 | }; |
888 | |
889 | static umode_t ili210x_attributes_visible(struct kobject *kobj, |
890 | struct attribute *attr, int index) |
891 | { |
892 | struct device *dev = kobj_to_dev(kobj); |
893 | struct i2c_client *client = to_i2c_client(dev); |
894 | struct ili210x *priv = i2c_get_clientdata(client); |
895 | |
896 | /* Calibrate is present on all ILI2xxx which have calibrate register */ |
897 | if (attr == &dev_attr_calibrate.attr) |
898 | return priv->chip->has_calibrate_reg ? attr->mode : 0; |
899 | |
900 | /* Firmware/Kernel/Protocol/BootMode is implememted only for ILI251x */ |
901 | if (!priv->chip->has_firmware_proto) |
902 | return 0; |
903 | |
904 | return attr->mode; |
905 | } |
906 | |
907 | static const struct attribute_group ili210x_attr_group = { |
908 | .attrs = ili210x_attributes, |
909 | .is_visible = ili210x_attributes_visible, |
910 | }; |
911 | |
912 | static void ili210x_power_down(void *data) |
913 | { |
914 | struct gpio_desc *reset_gpio = data; |
915 | |
916 | gpiod_set_value_cansleep(desc: reset_gpio, value: 1); |
917 | } |
918 | |
919 | static void ili210x_stop(void *data) |
920 | { |
921 | struct ili210x *priv = data; |
922 | |
923 | /* Tell ISR to quit even if there is a contact. */ |
924 | priv->stop = true; |
925 | } |
926 | |
927 | static int ili210x_i2c_probe(struct i2c_client *client) |
928 | { |
929 | const struct i2c_device_id *id = i2c_client_get_device_id(client); |
930 | struct device *dev = &client->dev; |
931 | const struct ili2xxx_chip *chip; |
932 | struct ili210x *priv; |
933 | struct gpio_desc *reset_gpio; |
934 | struct input_dev *input; |
935 | int error; |
936 | unsigned int max_xy; |
937 | |
938 | dev_dbg(dev, "Probing for ILI210X I2C Touschreen driver" ); |
939 | |
940 | chip = device_get_match_data(dev); |
941 | if (!chip && id) |
942 | chip = (const struct ili2xxx_chip *)id->driver_data; |
943 | if (!chip) { |
944 | dev_err(&client->dev, "unknown device model\n" ); |
945 | return -ENODEV; |
946 | } |
947 | |
948 | if (client->irq <= 0) { |
949 | dev_err(dev, "No IRQ!\n" ); |
950 | return -EINVAL; |
951 | } |
952 | |
953 | reset_gpio = devm_gpiod_get_optional(dev, con_id: "reset" , flags: GPIOD_OUT_HIGH); |
954 | if (IS_ERR(ptr: reset_gpio)) |
955 | return PTR_ERR(ptr: reset_gpio); |
956 | |
957 | if (reset_gpio) { |
958 | error = devm_add_action_or_reset(dev, ili210x_power_down, |
959 | reset_gpio); |
960 | if (error) |
961 | return error; |
962 | |
963 | ili210x_hardware_reset(reset_gpio); |
964 | } |
965 | |
966 | priv = devm_kzalloc(dev, size: sizeof(*priv), GFP_KERNEL); |
967 | if (!priv) |
968 | return -ENOMEM; |
969 | |
970 | input = devm_input_allocate_device(dev); |
971 | if (!input) |
972 | return -ENOMEM; |
973 | |
974 | priv->client = client; |
975 | priv->input = input; |
976 | priv->reset_gpio = reset_gpio; |
977 | priv->chip = chip; |
978 | i2c_set_clientdata(client, data: priv); |
979 | |
980 | /* Setup input device */ |
981 | input->name = "ILI210x Touchscreen" ; |
982 | input->id.bustype = BUS_I2C; |
983 | |
984 | /* Multi touch */ |
985 | max_xy = (chip->resolution ?: SZ_64K) - 1; |
986 | input_set_abs_params(dev: input, ABS_MT_POSITION_X, min: 0, max: max_xy, fuzz: 0, flat: 0); |
987 | input_set_abs_params(dev: input, ABS_MT_POSITION_Y, min: 0, max: max_xy, fuzz: 0, flat: 0); |
988 | if (priv->chip->has_pressure_reg) |
989 | input_set_abs_params(dev: input, ABS_MT_PRESSURE, min: 0, max: 0xa, fuzz: 0, flat: 0); |
990 | error = ili251x_firmware_update_cached_state(dev); |
991 | if (error) |
992 | dev_warn(dev, "Unable to cache firmware information, err: %d\n" , |
993 | error); |
994 | |
995 | touchscreen_parse_properties(input, multitouch: true, prop: &priv->prop); |
996 | |
997 | error = input_mt_init_slots(dev: input, num_slots: priv->chip->max_touches, |
998 | INPUT_MT_DIRECT); |
999 | if (error) { |
1000 | dev_err(dev, "Unable to set up slots, err: %d\n" , error); |
1001 | return error; |
1002 | } |
1003 | |
1004 | error = devm_request_threaded_irq(dev, irq: client->irq, NULL, thread_fn: ili210x_irq, |
1005 | IRQF_ONESHOT, devname: client->name, dev_id: priv); |
1006 | if (error) { |
1007 | dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n" , |
1008 | error); |
1009 | return error; |
1010 | } |
1011 | |
1012 | error = devm_add_action_or_reset(dev, ili210x_stop, priv); |
1013 | if (error) |
1014 | return error; |
1015 | |
1016 | error = devm_device_add_group(dev, grp: &ili210x_attr_group); |
1017 | if (error) { |
1018 | dev_err(dev, "Unable to create sysfs attributes, err: %d\n" , |
1019 | error); |
1020 | return error; |
1021 | } |
1022 | |
1023 | error = input_register_device(priv->input); |
1024 | if (error) { |
1025 | dev_err(dev, "Cannot register input device, err: %d\n" , error); |
1026 | return error; |
1027 | } |
1028 | |
1029 | return 0; |
1030 | } |
1031 | |
1032 | static const struct i2c_device_id ili210x_i2c_id[] = { |
1033 | { "ili210x" , (long)&ili210x_chip }, |
1034 | { "ili2117" , (long)&ili211x_chip }, |
1035 | { "ili2120" , (long)&ili212x_chip }, |
1036 | { "ili251x" , (long)&ili251x_chip }, |
1037 | { } |
1038 | }; |
1039 | MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id); |
1040 | |
1041 | static const struct of_device_id ili210x_dt_ids[] = { |
1042 | { .compatible = "ilitek,ili210x" , .data = &ili210x_chip }, |
1043 | { .compatible = "ilitek,ili2117" , .data = &ili211x_chip }, |
1044 | { .compatible = "ilitek,ili2120" , .data = &ili212x_chip }, |
1045 | { .compatible = "ilitek,ili251x" , .data = &ili251x_chip }, |
1046 | { } |
1047 | }; |
1048 | MODULE_DEVICE_TABLE(of, ili210x_dt_ids); |
1049 | |
1050 | static struct i2c_driver ili210x_ts_driver = { |
1051 | .driver = { |
1052 | .name = "ili210x_i2c" , |
1053 | .of_match_table = ili210x_dt_ids, |
1054 | }, |
1055 | .id_table = ili210x_i2c_id, |
1056 | .probe = ili210x_i2c_probe, |
1057 | }; |
1058 | |
1059 | module_i2c_driver(ili210x_ts_driver); |
1060 | |
1061 | MODULE_AUTHOR("Olivier Sobrie <olivier@sobrie.be>" ); |
1062 | MODULE_DESCRIPTION("ILI210X I2C Touchscreen Driver" ); |
1063 | MODULE_LICENSE("GPL" ); |
1064 | |