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