1 // SPDX-License-Identifier: GPL-2.0-only
3 * This file is part of wl1271
5 * Copyright (C) 2008-2010 Nokia Corporation
7 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
10 #include <linux/slab.h>
11 #include <linux/export.h>
21 static int wl1271_boot_set_ecpu_ctrl(struct wl1271
*wl
, u32 flag
)
26 /* 10.5.0 run the firmware (I) */
27 ret
= wlcore_read_reg(wl
, REG_ECPU_CONTROL
, &cpu_ctrl
);
31 /* 10.5.1 run the firmware (II) */
33 ret
= wlcore_write_reg(wl
, REG_ECPU_CONTROL
, cpu_ctrl
);
39 static int wlcore_boot_parse_fw_ver(struct wl1271
*wl
,
40 struct wl1271_static_data
*static_data
)
44 strncpy(wl
->chip
.fw_ver_str
, static_data
->fw_version
,
45 sizeof(wl
->chip
.fw_ver_str
));
47 /* make sure the string is NULL-terminated */
48 wl
->chip
.fw_ver_str
[sizeof(wl
->chip
.fw_ver_str
) - 1] = '\0';
50 ret
= sscanf(wl
->chip
.fw_ver_str
+ 4, "%u.%u.%u.%u.%u",
51 &wl
->chip
.fw_ver
[0], &wl
->chip
.fw_ver
[1],
52 &wl
->chip
.fw_ver
[2], &wl
->chip
.fw_ver
[3],
56 wl1271_warning("fw version incorrect value");
57 memset(wl
->chip
.fw_ver
, 0, sizeof(wl
->chip
.fw_ver
));
62 ret
= wlcore_identify_fw(wl
);
69 static int wlcore_validate_fw_ver(struct wl1271
*wl
)
71 unsigned int *fw_ver
= wl
->chip
.fw_ver
;
72 unsigned int *min_ver
= (wl
->fw_type
== WL12XX_FW_TYPE_MULTI
) ?
73 wl
->min_mr_fw_ver
: wl
->min_sr_fw_ver
;
74 char min_fw_str
[32] = "";
77 /* the chip must be exactly equal */
78 if ((min_ver
[FW_VER_CHIP
] != WLCORE_FW_VER_IGNORE
) &&
79 (min_ver
[FW_VER_CHIP
] != fw_ver
[FW_VER_CHIP
]))
82 /* the firmware type must be equal */
83 if ((min_ver
[FW_VER_IF_TYPE
] != WLCORE_FW_VER_IGNORE
) &&
84 (min_ver
[FW_VER_IF_TYPE
] != fw_ver
[FW_VER_IF_TYPE
]))
87 /* the project number must be equal */
88 if ((min_ver
[FW_VER_SUBTYPE
] != WLCORE_FW_VER_IGNORE
) &&
89 (min_ver
[FW_VER_SUBTYPE
] != fw_ver
[FW_VER_SUBTYPE
]))
92 /* the API version must be greater or equal */
93 if ((min_ver
[FW_VER_MAJOR
] != WLCORE_FW_VER_IGNORE
) &&
94 (min_ver
[FW_VER_MAJOR
] > fw_ver
[FW_VER_MAJOR
]))
97 /* if the API version is equal... */
98 if (((min_ver
[FW_VER_MAJOR
] == WLCORE_FW_VER_IGNORE
) ||
99 (min_ver
[FW_VER_MAJOR
] == fw_ver
[FW_VER_MAJOR
])) &&
100 /* ...the minor must be greater or equal */
101 ((min_ver
[FW_VER_MINOR
] != WLCORE_FW_VER_IGNORE
) &&
102 (min_ver
[FW_VER_MINOR
] > fw_ver
[FW_VER_MINOR
])))
108 for (i
= 0; i
< NUM_FW_VER
; i
++)
109 if (min_ver
[i
] == WLCORE_FW_VER_IGNORE
)
110 snprintf(min_fw_str
, sizeof(min_fw_str
),
113 snprintf(min_fw_str
, sizeof(min_fw_str
),
114 "%s%u.", min_fw_str
, min_ver
[i
]);
116 wl1271_error("Your WiFi FW version (%u.%u.%u.%u.%u) is invalid.\n"
117 "Please use at least FW %s\n"
118 "You can get the latest firmwares at:\n"
119 "git://git.ti.com/wilink8-wlan/wl18xx_fw.git",
120 fw_ver
[FW_VER_CHIP
], fw_ver
[FW_VER_IF_TYPE
],
121 fw_ver
[FW_VER_MAJOR
], fw_ver
[FW_VER_SUBTYPE
],
122 fw_ver
[FW_VER_MINOR
], min_fw_str
);
126 static int wlcore_boot_static_data(struct wl1271
*wl
)
128 struct wl1271_static_data
*static_data
;
129 size_t len
= sizeof(*static_data
) + wl
->static_data_priv_len
;
132 static_data
= kmalloc(len
, GFP_KERNEL
);
138 ret
= wlcore_read(wl
, wl
->cmd_box_addr
, static_data
, len
, false);
142 ret
= wlcore_boot_parse_fw_ver(wl
, static_data
);
146 ret
= wlcore_validate_fw_ver(wl
);
150 ret
= wlcore_handle_static_data(wl
, static_data
);
160 static int wl1271_boot_upload_firmware_chunk(struct wl1271
*wl
, void *buf
,
161 size_t fw_data_len
, u32 dest
)
163 struct wlcore_partition_set partition
;
164 int addr
, chunk_num
, partition_limit
;
168 /* whal_FwCtrl_LoadFwImageSm() */
170 wl1271_debug(DEBUG_BOOT
, "starting firmware upload");
172 wl1271_debug(DEBUG_BOOT
, "fw_data_len %zd chunk_size %d",
173 fw_data_len
, CHUNK_SIZE
);
175 if ((fw_data_len
% 4) != 0) {
176 wl1271_error("firmware length not multiple of four");
180 chunk
= kmalloc(CHUNK_SIZE
, GFP_KERNEL
);
182 wl1271_error("allocation for firmware upload chunk failed");
186 memcpy(&partition
, &wl
->ptable
[PART_DOWN
], sizeof(partition
));
187 partition
.mem
.start
= dest
;
188 ret
= wlcore_set_partition(wl
, &partition
);
192 /* 10.1 set partition limit and chunk num */
194 partition_limit
= wl
->ptable
[PART_DOWN
].mem
.size
;
196 while (chunk_num
< fw_data_len
/ CHUNK_SIZE
) {
197 /* 10.2 update partition, if needed */
198 addr
= dest
+ (chunk_num
+ 2) * CHUNK_SIZE
;
199 if (addr
> partition_limit
) {
200 addr
= dest
+ chunk_num
* CHUNK_SIZE
;
201 partition_limit
= chunk_num
* CHUNK_SIZE
+
202 wl
->ptable
[PART_DOWN
].mem
.size
;
203 partition
.mem
.start
= addr
;
204 ret
= wlcore_set_partition(wl
, &partition
);
209 /* 10.3 upload the chunk */
210 addr
= dest
+ chunk_num
* CHUNK_SIZE
;
211 p
= buf
+ chunk_num
* CHUNK_SIZE
;
212 memcpy(chunk
, p
, CHUNK_SIZE
);
213 wl1271_debug(DEBUG_BOOT
, "uploading fw chunk 0x%p to 0x%x",
215 ret
= wlcore_write(wl
, addr
, chunk
, CHUNK_SIZE
, false);
222 /* 10.4 upload the last chunk */
223 addr
= dest
+ chunk_num
* CHUNK_SIZE
;
224 p
= buf
+ chunk_num
* CHUNK_SIZE
;
225 memcpy(chunk
, p
, fw_data_len
% CHUNK_SIZE
);
226 wl1271_debug(DEBUG_BOOT
, "uploading fw last chunk (%zd B) 0x%p to 0x%x",
227 fw_data_len
% CHUNK_SIZE
, p
, addr
);
228 ret
= wlcore_write(wl
, addr
, chunk
, fw_data_len
% CHUNK_SIZE
, false);
235 int wlcore_boot_upload_firmware(struct wl1271
*wl
)
237 u32 chunks
, addr
, len
;
242 chunks
= be32_to_cpup((__be32
*) fw
);
245 wl1271_debug(DEBUG_BOOT
, "firmware chunks to be uploaded: %u", chunks
);
248 addr
= be32_to_cpup((__be32
*) fw
);
250 len
= be32_to_cpup((__be32
*) fw
);
254 wl1271_info("firmware chunk too long: %u", len
);
257 wl1271_debug(DEBUG_BOOT
, "chunk %d addr 0x%x len %u",
259 ret
= wl1271_boot_upload_firmware_chunk(wl
, fw
, len
, addr
);
267 EXPORT_SYMBOL_GPL(wlcore_boot_upload_firmware
);
269 int wlcore_boot_upload_nvs(struct wl1271
*wl
)
271 struct platform_device
*pdev
= wl
->pdev
;
272 struct wlcore_platdev_data
*pdev_data
= dev_get_platdata(&pdev
->dev
);
273 const char *nvs_name
= "unknown";
274 size_t nvs_len
, burst_len
;
277 u8
*nvs_ptr
, *nvs_aligned
;
280 if (wl
->nvs
== NULL
) {
281 wl1271_error("NVS file is needed during boot");
285 if (pdev_data
&& pdev_data
->family
)
286 nvs_name
= pdev_data
->family
->nvs_name
;
288 if (wl
->quirks
& WLCORE_QUIRK_LEGACY_NVS
) {
289 struct wl1271_nvs_file
*nvs
=
290 (struct wl1271_nvs_file
*)wl
->nvs
;
292 * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz
293 * band configurations) can be removed when those NVS files stop
296 if (wl
->nvs_len
== sizeof(struct wl1271_nvs_file
) ||
297 wl
->nvs_len
== WL1271_INI_LEGACY_NVS_FILE_SIZE
) {
298 if (nvs
->general_params
.dual_mode_select
)
299 wl
->enable_11a
= true;
302 if (wl
->nvs_len
!= sizeof(struct wl1271_nvs_file
) &&
303 (wl
->nvs_len
!= WL1271_INI_LEGACY_NVS_FILE_SIZE
||
305 wl1271_error("%s size is not as expected: %zu != %zu",
306 nvs_name
, wl
->nvs_len
,
307 sizeof(struct wl1271_nvs_file
));
314 /* only the first part of the NVS needs to be uploaded */
315 nvs_len
= sizeof(nvs
->nvs
);
316 nvs_ptr
= (u8
*) nvs
->nvs
;
318 struct wl128x_nvs_file
*nvs
= (struct wl128x_nvs_file
*)wl
->nvs
;
320 if (wl
->nvs_len
== sizeof(struct wl128x_nvs_file
)) {
321 if (nvs
->general_params
.dual_mode_select
)
322 wl
->enable_11a
= true;
324 wl1271_error("%s size is not as expected: %zu != %zu",
325 nvs_name
, wl
->nvs_len
,
326 sizeof(struct wl128x_nvs_file
));
333 /* only the first part of the NVS needs to be uploaded */
334 nvs_len
= sizeof(nvs
->nvs
);
335 nvs_ptr
= (u8
*)nvs
->nvs
;
338 /* update current MAC address to NVS */
339 nvs_ptr
[11] = wl
->addresses
[0].addr
[0];
340 nvs_ptr
[10] = wl
->addresses
[0].addr
[1];
341 nvs_ptr
[6] = wl
->addresses
[0].addr
[2];
342 nvs_ptr
[5] = wl
->addresses
[0].addr
[3];
343 nvs_ptr
[4] = wl
->addresses
[0].addr
[4];
344 nvs_ptr
[3] = wl
->addresses
[0].addr
[5];
347 * Layout before the actual NVS tables:
348 * 1 byte : burst length.
349 * 2 bytes: destination address.
350 * n bytes: data to burst copy.
352 * This is ended by a 0 length, then the NVS tables.
355 /* FIXME: Do we need to check here whether the LSB is 1? */
357 burst_len
= nvs_ptr
[0];
358 dest_addr
= (nvs_ptr
[1] & 0xfe) | ((u32
)(nvs_ptr
[2] << 8));
361 * Due to our new wl1271_translate_reg_addr function,
362 * we need to add the register partition start address
365 dest_addr
+= wl
->curr_part
.reg
.start
;
367 /* We move our pointer to the data */
370 for (i
= 0; i
< burst_len
; i
++) {
371 if (nvs_ptr
+ 3 >= (u8
*) wl
->nvs
+ nvs_len
)
374 val
= (nvs_ptr
[0] | (nvs_ptr
[1] << 8)
375 | (nvs_ptr
[2] << 16) | (nvs_ptr
[3] << 24));
377 wl1271_debug(DEBUG_BOOT
,
378 "nvs burst write 0x%x: 0x%x",
380 ret
= wlcore_write32(wl
, dest_addr
, val
);
388 if (nvs_ptr
>= (u8
*) wl
->nvs
+ nvs_len
)
393 * We've reached the first zero length, the first NVS table
394 * is located at an aligned offset which is at least 7 bytes further.
395 * NOTE: The wl->nvs->nvs element must be first, in order to
396 * simplify the casting, we assume it is at the beginning of
397 * the wl->nvs structure.
399 nvs_ptr
= (u8
*)wl
->nvs
+
400 ALIGN(nvs_ptr
- (u8
*)wl
->nvs
+ 7, 4);
402 if (nvs_ptr
>= (u8
*) wl
->nvs
+ nvs_len
)
405 nvs_len
-= nvs_ptr
- (u8
*)wl
->nvs
;
407 /* Now we must set the partition correctly */
408 ret
= wlcore_set_partition(wl
, &wl
->ptable
[PART_WORK
]);
412 /* Copy the NVS tables to a new block to ensure alignment */
413 nvs_aligned
= kmemdup(nvs_ptr
, nvs_len
, GFP_KERNEL
);
417 /* And finally we upload the NVS tables */
418 ret
= wlcore_write_data(wl
, REG_CMD_MBOX_ADDRESS
, nvs_aligned
, nvs_len
,
425 wl1271_error("nvs data is malformed");
428 EXPORT_SYMBOL_GPL(wlcore_boot_upload_nvs
);
430 int wlcore_boot_run_firmware(struct wl1271
*wl
)
435 /* Make sure we have the boot partition */
436 ret
= wlcore_set_partition(wl
, &wl
->ptable
[PART_BOOT
]);
440 ret
= wl1271_boot_set_ecpu_ctrl(wl
, ECPU_CONTROL_HALT
);
444 ret
= wlcore_read_reg(wl
, REG_CHIP_ID_B
, &chip_id
);
448 wl1271_debug(DEBUG_BOOT
, "chip id after firmware boot: 0x%x", chip_id
);
450 if (chip_id
!= wl
->chip
.id
) {
451 wl1271_error("chip id doesn't match after firmware boot");
455 /* wait for init to complete */
457 while (loop
++ < INIT_LOOP
) {
458 udelay(INIT_LOOP_DELAY
);
459 ret
= wlcore_read_reg(wl
, REG_INTERRUPT_NO_CLEAR
, &intr
);
463 if (intr
== 0xffffffff) {
464 wl1271_error("error reading hardware complete "
468 /* check that ACX_INTR_INIT_COMPLETE is enabled */
469 else if (intr
& WL1271_ACX_INTR_INIT_COMPLETE
) {
470 ret
= wlcore_write_reg(wl
, REG_INTERRUPT_ACK
,
471 WL1271_ACX_INTR_INIT_COMPLETE
);
478 if (loop
> INIT_LOOP
) {
479 wl1271_error("timeout waiting for the hardware to "
480 "complete initialization");
484 /* get hardware config command mail box */
485 ret
= wlcore_read_reg(wl
, REG_COMMAND_MAILBOX_PTR
, &wl
->cmd_box_addr
);
489 wl1271_debug(DEBUG_MAILBOX
, "cmd_box_addr 0x%x", wl
->cmd_box_addr
);
491 /* get hardware config event mail box */
492 ret
= wlcore_read_reg(wl
, REG_EVENT_MAILBOX_PTR
, &wl
->mbox_ptr
[0]);
496 wl
->mbox_ptr
[1] = wl
->mbox_ptr
[0] + wl
->mbox_size
;
498 wl1271_debug(DEBUG_MAILBOX
, "MBOX ptrs: 0x%x 0x%x",
499 wl
->mbox_ptr
[0], wl
->mbox_ptr
[1]);
501 ret
= wlcore_boot_static_data(wl
);
503 wl1271_error("error getting static data");
508 * in case of full asynchronous mode the firmware event must be
509 * ready to receive event from the command mailbox
512 /* unmask required mbox events */
513 ret
= wl1271_event_unmask(wl
);
515 wl1271_error("EVENT mask setting failed");
519 /* set the working partition to its "running" mode offset */
520 ret
= wlcore_set_partition(wl
, &wl
->ptable
[PART_WORK
]);
522 /* firmware startup completed */
525 EXPORT_SYMBOL_GPL(wlcore_boot_run_firmware
);