linux/drivers/net/wireless/ti/wl1251/boot.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * This file is part of wl1251
   4 *
   5 * Copyright (C) 2008 Nokia Corporation
   6 */
   7
   8#include <linux/slab.h>
   9
  10#include "reg.h"
  11#include "boot.h"
  12#include "io.h"
  13#include "spi.h"
  14#include "event.h"
  15#include "acx.h"
  16
  17void wl1251_boot_target_enable_interrupts(struct wl1251 *wl)
  18{
  19        wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask));
  20        wl1251_reg_write32(wl, HI_CFG, HI_CFG_DEF_VAL);
  21}
  22
  23int wl1251_boot_soft_reset(struct wl1251 *wl)
  24{
  25        unsigned long timeout;
  26        u32 boot_data;
  27
  28        /* perform soft reset */
  29        wl1251_reg_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);
  30
  31        /* SOFT_RESET is self clearing */
  32        timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
  33        while (1) {
  34                boot_data = wl1251_reg_read32(wl, ACX_REG_SLV_SOFT_RESET);
  35                wl1251_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data);
  36                if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0)
  37                        break;
  38
  39                if (time_after(jiffies, timeout)) {
  40                        /* 1.2 check pWhalBus->uSelfClearTime if the
  41                         * timeout was reached */
  42                        wl1251_error("soft reset timeout");
  43                        return -1;
  44                }
  45
  46                udelay(SOFT_RESET_STALL_TIME);
  47        }
  48
  49        /* disable Rx/Tx */
  50        wl1251_reg_write32(wl, ENABLE, 0x0);
  51
  52        /* disable auto calibration on start*/
  53        wl1251_reg_write32(wl, SPARE_A2, 0xffff);
  54
  55        return 0;
  56}
  57
  58int wl1251_boot_init_seq(struct wl1251 *wl)
  59{
  60        u32 scr_pad6, init_data, tmp, elp_cmd, ref_freq;
  61
  62        /*
  63         * col #1: INTEGER_DIVIDER
  64         * col #2: FRACTIONAL_DIVIDER
  65         * col #3: ATTN_BB
  66         * col #4: ALPHA_BB
  67         * col #5: STOP_TIME_BB
  68         * col #6: BB_PLL_LOOP_FILTER
  69         */
  70        static const u32 LUT[REF_FREQ_NUM][LUT_PARAM_NUM] = {
  71
  72                {   83, 87381,  0xB, 5, 0xF00,  3}, /* REF_FREQ_19_2*/
  73                {   61, 141154, 0xB, 5, 0x1450, 2}, /* REF_FREQ_26_0*/
  74                {   41, 174763, 0xC, 6, 0x2D00, 1}, /* REF_FREQ_38_4*/
  75                {   40, 0,      0xC, 6, 0x2EE0, 1}, /* REF_FREQ_40_0*/
  76                {   47, 162280, 0xC, 6, 0x2760, 1}  /* REF_FREQ_33_6        */
  77        };
  78
  79        /* read NVS params */
  80        scr_pad6 = wl1251_reg_read32(wl, SCR_PAD6);
  81        wl1251_debug(DEBUG_BOOT, "scr_pad6 0x%x", scr_pad6);
  82
  83        /* read ELP_CMD */
  84        elp_cmd = wl1251_reg_read32(wl, ELP_CMD);
  85        wl1251_debug(DEBUG_BOOT, "elp_cmd 0x%x", elp_cmd);
  86
  87        /* set the BB calibration time to be 300 usec (PLL_CAL_TIME) */
  88        ref_freq = scr_pad6 & 0x000000FF;
  89        wl1251_debug(DEBUG_BOOT, "ref_freq 0x%x", ref_freq);
  90
  91        wl1251_reg_write32(wl, PLL_CAL_TIME, 0x9);
  92
  93        /*
  94         * PG 1.2: set the clock buffer time to be 210 usec (CLK_BUF_TIME)
  95         */
  96        wl1251_reg_write32(wl, CLK_BUF_TIME, 0x6);
  97
  98        /*
  99         * set the clock detect feature to work in the restart wu procedure
 100         * (ELP_CFG_MODE[14]) and Select the clock source type
 101         * (ELP_CFG_MODE[13:12])
 102         */
 103        tmp = ((scr_pad6 & 0x0000FF00) << 4) | 0x00004000;
 104        wl1251_reg_write32(wl, ELP_CFG_MODE, tmp);
 105
 106        /* PG 1.2: enable the BB PLL fix. Enable the PLL_LIMP_CLK_EN_CMD */
 107        elp_cmd |= 0x00000040;
 108        wl1251_reg_write32(wl, ELP_CMD, elp_cmd);
 109
 110        /* PG 1.2: Set the BB PLL stable time to be 1000usec
 111         * (PLL_STABLE_TIME) */
 112        wl1251_reg_write32(wl, CFG_PLL_SYNC_CNT, 0x20);
 113
 114        /* PG 1.2: read clock request time */
 115        init_data = wl1251_reg_read32(wl, CLK_REQ_TIME);
 116
 117        /*
 118         * PG 1.2: set the clock request time to be ref_clk_settling_time -
 119         * 1ms = 4ms
 120         */
 121        if (init_data > 0x21)
 122                tmp = init_data - 0x21;
 123        else
 124                tmp = 0;
 125        wl1251_reg_write32(wl, CLK_REQ_TIME, tmp);
 126
 127        /* set BB PLL configurations in RF AFE */
 128        wl1251_reg_write32(wl, 0x003058cc, 0x4B5);
 129
 130        /* set RF_AFE_REG_5 */
 131        wl1251_reg_write32(wl, 0x003058d4, 0x50);
 132
 133        /* set RF_AFE_CTRL_REG_2 */
 134        wl1251_reg_write32(wl, 0x00305948, 0x11c001);
 135
 136        /*
 137         * change RF PLL and BB PLL divider for VCO clock and adjust VCO
 138         * bais current(RF_AFE_REG_13)
 139         */
 140        wl1251_reg_write32(wl, 0x003058f4, 0x1e);
 141
 142        /* set BB PLL configurations */
 143        tmp = LUT[ref_freq][LUT_PARAM_INTEGER_DIVIDER] | 0x00017000;
 144        wl1251_reg_write32(wl, 0x00305840, tmp);
 145
 146        /* set fractional divider according to Appendix C-BB PLL
 147         * Calculations
 148         */
 149        tmp = LUT[ref_freq][LUT_PARAM_FRACTIONAL_DIVIDER];
 150        wl1251_reg_write32(wl, 0x00305844, tmp);
 151
 152        /* set the initial data for the sigma delta */
 153        wl1251_reg_write32(wl, 0x00305848, 0x3039);
 154
 155        /*
 156         * set the accumulator attenuation value, calibration loop1
 157         * (alpha), calibration loop2 (beta), calibration loop3 (gamma) and
 158         * the VCO gain
 159         */
 160        tmp = (LUT[ref_freq][LUT_PARAM_ATTN_BB] << 16) |
 161                (LUT[ref_freq][LUT_PARAM_ALPHA_BB] << 12) | 0x1;
 162        wl1251_reg_write32(wl, 0x00305854, tmp);
 163
 164        /*
 165         * set the calibration stop time after holdoff time expires and set
 166         * settling time HOLD_OFF_TIME_BB
 167         */
 168        tmp = LUT[ref_freq][LUT_PARAM_STOP_TIME_BB] | 0x000A0000;
 169        wl1251_reg_write32(wl, 0x00305858, tmp);
 170
 171        /*
 172         * set BB PLL Loop filter capacitor3- BB_C3[2:0] and set BB PLL
 173         * constant leakage current to linearize PFD to 0uA -
 174         * BB_ILOOPF[7:3]
 175         */
 176        tmp = LUT[ref_freq][LUT_PARAM_BB_PLL_LOOP_FILTER] | 0x00000030;
 177        wl1251_reg_write32(wl, 0x003058f8, tmp);
 178
 179        /*
 180         * set regulator output voltage for n divider to
 181         * 1.35-BB_REFDIV[1:0], set charge pump current- BB_CPGAIN[4:2],
 182         * set BB PLL Loop filter capacitor2- BB_C2[7:5], set gain of BB
 183         * PLL auto-call to normal mode- BB_CALGAIN_3DB[8]
 184         */
 185        wl1251_reg_write32(wl, 0x003058f0, 0x29);
 186
 187        /* enable restart wakeup sequence (ELP_CMD[0]) */
 188        wl1251_reg_write32(wl, ELP_CMD, elp_cmd | 0x1);
 189
 190        /* restart sequence completed */
 191        udelay(2000);
 192
 193        return 0;
 194}
 195
 196static void wl1251_boot_set_ecpu_ctrl(struct wl1251 *wl, u32 flag)
 197{
 198        u32 cpu_ctrl;
 199
 200        /* 10.5.0 run the firmware (I) */
 201        cpu_ctrl = wl1251_reg_read32(wl, ACX_REG_ECPU_CONTROL);
 202
 203        /* 10.5.1 run the firmware (II) */
 204        cpu_ctrl &= ~flag;
 205        wl1251_reg_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
 206}
 207
 208int wl1251_boot_run_firmware(struct wl1251 *wl)
 209{
 210        int loop, ret;
 211        u32 chip_id, acx_intr;
 212
 213        wl1251_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
 214
 215        chip_id = wl1251_reg_read32(wl, CHIP_ID_B);
 216
 217        wl1251_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id);
 218
 219        if (chip_id != wl->chip_id) {
 220                wl1251_error("chip id doesn't match after firmware boot");
 221                return -EIO;
 222        }
 223
 224        /* wait for init to complete */
 225        loop = 0;
 226        while (loop++ < INIT_LOOP) {
 227                udelay(INIT_LOOP_DELAY);
 228                acx_intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
 229
 230                if (acx_intr == 0xffffffff) {
 231                        wl1251_error("error reading hardware complete "
 232                                     "init indication");
 233                        return -EIO;
 234                }
 235                /* check that ACX_INTR_INIT_COMPLETE is enabled */
 236                else if (acx_intr & WL1251_ACX_INTR_INIT_COMPLETE) {
 237                        wl1251_reg_write32(wl, ACX_REG_INTERRUPT_ACK,
 238                                           WL1251_ACX_INTR_INIT_COMPLETE);
 239                        break;
 240                }
 241        }
 242
 243        if (loop > INIT_LOOP) {
 244                wl1251_error("timeout waiting for the hardware to "
 245                             "complete initialization");
 246                return -EIO;
 247        }
 248
 249        /* get hardware config command mail box */
 250        wl->cmd_box_addr = wl1251_reg_read32(wl, REG_COMMAND_MAILBOX_PTR);
 251
 252        /* get hardware config event mail box */
 253        wl->event_box_addr = wl1251_reg_read32(wl, REG_EVENT_MAILBOX_PTR);
 254
 255        /* set the working partition to its "running" mode offset */
 256        wl1251_set_partition(wl, WL1251_PART_WORK_MEM_START,
 257                             WL1251_PART_WORK_MEM_SIZE,
 258                             WL1251_PART_WORK_REG_START,
 259                             WL1251_PART_WORK_REG_SIZE);
 260
 261        wl1251_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x",
 262                     wl->cmd_box_addr, wl->event_box_addr);
 263
 264        wl1251_acx_fw_version(wl, wl->fw_ver, sizeof(wl->fw_ver));
 265
 266        /*
 267         * in case of full asynchronous mode the firmware event must be
 268         * ready to receive event from the command mailbox
 269         */
 270
 271        /* enable gpio interrupts */
 272        wl1251_enable_interrupts(wl);
 273
 274        /* Enable target's interrupts */
 275        wl->intr_mask = WL1251_ACX_INTR_RX0_DATA |
 276                WL1251_ACX_INTR_RX1_DATA |
 277                WL1251_ACX_INTR_TX_RESULT |
 278                WL1251_ACX_INTR_EVENT_A |
 279                WL1251_ACX_INTR_EVENT_B |
 280                WL1251_ACX_INTR_INIT_COMPLETE;
 281        wl1251_boot_target_enable_interrupts(wl);
 282
 283        wl->event_mask = SCAN_COMPLETE_EVENT_ID | BSS_LOSE_EVENT_ID |
 284                SYNCHRONIZATION_TIMEOUT_EVENT_ID |
 285                ROAMING_TRIGGER_LOW_RSSI_EVENT_ID |
 286                ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID |
 287                REGAINED_BSS_EVENT_ID | BT_PTA_SENSE_EVENT_ID |
 288                BT_PTA_PREDICTION_EVENT_ID | JOIN_EVENT_COMPLETE_ID |
 289                PS_REPORT_EVENT_ID;
 290
 291        ret = wl1251_event_unmask(wl);
 292        if (ret < 0) {
 293                wl1251_error("EVENT mask setting failed");
 294                return ret;
 295        }
 296
 297        wl1251_event_mbox_config(wl);
 298
 299        /* firmware startup completed */
 300        return 0;
 301}
 302
 303static int wl1251_boot_upload_firmware(struct wl1251 *wl)
 304{
 305        int addr, chunk_num, partition_limit;
 306        size_t fw_data_len, len;
 307        u8 *p, *buf;
 308
 309        /* whal_FwCtrl_LoadFwImageSm() */
 310
 311        wl1251_debug(DEBUG_BOOT, "chip id before fw upload: 0x%x",
 312                     wl1251_reg_read32(wl, CHIP_ID_B));
 313
 314        /* 10.0 check firmware length and set partition */
 315        fw_data_len =  (wl->fw[4] << 24) | (wl->fw[5] << 16) |
 316                (wl->fw[6] << 8) | (wl->fw[7]);
 317
 318        wl1251_debug(DEBUG_BOOT, "fw_data_len %zu chunk_size %d", fw_data_len,
 319                CHUNK_SIZE);
 320
 321        if ((fw_data_len % 4) != 0) {
 322                wl1251_error("firmware length not multiple of four");
 323                return -EIO;
 324        }
 325
 326        buf = kmalloc(CHUNK_SIZE, GFP_KERNEL);
 327        if (!buf) {
 328                wl1251_error("allocation for firmware upload chunk failed");
 329                return -ENOMEM;
 330        }
 331
 332        wl1251_set_partition(wl, WL1251_PART_DOWN_MEM_START,
 333                             WL1251_PART_DOWN_MEM_SIZE,
 334                             WL1251_PART_DOWN_REG_START,
 335                             WL1251_PART_DOWN_REG_SIZE);
 336
 337        /* 10.1 set partition limit and chunk num */
 338        chunk_num = 0;
 339        partition_limit = WL1251_PART_DOWN_MEM_SIZE;
 340
 341        while (chunk_num < fw_data_len / CHUNK_SIZE) {
 342                /* 10.2 update partition, if needed */
 343                addr = WL1251_PART_DOWN_MEM_START +
 344                        (chunk_num + 2) * CHUNK_SIZE;
 345                if (addr > partition_limit) {
 346                        addr = WL1251_PART_DOWN_MEM_START +
 347                                chunk_num * CHUNK_SIZE;
 348                        partition_limit = chunk_num * CHUNK_SIZE +
 349                                WL1251_PART_DOWN_MEM_SIZE;
 350                        wl1251_set_partition(wl,
 351                                             addr,
 352                                             WL1251_PART_DOWN_MEM_SIZE,
 353                                             WL1251_PART_DOWN_REG_START,
 354                                             WL1251_PART_DOWN_REG_SIZE);
 355                }
 356
 357                /* 10.3 upload the chunk */
 358                addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE;
 359                p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;
 360                wl1251_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
 361                             p, addr);
 362
 363                /* need to copy the chunk for dma */
 364                len = CHUNK_SIZE;
 365                memcpy(buf, p, len);
 366                wl1251_mem_write(wl, addr, buf, len);
 367
 368                chunk_num++;
 369        }
 370
 371        /* 10.4 upload the last chunk */
 372        addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE;
 373        p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;
 374
 375        /* need to copy the chunk for dma */
 376        len = fw_data_len % CHUNK_SIZE;
 377        memcpy(buf, p, len);
 378
 379        wl1251_debug(DEBUG_BOOT, "uploading fw last chunk (%zu B) 0x%p to 0x%x",
 380                     len, p, addr);
 381        wl1251_mem_write(wl, addr, buf, len);
 382
 383        kfree(buf);
 384
 385        return 0;
 386}
 387
 388static int wl1251_boot_upload_nvs(struct wl1251 *wl)
 389{
 390        size_t nvs_len, nvs_bytes_written, burst_len;
 391        int nvs_start, i;
 392        u32 dest_addr, val;
 393        u8 *nvs_ptr, *nvs;
 394
 395        nvs = wl->nvs;
 396        if (nvs == NULL)
 397                return -ENODEV;
 398
 399        nvs_ptr = nvs;
 400
 401        nvs_len = wl->nvs_len;
 402        nvs_start = wl->fw_len;
 403
 404        /*
 405         * Layout before the actual NVS tables:
 406         * 1 byte : burst length.
 407         * 2 bytes: destination address.
 408         * n bytes: data to burst copy.
 409         *
 410         * This is ended by a 0 length, then the NVS tables.
 411         */
 412
 413        while (nvs_ptr[0]) {
 414                burst_len = nvs_ptr[0];
 415                dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8));
 416
 417                /* We move our pointer to the data */
 418                nvs_ptr += 3;
 419
 420                for (i = 0; i < burst_len; i++) {
 421                        val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
 422                               | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
 423
 424                        wl1251_debug(DEBUG_BOOT,
 425                                     "nvs burst write 0x%x: 0x%x",
 426                                     dest_addr, val);
 427                        wl1251_mem_write32(wl, dest_addr, val);
 428
 429                        nvs_ptr += 4;
 430                        dest_addr += 4;
 431                }
 432        }
 433
 434        /*
 435         * We've reached the first zero length, the first NVS table
 436         * is 7 bytes further.
 437         */
 438        nvs_ptr += 7;
 439        nvs_len -= nvs_ptr - nvs;
 440        nvs_len = ALIGN(nvs_len, 4);
 441
 442        /* Now we must set the partition correctly */
 443        wl1251_set_partition(wl, nvs_start,
 444                             WL1251_PART_DOWN_MEM_SIZE,
 445                             WL1251_PART_DOWN_REG_START,
 446                             WL1251_PART_DOWN_REG_SIZE);
 447
 448        /* And finally we upload the NVS tables */
 449        nvs_bytes_written = 0;
 450        while (nvs_bytes_written < nvs_len) {
 451                val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
 452                       | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
 453
 454                wl1251_debug(DEBUG_BOOT,
 455                             "nvs write table 0x%x: 0x%x",
 456                             nvs_start, val);
 457                wl1251_mem_write32(wl, nvs_start, val);
 458
 459                nvs_ptr += 4;
 460                nvs_bytes_written += 4;
 461                nvs_start += 4;
 462        }
 463
 464        return 0;
 465}
 466
 467int wl1251_boot(struct wl1251 *wl)
 468{
 469        int ret = 0, minor_minor_e2_ver;
 470        u32 tmp, boot_data;
 471
 472        /* halt embedded ARM CPU while loading firmware */
 473        wl1251_reg_write32(wl, ACX_REG_ECPU_CONTROL, ECPU_CONTROL_HALT);
 474
 475        ret = wl1251_boot_soft_reset(wl);
 476        if (ret < 0)
 477                goto out;
 478
 479        /* 2. start processing NVS file */
 480        if (wl->use_eeprom) {
 481                wl1251_reg_write32(wl, ACX_REG_EE_START, START_EEPROM_MGR);
 482                /* Wait for EEPROM NVS burst read to complete */
 483                msleep(40);
 484                wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, USE_EEPROM);
 485        } else {
 486                ret = wl1251_boot_upload_nvs(wl);
 487                if (ret < 0)
 488                        goto out;
 489
 490                /* write firmware's last address (ie. it's length) to
 491                 * ACX_EEPROMLESS_IND_REG */
 492                wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, wl->fw_len);
 493        }
 494
 495        /* 6. read the EEPROM parameters */
 496        tmp = wl1251_reg_read32(wl, SCR_PAD2);
 497
 498        /* 7. read bootdata */
 499        wl->boot_attr.radio_type = (tmp & 0x0000FF00) >> 8;
 500        wl->boot_attr.major = (tmp & 0x00FF0000) >> 16;
 501        tmp = wl1251_reg_read32(wl, SCR_PAD3);
 502
 503        /* 8. check bootdata and call restart sequence */
 504        wl->boot_attr.minor = (tmp & 0x00FF0000) >> 16;
 505        minor_minor_e2_ver = (tmp & 0xFF000000) >> 24;
 506
 507        wl1251_debug(DEBUG_BOOT, "radioType 0x%x majorE2Ver 0x%x "
 508                     "minorE2Ver 0x%x minor_minor_e2_ver 0x%x",
 509                     wl->boot_attr.radio_type, wl->boot_attr.major,
 510                     wl->boot_attr.minor, minor_minor_e2_ver);
 511
 512        ret = wl1251_boot_init_seq(wl);
 513        if (ret < 0)
 514                goto out;
 515
 516        /* 9. NVS processing done */
 517        boot_data = wl1251_reg_read32(wl, ACX_REG_ECPU_CONTROL);
 518
 519        wl1251_debug(DEBUG_BOOT, "halt boot_data 0x%x", boot_data);
 520
 521        /* 10. check that ECPU_CONTROL_HALT bits are set in
 522         * pWhalBus->uBootData and start uploading firmware
 523         */
 524        if ((boot_data & ECPU_CONTROL_HALT) == 0) {
 525                wl1251_error("boot failed, ECPU_CONTROL_HALT not set");
 526                ret = -EIO;
 527                goto out;
 528        }
 529
 530        ret = wl1251_boot_upload_firmware(wl);
 531        if (ret < 0)
 532                goto out;
 533
 534        /* 10.5 start firmware */
 535        ret = wl1251_boot_run_firmware(wl);
 536        if (ret < 0)
 537                goto out;
 538
 539out:
 540        return ret;
 541}
 542