24 #include <linux/slab.h>
26 #include <linux/export.h>
36 static int wl1271_boot_set_ecpu_ctrl(
struct wl1271 *wl,
u32 flag)
54 static int wlcore_boot_parse_fw_ver(
struct wl1271 *wl,
60 sizeof(wl->
chip.fw_ver_str));
63 wl->
chip.fw_ver_str[
sizeof(wl->
chip.fw_ver_str) - 1] =
'\0';
65 ret =
sscanf(wl->
chip.fw_ver_str + 4,
"%u.%u.%u.%u.%u",
66 &wl->
chip.fw_ver[0], &wl->
chip.fw_ver[1],
67 &wl->
chip.fw_ver[2], &wl->
chip.fw_ver[3],
77 ret = wlcore_identify_fw(wl);
84 static int wlcore_validate_fw_ver(
struct wl1271 *wl)
86 unsigned int *fw_ver = wl->
chip.fw_ver;
97 else if (min_ver[FW_VER_IF_TYPE] > fw_ver[FW_VER_IF_TYPE])
102 else if (min_ver[FW_VER_MAJOR] > fw_ver[FW_VER_MAJOR])
107 else if (min_ver[FW_VER_SUBTYPE] > fw_ver[FW_VER_SUBTYPE])
112 else if (min_ver[FW_VER_MINOR] > fw_ver[FW_VER_MINOR])
119 wl1271_error(
"Your WiFi FW version (%u.%u.%u.%u.%u) is outdated.\n"
120 "Please use at least FW %u.%u.%u.%u.%u.\n"
121 "You can get more information at:\n"
122 "http://wireless.kernel.org/en/users/Drivers/wl12xx",
123 fw_ver[FW_VER_CHIP], fw_ver[FW_VER_IF_TYPE],
124 fw_ver[FW_VER_MAJOR], fw_ver[FW_VER_SUBTYPE],
125 fw_ver[FW_VER_MINOR], min_ver[FW_VER_CHIP],
126 min_ver[FW_VER_IF_TYPE], min_ver[FW_VER_MAJOR],
127 min_ver[FW_VER_SUBTYPE], min_ver[FW_VER_MINOR]);
131 static int wlcore_boot_static_data(
struct wl1271 *wl)
143 ret = wlcore_read(wl, wl->
cmd_box_addr, static_data, len,
false);
147 ret = wlcore_boot_parse_fw_ver(wl, static_data);
151 ret = wlcore_validate_fw_ver(wl);
155 ret = wlcore_handle_static_data(wl, static_data);
165 static int wl1271_boot_upload_firmware_chunk(
struct wl1271 *wl,
void *
buf,
169 int addr, chunk_num, partition_limit;
180 if ((fw_data_len % 4) != 0) {
187 wl1271_error(
"allocation for firmware upload chunk failed");
201 while (chunk_num < fw_data_len /
CHUNK_SIZE) {
204 if (addr > partition_limit) {
206 partition_limit = chunk_num * CHUNK_SIZE +
217 memcpy(chunk, p, CHUNK_SIZE);
220 ret = wlcore_write(wl, addr, chunk, CHUNK_SIZE,
false);
230 memcpy(chunk, p, fw_data_len % CHUNK_SIZE);
232 fw_data_len % CHUNK_SIZE, p, addr);
233 ret = wlcore_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE,
false);
264 ret = wl1271_boot_upload_firmware_chunk(wl, fw, len, addr);
276 size_t nvs_len, burst_len;
279 u8 *nvs_ptr, *nvs_aligned;
313 nvs_len =
sizeof(nvs->
nvs);
314 nvs_ptr = (
u8 *) nvs->
nvs;
332 nvs_len =
sizeof(nvs->
nvs);
333 nvs_ptr = (
u8 *)nvs->
nvs;
355 burst_len = nvs_ptr[0];
356 dest_addr = (nvs_ptr[1] & 0xfe) | ((
u32)(nvs_ptr[2] << 8));
368 for (i = 0; i < burst_len; i++) {
369 if (nvs_ptr + 3 >= (
u8 *) wl->
nvs + nvs_len)
372 val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
373 | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
376 "nvs burst write 0x%x: 0x%x",
378 ret = wlcore_write32(wl, dest_addr, val);
386 if (nvs_ptr >= (
u8 *) wl->
nvs + nvs_len)
397 nvs_ptr = (
u8 *)wl->
nvs +
400 if (nvs_ptr >= (
u8 *) wl->
nvs + nvs_len)
403 nvs_len -= nvs_ptr - (
u8 *)wl->
nvs;
448 if (chip_id != wl->
chip.id) {
449 wl1271_error(
"chip id doesn't match after firmware boot");
461 if (intr == 0xffffffff) {
469 WL1271_ACX_INTR_INIT_COMPLETE);
478 "complete initialization");
499 ret = wlcore_boot_static_data(wl);