1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (C) 2012-2017 Hideep, Inc. |
4 | */ |
5 | |
6 | #include <linux/module.h> |
7 | #include <linux/of.h> |
8 | #include <linux/firmware.h> |
9 | #include <linux/delay.h> |
10 | #include <linux/gpio/consumer.h> |
11 | #include <linux/i2c.h> |
12 | #include <linux/acpi.h> |
13 | #include <linux/interrupt.h> |
14 | #include <linux/regmap.h> |
15 | #include <linux/sysfs.h> |
16 | #include <linux/input.h> |
17 | #include <linux/input/mt.h> |
18 | #include <linux/input/touchscreen.h> |
19 | #include <linux/regulator/consumer.h> |
20 | #include <asm/unaligned.h> |
21 | |
22 | #define HIDEEP_TS_NAME "HiDeep Touchscreen" |
23 | #define HIDEEP_I2C_NAME "hideep_ts" |
24 | |
25 | #define HIDEEP_MT_MAX 10 |
26 | #define HIDEEP_KEY_MAX 3 |
27 | |
28 | /* count(2) + touch data(100) + key data(6) */ |
29 | #define HIDEEP_MAX_EVENT 108UL |
30 | |
31 | #define HIDEEP_TOUCH_EVENT_INDEX 2 |
32 | #define HIDEEP_KEY_EVENT_INDEX 102 |
33 | |
34 | /* Touch & key event */ |
35 | #define HIDEEP_EVENT_ADDR 0x240 |
36 | |
37 | /* command list */ |
38 | #define HIDEEP_WORK_MODE 0x081e |
39 | #define HIDEEP_RESET_CMD 0x9800 |
40 | |
41 | /* event bit */ |
42 | #define HIDEEP_MT_RELEASED BIT(4) |
43 | #define HIDEEP_KEY_PRESSED BIT(7) |
44 | #define HIDEEP_KEY_FIRST_PRESSED BIT(8) |
45 | #define HIDEEP_KEY_PRESSED_MASK (HIDEEP_KEY_PRESSED | \ |
46 | HIDEEP_KEY_FIRST_PRESSED) |
47 | |
48 | #define HIDEEP_KEY_IDX_MASK 0x0f |
49 | |
50 | /* For NVM */ |
51 | #define HIDEEP_YRAM_BASE 0x40000000 |
52 | #define HIDEEP_PERIPHERAL_BASE 0x50000000 |
53 | #define HIDEEP_ESI_BASE (HIDEEP_PERIPHERAL_BASE + 0x00000000) |
54 | #define HIDEEP_FLASH_BASE (HIDEEP_PERIPHERAL_BASE + 0x01000000) |
55 | #define HIDEEP_SYSCON_BASE (HIDEEP_PERIPHERAL_BASE + 0x02000000) |
56 | |
57 | #define HIDEEP_SYSCON_MOD_CON (HIDEEP_SYSCON_BASE + 0x0000) |
58 | #define HIDEEP_SYSCON_SPC_CON (HIDEEP_SYSCON_BASE + 0x0004) |
59 | #define HIDEEP_SYSCON_CLK_CON (HIDEEP_SYSCON_BASE + 0x0008) |
60 | #define HIDEEP_SYSCON_CLK_ENA (HIDEEP_SYSCON_BASE + 0x000C) |
61 | #define HIDEEP_SYSCON_RST_CON (HIDEEP_SYSCON_BASE + 0x0010) |
62 | #define HIDEEP_SYSCON_WDT_CON (HIDEEP_SYSCON_BASE + 0x0014) |
63 | #define HIDEEP_SYSCON_WDT_CNT (HIDEEP_SYSCON_BASE + 0x0018) |
64 | #define HIDEEP_SYSCON_PWR_CON (HIDEEP_SYSCON_BASE + 0x0020) |
65 | #define HIDEEP_SYSCON_PGM_ID (HIDEEP_SYSCON_BASE + 0x00F4) |
66 | |
67 | #define HIDEEP_FLASH_CON (HIDEEP_FLASH_BASE + 0x0000) |
68 | #define HIDEEP_FLASH_STA (HIDEEP_FLASH_BASE + 0x0004) |
69 | #define HIDEEP_FLASH_CFG (HIDEEP_FLASH_BASE + 0x0008) |
70 | #define HIDEEP_FLASH_TIM (HIDEEP_FLASH_BASE + 0x000C) |
71 | #define HIDEEP_FLASH_CACHE_CFG (HIDEEP_FLASH_BASE + 0x0010) |
72 | #define HIDEEP_FLASH_PIO_SIG (HIDEEP_FLASH_BASE + 0x400000) |
73 | |
74 | #define HIDEEP_ESI_TX_INVALID (HIDEEP_ESI_BASE + 0x0008) |
75 | |
76 | #define HIDEEP_PERASE 0x00040000 |
77 | #define HIDEEP_WRONLY 0x00100000 |
78 | |
79 | #define HIDEEP_NVM_MASK_OFS 0x0000000C |
80 | #define HIDEEP_NVM_DEFAULT_PAGE 0 |
81 | #define HIDEEP_NVM_SFR_WPAGE 1 |
82 | #define HIDEEP_NVM_SFR_RPAGE 2 |
83 | |
84 | #define HIDEEP_PIO_SIG 0x00400000 |
85 | #define HIDEEP_PROT_MODE 0x03400000 |
86 | |
87 | #define HIDEEP_NVM_PAGE_SIZE 128 |
88 | |
89 | #define HIDEEP_DWZ_INFO 0x000002C0 |
90 | |
91 | struct hideep_event { |
92 | __le16 x; |
93 | __le16 y; |
94 | __le16 z; |
95 | u8 w; |
96 | u8 flag; |
97 | u8 type; |
98 | u8 index; |
99 | }; |
100 | |
101 | struct dwz_info { |
102 | __be32 code_start; |
103 | u8 code_crc[12]; |
104 | |
105 | __be32 c_code_start; |
106 | __be16 gen_ver; |
107 | __be16 c_code_len; |
108 | |
109 | __be32 vr_start; |
110 | __be16 rsv0; |
111 | __be16 vr_len; |
112 | |
113 | __be32 ft_start; |
114 | __be16 vr_version; |
115 | __be16 ft_len; |
116 | |
117 | __be16 core_ver; |
118 | __be16 boot_ver; |
119 | |
120 | __be16 release_ver; |
121 | __be16 custom_ver; |
122 | |
123 | u8 factory_id; |
124 | u8 panel_type; |
125 | u8 model_name[6]; |
126 | |
127 | __be16 ; |
128 | __be16 product_code; |
129 | |
130 | __be16 vendor_id; |
131 | __be16 product_id; |
132 | }; |
133 | |
134 | struct pgm_packet { |
135 | struct { |
136 | u8 unused[3]; |
137 | u8 len; |
138 | __be32 addr; |
139 | } ; |
140 | __be32 payload[HIDEEP_NVM_PAGE_SIZE / sizeof(__be32)]; |
141 | }; |
142 | |
143 | #define HIDEEP_XFER_BUF_SIZE sizeof(struct pgm_packet) |
144 | |
145 | struct hideep_ts { |
146 | struct i2c_client *client; |
147 | struct input_dev *input_dev; |
148 | struct regmap *reg; |
149 | |
150 | struct touchscreen_properties prop; |
151 | |
152 | struct gpio_desc *reset_gpio; |
153 | |
154 | struct regulator *vcc_vdd; |
155 | struct regulator *vcc_vid; |
156 | |
157 | struct mutex dev_mutex; |
158 | |
159 | u32 tch_count; |
160 | u32 lpm_count; |
161 | |
162 | /* |
163 | * Data buffer to read packet from the device (contacts and key |
164 | * states). We align it on double-word boundary to keep word-sized |
165 | * fields in contact data and double-word-sized fields in program |
166 | * packet aligned. |
167 | */ |
168 | u8 xfer_buf[HIDEEP_XFER_BUF_SIZE] __aligned(4); |
169 | |
170 | int key_num; |
171 | u32 key_codes[HIDEEP_KEY_MAX]; |
172 | |
173 | struct dwz_info dwz_info; |
174 | |
175 | unsigned int fw_size; |
176 | u32 nvm_mask; |
177 | }; |
178 | |
179 | static int hideep_pgm_w_mem(struct hideep_ts *ts, u32 addr, |
180 | const __be32 *data, size_t count) |
181 | { |
182 | struct pgm_packet *packet = (void *)ts->xfer_buf; |
183 | size_t len = count * sizeof(*data); |
184 | struct i2c_msg msg = { |
185 | .addr = ts->client->addr, |
186 | .len = len + sizeof(packet->header.len) + |
187 | sizeof(packet->header.addr), |
188 | .buf = &packet->header.len, |
189 | }; |
190 | int ret; |
191 | |
192 | if (len > HIDEEP_NVM_PAGE_SIZE) |
193 | return -EINVAL; |
194 | |
195 | packet->header.len = 0x80 | (count - 1); |
196 | packet->header.addr = cpu_to_be32(addr); |
197 | memcpy(packet->payload, data, len); |
198 | |
199 | ret = i2c_transfer(adap: ts->client->adapter, msgs: &msg, num: 1); |
200 | if (ret != 1) |
201 | return ret < 0 ? ret : -EIO; |
202 | |
203 | return 0; |
204 | } |
205 | |
206 | static int hideep_pgm_r_mem(struct hideep_ts *ts, u32 addr, |
207 | __be32 *data, size_t count) |
208 | { |
209 | struct pgm_packet *packet = (void *)ts->xfer_buf; |
210 | size_t len = count * sizeof(*data); |
211 | struct i2c_msg msg[] = { |
212 | { |
213 | .addr = ts->client->addr, |
214 | .len = sizeof(packet->header.len) + |
215 | sizeof(packet->header.addr), |
216 | .buf = &packet->header.len, |
217 | }, |
218 | { |
219 | .addr = ts->client->addr, |
220 | .flags = I2C_M_RD, |
221 | .len = len, |
222 | .buf = (u8 *)data, |
223 | }, |
224 | }; |
225 | int ret; |
226 | |
227 | if (len > HIDEEP_NVM_PAGE_SIZE) |
228 | return -EINVAL; |
229 | |
230 | packet->header.len = count - 1; |
231 | packet->header.addr = cpu_to_be32(addr); |
232 | |
233 | ret = i2c_transfer(adap: ts->client->adapter, msgs: msg, ARRAY_SIZE(msg)); |
234 | if (ret != ARRAY_SIZE(msg)) |
235 | return ret < 0 ? ret : -EIO; |
236 | |
237 | return 0; |
238 | } |
239 | |
240 | static int hideep_pgm_r_reg(struct hideep_ts *ts, u32 addr, u32 *val) |
241 | { |
242 | __be32 data; |
243 | int error; |
244 | |
245 | error = hideep_pgm_r_mem(ts, addr, data: &data, count: 1); |
246 | if (error) { |
247 | dev_err(&ts->client->dev, |
248 | "read of register %#08x failed: %d\n" , |
249 | addr, error); |
250 | return error; |
251 | } |
252 | |
253 | *val = be32_to_cpu(data); |
254 | return 0; |
255 | } |
256 | |
257 | static int hideep_pgm_w_reg(struct hideep_ts *ts, u32 addr, u32 val) |
258 | { |
259 | __be32 data = cpu_to_be32(val); |
260 | int error; |
261 | |
262 | error = hideep_pgm_w_mem(ts, addr, data: &data, count: 1); |
263 | if (error) { |
264 | dev_err(&ts->client->dev, |
265 | "write to register %#08x (%#08x) failed: %d\n" , |
266 | addr, val, error); |
267 | return error; |
268 | } |
269 | |
270 | return 0; |
271 | } |
272 | |
273 | #define SW_RESET_IN_PGM(clk) \ |
274 | { \ |
275 | __be32 data = cpu_to_be32(0x01); \ |
276 | hideep_pgm_w_reg(ts, HIDEEP_SYSCON_WDT_CNT, (clk)); \ |
277 | hideep_pgm_w_reg(ts, HIDEEP_SYSCON_WDT_CON, 0x03); \ |
278 | /* \ |
279 | * The first write may already cause a reset, use a raw \ |
280 | * write for the second write to avoid error logging. \ |
281 | */ \ |
282 | hideep_pgm_w_mem(ts, HIDEEP_SYSCON_WDT_CON, &data, 1); \ |
283 | } |
284 | |
285 | #define SET_FLASH_PIO(ce) \ |
286 | hideep_pgm_w_reg(ts, HIDEEP_FLASH_CON, \ |
287 | 0x01 | ((ce) << 1)) |
288 | |
289 | #define SET_PIO_SIG(x, y) \ |
290 | hideep_pgm_w_reg(ts, HIDEEP_FLASH_PIO_SIG + (x), (y)) |
291 | |
292 | #define SET_FLASH_HWCONTROL() \ |
293 | hideep_pgm_w_reg(ts, HIDEEP_FLASH_CON, 0x00) |
294 | |
295 | #define NVM_W_SFR(x, y) \ |
296 | { \ |
297 | SET_FLASH_PIO(1); \ |
298 | SET_PIO_SIG(x, y); \ |
299 | SET_FLASH_PIO(0); \ |
300 | } |
301 | |
302 | static void hideep_pgm_set(struct hideep_ts *ts) |
303 | { |
304 | hideep_pgm_w_reg(ts, HIDEEP_SYSCON_WDT_CON, val: 0x00); |
305 | hideep_pgm_w_reg(ts, HIDEEP_SYSCON_SPC_CON, val: 0x00); |
306 | hideep_pgm_w_reg(ts, HIDEEP_SYSCON_CLK_ENA, val: 0xFF); |
307 | hideep_pgm_w_reg(ts, HIDEEP_SYSCON_CLK_CON, val: 0x01); |
308 | hideep_pgm_w_reg(ts, HIDEEP_SYSCON_PWR_CON, val: 0x01); |
309 | hideep_pgm_w_reg(ts, HIDEEP_FLASH_TIM, val: 0x03); |
310 | hideep_pgm_w_reg(ts, HIDEEP_FLASH_CACHE_CFG, val: 0x00); |
311 | } |
312 | |
313 | static int hideep_pgm_get_pattern(struct hideep_ts *ts, u32 *pattern) |
314 | { |
315 | u16 p1 = 0xAF39; |
316 | u16 p2 = 0xDF9D; |
317 | int error; |
318 | |
319 | error = regmap_bulk_write(map: ts->reg, reg: p1, val: &p2, val_count: 1); |
320 | if (error) { |
321 | dev_err(&ts->client->dev, |
322 | "%s: regmap_bulk_write() failed with %d\n" , |
323 | __func__, error); |
324 | return error; |
325 | } |
326 | |
327 | usleep_range(min: 1000, max: 1100); |
328 | |
329 | /* flush invalid Tx load register */ |
330 | error = hideep_pgm_w_reg(ts, HIDEEP_ESI_TX_INVALID, val: 0x01); |
331 | if (error) |
332 | return error; |
333 | |
334 | error = hideep_pgm_r_reg(ts, HIDEEP_SYSCON_PGM_ID, val: pattern); |
335 | if (error) |
336 | return error; |
337 | |
338 | return 0; |
339 | } |
340 | |
341 | static int hideep_enter_pgm(struct hideep_ts *ts) |
342 | { |
343 | int retry_count = 10; |
344 | u32 pattern; |
345 | int error; |
346 | |
347 | while (retry_count--) { |
348 | error = hideep_pgm_get_pattern(ts, pattern: &pattern); |
349 | if (error) { |
350 | dev_err(&ts->client->dev, |
351 | "hideep_pgm_get_pattern failed: %d\n" , error); |
352 | } else if (pattern != 0x39AF9DDF) { |
353 | dev_err(&ts->client->dev, "%s: bad pattern: %#08x\n" , |
354 | __func__, pattern); |
355 | } else { |
356 | dev_dbg(&ts->client->dev, "found magic code" ); |
357 | |
358 | hideep_pgm_set(ts); |
359 | usleep_range(min: 1000, max: 1100); |
360 | |
361 | return 0; |
362 | } |
363 | } |
364 | |
365 | dev_err(&ts->client->dev, "failed to enter pgm mode\n" ); |
366 | SW_RESET_IN_PGM(1000); |
367 | return -EIO; |
368 | } |
369 | |
370 | static int hideep_nvm_unlock(struct hideep_ts *ts) |
371 | { |
372 | u32 unmask_code; |
373 | int error; |
374 | |
375 | hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_SFR_RPAGE); |
376 | error = hideep_pgm_r_reg(ts, addr: 0x0000000C, val: &unmask_code); |
377 | hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_DEFAULT_PAGE); |
378 | if (error) |
379 | return error; |
380 | |
381 | /* make it unprotected code */ |
382 | unmask_code &= ~HIDEEP_PROT_MODE; |
383 | |
384 | /* compare unmask code */ |
385 | if (unmask_code != ts->nvm_mask) |
386 | dev_warn(&ts->client->dev, |
387 | "read mask code different %#08x vs %#08x" , |
388 | unmask_code, ts->nvm_mask); |
389 | |
390 | hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_SFR_WPAGE); |
391 | SET_FLASH_PIO(0); |
392 | |
393 | NVM_W_SFR(HIDEEP_NVM_MASK_OFS, ts->nvm_mask); |
394 | SET_FLASH_HWCONTROL(); |
395 | hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_DEFAULT_PAGE); |
396 | |
397 | return 0; |
398 | } |
399 | |
400 | static int hideep_check_status(struct hideep_ts *ts) |
401 | { |
402 | int time_out = 100; |
403 | int status; |
404 | int error; |
405 | |
406 | while (time_out--) { |
407 | error = hideep_pgm_r_reg(ts, HIDEEP_FLASH_STA, val: &status); |
408 | if (!error && status) |
409 | return 0; |
410 | |
411 | usleep_range(min: 1000, max: 1100); |
412 | } |
413 | |
414 | return -ETIMEDOUT; |
415 | } |
416 | |
417 | static int hideep_program_page(struct hideep_ts *ts, u32 addr, |
418 | const __be32 *ucode, size_t xfer_count) |
419 | { |
420 | u32 val; |
421 | int error; |
422 | |
423 | error = hideep_check_status(ts); |
424 | if (error) |
425 | return -EBUSY; |
426 | |
427 | addr &= ~(HIDEEP_NVM_PAGE_SIZE - 1); |
428 | |
429 | SET_FLASH_PIO(0); |
430 | SET_FLASH_PIO(1); |
431 | |
432 | /* erase page */ |
433 | SET_PIO_SIG(HIDEEP_PERASE | addr, 0xFFFFFFFF); |
434 | |
435 | SET_FLASH_PIO(0); |
436 | |
437 | error = hideep_check_status(ts); |
438 | if (error) |
439 | return -EBUSY; |
440 | |
441 | /* write page */ |
442 | SET_FLASH_PIO(1); |
443 | |
444 | val = be32_to_cpu(ucode[0]); |
445 | SET_PIO_SIG(HIDEEP_WRONLY | addr, val); |
446 | |
447 | hideep_pgm_w_mem(ts, HIDEEP_FLASH_PIO_SIG | HIDEEP_WRONLY, |
448 | data: ucode, count: xfer_count); |
449 | |
450 | val = be32_to_cpu(ucode[xfer_count - 1]); |
451 | SET_PIO_SIG(124, val); |
452 | |
453 | SET_FLASH_PIO(0); |
454 | |
455 | usleep_range(min: 1000, max: 1100); |
456 | |
457 | error = hideep_check_status(ts); |
458 | if (error) |
459 | return -EBUSY; |
460 | |
461 | SET_FLASH_HWCONTROL(); |
462 | |
463 | return 0; |
464 | } |
465 | |
466 | static int hideep_program_nvm(struct hideep_ts *ts, |
467 | const __be32 *ucode, size_t ucode_len) |
468 | { |
469 | struct pgm_packet *packet_r = (void *)ts->xfer_buf; |
470 | __be32 *current_ucode = packet_r->payload; |
471 | size_t xfer_len; |
472 | size_t xfer_count; |
473 | u32 addr = 0; |
474 | int error; |
475 | |
476 | error = hideep_nvm_unlock(ts); |
477 | if (error) |
478 | return error; |
479 | |
480 | while (ucode_len > 0) { |
481 | xfer_len = min_t(size_t, ucode_len, HIDEEP_NVM_PAGE_SIZE); |
482 | xfer_count = xfer_len / sizeof(*ucode); |
483 | |
484 | error = hideep_pgm_r_mem(ts, addr: 0x00000000 + addr, |
485 | data: current_ucode, count: xfer_count); |
486 | if (error) { |
487 | dev_err(&ts->client->dev, |
488 | "%s: failed to read page at offset %#08x: %d\n" , |
489 | __func__, addr, error); |
490 | return error; |
491 | } |
492 | |
493 | /* See if the page needs updating */ |
494 | if (memcmp(p: ucode, q: current_ucode, size: xfer_len)) { |
495 | error = hideep_program_page(ts, addr, |
496 | ucode, xfer_count); |
497 | if (error) { |
498 | dev_err(&ts->client->dev, |
499 | "%s: iwrite failure @%#08x: %d\n" , |
500 | __func__, addr, error); |
501 | return error; |
502 | } |
503 | |
504 | usleep_range(min: 1000, max: 1100); |
505 | } |
506 | |
507 | ucode += xfer_count; |
508 | addr += xfer_len; |
509 | ucode_len -= xfer_len; |
510 | } |
511 | |
512 | return 0; |
513 | } |
514 | |
515 | static int hideep_verify_nvm(struct hideep_ts *ts, |
516 | const __be32 *ucode, size_t ucode_len) |
517 | { |
518 | struct pgm_packet *packet_r = (void *)ts->xfer_buf; |
519 | __be32 *current_ucode = packet_r->payload; |
520 | size_t xfer_len; |
521 | size_t xfer_count; |
522 | u32 addr = 0; |
523 | int i; |
524 | int error; |
525 | |
526 | while (ucode_len > 0) { |
527 | xfer_len = min_t(size_t, ucode_len, HIDEEP_NVM_PAGE_SIZE); |
528 | xfer_count = xfer_len / sizeof(*ucode); |
529 | |
530 | error = hideep_pgm_r_mem(ts, addr: 0x00000000 + addr, |
531 | data: current_ucode, count: xfer_count); |
532 | if (error) { |
533 | dev_err(&ts->client->dev, |
534 | "%s: failed to read page at offset %#08x: %d\n" , |
535 | __func__, addr, error); |
536 | return error; |
537 | } |
538 | |
539 | if (memcmp(p: ucode, q: current_ucode, size: xfer_len)) { |
540 | const u8 *ucode_bytes = (const u8 *)ucode; |
541 | const u8 *current_bytes = (const u8 *)current_ucode; |
542 | |
543 | for (i = 0; i < xfer_len; i++) |
544 | if (ucode_bytes[i] != current_bytes[i]) |
545 | dev_err(&ts->client->dev, |
546 | "%s: mismatch @%#08x: (%#02x vs %#02x)\n" , |
547 | __func__, addr + i, |
548 | ucode_bytes[i], |
549 | current_bytes[i]); |
550 | |
551 | return -EIO; |
552 | } |
553 | |
554 | ucode += xfer_count; |
555 | addr += xfer_len; |
556 | ucode_len -= xfer_len; |
557 | } |
558 | |
559 | return 0; |
560 | } |
561 | |
562 | static int hideep_load_dwz(struct hideep_ts *ts) |
563 | { |
564 | u16 product_code; |
565 | int error; |
566 | |
567 | error = hideep_enter_pgm(ts); |
568 | if (error) |
569 | return error; |
570 | |
571 | msleep(msecs: 50); |
572 | |
573 | error = hideep_pgm_r_mem(ts, HIDEEP_DWZ_INFO, |
574 | data: (void *)&ts->dwz_info, |
575 | count: sizeof(ts->dwz_info) / sizeof(__be32)); |
576 | |
577 | SW_RESET_IN_PGM(10); |
578 | msleep(msecs: 50); |
579 | |
580 | if (error) { |
581 | dev_err(&ts->client->dev, |
582 | "failed to fetch DWZ data: %d\n" , error); |
583 | return error; |
584 | } |
585 | |
586 | product_code = be16_to_cpu(ts->dwz_info.product_code); |
587 | |
588 | switch (product_code & 0xF0) { |
589 | case 0x40: |
590 | dev_dbg(&ts->client->dev, "used crimson IC" ); |
591 | ts->fw_size = 1024 * 48; |
592 | ts->nvm_mask = 0x00310000; |
593 | break; |
594 | case 0x60: |
595 | dev_dbg(&ts->client->dev, "used lime IC" ); |
596 | ts->fw_size = 1024 * 64; |
597 | ts->nvm_mask = 0x0030027B; |
598 | break; |
599 | default: |
600 | dev_err(&ts->client->dev, "product code is wrong: %#04x" , |
601 | product_code); |
602 | return -EINVAL; |
603 | } |
604 | |
605 | dev_dbg(&ts->client->dev, "firmware release version: %#04x" , |
606 | be16_to_cpu(ts->dwz_info.release_ver)); |
607 | |
608 | return 0; |
609 | } |
610 | |
611 | static int hideep_flash_firmware(struct hideep_ts *ts, |
612 | const __be32 *ucode, size_t ucode_len) |
613 | { |
614 | int retry_cnt = 3; |
615 | int error; |
616 | |
617 | while (retry_cnt--) { |
618 | error = hideep_program_nvm(ts, ucode, ucode_len); |
619 | if (!error) { |
620 | error = hideep_verify_nvm(ts, ucode, ucode_len); |
621 | if (!error) |
622 | return 0; |
623 | } |
624 | } |
625 | |
626 | return error; |
627 | } |
628 | |
629 | static int hideep_update_firmware(struct hideep_ts *ts, |
630 | const __be32 *ucode, size_t ucode_len) |
631 | { |
632 | int error, error2; |
633 | |
634 | dev_dbg(&ts->client->dev, "starting firmware update" ); |
635 | |
636 | /* enter program mode */ |
637 | error = hideep_enter_pgm(ts); |
638 | if (error) |
639 | return error; |
640 | |
641 | error = hideep_flash_firmware(ts, ucode, ucode_len); |
642 | if (error) |
643 | dev_err(&ts->client->dev, |
644 | "firmware update failed: %d\n" , error); |
645 | else |
646 | dev_dbg(&ts->client->dev, "firmware updated successfully\n" ); |
647 | |
648 | SW_RESET_IN_PGM(1000); |
649 | |
650 | error2 = hideep_load_dwz(ts); |
651 | if (error2) |
652 | dev_err(&ts->client->dev, |
653 | "failed to load dwz after firmware update: %d\n" , |
654 | error2); |
655 | |
656 | return error ?: error2; |
657 | } |
658 | |
659 | static int hideep_power_on(struct hideep_ts *ts) |
660 | { |
661 | int error = 0; |
662 | |
663 | error = regulator_enable(regulator: ts->vcc_vdd); |
664 | if (error) |
665 | dev_err(&ts->client->dev, |
666 | "failed to enable 'vdd' regulator: %d" , error); |
667 | |
668 | usleep_range(min: 999, max: 1000); |
669 | |
670 | error = regulator_enable(regulator: ts->vcc_vid); |
671 | if (error) |
672 | dev_err(&ts->client->dev, |
673 | "failed to enable 'vcc_vid' regulator: %d" , |
674 | error); |
675 | |
676 | msleep(msecs: 30); |
677 | |
678 | if (ts->reset_gpio) { |
679 | gpiod_set_value_cansleep(desc: ts->reset_gpio, value: 0); |
680 | } else { |
681 | error = regmap_write(map: ts->reg, HIDEEP_RESET_CMD, val: 0x01); |
682 | if (error) |
683 | dev_err(&ts->client->dev, |
684 | "failed to send 'reset' command: %d\n" , error); |
685 | } |
686 | |
687 | msleep(msecs: 50); |
688 | |
689 | return error; |
690 | } |
691 | |
692 | static void hideep_power_off(void *data) |
693 | { |
694 | struct hideep_ts *ts = data; |
695 | |
696 | if (ts->reset_gpio) |
697 | gpiod_set_value(desc: ts->reset_gpio, value: 1); |
698 | |
699 | regulator_disable(regulator: ts->vcc_vid); |
700 | regulator_disable(regulator: ts->vcc_vdd); |
701 | } |
702 | |
703 | #define __GET_MT_TOOL_TYPE(type) ((type) == 0x01 ? MT_TOOL_FINGER : MT_TOOL_PEN) |
704 | |
705 | static void hideep_report_slot(struct input_dev *input, |
706 | const struct hideep_event *event) |
707 | { |
708 | input_mt_slot(dev: input, slot: event->index & 0x0f); |
709 | input_mt_report_slot_state(dev: input, |
710 | __GET_MT_TOOL_TYPE(event->type), |
711 | active: !(event->flag & HIDEEP_MT_RELEASED)); |
712 | if (!(event->flag & HIDEEP_MT_RELEASED)) { |
713 | input_report_abs(dev: input, ABS_MT_POSITION_X, |
714 | le16_to_cpup(p: &event->x)); |
715 | input_report_abs(dev: input, ABS_MT_POSITION_Y, |
716 | le16_to_cpup(p: &event->y)); |
717 | input_report_abs(dev: input, ABS_MT_PRESSURE, |
718 | le16_to_cpup(p: &event->z)); |
719 | input_report_abs(dev: input, ABS_MT_TOUCH_MAJOR, value: event->w); |
720 | } |
721 | } |
722 | |
723 | static void hideep_parse_and_report(struct hideep_ts *ts) |
724 | { |
725 | const struct hideep_event *events = |
726 | (void *)&ts->xfer_buf[HIDEEP_TOUCH_EVENT_INDEX]; |
727 | const u8 *keys = &ts->xfer_buf[HIDEEP_KEY_EVENT_INDEX]; |
728 | int touch_count = ts->xfer_buf[0]; |
729 | int key_count = ts->xfer_buf[1] & 0x0f; |
730 | int lpm_count = ts->xfer_buf[1] & 0xf0; |
731 | int i; |
732 | |
733 | /* get touch event count */ |
734 | dev_dbg(&ts->client->dev, "mt = %d, key = %d, lpm = %02x" , |
735 | touch_count, key_count, lpm_count); |
736 | |
737 | touch_count = min(touch_count, HIDEEP_MT_MAX); |
738 | for (i = 0; i < touch_count; i++) |
739 | hideep_report_slot(input: ts->input_dev, event: events + i); |
740 | |
741 | key_count = min(key_count, HIDEEP_KEY_MAX); |
742 | for (i = 0; i < key_count; i++) { |
743 | u8 key_data = keys[i * 2]; |
744 | |
745 | input_report_key(dev: ts->input_dev, |
746 | code: ts->key_codes[key_data & HIDEEP_KEY_IDX_MASK], |
747 | value: key_data & HIDEEP_KEY_PRESSED_MASK); |
748 | } |
749 | |
750 | input_mt_sync_frame(dev: ts->input_dev); |
751 | input_sync(dev: ts->input_dev); |
752 | } |
753 | |
754 | static irqreturn_t hideep_irq(int irq, void *handle) |
755 | { |
756 | struct hideep_ts *ts = handle; |
757 | int error; |
758 | |
759 | BUILD_BUG_ON(HIDEEP_MAX_EVENT > HIDEEP_XFER_BUF_SIZE); |
760 | |
761 | error = regmap_bulk_read(map: ts->reg, HIDEEP_EVENT_ADDR, |
762 | val: ts->xfer_buf, HIDEEP_MAX_EVENT / 2); |
763 | if (error) { |
764 | dev_err(&ts->client->dev, "failed to read events: %d\n" , error); |
765 | goto out; |
766 | } |
767 | |
768 | hideep_parse_and_report(ts); |
769 | |
770 | out: |
771 | return IRQ_HANDLED; |
772 | } |
773 | |
774 | static int hideep_get_axis_info(struct hideep_ts *ts) |
775 | { |
776 | __le16 val[2]; |
777 | int error; |
778 | |
779 | error = regmap_bulk_read(map: ts->reg, reg: 0x28, val, ARRAY_SIZE(val)); |
780 | if (error) |
781 | return error; |
782 | |
783 | ts->prop.max_x = le16_to_cpup(p: val); |
784 | ts->prop.max_y = le16_to_cpup(p: val + 1); |
785 | |
786 | dev_dbg(&ts->client->dev, "X: %d, Y: %d" , |
787 | ts->prop.max_x, ts->prop.max_y); |
788 | |
789 | return 0; |
790 | } |
791 | |
792 | static int hideep_init_input(struct hideep_ts *ts) |
793 | { |
794 | struct device *dev = &ts->client->dev; |
795 | int i; |
796 | int error; |
797 | |
798 | ts->input_dev = devm_input_allocate_device(dev); |
799 | if (!ts->input_dev) { |
800 | dev_err(dev, "failed to allocate input device\n" ); |
801 | return -ENOMEM; |
802 | } |
803 | |
804 | ts->input_dev->name = HIDEEP_TS_NAME; |
805 | ts->input_dev->id.bustype = BUS_I2C; |
806 | input_set_drvdata(dev: ts->input_dev, data: ts); |
807 | |
808 | input_set_capability(dev: ts->input_dev, EV_ABS, ABS_MT_POSITION_X); |
809 | input_set_capability(dev: ts->input_dev, EV_ABS, ABS_MT_POSITION_Y); |
810 | input_set_abs_params(dev: ts->input_dev, ABS_MT_PRESSURE, min: 0, max: 65535, fuzz: 0, flat: 0); |
811 | input_set_abs_params(dev: ts->input_dev, ABS_MT_TOUCH_MAJOR, min: 0, max: 255, fuzz: 0, flat: 0); |
812 | input_set_abs_params(dev: ts->input_dev, ABS_MT_TOOL_TYPE, |
813 | min: 0, MT_TOOL_MAX, fuzz: 0, flat: 0); |
814 | touchscreen_parse_properties(input: ts->input_dev, multitouch: true, prop: &ts->prop); |
815 | |
816 | if (ts->prop.max_x == 0 || ts->prop.max_y == 0) { |
817 | error = hideep_get_axis_info(ts); |
818 | if (error) |
819 | return error; |
820 | } |
821 | |
822 | error = input_mt_init_slots(dev: ts->input_dev, HIDEEP_MT_MAX, |
823 | INPUT_MT_DIRECT); |
824 | if (error) |
825 | return error; |
826 | |
827 | ts->key_num = device_property_count_u32(dev, propname: "linux,keycodes" ); |
828 | if (ts->key_num > HIDEEP_KEY_MAX) { |
829 | dev_err(dev, "too many keys defined: %d\n" , |
830 | ts->key_num); |
831 | return -EINVAL; |
832 | } |
833 | |
834 | if (ts->key_num <= 0) { |
835 | dev_dbg(dev, |
836 | "missing or malformed 'linux,keycodes' property\n" ); |
837 | } else { |
838 | error = device_property_read_u32_array(dev, propname: "linux,keycodes" , |
839 | val: ts->key_codes, |
840 | nval: ts->key_num); |
841 | if (error) { |
842 | dev_dbg(dev, "failed to read keymap: %d" , error); |
843 | return error; |
844 | } |
845 | |
846 | if (ts->key_num) { |
847 | ts->input_dev->keycode = ts->key_codes; |
848 | ts->input_dev->keycodesize = sizeof(ts->key_codes[0]); |
849 | ts->input_dev->keycodemax = ts->key_num; |
850 | |
851 | for (i = 0; i < ts->key_num; i++) |
852 | input_set_capability(dev: ts->input_dev, EV_KEY, |
853 | code: ts->key_codes[i]); |
854 | } |
855 | } |
856 | |
857 | error = input_register_device(ts->input_dev); |
858 | if (error) { |
859 | dev_err(dev, "failed to register input device: %d" , error); |
860 | return error; |
861 | } |
862 | |
863 | return 0; |
864 | } |
865 | |
866 | static ssize_t hideep_update_fw(struct device *dev, |
867 | struct device_attribute *attr, |
868 | const char *buf, size_t count) |
869 | { |
870 | struct i2c_client *client = to_i2c_client(dev); |
871 | struct hideep_ts *ts = i2c_get_clientdata(client); |
872 | const struct firmware *fw_entry; |
873 | char *fw_name; |
874 | int mode; |
875 | int error; |
876 | |
877 | error = kstrtoint(s: buf, base: 0, res: &mode); |
878 | if (error) |
879 | return error; |
880 | |
881 | fw_name = kasprintf(GFP_KERNEL, fmt: "hideep_ts_%04x.bin" , |
882 | be16_to_cpu(ts->dwz_info.product_id)); |
883 | if (!fw_name) |
884 | return -ENOMEM; |
885 | |
886 | error = request_firmware(fw: &fw_entry, name: fw_name, device: dev); |
887 | if (error) { |
888 | dev_err(dev, "failed to request firmware %s: %d" , |
889 | fw_name, error); |
890 | goto out_free_fw_name; |
891 | } |
892 | |
893 | if (fw_entry->size % sizeof(__be32)) { |
894 | dev_err(dev, "invalid firmware size %zu\n" , fw_entry->size); |
895 | error = -EINVAL; |
896 | goto out_release_fw; |
897 | } |
898 | |
899 | if (fw_entry->size > ts->fw_size) { |
900 | dev_err(dev, "fw size (%zu) is too big (memory size %d)\n" , |
901 | fw_entry->size, ts->fw_size); |
902 | error = -EFBIG; |
903 | goto out_release_fw; |
904 | } |
905 | |
906 | mutex_lock(&ts->dev_mutex); |
907 | disable_irq(irq: client->irq); |
908 | |
909 | error = hideep_update_firmware(ts, ucode: (const __be32 *)fw_entry->data, |
910 | ucode_len: fw_entry->size); |
911 | |
912 | enable_irq(irq: client->irq); |
913 | mutex_unlock(lock: &ts->dev_mutex); |
914 | |
915 | out_release_fw: |
916 | release_firmware(fw: fw_entry); |
917 | out_free_fw_name: |
918 | kfree(objp: fw_name); |
919 | |
920 | return error ?: count; |
921 | } |
922 | |
923 | static ssize_t hideep_fw_version_show(struct device *dev, |
924 | struct device_attribute *attr, char *buf) |
925 | { |
926 | struct i2c_client *client = to_i2c_client(dev); |
927 | struct hideep_ts *ts = i2c_get_clientdata(client); |
928 | ssize_t len; |
929 | |
930 | mutex_lock(&ts->dev_mutex); |
931 | len = scnprintf(buf, PAGE_SIZE, fmt: "%04x\n" , |
932 | be16_to_cpu(ts->dwz_info.release_ver)); |
933 | mutex_unlock(lock: &ts->dev_mutex); |
934 | |
935 | return len; |
936 | } |
937 | |
938 | static ssize_t hideep_product_id_show(struct device *dev, |
939 | struct device_attribute *attr, char *buf) |
940 | { |
941 | struct i2c_client *client = to_i2c_client(dev); |
942 | struct hideep_ts *ts = i2c_get_clientdata(client); |
943 | ssize_t len; |
944 | |
945 | mutex_lock(&ts->dev_mutex); |
946 | len = scnprintf(buf, PAGE_SIZE, fmt: "%04x\n" , |
947 | be16_to_cpu(ts->dwz_info.product_id)); |
948 | mutex_unlock(lock: &ts->dev_mutex); |
949 | |
950 | return len; |
951 | } |
952 | |
953 | static DEVICE_ATTR(version, 0664, hideep_fw_version_show, NULL); |
954 | static DEVICE_ATTR(product_id, 0664, hideep_product_id_show, NULL); |
955 | static DEVICE_ATTR(update_fw, 0664, NULL, hideep_update_fw); |
956 | |
957 | static struct attribute *hideep_ts_sysfs_entries[] = { |
958 | &dev_attr_version.attr, |
959 | &dev_attr_product_id.attr, |
960 | &dev_attr_update_fw.attr, |
961 | NULL, |
962 | }; |
963 | |
964 | static const struct attribute_group hideep_ts_attr_group = { |
965 | .attrs = hideep_ts_sysfs_entries, |
966 | }; |
967 | |
968 | static void hideep_set_work_mode(struct hideep_ts *ts) |
969 | { |
970 | /* |
971 | * Reset touch report format to the native HiDeep 20 protocol if requested. |
972 | * This is necessary to make touchscreens which come up in I2C-HID mode |
973 | * work with this driver. |
974 | * |
975 | * Note this is a kernel internal device-property set by x86 platform code, |
976 | * this MUST not be used in devicetree files without first adding it to |
977 | * the DT bindings. |
978 | */ |
979 | if (device_property_read_bool(dev: &ts->client->dev, propname: "hideep,force-native-protocol" )) |
980 | regmap_write(map: ts->reg, HIDEEP_WORK_MODE, val: 0x00); |
981 | } |
982 | |
983 | static int hideep_suspend(struct device *dev) |
984 | { |
985 | struct i2c_client *client = to_i2c_client(dev); |
986 | struct hideep_ts *ts = i2c_get_clientdata(client); |
987 | |
988 | disable_irq(irq: client->irq); |
989 | hideep_power_off(data: ts); |
990 | |
991 | return 0; |
992 | } |
993 | |
994 | static int hideep_resume(struct device *dev) |
995 | { |
996 | struct i2c_client *client = to_i2c_client(dev); |
997 | struct hideep_ts *ts = i2c_get_clientdata(client); |
998 | int error; |
999 | |
1000 | error = hideep_power_on(ts); |
1001 | if (error) { |
1002 | dev_err(&client->dev, "power on failed" ); |
1003 | return error; |
1004 | } |
1005 | |
1006 | hideep_set_work_mode(ts); |
1007 | |
1008 | enable_irq(irq: client->irq); |
1009 | |
1010 | return 0; |
1011 | } |
1012 | |
1013 | static DEFINE_SIMPLE_DEV_PM_OPS(hideep_pm_ops, hideep_suspend, hideep_resume); |
1014 | |
1015 | static const struct regmap_config hideep_regmap_config = { |
1016 | .reg_bits = 16, |
1017 | .reg_format_endian = REGMAP_ENDIAN_LITTLE, |
1018 | .val_bits = 16, |
1019 | .val_format_endian = REGMAP_ENDIAN_LITTLE, |
1020 | .max_register = 0xffff, |
1021 | }; |
1022 | |
1023 | static int hideep_probe(struct i2c_client *client) |
1024 | { |
1025 | struct hideep_ts *ts; |
1026 | int error; |
1027 | |
1028 | /* check i2c bus */ |
1029 | if (!i2c_check_functionality(adap: client->adapter, I2C_FUNC_I2C)) { |
1030 | dev_err(&client->dev, "check i2c device error" ); |
1031 | return -ENODEV; |
1032 | } |
1033 | |
1034 | if (client->irq <= 0) { |
1035 | dev_err(&client->dev, "missing irq: %d\n" , client->irq); |
1036 | return -EINVAL; |
1037 | } |
1038 | |
1039 | ts = devm_kzalloc(dev: &client->dev, size: sizeof(*ts), GFP_KERNEL); |
1040 | if (!ts) |
1041 | return -ENOMEM; |
1042 | |
1043 | ts->client = client; |
1044 | i2c_set_clientdata(client, data: ts); |
1045 | mutex_init(&ts->dev_mutex); |
1046 | |
1047 | ts->reg = devm_regmap_init_i2c(client, &hideep_regmap_config); |
1048 | if (IS_ERR(ptr: ts->reg)) { |
1049 | error = PTR_ERR(ptr: ts->reg); |
1050 | dev_err(&client->dev, |
1051 | "failed to initialize regmap: %d\n" , error); |
1052 | return error; |
1053 | } |
1054 | |
1055 | ts->vcc_vdd = devm_regulator_get(dev: &client->dev, id: "vdd" ); |
1056 | if (IS_ERR(ptr: ts->vcc_vdd)) |
1057 | return PTR_ERR(ptr: ts->vcc_vdd); |
1058 | |
1059 | ts->vcc_vid = devm_regulator_get(dev: &client->dev, id: "vid" ); |
1060 | if (IS_ERR(ptr: ts->vcc_vid)) |
1061 | return PTR_ERR(ptr: ts->vcc_vid); |
1062 | |
1063 | ts->reset_gpio = devm_gpiod_get_optional(dev: &client->dev, |
1064 | con_id: "reset" , flags: GPIOD_OUT_HIGH); |
1065 | if (IS_ERR(ptr: ts->reset_gpio)) |
1066 | return PTR_ERR(ptr: ts->reset_gpio); |
1067 | |
1068 | error = hideep_power_on(ts); |
1069 | if (error) { |
1070 | dev_err(&client->dev, "power on failed: %d\n" , error); |
1071 | return error; |
1072 | } |
1073 | |
1074 | error = devm_add_action_or_reset(&client->dev, hideep_power_off, ts); |
1075 | if (error) |
1076 | return error; |
1077 | |
1078 | error = hideep_load_dwz(ts); |
1079 | if (error) { |
1080 | dev_err(&client->dev, "failed to load dwz: %d" , error); |
1081 | return error; |
1082 | } |
1083 | |
1084 | hideep_set_work_mode(ts); |
1085 | |
1086 | error = hideep_init_input(ts); |
1087 | if (error) |
1088 | return error; |
1089 | |
1090 | error = devm_request_threaded_irq(dev: &client->dev, irq: client->irq, |
1091 | NULL, thread_fn: hideep_irq, IRQF_ONESHOT, |
1092 | devname: client->name, dev_id: ts); |
1093 | if (error) { |
1094 | dev_err(&client->dev, "failed to request irq %d: %d\n" , |
1095 | client->irq, error); |
1096 | return error; |
1097 | } |
1098 | |
1099 | error = devm_device_add_group(dev: &client->dev, grp: &hideep_ts_attr_group); |
1100 | if (error) { |
1101 | dev_err(&client->dev, |
1102 | "failed to add sysfs attributes: %d\n" , error); |
1103 | return error; |
1104 | } |
1105 | |
1106 | return 0; |
1107 | } |
1108 | |
1109 | static const struct i2c_device_id hideep_i2c_id[] = { |
1110 | { HIDEEP_I2C_NAME, 0 }, |
1111 | { } |
1112 | }; |
1113 | MODULE_DEVICE_TABLE(i2c, hideep_i2c_id); |
1114 | |
1115 | #ifdef CONFIG_ACPI |
1116 | static const struct acpi_device_id hideep_acpi_id[] = { |
1117 | { "HIDP0001" , 0 }, |
1118 | { } |
1119 | }; |
1120 | MODULE_DEVICE_TABLE(acpi, hideep_acpi_id); |
1121 | #endif |
1122 | |
1123 | #ifdef CONFIG_OF |
1124 | static const struct of_device_id hideep_match_table[] = { |
1125 | { .compatible = "hideep,hideep-ts" }, |
1126 | { } |
1127 | }; |
1128 | MODULE_DEVICE_TABLE(of, hideep_match_table); |
1129 | #endif |
1130 | |
1131 | static struct i2c_driver hideep_driver = { |
1132 | .driver = { |
1133 | .name = HIDEEP_I2C_NAME, |
1134 | .of_match_table = of_match_ptr(hideep_match_table), |
1135 | .acpi_match_table = ACPI_PTR(hideep_acpi_id), |
1136 | .pm = pm_sleep_ptr(&hideep_pm_ops), |
1137 | }, |
1138 | .id_table = hideep_i2c_id, |
1139 | .probe = hideep_probe, |
1140 | }; |
1141 | |
1142 | module_i2c_driver(hideep_driver); |
1143 | |
1144 | MODULE_DESCRIPTION("Driver for HiDeep Touchscreen Controller" ); |
1145 | MODULE_AUTHOR("anthony.kim@hideep.com" ); |
1146 | MODULE_LICENSE("GPL v2" ); |
1147 | |