1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Raydium touchscreen I2C driver. |
4 | * |
5 | * Copyright (C) 2012-2014, Raydium Semiconductor Corporation. |
6 | * |
7 | * Raydium reserves the right to make changes without further notice |
8 | * to the materials described herein. Raydium does not assume any |
9 | * liability arising out of the application described herein. |
10 | * |
11 | * Contact Raydium Semiconductor Corporation at www.rad-ic.com |
12 | */ |
13 | |
14 | #include <linux/acpi.h> |
15 | #include <linux/delay.h> |
16 | #include <linux/firmware.h> |
17 | #include <linux/gpio/consumer.h> |
18 | #include <linux/i2c.h> |
19 | #include <linux/input.h> |
20 | #include <linux/input/mt.h> |
21 | #include <linux/interrupt.h> |
22 | #include <linux/module.h> |
23 | #include <linux/of.h> |
24 | #include <linux/pm_wakeirq.h> |
25 | #include <linux/regulator/consumer.h> |
26 | #include <linux/slab.h> |
27 | #include <asm/unaligned.h> |
28 | |
29 | /* Slave I2C mode */ |
30 | #define RM_BOOT_BLDR 0x02 |
31 | #define RM_BOOT_MAIN 0x03 |
32 | |
33 | /* I2C bootoloader commands */ |
34 | #define RM_CMD_BOOT_PAGE_WRT 0x0B /* send bl page write */ |
35 | #define RM_CMD_BOOT_WRT 0x11 /* send bl write */ |
36 | #define RM_CMD_BOOT_ACK 0x22 /* send ack*/ |
37 | #define RM_CMD_BOOT_CHK 0x33 /* send data check */ |
38 | #define RM_CMD_BOOT_READ 0x44 /* send wait bl data ready*/ |
39 | |
40 | #define RM_BOOT_RDY 0xFF /* bl data ready */ |
41 | #define RM_BOOT_CMD_READHWID 0x0E /* read hwid */ |
42 | |
43 | /* I2C main commands */ |
44 | #define RM_CMD_QUERY_BANK 0x2B |
45 | #define RM_CMD_DATA_BANK 0x4D |
46 | #define RM_CMD_ENTER_SLEEP 0x4E |
47 | #define RM_CMD_BANK_SWITCH 0xAA |
48 | |
49 | #define RM_RESET_MSG_ADDR 0x40000004 |
50 | |
51 | #define RM_MAX_READ_SIZE 56 |
52 | #define RM_PACKET_CRC_SIZE 2 |
53 | |
54 | /* Touch relative info */ |
55 | #define RM_MAX_RETRIES 3 |
56 | #define RM_RETRY_DELAY_MS 20 |
57 | #define RM_MAX_TOUCH_NUM 10 |
58 | #define RM_BOOT_DELAY_MS 100 |
59 | |
60 | /* Offsets in contact data */ |
61 | #define RM_CONTACT_STATE_POS 0 |
62 | #define RM_CONTACT_X_POS 1 |
63 | #define RM_CONTACT_Y_POS 3 |
64 | #define RM_CONTACT_PRESSURE_POS 5 |
65 | #define RM_CONTACT_WIDTH_X_POS 6 |
66 | #define RM_CONTACT_WIDTH_Y_POS 7 |
67 | |
68 | /* Bootloader relative info */ |
69 | #define RM_BL_WRT_CMD_SIZE 3 /* bl flash wrt cmd size */ |
70 | #define RM_BL_WRT_PKG_SIZE 32 /* bl wrt pkg size */ |
71 | #define RM_BL_WRT_LEN (RM_BL_WRT_PKG_SIZE + RM_BL_WRT_CMD_SIZE) |
72 | #define RM_FW_PAGE_SIZE 128 |
73 | #define RM_MAX_FW_RETRIES 30 |
74 | #define RM_MAX_FW_SIZE 0xD000 |
75 | |
76 | #define RM_POWERON_DELAY_USEC 500 |
77 | #define RM_RESET_DELAY_MSEC 50 |
78 | |
79 | enum raydium_bl_cmd { |
80 | = 0, |
81 | BL_PAGE_STR, |
82 | BL_PKG_IDX, |
83 | BL_DATA_STR, |
84 | }; |
85 | |
86 | enum raydium_bl_ack { |
87 | RAYDIUM_ACK_NULL = 0, |
88 | RAYDIUM_WAIT_READY, |
89 | RAYDIUM_PATH_READY, |
90 | }; |
91 | |
92 | enum raydium_boot_mode { |
93 | RAYDIUM_TS_MAIN = 0, |
94 | RAYDIUM_TS_BLDR, |
95 | }; |
96 | |
97 | /* Response to RM_CMD_DATA_BANK request */ |
98 | struct raydium_data_info { |
99 | __le32 data_bank_addr; |
100 | u8 pkg_size; |
101 | u8 tp_info_size; |
102 | }; |
103 | |
104 | struct raydium_info { |
105 | __le32 hw_ver; /*device version */ |
106 | u8 main_ver; |
107 | u8 sub_ver; |
108 | __le16 ft_ver; /* test version */ |
109 | u8 x_num; |
110 | u8 y_num; |
111 | __le16 x_max; |
112 | __le16 y_max; |
113 | u8 x_res; /* units/mm */ |
114 | u8 y_res; /* units/mm */ |
115 | }; |
116 | |
117 | /* struct raydium_data - represents state of Raydium touchscreen device */ |
118 | struct raydium_data { |
119 | struct i2c_client *client; |
120 | struct input_dev *input; |
121 | |
122 | struct regulator *avdd; |
123 | struct regulator *vccio; |
124 | struct gpio_desc *reset_gpio; |
125 | |
126 | struct raydium_info info; |
127 | |
128 | struct mutex sysfs_mutex; |
129 | |
130 | u8 *report_data; |
131 | |
132 | u32 data_bank_addr; |
133 | u8 report_size; |
134 | u8 contact_size; |
135 | u8 pkg_size; |
136 | |
137 | enum raydium_boot_mode boot_mode; |
138 | }; |
139 | |
140 | /* |
141 | * Header to be sent for RM_CMD_BANK_SWITCH command. This is used by |
142 | * raydium_i2c_{read|send} below. |
143 | */ |
144 | struct __packed { |
145 | u8 ; |
146 | __be32 ; |
147 | }; |
148 | |
149 | static int raydium_i2c_xfer(struct i2c_client *client, u32 addr, |
150 | struct i2c_msg *xfer, size_t xfer_count) |
151 | { |
152 | int ret; |
153 | /* |
154 | * If address is greater than 255, then RM_CMD_BANK_SWITCH needs to be |
155 | * sent first. Else, skip the header i.e. xfer[0]. |
156 | */ |
157 | int xfer_start_idx = (addr > 0xff) ? 0 : 1; |
158 | xfer_count -= xfer_start_idx; |
159 | |
160 | ret = i2c_transfer(adap: client->adapter, msgs: &xfer[xfer_start_idx], num: xfer_count); |
161 | if (likely(ret == xfer_count)) |
162 | return 0; |
163 | |
164 | return ret < 0 ? ret : -EIO; |
165 | } |
166 | |
167 | static int raydium_i2c_send(struct i2c_client *client, |
168 | u32 addr, const void *data, size_t len) |
169 | { |
170 | int tries = 0; |
171 | int error; |
172 | u8 *tx_buf; |
173 | u8 reg_addr = addr & 0xff; |
174 | |
175 | tx_buf = kmalloc(size: len + 1, GFP_KERNEL); |
176 | if (!tx_buf) |
177 | return -ENOMEM; |
178 | |
179 | tx_buf[0] = reg_addr; |
180 | memcpy(tx_buf + 1, data, len); |
181 | |
182 | do { |
183 | struct raydium_bank_switch_header = { |
184 | .cmd = RM_CMD_BANK_SWITCH, |
185 | .be_addr = cpu_to_be32(addr), |
186 | }; |
187 | |
188 | /* |
189 | * Perform as a single i2c_transfer transaction to ensure that |
190 | * no other I2C transactions are initiated on the bus to any |
191 | * other device in between. Initiating transacations to other |
192 | * devices after RM_CMD_BANK_SWITCH is sent is known to cause |
193 | * issues. This is also why regmap infrastructure cannot be used |
194 | * for this driver. Regmap handles page(bank) switch and reads |
195 | * as separate i2c_transfer() operations. This can result in |
196 | * problems if the Raydium device is on a shared I2C bus. |
197 | */ |
198 | struct i2c_msg xfer[] = { |
199 | { |
200 | .addr = client->addr, |
201 | .len = sizeof(header), |
202 | .buf = (u8 *)&header, |
203 | }, |
204 | { |
205 | .addr = client->addr, |
206 | .len = len + 1, |
207 | .buf = tx_buf, |
208 | }, |
209 | }; |
210 | |
211 | error = raydium_i2c_xfer(client, addr, xfer, ARRAY_SIZE(xfer)); |
212 | if (likely(!error)) |
213 | goto out; |
214 | |
215 | msleep(RM_RETRY_DELAY_MS); |
216 | } while (++tries < RM_MAX_RETRIES); |
217 | |
218 | dev_err(&client->dev, "%s failed: %d\n" , __func__, error); |
219 | out: |
220 | kfree(objp: tx_buf); |
221 | return error; |
222 | } |
223 | |
224 | static int raydium_i2c_read(struct i2c_client *client, |
225 | u32 addr, void *data, size_t len) |
226 | { |
227 | int error; |
228 | |
229 | while (len) { |
230 | u8 reg_addr = addr & 0xff; |
231 | struct raydium_bank_switch_header = { |
232 | .cmd = RM_CMD_BANK_SWITCH, |
233 | .be_addr = cpu_to_be32(addr), |
234 | }; |
235 | size_t xfer_len = min_t(size_t, len, RM_MAX_READ_SIZE); |
236 | |
237 | /* |
238 | * Perform as a single i2c_transfer transaction to ensure that |
239 | * no other I2C transactions are initiated on the bus to any |
240 | * other device in between. Initiating transacations to other |
241 | * devices after RM_CMD_BANK_SWITCH is sent is known to cause |
242 | * issues. This is also why regmap infrastructure cannot be used |
243 | * for this driver. Regmap handles page(bank) switch and writes |
244 | * as separate i2c_transfer() operations. This can result in |
245 | * problems if the Raydium device is on a shared I2C bus. |
246 | */ |
247 | struct i2c_msg xfer[] = { |
248 | { |
249 | .addr = client->addr, |
250 | .len = sizeof(header), |
251 | .buf = (u8 *)&header, |
252 | }, |
253 | { |
254 | .addr = client->addr, |
255 | .len = 1, |
256 | .buf = ®_addr, |
257 | }, |
258 | { |
259 | .addr = client->addr, |
260 | .len = xfer_len, |
261 | .buf = data, |
262 | .flags = I2C_M_RD, |
263 | } |
264 | }; |
265 | |
266 | error = raydium_i2c_xfer(client, addr, xfer, ARRAY_SIZE(xfer)); |
267 | if (unlikely(error)) |
268 | return error; |
269 | |
270 | len -= xfer_len; |
271 | data += xfer_len; |
272 | addr += xfer_len; |
273 | } |
274 | |
275 | return 0; |
276 | } |
277 | |
278 | static int raydium_i2c_sw_reset(struct i2c_client *client) |
279 | { |
280 | const u8 soft_rst_cmd = 0x01; |
281 | int error; |
282 | |
283 | error = raydium_i2c_send(client, RM_RESET_MSG_ADDR, data: &soft_rst_cmd, |
284 | len: sizeof(soft_rst_cmd)); |
285 | if (error) { |
286 | dev_err(&client->dev, "software reset failed: %d\n" , error); |
287 | return error; |
288 | } |
289 | |
290 | msleep(RM_RESET_DELAY_MSEC); |
291 | |
292 | return 0; |
293 | } |
294 | |
295 | static int raydium_i2c_query_ts_bootloader_info(struct raydium_data *ts) |
296 | { |
297 | struct i2c_client *client = ts->client; |
298 | static const u8 get_hwid[] = { RM_BOOT_CMD_READHWID, |
299 | 0x10, 0xc0, 0x01, 0x00, 0x04, 0x00 }; |
300 | u8 rbuf[5] = { 0 }; |
301 | u32 hw_ver; |
302 | int error; |
303 | |
304 | error = raydium_i2c_send(client, RM_CMD_BOOT_WRT, |
305 | data: get_hwid, len: sizeof(get_hwid)); |
306 | if (error) { |
307 | dev_err(&client->dev, "WRT HWID command failed: %d\n" , error); |
308 | return error; |
309 | } |
310 | |
311 | error = raydium_i2c_send(client, RM_CMD_BOOT_ACK, data: rbuf, len: 1); |
312 | if (error) { |
313 | dev_err(&client->dev, "Ack HWID command failed: %d\n" , error); |
314 | return error; |
315 | } |
316 | |
317 | error = raydium_i2c_read(client, RM_CMD_BOOT_CHK, data: rbuf, len: sizeof(rbuf)); |
318 | if (error) { |
319 | dev_err(&client->dev, "Read HWID command failed: %d (%4ph)\n" , |
320 | error, rbuf + 1); |
321 | hw_ver = 0xffffffffUL; |
322 | } else { |
323 | hw_ver = get_unaligned_be32(p: rbuf + 1); |
324 | } |
325 | |
326 | ts->info.hw_ver = cpu_to_le32(hw_ver); |
327 | ts->info.main_ver = 0xff; |
328 | ts->info.sub_ver = 0xff; |
329 | |
330 | return error; |
331 | } |
332 | |
333 | static int raydium_i2c_query_ts_info(struct raydium_data *ts) |
334 | { |
335 | struct i2c_client *client = ts->client; |
336 | struct raydium_data_info data_info; |
337 | __le32 query_bank_addr; |
338 | |
339 | int error, retry_cnt; |
340 | |
341 | for (retry_cnt = 0; retry_cnt < RM_MAX_RETRIES; retry_cnt++) { |
342 | error = raydium_i2c_read(client, RM_CMD_DATA_BANK, |
343 | data: &data_info, len: sizeof(data_info)); |
344 | if (error) |
345 | continue; |
346 | |
347 | /* |
348 | * Warn user if we already allocated memory for reports and |
349 | * then the size changed (due to firmware update?) and keep |
350 | * old size instead. |
351 | */ |
352 | if (ts->report_data && ts->pkg_size != data_info.pkg_size) { |
353 | dev_warn(&client->dev, |
354 | "report size changes, was: %d, new: %d\n" , |
355 | ts->pkg_size, data_info.pkg_size); |
356 | } else { |
357 | ts->pkg_size = data_info.pkg_size; |
358 | ts->report_size = ts->pkg_size - RM_PACKET_CRC_SIZE; |
359 | } |
360 | |
361 | ts->contact_size = data_info.tp_info_size; |
362 | ts->data_bank_addr = le32_to_cpu(data_info.data_bank_addr); |
363 | |
364 | dev_dbg(&client->dev, |
365 | "data_bank_addr: %#08x, report_size: %d, contact_size: %d\n" , |
366 | ts->data_bank_addr, ts->report_size, ts->contact_size); |
367 | |
368 | error = raydium_i2c_read(client, RM_CMD_QUERY_BANK, |
369 | data: &query_bank_addr, |
370 | len: sizeof(query_bank_addr)); |
371 | if (error) |
372 | continue; |
373 | |
374 | error = raydium_i2c_read(client, le32_to_cpu(query_bank_addr), |
375 | data: &ts->info, len: sizeof(ts->info)); |
376 | if (error) |
377 | continue; |
378 | |
379 | return 0; |
380 | } |
381 | |
382 | dev_err(&client->dev, "failed to query device parameters: %d\n" , error); |
383 | return error; |
384 | } |
385 | |
386 | static int raydium_i2c_check_fw_status(struct raydium_data *ts) |
387 | { |
388 | struct i2c_client *client = ts->client; |
389 | static const u8 bl_ack = 0x62; |
390 | static const u8 main_ack = 0x66; |
391 | u8 buf[4]; |
392 | int error; |
393 | |
394 | error = raydium_i2c_read(client, RM_CMD_BOOT_READ, data: buf, len: sizeof(buf)); |
395 | if (!error) { |
396 | if (buf[0] == bl_ack) |
397 | ts->boot_mode = RAYDIUM_TS_BLDR; |
398 | else if (buf[0] == main_ack) |
399 | ts->boot_mode = RAYDIUM_TS_MAIN; |
400 | return 0; |
401 | } |
402 | |
403 | return error; |
404 | } |
405 | |
406 | static int raydium_i2c_initialize(struct raydium_data *ts) |
407 | { |
408 | struct i2c_client *client = ts->client; |
409 | int error, retry_cnt; |
410 | |
411 | for (retry_cnt = 0; retry_cnt < RM_MAX_RETRIES; retry_cnt++) { |
412 | /* Wait for Hello packet */ |
413 | msleep(RM_BOOT_DELAY_MS); |
414 | |
415 | error = raydium_i2c_check_fw_status(ts); |
416 | if (error) { |
417 | dev_err(&client->dev, |
418 | "failed to read 'hello' packet: %d\n" , error); |
419 | continue; |
420 | } |
421 | |
422 | if (ts->boot_mode == RAYDIUM_TS_BLDR || |
423 | ts->boot_mode == RAYDIUM_TS_MAIN) { |
424 | break; |
425 | } |
426 | } |
427 | |
428 | if (error) |
429 | ts->boot_mode = RAYDIUM_TS_BLDR; |
430 | |
431 | if (ts->boot_mode == RAYDIUM_TS_BLDR) |
432 | raydium_i2c_query_ts_bootloader_info(ts); |
433 | else |
434 | raydium_i2c_query_ts_info(ts); |
435 | |
436 | return error; |
437 | } |
438 | |
439 | static int raydium_i2c_bl_chk_state(struct i2c_client *client, |
440 | enum raydium_bl_ack state) |
441 | { |
442 | static const u8 ack_ok[] = { 0xFF, 0x39, 0x30, 0x30, 0x54 }; |
443 | u8 rbuf[sizeof(ack_ok)]; |
444 | u8 retry; |
445 | int error; |
446 | |
447 | for (retry = 0; retry < RM_MAX_FW_RETRIES; retry++) { |
448 | switch (state) { |
449 | case RAYDIUM_ACK_NULL: |
450 | return 0; |
451 | |
452 | case RAYDIUM_WAIT_READY: |
453 | error = raydium_i2c_read(client, RM_CMD_BOOT_CHK, |
454 | data: &rbuf[0], len: 1); |
455 | if (!error && rbuf[0] == RM_BOOT_RDY) |
456 | return 0; |
457 | |
458 | break; |
459 | |
460 | case RAYDIUM_PATH_READY: |
461 | error = raydium_i2c_read(client, RM_CMD_BOOT_CHK, |
462 | data: rbuf, len: sizeof(rbuf)); |
463 | if (!error && !memcmp(p: rbuf, q: ack_ok, size: sizeof(ack_ok))) |
464 | return 0; |
465 | |
466 | break; |
467 | |
468 | default: |
469 | dev_err(&client->dev, "%s: invalid target state %d\n" , |
470 | __func__, state); |
471 | return -EINVAL; |
472 | } |
473 | |
474 | msleep(msecs: 20); |
475 | } |
476 | |
477 | return -ETIMEDOUT; |
478 | } |
479 | |
480 | static int raydium_i2c_write_object(struct i2c_client *client, |
481 | const void *data, size_t len, |
482 | enum raydium_bl_ack state) |
483 | { |
484 | int error; |
485 | static const u8 cmd[] = { 0xFF, 0x39 }; |
486 | |
487 | error = raydium_i2c_send(client, RM_CMD_BOOT_WRT, data, len); |
488 | if (error) { |
489 | dev_err(&client->dev, "WRT obj command failed: %d\n" , |
490 | error); |
491 | return error; |
492 | } |
493 | |
494 | error = raydium_i2c_send(client, RM_CMD_BOOT_ACK, data: cmd, len: sizeof(cmd)); |
495 | if (error) { |
496 | dev_err(&client->dev, "Ack obj command failed: %d\n" , error); |
497 | return error; |
498 | } |
499 | |
500 | error = raydium_i2c_bl_chk_state(client, state); |
501 | if (error) { |
502 | dev_err(&client->dev, "BL check state failed: %d\n" , error); |
503 | return error; |
504 | } |
505 | return 0; |
506 | } |
507 | |
508 | static int raydium_i2c_boot_trigger(struct i2c_client *client) |
509 | { |
510 | static const u8 cmd[7][6] = { |
511 | { 0x08, 0x0C, 0x09, 0x00, 0x50, 0xD7 }, |
512 | { 0x08, 0x04, 0x09, 0x00, 0x50, 0xA5 }, |
513 | { 0x08, 0x04, 0x09, 0x00, 0x50, 0x00 }, |
514 | { 0x08, 0x04, 0x09, 0x00, 0x50, 0xA5 }, |
515 | { 0x08, 0x0C, 0x09, 0x00, 0x50, 0x00 }, |
516 | { 0x06, 0x01, 0x00, 0x00, 0x00, 0x00 }, |
517 | { 0x02, 0xA2, 0x00, 0x00, 0x00, 0x00 }, |
518 | }; |
519 | int i; |
520 | int error; |
521 | |
522 | for (i = 0; i < 7; i++) { |
523 | error = raydium_i2c_write_object(client, data: cmd[i], len: sizeof(cmd[i]), |
524 | state: RAYDIUM_WAIT_READY); |
525 | if (error) { |
526 | dev_err(&client->dev, |
527 | "boot trigger failed at step %d: %d\n" , |
528 | i, error); |
529 | return error; |
530 | } |
531 | } |
532 | |
533 | return 0; |
534 | } |
535 | |
536 | static int raydium_i2c_fw_trigger(struct i2c_client *client) |
537 | { |
538 | static const u8 cmd[5][11] = { |
539 | { 0, 0x09, 0x71, 0x0C, 0x09, 0x00, 0x50, 0xD7, 0, 0, 0 }, |
540 | { 0, 0x09, 0x71, 0x04, 0x09, 0x00, 0x50, 0xA5, 0, 0, 0 }, |
541 | { 0, 0x09, 0x71, 0x04, 0x09, 0x00, 0x50, 0x00, 0, 0, 0 }, |
542 | { 0, 0x09, 0x71, 0x04, 0x09, 0x00, 0x50, 0xA5, 0, 0, 0 }, |
543 | { 0, 0x09, 0x71, 0x0C, 0x09, 0x00, 0x50, 0x00, 0, 0, 0 }, |
544 | }; |
545 | int i; |
546 | int error; |
547 | |
548 | for (i = 0; i < 5; i++) { |
549 | error = raydium_i2c_write_object(client, data: cmd[i], len: sizeof(cmd[i]), |
550 | state: RAYDIUM_ACK_NULL); |
551 | if (error) { |
552 | dev_err(&client->dev, |
553 | "fw trigger failed at step %d: %d\n" , |
554 | i, error); |
555 | return error; |
556 | } |
557 | } |
558 | |
559 | return 0; |
560 | } |
561 | |
562 | static int raydium_i2c_check_path(struct i2c_client *client) |
563 | { |
564 | static const u8 cmd[] = { 0x09, 0x00, 0x09, 0x00, 0x50, 0x10, 0x00 }; |
565 | int error; |
566 | |
567 | error = raydium_i2c_write_object(client, data: cmd, len: sizeof(cmd), |
568 | state: RAYDIUM_PATH_READY); |
569 | if (error) { |
570 | dev_err(&client->dev, "check path command failed: %d\n" , error); |
571 | return error; |
572 | } |
573 | |
574 | return 0; |
575 | } |
576 | |
577 | static int raydium_i2c_enter_bl(struct i2c_client *client) |
578 | { |
579 | static const u8 cal_cmd[] = { 0x00, 0x01, 0x52 }; |
580 | int error; |
581 | |
582 | error = raydium_i2c_write_object(client, data: cal_cmd, len: sizeof(cal_cmd), |
583 | state: RAYDIUM_ACK_NULL); |
584 | if (error) { |
585 | dev_err(&client->dev, "enter bl command failed: %d\n" , error); |
586 | return error; |
587 | } |
588 | |
589 | msleep(RM_BOOT_DELAY_MS); |
590 | return 0; |
591 | } |
592 | |
593 | static int raydium_i2c_leave_bl(struct i2c_client *client) |
594 | { |
595 | static const u8 leave_cmd[] = { 0x05, 0x00 }; |
596 | int error; |
597 | |
598 | error = raydium_i2c_write_object(client, data: leave_cmd, len: sizeof(leave_cmd), |
599 | state: RAYDIUM_ACK_NULL); |
600 | if (error) { |
601 | dev_err(&client->dev, "leave bl command failed: %d\n" , error); |
602 | return error; |
603 | } |
604 | |
605 | msleep(RM_BOOT_DELAY_MS); |
606 | return 0; |
607 | } |
608 | |
609 | static int raydium_i2c_write_checksum(struct i2c_client *client, |
610 | size_t length, u16 checksum) |
611 | { |
612 | u8 checksum_cmd[] = { 0x00, 0x05, 0x6D, 0x00, 0x00, 0x00, 0x00 }; |
613 | int error; |
614 | |
615 | put_unaligned_le16(val: length, p: &checksum_cmd[3]); |
616 | put_unaligned_le16(val: checksum, p: &checksum_cmd[5]); |
617 | |
618 | error = raydium_i2c_write_object(client, |
619 | data: checksum_cmd, len: sizeof(checksum_cmd), |
620 | state: RAYDIUM_ACK_NULL); |
621 | if (error) { |
622 | dev_err(&client->dev, "failed to write checksum: %d\n" , |
623 | error); |
624 | return error; |
625 | } |
626 | |
627 | return 0; |
628 | } |
629 | |
630 | static int raydium_i2c_disable_watch_dog(struct i2c_client *client) |
631 | { |
632 | static const u8 cmd[] = { 0x0A, 0xAA }; |
633 | int error; |
634 | |
635 | error = raydium_i2c_write_object(client, data: cmd, len: sizeof(cmd), |
636 | state: RAYDIUM_WAIT_READY); |
637 | if (error) { |
638 | dev_err(&client->dev, "disable watchdog command failed: %d\n" , |
639 | error); |
640 | return error; |
641 | } |
642 | |
643 | return 0; |
644 | } |
645 | |
646 | static int raydium_i2c_fw_write_page(struct i2c_client *client, |
647 | u16 page_idx, const void *data, size_t len) |
648 | { |
649 | u8 buf[RM_BL_WRT_LEN]; |
650 | size_t xfer_len; |
651 | int error; |
652 | int i; |
653 | |
654 | BUILD_BUG_ON((RM_FW_PAGE_SIZE % RM_BL_WRT_PKG_SIZE) != 0); |
655 | |
656 | for (i = 0; i < RM_FW_PAGE_SIZE / RM_BL_WRT_PKG_SIZE; i++) { |
657 | buf[BL_HEADER] = RM_CMD_BOOT_PAGE_WRT; |
658 | buf[BL_PAGE_STR] = page_idx ? 0xff : 0; |
659 | buf[BL_PKG_IDX] = i + 1; |
660 | |
661 | xfer_len = min_t(size_t, len, RM_BL_WRT_PKG_SIZE); |
662 | memcpy(&buf[BL_DATA_STR], data, xfer_len); |
663 | if (len < RM_BL_WRT_PKG_SIZE) |
664 | memset(&buf[BL_DATA_STR + xfer_len], 0xff, |
665 | RM_BL_WRT_PKG_SIZE - xfer_len); |
666 | |
667 | error = raydium_i2c_write_object(client, data: buf, RM_BL_WRT_LEN, |
668 | state: RAYDIUM_WAIT_READY); |
669 | if (error) { |
670 | dev_err(&client->dev, |
671 | "page write command failed for page %d, chunk %d: %d\n" , |
672 | page_idx, i, error); |
673 | return error; |
674 | } |
675 | |
676 | data += xfer_len; |
677 | len -= xfer_len; |
678 | } |
679 | |
680 | return error; |
681 | } |
682 | |
683 | static u16 raydium_calc_chksum(const u8 *buf, u16 len) |
684 | { |
685 | u16 checksum = 0; |
686 | u16 i; |
687 | |
688 | for (i = 0; i < len; i++) |
689 | checksum += buf[i]; |
690 | |
691 | return checksum; |
692 | } |
693 | |
694 | static int raydium_i2c_do_update_firmware(struct raydium_data *ts, |
695 | const struct firmware *fw) |
696 | { |
697 | struct i2c_client *client = ts->client; |
698 | const void *data; |
699 | size_t data_len; |
700 | size_t len; |
701 | int page_nr; |
702 | int i; |
703 | int error; |
704 | u16 fw_checksum; |
705 | |
706 | if (fw->size == 0 || fw->size > RM_MAX_FW_SIZE) { |
707 | dev_err(&client->dev, "Invalid firmware length\n" ); |
708 | return -EINVAL; |
709 | } |
710 | |
711 | error = raydium_i2c_check_fw_status(ts); |
712 | if (error) { |
713 | dev_err(&client->dev, "Unable to access IC %d\n" , error); |
714 | return error; |
715 | } |
716 | |
717 | if (ts->boot_mode == RAYDIUM_TS_MAIN) { |
718 | for (i = 0; i < RM_MAX_RETRIES; i++) { |
719 | error = raydium_i2c_enter_bl(client); |
720 | if (!error) { |
721 | error = raydium_i2c_check_fw_status(ts); |
722 | if (error) { |
723 | dev_err(&client->dev, |
724 | "unable to access IC: %d\n" , |
725 | error); |
726 | return error; |
727 | } |
728 | |
729 | if (ts->boot_mode == RAYDIUM_TS_BLDR) |
730 | break; |
731 | } |
732 | } |
733 | |
734 | if (ts->boot_mode == RAYDIUM_TS_MAIN) { |
735 | dev_err(&client->dev, |
736 | "failed to jump to boot loader: %d\n" , |
737 | error); |
738 | return -EIO; |
739 | } |
740 | } |
741 | |
742 | error = raydium_i2c_disable_watch_dog(client); |
743 | if (error) |
744 | return error; |
745 | |
746 | error = raydium_i2c_check_path(client); |
747 | if (error) |
748 | return error; |
749 | |
750 | error = raydium_i2c_boot_trigger(client); |
751 | if (error) { |
752 | dev_err(&client->dev, "send boot trigger fail: %d\n" , error); |
753 | return error; |
754 | } |
755 | |
756 | msleep(RM_BOOT_DELAY_MS); |
757 | |
758 | data = fw->data; |
759 | data_len = fw->size; |
760 | page_nr = 0; |
761 | |
762 | while (data_len) { |
763 | len = min_t(size_t, data_len, RM_FW_PAGE_SIZE); |
764 | |
765 | error = raydium_i2c_fw_write_page(client, page_idx: page_nr++, data, len); |
766 | if (error) |
767 | return error; |
768 | |
769 | msleep(msecs: 20); |
770 | |
771 | data += len; |
772 | data_len -= len; |
773 | } |
774 | |
775 | error = raydium_i2c_leave_bl(client); |
776 | if (error) { |
777 | dev_err(&client->dev, |
778 | "failed to leave boot loader: %d\n" , error); |
779 | return error; |
780 | } |
781 | |
782 | dev_dbg(&client->dev, "left boot loader mode\n" ); |
783 | msleep(RM_BOOT_DELAY_MS); |
784 | |
785 | error = raydium_i2c_check_fw_status(ts); |
786 | if (error) { |
787 | dev_err(&client->dev, |
788 | "failed to check fw status after write: %d\n" , |
789 | error); |
790 | return error; |
791 | } |
792 | |
793 | if (ts->boot_mode != RAYDIUM_TS_MAIN) { |
794 | dev_err(&client->dev, |
795 | "failed to switch to main fw after writing firmware: %d\n" , |
796 | error); |
797 | return -EINVAL; |
798 | } |
799 | |
800 | error = raydium_i2c_fw_trigger(client); |
801 | if (error) { |
802 | dev_err(&client->dev, "failed to trigger fw: %d\n" , error); |
803 | return error; |
804 | } |
805 | |
806 | fw_checksum = raydium_calc_chksum(buf: fw->data, len: fw->size); |
807 | |
808 | error = raydium_i2c_write_checksum(client, length: fw->size, checksum: fw_checksum); |
809 | if (error) |
810 | return error; |
811 | |
812 | return 0; |
813 | } |
814 | |
815 | static int raydium_i2c_fw_update(struct raydium_data *ts) |
816 | { |
817 | struct i2c_client *client = ts->client; |
818 | const struct firmware *fw = NULL; |
819 | char *fw_file; |
820 | int error; |
821 | |
822 | fw_file = kasprintf(GFP_KERNEL, fmt: "raydium_%#04x.fw" , |
823 | le32_to_cpu(ts->info.hw_ver)); |
824 | if (!fw_file) |
825 | return -ENOMEM; |
826 | |
827 | dev_dbg(&client->dev, "firmware name: %s\n" , fw_file); |
828 | |
829 | error = request_firmware(fw: &fw, name: fw_file, device: &client->dev); |
830 | if (error) { |
831 | dev_err(&client->dev, "Unable to open firmware %s\n" , fw_file); |
832 | goto out_free_fw_file; |
833 | } |
834 | |
835 | disable_irq(irq: client->irq); |
836 | |
837 | error = raydium_i2c_do_update_firmware(ts, fw); |
838 | if (error) { |
839 | dev_err(&client->dev, "firmware update failed: %d\n" , error); |
840 | ts->boot_mode = RAYDIUM_TS_BLDR; |
841 | goto out_enable_irq; |
842 | } |
843 | |
844 | error = raydium_i2c_initialize(ts); |
845 | if (error) { |
846 | dev_err(&client->dev, |
847 | "failed to initialize device after firmware update: %d\n" , |
848 | error); |
849 | ts->boot_mode = RAYDIUM_TS_BLDR; |
850 | goto out_enable_irq; |
851 | } |
852 | |
853 | ts->boot_mode = RAYDIUM_TS_MAIN; |
854 | |
855 | out_enable_irq: |
856 | enable_irq(irq: client->irq); |
857 | msleep(msecs: 100); |
858 | |
859 | release_firmware(fw); |
860 | |
861 | out_free_fw_file: |
862 | kfree(objp: fw_file); |
863 | |
864 | return error; |
865 | } |
866 | |
867 | static void raydium_mt_event(struct raydium_data *ts) |
868 | { |
869 | int i; |
870 | |
871 | for (i = 0; i < ts->report_size / ts->contact_size; i++) { |
872 | u8 *contact = &ts->report_data[ts->contact_size * i]; |
873 | bool state = contact[RM_CONTACT_STATE_POS]; |
874 | u8 wx, wy; |
875 | |
876 | input_mt_slot(dev: ts->input, slot: i); |
877 | input_mt_report_slot_state(dev: ts->input, MT_TOOL_FINGER, active: state); |
878 | |
879 | if (!state) |
880 | continue; |
881 | |
882 | input_report_abs(dev: ts->input, ABS_MT_POSITION_X, |
883 | value: get_unaligned_le16(p: &contact[RM_CONTACT_X_POS])); |
884 | input_report_abs(dev: ts->input, ABS_MT_POSITION_Y, |
885 | value: get_unaligned_le16(p: &contact[RM_CONTACT_Y_POS])); |
886 | input_report_abs(dev: ts->input, ABS_MT_PRESSURE, |
887 | value: contact[RM_CONTACT_PRESSURE_POS]); |
888 | |
889 | wx = contact[RM_CONTACT_WIDTH_X_POS]; |
890 | wy = contact[RM_CONTACT_WIDTH_Y_POS]; |
891 | |
892 | input_report_abs(dev: ts->input, ABS_MT_TOUCH_MAJOR, max(wx, wy)); |
893 | input_report_abs(dev: ts->input, ABS_MT_TOUCH_MINOR, min(wx, wy)); |
894 | } |
895 | |
896 | input_mt_sync_frame(dev: ts->input); |
897 | input_sync(dev: ts->input); |
898 | } |
899 | |
900 | static irqreturn_t raydium_i2c_irq(int irq, void *_dev) |
901 | { |
902 | struct raydium_data *ts = _dev; |
903 | int error; |
904 | u16 fw_crc; |
905 | u16 calc_crc; |
906 | |
907 | if (ts->boot_mode != RAYDIUM_TS_MAIN) |
908 | goto out; |
909 | |
910 | error = raydium_i2c_read(client: ts->client, addr: ts->data_bank_addr, |
911 | data: ts->report_data, len: ts->pkg_size); |
912 | if (error) |
913 | goto out; |
914 | |
915 | fw_crc = get_unaligned_le16(p: &ts->report_data[ts->report_size]); |
916 | calc_crc = raydium_calc_chksum(buf: ts->report_data, len: ts->report_size); |
917 | if (unlikely(fw_crc != calc_crc)) { |
918 | dev_warn(&ts->client->dev, |
919 | "%s: invalid packet crc %#04x vs %#04x\n" , |
920 | __func__, calc_crc, fw_crc); |
921 | goto out; |
922 | } |
923 | |
924 | raydium_mt_event(ts); |
925 | |
926 | out: |
927 | return IRQ_HANDLED; |
928 | } |
929 | |
930 | static ssize_t raydium_i2c_fw_ver_show(struct device *dev, |
931 | struct device_attribute *attr, char *buf) |
932 | { |
933 | struct i2c_client *client = to_i2c_client(dev); |
934 | struct raydium_data *ts = i2c_get_clientdata(client); |
935 | |
936 | return sprintf(buf, fmt: "%d.%d\n" , ts->info.main_ver, ts->info.sub_ver); |
937 | } |
938 | |
939 | static ssize_t raydium_i2c_hw_ver_show(struct device *dev, |
940 | struct device_attribute *attr, char *buf) |
941 | { |
942 | struct i2c_client *client = to_i2c_client(dev); |
943 | struct raydium_data *ts = i2c_get_clientdata(client); |
944 | |
945 | return sprintf(buf, fmt: "%#04x\n" , le32_to_cpu(ts->info.hw_ver)); |
946 | } |
947 | |
948 | static ssize_t raydium_i2c_boot_mode_show(struct device *dev, |
949 | struct device_attribute *attr, |
950 | char *buf) |
951 | { |
952 | struct i2c_client *client = to_i2c_client(dev); |
953 | struct raydium_data *ts = i2c_get_clientdata(client); |
954 | |
955 | return sprintf(buf, fmt: "%s\n" , |
956 | ts->boot_mode == RAYDIUM_TS_MAIN ? |
957 | "Normal" : "Recovery" ); |
958 | } |
959 | |
960 | static ssize_t raydium_i2c_update_fw_store(struct device *dev, |
961 | struct device_attribute *attr, |
962 | const char *buf, size_t count) |
963 | { |
964 | struct i2c_client *client = to_i2c_client(dev); |
965 | struct raydium_data *ts = i2c_get_clientdata(client); |
966 | int error; |
967 | |
968 | error = mutex_lock_interruptible(&ts->sysfs_mutex); |
969 | if (error) |
970 | return error; |
971 | |
972 | error = raydium_i2c_fw_update(ts); |
973 | |
974 | mutex_unlock(lock: &ts->sysfs_mutex); |
975 | |
976 | return error ?: count; |
977 | } |
978 | |
979 | static ssize_t raydium_i2c_calibrate_store(struct device *dev, |
980 | struct device_attribute *attr, |
981 | const char *buf, size_t count) |
982 | { |
983 | struct i2c_client *client = to_i2c_client(dev); |
984 | struct raydium_data *ts = i2c_get_clientdata(client); |
985 | static const u8 cal_cmd[] = { 0x00, 0x01, 0x9E }; |
986 | int error; |
987 | |
988 | error = mutex_lock_interruptible(&ts->sysfs_mutex); |
989 | if (error) |
990 | return error; |
991 | |
992 | error = raydium_i2c_write_object(client, data: cal_cmd, len: sizeof(cal_cmd), |
993 | state: RAYDIUM_WAIT_READY); |
994 | if (error) |
995 | dev_err(&client->dev, "calibrate command failed: %d\n" , error); |
996 | |
997 | mutex_unlock(lock: &ts->sysfs_mutex); |
998 | return error ?: count; |
999 | } |
1000 | |
1001 | static DEVICE_ATTR(fw_version, S_IRUGO, raydium_i2c_fw_ver_show, NULL); |
1002 | static DEVICE_ATTR(hw_version, S_IRUGO, raydium_i2c_hw_ver_show, NULL); |
1003 | static DEVICE_ATTR(boot_mode, S_IRUGO, raydium_i2c_boot_mode_show, NULL); |
1004 | static DEVICE_ATTR(update_fw, S_IWUSR, NULL, raydium_i2c_update_fw_store); |
1005 | static DEVICE_ATTR(calibrate, S_IWUSR, NULL, raydium_i2c_calibrate_store); |
1006 | |
1007 | static struct attribute *raydium_i2c_attributes[] = { |
1008 | &dev_attr_update_fw.attr, |
1009 | &dev_attr_boot_mode.attr, |
1010 | &dev_attr_fw_version.attr, |
1011 | &dev_attr_hw_version.attr, |
1012 | &dev_attr_calibrate.attr, |
1013 | NULL |
1014 | }; |
1015 | |
1016 | static const struct attribute_group raydium_i2c_attribute_group = { |
1017 | .attrs = raydium_i2c_attributes, |
1018 | }; |
1019 | |
1020 | static int raydium_i2c_power_on(struct raydium_data *ts) |
1021 | { |
1022 | int error; |
1023 | |
1024 | if (!ts->reset_gpio) |
1025 | return 0; |
1026 | |
1027 | gpiod_set_value_cansleep(desc: ts->reset_gpio, value: 1); |
1028 | |
1029 | error = regulator_enable(regulator: ts->avdd); |
1030 | if (error) { |
1031 | dev_err(&ts->client->dev, |
1032 | "failed to enable avdd regulator: %d\n" , error); |
1033 | goto release_reset_gpio; |
1034 | } |
1035 | |
1036 | error = regulator_enable(regulator: ts->vccio); |
1037 | if (error) { |
1038 | regulator_disable(regulator: ts->avdd); |
1039 | dev_err(&ts->client->dev, |
1040 | "failed to enable vccio regulator: %d\n" , error); |
1041 | goto release_reset_gpio; |
1042 | } |
1043 | |
1044 | udelay(RM_POWERON_DELAY_USEC); |
1045 | |
1046 | release_reset_gpio: |
1047 | gpiod_set_value_cansleep(desc: ts->reset_gpio, value: 0); |
1048 | |
1049 | if (error) |
1050 | return error; |
1051 | |
1052 | msleep(RM_RESET_DELAY_MSEC); |
1053 | |
1054 | return 0; |
1055 | } |
1056 | |
1057 | static void raydium_i2c_power_off(void *_data) |
1058 | { |
1059 | struct raydium_data *ts = _data; |
1060 | |
1061 | if (ts->reset_gpio) { |
1062 | gpiod_set_value_cansleep(desc: ts->reset_gpio, value: 1); |
1063 | regulator_disable(regulator: ts->vccio); |
1064 | regulator_disable(regulator: ts->avdd); |
1065 | } |
1066 | } |
1067 | |
1068 | static int raydium_i2c_probe(struct i2c_client *client) |
1069 | { |
1070 | union i2c_smbus_data dummy; |
1071 | struct raydium_data *ts; |
1072 | int error; |
1073 | |
1074 | if (!i2c_check_functionality(adap: client->adapter, I2C_FUNC_I2C)) { |
1075 | dev_err(&client->dev, |
1076 | "i2c check functionality error (need I2C_FUNC_I2C)\n" ); |
1077 | return -ENXIO; |
1078 | } |
1079 | |
1080 | ts = devm_kzalloc(dev: &client->dev, size: sizeof(*ts), GFP_KERNEL); |
1081 | if (!ts) |
1082 | return -ENOMEM; |
1083 | |
1084 | mutex_init(&ts->sysfs_mutex); |
1085 | |
1086 | ts->client = client; |
1087 | i2c_set_clientdata(client, data: ts); |
1088 | |
1089 | ts->avdd = devm_regulator_get(dev: &client->dev, id: "avdd" ); |
1090 | if (IS_ERR(ptr: ts->avdd)) |
1091 | return dev_err_probe(dev: &client->dev, err: PTR_ERR(ptr: ts->avdd), |
1092 | fmt: "Failed to get 'avdd' regulator\n" ); |
1093 | |
1094 | ts->vccio = devm_regulator_get(dev: &client->dev, id: "vccio" ); |
1095 | if (IS_ERR(ptr: ts->vccio)) |
1096 | return dev_err_probe(dev: &client->dev, err: PTR_ERR(ptr: ts->vccio), |
1097 | fmt: "Failed to get 'vccio' regulator\n" ); |
1098 | |
1099 | ts->reset_gpio = devm_gpiod_get_optional(dev: &client->dev, con_id: "reset" , |
1100 | flags: GPIOD_OUT_LOW); |
1101 | if (IS_ERR(ptr: ts->reset_gpio)) |
1102 | return dev_err_probe(dev: &client->dev, err: PTR_ERR(ptr: ts->reset_gpio), |
1103 | fmt: "Failed to get reset gpio\n" ); |
1104 | |
1105 | error = raydium_i2c_power_on(ts); |
1106 | if (error) |
1107 | return error; |
1108 | |
1109 | error = devm_add_action_or_reset(&client->dev, |
1110 | raydium_i2c_power_off, ts); |
1111 | if (error) { |
1112 | dev_err(&client->dev, |
1113 | "failed to install power off action: %d\n" , error); |
1114 | return error; |
1115 | } |
1116 | |
1117 | /* Make sure there is something at this address */ |
1118 | if (i2c_smbus_xfer(adapter: client->adapter, addr: client->addr, flags: 0, |
1119 | I2C_SMBUS_READ, command: 0, I2C_SMBUS_BYTE, data: &dummy) < 0) { |
1120 | dev_err(&client->dev, "nothing at this address\n" ); |
1121 | return -ENXIO; |
1122 | } |
1123 | |
1124 | error = raydium_i2c_initialize(ts); |
1125 | if (error) { |
1126 | dev_err(&client->dev, "failed to initialize: %d\n" , error); |
1127 | return error; |
1128 | } |
1129 | |
1130 | ts->report_data = devm_kmalloc(dev: &client->dev, |
1131 | size: ts->pkg_size, GFP_KERNEL); |
1132 | if (!ts->report_data) |
1133 | return -ENOMEM; |
1134 | |
1135 | ts->input = devm_input_allocate_device(&client->dev); |
1136 | if (!ts->input) { |
1137 | dev_err(&client->dev, "Failed to allocate input device\n" ); |
1138 | return -ENOMEM; |
1139 | } |
1140 | |
1141 | ts->input->name = "Raydium Touchscreen" ; |
1142 | ts->input->id.bustype = BUS_I2C; |
1143 | |
1144 | input_set_abs_params(dev: ts->input, ABS_MT_POSITION_X, |
1145 | min: 0, le16_to_cpu(ts->info.x_max), fuzz: 0, flat: 0); |
1146 | input_set_abs_params(dev: ts->input, ABS_MT_POSITION_Y, |
1147 | min: 0, le16_to_cpu(ts->info.y_max), fuzz: 0, flat: 0); |
1148 | input_abs_set_res(dev: ts->input, ABS_MT_POSITION_X, val: ts->info.x_res); |
1149 | input_abs_set_res(dev: ts->input, ABS_MT_POSITION_Y, val: ts->info.y_res); |
1150 | |
1151 | input_set_abs_params(dev: ts->input, ABS_MT_TOUCH_MAJOR, min: 0, max: 255, fuzz: 0, flat: 0); |
1152 | input_set_abs_params(dev: ts->input, ABS_MT_PRESSURE, min: 0, max: 255, fuzz: 0, flat: 0); |
1153 | |
1154 | error = input_mt_init_slots(dev: ts->input, RM_MAX_TOUCH_NUM, |
1155 | INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); |
1156 | if (error) { |
1157 | dev_err(&client->dev, |
1158 | "failed to initialize MT slots: %d\n" , error); |
1159 | return error; |
1160 | } |
1161 | |
1162 | error = input_register_device(ts->input); |
1163 | if (error) { |
1164 | dev_err(&client->dev, |
1165 | "unable to register input device: %d\n" , error); |
1166 | return error; |
1167 | } |
1168 | |
1169 | error = devm_request_threaded_irq(dev: &client->dev, irq: client->irq, |
1170 | NULL, thread_fn: raydium_i2c_irq, |
1171 | IRQF_ONESHOT, devname: client->name, dev_id: ts); |
1172 | if (error) { |
1173 | dev_err(&client->dev, "Failed to register interrupt\n" ); |
1174 | return error; |
1175 | } |
1176 | |
1177 | error = devm_device_add_group(dev: &client->dev, |
1178 | grp: &raydium_i2c_attribute_group); |
1179 | if (error) { |
1180 | dev_err(&client->dev, "failed to create sysfs attributes: %d\n" , |
1181 | error); |
1182 | return error; |
1183 | } |
1184 | |
1185 | return 0; |
1186 | } |
1187 | |
1188 | static void raydium_enter_sleep(struct i2c_client *client) |
1189 | { |
1190 | static const u8 sleep_cmd[] = { 0x5A, 0xff, 0x00, 0x0f }; |
1191 | int error; |
1192 | |
1193 | error = raydium_i2c_send(client, RM_CMD_ENTER_SLEEP, |
1194 | data: sleep_cmd, len: sizeof(sleep_cmd)); |
1195 | if (error) |
1196 | dev_err(&client->dev, |
1197 | "sleep command failed: %d\n" , error); |
1198 | } |
1199 | |
1200 | static int raydium_i2c_suspend(struct device *dev) |
1201 | { |
1202 | struct i2c_client *client = to_i2c_client(dev); |
1203 | struct raydium_data *ts = i2c_get_clientdata(client); |
1204 | |
1205 | /* Sleep is not available in BLDR recovery mode */ |
1206 | if (ts->boot_mode != RAYDIUM_TS_MAIN) |
1207 | return -EBUSY; |
1208 | |
1209 | disable_irq(irq: client->irq); |
1210 | |
1211 | if (device_may_wakeup(dev)) { |
1212 | raydium_enter_sleep(client); |
1213 | } else { |
1214 | raydium_i2c_power_off(data: ts); |
1215 | } |
1216 | |
1217 | return 0; |
1218 | } |
1219 | |
1220 | static int raydium_i2c_resume(struct device *dev) |
1221 | { |
1222 | struct i2c_client *client = to_i2c_client(dev); |
1223 | struct raydium_data *ts = i2c_get_clientdata(client); |
1224 | |
1225 | if (device_may_wakeup(dev)) { |
1226 | raydium_i2c_sw_reset(client); |
1227 | } else { |
1228 | raydium_i2c_power_on(ts); |
1229 | raydium_i2c_initialize(ts); |
1230 | } |
1231 | |
1232 | enable_irq(irq: client->irq); |
1233 | |
1234 | return 0; |
1235 | } |
1236 | |
1237 | static DEFINE_SIMPLE_DEV_PM_OPS(raydium_i2c_pm_ops, |
1238 | raydium_i2c_suspend, raydium_i2c_resume); |
1239 | |
1240 | static const struct i2c_device_id raydium_i2c_id[] = { |
1241 | { "raydium_i2c" , 0 }, |
1242 | { "rm32380" , 0 }, |
1243 | { /* sentinel */ } |
1244 | }; |
1245 | MODULE_DEVICE_TABLE(i2c, raydium_i2c_id); |
1246 | |
1247 | #ifdef CONFIG_ACPI |
1248 | static const struct acpi_device_id raydium_acpi_id[] = { |
1249 | { "RAYD0001" , 0 }, |
1250 | { /* sentinel */ } |
1251 | }; |
1252 | MODULE_DEVICE_TABLE(acpi, raydium_acpi_id); |
1253 | #endif |
1254 | |
1255 | #ifdef CONFIG_OF |
1256 | static const struct of_device_id raydium_of_match[] = { |
1257 | { .compatible = "raydium,rm32380" , }, |
1258 | { /* sentinel */ } |
1259 | }; |
1260 | MODULE_DEVICE_TABLE(of, raydium_of_match); |
1261 | #endif |
1262 | |
1263 | static struct i2c_driver raydium_i2c_driver = { |
1264 | .probe = raydium_i2c_probe, |
1265 | .id_table = raydium_i2c_id, |
1266 | .driver = { |
1267 | .name = "raydium_ts" , |
1268 | .pm = pm_sleep_ptr(&raydium_i2c_pm_ops), |
1269 | .acpi_match_table = ACPI_PTR(raydium_acpi_id), |
1270 | .of_match_table = of_match_ptr(raydium_of_match), |
1271 | }, |
1272 | }; |
1273 | module_i2c_driver(raydium_i2c_driver); |
1274 | |
1275 | MODULE_AUTHOR("Raydium" ); |
1276 | MODULE_DESCRIPTION("Raydium I2c Touchscreen driver" ); |
1277 | MODULE_LICENSE("GPL v2" ); |
1278 | |