1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (c) 2016, Zodiac Inflight Innovations |
4 | * Copyright (c) 2007-2016, Synaptics Incorporated |
5 | * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com> |
6 | * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com> |
7 | */ |
8 | |
9 | #include <linux/bitops.h> |
10 | #include <linux/kernel.h> |
11 | #include <linux/rmi.h> |
12 | #include <linux/firmware.h> |
13 | #include <linux/delay.h> |
14 | #include <linux/slab.h> |
15 | #include <linux/jiffies.h> |
16 | #include <asm/unaligned.h> |
17 | |
18 | #include "rmi_driver.h" |
19 | #include "rmi_f34.h" |
20 | |
21 | static int rmi_f34v7_read_flash_status(struct f34_data *f34) |
22 | { |
23 | u8 status; |
24 | u8 command; |
25 | int ret; |
26 | |
27 | ret = rmi_read_block(d: f34->fn->rmi_dev, |
28 | addr: f34->fn->fd.data_base_addr + V7_FLASH_STATUS_OFFSET, |
29 | buf: &status, |
30 | len: sizeof(status)); |
31 | if (ret < 0) { |
32 | rmi_dbg(RMI_DEBUG_FN, dev: &f34->fn->dev, |
33 | fmt: "%s: Error %d reading flash status\n" , __func__, ret); |
34 | return ret; |
35 | } |
36 | |
37 | f34->v7.in_bl_mode = status >> 7; |
38 | f34->v7.flash_status = status & 0x1f; |
39 | |
40 | if (f34->v7.flash_status != 0x00) { |
41 | dev_err(&f34->fn->dev, "%s: status=%d, command=0x%02x\n" , |
42 | __func__, f34->v7.flash_status, f34->v7.command); |
43 | } |
44 | |
45 | ret = rmi_read_block(d: f34->fn->rmi_dev, |
46 | addr: f34->fn->fd.data_base_addr + V7_COMMAND_OFFSET, |
47 | buf: &command, |
48 | len: sizeof(command)); |
49 | if (ret < 0) { |
50 | dev_err(&f34->fn->dev, "%s: Failed to read flash command\n" , |
51 | __func__); |
52 | return ret; |
53 | } |
54 | |
55 | f34->v7.command = command; |
56 | |
57 | return 0; |
58 | } |
59 | |
60 | static int rmi_f34v7_wait_for_idle(struct f34_data *f34, int timeout_ms) |
61 | { |
62 | unsigned long timeout; |
63 | |
64 | timeout = msecs_to_jiffies(m: timeout_ms); |
65 | |
66 | if (!wait_for_completion_timeout(x: &f34->v7.cmd_done, timeout)) { |
67 | dev_warn(&f34->fn->dev, "%s: Timed out waiting for idle status\n" , |
68 | __func__); |
69 | return -ETIMEDOUT; |
70 | } |
71 | |
72 | return 0; |
73 | } |
74 | |
75 | static int rmi_f34v7_check_command_status(struct f34_data *f34, int timeout_ms) |
76 | { |
77 | int ret; |
78 | |
79 | ret = rmi_f34v7_wait_for_idle(f34, timeout_ms); |
80 | if (ret < 0) |
81 | return ret; |
82 | |
83 | ret = rmi_f34v7_read_flash_status(f34); |
84 | if (ret < 0) |
85 | return ret; |
86 | |
87 | if (f34->v7.flash_status != 0x00) |
88 | return -EIO; |
89 | |
90 | return 0; |
91 | } |
92 | |
93 | static int rmi_f34v7_write_command_single_transaction(struct f34_data *f34, |
94 | u8 cmd) |
95 | { |
96 | int ret; |
97 | u8 base; |
98 | struct f34v7_data_1_5 data_1_5; |
99 | |
100 | base = f34->fn->fd.data_base_addr; |
101 | |
102 | memset(&data_1_5, 0, sizeof(data_1_5)); |
103 | |
104 | switch (cmd) { |
105 | case v7_CMD_ERASE_ALL: |
106 | data_1_5.partition_id = CORE_CODE_PARTITION; |
107 | data_1_5.command = CMD_V7_ERASE_AP; |
108 | break; |
109 | case v7_CMD_ERASE_UI_FIRMWARE: |
110 | data_1_5.partition_id = CORE_CODE_PARTITION; |
111 | data_1_5.command = CMD_V7_ERASE; |
112 | break; |
113 | case v7_CMD_ERASE_BL_CONFIG: |
114 | data_1_5.partition_id = GLOBAL_PARAMETERS_PARTITION; |
115 | data_1_5.command = CMD_V7_ERASE; |
116 | break; |
117 | case v7_CMD_ERASE_UI_CONFIG: |
118 | data_1_5.partition_id = CORE_CONFIG_PARTITION; |
119 | data_1_5.command = CMD_V7_ERASE; |
120 | break; |
121 | case v7_CMD_ERASE_DISP_CONFIG: |
122 | data_1_5.partition_id = DISPLAY_CONFIG_PARTITION; |
123 | data_1_5.command = CMD_V7_ERASE; |
124 | break; |
125 | case v7_CMD_ERASE_FLASH_CONFIG: |
126 | data_1_5.partition_id = FLASH_CONFIG_PARTITION; |
127 | data_1_5.command = CMD_V7_ERASE; |
128 | break; |
129 | case v7_CMD_ERASE_GUEST_CODE: |
130 | data_1_5.partition_id = GUEST_CODE_PARTITION; |
131 | data_1_5.command = CMD_V7_ERASE; |
132 | break; |
133 | case v7_CMD_ENABLE_FLASH_PROG: |
134 | data_1_5.partition_id = BOOTLOADER_PARTITION; |
135 | data_1_5.command = CMD_V7_ENTER_BL; |
136 | break; |
137 | } |
138 | |
139 | data_1_5.payload[0] = f34->bootloader_id[0]; |
140 | data_1_5.payload[1] = f34->bootloader_id[1]; |
141 | |
142 | ret = rmi_write_block(d: f34->fn->rmi_dev, |
143 | addr: base + V7_PARTITION_ID_OFFSET, |
144 | buf: &data_1_5, len: sizeof(data_1_5)); |
145 | if (ret < 0) { |
146 | dev_err(&f34->fn->dev, |
147 | "%s: Failed to write single transaction command\n" , |
148 | __func__); |
149 | return ret; |
150 | } |
151 | |
152 | return 0; |
153 | } |
154 | |
155 | static int rmi_f34v7_write_command(struct f34_data *f34, u8 cmd) |
156 | { |
157 | int ret; |
158 | u8 base; |
159 | u8 command; |
160 | |
161 | base = f34->fn->fd.data_base_addr; |
162 | |
163 | switch (cmd) { |
164 | case v7_CMD_WRITE_FW: |
165 | case v7_CMD_WRITE_CONFIG: |
166 | case v7_CMD_WRITE_GUEST_CODE: |
167 | command = CMD_V7_WRITE; |
168 | break; |
169 | case v7_CMD_READ_CONFIG: |
170 | command = CMD_V7_READ; |
171 | break; |
172 | case v7_CMD_ERASE_ALL: |
173 | command = CMD_V7_ERASE_AP; |
174 | break; |
175 | case v7_CMD_ERASE_UI_FIRMWARE: |
176 | case v7_CMD_ERASE_BL_CONFIG: |
177 | case v7_CMD_ERASE_UI_CONFIG: |
178 | case v7_CMD_ERASE_DISP_CONFIG: |
179 | case v7_CMD_ERASE_FLASH_CONFIG: |
180 | case v7_CMD_ERASE_GUEST_CODE: |
181 | command = CMD_V7_ERASE; |
182 | break; |
183 | case v7_CMD_ENABLE_FLASH_PROG: |
184 | command = CMD_V7_ENTER_BL; |
185 | break; |
186 | default: |
187 | dev_err(&f34->fn->dev, "%s: Invalid command 0x%02x\n" , |
188 | __func__, cmd); |
189 | return -EINVAL; |
190 | } |
191 | |
192 | f34->v7.command = command; |
193 | |
194 | switch (cmd) { |
195 | case v7_CMD_ERASE_ALL: |
196 | case v7_CMD_ERASE_UI_FIRMWARE: |
197 | case v7_CMD_ERASE_BL_CONFIG: |
198 | case v7_CMD_ERASE_UI_CONFIG: |
199 | case v7_CMD_ERASE_DISP_CONFIG: |
200 | case v7_CMD_ERASE_FLASH_CONFIG: |
201 | case v7_CMD_ERASE_GUEST_CODE: |
202 | case v7_CMD_ENABLE_FLASH_PROG: |
203 | ret = rmi_f34v7_write_command_single_transaction(f34, cmd); |
204 | if (ret < 0) |
205 | return ret; |
206 | else |
207 | return 0; |
208 | default: |
209 | break; |
210 | } |
211 | |
212 | rmi_dbg(RMI_DEBUG_FN, dev: &f34->fn->dev, fmt: "%s: writing cmd %02X\n" , |
213 | __func__, command); |
214 | |
215 | ret = rmi_write_block(d: f34->fn->rmi_dev, |
216 | addr: base + V7_COMMAND_OFFSET, |
217 | buf: &command, len: sizeof(command)); |
218 | if (ret < 0) { |
219 | dev_err(&f34->fn->dev, "%s: Failed to write flash command\n" , |
220 | __func__); |
221 | return ret; |
222 | } |
223 | |
224 | return 0; |
225 | } |
226 | |
227 | static int rmi_f34v7_write_partition_id(struct f34_data *f34, u8 cmd) |
228 | { |
229 | int ret; |
230 | u8 base; |
231 | u8 partition; |
232 | |
233 | base = f34->fn->fd.data_base_addr; |
234 | |
235 | switch (cmd) { |
236 | case v7_CMD_WRITE_FW: |
237 | partition = CORE_CODE_PARTITION; |
238 | break; |
239 | case v7_CMD_WRITE_CONFIG: |
240 | case v7_CMD_READ_CONFIG: |
241 | if (f34->v7.config_area == v7_UI_CONFIG_AREA) |
242 | partition = CORE_CONFIG_PARTITION; |
243 | else if (f34->v7.config_area == v7_DP_CONFIG_AREA) |
244 | partition = DISPLAY_CONFIG_PARTITION; |
245 | else if (f34->v7.config_area == v7_PM_CONFIG_AREA) |
246 | partition = GUEST_SERIALIZATION_PARTITION; |
247 | else if (f34->v7.config_area == v7_BL_CONFIG_AREA) |
248 | partition = GLOBAL_PARAMETERS_PARTITION; |
249 | else if (f34->v7.config_area == v7_FLASH_CONFIG_AREA) |
250 | partition = FLASH_CONFIG_PARTITION; |
251 | break; |
252 | case v7_CMD_WRITE_GUEST_CODE: |
253 | partition = GUEST_CODE_PARTITION; |
254 | break; |
255 | case v7_CMD_ERASE_ALL: |
256 | partition = CORE_CODE_PARTITION; |
257 | break; |
258 | case v7_CMD_ERASE_BL_CONFIG: |
259 | partition = GLOBAL_PARAMETERS_PARTITION; |
260 | break; |
261 | case v7_CMD_ERASE_UI_CONFIG: |
262 | partition = CORE_CONFIG_PARTITION; |
263 | break; |
264 | case v7_CMD_ERASE_DISP_CONFIG: |
265 | partition = DISPLAY_CONFIG_PARTITION; |
266 | break; |
267 | case v7_CMD_ERASE_FLASH_CONFIG: |
268 | partition = FLASH_CONFIG_PARTITION; |
269 | break; |
270 | case v7_CMD_ERASE_GUEST_CODE: |
271 | partition = GUEST_CODE_PARTITION; |
272 | break; |
273 | case v7_CMD_ENABLE_FLASH_PROG: |
274 | partition = BOOTLOADER_PARTITION; |
275 | break; |
276 | default: |
277 | dev_err(&f34->fn->dev, "%s: Invalid command 0x%02x\n" , |
278 | __func__, cmd); |
279 | return -EINVAL; |
280 | } |
281 | |
282 | ret = rmi_write_block(d: f34->fn->rmi_dev, |
283 | addr: base + V7_PARTITION_ID_OFFSET, |
284 | buf: &partition, len: sizeof(partition)); |
285 | if (ret < 0) { |
286 | dev_err(&f34->fn->dev, "%s: Failed to write partition ID\n" , |
287 | __func__); |
288 | return ret; |
289 | } |
290 | |
291 | return 0; |
292 | } |
293 | |
294 | static int rmi_f34v7_read_partition_table(struct f34_data *f34) |
295 | { |
296 | int ret; |
297 | unsigned long timeout; |
298 | u8 base; |
299 | __le16 length; |
300 | u16 block_number = 0; |
301 | |
302 | base = f34->fn->fd.data_base_addr; |
303 | |
304 | f34->v7.config_area = v7_FLASH_CONFIG_AREA; |
305 | |
306 | ret = rmi_f34v7_write_partition_id(f34, v7_CMD_READ_CONFIG); |
307 | if (ret < 0) |
308 | return ret; |
309 | |
310 | ret = rmi_write_block(d: f34->fn->rmi_dev, |
311 | addr: base + V7_BLOCK_NUMBER_OFFSET, |
312 | buf: &block_number, len: sizeof(block_number)); |
313 | if (ret < 0) { |
314 | dev_err(&f34->fn->dev, "%s: Failed to write block number\n" , |
315 | __func__); |
316 | return ret; |
317 | } |
318 | |
319 | put_unaligned_le16(val: f34->v7.flash_config_length, p: &length); |
320 | |
321 | ret = rmi_write_block(d: f34->fn->rmi_dev, |
322 | addr: base + V7_TRANSFER_LENGTH_OFFSET, |
323 | buf: &length, len: sizeof(length)); |
324 | if (ret < 0) { |
325 | dev_err(&f34->fn->dev, "%s: Failed to write transfer length\n" , |
326 | __func__); |
327 | return ret; |
328 | } |
329 | |
330 | init_completion(x: &f34->v7.cmd_done); |
331 | |
332 | ret = rmi_f34v7_write_command(f34, v7_CMD_READ_CONFIG); |
333 | if (ret < 0) { |
334 | dev_err(&f34->fn->dev, "%s: Failed to write command\n" , |
335 | __func__); |
336 | return ret; |
337 | } |
338 | |
339 | /* |
340 | * rmi_f34v7_check_command_status() can't be used here, as this |
341 | * function is called before IRQs are available |
342 | */ |
343 | timeout = msecs_to_jiffies(F34_WRITE_WAIT_MS); |
344 | while (time_before(jiffies, timeout)) { |
345 | usleep_range(min: 5000, max: 6000); |
346 | rmi_f34v7_read_flash_status(f34); |
347 | |
348 | if (f34->v7.command == v7_CMD_IDLE && |
349 | f34->v7.flash_status == 0x00) { |
350 | break; |
351 | } |
352 | } |
353 | |
354 | ret = rmi_read_block(d: f34->fn->rmi_dev, |
355 | addr: base + V7_PAYLOAD_OFFSET, |
356 | buf: f34->v7.read_config_buf, |
357 | len: f34->v7.partition_table_bytes); |
358 | if (ret < 0) { |
359 | dev_err(&f34->fn->dev, "%s: Failed to read block data\n" , |
360 | __func__); |
361 | return ret; |
362 | } |
363 | |
364 | return 0; |
365 | } |
366 | |
367 | static void rmi_f34v7_parse_partition_table(struct f34_data *f34, |
368 | const void *partition_table, |
369 | struct block_count *blkcount, |
370 | struct physical_address *phyaddr) |
371 | { |
372 | int i; |
373 | int index; |
374 | u16 partition_length; |
375 | u16 physical_address; |
376 | const struct partition_table *ptable; |
377 | |
378 | for (i = 0; i < f34->v7.partitions; i++) { |
379 | index = i * 8 + 2; |
380 | ptable = partition_table + index; |
381 | partition_length = le16_to_cpu(ptable->partition_length); |
382 | physical_address = le16_to_cpu(ptable->start_physical_address); |
383 | rmi_dbg(RMI_DEBUG_FN, dev: &f34->fn->dev, |
384 | fmt: "%s: Partition entry %d: %*ph\n" , |
385 | __func__, i, sizeof(struct partition_table), ptable); |
386 | switch (ptable->partition_id & 0x1f) { |
387 | case CORE_CODE_PARTITION: |
388 | blkcount->ui_firmware = partition_length; |
389 | phyaddr->ui_firmware = physical_address; |
390 | rmi_dbg(RMI_DEBUG_FN, dev: &f34->fn->dev, |
391 | fmt: "%s: Core code block count: %d\n" , |
392 | __func__, blkcount->ui_firmware); |
393 | break; |
394 | case CORE_CONFIG_PARTITION: |
395 | blkcount->ui_config = partition_length; |
396 | phyaddr->ui_config = physical_address; |
397 | rmi_dbg(RMI_DEBUG_FN, dev: &f34->fn->dev, |
398 | fmt: "%s: Core config block count: %d\n" , |
399 | __func__, blkcount->ui_config); |
400 | break; |
401 | case DISPLAY_CONFIG_PARTITION: |
402 | blkcount->dp_config = partition_length; |
403 | phyaddr->dp_config = physical_address; |
404 | rmi_dbg(RMI_DEBUG_FN, dev: &f34->fn->dev, |
405 | fmt: "%s: Display config block count: %d\n" , |
406 | __func__, blkcount->dp_config); |
407 | break; |
408 | case FLASH_CONFIG_PARTITION: |
409 | blkcount->fl_config = partition_length; |
410 | rmi_dbg(RMI_DEBUG_FN, dev: &f34->fn->dev, |
411 | fmt: "%s: Flash config block count: %d\n" , |
412 | __func__, blkcount->fl_config); |
413 | break; |
414 | case GUEST_CODE_PARTITION: |
415 | blkcount->guest_code = partition_length; |
416 | phyaddr->guest_code = physical_address; |
417 | rmi_dbg(RMI_DEBUG_FN, dev: &f34->fn->dev, |
418 | fmt: "%s: Guest code block count: %d\n" , |
419 | __func__, blkcount->guest_code); |
420 | break; |
421 | case GUEST_SERIALIZATION_PARTITION: |
422 | blkcount->pm_config = partition_length; |
423 | rmi_dbg(RMI_DEBUG_FN, dev: &f34->fn->dev, |
424 | fmt: "%s: Guest serialization block count: %d\n" , |
425 | __func__, blkcount->pm_config); |
426 | break; |
427 | case GLOBAL_PARAMETERS_PARTITION: |
428 | blkcount->bl_config = partition_length; |
429 | rmi_dbg(RMI_DEBUG_FN, dev: &f34->fn->dev, |
430 | fmt: "%s: Global parameters block count: %d\n" , |
431 | __func__, blkcount->bl_config); |
432 | break; |
433 | case DEVICE_CONFIG_PARTITION: |
434 | blkcount->lockdown = partition_length; |
435 | rmi_dbg(RMI_DEBUG_FN, dev: &f34->fn->dev, |
436 | fmt: "%s: Device config block count: %d\n" , |
437 | __func__, blkcount->lockdown); |
438 | break; |
439 | } |
440 | } |
441 | } |
442 | |
443 | static int rmi_f34v7_read_queries_bl_version(struct f34_data *f34) |
444 | { |
445 | int ret; |
446 | u8 base; |
447 | int offset; |
448 | u8 query_0; |
449 | struct f34v7_query_1_7 query_1_7; |
450 | |
451 | base = f34->fn->fd.query_base_addr; |
452 | |
453 | ret = rmi_read_block(d: f34->fn->rmi_dev, |
454 | addr: base, |
455 | buf: &query_0, |
456 | len: sizeof(query_0)); |
457 | if (ret < 0) { |
458 | dev_err(&f34->fn->dev, |
459 | "%s: Failed to read query 0\n" , __func__); |
460 | return ret; |
461 | } |
462 | |
463 | offset = (query_0 & 0x7) + 1; |
464 | |
465 | ret = rmi_read_block(d: f34->fn->rmi_dev, |
466 | addr: base + offset, |
467 | buf: &query_1_7, |
468 | len: sizeof(query_1_7)); |
469 | if (ret < 0) { |
470 | dev_err(&f34->fn->dev, "%s: Failed to read queries 1 to 7\n" , |
471 | __func__); |
472 | return ret; |
473 | } |
474 | |
475 | f34->bootloader_id[0] = query_1_7.bl_minor_revision; |
476 | f34->bootloader_id[1] = query_1_7.bl_major_revision; |
477 | |
478 | rmi_dbg(RMI_DEBUG_FN, dev: &f34->fn->dev, fmt: "Bootloader V%d.%d\n" , |
479 | f34->bootloader_id[1], f34->bootloader_id[0]); |
480 | |
481 | return 0; |
482 | } |
483 | |
484 | static int rmi_f34v7_read_queries(struct f34_data *f34) |
485 | { |
486 | int ret; |
487 | int i; |
488 | u8 base; |
489 | int offset; |
490 | u8 *ptable; |
491 | u8 query_0; |
492 | struct f34v7_query_1_7 query_1_7; |
493 | |
494 | base = f34->fn->fd.query_base_addr; |
495 | |
496 | ret = rmi_read_block(d: f34->fn->rmi_dev, |
497 | addr: base, |
498 | buf: &query_0, |
499 | len: sizeof(query_0)); |
500 | if (ret < 0) { |
501 | dev_err(&f34->fn->dev, |
502 | "%s: Failed to read query 0\n" , __func__); |
503 | return ret; |
504 | } |
505 | |
506 | offset = (query_0 & 0x07) + 1; |
507 | |
508 | ret = rmi_read_block(d: f34->fn->rmi_dev, |
509 | addr: base + offset, |
510 | buf: &query_1_7, |
511 | len: sizeof(query_1_7)); |
512 | if (ret < 0) { |
513 | dev_err(&f34->fn->dev, "%s: Failed to read queries 1 to 7\n" , |
514 | __func__); |
515 | return ret; |
516 | } |
517 | |
518 | f34->bootloader_id[0] = query_1_7.bl_minor_revision; |
519 | f34->bootloader_id[1] = query_1_7.bl_major_revision; |
520 | |
521 | f34->v7.block_size = le16_to_cpu(query_1_7.block_size); |
522 | f34->v7.flash_config_length = |
523 | le16_to_cpu(query_1_7.flash_config_length); |
524 | f34->v7.payload_length = le16_to_cpu(query_1_7.payload_length); |
525 | |
526 | rmi_dbg(RMI_DEBUG_FN, dev: &f34->fn->dev, fmt: "%s: f34->v7.block_size = %d\n" , |
527 | __func__, f34->v7.block_size); |
528 | |
529 | f34->v7.has_display_cfg = query_1_7.partition_support[1] & HAS_DISP_CFG; |
530 | f34->v7.has_guest_code = |
531 | query_1_7.partition_support[1] & HAS_GUEST_CODE; |
532 | |
533 | if (query_0 & HAS_CONFIG_ID) { |
534 | u8 f34_ctrl[CONFIG_ID_SIZE]; |
535 | |
536 | ret = rmi_read_block(d: f34->fn->rmi_dev, |
537 | addr: f34->fn->fd.control_base_addr, |
538 | buf: f34_ctrl, |
539 | len: sizeof(f34_ctrl)); |
540 | if (ret) |
541 | return ret; |
542 | |
543 | /* Eat leading zeros */ |
544 | for (i = 0; i < sizeof(f34_ctrl) - 1 && !f34_ctrl[i]; i++) |
545 | /* Empty */; |
546 | |
547 | snprintf(buf: f34->configuration_id, size: sizeof(f34->configuration_id), |
548 | fmt: "%*phN" , (int)sizeof(f34_ctrl) - i, f34_ctrl + i); |
549 | |
550 | rmi_dbg(RMI_DEBUG_FN, dev: &f34->fn->dev, fmt: "Configuration ID: %s\n" , |
551 | f34->configuration_id); |
552 | } |
553 | |
554 | f34->v7.partitions = 0; |
555 | for (i = 0; i < sizeof(query_1_7.partition_support); i++) |
556 | f34->v7.partitions += hweight8(query_1_7.partition_support[i]); |
557 | |
558 | rmi_dbg(RMI_DEBUG_FN, dev: &f34->fn->dev, fmt: "%s: Supported partitions: %*ph\n" , |
559 | __func__, sizeof(query_1_7.partition_support), |
560 | query_1_7.partition_support); |
561 | |
562 | |
563 | f34->v7.partition_table_bytes = f34->v7.partitions * 8 + 2; |
564 | |
565 | f34->v7.read_config_buf = devm_kzalloc(dev: &f34->fn->dev, |
566 | size: f34->v7.partition_table_bytes, |
567 | GFP_KERNEL); |
568 | if (!f34->v7.read_config_buf) { |
569 | f34->v7.read_config_buf_size = 0; |
570 | return -ENOMEM; |
571 | } |
572 | |
573 | f34->v7.read_config_buf_size = f34->v7.partition_table_bytes; |
574 | ptable = f34->v7.read_config_buf; |
575 | |
576 | ret = rmi_f34v7_read_partition_table(f34); |
577 | if (ret < 0) { |
578 | dev_err(&f34->fn->dev, "%s: Failed to read partition table\n" , |
579 | __func__); |
580 | return ret; |
581 | } |
582 | |
583 | rmi_f34v7_parse_partition_table(f34, partition_table: ptable, |
584 | blkcount: &f34->v7.blkcount, phyaddr: &f34->v7.phyaddr); |
585 | |
586 | return 0; |
587 | } |
588 | |
589 | static int rmi_f34v7_check_bl_config_size(struct f34_data *f34) |
590 | { |
591 | u16 block_count; |
592 | |
593 | block_count = f34->v7.img.bl_config.size / f34->v7.block_size; |
594 | f34->update_size += block_count; |
595 | |
596 | if (block_count != f34->v7.blkcount.bl_config) { |
597 | dev_err(&f34->fn->dev, "Bootloader config size mismatch\n" ); |
598 | return -EINVAL; |
599 | } |
600 | |
601 | return 0; |
602 | } |
603 | |
604 | static int rmi_f34v7_erase_all(struct f34_data *f34) |
605 | { |
606 | int ret; |
607 | |
608 | dev_info(&f34->fn->dev, "Erasing firmware...\n" ); |
609 | |
610 | init_completion(x: &f34->v7.cmd_done); |
611 | |
612 | ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_ALL); |
613 | if (ret < 0) |
614 | return ret; |
615 | |
616 | ret = rmi_f34v7_check_command_status(f34, F34_ERASE_WAIT_MS); |
617 | if (ret < 0) |
618 | return ret; |
619 | |
620 | return 0; |
621 | } |
622 | |
623 | static int rmi_f34v7_read_blocks(struct f34_data *f34, |
624 | u16 block_cnt, u8 command) |
625 | { |
626 | int ret; |
627 | u8 base; |
628 | __le16 length; |
629 | u16 transfer; |
630 | u16 max_transfer; |
631 | u16 remaining = block_cnt; |
632 | u16 block_number = 0; |
633 | u16 index = 0; |
634 | |
635 | base = f34->fn->fd.data_base_addr; |
636 | |
637 | ret = rmi_f34v7_write_partition_id(f34, cmd: command); |
638 | if (ret < 0) |
639 | return ret; |
640 | |
641 | ret = rmi_write_block(d: f34->fn->rmi_dev, |
642 | addr: base + V7_BLOCK_NUMBER_OFFSET, |
643 | buf: &block_number, len: sizeof(block_number)); |
644 | if (ret < 0) { |
645 | dev_err(&f34->fn->dev, "%s: Failed to write block number\n" , |
646 | __func__); |
647 | return ret; |
648 | } |
649 | |
650 | max_transfer = min(f34->v7.payload_length, |
651 | (u16)(PAGE_SIZE / f34->v7.block_size)); |
652 | |
653 | do { |
654 | transfer = min(remaining, max_transfer); |
655 | put_unaligned_le16(val: transfer, p: &length); |
656 | |
657 | ret = rmi_write_block(d: f34->fn->rmi_dev, |
658 | addr: base + V7_TRANSFER_LENGTH_OFFSET, |
659 | buf: &length, len: sizeof(length)); |
660 | if (ret < 0) { |
661 | dev_err(&f34->fn->dev, |
662 | "%s: Write transfer length fail (%d remaining)\n" , |
663 | __func__, remaining); |
664 | return ret; |
665 | } |
666 | |
667 | init_completion(x: &f34->v7.cmd_done); |
668 | |
669 | ret = rmi_f34v7_write_command(f34, cmd: command); |
670 | if (ret < 0) |
671 | return ret; |
672 | |
673 | ret = rmi_f34v7_check_command_status(f34, F34_ENABLE_WAIT_MS); |
674 | if (ret < 0) |
675 | return ret; |
676 | |
677 | ret = rmi_read_block(d: f34->fn->rmi_dev, |
678 | addr: base + V7_PAYLOAD_OFFSET, |
679 | buf: &f34->v7.read_config_buf[index], |
680 | len: transfer * f34->v7.block_size); |
681 | if (ret < 0) { |
682 | dev_err(&f34->fn->dev, |
683 | "%s: Read block failed (%d blks remaining)\n" , |
684 | __func__, remaining); |
685 | return ret; |
686 | } |
687 | |
688 | index += (transfer * f34->v7.block_size); |
689 | remaining -= transfer; |
690 | } while (remaining); |
691 | |
692 | return 0; |
693 | } |
694 | |
695 | static int rmi_f34v7_write_f34v7_blocks(struct f34_data *f34, |
696 | const void *block_ptr, u16 block_cnt, |
697 | u8 command) |
698 | { |
699 | int ret; |
700 | u8 base; |
701 | __le16 length; |
702 | u16 transfer; |
703 | u16 max_transfer; |
704 | u16 remaining = block_cnt; |
705 | u16 block_number = 0; |
706 | |
707 | base = f34->fn->fd.data_base_addr; |
708 | |
709 | ret = rmi_f34v7_write_partition_id(f34, cmd: command); |
710 | if (ret < 0) |
711 | return ret; |
712 | |
713 | ret = rmi_write_block(d: f34->fn->rmi_dev, |
714 | addr: base + V7_BLOCK_NUMBER_OFFSET, |
715 | buf: &block_number, len: sizeof(block_number)); |
716 | if (ret < 0) { |
717 | dev_err(&f34->fn->dev, "%s: Failed to write block number\n" , |
718 | __func__); |
719 | return ret; |
720 | } |
721 | |
722 | if (f34->v7.payload_length > (PAGE_SIZE / f34->v7.block_size)) |
723 | max_transfer = PAGE_SIZE / f34->v7.block_size; |
724 | else |
725 | max_transfer = f34->v7.payload_length; |
726 | |
727 | do { |
728 | transfer = min(remaining, max_transfer); |
729 | put_unaligned_le16(val: transfer, p: &length); |
730 | |
731 | init_completion(x: &f34->v7.cmd_done); |
732 | |
733 | ret = rmi_write_block(d: f34->fn->rmi_dev, |
734 | addr: base + V7_TRANSFER_LENGTH_OFFSET, |
735 | buf: &length, len: sizeof(length)); |
736 | if (ret < 0) { |
737 | dev_err(&f34->fn->dev, |
738 | "%s: Write transfer length fail (%d remaining)\n" , |
739 | __func__, remaining); |
740 | return ret; |
741 | } |
742 | |
743 | ret = rmi_f34v7_write_command(f34, cmd: command); |
744 | if (ret < 0) |
745 | return ret; |
746 | |
747 | ret = rmi_write_block(d: f34->fn->rmi_dev, |
748 | addr: base + V7_PAYLOAD_OFFSET, |
749 | buf: block_ptr, len: transfer * f34->v7.block_size); |
750 | if (ret < 0) { |
751 | dev_err(&f34->fn->dev, |
752 | "%s: Failed writing data (%d blks remaining)\n" , |
753 | __func__, remaining); |
754 | return ret; |
755 | } |
756 | |
757 | ret = rmi_f34v7_check_command_status(f34, F34_ENABLE_WAIT_MS); |
758 | if (ret < 0) |
759 | return ret; |
760 | |
761 | block_ptr += (transfer * f34->v7.block_size); |
762 | remaining -= transfer; |
763 | f34->update_progress += transfer; |
764 | f34->update_status = (f34->update_progress * 100) / |
765 | f34->update_size; |
766 | } while (remaining); |
767 | |
768 | return 0; |
769 | } |
770 | |
771 | static int rmi_f34v7_write_config(struct f34_data *f34) |
772 | { |
773 | return rmi_f34v7_write_f34v7_blocks(f34, block_ptr: f34->v7.config_data, |
774 | block_cnt: f34->v7.config_block_count, |
775 | v7_CMD_WRITE_CONFIG); |
776 | } |
777 | |
778 | static int rmi_f34v7_write_ui_config(struct f34_data *f34) |
779 | { |
780 | f34->v7.config_area = v7_UI_CONFIG_AREA; |
781 | f34->v7.config_data = f34->v7.img.ui_config.data; |
782 | f34->v7.config_size = f34->v7.img.ui_config.size; |
783 | f34->v7.config_block_count = f34->v7.config_size / f34->v7.block_size; |
784 | |
785 | return rmi_f34v7_write_config(f34); |
786 | } |
787 | |
788 | static int rmi_f34v7_write_dp_config(struct f34_data *f34) |
789 | { |
790 | f34->v7.config_area = v7_DP_CONFIG_AREA; |
791 | f34->v7.config_data = f34->v7.img.dp_config.data; |
792 | f34->v7.config_size = f34->v7.img.dp_config.size; |
793 | f34->v7.config_block_count = f34->v7.config_size / f34->v7.block_size; |
794 | |
795 | return rmi_f34v7_write_config(f34); |
796 | } |
797 | |
798 | static int rmi_f34v7_write_guest_code(struct f34_data *f34) |
799 | { |
800 | return rmi_f34v7_write_f34v7_blocks(f34, block_ptr: f34->v7.img.guest_code.data, |
801 | block_cnt: f34->v7.img.guest_code.size / |
802 | f34->v7.block_size, |
803 | v7_CMD_WRITE_GUEST_CODE); |
804 | } |
805 | |
806 | static int rmi_f34v7_write_flash_config(struct f34_data *f34) |
807 | { |
808 | int ret; |
809 | |
810 | f34->v7.config_area = v7_FLASH_CONFIG_AREA; |
811 | f34->v7.config_data = f34->v7.img.fl_config.data; |
812 | f34->v7.config_size = f34->v7.img.fl_config.size; |
813 | f34->v7.config_block_count = f34->v7.config_size / f34->v7.block_size; |
814 | |
815 | if (f34->v7.config_block_count != f34->v7.blkcount.fl_config) { |
816 | dev_err(&f34->fn->dev, "%s: Flash config size mismatch\n" , |
817 | __func__); |
818 | return -EINVAL; |
819 | } |
820 | |
821 | init_completion(x: &f34->v7.cmd_done); |
822 | |
823 | ret = rmi_f34v7_write_config(f34); |
824 | if (ret < 0) |
825 | return ret; |
826 | |
827 | return 0; |
828 | } |
829 | |
830 | static int rmi_f34v7_write_partition_table(struct f34_data *f34) |
831 | { |
832 | u16 block_count; |
833 | int ret; |
834 | |
835 | block_count = f34->v7.blkcount.bl_config; |
836 | f34->v7.config_area = v7_BL_CONFIG_AREA; |
837 | f34->v7.config_size = f34->v7.block_size * block_count; |
838 | devm_kfree(dev: &f34->fn->dev, p: f34->v7.read_config_buf); |
839 | f34->v7.read_config_buf = devm_kzalloc(dev: &f34->fn->dev, |
840 | size: f34->v7.config_size, GFP_KERNEL); |
841 | if (!f34->v7.read_config_buf) { |
842 | f34->v7.read_config_buf_size = 0; |
843 | return -ENOMEM; |
844 | } |
845 | |
846 | f34->v7.read_config_buf_size = f34->v7.config_size; |
847 | |
848 | ret = rmi_f34v7_read_blocks(f34, block_cnt: block_count, v7_CMD_READ_CONFIG); |
849 | if (ret < 0) |
850 | return ret; |
851 | |
852 | ret = rmi_f34v7_write_flash_config(f34); |
853 | if (ret < 0) |
854 | return ret; |
855 | |
856 | f34->v7.config_area = v7_BL_CONFIG_AREA; |
857 | f34->v7.config_data = f34->v7.read_config_buf; |
858 | f34->v7.config_size = f34->v7.img.bl_config.size; |
859 | f34->v7.config_block_count = f34->v7.config_size / f34->v7.block_size; |
860 | |
861 | ret = rmi_f34v7_write_config(f34); |
862 | if (ret < 0) |
863 | return ret; |
864 | |
865 | return 0; |
866 | } |
867 | |
868 | static int rmi_f34v7_write_firmware(struct f34_data *f34) |
869 | { |
870 | u16 blk_count; |
871 | |
872 | blk_count = f34->v7.img.ui_firmware.size / f34->v7.block_size; |
873 | |
874 | return rmi_f34v7_write_f34v7_blocks(f34, block_ptr: f34->v7.img.ui_firmware.data, |
875 | block_cnt: blk_count, v7_CMD_WRITE_FW); |
876 | } |
877 | |
878 | static void (struct f34_data *f34, |
879 | const void *image) |
880 | { |
881 | int i; |
882 | int num_of_containers; |
883 | unsigned int addr; |
884 | unsigned int container_id; |
885 | unsigned int length; |
886 | const void *content; |
887 | const struct container_descriptor *descriptor; |
888 | |
889 | num_of_containers = f34->v7.img.bootloader.size / 4 - 1; |
890 | |
891 | for (i = 1; i <= num_of_containers; i++) { |
892 | addr = get_unaligned_le32(p: f34->v7.img.bootloader.data + i * 4); |
893 | descriptor = image + addr; |
894 | container_id = le16_to_cpu(descriptor->container_id); |
895 | content = image + le32_to_cpu(descriptor->content_address); |
896 | length = le32_to_cpu(descriptor->content_length); |
897 | switch (container_id) { |
898 | case BL_CONFIG_CONTAINER: |
899 | case GLOBAL_PARAMETERS_CONTAINER: |
900 | f34->v7.img.bl_config.data = content; |
901 | f34->v7.img.bl_config.size = length; |
902 | break; |
903 | case BL_LOCKDOWN_INFO_CONTAINER: |
904 | case DEVICE_CONFIG_CONTAINER: |
905 | f34->v7.img.lockdown.data = content; |
906 | f34->v7.img.lockdown.size = length; |
907 | break; |
908 | default: |
909 | break; |
910 | } |
911 | } |
912 | } |
913 | |
914 | static void (struct f34_data *f34) |
915 | { |
916 | unsigned int i; |
917 | unsigned int num_of_containers; |
918 | unsigned int addr; |
919 | unsigned int offset; |
920 | unsigned int container_id; |
921 | unsigned int length; |
922 | const void *image = f34->v7.image; |
923 | const u8 *content; |
924 | const struct container_descriptor *descriptor; |
925 | const struct image_header_10 * = image; |
926 | |
927 | f34->v7.img.checksum = le32_to_cpu(header->checksum); |
928 | |
929 | rmi_dbg(RMI_DEBUG_FN, dev: &f34->fn->dev, fmt: "%s: f34->v7.img.checksum=%X\n" , |
930 | __func__, f34->v7.img.checksum); |
931 | |
932 | /* address of top level container */ |
933 | offset = le32_to_cpu(header->top_level_container_start_addr); |
934 | descriptor = image + offset; |
935 | |
936 | /* address of top level container content */ |
937 | offset = le32_to_cpu(descriptor->content_address); |
938 | num_of_containers = le32_to_cpu(descriptor->content_length) / 4; |
939 | |
940 | for (i = 0; i < num_of_containers; i++) { |
941 | addr = get_unaligned_le32(p: image + offset); |
942 | offset += 4; |
943 | descriptor = image + addr; |
944 | container_id = le16_to_cpu(descriptor->container_id); |
945 | content = image + le32_to_cpu(descriptor->content_address); |
946 | length = le32_to_cpu(descriptor->content_length); |
947 | |
948 | rmi_dbg(RMI_DEBUG_FN, dev: &f34->fn->dev, |
949 | fmt: "%s: container_id=%d, length=%d\n" , __func__, |
950 | container_id, length); |
951 | |
952 | switch (container_id) { |
953 | case UI_CONTAINER: |
954 | case CORE_CODE_CONTAINER: |
955 | f34->v7.img.ui_firmware.data = content; |
956 | f34->v7.img.ui_firmware.size = length; |
957 | break; |
958 | case UI_CONFIG_CONTAINER: |
959 | case CORE_CONFIG_CONTAINER: |
960 | f34->v7.img.ui_config.data = content; |
961 | f34->v7.img.ui_config.size = length; |
962 | break; |
963 | case BL_CONTAINER: |
964 | f34->v7.img.bl_version = *content; |
965 | f34->v7.img.bootloader.data = content; |
966 | f34->v7.img.bootloader.size = length; |
967 | rmi_f34v7_parse_img_header_10_bl_container(f34, image); |
968 | break; |
969 | case GUEST_CODE_CONTAINER: |
970 | f34->v7.img.contains_guest_code = true; |
971 | f34->v7.img.guest_code.data = content; |
972 | f34->v7.img.guest_code.size = length; |
973 | break; |
974 | case DISPLAY_CONFIG_CONTAINER: |
975 | f34->v7.img.contains_display_cfg = true; |
976 | f34->v7.img.dp_config.data = content; |
977 | f34->v7.img.dp_config.size = length; |
978 | break; |
979 | case FLASH_CONFIG_CONTAINER: |
980 | f34->v7.img.contains_flash_config = true; |
981 | f34->v7.img.fl_config.data = content; |
982 | f34->v7.img.fl_config.size = length; |
983 | break; |
984 | case GENERAL_INFORMATION_CONTAINER: |
985 | f34->v7.img.contains_firmware_id = true; |
986 | f34->v7.img.firmware_id = |
987 | get_unaligned_le32(p: content + 4); |
988 | break; |
989 | default: |
990 | break; |
991 | } |
992 | } |
993 | } |
994 | |
995 | static int rmi_f34v7_parse_image_info(struct f34_data *f34) |
996 | { |
997 | const struct image_header_10 * = f34->v7.image; |
998 | |
999 | memset(&f34->v7.img, 0x00, sizeof(f34->v7.img)); |
1000 | |
1001 | rmi_dbg(RMI_DEBUG_FN, dev: &f34->fn->dev, |
1002 | fmt: "%s: header->major_header_version = %d\n" , |
1003 | __func__, header->major_header_version); |
1004 | |
1005 | switch (header->major_header_version) { |
1006 | case IMAGE_HEADER_VERSION_10: |
1007 | rmi_f34v7_parse_image_header_10(f34); |
1008 | break; |
1009 | default: |
1010 | dev_err(&f34->fn->dev, "Unsupported image file format %02X\n" , |
1011 | header->major_header_version); |
1012 | return -EINVAL; |
1013 | } |
1014 | |
1015 | if (!f34->v7.img.contains_flash_config) { |
1016 | dev_err(&f34->fn->dev, "%s: No flash config in fw image\n" , |
1017 | __func__); |
1018 | return -EINVAL; |
1019 | } |
1020 | |
1021 | rmi_f34v7_parse_partition_table(f34, partition_table: f34->v7.img.fl_config.data, |
1022 | blkcount: &f34->v7.img.blkcount, phyaddr: &f34->v7.img.phyaddr); |
1023 | |
1024 | return 0; |
1025 | } |
1026 | |
1027 | int rmi_f34v7_do_reflash(struct f34_data *f34, const struct firmware *fw) |
1028 | { |
1029 | int ret; |
1030 | |
1031 | f34->fn->rmi_dev->driver->set_irq_bits(f34->fn->rmi_dev, |
1032 | f34->fn->irq_mask); |
1033 | |
1034 | rmi_f34v7_read_queries_bl_version(f34); |
1035 | |
1036 | f34->v7.image = fw->data; |
1037 | f34->update_progress = 0; |
1038 | f34->update_size = 0; |
1039 | |
1040 | ret = rmi_f34v7_parse_image_info(f34); |
1041 | if (ret < 0) |
1042 | return ret; |
1043 | |
1044 | ret = rmi_f34v7_check_bl_config_size(f34); |
1045 | if (ret < 0) |
1046 | return ret; |
1047 | |
1048 | ret = rmi_f34v7_erase_all(f34); |
1049 | if (ret < 0) |
1050 | return ret; |
1051 | |
1052 | ret = rmi_f34v7_write_partition_table(f34); |
1053 | if (ret < 0) |
1054 | return ret; |
1055 | dev_info(&f34->fn->dev, "%s: Partition table programmed\n" , __func__); |
1056 | |
1057 | /* |
1058 | * Reset to reload partition table - as the previous firmware has been |
1059 | * erased, we remain in bootloader mode. |
1060 | */ |
1061 | ret = rmi_scan_pdt(rmi_dev: f34->fn->rmi_dev, NULL, callback: rmi_initial_reset); |
1062 | if (ret < 0) |
1063 | dev_warn(&f34->fn->dev, "RMI reset failed!\n" ); |
1064 | |
1065 | dev_info(&f34->fn->dev, "Writing firmware (%d bytes)...\n" , |
1066 | f34->v7.img.ui_firmware.size); |
1067 | |
1068 | ret = rmi_f34v7_write_firmware(f34); |
1069 | if (ret < 0) |
1070 | return ret; |
1071 | |
1072 | dev_info(&f34->fn->dev, "Writing config (%d bytes)...\n" , |
1073 | f34->v7.img.ui_config.size); |
1074 | |
1075 | f34->v7.config_area = v7_UI_CONFIG_AREA; |
1076 | ret = rmi_f34v7_write_ui_config(f34); |
1077 | if (ret < 0) |
1078 | return ret; |
1079 | |
1080 | if (f34->v7.has_display_cfg && f34->v7.img.contains_display_cfg) { |
1081 | dev_info(&f34->fn->dev, "Writing display config...\n" ); |
1082 | |
1083 | ret = rmi_f34v7_write_dp_config(f34); |
1084 | if (ret < 0) |
1085 | return ret; |
1086 | } |
1087 | |
1088 | if (f34->v7.has_guest_code && f34->v7.img.contains_guest_code) { |
1089 | dev_info(&f34->fn->dev, "Writing guest code...\n" ); |
1090 | |
1091 | ret = rmi_f34v7_write_guest_code(f34); |
1092 | if (ret < 0) |
1093 | return ret; |
1094 | } |
1095 | |
1096 | return 0; |
1097 | } |
1098 | |
1099 | static int rmi_f34v7_enter_flash_prog(struct f34_data *f34) |
1100 | { |
1101 | int ret; |
1102 | |
1103 | f34->fn->rmi_dev->driver->set_irq_bits(f34->fn->rmi_dev, f34->fn->irq_mask); |
1104 | |
1105 | ret = rmi_f34v7_read_flash_status(f34); |
1106 | if (ret < 0) |
1107 | return ret; |
1108 | |
1109 | if (f34->v7.in_bl_mode) { |
1110 | dev_info(&f34->fn->dev, "%s: Device in bootloader mode\n" , |
1111 | __func__); |
1112 | return 0; |
1113 | } |
1114 | |
1115 | init_completion(x: &f34->v7.cmd_done); |
1116 | |
1117 | ret = rmi_f34v7_write_command(f34, v7_CMD_ENABLE_FLASH_PROG); |
1118 | if (ret < 0) |
1119 | return ret; |
1120 | |
1121 | ret = rmi_f34v7_check_command_status(f34, F34_ENABLE_WAIT_MS); |
1122 | if (ret < 0) |
1123 | return ret; |
1124 | |
1125 | return 0; |
1126 | } |
1127 | |
1128 | int rmi_f34v7_start_reflash(struct f34_data *f34, const struct firmware *fw) |
1129 | { |
1130 | int ret = 0; |
1131 | |
1132 | f34->v7.config_area = v7_UI_CONFIG_AREA; |
1133 | f34->v7.image = fw->data; |
1134 | |
1135 | ret = rmi_f34v7_parse_image_info(f34); |
1136 | if (ret < 0) |
1137 | return ret; |
1138 | |
1139 | dev_info(&f34->fn->dev, "Firmware image OK\n" ); |
1140 | |
1141 | return rmi_f34v7_enter_flash_prog(f34); |
1142 | } |
1143 | |
1144 | int rmi_f34v7_probe(struct f34_data *f34) |
1145 | { |
1146 | int ret; |
1147 | |
1148 | /* Read bootloader version */ |
1149 | ret = rmi_read_block(d: f34->fn->rmi_dev, |
1150 | addr: f34->fn->fd.query_base_addr + V7_BOOTLOADER_ID_OFFSET, |
1151 | buf: f34->bootloader_id, |
1152 | len: sizeof(f34->bootloader_id)); |
1153 | if (ret < 0) { |
1154 | dev_err(&f34->fn->dev, "%s: Failed to read bootloader ID\n" , |
1155 | __func__); |
1156 | return ret; |
1157 | } |
1158 | |
1159 | if (f34->bootloader_id[1] == '5') { |
1160 | f34->bl_version = 5; |
1161 | } else if (f34->bootloader_id[1] == '6') { |
1162 | f34->bl_version = 6; |
1163 | } else if (f34->bootloader_id[1] == 7) { |
1164 | f34->bl_version = 7; |
1165 | } else if (f34->bootloader_id[1] == 8) { |
1166 | f34->bl_version = 8; |
1167 | } else { |
1168 | dev_err(&f34->fn->dev, |
1169 | "%s: Unrecognized bootloader version: %d (%c) %d (%c)\n" , |
1170 | __func__, |
1171 | f34->bootloader_id[0], f34->bootloader_id[0], |
1172 | f34->bootloader_id[1], f34->bootloader_id[1]); |
1173 | return -EINVAL; |
1174 | } |
1175 | |
1176 | memset(&f34->v7.blkcount, 0x00, sizeof(f34->v7.blkcount)); |
1177 | memset(&f34->v7.phyaddr, 0x00, sizeof(f34->v7.phyaddr)); |
1178 | |
1179 | init_completion(x: &f34->v7.cmd_done); |
1180 | |
1181 | ret = rmi_f34v7_read_queries(f34); |
1182 | if (ret < 0) |
1183 | return ret; |
1184 | |
1185 | return 0; |
1186 | } |
1187 | |