1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * This file is part of wl1271 4 * 5 * Copyright (C) 2008-2010 Nokia Corporation 6 * 7 * Contact: Luciano Coelho <luciano.coelho@nokia.com> 8 */ 9 10 #include <linux/slab.h> 11 #include <linux/export.h> 12 13 #include "debug.h" 14 #include "acx.h" 15 #include "boot.h" 16 #include "io.h" 17 #include "event.h" 18 #include "rx.h" 19 #include "hw_ops.h" 20 21 static int wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag) 22 { 23 u32 cpu_ctrl; 24 int ret; 25 26 /* 10.5.0 run the firmware (I) */ 27 ret = wlcore_read_reg(wl, REG_ECPU_CONTROL, &cpu_ctrl); 28 if (ret < 0) 29 goto out; 30 31 /* 10.5.1 run the firmware (II) */ 32 cpu_ctrl |= flag; 33 ret = wlcore_write_reg(wl, REG_ECPU_CONTROL, cpu_ctrl); 34 35 out: 36 return ret; 37 } 38 39 static int wlcore_boot_parse_fw_ver(struct wl1271 *wl, 40 struct wl1271_static_data *static_data) 41 { 42 int ret; 43 44 strncpy(wl->chip.fw_ver_str, static_data->fw_version, 45 sizeof(wl->chip.fw_ver_str)); 46 47 /* make sure the string is NULL-terminated */ 48 wl->chip.fw_ver_str[sizeof(wl->chip.fw_ver_str) - 1] = '\0'; 49 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], 53 &wl->chip.fw_ver[4]); 54 55 if (ret != 5) { 56 wl1271_warning("fw version incorrect value"); 57 memset(wl->chip.fw_ver, 0, sizeof(wl->chip.fw_ver)); 58 ret = -EINVAL; 59 goto out; 60 } 61 62 ret = wlcore_identify_fw(wl); 63 if (ret < 0) 64 goto out; 65 out: 66 return ret; 67 } 68 69 static int wlcore_validate_fw_ver(struct wl1271 *wl) 70 { 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] = ""; 75 int i; 76 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])) 80 goto fail; 81 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])) 85 goto fail; 86 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])) 90 goto fail; 91 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])) 95 goto fail; 96 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]))) 103 goto fail; 104 105 return 0; 106 107 fail: 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), 111 "%s*.", min_fw_str); 112 else 113 snprintf(min_fw_str, sizeof(min_fw_str), 114 "%s%u.", min_fw_str, min_ver[i]); 115 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); 123 return -EINVAL; 124 } 125 126 static int wlcore_boot_static_data(struct wl1271 *wl) 127 { 128 struct wl1271_static_data *static_data; 129 size_t len = sizeof(*static_data) + wl->static_data_priv_len; 130 int ret; 131 132 static_data = kmalloc(len, GFP_KERNEL); 133 if (!static_data) { 134 ret = -ENOMEM; 135 goto out; 136 } 137 138 ret = wlcore_read(wl, wl->cmd_box_addr, static_data, len, false); 139 if (ret < 0) 140 goto out_free; 141 142 ret = wlcore_boot_parse_fw_ver(wl, static_data); 143 if (ret < 0) 144 goto out_free; 145 146 ret = wlcore_validate_fw_ver(wl); 147 if (ret < 0) 148 goto out_free; 149 150 ret = wlcore_handle_static_data(wl, static_data); 151 if (ret < 0) 152 goto out_free; 153 154 out_free: 155 kfree(static_data); 156 out: 157 return ret; 158 } 159 160 static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, 161 size_t fw_data_len, u32 dest) 162 { 163 struct wlcore_partition_set partition; 164 int addr, chunk_num, partition_limit; 165 u8 *p, *chunk; 166 int ret; 167 168 /* whal_FwCtrl_LoadFwImageSm() */ 169 170 wl1271_debug(DEBUG_BOOT, "starting firmware upload"); 171 172 wl1271_debug(DEBUG_BOOT, "fw_data_len %zd chunk_size %d", 173 fw_data_len, CHUNK_SIZE); 174 175 if ((fw_data_len % 4) != 0) { 176 wl1271_error("firmware length not multiple of four"); 177 return -EIO; 178 } 179 180 chunk = kmalloc(CHUNK_SIZE, GFP_KERNEL); 181 if (!chunk) { 182 wl1271_error("allocation for firmware upload chunk failed"); 183 return -ENOMEM; 184 } 185 186 memcpy(&partition, &wl->ptable[PART_DOWN], sizeof(partition)); 187 partition.mem.start = dest; 188 ret = wlcore_set_partition(wl, &partition); 189 if (ret < 0) 190 goto out; 191 192 /* 10.1 set partition limit and chunk num */ 193 chunk_num = 0; 194 partition_limit = wl->ptable[PART_DOWN].mem.size; 195 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); 205 if (ret < 0) 206 goto out; 207 } 208 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", 214 p, addr); 215 ret = wlcore_write(wl, addr, chunk, CHUNK_SIZE, false); 216 if (ret < 0) 217 goto out; 218 219 chunk_num++; 220 } 221 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); 229 230 out: 231 kfree(chunk); 232 return ret; 233 } 234 235 int wlcore_boot_upload_firmware(struct wl1271 *wl) 236 { 237 u32 chunks, addr, len; 238 int ret = 0; 239 u8 *fw; 240 241 fw = wl->fw; 242 chunks = be32_to_cpup((__be32 *) fw); 243 fw += sizeof(u32); 244 245 wl1271_debug(DEBUG_BOOT, "firmware chunks to be uploaded: %u", chunks); 246 247 while (chunks--) { 248 addr = be32_to_cpup((__be32 *) fw); 249 fw += sizeof(u32); 250 len = be32_to_cpup((__be32 *) fw); 251 fw += sizeof(u32); 252 253 if (len > 300000) { 254 wl1271_info("firmware chunk too long: %u", len); 255 return -EINVAL; 256 } 257 wl1271_debug(DEBUG_BOOT, "chunk %d addr 0x%x len %u", 258 chunks, addr, len); 259 ret = wl1271_boot_upload_firmware_chunk(wl, fw, len, addr); 260 if (ret != 0) 261 break; 262 fw += len; 263 } 264 265 return ret; 266 } 267 EXPORT_SYMBOL_GPL(wlcore_boot_upload_firmware); 268 269 int wlcore_boot_upload_nvs(struct wl1271 *wl) 270 { 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; 275 int i; 276 u32 dest_addr, val; 277 u8 *nvs_ptr, *nvs_aligned; 278 int ret; 279 280 if (wl->nvs == NULL) { 281 wl1271_error("NVS file is needed during boot"); 282 return -ENODEV; 283 } 284 285 if (pdev_data && pdev_data->family) 286 nvs_name = pdev_data->family->nvs_name; 287 288 if (wl->quirks & WLCORE_QUIRK_LEGACY_NVS) { 289 struct wl1271_nvs_file *nvs = 290 (struct wl1271_nvs_file *)wl->nvs; 291 /* 292 * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz 293 * band configurations) can be removed when those NVS files stop 294 * floating around. 295 */ 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; 300 } 301 302 if (wl->nvs_len != sizeof(struct wl1271_nvs_file) && 303 (wl->nvs_len != WL1271_INI_LEGACY_NVS_FILE_SIZE || 304 wl->enable_11a)) { 305 wl1271_error("%s size is not as expected: %zu != %zu", 306 nvs_name, wl->nvs_len, 307 sizeof(struct wl1271_nvs_file)); 308 kfree(wl->nvs); 309 wl->nvs = NULL; 310 wl->nvs_len = 0; 311 return -EILSEQ; 312 } 313 314 /* only the first part of the NVS needs to be uploaded */ 315 nvs_len = sizeof(nvs->nvs); 316 nvs_ptr = (u8 *) nvs->nvs; 317 } else { 318 struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs; 319 320 if (wl->nvs_len == sizeof(struct wl128x_nvs_file)) { 321 if (nvs->general_params.dual_mode_select) 322 wl->enable_11a = true; 323 } else { 324 wl1271_error("%s size is not as expected: %zu != %zu", 325 nvs_name, wl->nvs_len, 326 sizeof(struct wl128x_nvs_file)); 327 kfree(wl->nvs); 328 wl->nvs = NULL; 329 wl->nvs_len = 0; 330 return -EILSEQ; 331 } 332 333 /* only the first part of the NVS needs to be uploaded */ 334 nvs_len = sizeof(nvs->nvs); 335 nvs_ptr = (u8 *)nvs->nvs; 336 } 337 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]; 345 346 /* 347 * Layout before the actual NVS tables: 348 * 1 byte : burst length. 349 * 2 bytes: destination address. 350 * n bytes: data to burst copy. 351 * 352 * This is ended by a 0 length, then the NVS tables. 353 */ 354 355 /* FIXME: Do we need to check here whether the LSB is 1? */ 356 while (nvs_ptr[0]) { 357 burst_len = nvs_ptr[0]; 358 dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8)); 359 360 /* 361 * Due to our new wl1271_translate_reg_addr function, 362 * we need to add the register partition start address 363 * to the destination 364 */ 365 dest_addr += wl->curr_part.reg.start; 366 367 /* We move our pointer to the data */ 368 nvs_ptr += 3; 369 370 for (i = 0; i < burst_len; i++) { 371 if (nvs_ptr + 3 >= (u8 *) wl->nvs + nvs_len) 372 goto out_badnvs; 373 374 val = (nvs_ptr[0] | (nvs_ptr[1] << 8) 375 | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24)); 376 377 wl1271_debug(DEBUG_BOOT, 378 "nvs burst write 0x%x: 0x%x", 379 dest_addr, val); 380 ret = wlcore_write32(wl, dest_addr, val); 381 if (ret < 0) 382 return ret; 383 384 nvs_ptr += 4; 385 dest_addr += 4; 386 } 387 388 if (nvs_ptr >= (u8 *) wl->nvs + nvs_len) 389 goto out_badnvs; 390 } 391 392 /* 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. 398 */ 399 nvs_ptr = (u8 *)wl->nvs + 400 ALIGN(nvs_ptr - (u8 *)wl->nvs + 7, 4); 401 402 if (nvs_ptr >= (u8 *) wl->nvs + nvs_len) 403 goto out_badnvs; 404 405 nvs_len -= nvs_ptr - (u8 *)wl->nvs; 406 407 /* Now we must set the partition correctly */ 408 ret = wlcore_set_partition(wl, &wl->ptable[PART_WORK]); 409 if (ret < 0) 410 return ret; 411 412 /* Copy the NVS tables to a new block to ensure alignment */ 413 nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); 414 if (!nvs_aligned) 415 return -ENOMEM; 416 417 /* And finally we upload the NVS tables */ 418 ret = wlcore_write_data(wl, REG_CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, 419 false); 420 421 kfree(nvs_aligned); 422 return ret; 423 424 out_badnvs: 425 wl1271_error("nvs data is malformed"); 426 return -EILSEQ; 427 } 428 EXPORT_SYMBOL_GPL(wlcore_boot_upload_nvs); 429 430 int wlcore_boot_run_firmware(struct wl1271 *wl) 431 { 432 int loop, ret; 433 u32 chip_id, intr; 434 435 /* Make sure we have the boot partition */ 436 ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); 437 if (ret < 0) 438 return ret; 439 440 ret = wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); 441 if (ret < 0) 442 return ret; 443 444 ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &chip_id); 445 if (ret < 0) 446 return ret; 447 448 wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); 449 450 if (chip_id != wl->chip.id) { 451 wl1271_error("chip id doesn't match after firmware boot"); 452 return -EIO; 453 } 454 455 /* wait for init to complete */ 456 loop = 0; 457 while (loop++ < INIT_LOOP) { 458 udelay(INIT_LOOP_DELAY); 459 ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr); 460 if (ret < 0) 461 return ret; 462 463 if (intr == 0xffffffff) { 464 wl1271_error("error reading hardware complete " 465 "init indication"); 466 return -EIO; 467 } 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); 472 if (ret < 0) 473 return ret; 474 break; 475 } 476 } 477 478 if (loop > INIT_LOOP) { 479 wl1271_error("timeout waiting for the hardware to " 480 "complete initialization"); 481 return -EIO; 482 } 483 484 /* get hardware config command mail box */ 485 ret = wlcore_read_reg(wl, REG_COMMAND_MAILBOX_PTR, &wl->cmd_box_addr); 486 if (ret < 0) 487 return ret; 488 489 wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x", wl->cmd_box_addr); 490 491 /* get hardware config event mail box */ 492 ret = wlcore_read_reg(wl, REG_EVENT_MAILBOX_PTR, &wl->mbox_ptr[0]); 493 if (ret < 0) 494 return ret; 495 496 wl->mbox_ptr[1] = wl->mbox_ptr[0] + wl->mbox_size; 497 498 wl1271_debug(DEBUG_MAILBOX, "MBOX ptrs: 0x%x 0x%x", 499 wl->mbox_ptr[0], wl->mbox_ptr[1]); 500 501 ret = wlcore_boot_static_data(wl); 502 if (ret < 0) { 503 wl1271_error("error getting static data"); 504 return ret; 505 } 506 507 /* 508 * in case of full asynchronous mode the firmware event must be 509 * ready to receive event from the command mailbox 510 */ 511 512 /* unmask required mbox events */ 513 ret = wl1271_event_unmask(wl); 514 if (ret < 0) { 515 wl1271_error("EVENT mask setting failed"); 516 return ret; 517 } 518 519 /* set the working partition to its "running" mode offset */ 520 ret = wlcore_set_partition(wl, &wl->ptable[PART_WORK]); 521 522 /* firmware startup completed */ 523 return ret; 524 } 525 EXPORT_SYMBOL_GPL(wlcore_boot_run_firmware); 526