root/drivers/net/wireless/ti/wlcore/boot.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wl1271_boot_set_ecpu_ctrl
  2. wlcore_boot_parse_fw_ver
  3. wlcore_validate_fw_ver
  4. wlcore_boot_static_data
  5. wl1271_boot_upload_firmware_chunk
  6. wlcore_boot_upload_firmware
  7. wlcore_boot_upload_nvs
  8. wlcore_boot_run_firmware

   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);

/* [<][>][^][v][top][bottom][index][help] */