2 * Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
3 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 /* Algorithmic part of the firmware download.
19 * To be included in the container file providing framework
22 #define wil_err_fw(wil, fmt, arg...) wil_err(wil, "ERR[ FW ]" fmt, ##arg)
23 #define wil_dbg_fw(wil, fmt, arg...) wil_dbg(wil, "DBG[ FW ]" fmt, ##arg)
24 #define wil_hex_dump_fw(prefix_str, prefix_type, rowsize, \
25 groupsize, buf, len, ascii) \
26 print_hex_dump_debug("DBG[ FW ]" prefix_str, \
27 prefix_type, rowsize, \
28 groupsize, buf, len, ascii)
30 static bool wil_fw_addr_check(struct wil6210_priv
*wil
,
31 void __iomem
**ioaddr
, __le32 val
,
32 u32 size
, const char *msg
)
34 *ioaddr
= wmi_buffer_block(wil
, val
, size
);
36 wil_err_fw(wil
, "bad %s: 0x%08x\n", msg
, le32_to_cpu(val
));
43 * wil_fw_verify - verify firmware file validity
45 * perform various checks for the firmware file header.
46 * records are not validated.
48 * Return file size or negative error
50 static int wil_fw_verify(struct wil6210_priv
*wil
, const u8
*data
, size_t size
)
52 const struct wil_fw_record_head
*hdr
= (const void *)data
;
53 struct wil_fw_record_file_header fh
;
54 const struct wil_fw_record_file_header
*fh_
;
59 wil_err_fw(wil
, "image size not aligned: %zu\n", size
);
62 /* have enough data for the file header? */
63 if (size
< sizeof(*hdr
) + sizeof(fh
)) {
64 wil_err_fw(wil
, "file too short: %zu bytes\n", size
);
68 /* start with the file header? */
69 if (le16_to_cpu(hdr
->type
) != wil_fw_type_file_header
) {
70 wil_err_fw(wil
, "no file header\n");
75 fh_
= (struct wil_fw_record_file_header
*)&hdr
[1];
76 dlen
= le32_to_cpu(fh_
->data_len
);
78 wil_err_fw(wil
, "data length not aligned: %lu\n", (ulong
)dlen
);
82 wil_err_fw(wil
, "file truncated at %zu/%lu\n",
86 if (dlen
< sizeof(*hdr
) + sizeof(fh
)) {
87 wil_err_fw(wil
, "data length too short: %lu\n", (ulong
)dlen
);
92 if (le32_to_cpu(fh_
->signature
) != WIL_FW_SIGNATURE
) {
93 wil_err_fw(wil
, "bad header signature: 0x%08x\n",
94 le32_to_cpu(fh_
->signature
));
99 if (le32_to_cpu(fh_
->version
) > WIL_FW_FMT_VERSION
) {
100 wil_err_fw(wil
, "unsupported header version: %d\n",
101 le32_to_cpu(fh_
->version
));
105 /* checksum. ~crc32(~0, data, size) when fh.crc set to 0*/
109 crc
= crc32_le(~0, (unsigned char const *)hdr
, sizeof(*hdr
));
110 crc
= crc32_le(crc
, (unsigned char const *)&fh
, sizeof(fh
));
111 crc
= crc32_le(crc
, (unsigned char const *)&fh_
[1],
112 dlen
- sizeof(*hdr
) - sizeof(fh
));
115 if (crc
!= le32_to_cpu(fh_
->crc
)) {
116 wil_err_fw(wil
, "checksum mismatch:"
117 " calculated for %lu bytes 0x%08x != 0x%08x\n",
118 (ulong
)dlen
, crc
, le32_to_cpu(fh_
->crc
));
125 static int fw_ignore_section(struct wil6210_priv
*wil
, const void *data
,
132 fw_handle_capabilities(struct wil6210_priv
*wil
, const void *data
,
135 const struct wil_fw_record_capabilities
*rec
= data
;
138 if (size
< sizeof(*rec
)) {
139 wil_hex_dump_fw("", DUMP_PREFIX_OFFSET
, 16, 1,
144 capa_size
= size
- offsetof(struct wil_fw_record_capabilities
,
146 bitmap_zero(wil
->fw_capabilities
, WMI_FW_CAPABILITY_MAX
);
147 memcpy(wil
->fw_capabilities
, rec
->capabilities
,
148 min(sizeof(wil
->fw_capabilities
), capa_size
));
149 wil_hex_dump_fw("CAPA", DUMP_PREFIX_OFFSET
, 16, 1,
150 rec
->capabilities
, capa_size
, false);
155 fw_handle_brd_file(struct wil6210_priv
*wil
, const void *data
,
158 const struct wil_fw_record_brd_file
*rec
= data
;
160 if (size
< sizeof(*rec
)) {
161 wil_hex_dump_fw("", DUMP_PREFIX_OFFSET
, 16, 1,
166 wil
->brd_file_addr
= le32_to_cpu(rec
->base_addr
);
167 wil
->brd_file_max_size
= le32_to_cpu(rec
->max_size_bytes
);
169 wil_dbg_fw(wil
, "brd_file_addr 0x%x, brd_file_max_size %d\n",
170 wil
->brd_file_addr
, wil
->brd_file_max_size
);
176 fw_handle_comment(struct wil6210_priv
*wil
, const void *data
,
179 const struct wil_fw_record_comment_hdr
*hdr
= data
;
183 if (size
< sizeof(*hdr
))
186 magic
= le32_to_cpu(hdr
->magic
);
189 case WIL_FW_CAPABILITIES_MAGIC
:
190 wil_dbg_fw(wil
, "magic is WIL_FW_CAPABILITIES_MAGIC\n");
191 rc
= fw_handle_capabilities(wil
, data
, size
);
193 case WIL_BRD_FILE_MAGIC
:
194 wil_dbg_fw(wil
, "magic is WIL_BRD_FILE_MAGIC\n");
195 rc
= fw_handle_brd_file(wil
, data
, size
);
202 static int __fw_handle_data(struct wil6210_priv
*wil
, const void *data
,
203 size_t size
, __le32 addr
)
205 const struct wil_fw_record_data
*d
= data
;
207 size_t s
= size
- sizeof(*d
);
209 if (size
< sizeof(*d
) + sizeof(u32
)) {
210 wil_err_fw(wil
, "data record too short: %zu\n", size
);
214 if (!wil_fw_addr_check(wil
, &dst
, addr
, s
, "address"))
216 wil_dbg_fw(wil
, "write [0x%08x] <== %zu bytes\n", le32_to_cpu(addr
), s
);
217 wil_memcpy_toio_32(dst
, d
->data
, s
);
218 wmb(); /* finish before processing next record */
223 static int fw_handle_data(struct wil6210_priv
*wil
, const void *data
,
226 const struct wil_fw_record_data
*d
= data
;
228 return __fw_handle_data(wil
, data
, size
, d
->addr
);
231 static int fw_handle_fill(struct wil6210_priv
*wil
, const void *data
,
234 const struct wil_fw_record_fill
*d
= data
;
237 size_t s
= (size_t)le32_to_cpu(d
->size
);
239 if (size
!= sizeof(*d
)) {
240 wil_err_fw(wil
, "bad size for fill record: %zu\n", size
);
244 if (s
< sizeof(u32
)) {
245 wil_err_fw(wil
, "fill size too short: %zu\n", s
);
249 if (s
% sizeof(u32
)) {
250 wil_err_fw(wil
, "fill size not aligned: %zu\n", s
);
254 if (!wil_fw_addr_check(wil
, &dst
, d
->addr
, s
, "address"))
257 v
= le32_to_cpu(d
->value
);
258 wil_dbg_fw(wil
, "fill [0x%08x] <== 0x%08x, %zu bytes\n",
259 le32_to_cpu(d
->addr
), v
, s
);
260 wil_memset_toio_32(dst
, v
, s
);
261 wmb(); /* finish before processing next record */
266 static int fw_handle_file_header(struct wil6210_priv
*wil
, const void *data
,
269 const struct wil_fw_record_file_header
*d
= data
;
271 if (size
!= sizeof(*d
)) {
272 wil_err_fw(wil
, "file header length incorrect: %zu\n", size
);
276 wil_dbg_fw(wil
, "new file, ver. %d, %i bytes\n",
277 d
->version
, d
->data_len
);
278 wil_hex_dump_fw("", DUMP_PREFIX_OFFSET
, 16, 1, d
->comment
,
279 sizeof(d
->comment
), true);
281 if (!memcmp(d
->comment
, WIL_FW_VERSION_PREFIX
,
282 WIL_FW_VERSION_PREFIX_LEN
))
283 memcpy(wil
->fw_version
,
284 d
->comment
+ WIL_FW_VERSION_PREFIX_LEN
,
285 min(sizeof(d
->comment
) - WIL_FW_VERSION_PREFIX_LEN
,
286 sizeof(wil
->fw_version
) - 1));
291 static int fw_handle_direct_write(struct wil6210_priv
*wil
, const void *data
,
294 const struct wil_fw_record_direct_write
*d
= data
;
295 const struct wil_fw_data_dwrite
*block
= d
->data
;
298 if (size
% sizeof(*block
)) {
299 wil_err_fw(wil
, "record size not aligned on %zu: %zu\n",
300 sizeof(*block
), size
);
303 n
= size
/ sizeof(*block
);
305 for (i
= 0; i
< n
; i
++) {
307 u32 m
= le32_to_cpu(block
[i
].mask
);
308 u32 v
= le32_to_cpu(block
[i
].value
);
311 if (!wil_fw_addr_check(wil
, &dst
, block
[i
].addr
, 0, "address"))
315 y
= (x
& m
) | (v
& ~m
);
316 wil_dbg_fw(wil
, "write [0x%08x] <== 0x%08x "
317 "(old 0x%08x val 0x%08x mask 0x%08x)\n",
318 le32_to_cpu(block
[i
].addr
), y
, x
, v
, m
);
320 wmb(); /* finish before processing next record */
326 static int gw_write(struct wil6210_priv
*wil
, void __iomem
*gwa_addr
,
327 void __iomem
*gwa_cmd
, void __iomem
*gwa_ctl
, u32 gw_cmd
,
333 writel(gw_cmd
, gwa_cmd
);
334 wmb(); /* finish before activate gw */
336 writel(WIL_FW_GW_CTL_RUN
, gwa_ctl
); /* activate gw */
338 udelay(1); /* typical time is few usec */
340 wil_err_fw(wil
, "gw timeout\n");
343 } while (readl(gwa_ctl
) & WIL_FW_GW_CTL_BUSY
); /* gw done? */
348 static int fw_handle_gateway_data(struct wil6210_priv
*wil
, const void *data
,
351 const struct wil_fw_record_gateway_data
*d
= data
;
352 const struct wil_fw_data_gw
*block
= d
->data
;
353 void __iomem
*gwa_addr
;
354 void __iomem
*gwa_val
;
355 void __iomem
*gwa_cmd
;
356 void __iomem
*gwa_ctl
;
360 if (size
< sizeof(*d
) + sizeof(*block
)) {
361 wil_err_fw(wil
, "gateway record too short: %zu\n", size
);
365 if ((size
- sizeof(*d
)) % sizeof(*block
)) {
366 wil_err_fw(wil
, "gateway record data size"
367 " not aligned on %zu: %zu\n",
368 sizeof(*block
), size
- sizeof(*d
));
371 n
= (size
- sizeof(*d
)) / sizeof(*block
);
373 gw_cmd
= le32_to_cpu(d
->command
);
375 wil_dbg_fw(wil
, "gw write record [%3d] blocks, cmd 0x%08x\n",
378 if (!wil_fw_addr_check(wil
, &gwa_addr
, d
->gateway_addr_addr
, 0,
379 "gateway_addr_addr") ||
380 !wil_fw_addr_check(wil
, &gwa_val
, d
->gateway_value_addr
, 0,
381 "gateway_value_addr") ||
382 !wil_fw_addr_check(wil
, &gwa_cmd
, d
->gateway_cmd_addr
, 0,
383 "gateway_cmd_addr") ||
384 !wil_fw_addr_check(wil
, &gwa_ctl
, d
->gateway_ctrl_address
, 0,
385 "gateway_ctrl_address"))
388 wil_dbg_fw(wil
, "gw addresses: addr 0x%08x val 0x%08x"
389 " cmd 0x%08x ctl 0x%08x\n",
390 le32_to_cpu(d
->gateway_addr_addr
),
391 le32_to_cpu(d
->gateway_value_addr
),
392 le32_to_cpu(d
->gateway_cmd_addr
),
393 le32_to_cpu(d
->gateway_ctrl_address
));
395 for (i
= 0; i
< n
; i
++) {
397 u32 a
= le32_to_cpu(block
[i
].addr
);
398 u32 v
= le32_to_cpu(block
[i
].value
);
400 wil_dbg_fw(wil
, " gw write[%3d] [0x%08x] <== 0x%08x\n",
404 rc
= gw_write(wil
, gwa_addr
, gwa_cmd
, gwa_ctl
, gw_cmd
, a
);
412 static int fw_handle_gateway_data4(struct wil6210_priv
*wil
, const void *data
,
415 const struct wil_fw_record_gateway_data4
*d
= data
;
416 const struct wil_fw_data_gw4
*block
= d
->data
;
417 void __iomem
*gwa_addr
;
418 void __iomem
*gwa_val
[ARRAY_SIZE(block
->value
)];
419 void __iomem
*gwa_cmd
;
420 void __iomem
*gwa_ctl
;
424 if (size
< sizeof(*d
) + sizeof(*block
)) {
425 wil_err_fw(wil
, "gateway4 record too short: %zu\n", size
);
429 if ((size
- sizeof(*d
)) % sizeof(*block
)) {
430 wil_err_fw(wil
, "gateway4 record data size"
431 " not aligned on %zu: %zu\n",
432 sizeof(*block
), size
- sizeof(*d
));
435 n
= (size
- sizeof(*d
)) / sizeof(*block
);
437 gw_cmd
= le32_to_cpu(d
->command
);
439 wil_dbg_fw(wil
, "gw4 write record [%3d] blocks, cmd 0x%08x\n",
442 if (!wil_fw_addr_check(wil
, &gwa_addr
, d
->gateway_addr_addr
, 0,
443 "gateway_addr_addr"))
445 for (k
= 0; k
< ARRAY_SIZE(block
->value
); k
++)
446 if (!wil_fw_addr_check(wil
, &gwa_val
[k
],
447 d
->gateway_value_addr
[k
],
448 0, "gateway_value_addr"))
450 if (!wil_fw_addr_check(wil
, &gwa_cmd
, d
->gateway_cmd_addr
, 0,
451 "gateway_cmd_addr") ||
452 !wil_fw_addr_check(wil
, &gwa_ctl
, d
->gateway_ctrl_address
, 0,
453 "gateway_ctrl_address"))
456 wil_dbg_fw(wil
, "gw4 addresses: addr 0x%08x cmd 0x%08x ctl 0x%08x\n",
457 le32_to_cpu(d
->gateway_addr_addr
),
458 le32_to_cpu(d
->gateway_cmd_addr
),
459 le32_to_cpu(d
->gateway_ctrl_address
));
460 wil_hex_dump_fw("val addresses: ", DUMP_PREFIX_NONE
, 16, 4,
461 d
->gateway_value_addr
, sizeof(d
->gateway_value_addr
),
464 for (i
= 0; i
< n
; i
++) {
466 u32 a
= le32_to_cpu(block
[i
].addr
);
467 u32 v
[ARRAY_SIZE(block
->value
)];
469 for (k
= 0; k
< ARRAY_SIZE(block
->value
); k
++)
470 v
[k
] = le32_to_cpu(block
[i
].value
[k
]);
472 wil_dbg_fw(wil
, " gw4 write[%3d] [0x%08x] <==\n", i
, a
);
473 wil_hex_dump_fw(" val ", DUMP_PREFIX_NONE
, 16, 4, v
,
476 for (k
= 0; k
< ARRAY_SIZE(block
->value
); k
++)
477 writel(v
[k
], gwa_val
[k
]);
478 rc
= gw_write(wil
, gwa_addr
, gwa_cmd
, gwa_ctl
, gw_cmd
, a
);
486 static const struct {
488 int (*load_handler
)(struct wil6210_priv
*wil
, const void *data
,
490 int (*parse_handler
)(struct wil6210_priv
*wil
, const void *data
,
492 } wil_fw_handlers
[] = {
493 {wil_fw_type_comment
, fw_handle_comment
, fw_handle_comment
},
494 {wil_fw_type_data
, fw_handle_data
, fw_ignore_section
},
495 {wil_fw_type_fill
, fw_handle_fill
, fw_ignore_section
},
496 /* wil_fw_type_action */
497 /* wil_fw_type_verify */
498 {wil_fw_type_file_header
, fw_handle_file_header
,
499 fw_handle_file_header
},
500 {wil_fw_type_direct_write
, fw_handle_direct_write
, fw_ignore_section
},
501 {wil_fw_type_gateway_data
, fw_handle_gateway_data
, fw_ignore_section
},
502 {wil_fw_type_gateway_data4
, fw_handle_gateway_data4
,
506 static int wil_fw_handle_record(struct wil6210_priv
*wil
, int type
,
507 const void *data
, size_t size
, bool load
)
511 for (i
= 0; i
< ARRAY_SIZE(wil_fw_handlers
); i
++)
512 if (wil_fw_handlers
[i
].type
== type
)
514 wil_fw_handlers
[i
].load_handler(
516 wil_fw_handlers
[i
].parse_handler(
519 wil_err_fw(wil
, "unknown record type: %d\n", type
);
524 * wil_fw_process - process section from FW file
525 * if load is true: Load the FW and uCode code and data to the
526 * corresponding device memory regions,
527 * otherwise only parse and look for capabilities
531 static int wil_fw_process(struct wil6210_priv
*wil
, const void *data
,
532 size_t size
, bool load
)
535 const struct wil_fw_record_head
*hdr
;
538 for (hdr
= data
;; hdr
= (const void *)hdr
+ s
, size
-= s
) {
539 if (size
< sizeof(*hdr
))
541 hdr_sz
= le32_to_cpu(hdr
->size
);
542 s
= sizeof(*hdr
) + hdr_sz
;
546 wil_err_fw(wil
, "unaligned record size: %zu\n",
550 rc
= wil_fw_handle_record(wil
, le16_to_cpu(hdr
->type
),
551 &hdr
[1], hdr_sz
, load
);
556 wil_err_fw(wil
, "unprocessed bytes: %zu\n", size
);
557 if (size
>= sizeof(*hdr
)) {
558 wil_err_fw(wil
, "Stop at offset %ld"
559 " record type %d [%zd bytes]\n",
560 (long)((const void *)hdr
- data
),
561 le16_to_cpu(hdr
->type
), hdr_sz
);
570 * wil_request_firmware - Request firmware
572 * Request firmware image from the file
573 * If load is true, load firmware to device, otherwise
574 * only parse and extract capabilities
578 int wil_request_firmware(struct wil6210_priv
*wil
, const char *name
,
582 const struct firmware
*fw
;
586 rc
= request_firmware(&fw
, name
, wil_to_dev(wil
));
588 wil_err_fw(wil
, "Failed to load firmware %s rc %d\n", name
, rc
);
591 wil_dbg_fw(wil
, "Loading <%s>, %zu bytes\n", name
, fw
->size
);
593 for (sz
= fw
->size
, d
= fw
->data
; sz
; sz
-= rc1
, d
+= rc1
) {
594 rc1
= wil_fw_verify(wil
, d
, sz
);
599 rc
= wil_fw_process(wil
, d
, rc1
, load
);
605 release_firmware(fw
);
610 * wil_brd_process - process section from BRD file
614 static int wil_brd_process(struct wil6210_priv
*wil
, const void *data
,
618 const struct wil_fw_record_head
*hdr
= data
;
622 /* Assuming the board file includes only one header record and one data
623 * record. Each record starts with wil_fw_record_head.
625 if (size
< sizeof(*hdr
))
627 s
= sizeof(*hdr
) + le32_to_cpu(hdr
->size
);
631 /* Skip the header record and handle the data record */
632 hdr
= (const void *)hdr
+ s
;
634 if (size
< sizeof(*hdr
))
636 hdr_sz
= le32_to_cpu(hdr
->size
);
638 if (wil
->brd_file_max_size
&& hdr_sz
> wil
->brd_file_max_size
)
640 if (sizeof(*hdr
) + hdr_sz
> size
)
643 wil_err_fw(wil
, "unaligned record size: %zu\n",
647 type
= le16_to_cpu(hdr
->type
);
648 if (type
!= wil_fw_type_data
) {
649 wil_err_fw(wil
, "invalid record type for board file: %d\n",
653 if (hdr_sz
< sizeof(struct wil_fw_record_data
)) {
654 wil_err_fw(wil
, "data record too short: %zu\n", hdr_sz
);
658 wil_dbg_fw(wil
, "using addr from fw file: [0x%08x]\n",
661 rc
= __fw_handle_data(wil
, &hdr
[1], hdr_sz
,
662 cpu_to_le32(wil
->brd_file_addr
));
668 * wil_request_board - Request board file
670 * Request board image from the file
671 * board file address and max size are read from FW file
672 * during initialization.
673 * brd file shall include one header and one data section.
677 int wil_request_board(struct wil6210_priv
*wil
, const char *name
)
680 const struct firmware
*brd
;
682 rc
= request_firmware(&brd
, name
, wil_to_dev(wil
));
684 wil_err_fw(wil
, "Failed to load brd %s\n", name
);
687 wil_dbg_fw(wil
, "Loading <%s>, %zu bytes\n", name
, brd
->size
);
689 /* Verify the header */
690 dlen
= wil_fw_verify(wil
, brd
->data
, brd
->size
);
695 /* Process the data record */
696 rc
= wil_brd_process(wil
, brd
->data
, dlen
);
699 release_firmware(brd
);
704 * wil_fw_verify_file_exists - checks if firmware file exist
706 * @wil: driver context
707 * @name: firmware file name
709 * return value - boolean, true for success, false for failure
711 bool wil_fw_verify_file_exists(struct wil6210_priv
*wil
, const char *name
)
713 const struct firmware
*fw
;
716 rc
= request_firmware(&fw
, name
, wil_to_dev(wil
));
718 release_firmware(fw
);
720 wil_dbg_fw(wil
, "<%s> not available: %d\n", name
, rc
);